From: Tejun Heo <[email protected]> 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 <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> --- 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 [email protected] 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 <[email protected]>
- [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 <[email protected]>
- [PATCH 01/61] Rules on how to use sysfs in userspace programs
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 02/61] debugfs: add rename for debugfs files
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 03/61] DMI-based module autoloading
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 04/61] Driver core: add missing kset uevent
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 05/61] sysdev: use mutex instead of semaphore
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 06/61] Power Management: use mutexes instead of semaphores
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 07/61] PM: Remove pm_parent from struct dev_pm_info
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 08/61] PM: Remove saved_state from struct dev_pm_info
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 09/61] PM: Simplify suspend_device
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 10/61] Driver core: include linux/mutex.h from attribute_container.c
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 11/61] driver core: properly get driver in device_release_driver
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 12/61] driver core: fix kernel doc of device_release_driver
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 13/61] Driver core: fix devres_release_all() return value
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 14/61] PM: Remove prev_state from struct dev_pm_info
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 15/61] PM: Remove power_state.event checks from suspend core code
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 16/61] PM: Do not check parent state in suspend and resume core code
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 17/61] PM: do not use saved_state from struct dev_pm_info on ARM
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 18/61] Driver core: coding style cleanup
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 19/61] idr: fix obscure bug in allocation path
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 20/61] idr: separate out idr_mark_full()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 21/61] ida: implement idr based id allocator
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 22/61] sysfs: move release_sysfs_dirent() to dir.c
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 23/61] sysfs: allocate inode number using ida
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 24/61] sysfs: make sysfs_put() ignore NULL sd
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 25/61] sysfs: fix error handling in binattr write()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 26/61] sysfs: flatten cleanup paths in sysfs_add_link() and create_dir()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 27/61] sysfs: flatten and fix sysfs_rename_dir() error handling
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 28/61] sysfs: consolidate sysfs_dirent creation functions
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 29/61] sysfs: add sysfs_dirent->s_parent
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 30/61] sysfs: add sysfs_dirent->s_name
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 31/61] sysfs: make sysfs_dirent->s_element a union
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 32/61] sysfs: implement kobj_sysfs_assoc_lock
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 33/61] sysfs: reimplement symlink using sysfs_dirent tree
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 34/61] sysfs: implement bin_buffer
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 35/61] sysfs: implement sysfs_dirent active reference and immediate disconnect
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 36/61] sysfs: kill attribute file orphaning
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 37/61] sysfs: separate out sysfs_attach_dentry()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 38/61] sysfs: reimplement sysfs_drop_dentry()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 39/61] sysfs: kill unnecessary attribute->owner
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 40/61] driver-core: make devt_attr and uevent_attr static
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 41/61] sysfs: make sysfs_alloc_ino() static
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 42/61] sysfs: fix parent refcounting during rename and move
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 43/61] sysfs: reorganize sysfs_new_indoe() and sysfs_create()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 44/61] sysfs: use iget_locked() instead of new_inode()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 45/61] sysfs: fix root sysfs_dirent -> root dentry association
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 46/61] sysfs: move s_active functions to fs/sysfs/dir.c
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 47/61] sysfs: slim down sysfs_dirent->s_active
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 48/61] sysfs: use singly-linked list for sysfs_dirent tree
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 49/61] sysfs: Fix oops in sysfs_drop_dentry on x86_64
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 50/61] sysfs: make sysfs_drop_dentry() access inodes using ilookup()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 51/61] sysfs: rename sysfs_dirent->s_type to s_flags and make room for flags
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 52/61] sysfs: implement SYSFS_FLAG_REMOVED flag
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 53/61] sysfs: implement sysfs_find_dirent() and sysfs_get_dirent()
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 54/61] sysfs: make kobj point to sysfs_dirent instead of dentry
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 55/61] sysfs: consolidate sysfs spinlocks
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 56/61] sysfs: use sysfs_mutex to protect the sysfs_dirent tree
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 57/61] sysfs: restructure add/remove paths and fix inode update
- From: Greg Kroah-Hartman <[email protected]>
- [PATCH 58/61] sysfs: move sysfs_drop_dentry() to dir.c and make it static
- From: Greg Kroah-Hartman <[email protected]>
- [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):