summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs/devfs_devs.c
diff options
context:
space:
mode:
authorjh <jh@FreeBSD.org>2010-09-27 17:47:09 +0000
committerjh <jh@FreeBSD.org>2010-09-27 17:47:09 +0000
commitb6e78e30f23dbed7263727af46739f94ef85fd86 (patch)
treeaac5e5193fff6dc7e4ad901a2ea6b4bab1a82a25 /sys/fs/devfs/devfs_devs.c
parent0901947e8d8500bb8120febd32587bc1eeabca98 (diff)
downloadFreeBSD-src-b6e78e30f23dbed7263727af46739f94ef85fd86.zip
FreeBSD-src-b6e78e30f23dbed7263727af46739f94ef85fd86.tar.gz
Add reference counting for devfs paths containing user created symbolic
links. The reference counting is needed to be able to determine if a specific devfs path exists. For true device file paths we can traverse the cdevp_list but a separate directory list is needed for user created symbolic links. Add a new directory entry flag DE_USER to mark entries which should unreference their parent directory on deletion. A new function to traverse cdevp_list and the directory list will be introduced in a separate commit. Idea from: kib Reviewed by: kib
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