summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs/devfs_devs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/devfs/devfs_devs.c')
-rw-r--r--sys/fs/devfs/devfs_devs.c13
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)
OpenPOWER on IntegriCloud