diff options
Diffstat (limited to 'sys/fs/devfs/devfs_devs.c')
-rw-r--r-- | sys/fs/devfs/devfs_devs.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c index 60c296b..99b33ec 100644 --- a/sys/fs/devfs/devfs_devs.c +++ b/sys/fs/devfs/devfs_devs.c @@ -338,6 +338,10 @@ devfs_delete(struct devfs_mount *dm, struct devfs_dirent *de, int flags) dd = devfs_parent_dirent(de); if (dd != NULL) DEVFS_DE_HOLD(dd); + if (de->de_flags & DE_USER) { + KASSERT(dd != NULL, ("devfs_delete: NULL dd")); + devfs_dir_unref_de(dm, dd); + } } else dd = NULL; @@ -396,10 +400,17 @@ devfs_purge(struct devfs_mount *dm, struct devfs_dirent *dd) DEVFS_DE_HOLD(dd); for (;;) { - de = TAILQ_FIRST(&dd->de_dlist); + /* + * Use TAILQ_LAST() to remove "." and ".." last. + * We might need ".." to resolve a path in + * devfs_dir_unref_de(). + */ + de = TAILQ_LAST(&dd->de_dlist, devfs_dlist_head); if (de == NULL) break; TAILQ_REMOVE(&dd->de_dlist, de, de_list); + if (de->de_flags & DE_USER) + devfs_dir_unref_de(dm, dd); if (de->de_flags & (DE_DOT | DE_DOTDOT)) devfs_delete(dm, de, DEVFS_DEL_NORECURSE); else if (de->de_dirent->d_type == DT_DIR) |