From: Tejun Heo <htejun@gmail.com> Some sysfs operations require dentry and inode. sysfs_get_dentry() looks up and gets dentry for the specified sysfs_dirent. It finds the first ancestor with dentry attached and starts looking up dentries from there. Looking up from the nearest ancestor is necessary to support shadowed directories because we can't reliably lookup dentry for one of the shadows. Dentries for each shadow will be pinned in memory such that they can serve as the starting point for dentry lookup. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/dir.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/sysfs/sysfs.h | 1 + 2 files changed, 99 insertions(+), 0 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index c6f3b69..9872112 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -63,6 +63,104 @@ void sysfs_unlink_sibling(struct sysfs_dirent *sd) } /** + * sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sd: sysfs_dirent of interest + * + * Get dentry for @sd. Dentry is looked up if currently not + * present. This function climbs sysfs_dirent tree till it + * reaches a sysfs_dirent with valid dentry attached and descends + * down from there looking up dentry for each step. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * Pointer to found dentry on success, ERR_PTR() value on error. + */ +struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) +{ + struct sysfs_dirent *cur; + struct dentry *parent_dentry, *dentry; + int i, depth; + + /* Find the first parent which has valid s_dentry and get the + * dentry. + */ + mutex_lock(&sysfs_mutex); + restart0: + spin_lock(&sysfs_assoc_lock); + restart1: + spin_lock(&dcache_lock); + + dentry = NULL; + depth = 0; + cur = sd; + while (!cur->s_dentry || !cur->s_dentry->d_inode) { + if (cur->s_flags & SYSFS_FLAG_REMOVED) { + dentry = ERR_PTR(-ENOENT); + depth = 0; + break; + } + cur = cur->s_parent; + depth++; + } + if (!IS_ERR(dentry)) + dentry = dget_locked(cur->s_dentry); + + spin_unlock(&dcache_lock); + spin_unlock(&sysfs_assoc_lock); + + /* from the found dentry, look up depth times */ + while (depth--) { + /* find and get depth'th ancestor */ + for (cur = sd, i = 0; cur && i < depth; i++) + cur = cur->s_parent; + + /* This can happen if tree structure was modified due + * to move/rename. Restart. + */ + if (i != depth) { + dput(dentry); + goto restart0; + } + + sysfs_get(cur); + + mutex_unlock(&sysfs_mutex); + + /* look it up */ + parent_dentry = dentry; + dentry = lookup_one_len_kern(cur->s_name, parent_dentry, + strlen(cur->s_name)); + dput(parent_dentry); + + if (IS_ERR(dentry)) { + sysfs_put(cur); + return dentry; + } + + mutex_lock(&sysfs_mutex); + spin_lock(&sysfs_assoc_lock); + + /* This, again, can happen if tree structure has + * changed and we looked up the wrong thing. Restart. + */ + if (cur->s_dentry != dentry) { + dput(dentry); + sysfs_put(cur); + goto restart1; + } + + spin_unlock(&sysfs_assoc_lock); + + sysfs_put(cur); + } + + mutex_unlock(&sysfs_mutex); + return dentry; +} + +/** * sysfs_get_active - get an active reference to sysfs_dirent * @sd: sysfs_dirent to get an active reference to * diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 92fe1e5..72530dc 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -54,6 +54,7 @@ struct sysfs_addrm_cxt { extern struct vfsmount * sysfs_mount; extern struct kmem_cache *sysfs_dir_cachep; +extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); extern void sysfs_link_sibling(struct sysfs_dirent *sd); extern void sysfs_unlink_sibling(struct sysfs_dirent *sd); extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); -- 1.5.2.2 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
- Follow-Ups:
- [PATCH 60/61] sysfs: make directory dentries and inodes reclaimable
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 60/61] sysfs: make directory dentries and inodes reclaimable
- References:
- [GIT PATCH] sysfs and driver core patches for 2.6.22
- From: Greg KH <gregkh@suse.de>
- [PATCH 01/61] Rules on how to use sysfs in userspace programs
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 02/61] debugfs: add rename for debugfs files
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 03/61] DMI-based module autoloading
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 04/61] Driver core: add missing kset uevent
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 05/61] sysdev: use mutex instead of semaphore
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 06/61] Power Management: use mutexes instead of semaphores
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 07/61] PM: Remove pm_parent from struct dev_pm_info
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 08/61] PM: Remove saved_state from struct dev_pm_info
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 09/61] PM: Simplify suspend_device
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 10/61] Driver core: include linux/mutex.h from attribute_container.c
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 11/61] driver core: properly get driver in device_release_driver
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 12/61] driver core: fix kernel doc of device_release_driver
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 13/61] Driver core: fix devres_release_all() return value
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 14/61] PM: Remove prev_state from struct dev_pm_info
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 15/61] PM: Remove power_state.event checks from suspend core code
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 16/61] PM: Do not check parent state in suspend and resume core code
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 17/61] PM: do not use saved_state from struct dev_pm_info on ARM
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 18/61] Driver core: coding style cleanup
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 19/61] idr: fix obscure bug in allocation path
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 20/61] idr: separate out idr_mark_full()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 21/61] ida: implement idr based id allocator
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 22/61] sysfs: move release_sysfs_dirent() to dir.c
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 23/61] sysfs: allocate inode number using ida
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 24/61] sysfs: make sysfs_put() ignore NULL sd
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 25/61] sysfs: fix error handling in binattr write()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 26/61] sysfs: flatten cleanup paths in sysfs_add_link() and create_dir()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 27/61] sysfs: flatten and fix sysfs_rename_dir() error handling
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 28/61] sysfs: consolidate sysfs_dirent creation functions
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 29/61] sysfs: add sysfs_dirent->s_parent
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 30/61] sysfs: add sysfs_dirent->s_name
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 31/61] sysfs: make sysfs_dirent->s_element a union
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 32/61] sysfs: implement kobj_sysfs_assoc_lock
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 33/61] sysfs: reimplement symlink using sysfs_dirent tree
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 34/61] sysfs: implement bin_buffer
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 35/61] sysfs: implement sysfs_dirent active reference and immediate disconnect
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 36/61] sysfs: kill attribute file orphaning
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 37/61] sysfs: separate out sysfs_attach_dentry()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 38/61] sysfs: reimplement sysfs_drop_dentry()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 39/61] sysfs: kill unnecessary attribute->owner
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 40/61] driver-core: make devt_attr and uevent_attr static
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 41/61] sysfs: make sysfs_alloc_ino() static
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 42/61] sysfs: fix parent refcounting during rename and move
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 43/61] sysfs: reorganize sysfs_new_indoe() and sysfs_create()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 44/61] sysfs: use iget_locked() instead of new_inode()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 45/61] sysfs: fix root sysfs_dirent -> root dentry association
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 46/61] sysfs: move s_active functions to fs/sysfs/dir.c
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 47/61] sysfs: slim down sysfs_dirent->s_active
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 48/61] sysfs: use singly-linked list for sysfs_dirent tree
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 49/61] sysfs: Fix oops in sysfs_drop_dentry on x86_64
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 50/61] sysfs: make sysfs_drop_dentry() access inodes using ilookup()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 51/61] sysfs: rename sysfs_dirent->s_type to s_flags and make room for flags
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 52/61] sysfs: implement SYSFS_FLAG_REMOVED flag
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 53/61] sysfs: implement sysfs_find_dirent() and sysfs_get_dirent()
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 54/61] sysfs: make kobj point to sysfs_dirent instead of dentry
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 55/61] sysfs: consolidate sysfs spinlocks
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 56/61] sysfs: use sysfs_mutex to protect the sysfs_dirent tree
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 57/61] sysfs: restructure add/remove paths and fix inode update
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [PATCH 58/61] sysfs: move sysfs_drop_dentry() to dir.c and make it static
- From: Greg Kroah-Hartman <gregkh@suse.de>
- [GIT PATCH] sysfs and driver core patches for 2.6.22
- Prev by Date: [PATCH 58/61] sysfs: move sysfs_drop_dentry() to dir.c and make it static
- Next by Date: [PATCH 60/61] sysfs: make directory dentries and inodes reclaimable
- Previous by thread: [PATCH 58/61] sysfs: move sysfs_drop_dentry() to dir.c and make it static
- Next by thread: [PATCH 60/61] sysfs: make directory dentries and inodes reclaimable
- Index(es):
![]() |