* [PATCH 00/11] sysfs tagged directories V6
@ 2008-06-18 17:07 Benjamin Thery
2008-06-18 17:07 ` [PATCH 01/11] sysfs: Support for preventing unmounts Benjamin Thery
` (10 more replies)
0 siblings, 11 replies; 145+ messages in thread
From: Benjamin Thery @ 2008-06-18 17:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, Andrew Morton
Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel,
Tejun Heo, Al Viro, Linux Containers, Benjamin Thery
Greg, Andrew,
Here is yet another updated version of Eric Biederman's patchset to
implement tagged directories in sysfs ported on top of 2.6.26-rc5-mm3.
This may be easier for you to review as 2.6.26-rc2-mm1 was getting a
bit old now.
There is no major changes since the last version which introduced some
changes to address concerns from Greg about the patch "Enable tagging
for net_class directories" being to intrusive in sysfs core.
Refer to the Changelog below and
http://thread.gmane.org/gmane.linux.kernel/690799 to read the details
about the proposed changes (I didn't copy them here to save some space).
Andrew,
Can you consider merging this patchset in -mm until Greg has time
to re-review it and take it (or reject it)?
Thanks,
Benjamin
(Below you'll find the traditional introduction for sysfs tagged dirs
and the updated changelog)
--
With the introduction of network namespaces, there can be duplicate
network interface names on the same machine. Indeed, two network
interfaces can have the same name if they reside in different network
namespaces.
* Network interfaces names show up in sysfs.
* Today there is nothing in sysfs that is currently per namespace.
* Therefore we need to support multiple mounts of sysfs each showing a
different network namespace.
We introduce tagged directories in sysfs for this purpose.
Of course the usefulness of this feature is not limited to network stuff:
Serge Hallyn wrote a patch to fix a similar issue with user namespaces based
on this patchset. His patch is included at the end of the patchset.
Tested with and without SYSFS_DEPRECATED. No regression found so far.
Changelog
---------
* V6:
- Ported to 2.6.26-rc5-mm3
- Patch 11 (userns) Removed an unused kset member from struct
user_namespace left from a previous version of the patch.
* V5:
- Make namespace tags a bit less intrusive in sysfs core:
- New patch 09: Added a generic sysfs_ns_exit routine called by
exiting namespaces. A callback is passed to this routine to
execute the subsystem specific code.
- Modified patches 09 and 10 (now 10 and 11) ("netns tagging" and
"userns tagging") to use this new routine instead of adding
#ifdef'd code in fs/sysfs/mount.c.
- Added missing -ENOMEM in fs/sysfs/dir.c:prep_rename() (Roel Kluin)
* V4:
- Ported to 2.6.26-rc2-mm1
- Updated patch for user namespace by Serge Hallyn (patch 10).
* V3:
- Removed patch 10 ("avoid kobject name conflict with different
namespaces"), a better one was provided by Eric.
- Removed patch 11 ("sysfs: user namespaces: add ns to user_struct"),
Serge needs to rework some parts of it.
- Change Acked-by: to Signed-off-by:, someone told me it is more
appropriate (as I'm in the delivery path).
Here is the announcement Eric wrote back in December to introduce his
patchset:
"
Now that we have network namespace support merged it is time to
revisit the sysfs support so we can remove the dependency on !SYSFS.
[...]
The bulk of the patches are the changes to allow multiple sysfs
superblocks.
Then comes the tagged directory sysfs support which uses information
captured at mount time to decide which object with which tag will
appear in a directory.
Then the support for renaming and deleting objects where the source
may be ambiguous because of tagging.
Then finally the network namespace support so it is clear how all
of this tied together.
"
Regards,
Benjamin
--
^ permalink raw reply [flat|nested] 145+ messages in thread* [PATCH 01/11] sysfs: Support for preventing unmounts. 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery @ 2008-06-18 17:07 ` Benjamin Thery [not found] ` <20080618170730.256129077-4vkkeT0zb4ZEtYaxpPmRp1aPQRlvutdw@public.gmane.org> 2008-06-18 17:07 ` [PATCH 02/11] sysfs: sysfs_get_dentry add a sb parameter Benjamin Thery ` (9 subsequent siblings) 10 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:07 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: Support for preventing unmounts. To support mounting multiple instances of sysfs occassionally I need to walk through all of the currently present sysfs super blocks. To allow this iteration this patch adds sysfs_grab_supers and sysfs_release_supers. While a piece of code is in a section surrounded by these no more sysfs super blocks will be either created or destroyed. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/mount.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++------ fs/sysfs/sysfs.h | 10 ++++++ 2 files changed, 81 insertions(+), 8 deletions(-) Index: linux-mm/fs/sysfs/mount.c =================================================================== --- linux-mm.orig/fs/sysfs/mount.c +++ linux-mm/fs/sysfs/mount.c @@ -41,47 +41,110 @@ struct sysfs_dirent sysfs_root = { static int sysfs_fill_super(struct super_block *sb, void *data, int silent) { - struct inode *inode; - struct dentry *root; + struct sysfs_super_info *info = NULL; + struct inode *inode = NULL; + struct dentry *root = NULL; + int error; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = SYSFS_MAGIC; sb->s_op = &sysfs_ops; sb->s_time_gran = 1; - sysfs_sb = sb; + if (!sysfs_sb) + sysfs_sb = sb; + + error = -ENOMEM; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out_err; /* get root inode, initialize and unlock it */ + error = -ENOMEM; inode = sysfs_get_inode(&sysfs_root); if (!inode) { pr_debug("sysfs: could not get root inode\n"); - return -ENOMEM; + goto out_err; } /* instantiate and link root dentry */ + error = -ENOMEM; root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); - iput(inode); - return -ENOMEM; + goto out_err; } root->d_fsdata = &sysfs_root; sb->s_root = root; + sb->s_fs_info = info; return 0; + +out_err: + dput(root); + iput(inode); + kfree(info); + if (sysfs_sb == sb) + sysfs_sb = NULL; + return error; } static int sysfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + int rc; + mutex_lock(&sysfs_rename_mutex); + rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + mutex_unlock(&sysfs_rename_mutex); + return rc; } -static struct file_system_type sysfs_fs_type = { +struct file_system_type sysfs_fs_type = { .name = "sysfs", .get_sb = sysfs_get_sb, .kill_sb = kill_anon_super, }; +void sysfs_grab_supers(void) +{ + /* must hold sysfs_rename_mutex */ + struct super_block *sb; + /* Loop until I have taken s_umount on all sysfs superblocks */ +restart: + spin_lock(&sb_lock); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + if (sysfs_info(sb)->grabbed) + continue; + /* Wait for unmount activity to complete. */ + if (sb->s_count < S_BIAS) { + sb->s_count += 1; + spin_unlock(&sb_lock); + down_read(&sb->s_umount); + drop_super(sb); + goto restart; + } + atomic_inc(&sb->s_active); + sysfs_info(sb)->grabbed = 1; + } + spin_unlock(&sb_lock); +} + +void sysfs_release_supers(void) +{ + /* must hold sysfs_rename_mutex */ + struct super_block *sb; +restart: + spin_lock(&sb_lock); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + if (!sysfs_info(sb)->grabbed) + continue; + sysfs_info(sb)->grabbed = 0; + spin_unlock(&sb_lock); + deactivate_super(sb); + goto restart; + } + spin_unlock(&sb_lock); +} + int __init sysfs_init(void) { int err = -ENOMEM; Index: linux-mm/fs/sysfs/sysfs.h =================================================================== --- linux-mm.orig/fs/sysfs/sysfs.h +++ linux-mm/fs/sysfs/sysfs.h @@ -85,6 +85,12 @@ struct sysfs_addrm_cxt { int cnt; }; +struct sysfs_super_info { + int grabbed; +}; + +#define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) + /* * mount.c */ @@ -92,6 +98,10 @@ extern struct sysfs_dirent sysfs_root; extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; extern struct vfsmount *sysfs_mount; +extern struct file_system_type sysfs_fs_type; + +void sysfs_grab_supers(void); +void sysfs_release_supers(void); /* * dir.c -- ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <20080618170730.256129077-4vkkeT0zb4ZEtYaxpPmRp1aPQRlvutdw@public.gmane.org>]
* Re: [PATCH 01/11] sysfs: Support for preventing unmounts. [not found] ` <20080618170730.256129077-4vkkeT0zb4ZEtYaxpPmRp1aPQRlvutdw@public.gmane.org> @ 2008-06-18 17:44 ` Dave Hansen 2008-06-18 20:12 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Dave Hansen @ 2008-06-18 17:44 UTC (permalink / raw) To: Benjamin Thery Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Eric Biederman, Al Viro, Linux Containers, Andrew Morton On Wed, 2008-06-18 at 19:07 +0200, Benjamin Thery wrote: > To support mounting multiple instances of sysfs occassionally I > need to walk through all of the currently present sysfs super blocks. I know you may have addressed this before, but I forgot and it didn't make it into the changelogs. Why are you doing this again? It seems like an awfully blunt instrument. -- Dave ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 01/11] sysfs: Support for preventing unmounts. 2008-06-18 17:44 ` Dave Hansen @ 2008-06-18 20:12 ` Eric W. Biederman 2008-06-19 8:54 ` Benjamin Thery 2008-06-19 16:32 ` Dave Hansen 0 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-06-18 20:12 UTC (permalink / raw) To: Dave Hansen Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Tejun Heo, linux-kernel, Al Viro, Linux Containers Dave Hansen <dave@linux.vnet.ibm.com> writes: > On Wed, 2008-06-18 at 19:07 +0200, Benjamin Thery wrote: >> To support mounting multiple instances of sysfs occassionally I >> need to walk through all of the currently present sysfs super blocks. > > I know you may have addressed this before, but I forgot and it didn't > make it into the changelogs. > > Why are you doing this again? It seems like an awfully blunt > instrument. So the fundamentals. - The data in sysfs fundamentally changes behind the back of the VFS and we need to keep the VFS in sync. Essentially this is the distributed filesystem problem. - In particular for sysfs_rename and sysfs_move_dir we need to support finding the dcache entries and calling d_move. So that the dcache does not get into an inconsistent state. Timeouts and invalidates like NFS uses are to be avoided if at all possible. - Coming through the vfs we are guaranteed that the filesystem will not be unmounted while we have a reference on a dentry, and with multiple mounts we do not get that guarantee. Therefore to get that guarantee for all of the superblocks we need the blunt instrument. - Since mount/unmount are rare blocking them is no big deal. I believe any distributed filesystem that is together enough to tell us about renames (so we can update the dcache) instead of doing the NFS timeout will need the ability to block mount/unmount while it is executing d_move. Currently sysfs does not need to block mounts only because we perform an internal mount and then never unmount sysfs. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 01/11] sysfs: Support for preventing unmounts. 2008-06-18 20:12 ` Eric W. Biederman @ 2008-06-19 8:54 ` Benjamin Thery 2008-06-19 16:32 ` Dave Hansen 1 sibling, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-19 8:54 UTC (permalink / raw) To: Eric W. Biederman Cc: Dave Hansen, Greg Kroah-Hartman, Andrew Morton, Tejun Heo, linux-kernel, Al Viro, Linux Containers, Serge E. Hallyn, Daniel Lezcano Eric W. Biederman wrote: > Dave Hansen <dave@linux.vnet.ibm.com> writes: > >> On Wed, 2008-06-18 at 19:07 +0200, Benjamin Thery wrote: >>> To support mounting multiple instances of sysfs occassionally I >>> need to walk through all of the currently present sysfs super blocks. >> I know you may have addressed this before, but I forgot and it didn't >> make it into the changelogs. >> >> Why are you doing this again? It seems like an awfully blunt >> instrument. > > So the fundamentals. > - The data in sysfs fundamentally changes behind the back of the > VFS and we need to keep the VFS in sync. Essentially this is the > distributed filesystem problem. > > - In particular for sysfs_rename and sysfs_move_dir we need to support finding > the dcache entries and calling d_move. So that the dcache does not > get into an inconsistent state. Timeouts and invalidates like NFS > uses are to be avoided if at all possible. > > - Coming through the vfs we are guaranteed that the filesystem will > not be unmounted while we have a reference on a dentry, and with > multiple mounts we do not get that guarantee. Therefore to get that > guarantee for all of the superblocks we need the blunt instrument. > > - Since mount/unmount are rare blocking them is no big deal. > > I believe any distributed filesystem that is together enough to tell > us about renames (so we can update the dcache) instead of doing the > NFS timeout will need the ability to block mount/unmount while it is > executing d_move. > > Currently sysfs does not need to block mounts only because we perform > an internal mount and then never unmount sysfs. Thanks Eric for detailing this. I think you explained it in much better way than I could do. You're the author of the patch after all ;-) Benjamin > > Eric > > -- B e n j a m i n T h e r y - BULL/DT/Open Software R&D http://www.bull.com ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 01/11] sysfs: Support for preventing unmounts. 2008-06-18 20:12 ` Eric W. Biederman 2008-06-19 8:54 ` Benjamin Thery @ 2008-06-19 16:32 ` Dave Hansen 2008-06-19 20:19 ` Benjamin Thery 1 sibling, 1 reply; 145+ messages in thread From: Dave Hansen @ 2008-06-19 16:32 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery On Wed, 2008-06-18 at 13:12 -0700, Eric W. Biederman wrote: > > - The data in sysfs fundamentally changes behind the back of the > VFS and we need to keep the VFS in sync. Essentially this is the > distributed filesystem problem. > > - In particular for sysfs_rename and sysfs_move_dir we need to support > finding > the dcache entries and calling d_move. So that the dcache does not > get into an inconsistent state. Timeouts and invalidates like NFS > uses are to be avoided if at all possible. Much clearer now, thanks! Can we get this description into the changelog, pretty please? -- Dave ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 01/11] sysfs: Support for preventing unmounts. 2008-06-19 16:32 ` Dave Hansen @ 2008-06-19 20:19 ` Benjamin Thery 0 siblings, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-19 20:19 UTC (permalink / raw) To: Dave Hansen Cc: Eric W. Biederman, Tejun Heo, Greg Kroah-Hartman, linux-kernel, Al Viro, Linux Containers, Andrew Morton Quoting Dave Hansen <dave@linux.vnet.ibm.com>: > On Wed, 2008-06-18 at 13:12 -0700, Eric W. Biederman wrote: >> >> - The data in sysfs fundamentally changes behind the back of the >> VFS and we need to keep the VFS in sync. Essentially this is the >> distributed filesystem problem. >> >> - In particular for sysfs_rename and sysfs_move_dir we need to support >> finding >> the dcache entries and calling d_move. So that the dcache does not >> get into an inconsistent state. Timeouts and invalidates like NFS >> uses are to be avoided if at all possible. > > Much clearer now, thanks! > > Can we get this description into the changelog, pretty please? Yes sure. I'll add it to the patch introduction. Benjamin > > -- Dave > > > ---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program. ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 02/11] sysfs: sysfs_get_dentry add a sb parameter 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery 2008-06-18 17:07 ` [PATCH 01/11] sysfs: Support for preventing unmounts Benjamin Thery @ 2008-06-18 17:07 ` Benjamin Thery 2008-06-18 17:07 ` [PATCH 03/11] sysfs: Implement __sysfs_get_dentry Benjamin Thery ` (8 subsequent siblings) 10 siblings, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:07 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: sysfs_get_dentry add a sb parameter In preparation for multiple mounts of sysfs add a superblock parameter to sysfs_get_dentry. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/dir.c | 12 +++++++----- fs/sysfs/file.c | 2 +- fs/sysfs/sysfs.h | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) Index: linux-mm/fs/sysfs/dir.c =================================================================== --- linux-mm.orig/fs/sysfs/dir.c +++ linux-mm/fs/sysfs/dir.c @@ -85,6 +85,7 @@ static void sysfs_unlink_sibling(struct /** * sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sb: superblock of the dentry to return * @sd: sysfs_dirent of interest * * Get dentry for @sd. Dentry is looked up if currently not @@ -97,9 +98,10 @@ static void sysfs_unlink_sibling(struct * RETURNS: * Pointer to found dentry on success, ERR_PTR() value on error. */ -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) +struct dentry *sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd) { - struct dentry *dentry = dget(sysfs_sb->s_root); + struct dentry *dentry = dget(sb->s_root); while (dentry->d_fsdata != sd) { struct sysfs_dirent *cur; @@ -777,7 +779,7 @@ int sysfs_rename_dir(struct kobject * ko goto out; /* nothing to rename */ /* get the original dentry */ - old_dentry = sysfs_get_dentry(sd); + old_dentry = sysfs_get_dentry(sysfs_sb, sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); old_dentry = NULL; @@ -845,7 +847,7 @@ int sysfs_move_dir(struct kobject *kobj, goto out; /* nothing to move */ /* get dentries */ - old_dentry = sysfs_get_dentry(sd); + old_dentry = sysfs_get_dentry(sysfs_sb, sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); old_dentry = NULL; @@ -853,7 +855,7 @@ int sysfs_move_dir(struct kobject *kobj, } old_parent = old_dentry->d_parent; - new_parent = sysfs_get_dentry(new_parent_sd); + new_parent = sysfs_get_dentry(sysfs_sb, new_parent_sd); if (IS_ERR(new_parent)) { error = PTR_ERR(new_parent); new_parent = NULL; Index: linux-mm/fs/sysfs/file.c =================================================================== --- linux-mm.orig/fs/sysfs/file.c +++ linux-mm/fs/sysfs/file.c @@ -584,7 +584,7 @@ int sysfs_chmod_file(struct kobject *kob goto out; mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(victim_sd); + victim = sysfs_get_dentry(sysfs_sb, victim_sd); mutex_unlock(&sysfs_rename_mutex); if (IS_ERR(victim)) { rc = PTR_ERR(victim); Index: linux-mm/fs/sysfs/sysfs.h =================================================================== --- linux-mm.orig/fs/sysfs/sysfs.h +++ linux-mm/fs/sysfs/sysfs.h @@ -113,7 +113,8 @@ extern spinlock_t sysfs_assoc_lock; extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); +struct dentry *sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd); struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); void sysfs_put_active_two(struct sysfs_dirent *sd); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 03/11] sysfs: Implement __sysfs_get_dentry 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery 2008-06-18 17:07 ` [PATCH 01/11] sysfs: Support for preventing unmounts Benjamin Thery 2008-06-18 17:07 ` [PATCH 02/11] sysfs: sysfs_get_dentry add a sb parameter Benjamin Thery @ 2008-06-18 17:07 ` Benjamin Thery 2008-06-18 17:08 ` [PATCH 04/11] sysfs: Rename Support multiple superblocks Benjamin Thery ` (7 subsequent siblings) 10 siblings, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:07 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: Implement __sysfs_get_dentry This function is similar but much simpler to sysfs_get_dentry returns a sysfs dentry if one curently exists. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/dir.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) Index: linux-mm/fs/sysfs/dir.c =================================================================== --- linux-mm.orig/fs/sysfs/dir.c +++ linux-mm/fs/sysfs/dir.c @@ -764,6 +764,45 @@ void sysfs_remove_dir(struct kobject * k __sysfs_remove_dir(sd); } +/** + * __sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sb: superblock of the dentry to return + * @sd: sysfs_dirent of interest + * + * Get dentry for @sd. Only return a dentry if one currently + * exists. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * Pointer to found dentry on success, NULL on failure. + */ +static struct dentry *__sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd) +{ + struct inode *inode; + struct dentry *dentry = NULL; + + inode = ilookup5_nowait(sysfs_sb, sd->s_ino, sysfs_ilookup_test, sd); + if (inode && !(inode->i_state & I_NEW)) { + struct dentry *alias; + spin_lock(&dcache_lock); + list_for_each_entry(alias, &inode->i_dentry, d_alias) { + if (!IS_ROOT(alias) && d_unhashed(alias)) + continue; + if (alias->d_sb != sb) + continue; + dentry = alias; + dget_locked(dentry); + break; + } + spin_unlock(&dcache_lock); + } + iput(inode); + return dentry; +} + int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 04/11] sysfs: Rename Support multiple superblocks 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (2 preceding siblings ...) 2008-06-18 17:07 ` [PATCH 03/11] sysfs: Implement __sysfs_get_dentry Benjamin Thery @ 2008-06-18 17:08 ` Benjamin Thery 2008-06-18 17:08 ` [PATCH 05/11] sysfs: sysfs_chmod_file handle " Benjamin Thery ` (6 subsequent siblings) 10 siblings, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: Rename Support multiple superblocks This patch modifies the sysfs_rename_dir and sysfs_move_dir routines to support multiple sysfs dentry tries rooted in different sysfs superblocks. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/dir.c | 195 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 137 insertions(+), 58 deletions(-) Index: linux-mm/fs/sysfs/dir.c =================================================================== --- linux-mm.orig/fs/sysfs/dir.c +++ linux-mm/fs/sysfs/dir.c @@ -803,43 +803,113 @@ static struct dentry *__sysfs_get_dentry return dentry; } +struct sysfs_rename_struct { + struct list_head list; + struct dentry *old_dentry; + struct dentry *new_dentry; + struct dentry *old_parent; + struct dentry *new_parent; +}; + +static void post_rename(struct list_head *head) +{ + struct sysfs_rename_struct *srs; + while (!list_empty(head)) { + srs = list_entry(head->next, struct sysfs_rename_struct, list); + dput(srs->old_dentry); + dput(srs->new_dentry); + dput(srs->old_parent); + dput(srs->new_parent); + list_del(&srs->list); + kfree(srs); + } +} + +static int prep_rename(struct list_head *head, + struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd, + const char *name) +{ + struct sysfs_rename_struct *srs; + struct super_block *sb; + struct dentry *dentry; + int error; + + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + dentry = sysfs_get_dentry(sb, sd); + if (dentry == ERR_PTR(-EXDEV)) + continue; + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto err_out; + } + + srs = kzalloc(sizeof(*srs), GFP_KERNEL); + if (!srs) { + error = -ENOMEM; + dput(dentry); + goto err_out; + } + + INIT_LIST_HEAD(&srs->list); + list_add(head, &srs->list); + srs->old_dentry = dentry; + srs->old_parent = dget(dentry->d_parent); + + dentry = sysfs_get_dentry(sb, new_parent_sd); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto err_out; + } + srs->new_parent = dentry; + + error = -ENOMEM; + dentry = d_alloc_name(srs->new_parent, name); + if (!dentry) + goto err_out; + srs->new_dentry = dentry; + } + return 0; + +err_out: + post_rename(head); + return error; +} + int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; - struct dentry *parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct list_head todo; + struct sysfs_rename_struct *srs; + struct inode *parent_inode = NULL; const char *dup_name = NULL; int error; + INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); error = 0; if (strcmp(sd->s_name, new_name) == 0) goto out; /* nothing to rename */ - /* get the original dentry */ - old_dentry = sysfs_get_dentry(sysfs_sb, sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } + sysfs_grab_supers(); + error = prep_rename(&todo, sd, sd->s_parent, new_name); + if (error) + goto out_release; - parent = old_dentry->d_parent; + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + parent_inode = sysfs_get_inode(sd->s_parent); + mutex_unlock(&sysfs_mutex); + if (!parent_inode) + goto out_release; - /* lock parent and get dentry for new name */ - mutex_lock(&parent->d_inode->i_mutex); + mutex_lock(&parent_inode->i_mutex); mutex_lock(&sysfs_mutex); error = -EEXIST; if (sysfs_find_dirent(sd->s_parent, new_name)) goto out_unlock; - error = -ENOMEM; - new_dentry = d_alloc_name(parent, new_name); - if (!new_dentry) - goto out_unlock; - /* rename kobject and sysfs_dirent */ error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); @@ -854,17 +924,21 @@ int sysfs_rename_dir(struct kobject * ko sd->s_name = new_name; /* rename */ - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + list_for_each_entry(srs, &todo, list) { + d_add(srs->new_dentry, NULL); + d_move(srs->old_dentry, srs->new_dentry); + } error = 0; - out_unlock: +out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&parent->d_inode->i_mutex); + mutex_unlock(&parent_inode->i_mutex); kfree(dup_name); - dput(old_dentry); - dput(new_dentry); - out: +out_release: + iput(parent_inode); + post_rename(&todo); + sysfs_release_supers(); +out: mutex_unlock(&sysfs_rename_mutex); return error; } @@ -873,10 +947,12 @@ int sysfs_move_dir(struct kobject *kobj, { struct sysfs_dirent *sd = kobj->sd; struct sysfs_dirent *new_parent_sd; - struct dentry *old_parent, *new_parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct list_head todo; + struct sysfs_rename_struct *srs; + struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; int error; + INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; @@ -885,26 +961,29 @@ int sysfs_move_dir(struct kobject *kobj, if (sd->s_parent == new_parent_sd) goto out; /* nothing to move */ - /* get dentries */ - old_dentry = sysfs_get_dentry(sysfs_sb, sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } - old_parent = old_dentry->d_parent; - - new_parent = sysfs_get_dentry(sysfs_sb, new_parent_sd); - if (IS_ERR(new_parent)) { - error = PTR_ERR(new_parent); - new_parent = NULL; - goto out; - } + sysfs_grab_supers(); + error = prep_rename(&todo, sd, new_parent_sd, sd->s_name); + if (error) + goto out_release; + + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + old_parent_inode = sysfs_get_inode(sd->s_parent); + mutex_unlock(&sysfs_mutex); + if (!old_parent_inode) + goto out_release; + + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + new_parent_inode = sysfs_get_inode(new_parent_sd); + mutex_unlock(&sysfs_mutex); + if (!new_parent_inode) + goto out_release; again: - mutex_lock(&old_parent->d_inode->i_mutex); - if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { - mutex_unlock(&old_parent->d_inode->i_mutex); + mutex_lock(&old_parent_inode->i_mutex); + if (!mutex_trylock(&new_parent_inode->i_mutex)) { + mutex_unlock(&old_parent_inode->i_mutex); goto again; } mutex_lock(&sysfs_mutex); @@ -913,14 +992,11 @@ again: if (sysfs_find_dirent(new_parent_sd, sd->s_name)) goto out_unlock; - error = -ENOMEM; - new_dentry = d_alloc_name(new_parent, sd->s_name); - if (!new_dentry) - goto out_unlock; - error = 0; - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + list_for_each_entry(srs, &todo, list) { + d_add(srs->new_dentry, NULL); + d_move(srs->old_dentry, srs->new_dentry); + } /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); @@ -929,14 +1005,17 @@ again: sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); - out_unlock: +out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&new_parent->d_inode->i_mutex); - mutex_unlock(&old_parent->d_inode->i_mutex); - out: - dput(new_parent); - dput(old_dentry); - dput(new_dentry); + mutex_unlock(&new_parent_inode->i_mutex); + mutex_unlock(&old_parent_inode->i_mutex); + +out_release: + iput(new_parent_inode); + iput(old_parent_inode); + post_rename(&todo); + sysfs_release_supers(); +out: mutex_unlock(&sysfs_rename_mutex); return error; } -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (3 preceding siblings ...) 2008-06-18 17:08 ` [PATCH 04/11] sysfs: Rename Support multiple superblocks Benjamin Thery @ 2008-06-18 17:08 ` Benjamin Thery 2008-06-22 4:46 ` Tejun Heo 2008-06-18 17:08 ` [PATCH 06/11] sysfs: Implement sysfs tagged directory support Benjamin Thery ` (5 subsequent siblings) 10 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: sysfs_chmod_file handle multiple superblocks Teach sysfs_chmod_file how to handle multiple sysfs superblocks. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/file.c | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) Index: linux-mm/fs/sysfs/file.c =================================================================== --- linux-mm.orig/fs/sysfs/file.c +++ linux-mm/fs/sysfs/file.c @@ -573,7 +573,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_grou int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct sysfs_dirent *victim_sd = NULL; - struct dentry *victim = NULL; + struct super_block *sb; + struct dentry *victim; struct inode * inode; struct iattr newattrs; int rc; @@ -584,31 +585,36 @@ int sysfs_chmod_file(struct kobject *kob goto out; mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(sysfs_sb, victim_sd); - mutex_unlock(&sysfs_rename_mutex); - if (IS_ERR(victim)) { - rc = PTR_ERR(victim); - victim = NULL; - goto out; - } - - inode = victim->d_inode; + sysfs_grab_supers(); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + victim = sysfs_get_dentry(sb, victim_sd); + if (victim == ERR_PTR(-EXDEV)) + continue; + if (IS_ERR(victim)) { + rc = PTR_ERR(victim); + victim = NULL; + goto out_unlock; + } + + inode = victim->d_inode; + mutex_lock(&inode->i_mutex); + newattrs.ia_mode = (mode & S_IALLUGO) | + (inode->i_mode & ~S_IALLUGO); + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; + rc = notify_change(victim, &newattrs); + if (rc == 0) { + mutex_lock(&sysfs_mutex); + victim_sd->s_mode = newattrs.ia_mode; + mutex_unlock(&sysfs_mutex); + } + mutex_unlock(&inode->i_mutex); - mutex_lock(&inode->i_mutex); - - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - rc = notify_change(victim, &newattrs); - - if (rc == 0) { - mutex_lock(&sysfs_mutex); - victim_sd->s_mode = newattrs.ia_mode; - mutex_unlock(&sysfs_mutex); + dput(victim); } - - mutex_unlock(&inode->i_mutex); - out: - dput(victim); +out_unlock: + sysfs_release_supers(); + mutex_unlock(&sysfs_rename_mutex); +out: sysfs_put(victim_sd); return rc; } -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-18 17:08 ` [PATCH 05/11] sysfs: sysfs_chmod_file handle " Benjamin Thery @ 2008-06-22 4:46 ` Tejun Heo 2008-06-23 21:42 ` Daniel Lezcano 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-06-22 4:46 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, guys. Sorry about the long silence. Recent releases of popular distros overwhelmed me with ata bugs. They now seem to be under control (and hopefully stay that way for some time to come). On the previous iteration, I was hoping I could sort out sysfs interface problem before this patchset but given that this is a long overdue feature, I think we should get this thing working first. The first four patches looked good to me, so feel free to add Acked-by: Tejun Heo <tj@kernel.org> Benjamin Thery Wrote: > sysfs: sysfs_chmod_file handle multiple superblocks > > Teach sysfs_chmod_file how to handle multiple sysfs > superblocks. I think it would be great if sysfs_chmod_file can do all-or-nothing instead of failing half way through but given the interface of notify_change(), it could be difficult to implement. Any ideas? Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-22 4:46 ` Tejun Heo @ 2008-06-23 21:42 ` Daniel Lezcano 2008-06-24 4:45 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Daniel Lezcano @ 2008-06-23 21:42 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo wrote: > Hello, guys. Sorry about the long silence. Recent releases of > popular distros overwhelmed me with ata bugs. They now seem to be > under control (and hopefully stay that way for some time to come). > > On the previous iteration, I was hoping I could sort out sysfs > interface problem before this patchset but given that this is a long > overdue feature, I think we should get this thing working first. > > The first four patches looked good to me, so feel free to add > Acked-by: Tejun Heo <tj@kernel.org> > > Benjamin Thery Wrote: >> sysfs: sysfs_chmod_file handle multiple superblocks >> >> Teach sysfs_chmod_file how to handle multiple sysfs >> superblocks. > > I think it would be great if sysfs_chmod_file can do all-or-nothing > instead of failing half way through but given the interface of > notify_change(), it could be difficult to implement. Any ideas? Is it acceptable to queue the notifications in a list until we are in the loop and loop again to notify when exiting the first loop without error ? ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-23 21:42 ` Daniel Lezcano @ 2008-06-24 4:45 ` Tejun Heo 2008-06-24 10:39 ` Daniel Lezcano 2008-06-24 13:37 ` Daniel Lezcano 0 siblings, 2 replies; 145+ messages in thread From: Tejun Heo @ 2008-06-24 4:45 UTC (permalink / raw) To: Daniel Lezcano Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, Daniel Lezcano wrote: >> I think it would be great if sysfs_chmod_file can do all-or-nothing >> instead of failing half way through but given the interface of >> notify_change(), it could be difficult to implement. Any ideas? > > Is it acceptable to queue the notifications in a list until we are in > the loop and loop again to notify when exiting the first loop without > error ? Can you please take a look at the following patch? http://article.gmane.org/gmane.linux.file-systems/24484 Which replaces notify_change() call to two calls to sysfs_setattr() and fsnotify_change(). The latter never fails and the former should always succeed if inode_change_ok() succeeds (inode_setattr() never fails unless the size is changing), so I think the correct thing to do is... * Separate out sysfs_do_setattr() which doesn't do inode_change_ok() and just sets the attributes. Making it a void function which triggers WARN_ON() when inode_setattr() fails would be a good idea. * Implement sysfs_chmod_file() in similar way rename/move are implemented - allocate all resources and check conditions and then iff everything looks okay commit the operation by calling sysfs_do_setattr(). How does that sound? Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-24 4:45 ` Tejun Heo @ 2008-06-24 10:39 ` Daniel Lezcano 2008-06-24 13:37 ` Daniel Lezcano 1 sibling, 0 replies; 145+ messages in thread From: Daniel Lezcano @ 2008-06-24 10:39 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo wrote: > Hello, > > Daniel Lezcano wrote: >>> I think it would be great if sysfs_chmod_file can do all-or-nothing >>> instead of failing half way through but given the interface of >>> notify_change(), it could be difficult to implement. Any ideas? >> Is it acceptable to queue the notifications in a list until we are in >> the loop and loop again to notify when exiting the first loop without >> error ? > > Can you please take a look at the following patch? > > http://article.gmane.org/gmane.linux.file-systems/24484 > > Which replaces notify_change() call to two calls to sysfs_setattr() and > fsnotify_change(). The latter never fails and the former should always > succeed if inode_change_ok() succeeds (inode_setattr() never fails > unless the size is changing), so I think the correct thing to do is... > > * Separate out sysfs_do_setattr() which doesn't do inode_change_ok() and > just sets the attributes. Making it a void function which triggers > WARN_ON() when inode_setattr() fails would be a good idea. > > * Implement sysfs_chmod_file() in similar way rename/move are > implemented - allocate all resources and check conditions and then iff > everything looks okay commit the operation by calling sysfs_do_setattr(). > > How does that sound? Much better than my first proposition :) I will do a separate patchset. Thanks. ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-24 4:45 ` Tejun Heo 2008-06-24 10:39 ` Daniel Lezcano @ 2008-06-24 13:37 ` Daniel Lezcano 2008-06-25 12:31 ` Tejun Heo 1 sibling, 1 reply; 145+ messages in thread From: Daniel Lezcano @ 2008-06-24 13:37 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel, Al Viro, Linux Containers [-- Attachment #1: Type: text/plain, Size: 1639 bytes --] Tejun Heo wrote: > Hello, > > Daniel Lezcano wrote: >>> I think it would be great if sysfs_chmod_file can do all-or-nothing >>> instead of failing half way through but given the interface of >>> notify_change(), it could be difficult to implement. Any ideas? >> Is it acceptable to queue the notifications in a list until we are in >> the loop and loop again to notify when exiting the first loop without >> error ? > > Can you please take a look at the following patch? > > http://article.gmane.org/gmane.linux.file-systems/24484 > > Which replaces notify_change() call to two calls to sysfs_setattr() and > fsnotify_change(). The latter never fails and the former should always > succeed if inode_change_ok() succeeds (inode_setattr() never fails > unless the size is changing), so I think the correct thing to do is... > > * Separate out sysfs_do_setattr() which doesn't do inode_change_ok() and > just sets the attributes. Making it a void function which triggers > WARN_ON() when inode_setattr() fails would be a good idea. > > * Implement sysfs_chmod_file() in similar way rename/move are > implemented - allocate all resources and check conditions and then iff > everything looks okay commit the operation by calling sysfs_do_setattr(). > > How does that sound? Does this patch looks like what you are describing ? Sauf indication contraire ci-dessus: Compagnie IBM France Siège Social : Tour Descartes, 2, avenue Gambetta, La Défense 5, 92400 Courbevoie RCS Nanterre 552 118 465 Forme Sociale : S.A.S. Capital Social : 542.737.118 ? SIREN/SIRET : 552 118 465 02430 [-- Attachment #2: separate-sysfs_setattr.patch --] [-- Type: text/plain, Size: 5869 bytes --] Subject: sysfs_chmod_file can do all-or-nothing From: Daniel Lezcano <dlezcano@fr.ibm.com> Idea from: Tejun Teo <htejun@gmail.com> "I think it would be great if sysfs_chmod_file can do all-or-nothing instead of failing half way through but given the interface of notify_change(), it could be difficult to implement. Can you please take a look at the following patch? http://article.gmane.org/gmane.linux.file-systems/24484 Which replaces notify_change() call to two calls to sysfs_setattr() and fsnotify_change(). The latter never fails and the former should always succeed if inode_change_ok() succeeds (inode_setattr() never fails unless the size is changing), so I think the correct thing to do is... * Separate out sysfs_do_setattr() which doesn't do inode_change_ok() and just sets the attributes. Making it a void function which triggers WARN_ON() when inode_setattr() fails would be a good idea." Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> --- fs/sysfs/file.c | 23 ++++++++++++----- fs/sysfs/inode.c | 73 +++++++++++++++++++++++++++++++++---------------------- fs/sysfs/sysfs.h | 3 ++ 3 files changed, 63 insertions(+), 36 deletions(-) Index: 2.6.26-rc5-mm3/fs/sysfs/inode.c =================================================================== --- 2.6.26-rc5-mm3.orig/fs/sysfs/inode.c +++ 2.6.26-rc5-mm3/fs/sysfs/inode.c @@ -42,41 +42,29 @@ int __init sysfs_inode_init(void) return bdi_init(&sysfs_backing_dev_info); } -int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) +struct iattr *sysfs_alloc_iattr(struct sysfs_dirent *sd) { - struct inode * inode = dentry->d_inode; - struct sysfs_dirent * sd = dentry->d_fsdata; struct iattr * sd_iattr; - unsigned int ia_valid = iattr->ia_valid; - int error; - if (!sd) - return -EINVAL; - - sd_iattr = sd->s_iattr; + sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); + if (sd_iattr) { + sd_iattr->ia_mode = sd->s_mode; + sd_iattr->ia_uid = sd_iattr->ia_gid = 0; + sd_iattr->ia_atime = sd_iattr->ia_mtime = \ + sd_iattr->ia_ctime = CURRENT_TIME; + } + return sd_iattr; +} - error = inode_change_ok(inode, iattr); - if (error) - return error; +void sysfs_do_setattr(struct sysfs_dirent * sd, struct inode * inode, + struct iattr * iattr) +{ + unsigned int ia_valid = iattr->ia_valid; + struct iattr * sd_iattr = sd->s_iattr; iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ - error = inode_setattr(inode, iattr); - if (error) - return error; - - if (!sd_iattr) { - /* setting attributes for the first time, allocate now */ - sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); - if (!sd_iattr) - return -ENOMEM; - /* assign default attributes */ - sd_iattr->ia_mode = sd->s_mode; - sd_iattr->ia_uid = 0; - sd_iattr->ia_gid = 0; - sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; - sd->s_iattr = sd_iattr; - } + WARN_ON(inode_setattr(inode, iattr)); /* attributes were changed atleast once in past */ @@ -100,8 +88,35 @@ int sysfs_setattr(struct dentry * dentry mode &= ~S_ISGID; sd_iattr->ia_mode = sd->s_mode = mode; } +} + +int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) +{ + struct inode * inode = dentry->d_inode; + struct sysfs_dirent * sd = dentry->d_fsdata; + struct iattr * sd_iattr; + int error; + + if (!sd) + return -EINVAL; + + error = inode_change_ok(inode, iattr); + if (error) + return error; + + sd_iattr = sd->s_iattr; + + if (!sd_iattr) { + /* setting attributes for the first time, allocate now */ + sd_iattr = sysfs_alloc_iattr(sd); + if (!sd_iattr) + return -ENOMEM; + sd->s_iattr = sd_iattr; + } + + sysfs_do_setattr(sd, inode, iattr); - return error; + return 0; } static inline void set_default_inode_attr(struct inode * inode, mode_t mode) Index: 2.6.26-rc5-mm3/fs/sysfs/file.c =================================================================== --- 2.6.26-rc5-mm3.orig/fs/sysfs/file.c +++ 2.6.26-rc5-mm3/fs/sysfs/file.c @@ -577,6 +577,7 @@ int sysfs_chmod_file(struct kobject *kob struct dentry *victim = NULL; struct inode * inode; struct iattr newattrs; + struct iattr * sd_iattr; int rc; rc = -ENOENT; @@ -593,6 +594,14 @@ int sysfs_chmod_file(struct kobject *kob goto out; } + sd_iattr = victim_sd->s_iattr; + if (!sd_iattr) { + sd_iattr = sysfs_alloc_iattr(victim_sd); + if (!sd_iattr) + return -ENOMEM; + victim_sd->s_iattr = sd_iattr; + } + inode = victim->d_inode; mutex_lock(&inode->i_mutex); @@ -600,14 +609,14 @@ int sysfs_chmod_file(struct kobject *kob newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_ctime = current_fs_time(inode->i_sb); - rc = sysfs_setattr(victim, &newattrs); - if (rc == 0) { - fsnotify_change(victim, newattrs.ia_valid); - mutex_lock(&sysfs_mutex); - victim_sd->s_mode = newattrs.ia_mode; - mutex_unlock(&sysfs_mutex); - } + /* These two functions do not fail */ + sysfs_do_setattr(victim_sd, inode, &newattrs); + fsnotify_change(victim, newattrs.ia_valid); + + mutex_lock(&sysfs_mutex); + victim_sd->s_mode = newattrs.ia_mode; + mutex_unlock(&sysfs_mutex); mutex_unlock(&inode->i_mutex); out: Index: 2.6.26-rc5-mm3/fs/sysfs/sysfs.h =================================================================== --- 2.6.26-rc5-mm3.orig/fs/sysfs/sysfs.h +++ 2.6.26-rc5-mm3/fs/sysfs/sysfs.h @@ -143,9 +143,12 @@ static inline void sysfs_put(struct sysf * inode.c */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); +struct iattr *sysfs_alloc_iattr(struct sysfs_dirent *sd); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_inode_init(void); +void sysfs_do_setattr(struct sysfs_dirent * sd, struct inode * inode, + struct iattr * iattr); /* * file.c ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 05/11] sysfs: sysfs_chmod_file handle multiple superblocks 2008-06-24 13:37 ` Daniel Lezcano @ 2008-06-25 12:31 ` Tejun Heo 0 siblings, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-06-25 12:31 UTC (permalink / raw) To: Daniel Lezcano Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Daniel Lezcano wrote: > Tejun Heo wrote: >> Hello, >> >> Daniel Lezcano wrote: >>>> I think it would be great if sysfs_chmod_file can do all-or-nothing >>>> instead of failing half way through but given the interface of >>>> notify_change(), it could be difficult to implement. Any ideas? >>> Is it acceptable to queue the notifications in a list until we are in >>> the loop and loop again to notify when exiting the first loop without >>> error ? >> >> Can you please take a look at the following patch? >> >> http://article.gmane.org/gmane.linux.file-systems/24484 >> >> Which replaces notify_change() call to two calls to sysfs_setattr() and >> fsnotify_change(). The latter never fails and the former should always >> succeed if inode_change_ok() succeeds (inode_setattr() never fails >> unless the size is changing), so I think the correct thing to do is... >> >> * Separate out sysfs_do_setattr() which doesn't do inode_change_ok() and >> just sets the attributes. Making it a void function which triggers >> WARN_ON() when inode_setattr() fails would be a good idea. >> >> * Implement sysfs_chmod_file() in similar way rename/move are >> implemented - allocate all resources and check conditions and then iff >> everything looks okay commit the operation by calling sysfs_do_setattr(). >> >> How does that sound? > > Does this patch looks like what you are describing ? Yeah, something like that. With looping for all the inodes added, it looks like it will work fine. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (4 preceding siblings ...) 2008-06-18 17:08 ` [PATCH 05/11] sysfs: sysfs_chmod_file handle " Benjamin Thery @ 2008-06-18 17:08 ` Benjamin Thery 2008-06-23 2:05 ` Tejun Heo 2008-06-18 17:08 ` [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link Benjamin Thery ` (4 subsequent siblings) 10 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: Implement sysfs tagged directory support. The problem. When implementing a network namespace I need to be able to have multiple network devices with the same name. Currently this is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and potentially a few other directories of the form /sys/ ... /net/*. What this patch does is to add an additional tag field to the sysfs dirent structure. For directories that should show different contents depending on the context such as /sys/class/net/, and /sys/devices/virtual/net/ this tag field is used to specify the context in which those directories should be visible. Effectively this is the same as creating multiple distinct directories with the same name but internally to sysfs the result is nicer. I am calling the concept of a single directory that looks like multiple directories all at the same path in the filesystem tagged directories. For the networking namespace the set of directories whose contents I need to filter with tags can depend on the presence or absence of hotplug hardware or which modules are currently loaded. Which means I need a simple race free way to setup those directories as tagged. To achieve a race free design all tagged directories are created and managed by sysfs itself. The upper level code that knows what tagged directories we need provides just two methods that enable this: sb_tag() - that returns a "void *" tag that identifies the context of the process that mounted sysfs. kobject_tag(kobj) - that returns a "void *" tag that identifies the context a kobject should be in. Everything else is left up to sysfs. For the network namespace sb_tag and kobject_tag are essentially one line functions, and look to remain that. The work needed in sysfs is more extensive. At each directory or symlink creating I need to check if the directory it is being created in is a tagged directory and if so generate the appropriate tag to place on the sysfs_dirent. Likewise at each symlink or directory removal I need to check if the sysfs directory it is being removed from is a tagged directory and if so figure out which tag goes along with the name I am deleting. Currently only directories which hold kobjects, and symlinks are supported. There is not enough information in the current file attribute interfaces to give us anything to discriminate on which makes it useless, and there are no potential users which makes it an uninteresting problem to solve. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/bin.c | 2 fs/sysfs/dir.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++---- fs/sysfs/file.c | 8 +- fs/sysfs/group.c | 4 - fs/sysfs/inode.c | 7 + fs/sysfs/mount.c | 44 ++++++++++- fs/sysfs/symlink.c | 2 fs/sysfs/sysfs.h | 17 ++++ include/linux/sysfs.h | 17 ++++ 9 files changed, 257 insertions(+), 29 deletions(-) Index: linux-mm/fs/sysfs/bin.c =================================================================== --- linux-mm.orig/fs/sysfs/bin.c +++ linux-mm/fs/sysfs/bin.c @@ -252,7 +252,7 @@ int sysfs_create_bin_file(struct kobject void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) { - sysfs_hash_and_remove(kobj->sd, attr->attr.name); + sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_create_bin_file); Index: linux-mm/fs/sysfs/dir.c =================================================================== --- linux-mm.orig/fs/sysfs/dir.c +++ linux-mm/fs/sysfs/dir.c @@ -101,8 +101,17 @@ static void sysfs_unlink_sibling(struct struct dentry *sysfs_get_dentry(struct super_block *sb, struct sysfs_dirent *sd) { - struct dentry *dentry = dget(sb->s_root); + struct dentry *dentry; + + /* Bail if this sd won't show up in this superblock */ + if (sd->s_parent && sd->s_parent->s_flags & SYSFS_FLAG_TAGGED) { + const void *tag; + tag = sysfs_lookup_tag(sd->s_parent, sb); + if (sd->s_tag.tag != tag) + return ERR_PTR(-EXDEV); + } + dentry = dget(sb->s_root); while (dentry->d_fsdata != sd) { struct sysfs_dirent *cur; struct dentry *parent; @@ -421,11 +430,18 @@ void sysfs_addrm_start(struct sysfs_addr */ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) + const void *tag = NULL; + + tag = sysfs_creation_tag(acxt->parent_sd, sd); + + if (sysfs_find_dirent(acxt->parent_sd, tag, sd->s_name)) return -EEXIST; sd->s_parent = sysfs_get(acxt->parent_sd); + if (sd->s_parent->s_flags & SYSFS_FLAG_TAGGED) + sd->s_tag.tag = tag; + if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) inc_nlink(acxt->parent_inode); @@ -572,13 +588,18 @@ void sysfs_addrm_finish(struct sysfs_add * Pointer to sysfs_dirent if found, NULL if not. */ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const void *tag, const unsigned char *name) { struct sysfs_dirent *sd; - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { + if ((parent_sd->s_flags & SYSFS_FLAG_TAGGED) && + (sd->s_tag.tag != tag)) + continue; if (!strcmp(sd->s_name, name)) return sd; + } return NULL; } @@ -602,7 +623,7 @@ struct sysfs_dirent *sysfs_get_dirent(st struct sysfs_dirent *sd; mutex_lock(&sysfs_mutex); - sd = sysfs_find_dirent(parent_sd, name); + sd = sysfs_find_dirent(parent_sd, NULL, name); sysfs_get(sd); mutex_unlock(&sysfs_mutex); @@ -668,13 +689,16 @@ static struct dentry * sysfs_lookup(stru struct nameidata *nd) { struct dentry *ret = NULL; - struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; + struct dentry *parent = dentry->d_parent; + struct sysfs_dirent *parent_sd = parent->d_fsdata; struct sysfs_dirent *sd; struct inode *inode; + const void *tag; mutex_lock(&sysfs_mutex); - sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); + tag = sysfs_lookup_tag(parent_sd, parent->d_sb); + sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); /* no such entry */ if (!sd) { @@ -882,19 +906,24 @@ int sysfs_rename_dir(struct kobject * ko struct sysfs_rename_struct *srs; struct inode *parent_inode = NULL; const char *dup_name = NULL; + const void *old_tag, *tag; int error; INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); + old_tag = sysfs_dirent_tag(sd); + tag = sysfs_creation_tag(sd->s_parent, sd); error = 0; - if (strcmp(sd->s_name, new_name) == 0) + if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) goto out; /* nothing to rename */ sysfs_grab_supers(); - error = prep_rename(&todo, sd, sd->s_parent, new_name); - if (error) - goto out_release; + if (old_tag == tag) { + error = prep_rename(&todo, sd, sd->s_parent, new_name); + if (error) + goto out_release; + } error = -ENOMEM; mutex_lock(&sysfs_mutex); @@ -907,7 +936,7 @@ int sysfs_rename_dir(struct kobject * ko mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(sd->s_parent, new_name)) + if (sysfs_find_dirent(sd->s_parent, tag, new_name)) goto out_unlock; /* rename kobject and sysfs_dirent */ @@ -922,6 +951,8 @@ int sysfs_rename_dir(struct kobject * ko dup_name = sd->s_name; sd->s_name = new_name; + if (sd->s_parent->s_flags & SYSFS_FLAG_TAGGED) + sd->s_tag.tag = tag; /* rename */ list_for_each_entry(srs, &todo, list) { @@ -929,6 +960,20 @@ int sysfs_rename_dir(struct kobject * ko d_move(srs->old_dentry, srs->new_dentry); } + /* If we are moving across superblocks drop the dcache entries */ + if (old_tag != tag) { + struct super_block *sb; + struct dentry *dentry; + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + dentry = __sysfs_get_dentry(sb, sd); + if (!dentry) + continue; + shrink_dcache_parent(dentry); + d_drop(dentry); + dput(dentry); + } + } + error = 0; out_unlock: mutex_unlock(&sysfs_mutex); @@ -951,11 +996,13 @@ int sysfs_move_dir(struct kobject *kobj, struct sysfs_rename_struct *srs; struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; int error; + const void *tag; INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; + tag = sysfs_dirent_tag(sd); error = 0; if (sd->s_parent == new_parent_sd) @@ -989,7 +1036,7 @@ again: mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) + if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) goto out_unlock; error = 0; @@ -1028,10 +1075,11 @@ static inline unsigned char dt_type(stru static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_path.dentry; - struct sysfs_dirent * parent_sd = dentry->d_fsdata; + struct dentry *parent = filp->f_path.dentry; + struct sysfs_dirent *parent_sd = parent->d_fsdata; struct sysfs_dirent *pos; ino_t ino; + const void *tag; if (filp->f_pos == 0) { ino = parent_sd->s_ino; @@ -1049,6 +1097,8 @@ static int sysfs_readdir(struct file * f if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { mutex_lock(&sysfs_mutex); + tag = sysfs_lookup_tag(parent_sd, parent->d_sb); + /* Skip the dentries we have already reported */ pos = parent_sd->s_dir.children; while (pos && (filp->f_pos > pos->s_ino)) @@ -1058,6 +1108,10 @@ static int sysfs_readdir(struct file * f const char * name; int len; + if ((parent_sd->s_flags & SYSFS_FLAG_TAGGED) && + (pos->s_tag.tag != tag)) + continue; + name = pos->s_name; len = strlen(name); filp->f_pos = ino = pos->s_ino; @@ -1078,3 +1132,106 @@ const struct file_operations sysfs_dir_o .read = generic_read_dir, .readdir = sysfs_readdir, }; + +const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, + struct sysfs_dirent *sd) +{ + const void *tag = NULL; + + if (parent_sd->s_flags & SYSFS_FLAG_TAGGED) { + struct kobject *kobj; + switch (sysfs_type(sd)) { + case SYSFS_DIR: + kobj = sd->s_dir.kobj; + break; + case SYSFS_KOBJ_LINK: + kobj = sd->s_symlink.target_sd->s_dir.kobj; + break; + default: + BUG(); + } + tag = parent_sd->s_tag.ops->kobject_tag(kobj); + } + return tag; +} + +const void *sysfs_removal_tag(struct kobject *kobj, struct sysfs_dirent *dir_sd) +{ + const void *tag = NULL; + + if (dir_sd->s_flags & SYSFS_FLAG_TAGGED) + tag = kobj->sd->s_tag.tag; + + return tag; +} + +const void *sysfs_lookup_tag(struct sysfs_dirent *dir_sd, + struct super_block *sb) +{ + const void *tag = NULL; + + if (dir_sd->s_flags & SYSFS_FLAG_TAGGED) + tag = dir_sd->s_tag.ops->sb_tag(&sysfs_info(sb)->tag); + + return tag; +} + +const void *sysfs_dirent_tag(struct sysfs_dirent *sd) +{ + const void *tag = NULL; + + if (sd->s_parent && (sd->s_parent->s_flags & SYSFS_FLAG_TAGGED)) + tag = sd->s_tag.tag; + + return tag; +} + +/** + * sysfs_enable_tagging - Automatically tag all of the children in a + * directory. + * @kobj: object whose children should be filtered by tags + * + * Once tagging has been enabled on a directory the contents + * of the directory become dependent upon context captured when + * sysfs was mounted. + * + * tag_ops->sb_tag() returns the context for a given superblock. + * + * tag_ops->kobject_tag() returns the context that a given kobj + * resides in. + * + * Using those methods the sysfs code on tagged directories + * carefully stores the files so that when we lookup files + * we get the proper answer for our context. + * + * If the context of a kobject is changed it is expected that + * the kobject will be renamed so the appopriate sysfs data structures + * can be updated. + */ +int sysfs_enable_tagging(struct kobject *kobj, + const struct sysfs_tagged_dir_operations *tag_ops) +{ + struct sysfs_dirent *sd; + int err; + + err = -ENOENT; + sd = kobj->sd; + + mutex_lock(&sysfs_mutex); + err = -EINVAL; + /* We can only enable tagging on empty directories + * where tagging is not already enabled, and + * who are not subdirectories of directories where tagging is + * enabled. + */ + if (!sd->s_dir.children && (sysfs_type(sd) == SYSFS_DIR) && + !(sd->s_flags & SYSFS_FLAG_TAGGED) && + sd->s_parent && + !(sd->s_parent->s_flags & SYSFS_FLAG_TAGGED)) { + err = 0; + sd->s_flags |= SYSFS_FLAG_TAGGED; + sd->s_tag.ops = tag_ops; + } + mutex_unlock(&sysfs_mutex); + return err; +} Index: linux-mm/fs/sysfs/file.c =================================================================== --- linux-mm.orig/fs/sysfs/file.c +++ linux-mm/fs/sysfs/file.c @@ -460,9 +460,9 @@ void sysfs_notify(struct kobject *k, cha mutex_lock(&sysfs_mutex); if (sd && dir) - sd = sysfs_find_dirent(sd, dir); + sd = sysfs_find_dirent(sd, NULL, dir); if (sd && attr) - sd = sysfs_find_dirent(sd, attr); + sd = sysfs_find_dirent(sd, NULL, attr); if (sd) { struct sysfs_open_dirent *od; @@ -631,7 +631,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) { - sysfs_hash_and_remove(kobj->sd, attr->name); + sysfs_hash_and_remove(kobj, kobj->sd, attr->name); } @@ -651,7 +651,7 @@ void sysfs_remove_file_from_group(struct else dir_sd = sysfs_get(kobj->sd); if (dir_sd) { - sysfs_hash_and_remove(dir_sd, attr->name); + sysfs_hash_and_remove(kobj, dir_sd, attr->name); sysfs_put(dir_sd); } } Index: linux-mm/fs/sysfs/group.c =================================================================== --- linux-mm.orig/fs/sysfs/group.c +++ linux-mm/fs/sysfs/group.c @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_di int i; for (i = 0, attr = grp->attrs; *attr; i++, attr++) - sysfs_hash_and_remove(dir_sd, (*attr)->name); + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); } static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dir * visibility. Do this by first removing then * re-adding (if required) the file */ if (update) - sysfs_hash_and_remove(dir_sd, (*attr)->name); + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); if (grp->is_visible) { mode = grp->is_visible(kobj, *attr, i); if (!mode) Index: linux-mm/fs/sysfs/inode.c =================================================================== --- linux-mm.orig/fs/sysfs/inode.c +++ linux-mm/fs/sysfs/inode.c @@ -217,17 +217,20 @@ struct inode * sysfs_get_inode(struct sy return inode; } -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, + const char *name) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; + const void *tag; if (!dir_sd) return -ENOENT; sysfs_addrm_start(&acxt, dir_sd); + tag = sysfs_removal_tag(kobj, dir_sd); - sd = sysfs_find_dirent(dir_sd, name); + sd = sysfs_find_dirent(dir_sd, tag, name); if (sd) sysfs_remove_one(&acxt, sd); Index: linux-mm/fs/sysfs/mount.c =================================================================== --- linux-mm.orig/fs/sysfs/mount.c +++ linux-mm/fs/sysfs/mount.c @@ -75,6 +75,7 @@ static int sysfs_fill_super(struct super goto out_err; } root->d_fsdata = &sysfs_root; + root->d_sb = sb; sb->s_root = root; sb->s_fs_info = info; return 0; @@ -88,20 +89,55 @@ out_err: return error; } +static int sysfs_test_super(struct super_block *sb, void *ptr) +{ + struct task_struct *task = ptr; + struct sysfs_super_info *info = sysfs_info(sb); + int found = 1; + + return found; +} + static int sysfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - int rc; + struct super_block *sb; + int error; mutex_lock(&sysfs_rename_mutex); - rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + sb = sget(fs_type, sysfs_test_super, set_anon_super, current); + if (IS_ERR(sb)) { + error = PTR_ERR(sb); + goto out; + } + if (!sb->s_root) { + sb->s_flags = flags; + error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); + if (error) { + up_write(&sb->s_umount); + deactivate_super(sb); + goto out; + } + sb->s_flags |= MS_ACTIVE; + } + do_remount_sb(sb, flags, data, 0); + error = simple_set_mnt(mnt, sb); +out: mutex_unlock(&sysfs_rename_mutex); - return rc; + return error; +} + +static void sysfs_kill_sb(struct super_block *sb) +{ + struct sysfs_super_info *info = sysfs_info(sb); + + kill_anon_super(sb); + kfree(info); } struct file_system_type sysfs_fs_type = { .name = "sysfs", .get_sb = sysfs_get_sb, - .kill_sb = kill_anon_super, + .kill_sb = sysfs_kill_sb, }; void sysfs_grab_supers(void) Index: linux-mm/fs/sysfs/symlink.c =================================================================== --- linux-mm.orig/fs/sysfs/symlink.c +++ linux-mm/fs/sysfs/symlink.c @@ -94,7 +94,7 @@ void sysfs_remove_link(struct kobject * else parent_sd = kobj->sd; - sysfs_hash_and_remove(parent_sd, name); + sysfs_hash_and_remove(kobj, parent_sd, name); } static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, Index: linux-mm/fs/sysfs/sysfs.h =================================================================== --- linux-mm.orig/fs/sysfs/sysfs.h +++ linux-mm/fs/sysfs/sysfs.h @@ -46,6 +46,10 @@ struct sysfs_dirent { const char *s_name; union { + const struct sysfs_tagged_dir_operations *ops; + const void *tag; + } s_tag; + union { struct sysfs_elem_dir s_dir; struct sysfs_elem_symlink s_symlink; struct sysfs_elem_attr s_attr; @@ -69,6 +73,7 @@ struct sysfs_dirent { #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK #define SYSFS_FLAG_REMOVED 0x0200 +#define SYSFS_FLAG_TAGGED 0x0400 static inline unsigned int sysfs_type(struct sysfs_dirent *sd) { @@ -87,6 +92,7 @@ struct sysfs_addrm_cxt { struct sysfs_super_info { int grabbed; + struct sysfs_tag_info tag; }; #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) @@ -113,6 +119,13 @@ extern spinlock_t sysfs_assoc_lock; extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; +extern const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, + struct sysfs_dirent *sd); +extern const void *sysfs_removal_tag(struct kobject *kobj, + struct sysfs_dirent *dir_sd); +extern const void *sysfs_lookup_tag(struct sysfs_dirent *dir_sd, + struct super_block *sb); +extern const void *sysfs_dirent_tag(struct sysfs_dirent *sd); struct dentry *sysfs_get_dentry(struct super_block *sb, struct sysfs_dirent *sd); struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); @@ -124,6 +137,7 @@ void sysfs_remove_one(struct sysfs_addrm void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const void *tag, const unsigned char *name); struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name); @@ -155,7 +169,8 @@ static inline void sysfs_put(struct sysf */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, + const char *name); int sysfs_inode_init(void); /* Index: linux-mm/include/linux/sysfs.h =================================================================== --- linux-mm.orig/include/linux/sysfs.h +++ linux-mm/include/linux/sysfs.h @@ -80,6 +80,14 @@ struct sysfs_ops { ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); }; +struct sysfs_tag_info { +}; + +struct sysfs_tagged_dir_operations { + const void *(*sb_tag)(struct sysfs_tag_info *info); + const void *(*kobject_tag)(struct kobject *kobj); +}; + #ifdef CONFIG_SYSFS int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), @@ -119,6 +127,9 @@ void sysfs_remove_file_from_group(struct void sysfs_notify(struct kobject *kobj, char *dir, char *attr); void sysfs_printk_last_file(void); +int sysfs_enable_tagging(struct kobject *kobj, + const struct sysfs_tagged_dir_operations *tag_ops); + extern int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ @@ -215,6 +226,12 @@ static inline void sysfs_notify(struct k { } +static inline int sysfs_enable_tagging(struct kobject *kobj, + const struct sysfs_tagged_dir_operations *tag_ops) +{ + return 0; +} + static inline int __must_check sysfs_init(void) { return 0; -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-18 17:08 ` [PATCH 06/11] sysfs: Implement sysfs tagged directory support Benjamin Thery @ 2008-06-23 2:05 ` Tejun Heo 2008-06-26 20:21 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-06-23 2:05 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, > Index: linux-mm/fs/sysfs/file.c > =================================================================== > --- linux-mm.orig/fs/sysfs/file.c > +++ linux-mm/fs/sysfs/file.c > @@ -460,9 +460,9 @@ void sysfs_notify(struct kobject *k, cha > mutex_lock(&sysfs_mutex); > > if (sd && dir) > - sd = sysfs_find_dirent(sd, dir); > + sd = sysfs_find_dirent(sd, NULL, dir); > if (sd && attr) > - sd = sysfs_find_dirent(sd, attr); > + sd = sysfs_find_dirent(sd, NULL, attr); > if (sd) { > struct sysfs_open_dirent *od; > As only directories can be tagged, I suppose handling tags explicitly isn't necessary here, right? Can we please add a comment explaning that? > Index: linux-mm/fs/sysfs/inode.c > =================================================================== > --- linux-mm.orig/fs/sysfs/inode.c > +++ linux-mm/fs/sysfs/inode.c > @@ -217,17 +217,20 @@ struct inode * sysfs_get_inode(struct sy > return inode; > } > > -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) > +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, > + const char *name) > { > struct sysfs_addrm_cxt acxt; > struct sysfs_dirent *sd; > + const void *tag; > > if (!dir_sd) > return -ENOENT; > > sysfs_addrm_start(&acxt, dir_sd); > + tag = sysfs_removal_tag(kobj, dir_sd); > > - sd = sysfs_find_dirent(dir_sd, name); > + sd = sysfs_find_dirent(dir_sd, tag, name); > if (sd) > sysfs_remove_one(&acxt, sd); Taking both @kobj and @dir_sd is ugly but it isn't your fault. I'll clean things up later. > Index: linux-mm/include/linux/sysfs.h > =================================================================== > --- linux-mm.orig/include/linux/sysfs.h > +++ linux-mm/include/linux/sysfs.h > @@ -80,6 +80,14 @@ struct sysfs_ops { > ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); > }; > > +struct sysfs_tag_info { > +}; > + > +struct sysfs_tagged_dir_operations { > + const void *(*sb_tag)(struct sysfs_tag_info *info); > + const void *(*kobject_tag)(struct kobject *kobj); > +}; As before, I can't bring myself to like this interface. Is computing tags dynamically really necessary? Can't we do the followings? tag = sysfs_allocate_tag(s); sysfs_enable_tag(kobj (or sd), tag); sysfs_sb_show_tag(sb, tag); Where tags are allocated using ida and each sb has bitmap of enabled tags so that sysfs ops can simply use something like the following to test whether it's enabled. bool sysfs_tag_enabled(sb, tag) { return sysfs_info(sb)->tag_map & (1 << tag); } Tags which can change dynamically seems too confusing to me and it makes things difficult to verify as it's unclear how those tags are gonna to change. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-23 2:05 ` Tejun Heo @ 2008-06-26 20:21 ` Eric W. Biederman 2008-06-29 3:51 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-06-26 20:21 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun thank you for the review, and my apologies for the delayed reply. Tejun Heo <htejun@gmail.com> writes: >> Index: linux-mm/include/linux/sysfs.h >> =================================================================== >> --- linux-mm.orig/include/linux/sysfs.h >> +++ linux-mm/include/linux/sysfs.h >> @@ -80,6 +80,14 @@ struct sysfs_ops { >> ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); >> }; >> >> +struct sysfs_tag_info { >> +}; >> + >> +struct sysfs_tagged_dir_operations { >> + const void *(*sb_tag)(struct sysfs_tag_info *info); >> + const void *(*kobject_tag)(struct kobject *kobj); >> +}; > > As before, I can't bring myself to like this interface. Is computing > tags dynamically really necessary? Can't we do the followings? It isn't so much computing tags dynamically but rather it is reading them from where they are stored. > tag = sysfs_allocate_tag(s); > sysfs_enable_tag(kobj (or sd), tag); > sysfs_sb_show_tag(sb, tag); > > Where tags are allocated using ida and each sb has bitmap of enabled > tags so that sysfs ops can simply use something like the following to > test whether it's enabled. > > bool sysfs_tag_enabled(sb, tag) > { > return sysfs_info(sb)->tag_map & (1 << tag); > } Youch that seems limiting. The expectation is that we could have as many as 100 different containers in use on a single system at one time. So 100 apparent copies of the network stack. There is also a second dimension here we multiplex different directories based on different sets of tags. One directory based on user namespaces another on the network namespaces. The tags in practice are just pointers to the namespace pointers. So while we could use the ida technique to specify which set of tags we are talking about for a directory it isn't sufficient. The question sysfs_tag_enabled(sb, tag) makes no sense to me. Especially in the context of needed a sysfs_sb_show_tag(sb, tag); The current structure is because of all of the darn fool races and magic that sysfs does. We have to say for a given directory: Your contents will always be tagged, and only those that one tag that matches what was captured by the superblock when sysfs is mounted will be shown. > Tags which can change dynamically seems too confusing to me and it > makes things difficult to verify as it's unclear how those tags are > gonna to change. We have a fundamental issue that we have to handle, and it sounds like you are proposing something that will not handle it. - network devices can move between namespaces. - network devices have driver specific sysfs attributes hanging off of them. So we have to move the network devices and their sysfs attributes between namespaces, and I implemented that in kobject_rename, sysfs_rename path. The tags on a kobject can only change during a rename operation. So when the change happens is well defined. Further there is a set of functions: sysfs_creation_tag, sysfs_removal_tag, sysfs_lookup_tag, sysfs_dirent_tag which makes it clear what we are doing. If you really don't like how the tags are managed we need to talk about how we store the tags on kobjects and on the super block. Registering a set of tags could easily make the sb_tag function obsolete, and that is one small piece of code so it is no big deal. struct sysfs_tag_type_operations { const void *(*mount_tag)(void); const void *(*kobject_tag)(struct kobject *kobj); }; Then we could do: struct sysfs_sbtag_operations *tag_type_ops[MAX_TAG_TYPES]; And sysfs_tag_info could become. struct sysfs_tag_info { void *tag[MAX_TAG_TYPES]; }; During subsystem initialization we could call tag_type = sysfs_allocate_tag_type(); Just after the subsystem creates a directory. sysfs_enable_tagging(kobj/sd, tag_type); Then anytime we currently call sb_tag during lookup we can instead just look at sysfs_info(sb)->tag[tag_type] and compare that with sd->s_tag.tag. The actual tag values themselves are current stored in the object in which the kobject is embedded. So we still need to call kobject_tag when we create or rename something in a tagged directory. So we know what the tag is. When we go to remove a kobj using the existing tag on the object is the right choice. Rename is the fun case where we need to grab the old tag from the sd and place on it the new tag from kobject_tag. One of the big problems at least with the class directories is that the lifetimes are completely decoupled the between the tags and the subsystem objects and subsystem directories that need to be tagged. This isn't a set things up at the start of your subsystem and everything is happy situation. To handle the races there must be support at least at the kobject level for handling this in the network namespace case. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-26 20:21 ` Eric W. Biederman @ 2008-06-29 3:51 ` Tejun Heo 2008-06-30 18:56 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-06-29 3:51 UTC (permalink / raw) To: Eric W. Biederman Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, Eric. Eric W. Biederman wrote: > Tejun thank you for the review, and my apologies for the delayed > reply. Me being the king of delays, no need for apologies. :-) >> As before, I can't bring myself to like this interface. Is computing >> tags dynamically really necessary? Can't we do the followings? > > It isn't so much computing tags dynamically but rather it is reading them > from where they are stored. It's still dynamic from sysfs's POV and I think that will make maintenance more difficult. >> tag = sysfs_allocate_tag(s); >> sysfs_enable_tag(kobj (or sd), tag); >> sysfs_sb_show_tag(sb, tag); >> >> Where tags are allocated using ida and each sb has bitmap of enabled >> tags so that sysfs ops can simply use something like the following to >> test whether it's enabled. >> >> bool sysfs_tag_enabled(sb, tag) >> { >> return sysfs_info(sb)->tag_map & (1 << tag); >> } > > > Youch that seems limiting. The expectation is that we could have > as many as 100 different containers in use on a single system at one > time. So 100 apparent copies of the network stack. 100 netns would mean 100 bits and 100 different views of them would mean 100 sb's where each sb would need bitmap larger than 100 bits. I don't think there would be a scalability problem. Am I missing something? > There is also a second dimension here we multiplex different > directories based on different sets of tags. One directory based > on user namespaces another on the network namespaces. No matter which criteria is used to select ns, it should end up being mapped to a set of tags (here, ida allocated numbers). Unless tags can change dynamically, there shouldn't be functional difference. > The tags in practice are just pointers to the namespace pointers. > > So while we could use the ida technique to specify which set of tags > we are talking about for a directory it isn't sufficient. I failed to follow here. Can you please elaborate a bit? If you can describe a simple example to me, it would be much appreciated. > The question sysfs_tag_enabled(sb, tag) makes no sense to me. > Especially in the context of needed a sysfs_sb_show_tag(sb, tag); > > The current structure is because of all of the darn fool races and > magic that sysfs does. We have to say for a given directory: Your > contents will always be tagged, and only those that one tag that > matches what was captured by the superblock when sysfs is mounted > will be shown. sysfs_tag_enabled() was meant to test whether a directory which is tagged should be shown under the current sb. >> Tags which can change dynamically seems too confusing to me and it >> makes things difficult to verify as it's unclear how those tags are >> gonna to change. > > We have a fundamental issue that we have to handle, and it sounds like > you are proposing something that will not handle it. > > - network devices can move between namespaces. > - network devices have driver specific sysfs attributes hanging off of them. > > So we have to move the network devices and their sysfs attributes > between namespaces, and I implemented that in kobject_rename, > sysfs_rename path. > > The tags on a kobject can only change during a rename operation. > So when the change happens is well defined. Further there is a > set of functions: sysfs_creation_tag, sysfs_removal_tag, > sysfs_lookup_tag, sysfs_dirent_tag which makes it clear what we > are doing. > > If you really don't like how the tags are managed we need to talk > about how we store the tags on kobjects and on the super block. > > Registering a set of tags could easily make the sb_tag function > obsolete, and that is one small piece of code so it is no big deal. > > struct sysfs_tag_type_operations { > const void *(*mount_tag)(void); > const void *(*kobject_tag)(struct kobject *kobj); > }; > > Then we could do: > struct sysfs_sbtag_operations *tag_type_ops[MAX_TAG_TYPES]; > > And sysfs_tag_info could become. > struct sysfs_tag_info { > void *tag[MAX_TAG_TYPES]; > }; > > During subsystem initialization we could call > tag_type = sysfs_allocate_tag_type(); > > Just after the subsystem creates a directory. > sysfs_enable_tagging(kobj/sd, tag_type); > > Then anytime we currently call sb_tag during lookup we can instead > just look at sysfs_info(sb)->tag[tag_type] and compare that with > sd->s_tag.tag. What you described is pretty much what I'm talking about. The only difference is whether to use caller-provided pointer as tag or an ida-allocated integer. The last sentence of the above paragraph is basically sys_tag_enabled() function (maybe misnamed). The main reason why I'm whining about this so much is because I think tag should be something abstracted inside sysfs proper. It's something which affects very internal operation of sysfs and I really want to keep the implementation details inside sysfs. Spreading implementation over kobject and sysfs didn't turn out too pretty after all. Thank you. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-29 3:51 ` Tejun Heo @ 2008-06-30 18:56 ` Eric W. Biederman [not found] ` <m18wwmsqdv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 2008-07-01 6:47 ` Tejun Heo 0 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-06-30 18:56 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > Hello, Eric. > > Eric W. Biederman wrote: >> Tejun thank you for the review, and my apologies for the delayed >> reply. > > Me being the king of delays, no need for apologies. :-) > >>> As before, I can't bring myself to like this interface. Is computing >>> tags dynamically really necessary? Can't we do the followings? >> >> It isn't so much computing tags dynamically but rather it is reading them >> from where they are stored. > > It's still dynamic from sysfs's POV and I think that will make > maintenance more difficult. Potentially. I have no problem make it clear that things are more static. >> There is also a second dimension here we multiplex different >> directories based on different sets of tags. One directory based >> on user namespaces another on the network namespaces. > > No matter which criteria is used to select ns, it should end up being > mapped to a set of tags (here, ida allocated numbers). Unless tags can > change dynamically, there shouldn't be functional difference. > >> The tags in practice are just pointers to the namespace pointers. >> >> So while we could use the ida technique to specify which set of tags >> we are talking about for a directory it isn't sufficient. > > I failed to follow here. Can you please elaborate a bit? If you can > describe a simple example to me, it would be much appreciated. See below. >> The question sysfs_tag_enabled(sb, tag) makes no sense to me. >> Especially in the context of needed a sysfs_sb_show_tag(sb, tag); >> >> The current structure is because of all of the darn fool races and >> magic that sysfs does. We have to say for a given directory: Your >> contents will always be tagged, and only those that one tag that >> matches what was captured by the superblock when sysfs is mounted >> will be shown. > > sysfs_tag_enabled() was meant to test whether a directory which is > tagged should be shown under the current sb. Ah. When we are doing readdir or lookup. Yes that makes sense. See below. I honestly think sysfs_tab_enabled is the wrong question. >>> Tags which can change dynamically seems too confusing to me and it >>> makes things difficult to verify as it's unclear how those tags are >>> gonna to change. >> >> We have a fundamental issue that we have to handle, and it sounds like >> you are proposing something that will not handle it. >> >> - network devices can move between namespaces. >> - network devices have driver specific sysfs attributes hanging off of them. >> >> So we have to move the network devices and their sysfs attributes >> between namespaces, and I implemented that in kobject_rename, >> sysfs_rename path. >> >> The tags on a kobject can only change during a rename operation. >> So when the change happens is well defined. Further there is a >> set of functions: sysfs_creation_tag, sysfs_removal_tag, >> sysfs_lookup_tag, sysfs_dirent_tag which makes it clear what we >> are doing. >> >> If you really don't like how the tags are managed we need to talk >> about how we store the tags on kobjects and on the super block. >> >> Registering a set of tags could easily make the sb_tag function >> obsolete, and that is one small piece of code so it is no big deal. >> >> struct sysfs_tag_type_operations { >> const void *(*mount_tag)(void); >> const void *(*kobject_tag)(struct kobject *kobj); >> }; >> >> Then we could do: >> struct sysfs_sbtag_operations *tag_type_ops[MAX_TAG_TYPES]; >> >> And sysfs_tag_info could become. >> struct sysfs_tag_info { >> void *tag[MAX_TAG_TYPES]; >> }; >> >> During subsystem initialization we could call >> tag_type = sysfs_allocate_tag_type(); >> >> Just after the subsystem creates a directory. >> sysfs_enable_tagging(kobj/sd, tag_type); >> >> Then anytime we currently call sb_tag during lookup we can instead >> just look at sysfs_info(sb)->tag[tag_type] and compare that with >> sd->s_tag.tag. > > What you described is pretty much what I'm talking about. The only > difference is whether to use caller-provided pointer as tag or an > ida-allocated integer. The last sentence of the above paragraph is > basically sys_tag_enabled() function (maybe misnamed). So some concrete code examples here. In the current code in lookup what I am doing is: tag = sysfs_lookup_tag(parent_sd, parent->d_sb); sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); With the proposed change of adding tag types sysfs_lookup_tag becomes: const void *sysfs_lookup_tag(struct sysfs_dirent *dir_sd, struct super_block *sb) { const void *tag = NULL; if (dir_sd->s_flags & SYSFS_FLAG_TAGGED) tag = sysfs_info(sb)->tag[dir_sd->tag_type]; return tag; } Which means that in practice I can lookup that tag that I am displaying once. Then in sysfs_find_dirent we do: for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { if ((parent_sd->s_flags & SYSFS_FLAG_TAGGED) && (sd->s_tag.tag != tag)) continue; if (!strcmp(sd->s_name, name)) return sd; } That should keep the implementation sufficiently inside of sysfs for there to be no guessing. In addition as a practical matter we can only allow one tag to be visible in a directory at once or else we can not check for duplicate names. Which is the problem I see with a bitmap based test too unnecessary many degrees of freedom. The number of tag types will be low as it is the number of subsystems that use the feature. Simple enough that I expect statically allocating the tag types in an enumeration is a safe and sane way to operate. i.e. enum sysfs_tag_types { SYSFS_TAG_NETNS, SYSFS_TAG_USERNS, SYSFS_TAG_MAX }; > The main reason why I'm whining about this so much is because I think > tag should be something abstracted inside sysfs proper. It's something > which affects very internal operation of sysfs and I really want to keep > the implementation details inside sysfs. Spreading implementation over > kobject and sysfs didn't turn out too pretty after all. I agree. Most of the implementation is in sysfs already. We just have a few corner cases. Fundamentally it is the subsystems responsibility that creates the kobjects and the sysfs entries. The only case where I can see an ida generated number being a help is if we start having lifetime issues. Further the extra work to allocate and free tags ida based tags seems unnecessary. I don't doubt that there is a lot we can do better. My current goal is for something that is clean enough it won't get us into trouble later, and then merging the code. In tree where people can see the code and the interactions I expect it will be easier to talk about. Currently the interface with the users is very small. Adding the tag_type enumeration should make it smaller and make things more obviously static. Guys can we please make something useful happen? Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <m18wwmsqdv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <m18wwmsqdv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-06-30 21:44 ` Serge E. Hallyn 2008-07-01 7:50 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Serge E. Hallyn @ 2008-06-30 21:44 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Daniel Lezcano, Andrew Morton, Benjamin Thery Quoting Eric W. Biederman (ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org): > Tejun Heo <htejun-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes: > > > Hello, Eric. > > > > Eric W. Biederman wrote: > >> Tejun thank you for the review, and my apologies for the delayed > >> reply. > > > > Me being the king of delays, no need for apologies. :-) > > > >>> As before, I can't bring myself to like this interface. Is computing > >>> tags dynamically really necessary? Can't we do the followings? > >> > >> It isn't so much computing tags dynamically but rather it is reading them > >> from where they are stored. > > > > It's still dynamic from sysfs's POV and I think that will make > > maintenance more difficult. > > Potentially. I have no problem make it clear that things are more static. > > >> There is also a second dimension here we multiplex different > >> directories based on different sets of tags. One directory based > >> on user namespaces another on the network namespaces. > > > > No matter which criteria is used to select ns, it should end up being > > mapped to a set of tags (here, ida allocated numbers). Unless tags can > > change dynamically, there shouldn't be functional difference. > > > >> The tags in practice are just pointers to the namespace pointers. > >> > >> So while we could use the ida technique to specify which set of tags > >> we are talking about for a directory it isn't sufficient. > > > > I failed to follow here. Can you please elaborate a bit? If you can > > describe a simple example to me, it would be much appreciated. > > See below. > > >> The question sysfs_tag_enabled(sb, tag) makes no sense to me. > >> Especially in the context of needed a sysfs_sb_show_tag(sb, tag); > >> > >> The current structure is because of all of the darn fool races and > >> magic that sysfs does. We have to say for a given directory: Your > >> contents will always be tagged, and only those that one tag that > >> matches what was captured by the superblock when sysfs is mounted > >> will be shown. > > > > sysfs_tag_enabled() was meant to test whether a directory which is > > tagged should be shown under the current sb. > > Ah. When we are doing readdir or lookup. Yes that makes sense. > > See below. I honestly think sysfs_tab_enabled is the wrong question. > > >>> Tags which can change dynamically seems too confusing to me and it > >>> makes things difficult to verify as it's unclear how those tags are > >>> gonna to change. > >> > >> We have a fundamental issue that we have to handle, and it sounds like > >> you are proposing something that will not handle it. > >> > >> - network devices can move between namespaces. > >> - network devices have driver specific sysfs attributes hanging off of them. > >> > >> So we have to move the network devices and their sysfs attributes > >> between namespaces, and I implemented that in kobject_rename, > >> sysfs_rename path. > >> > >> The tags on a kobject can only change during a rename operation. > >> So when the change happens is well defined. Further there is a > >> set of functions: sysfs_creation_tag, sysfs_removal_tag, > >> sysfs_lookup_tag, sysfs_dirent_tag which makes it clear what we > >> are doing. > >> > >> If you really don't like how the tags are managed we need to talk > >> about how we store the tags on kobjects and on the super block. > >> > >> Registering a set of tags could easily make the sb_tag function > >> obsolete, and that is one small piece of code so it is no big deal. > >> > >> struct sysfs_tag_type_operations { > >> const void *(*mount_tag)(void); > >> const void *(*kobject_tag)(struct kobject *kobj); > >> }; > >> > >> Then we could do: > >> struct sysfs_sbtag_operations *tag_type_ops[MAX_TAG_TYPES]; > >> > >> And sysfs_tag_info could become. > >> struct sysfs_tag_info { > >> void *tag[MAX_TAG_TYPES]; > >> }; > >> > >> During subsystem initialization we could call > >> tag_type = sysfs_allocate_tag_type(); > >> > >> Just after the subsystem creates a directory. > >> sysfs_enable_tagging(kobj/sd, tag_type); > >> > >> Then anytime we currently call sb_tag during lookup we can instead > >> just look at sysfs_info(sb)->tag[tag_type] and compare that with > >> sd->s_tag.tag. > > > > What you described is pretty much what I'm talking about. The only > > difference is whether to use caller-provided pointer as tag or an > > ida-allocated integer. The last sentence of the above paragraph is > > basically sys_tag_enabled() function (maybe misnamed). > > So some concrete code examples here. In the current code in lookup > what I am doing is: > > tag = sysfs_lookup_tag(parent_sd, parent->d_sb); > sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); > > With the proposed change of adding tag types sysfs_lookup_tag becomes: > > const void *sysfs_lookup_tag(struct sysfs_dirent *dir_sd, struct super_block *sb) > { > const void *tag = NULL; > > if (dir_sd->s_flags & SYSFS_FLAG_TAGGED) > tag = sysfs_info(sb)->tag[dir_sd->tag_type]; > > return tag; > } > > Which means that in practice I can lookup that tag that I am displaying > once. > > Then in sysfs_find_dirent we do: > > for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { > if ((parent_sd->s_flags & SYSFS_FLAG_TAGGED) && > (sd->s_tag.tag != tag)) > continue; > if (!strcmp(sd->s_name, name)) > return sd; > } > > That should keep the implementation sufficiently inside of sysfs for there > to be no guessing. In addition as a practical matter we can only allow > one tag to be visible in a directory at once or else we can not check > for duplicate names. Which is the problem I see with a bitmap based test > too unnecessary many degrees of freedom. > > The number of tag types will be low as it is the number of subsystems > that use the feature. Simple enough that I expect statically allocating > the tag types in an enumeration is a safe and sane way to operate. > i.e. > > enum sysfs_tag_types { > SYSFS_TAG_NETNS, > SYSFS_TAG_USERNS, > SYSFS_TAG_MAX > }; > > > The main reason why I'm whining about this so much is because I think > > tag should be something abstracted inside sysfs proper. It's something > > which affects very internal operation of sysfs and I really want to keep > > the implementation details inside sysfs. Spreading implementation over > > kobject and sysfs didn't turn out too pretty after all. > > I agree. Most of the implementation is in sysfs already. We just have > a few corner cases. > > Fundamentally it is the subsystems responsibility that creates the > kobjects and the sysfs entries. The only case where I can see an > ida generated number being a help is if we start having lifetime > issues. Further the extra work to allocate and free tags ida based > tags seems unnecessary. > > I don't doubt that there is a lot we can do better. My current goal > is for something that is clean enough it won't get us into trouble > later, and then merging the code. In tree where people can see > the code and the interactions I expect it will be easier to talk > about. > > Currently the interface with the users is very small. Adding the > tag_type enumeration should make it smaller and make things more > obviously static. > > Guys can we please make something useful happen? > > Eric Now that the iproute2 patch is upstream, this patchset really is the only thing keeping us from using network namespaces. Given that the details of the tagging are trivially changeable with no abi changes, I'd personally much rather see the patches go in as is, with whatever new tagging patches Benjamin whips up, using ida or some new idea, being applied later if we feel the need. -serge ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-30 21:44 ` Serge E. Hallyn @ 2008-07-01 7:50 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-01 7:50 UTC (permalink / raw) To: Serge E. Hallyn Cc: Tejun Heo, Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers "Serge E. Hallyn" <serue@us.ibm.com> writes: > Now that the iproute2 patch is upstream, this patchset really is the > only thing keeping us from using network namespaces. Given that the > details of the tagging are trivially changeable with no abi changes, I'd > personally much rather see the patches go in as is, with whatever new > tagging patches Benjamin whips up, using ida or some new idea, being > applied later if we feel the need. My point exactly. No one seems to contest the userspace semantics so as long as we don't put ourselves into a real mess we should be fine. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-06-30 18:56 ` Eric W. Biederman [not found] ` <m18wwmsqdv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-07-01 6:47 ` Tejun Heo 2008-07-01 9:20 ` Eric W. Biederman 1 sibling, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-01 6:47 UTC (permalink / raw) To: Eric W. Biederman Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, Eric. Eric W. Biederman wrote: >> It's still dynamic from sysfs's POV and I think that will make >> maintenance more difficult. > > Potentially. I have no problem make it clear that things are more static. Great. :-) >> What you described is pretty much what I'm talking about. The only >> difference is whether to use caller-provided pointer as tag or an >> ida-allocated integer. The last sentence of the above paragraph is >> basically sys_tag_enabled() function (maybe misnamed). > > So some concrete code examples here. In the current code in lookup > what I am doing is: > > tag = sysfs_lookup_tag(parent_sd, parent->d_sb); > sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); > > With the proposed change of adding tag types sysfs_lookup_tag becomes: > > const void *sysfs_lookup_tag(struct sysfs_dirent *dir_sd, struct super_block *sb) > { > const void *tag = NULL; > > if (dir_sd->s_flags & SYSFS_FLAG_TAGGED) > tag = sysfs_info(sb)->tag[dir_sd->tag_type]; > > return tag; > } > > Which means that in practice I can lookup that tag that I am displaying > once. > > Then in sysfs_find_dirent we do: > > for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { > if ((parent_sd->s_flags & SYSFS_FLAG_TAGGED) && > (sd->s_tag.tag != tag)) > continue; > if (!strcmp(sd->s_name, name)) > return sd; > } > > That should keep the implementation sufficiently inside of sysfs for there > to be no guessing. In addition as a practical matter we can only allow > one tag to be visible in a directory at once or else we can not check > for duplicate names. Which is the problem I see with a bitmap based test > too unnecessary many degrees of freedom. Having enumed tag types limits that a sb can have map to only one tag but it doesn't really prevent multiple possibly visible entries which is the real unnecessary degrees of freedom. That said, I don't really think it's an issue. > The number of tag types will be low as it is the number of subsystems > that use the feature. Simple enough that I expect statically allocating > the tag types in an enumeration is a safe and sane way to operate. > i.e. > > enum sysfs_tag_types { > SYSFS_TAG_NETNS, > SYSFS_TAG_USERNS, > SYSFS_TAG_MAX > }; I still would prefer something which is more generic. The abstraction is clearer too. A sb shows untagged and a set of tags. A sd can either be untagged or tagged (a single tag). >> The main reason why I'm whining about this so much is because I think >> tag should be something abstracted inside sysfs proper. It's something >> which affects very internal operation of sysfs and I really want to keep >> the implementation details inside sysfs. Spreading implementation over >> kobject and sysfs didn't turn out too pretty after all. > > I agree. Most of the implementation is in sysfs already. We just have > a few corner cases. > > Fundamentally it is the subsystems responsibility that creates the > kobjects and the sysfs entries. The only case where I can see an > ida generated number being a help is if we start having lifetime > issues. Further the extra work to allocate and free tags ida based > tags seems unnecessary. > > I don't doubt that there is a lot we can do better. My current goal > is for something that is clean enough it won't get us into trouble > later, and then merging the code. In tree where people can see > the code and the interactions I expect it will be easier to talk > about. > > Currently the interface with the users is very small. Adding the > tag_type enumeration should make it smaller and make things more > obviously static. Using ida (or idr if a pointer for private data is necessary) is really easy. It'll probably take a few tens of lines of code. That said, I don't think I have enough rationale to nack what you described. So, as long as the tags are made static, I won't object. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-01 6:47 ` Tejun Heo @ 2008-07-01 9:20 ` Eric W. Biederman 2008-07-01 10:30 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-01 9:20 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > Hello, Eric. > > Eric W. Biederman wrote: >>> It's still dynamic from sysfs's POV and I think that will make >>> maintenance more difficult. >> >> Potentially. I have no problem make it clear that things are more static. > > Great. :-) > > Having enumed tag types limits that a sb can have map to only one tag > but it doesn't really prevent multiple possibly visible entries which is > the real unnecessary degrees of freedom. That said, I don't really > think it's an issue. Having a single tag type per directory and thus a single tag visible per directory does prevent multiple possible visible entries. That is we can check when we add the sd if there will be a conflict in the directory. >> The number of tag types will be low as it is the number of subsystems >> that use the feature. Simple enough that I expect statically allocating >> the tag types in an enumeration is a safe and sane way to operate. >> i.e. >> >> enum sysfs_tag_types { >> SYSFS_TAG_NETNS, >> SYSFS_TAG_USERNS, >> SYSFS_TAG_MAX >> }; > > I still would prefer something which is more generic. The abstraction > is clearer too. A sb shows untagged and a set of tags. A sd can either > be untagged or tagged (a single tag). That is the abstraction now. The only difference is how we represent the set of tags. I use and array of the valid tags. You use a bitmap. And array allows the lookup of the tag I am looking for before I search for the sd. An bitmap requires me to compare each entry. For me that is a deal breaker. Currently in certain pathological cases we have scaling issues with sysctl and sysfs that we can have enormous directories that start running slowly. To fix lookup performance requires that we know the full name before we do the directory search which is the name string and the tag. So I having a type of tag as being of fundamental importance in the interface now so we don't need to refactor all of the users later. In addition to the fact that we need the type to know how to set the tags when mounting a superblock and when given a new kobject to create an sd for. We could make the types dynamic rather then a static enumeration but that seems needless complexity for now. > Using ida (or idr if a pointer for private data is necessary) is really > easy. It'll probably take a few tens of lines of code. That said, I > don't think I have enough rationale to nack what you described. So, as > long as the tags are made static, I won't object. Sounds good. The only justification I can think of for ida tags is that they are smaller, and so can keep the sysfs_dirents smaller. Which occasionally is a significant concern. Still that should be an optimization that we can apply later, as it is not a structural difference in the code. Just to confirm. Do you the two operations: mount_tag - called only when the sb is mounted kobject_tag - called when we create new sd or rename an sd Cause you to view an the tags as dynamic? Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-01 9:20 ` Eric W. Biederman @ 2008-07-01 10:30 ` Tejun Heo 2008-07-01 12:30 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-01 10:30 UTC (permalink / raw) To: Eric W. Biederman Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, Eric W. Biederman wrote: >> Having enumed tag types limits that a sb can have map to only one tag >> but it doesn't really prevent multiple possibly visible entries which is >> the real unnecessary degrees of freedom. That said, I don't really >> think it's an issue. > > Having a single tag type per directory and thus a single tag visible per > directory does prevent multiple possible visible entries. > > That is we can check when we add the sd if there will be a conflict in > the directory. Yeap, that we can do. >> I still would prefer something which is more generic. The abstraction >> is clearer too. A sb shows untagged and a set of tags. A sd can either >> be untagged or tagged (a single tag). > > That is the abstraction now. > > The only difference is how we represent the set of tags. > I use and array of the valid tags. > You use a bitmap. > > And array allows the lookup of the tag I am looking for before > I search for the sd. An bitmap requires me to compare each entry. How so? sysfs_sb->bitmap which contains enough bits for all the defined tags and determining whether a sd should be shown or not is as simple as single test_bit. > For me that is a deal breaker. Currently in certain pathological > cases we have scaling issues with sysctl and sysfs that we can > have enormous directories that start running slowly. To fix > lookup performance requires that we know the full name before > we do the directory search which is the name string and the > tag. > > So I having a type of tag as being of fundamental importance in > the interface now so we don't need to refactor all of the users > later. In addition to the fact that we need the type to know > how to set the tags when mounting a superblock and when > given a new kobject to create an sd for. > > We could make the types dynamic rather then a static enumeration but > that seems needless complexity for now. What I'm feeling unease about is the extra level of abstraction added by tag types. A sd is given a tag. A sb shows a set of tags. The most straight forward to implement that is to give sd a tag and test the tag against sb's set of tags. The type is added because pointer tag requires sequential matching which is usually best to avoid. It's nothing fundamental. It's an extra baggage. >> Using ida (or idr if a pointer for private data is necessary) is really >> easy. It'll probably take a few tens of lines of code. That said, I >> don't think I have enough rationale to nack what you described. So, as >> long as the tags are made static, I won't object. > > Sounds good. The only justification I can think of for ida tags is that > they are smaller, and so can keep the sysfs_dirents smaller. Which > occasionally is a significant concern. Still that should be an optimization > that we can apply later, as it is not a structural difference in the code. > > Just to confirm. Do you the two operations: > mount_tag - called only when the sb is mounted > kobject_tag - called when we create new sd or rename an sd > > Cause you to view an the tags as dynamic? The thing is that I don't really see why there's tagged_dir_ops at all. What's needed is tagged sd's and sb's which can show subset of those tags, so adding callback ops for tags just doesn't make much sense to me. The interface should ideally be... 1. alloc/release tag 2. set / change / remove tag on sd 3. enable / disable tag on a sb This has been my opinion from the beginning. Unless the tags need to be changed dynamically on demand (which I hope is not the case), there just is plainly no reason to have callbacks for tags. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-01 10:30 ` Tejun Heo @ 2008-07-01 12:30 ` Eric W. Biederman 2008-07-02 3:24 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-01 12:30 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > Hello, > > Eric W. Biederman wrote: >>> Having enumed tag types limits that a sb can have map to only one tag >>> but it doesn't really prevent multiple possibly visible entries which is >>> the real unnecessary degrees of freedom. That said, I don't really >>> think it's an issue. >> >> Having a single tag type per directory and thus a single tag visible per >> directory does prevent multiple possible visible entries. >> >> That is we can check when we add the sd if there will be a conflict in >> the directory. > > Yeap, that we can do. What we are implementing is not, a sb with a set of tags that are displayed, but directories with a single tag that is displayed. The sb just happens to hold the state for the directories. A directory displaying only a single tag is an necessary constraint for a large number of reasons. >> And array allows the lookup of the tag I am looking for before >> I search for the sd. An bitmap requires me to compare each entry. > > How so? sysfs_sb->bitmap which contains enough bits for all the defined > tags and determining whether a sd should be shown or not is as simple as > single test_bit. Yes. The compare happens to be test_bit. With a bitmap you must visit each dirent with a given name and see if it has a tag that is displayed. With an array you can lookup the tag aprori and can potentially do a hash table lookup or a tree lookup and are not required to visit each entry. > What I'm feeling unease about is the extra level of abstraction added by > tag types. A sd is given a tag. A sb shows a set of tags. The most > straight forward to implement that is to give sd a tag and test the tag > against sb's set of tags. The type is added because pointer tag > requires sequential matching which is usually best to avoid. It's > nothing fundamental. It's an extra baggage. That is just one important aspect of it. We need a way to describe which tag a sb,directory pair displays. It is a fundamental concept. >>> Using ida (or idr if a pointer for private data is necessary) is really >>> easy. It'll probably take a few tens of lines of code. That said, I >>> don't think I have enough rationale to nack what you described. So, as >>> long as the tags are made static, I won't object. >> >> Sounds good. The only justification I can think of for ida tags is that >> they are smaller, and so can keep the sysfs_dirents smaller. Which >> occasionally is a significant concern. Still that should be an optimization >> that we can apply later, as it is not a structural difference in the code. >> >> Just to confirm. Do you the two operations: >> mount_tag - called only when the sb is mounted >> kobject_tag - called when we create new sd or rename an sd >> >> Cause you to view an the tags as dynamic? > > The thing is that I don't really see why there's tagged_dir_ops at all. We need callbacks for interfacing with the kobject layer, and for selecting our set of tags at mount time. Not tagged_dir_ops so much as tagged_type_ops. > What's needed is tagged sd's and sb's which can show subset of those > tags, so adding callback ops for tags just doesn't make much sense to > me. The interface should ideally be... > 1. alloc/release tag Agreed. > 2. set / change / remove tag on sd Essentially agreed. Create an sd with a tag, change the tag on a sd. Having an untagged sd in a directory that requires tags should not be allowed. > 3. enable / disable tag on a sb Disagree that is too flexible. Tags on a sb need to be unchanging or else we get vfs layer issues. Further the abstraction is logically exactly one tag on a (sb,directory) pair. The operations needed are. - Select the set of tags on a sb (at mount time) This requires we call a set of callbacks. [ My mount_sb callback ] - release a tag (which implies removing all tagged entries and removing the sb reference) 4. Interface with the kobject layer. kobject_add calls sysfs_create_dir kboject_rename calls sysfs_rename_dir kobject_del calls sysfs_remove_dir For the first two operations we need a helper function to go from a kobject to a tag. For the second two operations we need to go from a kobject to a sd. > This has been my opinion from the beginning. Unless the tags need to be > changed dynamically on demand (which I hope is not the case), there just > is plainly no reason to have callbacks for tags. We don't need callbacks to poll to see if the tags on a sd have changed. We need helper functions for interfacing with the rest of the kernel. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-01 12:30 ` Eric W. Biederman @ 2008-07-02 3:24 ` Tejun Heo 2008-07-02 3:53 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-02 3:24 UTC (permalink / raw) To: Eric W. Biederman Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, Eric W. Biederman wrote: > What we are implementing is not, a sb with a set of tags that are displayed, > but directories with a single tag that is displayed. The sb just happens > to hold the state for the directories. > > A directory displaying only a single tag is an necessary constraint for > a large number of reasons. Okay, that isn't exactly the impression I get but... well. Let's see. >>> And array allows the lookup of the tag I am looking for before >>> I search for the sd. An bitmap requires me to compare each entry. >> How so? sysfs_sb->bitmap which contains enough bits for all the defined >> tags and determining whether a sd should be shown or not is as simple as >> single test_bit. > > Yes. The compare happens to be test_bit. > > With a bitmap you must visit each dirent with a given name and see if > it has a tag that is displayed. > > With an array you can lookup the tag aprori and can potentially do a > hash table lookup or a tree lookup and are not required to visit each > entry. A few things... 1. The lookup is currently done linearly and is fast enough for now. Also, most lookup ops are cached by vfs layer. I'm not sure how probable it is that we're gonna need hash or tree based sd lookup. 2. I don't think it's gonna be too difficult to speed up bitmap based lookup. It would require a bit more intelligence but there's no fundamental restriction. Just organizing the tree by tag first would give us the same order of magnitude lookup given that the tags are used the same way. >> What I'm feeling unease about is the extra level of abstraction added by >> tag types. A sd is given a tag. A sb shows a set of tags. The most >> straight forward to implement that is to give sd a tag and test the tag >> against sb's set of tags. The type is added because pointer tag >> requires sequential matching which is usually best to avoid. It's >> nothing fundamental. It's an extra baggage. > > That is just one important aspect of it. We need a way to describe > which tag a sb,directory pair displays. It is a fundamental concept. For netns, yes. I just think it would be better if the sysfs mechanism to support that concept is more generic especially because it doesn't seem too difficult to make it that way. >>> Cause you to view an the tags as dynamic? >> The thing is that I don't really see why there's tagged_dir_ops at all. > > We need callbacks for interfacing with the kobject layer, and for > selecting our set of tags at mount time. Not tagged_dir_ops so much > as tagged_type_ops. The kobject op seems a bit strange way to interface to me. For mount, yeah, we'll need a hook somewhere or pass it via mount option maybe. >> What's needed is tagged sd's and sb's which can show subset of those >> tags, so adding callback ops for tags just doesn't make much sense to >> me. The interface should ideally be... > >> 1. alloc/release tag > Agreed. > >> 2. set / change / remove tag on sd > Essentially agreed. > > Create an sd with a tag, change the tag on a sd. > Having an untagged sd in a directory that requires tags should > not be allowed. > >> 3. enable / disable tag on a sb > Disagree that is too flexible. Tags on a sb need to be > unchanging or else we get vfs layer issues. Yeah, this really should be something which can't change once it's mounted. > Further the abstraction is logically exactly one tag on a > (sb,directory) pair. I'm not so sure here. As a policy, maybe but I don't really see a fundamental reason that the mechanism should enforce this. > The operations needed are. > - Select the set of tags on a sb (at mount time) > This requires we call a set of callbacks. [ My mount_sb callback ] > > - release a tag (which implies removing all tagged entries and > removing the sb reference) > > 4. Interface with the kobject layer. > kobject_add calls sysfs_create_dir > kboject_rename calls sysfs_rename_dir > kobject_del calls sysfs_remove_dir > > For the first two operations we need a helper function to go from a > kobject to a tag. Why not just add a parameter to sysfs_create_dir()? It's just twisted. > For the second two operations we need to go from a kobject to a sd. > >> This has been my opinion from the beginning. Unless the tags need to be >> changed dynamically on demand (which I hope is not the case), there just >> is plainly no reason to have callbacks for tags. > > We don't need callbacks to poll to see if the tags on a sd have > changed. > > We need helper functions for interfacing with the rest of the kernel. Yes, that's why I view it as strange. These can be done in forward way (by passing in mount options and/or arguments) but it's done by first going into the sysfs and then calling back out to outer layer. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-02 3:24 ` Tejun Heo @ 2008-07-02 3:53 ` Eric W. Biederman 2008-07-02 4:37 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-02 3:53 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > Hello, > > Eric W. Biederman wrote: >> What we are implementing is not, a sb with a set of tags that are displayed, >> but directories with a single tag that is displayed. The sb just happens >> to hold the state for the directories. >> >> A directory displaying only a single tag is an necessary constraint for >> a large number of reasons. > > Okay, that isn't exactly the impression I get but... well. Let's see. Well one of those reasons is not having duplicate entries in your directory listing. That is much harder otherwise. > A few things... > > 1. The lookup is currently done linearly and is fast enough for now. > Also, most lookup ops are cached by vfs layer. I'm not sure how > probable it is that we're gonna need hash or tree based sd lookup. I don't know how bad sysfs is. On the sysctl side I have people complaining because I am doing a lookup during insert and that lookup is linear. Sysfs appears to have the same complexity as sysctl but just smaller constants. >> That is just one important aspect of it. We need a way to describe >> which tag a sb,directory pair displays. It is a fundamental concept. > > For netns, yes. I just think it would be better if the sysfs mechanism > to support that concept is more generic especially because it doesn't > seem too difficult to make it that way. Well the envisioned use is for other namespaces and they all are similar to the network namespace in that way. >>>> Cause you to view an the tags as dynamic? >>> The thing is that I don't really see why there's tagged_dir_ops at all. >> >> We need callbacks for interfacing with the kobject layer, and for >> selecting our set of tags at mount time. Not tagged_dir_ops so much >> as tagged_type_ops. > > The kobject op seems a bit strange way to interface to me. For mount, > yeah, we'll need a hook somewhere or pass it via mount option maybe. I will look how if there is a place in the kobject layer to put it. With a second but noticeably different user I can compare and see how hard that will be. >>> 3. enable / disable tag on a sb >> Disagree that is too flexible. Tags on a sb need to be >> unchanging or else we get vfs layer issues. > > Yeah, this really should be something which can't change once it's mounted. The VFS chokes otherwise because it can't cache things properly. >> Further the abstraction is logically exactly one tag on a >> (sb,directory) pair. > > I'm not so sure here. As a policy, maybe but I don't really see a > fundamental reason that the mechanism should enforce this. Well in the first implementation. >> 4. Interface with the kobject layer. >> kobject_add calls sysfs_create_dir >> kboject_rename calls sysfs_rename_dir >> kobject_del calls sysfs_remove_dir >> >> For the first two operations we need a helper function to go from a >> kobject to a tag. > > Why not just add a parameter to sysfs_create_dir()? It's just twisted. I added it where it was easiest. Adding a parameter to sysfs_create_dir simply means I have to add the function to the kobject layer. It is certainly worth a second look though. >> We need helper functions for interfacing with the rest of the kernel. > > Yes, that's why I view it as strange. These can be done in forward way > (by passing in mount options and/or arguments) but it's done by first > going into the sysfs and then calling back out to outer layer. Well in the case of mount the default parameter at least is current, and there are good reasons for that. On the other side I can't pass a tag through from the device layer to the kobject layer. It isn't a concept the kobject layer supports. At least though the conversation is in relative agreement. I will refresh the patches shortly and see where we are at. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-02 3:53 ` Eric W. Biederman @ 2008-07-02 4:37 ` Tejun Heo [not found] ` <486B060C.7030607-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 2008-07-02 16:49 ` Eric W. Biederman 0 siblings, 2 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-02 4:37 UTC (permalink / raw) To: Eric W. Biederman Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Hello, Eric W. Biederman wrote: >>> A directory displaying only a single tag is an necessary constraint for >>> a large number of reasons. >> Okay, that isn't exactly the impression I get but... well. Let's see. > > Well one of those reasons is not having duplicate entries in your directory listing. > That is much harder otherwise. Agreed. >> For netns, yes. I just think it would be better if the sysfs mechanism >> to support that concept is more generic especially because it doesn't >> seem too difficult to make it that way. > > Well the envisioned use is for other namespaces and they all are similar > to the network namespace in that way. Something I've been curious about is a directory which contains both the untagged entries and tagged ones. I can definitely imagine something like that to be useful for block device namespace. >>>>> Cause you to view an the tags as dynamic? >>>> The thing is that I don't really see why there's tagged_dir_ops at all. >>> We need callbacks for interfacing with the kobject layer, and for >>> selecting our set of tags at mount time. Not tagged_dir_ops so much >>> as tagged_type_ops. >> The kobject op seems a bit strange way to interface to me. For mount, >> yeah, we'll need a hook somewhere or pass it via mount option maybe. > > I will look how if there is a place in the kobject layer to put it. With > a second but noticeably different user I can compare and see how hard that will be. Great, thanks. >>> Further the abstraction is logically exactly one tag on a >>> (sb,directory) pair. >> I'm not so sure here. As a policy, maybe but I don't really see a >> fundamental reason that the mechanism should enforce this. > > Well in the first implementation. This pretty much defines the interface and is likely to force future users to fit themselves into it. >>> 4. Interface with the kobject layer. >>> kobject_add calls sysfs_create_dir >>> kboject_rename calls sysfs_rename_dir >>> kobject_del calls sysfs_remove_dir >>> >>> For the first two operations we need a helper function to go from a >>> kobject to a tag. >> Why not just add a parameter to sysfs_create_dir()? It's just twisted. > > I added it where it was easiest. Adding a parameter to sysfs_create_dir > simply means I have to add the function to the kobject layer. It is certainly > worth a second look though. Is it difficult to just export it via kobject and device layer? If changing the default function is too much of a hassle (and I'm sure it would be), just add an extended version which takes @tag. The current implementation feels like it tried too hard to not add intermediate interfaces and ended up shooting outside from the innermost layer. >>> We need helper functions for interfacing with the rest of the kernel. >> Yes, that's why I view it as strange. These can be done in forward way >> (by passing in mount options and/or arguments) but it's done by first >> going into the sysfs and then calling back out to outer layer. > > Well in the case of mount the default parameter at least is current, and > there are good reasons for that. I was imagining something like... mount -t sysfs -o ns=0,4,5 /my/sys And let the userland control which ns's are visible in the particular mount. I'm not sure how useful that will be tho. > On the other side I can't pass a tag through from the device layer to > the kobject layer. It isn't a concept the kobject layer supports. I think it's best to make kobject layer support it. > At least though the conversation is in relative agreement. I will refresh > the patches shortly and see where we are at. Thanks a lot for the patience. :-) -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <486B060C.7030607-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <486B060C.7030607-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2008-07-02 7:18 ` Andreas B Aaen 0 siblings, 0 replies; 145+ messages in thread From: Andreas B Aaen @ 2008-07-02 7:18 UTC (permalink / raw) To: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA On Wednesday 02 July 2008 06:37, Tejun Heo wrote: > I was imagining something like... > > mount -t sysfs -o ns=0,4,5 /my/sys > > And let the userland control which ns's are visible in the particular > mount. I'm not sure how useful that will be tho. Useful. However I didn't know that an indexnumber was associated with the network namespaces. Especially if you want to use network namespaces for scaleability and not isolation purposes. Regards, -- Andreas Bach Aaen System Developer, M. Sc. Tieto Enator A/S tel: +45 89 38 51 00 Skanderborgvej 232 fax: +45 89 38 51 01 8260 Viby J Denmark andreas.aaen-546VmZ+UeKYX2WXlbB3fKg@public.gmane.org ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-02 4:37 ` Tejun Heo [not found] ` <486B060C.7030607-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2008-07-02 16:49 ` Eric W. Biederman 2008-07-03 0:15 ` Greg KH [not found] ` <m14p78s02q.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-02 16:49 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > Is it difficult to just export it via kobject and device layer? Well gregkh thought it wasn't a good idea last time I tried exploring that. > If > changing the default function is too much of a hassle (and I'm sure it > would be), just add an extended version which takes @tag. The current > implementation feels like it tried too hard to not add intermediate > interfaces and ended up shooting outside from the innermost layer. It tried for something that was simple to use and that worked. Also the way things work. I have to use all of the intermediate layers and their calls to various functions. So just passing a parameter through doesn't work to well. It looks to me like the clean solution is move kobject_tag into kobj_type, and have it call some higher level function. We also need to remove the maintenance disaster that is kobject_set_name from sysfs_rename_dir. And push it into kobject_rename instead. The error handling is harder in that case but otherwise we should be in good shape. >> On the other side I can't pass a tag through from the device layer to >> the kobject layer. It isn't a concept the kobject layer supports. > > I think it's best to make kobject layer support it. Assuming Greg will accept it when he sees reasonable patches. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-02 16:49 ` Eric W. Biederman @ 2008-07-03 0:15 ` Greg KH [not found] ` <m14p78s02q.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 1 sibling, 0 replies; 145+ messages in thread From: Greg KH @ 2008-07-03 0:15 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Benjamin Thery, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers On Wed, Jul 02, 2008 at 09:49:33AM -0700, Eric W. Biederman wrote: > Assuming Greg will accept it when he sees reasonable patches. I always accept "reasonable patches" :) thanks, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <m14p78s02q.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <m14p78s02q.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-07-03 3:18 ` Tejun Heo [not found] ` <486C4515.1070007-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-03 3:18 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Andrew Morton, Daniel Lezcano, Benjamin Thery Hello, Eric. Eric W. Biederman wrote: >> If >> changing the default function is too much of a hassle (and I'm sure it >> would be), just add an extended version which takes @tag. The current >> implementation feels like it tried too hard to not add intermediate >> interfaces and ended up shooting outside from the innermost layer. > > It tried for something that was simple to use and that worked. > > Also the way things work. I have to use all of the intermediate layers > and their calls to various functions. So just passing a parameter through > doesn't work to well. There is rather large possibility that I'm just being dumb here especially because I haven't reviewed the users of this facility, so all the comments I'm making are from the POV of interfaces of sysfs and the related layers. I think I've made my concerns clear by now. If you still think the callbacks are the best way to go, please try to enlighten me. I really don't wanna be stopping something which is better from ignorance. Just give me some concrete examples or point me to codes which show how and why the current interface is the best for the users and switching isn't a good idea. > It looks to me like the clean solution is move kobject_tag into > kobj_type, and have it call some higher level function. > > We also need to remove the maintenance disaster that is > kobject_set_name from sysfs_rename_dir. And push it into > kobject_rename instead. The error handling is harder in > that case but otherwise we should be in good shape. Heh... I personally think kobject layer as a whole should just be hidden under the cabinet of device driver model but I'm having difficult time convincing other people of it. Anyways, fully agree the interaction between kobject and sysfs is ugly at a lot of places. >>> On the other side I can't pass a tag through from the device layer to >>> the kobject layer. It isn't a concept the kobject layer supports. >> I think it's best to make kobject layer support it. > > Assuming Greg will accept it when he sees reasonable patches. Greg says he would. :-) Thanks a lot for your patience. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <486C4515.1070007-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <486C4515.1070007-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2008-07-03 5:11 ` Eric W. Biederman [not found] ` <m1hcb7o8lv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-03 5:11 UTC (permalink / raw) To: Tejun Heo Cc: Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Andrew Morton, Daniel Lezcano, Benjamin Thery Tejun Heo <htejun-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes: > There is rather large possibility that I'm just being dumb here > especially because I haven't reviewed the users of this facility, so all > the comments I'm making are from the POV of interfaces of sysfs and the > related layers. I think I've made my concerns clear by now. If you > still think the callbacks are the best way to go, please try to > enlighten me. I really don't wanna be stopping something which is > better from ignorance. Just give me some concrete examples or point me > to codes which show how and why the current interface is the best for > the users and switching isn't a good idea. Currently I think a callback on to get the tag from a kobject is the best way to go. That way we don't need to add a field to struct kobject (and don't need the associated redundancy), and we can lookup up the tag when we need it. I have been playing with the code and just about have it ready to go. I just need to refactor all of my changes into clean patches at this point, plus a bit of review and test. Ben & Daniel have given me a version of the previous patchset rebased unto the latest -mm so that should help for the unchanged parts. Introducing the sysfs_tag_type thing and pushing the functions to the edges helps. It especially cleans up the ugly mount/umount situation allowing us to handle that with generic code. Moving the kobject_tag into struct ktype works and looks roughly as clean as what happens with attributes. So I that seems reasonable, and doesn't result in a significant change in the users. The result of which means that I only have the helper function sysfs_creation_tag left in sysfs/dir.c Left in there are some of the nasties in dealing with symlinks. At this point I believe I have achieved a nice degree of simplifying the sysfs code in the current patches without really changing the users or making it more complex for them. I have not implemented ida tags, and I don't plan to. That is just unnecessary work right now. The users are simple and the meat of the logic would not change so it should be simple to add. >> It looks to me like the clean solution is move kobject_tag into >> kobj_type, and have it call some higher level function. >> >> We also need to remove the maintenance disaster that is >> kobject_set_name from sysfs_rename_dir. And push it into >> kobject_rename instead. The error handling is harder in >> that case but otherwise we should be in good shape. > > Heh... I personally think kobject layer as a whole should just be hidden > under the cabinet of device driver model but I'm having difficult time > convincing other people of it. Anyways, fully agree the interaction > between kobject and sysfs is ugly at a lot of places. I would be happy if we could remove all nonsense kobject that are there just for structural purposes but have no purpose otherwise. Things like kobjects for symlinks. The kobject layer doesn't seem to have a clear identity and purpose that I can see right now. > Thanks a lot for your patience. Welcome. The code reached a point a while ago where it didn't make sense to change it without review feedback. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <m1hcb7o8lv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <m1hcb7o8lv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-07-03 10:56 ` Daniel Lezcano [not found] ` <486CB051.5000507-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org> 0 siblings, 1 reply; 145+ messages in thread From: Daniel Lezcano @ 2008-07-03 10:56 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery Eric W. Biederman wrote: > Tejun Heo <htejun-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes: > >> There is rather large possibility that I'm just being dumb here >> especially because I haven't reviewed the users of this facility, so all >> the comments I'm making are from the POV of interfaces of sysfs and the >> related layers. I think I've made my concerns clear by now. If you >> still think the callbacks are the best way to go, please try to >> enlighten me. I really don't wanna be stopping something which is >> better from ignorance. Just give me some concrete examples or point me >> to codes which show how and why the current interface is the best for >> the users and switching isn't a good idea. > > Currently I think a callback on to get the tag from a kobject is the > best way to go. That way we don't need to add a field to struct > kobject (and don't need the associated redundancy), and we can lookup > up the tag when we need it. The kobject events are sent through a netlink message which is not currently per network namespace. Shouldn't be useful to have a way to retrieve from the kobject the network namespace or the uevent socket associated with it ? IMHO having idr in the kobject + netns pointer associated may help to handle the sysfs isolation and makes the uevent per namespace trivial, no ? > I have been playing with the code and just about have it ready > to go. I just need to refactor all of my changes into clean > patches at this point, plus a bit of review and test. Ben & Daniel > have given me a version of the previous patchset rebased unto the > latest -mm so that should help for the unchanged parts. > > Introducing the sysfs_tag_type thing and pushing the functions to > the edges helps. It especially cleans up the ugly mount/umount > situation allowing us to handle that with generic code. > > Moving the kobject_tag into struct ktype works and looks roughly > as clean as what happens with attributes. So I that seems reasonable, > and doesn't result in a significant change in the users. > > The result of which means that I only have the helper function sysfs_creation_tag > left in sysfs/dir.c Left in there are some of the nasties in dealing with symlinks. > > At this point I believe I have achieved a nice degree of simplifying the sysfs > code in the current patches without really changing the users or > making it more complex for them. > > I have not implemented ida tags, and I don't plan to. That is just > unnecessary work right now. The users are simple and the meat of the > logic would not change so it should be simple to add. > >>> It looks to me like the clean solution is move kobject_tag into >>> kobj_type, and have it call some higher level function. >>> >>> We also need to remove the maintenance disaster that is >>> kobject_set_name from sysfs_rename_dir. And push it into >>> kobject_rename instead. The error handling is harder in >>> that case but otherwise we should be in good shape. >> Heh... I personally think kobject layer as a whole should just be hidden >> under the cabinet of device driver model but I'm having difficult time >> convincing other people of it. Anyways, fully agree the interaction >> between kobject and sysfs is ugly at a lot of places. > > I would be happy if we could remove all nonsense kobject that are there just > for structural purposes but have no purpose otherwise. Things like kobjects > for symlinks. The kobject layer doesn't seem to have a clear identity > and purpose that I can see right now. > >> Thanks a lot for your patience. > > Welcome. The code reached a point a while ago where it didn't make sense > to change it without review feedback. > > Eric > > _______________________________________________ > Containers mailing list > Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org > https://lists.linux-foundation.org/mailman/listinfo/containers > -- Sauf indication contraire ci-dessus: Compagnie IBM France Siège Social : Tour Descartes, 2, avenue Gambetta, La Défense 5, 92400 Courbevoie RCS Nanterre 552 118 465 Forme Sociale : S.A.S. Capital Social : 542.737.118 ? SIREN/SIRET : 552 118 465 02430 ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <486CB051.5000507-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <486CB051.5000507-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org> @ 2008-07-03 12:27 ` Eric W. Biederman [not found] ` <m14p77m9uy.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 2008-07-03 15:58 ` Tejun Heo 0 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-03 12:27 UTC (permalink / raw) To: Daniel Lezcano Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org> writes: > The kobject events are sent through a netlink message which is not currently per > network namespace. Shouldn't be useful to have a way to retrieve from the > kobject the network namespace or the uevent socket associated with it ? IMHO > having idr in the kobject + netns pointer associated may help to handle the > sysfs isolation and makes the uevent per namespace trivial, no ? Grumble. I have been conveniently been forgetting about that socket. Similarly we have the user mode helpers to deal with. For this conversation there is a simple answer. All of that is in the kobject layer, and works even when you compile sysfs out of your kernel. Therefore it is a separate problem. And sysfs idr tags have nothing to do with it. It is most definitely something we need to come back to. I bet there are some interesting interactions when you have multiple network devices with the same name generating events. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <m14p77m9uy.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>]
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <m14p77m9uy.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-07-03 12:37 ` Benjamin Thery 2008-07-03 19:57 ` Eric W. Biederman 2008-07-03 12:55 ` Daniel Lezcano 1 sibling, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-07-03 12:37 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Daniel Lezcano, Andrew Morton Eric W. Biederman wrote: > Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org> writes: > >> The kobject events are sent through a netlink message which is not currently per >> network namespace. Shouldn't be useful to have a way to retrieve from the >> kobject the network namespace or the uevent socket associated with it ? IMHO >> having idr in the kobject + netns pointer associated may help to handle the >> sysfs isolation and makes the uevent per namespace trivial, no ? > > Grumble. I have been conveniently been forgetting about that socket. > Similarly we have the user mode helpers to deal with. > > For this conversation there is a simple answer. All of that is in the > kobject layer, and works even when you compile sysfs out of your kernel. > Therefore it is a separate problem. And sysfs idr tags have nothing > to do with it. > It is most definitely something we need to come back to. I bet there > are some interesting interactions when you have multiple network devices > with the same name generating events. Indeed, we observed some fun things with one distro (which defines some particular udev rules) when a device called eth0 in a namespace comes back to init net :) Benjamin > > Eric > > > > > > > > > > -- B e n j a m i n T h e r y - BULL/DT/Open Software R&D http://www.bull.com ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-03 12:37 ` Benjamin Thery @ 2008-07-03 19:57 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-03 19:57 UTC (permalink / raw) To: Benjamin Thery Cc: Daniel Lezcano, Tejun Heo, Greg Kroah-Hartman, linux-kernel, Al Viro, Linux Containers, Andrew Morton Benjamin Thery <benjamin.thery@bull.net> writes: > Indeed, we observed some fun things with one distro (which defines some > particular udev rules) when a device called eth0 in a namespace comes back to > init net :) Speaking of. Don't let me forget but I have a patch I need to send out that deletes pseudo devices instead of sending them back to eth0. We can't do that for real hardware obviously but for things like veth and macvlan devices it greatly simplifies the cleanup. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. [not found] ` <m14p77m9uy.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 2008-07-03 12:37 ` Benjamin Thery @ 2008-07-03 12:55 ` Daniel Lezcano 1 sibling, 0 replies; 145+ messages in thread From: Daniel Lezcano @ 2008-07-03 12:55 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery Eric W. Biederman wrote: > Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org> writes: > >> The kobject events are sent through a netlink message which is not currently per >> network namespace. Shouldn't be useful to have a way to retrieve from the >> kobject the network namespace or the uevent socket associated with it ? IMHO >> having idr in the kobject + netns pointer associated may help to handle the >> sysfs isolation and makes the uevent per namespace trivial, no ? > > Grumble. I have been conveniently been forgetting about that socket. > Similarly we have the user mode helpers to deal with. > > For this conversation there is a simple answer. All of that is in the > kobject layer, and works even when you compile sysfs out of your kernel. > Therefore it is a separate problem. And sysfs idr tags have nothing > to do with it. Ah Ok, I am not really familiar with kobject/sysfs so I thought there was a proposition to store the id in the kobject instead of using the tag callbacks, so I figured, perhaps, the idr could have been used in the kobject layer and the sysfs being built upon that. > It is most definitely something we need to come back to. I bet there > are some interesting interactions when you have multiple network devices > with the same name generating events. Yes as mentionned Benjamin, we have the eth0 in the init_net which is shut down when a network namespace with a netdev with the same name exits. There is a udev rule which ifdown eth0 :) ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-03 12:27 ` Eric W. Biederman [not found] ` <m14p77m9uy.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-07-03 15:58 ` Tejun Heo 2008-07-03 18:29 ` Daniel Lezcano ` (2 more replies) 1 sibling, 3 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-03 15:58 UTC (permalink / raw) To: Eric W. Biederman Cc: Daniel Lezcano, Greg Kroah-Hartman, linux-kernel, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery Hello, Eric W. Biederman wrote: > Daniel Lezcano <dlezcano@fr.ibm.com> writes: > >> The kobject events are sent through a netlink message which is not currently per >> network namespace. Shouldn't be useful to have a way to retrieve from the >> kobject the network namespace or the uevent socket associated with it ? IMHO >> having idr in the kobject + netns pointer associated may help to handle the >> sysfs isolation and makes the uevent per namespace trivial, no ? > > Grumble. I have been conveniently been forgetting about that socket. > Similarly we have the user mode helpers to deal with. > > For this conversation there is a simple answer. All of that is in the > kobject layer, and works even when you compile sysfs out of your kernel. > Therefore it is a separate problem. And sysfs idr tags have nothing > to do with it. > > It is most definitely something we need to come back to. I bet there > are some interesting interactions when you have multiple network devices > with the same name generating events. Related delta: I've been thinking that uevents should be part of sysfs not kobject as that's what the userland is gonna associate the event with. Would that solve the problem you're thinking about? Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-03 15:58 ` Tejun Heo @ 2008-07-03 18:29 ` Daniel Lezcano 2008-07-03 20:08 ` Eric W. Biederman 2008-07-04 0:48 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman 2 siblings, 0 replies; 145+ messages in thread From: Daniel Lezcano @ 2008-07-03 18:29 UTC (permalink / raw) To: Tejun Heo Cc: Eric W. Biederman, Greg Kroah-Hartman, linux-kernel, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery Tejun Heo wrote: > Hello, > > Eric W. Biederman wrote: >> Daniel Lezcano <dlezcano@fr.ibm.com> writes: >> >>> The kobject events are sent through a netlink message which is not currently per >>> network namespace. Shouldn't be useful to have a way to retrieve from the >>> kobject the network namespace or the uevent socket associated with it ? IMHO >>> having idr in the kobject + netns pointer associated may help to handle the >>> sysfs isolation and makes the uevent per namespace trivial, no ? >> Grumble. I have been conveniently been forgetting about that socket. >> Similarly we have the user mode helpers to deal with. >> >> For this conversation there is a simple answer. All of that is in the >> kobject layer, and works even when you compile sysfs out of your kernel. >> Therefore it is a separate problem. And sysfs idr tags have nothing >> to do with it. >> >> It is most definitely something we need to come back to. I bet there >> are some interesting interactions when you have multiple network devices >> with the same name generating events. > > Related delta: I've been thinking that uevents should be part of sysfs > not kobject as that's what the userland is gonna associate the event > with. Would that solve the problem you're thinking about? uevents can work with the network namespaces being compiled in and the sysfs compiled out. AFAICS, uevents will be unable to handle multiple network namespaces if it is tied with sysfs, no ? ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/11] sysfs: Implement sysfs tagged directory support. 2008-07-03 15:58 ` Tejun Heo 2008-07-03 18:29 ` Daniel Lezcano @ 2008-07-03 20:08 ` Eric W. Biederman 2008-07-04 0:48 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman 2 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-03 20:08 UTC (permalink / raw) To: Tejun Heo Cc: Daniel Lezcano, Greg Kroah-Hartman, linux-kernel, Al Viro, Linux Containers, Andrew Morton, Benjamin Thery Tejun Heo <htejun@gmail.com> writes: > Related delta: I've been thinking that uevents should be part of sysfs > not kobject as that's what the userland is gonna associate the event > with. Would that solve the problem you're thinking about? The good news is that uevent_sock is currently restricted to just the initial network namespace (so the functionality completely disappears in the other namespaces), and that it is broadcast only. So it should be possible to look at who the client is and by some magic criterian decide if it should receive the broadcast message. The call to the user mode helper is trickier. How do we setup the proper user space context. None of this is fundamentally hard just different work, for a different day. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 00/15] sysfs support for namespaces 2008-07-03 15:58 ` Tejun Heo 2008-07-03 18:29 ` Daniel Lezcano 2008-07-03 20:08 ` Eric W. Biederman @ 2008-07-04 0:48 ` Eric W. Biederman 2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman ` (2 more replies) 2 siblings, 3 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 0:48 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev When multiple namespaces are in use we can get multiple kernel objects with the same name which is currently impossible to represent in sysfs. In particular directories like /sys/class/net and /sys/kernel/uids have significant problems. Not wanting to change the user space interface and wanting to have a simple implementation where all objects are in the kobject and sysfs trees. The decision has been made to tag objects with the namespace they live in, and in a particular mount of sysfs only display objects with the tag that corresponds to the namespaces in effect when sysfs was mounted. After the last round of reviews the mount/umount logic is significantly cleaned up and easier to maintain. From a 10,000 foot view the code and the way it functions has remained the same since we settled on tagged directories a year or so ago. I intend any future cleanups to be as incremental patches on top of this existing set. Lack of these patches are keeping the generally complete network namespace work in 2.6.26 from being used and tested more heavily. Can we please get the patches merged? These patches are based off of 2.6.26-rc8 + the -gregkh tree from last night. Hopefully that means they apply -mm -gregkh and -linux-next. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS 2008-07-04 0:48 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman @ 2008-07-04 1:05 ` Eric W. Biederman 2008-07-04 1:07 ` [PATCH 02/15] sysfs: Support for preventing unmounts Eric W. Biederman ` (2 more replies) 2008-07-04 1:27 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman 2008-07-06 4:42 ` Eric W. Biederman 2 siblings, 3 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:05 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev It finally dawned on me what the clean fix to sysfs_rename_dir calling kobject_set_name is. Move the work into kobject_rename where it belongs. The callers serialize us anyway so this is safe. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/dir.c | 6 +----- include/linux/sysfs.h | 4 +--- lib/kobject.c | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 8c0e4b9..146b86a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -799,16 +799,12 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) if (!new_dentry) goto out_unlock; - /* rename kobject and sysfs_dirent */ + /* rename sysfs_dirent */ error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); if (!new_name) goto out_unlock; - error = kobject_set_name(kobj, "%s", new_name); - if (error) - goto out_unlock; - dup_name = sd->s_name; sd->s_name = new_name; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 84d92bb..f7e43ed 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -20,8 +20,6 @@ struct kobject; struct module; -extern int kobject_set_name(struct kobject *kobj, const char *name, ...) - __attribute__((format(printf, 2, 3))); /* FIXME * The *owner field is no longer used, but leave around * until the tree gets cleaned up fully. @@ -140,7 +138,7 @@ static inline void sysfs_remove_dir(struct kobject *kobj) static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name) { - return kobject_set_name(kobj, "%s", new_name); + return 0; } static inline int sysfs_move_dir(struct kobject *kobj, diff --git a/lib/kobject.c b/lib/kobject.c index 829b839..49b3bc4 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -451,6 +451,7 @@ int kobject_rename(struct kobject *kobj, const char *new_name) { int error = 0; const char *devpath = NULL; + const char *dup_name = NULL, *name; char *devpath_string = NULL; char *envp[2]; @@ -474,15 +475,27 @@ int kobject_rename(struct kobject *kobj, const char *new_name) envp[0] = devpath_string; envp[1] = NULL; + name = dup_name = kstrdup(new_name, GFP_KERNEL); + if (!name) { + error = -ENOMEM; + goto out; + } + error = sysfs_rename_dir(kobj, new_name); + if (error) + goto out; + + /* Install the new kobject name */ + dup_name = kobj->name; + kobj->name = name; /* This function is mostly/only used for network interface. * Some hotplug package track interfaces by their name and * therefore want to know when the name is changed by the user. */ - if (!error) - kobject_uevent_env(kobj, KOBJ_MOVE, envp); + kobject_uevent_env(kobj, KOBJ_MOVE, envp); out: + kfree(dup_name); kfree(devpath_string); kfree(devpath); kobject_put(kobj); -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 02/15] sysfs: Support for preventing unmounts. 2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman @ 2008-07-04 1:07 ` Eric W. Biederman 2008-07-04 1:08 ` [PATCH 03/15] sysfs: sysfs_get_dentry add a sb parameter Eric W. Biederman [not found] ` <m1prpuihjb.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 2008-07-04 6:33 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Tejun Heo 2008-08-20 1:48 ` patch kobject-cleanup-kobject_rename-and-config_sysfs.patch added to gregkh-2.6 tree gregkh 2 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:07 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev To support mounting multiple instances of sysfs occassionally I need to walk through all of the currently present sysfs super blocks. To allow this iteration this patch adds sysfs_grab_supers and sysfs_release_supers. While a piece of code is in a section surrounded by these no more sysfs super blocks will be either created or destroyed. So the fundamentals. - The data in sysfs fundamentally changes behind the back of the VFS and we need to keep the VFS in sync. Essentially this is the distributed filesystem problem. - In particular for sysfs_rename and sysfs_move_dir we need to support finding the dcache entries and calling d_move. So that the dcache does not get into an inconsistent state. Timeouts and invalidates like NFS uses are to be avoided if at all possible. - Coming through the vfs we are guaranteed that the filesystem will not be unmounted while we have a reference on a dentry, and with multiple mounts we do not get that guarantee. Therefore to get that guarantee for all of the superblocks we need the blunt instrument. - Since mount/unmount are rare blocking them is no big deal. I believe any distributed filesystem that is together enough to tell us about renames (so we can update the dcache) instead of doing the NFS timeout will need the ability to block mount/unmount while it is executing d_move. Currently sysfs does not need to block mounts only because we perform an internal mount and then never unmount sysfs. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> --- fs/sysfs/mount.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++----- fs/sysfs/sysfs.h | 10 +++++++ 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 9f328d2..c812cc4 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -41,47 +41,110 @@ struct sysfs_dirent sysfs_root = { static int sysfs_fill_super(struct super_block *sb, void *data, int silent) { - struct inode *inode; - struct dentry *root; + struct sysfs_super_info *info = NULL; + struct inode *inode = NULL; + struct dentry *root = NULL; + int error; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = SYSFS_MAGIC; sb->s_op = &sysfs_ops; sb->s_time_gran = 1; - sysfs_sb = sb; + if (!sysfs_sb) + sysfs_sb = sb; + + error = -ENOMEM; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out_err; /* get root inode, initialize and unlock it */ + error = -ENOMEM; inode = sysfs_get_inode(&sysfs_root); if (!inode) { pr_debug("sysfs: could not get root inode\n"); - return -ENOMEM; + goto out_err; } /* instantiate and link root dentry */ + error = -ENOMEM; root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); - iput(inode); - return -ENOMEM; + goto out_err; } root->d_fsdata = &sysfs_root; sb->s_root = root; + sb->s_fs_info = info; return 0; + +out_err: + dput(root); + iput(inode); + kfree(info); + if (sysfs_sb == sb) + sysfs_sb = NULL; + return error; } static int sysfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + int rc; + mutex_lock(&sysfs_rename_mutex); + rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + mutex_unlock(&sysfs_rename_mutex); + return rc; } -static struct file_system_type sysfs_fs_type = { +struct file_system_type sysfs_fs_type = { .name = "sysfs", .get_sb = sysfs_get_sb, .kill_sb = kill_anon_super, }; +void sysfs_grab_supers(void) +{ + /* must hold sysfs_rename_mutex */ + struct super_block *sb; + /* Loop until I have taken s_umount on all sysfs superblocks */ +restart: + spin_lock(&sb_lock); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + if (sysfs_info(sb)->grabbed) + continue; + /* Wait for unmount activity to complete. */ + if (sb->s_count < S_BIAS) { + sb->s_count += 1; + spin_unlock(&sb_lock); + down_read(&sb->s_umount); + drop_super(sb); + goto restart; + } + atomic_inc(&sb->s_active); + sysfs_info(sb)->grabbed = 1; + } + spin_unlock(&sb_lock); +} + +void sysfs_release_supers(void) +{ + /* must hold sysfs_rename_mutex */ + struct super_block *sb; +restart: + spin_lock(&sb_lock); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + if (!sysfs_info(sb)->grabbed) + continue; + sysfs_info(sb)->grabbed = 0; + spin_unlock(&sb_lock); + deactivate_super(sb); + goto restart; + } + spin_unlock(&sb_lock); +} + int __init sysfs_init(void) { int err = -ENOMEM; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 2915959..0fdc3de 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -85,6 +85,12 @@ struct sysfs_addrm_cxt { int cnt; }; +struct sysfs_super_info { + int grabbed; +}; + +#define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) + /* * mount.c */ @@ -92,6 +98,10 @@ extern struct sysfs_dirent sysfs_root; extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; extern struct vfsmount *sysfs_mount; +extern struct file_system_type sysfs_fs_type; + +void sysfs_grab_supers(void); +void sysfs_release_supers(void); /* * dir.c -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 03/15] sysfs: sysfs_get_dentry add a sb parameter 2008-07-04 1:07 ` [PATCH 02/15] sysfs: Support for preventing unmounts Eric W. Biederman @ 2008-07-04 1:08 ` Eric W. Biederman 2008-07-04 1:09 ` [PATCH 04/15] sysfs: Implement __sysfs_get_dentry Eric W. Biederman 2008-08-20 2:16 ` patch sysfs-sysfs_get_dentry-add-a-sb-parameter.patch " gregkh [not found] ` <m1prpuihjb.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev In preparation for multiple mounts of sysfs add a superblock parameter to sysfs_get_dentry. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> --- fs/sysfs/dir.c | 12 +++++++----- fs/sysfs/file.c | 2 +- fs/sysfs/sysfs.h | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 146b86a..69c40ed 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -85,6 +85,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) /** * sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sb: superblock of the dentry to return * @sd: sysfs_dirent of interest * * Get dentry for @sd. Dentry is looked up if currently not @@ -97,9 +98,10 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) * RETURNS: * Pointer to found dentry on success, ERR_PTR() value on error. */ -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) +struct dentry *sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd) { - struct dentry *dentry = dget(sysfs_sb->s_root); + struct dentry *dentry = dget(sb->s_root); while (dentry->d_fsdata != sd) { struct sysfs_dirent *cur; @@ -777,7 +779,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) goto out; /* nothing to rename */ /* get the original dentry */ - old_dentry = sysfs_get_dentry(sd); + old_dentry = sysfs_get_dentry(sysfs_sb, sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); old_dentry = NULL; @@ -841,7 +843,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) goto out; /* nothing to move */ /* get dentries */ - old_dentry = sysfs_get_dentry(sd); + old_dentry = sysfs_get_dentry(sysfs_sb, sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); old_dentry = NULL; @@ -849,7 +851,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) } old_parent = old_dentry->d_parent; - new_parent = sysfs_get_dentry(new_parent_sd); + new_parent = sysfs_get_dentry(sysfs_sb, new_parent_sd); if (IS_ERR(new_parent)) { error = PTR_ERR(new_parent); new_parent = NULL; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 15ff679..cb5dd3f 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -585,7 +585,7 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) goto out; mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(victim_sd); + victim = sysfs_get_dentry(sysfs_sb, victim_sd); mutex_unlock(&sysfs_rename_mutex); if (IS_ERR(victim)) { rc = PTR_ERR(victim); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 0fdc3de..b1bdc6e 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -113,7 +113,8 @@ extern spinlock_t sysfs_assoc_lock; extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); +struct dentry *sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd); struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); void sysfs_put_active_two(struct sysfs_dirent *sd); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 04/15] sysfs: Implement __sysfs_get_dentry 2008-07-04 1:08 ` [PATCH 03/15] sysfs: sysfs_get_dentry add a sb parameter Eric W. Biederman @ 2008-07-04 1:09 ` Eric W. Biederman 2008-07-04 1:10 ` [PATCH 05/15] sysfs: Rename Support multiple superblocks Eric W. Biederman 2008-08-20 2:16 ` patch sysfs-implement-__sysfs_get_dentry.patch " gregkh 2008-08-20 2:16 ` patch sysfs-sysfs_get_dentry-add-a-sb-parameter.patch " gregkh 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:09 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev This function is similar but much simpler to sysfs_get_dentry returns a sysfs dentry if one curently exists. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> --- fs/sysfs/dir.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 69c40ed..df9934a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -764,6 +764,45 @@ void sysfs_remove_dir(struct kobject * kobj) __sysfs_remove_dir(sd); } +/** + * __sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sb: superblock of the dentry to return + * @sd: sysfs_dirent of interest + * + * Get dentry for @sd. Only return a dentry if one currently + * exists. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * Pointer to found dentry on success, NULL on failure. + */ +static struct dentry *__sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd) +{ + struct inode *inode; + struct dentry *dentry = NULL; + + inode = ilookup5_nowait(sysfs_sb, sd->s_ino, sysfs_ilookup_test, sd); + if (inode && !(inode->i_state & I_NEW)) { + struct dentry *alias; + spin_lock(&dcache_lock); + list_for_each_entry(alias, &inode->i_dentry, d_alias) { + if (!IS_ROOT(alias) && d_unhashed(alias)) + continue; + if (alias->d_sb != sb) + continue; + dentry = alias; + dget_locked(dentry); + break; + } + spin_unlock(&dcache_lock); + } + iput(inode); + return dentry; +} + int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 05/15] sysfs: Rename Support multiple superblocks 2008-07-04 1:09 ` [PATCH 04/15] sysfs: Implement __sysfs_get_dentry Eric W. Biederman @ 2008-07-04 1:10 ` Eric W. Biederman 2008-07-04 1:11 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Eric W. Biederman 2008-08-20 2:16 ` patch sysfs-rename-support-multiple-superblocks.patch " gregkh 2008-08-20 2:16 ` patch sysfs-implement-__sysfs_get_dentry.patch " gregkh 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:10 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev This patch modifies the sysfs_rename_dir and sysfs_move_dir routines to support multiple sysfs dentry tries rooted in different sysfs superblocks. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> --- fs/sysfs/dir.c | 193 +++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 136 insertions(+), 57 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index df9934a..b2d92ea 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -803,43 +803,113 @@ static struct dentry *__sysfs_get_dentry(struct super_block *sb, return dentry; } +struct sysfs_rename_struct { + struct list_head list; + struct dentry *old_dentry; + struct dentry *new_dentry; + struct dentry *old_parent; + struct dentry *new_parent; +}; + +static void post_rename(struct list_head *head) +{ + struct sysfs_rename_struct *srs; + while (!list_empty(head)) { + srs = list_entry(head->next, struct sysfs_rename_struct, list); + dput(srs->old_dentry); + dput(srs->new_dentry); + dput(srs->old_parent); + dput(srs->new_parent); + list_del(&srs->list); + kfree(srs); + } +} + +static int prep_rename(struct list_head *head, + struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd, + const char *name) +{ + struct sysfs_rename_struct *srs; + struct super_block *sb; + struct dentry *dentry; + int error; + + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + dentry = sysfs_get_dentry(sb, sd); + if (dentry == ERR_PTR(-EXDEV)) + continue; + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto err_out; + } + + srs = kzalloc(sizeof(*srs), GFP_KERNEL); + if (!srs) { + error = -ENOMEM; + dput(dentry); + goto err_out; + } + + INIT_LIST_HEAD(&srs->list); + list_add(head, &srs->list); + srs->old_dentry = dentry; + srs->old_parent = dget(dentry->d_parent); + + dentry = sysfs_get_dentry(sb, new_parent_sd); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto err_out; + } + srs->new_parent = dentry; + + error = -ENOMEM; + dentry = d_alloc_name(srs->new_parent, name); + if (!dentry) + goto err_out; + srs->new_dentry = dentry; + } + return 0; + +err_out: + post_rename(head); + return error; +} + int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; - struct dentry *parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct list_head todo; + struct sysfs_rename_struct *srs; + struct inode *parent_inode = NULL; const char *dup_name = NULL; int error; + INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); error = 0; if (strcmp(sd->s_name, new_name) == 0) goto out; /* nothing to rename */ - /* get the original dentry */ - old_dentry = sysfs_get_dentry(sysfs_sb, sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } + sysfs_grab_supers(); + error = prep_rename(&todo, sd, sd->s_parent, new_name); + if (error) + goto out_release; - parent = old_dentry->d_parent; + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + parent_inode = sysfs_get_inode(sd->s_parent); + mutex_unlock(&sysfs_mutex); + if (!parent_inode) + goto out_release; - /* lock parent and get dentry for new name */ - mutex_lock(&parent->d_inode->i_mutex); + mutex_lock(&parent_inode->i_mutex); mutex_lock(&sysfs_mutex); error = -EEXIST; if (sysfs_find_dirent(sd->s_parent, new_name)) goto out_unlock; - error = -ENOMEM; - new_dentry = d_alloc_name(parent, new_name); - if (!new_dentry) - goto out_unlock; - /* rename sysfs_dirent */ error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); @@ -850,17 +920,21 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) sd->s_name = new_name; /* rename */ - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + list_for_each_entry(srs, &todo, list) { + d_add(srs->new_dentry, NULL); + d_move(srs->old_dentry, srs->new_dentry); + } error = 0; - out_unlock: +out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&parent->d_inode->i_mutex); + mutex_unlock(&parent_inode->i_mutex); kfree(dup_name); - dput(old_dentry); - dput(new_dentry); - out: +out_release: + iput(parent_inode); + post_rename(&todo); + sysfs_release_supers(); +out: mutex_unlock(&sysfs_rename_mutex); return error; } @@ -869,10 +943,12 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) { struct sysfs_dirent *sd = kobj->sd; struct sysfs_dirent *new_parent_sd; - struct dentry *old_parent, *new_parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct list_head todo; + struct sysfs_rename_struct *srs; + struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; int error; + INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; @@ -881,26 +957,29 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) if (sd->s_parent == new_parent_sd) goto out; /* nothing to move */ - /* get dentries */ - old_dentry = sysfs_get_dentry(sysfs_sb, sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } - old_parent = old_dentry->d_parent; + sysfs_grab_supers(); + error = prep_rename(&todo, sd, new_parent_sd, sd->s_name); + if (error) + goto out_release; - new_parent = sysfs_get_dentry(sysfs_sb, new_parent_sd); - if (IS_ERR(new_parent)) { - error = PTR_ERR(new_parent); - new_parent = NULL; - goto out; - } + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + old_parent_inode = sysfs_get_inode(sd->s_parent); + mutex_unlock(&sysfs_mutex); + if (!old_parent_inode) + goto out_release; + + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + new_parent_inode = sysfs_get_inode(new_parent_sd); + mutex_unlock(&sysfs_mutex); + if (!new_parent_inode) + goto out_release; again: - mutex_lock(&old_parent->d_inode->i_mutex); - if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { - mutex_unlock(&old_parent->d_inode->i_mutex); + mutex_lock(&old_parent_inode->i_mutex); + if (!mutex_trylock(&new_parent_inode->i_mutex)) { + mutex_unlock(&old_parent_inode->i_mutex); goto again; } mutex_lock(&sysfs_mutex); @@ -909,14 +988,11 @@ again: if (sysfs_find_dirent(new_parent_sd, sd->s_name)) goto out_unlock; - error = -ENOMEM; - new_dentry = d_alloc_name(new_parent, sd->s_name); - if (!new_dentry) - goto out_unlock; - error = 0; - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + list_for_each_entry(srs, &todo, list) { + d_add(srs->new_dentry, NULL); + d_move(srs->old_dentry, srs->new_dentry); + } /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); @@ -925,14 +1001,17 @@ again: sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); - out_unlock: +out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&new_parent->d_inode->i_mutex); - mutex_unlock(&old_parent->d_inode->i_mutex); - out: - dput(new_parent); - dput(old_dentry); - dput(new_dentry); + mutex_unlock(&new_parent_inode->i_mutex); + mutex_unlock(&old_parent_inode->i_mutex); + +out_release: + iput(new_parent_inode); + iput(old_parent_inode); + post_rename(&todo); + sysfs_release_supers(); +out: mutex_unlock(&sysfs_rename_mutex); return error; } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod 2008-07-04 1:10 ` [PATCH 05/15] sysfs: Rename Support multiple superblocks Eric W. Biederman @ 2008-07-04 1:11 ` Eric W. Biederman 2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman ` (2 more replies) 2008-08-20 2:16 ` patch sysfs-rename-support-multiple-superblocks.patch " gregkh 1 sibling, 3 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:11 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Currently sysfs_chmod calls sys_setattr which in turn calls inode_change_ok which checks to see if it is ok for the current user space process to change tha attributes. Since sysfs_chmod_file has only kernel mode clients denying them permission if user space is the problem is completely inappropriate. Therefore factor out sysfs_sd_setattr which does not call inode_change_ok and modify sysfs_chmod_file to call it. In addition setting victim_sd->s_mode explicitly in sysfs_chmod_file is redundant so remove that as well. Thanks to Tejun Heo <htejun@gmail.com>, and Daniel Lezcano <dlezcano@fr.ibm.com> for working on this and spotting this case. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/file.c | 5 +---- fs/sysfs/inode.c | 23 ++++++++++++++++------- fs/sysfs/sysfs.h | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index cb5dd3f..1304b3a 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -600,13 +600,10 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_ctime = current_fs_time(inode->i_sb); - rc = sysfs_setattr(victim, &newattrs); + rc = sysfs_sd_setattr(victim_sd, inode, &newattrs); if (rc == 0) { fsnotify_change(victim, newattrs.ia_valid); - mutex_lock(&sysfs_mutex); - victim_sd->s_mode = newattrs.ia_mode; - mutex_unlock(&sysfs_mutex); } mutex_unlock(&inode->i_mutex); diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index eb53c63..80f8fd4 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -42,10 +42,9 @@ int __init sysfs_inode_init(void) return bdi_init(&sysfs_backing_dev_info); } -int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, + struct iattr * iattr) { - struct inode * inode = dentry->d_inode; - struct sysfs_dirent * sd = dentry->d_fsdata; struct iattr * sd_iattr; unsigned int ia_valid = iattr->ia_valid; int error; @@ -55,10 +54,6 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) sd_iattr = sd->s_iattr; - error = inode_change_ok(inode, iattr); - if (error) - return error; - iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ error = inode_setattr(inode, iattr); @@ -104,6 +99,20 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) return error; } +int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) +{ + struct inode * inode = dentry->d_inode; + struct sysfs_dirent * sd = dentry->d_fsdata; + int error; + + error = inode_change_ok(inode, iattr); + if (error) + return error; + + return sysfs_sd_setattr(sd, inode, iattr); +} + + static inline void set_default_inode_attr(struct inode * inode, mode_t mode) { inode->i_mode = mode; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index b1bdc6e..5ee5d0a 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -154,6 +154,7 @@ static inline void sysfs_put(struct sysfs_dirent *sd) * inode.c */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_inode_init(void); -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks 2008-07-04 1:11 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Eric W. Biederman @ 2008-07-04 1:13 ` Eric W. Biederman 2008-07-04 1:14 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Eric W. Biederman ` (2 more replies) 2008-07-04 6:40 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Tejun Heo 2008-08-20 2:16 ` patch sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch added to gregkh-2.6 tree gregkh 2 siblings, 3 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:13 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Teach sysfs_chmod_file how to handle multiple sysfs superblocks. Since we only have one inode per sd the only thing we have to deal with is multiple dentries for sending fs notifications. This might dup the inode notifications oh well. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/file.c | 39 +++++++++++++++++++++++++-------------- 1 files changed, 25 insertions(+), 14 deletions(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1304b3a..5955ae9 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -574,8 +574,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct sysfs_dirent *victim_sd = NULL; - struct dentry *victim = NULL; - struct inode * inode; + struct super_block *sb; + struct inode * inode = NULL; struct iattr newattrs; int rc; @@ -584,31 +584,42 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) if (!victim_sd) goto out; - mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(sysfs_sb, victim_sd); - mutex_unlock(&sysfs_rename_mutex); - if (IS_ERR(victim)) { - rc = PTR_ERR(victim); - victim = NULL; - goto out; - } - - inode = victim->d_inode; + rc = -ENOENT; + mutex_lock(&sysfs_mutex); + inode = sysfs_get_inode(victim_sd); + mutex_unlock(&sysfs_mutex); + if (!inode) + goto out; + mutex_lock(&sysfs_rename_mutex); + sysfs_grab_supers(); mutex_lock(&inode->i_mutex); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_ctime = current_fs_time(inode->i_sb); rc = sysfs_sd_setattr(victim_sd, inode, &newattrs); + if (rc) + goto out_unlock; + + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + /* Ignore it when the dentry does not exist on the + * target superblock. + */ + struct dentry * victim = sysfs_get_dentry(sb, victim_sd); + if (IS_ERR(victim)) + continue; - if (rc == 0) { fsnotify_change(victim, newattrs.ia_valid); + dput(victim); } + out_unlock: mutex_unlock(&inode->i_mutex); + sysfs_release_supers(); + mutex_unlock(&sysfs_rename_mutex); out: - dput(victim); + iput(inode); sysfs_put(victim_sd); return rc; } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 08/15] sysfs: Make sysfs_mount static once again. 2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman @ 2008-07-04 1:14 ` Eric W. Biederman 2008-07-04 1:16 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Eric W. Biederman 2008-07-04 6:44 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Tejun Heo 2008-07-04 6:44 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Tejun Heo 2008-08-20 2:16 ` patch sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch added to gregkh-2.6 tree gregkh 2 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:14 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Accessing the internal sysfs_mount is error prone in the context of multiple super blocks, and nothing needs it. Not even the sysfs crash debugging patch (although it did in an earlier version). Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/mount.c | 2 +- fs/sysfs/sysfs.h | 1 - 2 files changed, 1 insertions(+), 2 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index c812cc4..99974f0 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -22,7 +22,7 @@ /* Random magic number */ #define SYSFS_MAGIC 0x62656572 -struct vfsmount *sysfs_mount; +static struct vfsmount *sysfs_mount; struct super_block * sysfs_sb = NULL; struct kmem_cache *sysfs_dir_cachep; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 5ee5d0a..33b3c73 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -97,7 +97,6 @@ struct sysfs_super_info { extern struct sysfs_dirent sysfs_root; extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; -extern struct vfsmount *sysfs_mount; extern struct file_system_type sysfs_fs_type; void sysfs_grab_supers(void); -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 09/15] sysfs: Implement sysfs tagged directory support. 2008-07-04 1:14 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Eric W. Biederman @ 2008-07-04 1:16 ` Eric W. Biederman 2008-07-04 1:17 ` [PATCH 10/15] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman 2008-08-20 2:17 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Greg KH 2008-07-04 6:44 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Tejun Heo 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:16 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev The problem. When implementing a network namespace I need to be able to have multiple network devices with the same name. Currently this is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and potentially a few other directories of the form /sys/ ... /net/*. What this patch does is to add an additional tag field to the sysfs dirent structure. For directories that should show different contents depending on the context such as /sys/class/net/, and /sys/devices/virtual/net/ this tag field is used to specify the context in which those directories should be visible. Effectively this is the same as creating multiple distinct directories with the same name but internally to sysfs the result is nicer. I am calling the concept of a single directory that looks like multiple directories all at the same path in the filesystem tagged directories. For the networking namespace the set of directories whose contents I need to filter with tags can depend on the presence or absence of hotplug hardware or which modules are currently loaded. Which means I need a simple race free way to setup those directories as tagged. To achieve a reace free design all tagged directories are created and managed by sysfs itself. Users of this interface: - define a type in the sysfs_tag_type enumeration. - call sysfs_register_tag_types with the type and it's operations - call sysfs_make_tagged_dir with the tag type on directories to be managed by this tag type - sysfs_exit_tag when an individual tag is no longer valid - Implement mount_tag() which returns the tag of the calling process so we can attach it to a sysfs superblock. - Implement ktype.sysfs_tag() which returns the tag of a syfs kobject. Everything else is left up to sysfs and the driver layer. For the network namespace mount_tag and sysfs_tag are essentially one line functions, and look to remain that. Tags are currently represented a const void * pointers as that is both generic, prevides enough information for equality comparisons, and is trivial to create for current users, as it is just the existing namespace pointer. The work needed in sysfs is more extensive. At each directory or symlink creating I need to check if the directory it is being created in is a tagged directory and if so generate the appropriate tag to place on the sysfs_dirent. Likewise at each symlink or directory removal I need to check if the sysfs directory it is being removed from is a tagged directory and if so figure out which tag goes along with the name I am deleting. Currently only directories which hold kobjects, and symlinks are supported. There is not enough information in the current file attribute interfaces to give us anything to discriminate on which makes it useless, and there are no potential users which makes it an uninteresting problem to solve. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/bin.c | 2 +- fs/sysfs/dir.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- fs/sysfs/file.c | 10 ++-- fs/sysfs/group.c | 4 +- fs/sysfs/inode.c | 7 ++- fs/sysfs/mount.c | 115 +++++++++++++++++++++++++++++++++++++-- fs/sysfs/symlink.c | 2 +- fs/sysfs/sysfs.h | 19 ++++++- include/linux/kobject.h | 1 + include/linux/sysfs.h | 29 ++++++++++ 10 files changed, 295 insertions(+), 33 deletions(-) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 006fc64..86e1128 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -252,7 +252,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) { - sysfs_hash_and_remove(kobj->sd, attr->attr.name); + sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_create_bin_file); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index b2d92ea..6dc3376 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -30,6 +30,30 @@ DEFINE_SPINLOCK(sysfs_assoc_lock); static DEFINE_SPINLOCK(sysfs_ino_lock); static DEFINE_IDA(sysfs_ino_ida); +static const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, + struct sysfs_dirent *sd) +{ + const void *tag = NULL; + + if (sysfs_tag_type(parent_sd)) { + struct kobject *kobj; + switch (sysfs_type(sd)) { + case SYSFS_DIR: + kobj = sd->s_dir.kobj; + break; + case SYSFS_KOBJ_LINK: + kobj = sd->s_symlink.target_sd->s_dir.kobj; + break; + default: + BUG(); + } + tag = kobj->ktype->sysfs_tag(kobj); + /* NULL tags are reserved for internal use */ + BUG_ON(tag == NULL); + } + return tag; +} + /** * sysfs_link_sibling - link sysfs_dirent into sibling list * @sd: sysfs_dirent of interest @@ -101,8 +125,19 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) struct dentry *sysfs_get_dentry(struct super_block *sb, struct sysfs_dirent *sd) { - struct dentry *dentry = dget(sb->s_root); + struct dentry *dentry; + + /* Bail if this sd won't show up in this superblock */ + if (sd->s_parent) { + enum sysfs_tag_type type; + const void *tag; + type = sysfs_tag_type(sd->s_parent); + tag = sysfs_info(sb)->tag[type]; + if (sd->s_tag != tag) + return ERR_PTR(-EXDEV); + } + dentry = dget(sb->s_root); while (dentry->d_fsdata != sd) { struct sysfs_dirent *cur; struct dentry *parent; @@ -421,10 +456,15 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, */ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) + const void *tag = NULL; + + tag = sysfs_creation_tag(acxt->parent_sd, sd); + + if (sysfs_find_dirent(acxt->parent_sd, tag, sd->s_name)) return -EEXIST; sd->s_parent = sysfs_get(acxt->parent_sd); + sd->s_tag = tag; if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) inc_nlink(acxt->parent_inode); @@ -572,13 +612,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) * Pointer to sysfs_dirent if found, NULL if not. */ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const void *tag, const unsigned char *name) { struct sysfs_dirent *sd; - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { + if (sd->s_tag != tag) + continue; if (!strcmp(sd->s_name, name)) return sd; + } return NULL; } @@ -602,7 +646,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, struct sysfs_dirent *sd; mutex_lock(&sysfs_mutex); - sd = sysfs_find_dirent(parent_sd, name); + sd = sysfs_find_dirent(parent_sd, NULL, name); sysfs_get(sd); mutex_unlock(&sysfs_mutex); @@ -668,13 +712,18 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret = NULL; - struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; + struct dentry *parent = dentry->d_parent; + struct sysfs_dirent *parent_sd = parent->d_fsdata; struct sysfs_dirent *sd; struct inode *inode; + enum sysfs_tag_type type; + const void *tag; mutex_lock(&sysfs_mutex); - sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); + type = sysfs_tag_type(parent_sd); + tag = sysfs_info(parent->d_sb)->tag[type]; + sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); /* no such entry */ if (!sd) { @@ -882,19 +931,24 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) struct sysfs_rename_struct *srs; struct inode *parent_inode = NULL; const char *dup_name = NULL; + const void *old_tag, *tag; int error; INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); + old_tag = sd->s_tag; + tag = sysfs_creation_tag(sd->s_parent, sd); error = 0; - if (strcmp(sd->s_name, new_name) == 0) + if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) goto out; /* nothing to rename */ sysfs_grab_supers(); - error = prep_rename(&todo, sd, sd->s_parent, new_name); - if (error) - goto out_release; + if (old_tag == tag) { + error = prep_rename(&todo, sd, sd->s_parent, new_name); + if (error) + goto out_release; + } error = -ENOMEM; mutex_lock(&sysfs_mutex); @@ -907,7 +961,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(sd->s_parent, new_name)) + if (sysfs_find_dirent(sd->s_parent, tag, new_name)) goto out_unlock; /* rename sysfs_dirent */ @@ -918,6 +972,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) dup_name = sd->s_name; sd->s_name = new_name; + sd->s_tag = tag; /* rename */ list_for_each_entry(srs, &todo, list) { @@ -925,6 +980,20 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) d_move(srs->old_dentry, srs->new_dentry); } + /* If we are moving across superblocks drop the dcache entries */ + if (old_tag != tag) { + struct super_block *sb; + struct dentry *dentry; + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + dentry = __sysfs_get_dentry(sb, sd); + if (!dentry) + continue; + shrink_dcache_parent(dentry); + d_drop(dentry); + dput(dentry); + } + } + error = 0; out_unlock: mutex_unlock(&sysfs_mutex); @@ -947,11 +1016,13 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) struct sysfs_rename_struct *srs; struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; int error; + const void *tag; INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; + tag = sd->s_tag; error = 0; if (sd->s_parent == new_parent_sd) @@ -985,7 +1056,7 @@ again: mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) + if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) goto out_unlock; error = 0; @@ -1024,10 +1095,12 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd) static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_path.dentry; - struct sysfs_dirent * parent_sd = dentry->d_fsdata; + struct dentry *parent = filp->f_path.dentry; + struct sysfs_dirent *parent_sd = parent->d_fsdata; struct sysfs_dirent *pos; ino_t ino; + enum sysfs_tag_type type; + const void *tag; if (filp->f_pos == 0) { ino = parent_sd->s_ino; @@ -1045,6 +1118,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { mutex_lock(&sysfs_mutex); + type = sysfs_tag_type(parent_sd); + tag = sysfs_info(parent->d_sb)->tag[type]; + /* Skip the dentries we have already reported */ pos = parent_sd->s_dir.children; while (pos && (filp->f_pos > pos->s_ino)) @@ -1054,6 +1130,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) const char * name; int len; + if (pos->s_tag != tag) + continue; + name = pos->s_name; len = strlen(name); filp->f_pos = ino = pos->s_ino; @@ -1074,3 +1153,35 @@ const struct file_operations sysfs_dir_operations = { .read = generic_read_dir, .readdir = sysfs_readdir, }; + +/** + * sysfs_make_tagged_dir - Require tags of all the entries in a directory. + * @kobj: object whose children should be filtered by tags + * + * Once tagging has been enabled on a directory the contents + * of the directory become dependent upon context captured when + * sysfs was mounted. + */ +int sysfs_make_tagged_dir(struct kobject *kobj, enum sysfs_tag_type type) +{ + struct sysfs_dirent *sd; + int err; + + err = -ENOENT; + sd = kobj->sd; + + mutex_lock(&sysfs_mutex); + err = -EINVAL; + /* We can only enable tagging when we have a valid tag type + * on empty directories where taggint has not already been + * enabled. + */ + if ((type > SYSFS_TAG_TYPE_NONE) && (type < SYSFS_TAG_TYPES) && + tag_ops[type] && !sysfs_tag_type(sd) && + (sysfs_type(sd) == SYSFS_DIR) && !sd->s_dir.children) { + err = 0; + sd->s_flags |= (type << SYSFS_TAG_TYPE_SHIFT); + } + mutex_unlock(&sysfs_mutex); + return err; +} diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 5955ae9..be95fa2 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -461,9 +461,11 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr) mutex_lock(&sysfs_mutex); if (sd && dir) - sd = sysfs_find_dirent(sd, dir); + /* only directories are tagged, so no need to pass + a tag explicitly */ + sd = sysfs_find_dirent(sd, NULL, dir); if (sd && attr) - sd = sysfs_find_dirent(sd, attr); + sd = sysfs_find_dirent(sd, NULL, attr); if (sd) { struct sysfs_open_dirent *od; @@ -636,7 +638,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) { - sysfs_hash_and_remove(kobj->sd, attr->name); + sysfs_hash_and_remove(kobj, kobj->sd, attr->name); } @@ -656,7 +658,7 @@ void sysfs_remove_file_from_group(struct kobject *kobj, else dir_sd = sysfs_get(kobj->sd); if (dir_sd) { - sysfs_hash_and_remove(dir_sd, attr->name); + sysfs_hash_and_remove(kobj, dir_sd, attr->name); sysfs_put(dir_sd); } } diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index eeba384..b6693b4 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, int i; for (i = 0, attr = grp->attrs; *attr; i++, attr++) - sysfs_hash_and_remove(dir_sd, (*attr)->name); + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); } static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, * visibility. Do this by first removing then * re-adding (if required) the file */ if (update) - sysfs_hash_and_remove(dir_sd, (*attr)->name); + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); if (grp->is_visible) { mode = grp->is_visible(kobj, *attr, i); if (!mode) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 80f8fd4..b5fc78a 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -226,17 +226,20 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) return inode; } -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, + const char *name) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; + const void *tag; if (!dir_sd) return -ENOENT; sysfs_addrm_start(&acxt, dir_sd); + tag = kobj->sd->s_tag; - sd = sysfs_find_dirent(dir_sd, name); + sd = sysfs_find_dirent(dir_sd, tag, name); if (sd) sysfs_remove_one(&acxt, sd); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 99974f0..c4a3022 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -34,12 +34,15 @@ static const struct super_operations sysfs_ops = { struct sysfs_dirent sysfs_root = { .s_name = "", .s_count = ATOMIC_INIT(1), - .s_flags = SYSFS_DIR, + .s_flags = SYSFS_DIR | (SYSFS_TAG_TYPE_NONE << SYSFS_TAG_TYPE_SHIFT), .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, .s_ino = 1, }; -static int sysfs_fill_super(struct super_block *sb, void *data, int silent) +struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; + +static int sysfs_fill_super(struct super_block *sb, void *data, int silent, + const void *tags[SYSFS_TAG_TYPES]) { struct sysfs_super_info *info = NULL; struct inode *inode = NULL; @@ -75,8 +78,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) goto out_err; } root->d_fsdata = &sysfs_root; + root->d_sb = sb; sb->s_root = root; sb->s_fs_info = info; + memcpy(info->tag, tags, sizeof(info->tag[0])*SYSFS_TAG_TYPES); return 0; out_err: @@ -88,20 +93,74 @@ out_err: return error; } +static int sysfs_test_super(struct super_block *sb, void *ptr) +{ + const void **tag = ptr; + struct sysfs_super_info *info = sysfs_info(sb); + enum sysfs_tag_type type; + int found = 1; + + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { + if (info->tag[type] != tag[type]) { + found = 0; + break; + } + } + + return found; +} + static int sysfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - int rc; + const void *tag[SYSFS_TAG_TYPES]; + struct super_block *sb; + int error; + enum sysfs_tag_type type; + + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { + tag[type] = NULL; + if (!tag_ops[type]) + continue; + tag[type] = tag_ops[type]->mount_tag(); + } + mutex_lock(&sysfs_rename_mutex); - rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + sb = sget(fs_type, sysfs_test_super, set_anon_super, tag); + if (IS_ERR(sb)) { + error = PTR_ERR(sb); + goto out; + } + if (!sb->s_root) { + sb->s_flags = flags; + error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0, + tag); + if (error) { + up_write(&sb->s_umount); + deactivate_super(sb); + goto out; + } + sb->s_flags |= MS_ACTIVE; + } + do_remount_sb(sb, flags, data, 0); + error = simple_set_mnt(mnt, sb); +out: mutex_unlock(&sysfs_rename_mutex); - return rc; + return error; +} + +static void sysfs_kill_sb(struct super_block *sb) +{ + struct sysfs_super_info *info = sysfs_info(sb); + + kill_anon_super(sb); + kfree(info); } struct file_system_type sysfs_fs_type = { .name = "sysfs", .get_sb = sysfs_get_sb, - .kill_sb = kill_anon_super, + .kill_sb = sysfs_kill_sb, }; void sysfs_grab_supers(void) @@ -145,6 +204,50 @@ restart: spin_unlock(&sb_lock); } +int sysfs_register_tag_type(enum sysfs_tag_type type, struct sysfs_tag_type_operations *ops) +{ + int error; + + mutex_lock(&sysfs_rename_mutex); + + error = -EINVAL; + if (type >= SYSFS_TAG_TYPES) + goto out; + + error = -EINVAL; + if (type <= SYSFS_TAG_TYPE_NONE) + goto out; + + error = -EBUSY; + if (tag_ops[type]) + goto out; + + error = 0; + tag_ops[type] = ops; + +out: + mutex_unlock(&sysfs_rename_mutex); + return error; +} + +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) +{ + /* Allow the tag to go away while sysfs is still mounted. */ + struct super_block *sb; + mutex_lock(&sysfs_rename_mutex); + sysfs_grab_supers(); + mutex_lock(&sysfs_mutex); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + struct sysfs_super_info *info = sysfs_info(sb); + if (info->tag[type] != tag) + continue; + info->tag[type] = NULL; + } + mutex_unlock(&sysfs_mutex); + sysfs_release_supers(); + mutex_unlock(&sysfs_rename_mutex); +} + int __init sysfs_init(void) { int err = -ENOMEM; diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 817f596..de9a5c0 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -94,7 +94,7 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) else parent_sd = kobj->sd; - sysfs_hash_and_remove(parent_sd, name); + sysfs_hash_and_remove(kobj, parent_sd, name); } static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 33b3c73..4128e6f 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -45,6 +45,7 @@ struct sysfs_dirent { struct sysfs_dirent *s_sibling; const char *s_name; + const void *s_tag; union { struct sysfs_elem_dir s_dir; struct sysfs_elem_symlink s_symlink; @@ -67,14 +68,22 @@ struct sysfs_dirent { #define SYSFS_KOBJ_LINK 0x0008 #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK -#define SYSFS_FLAG_REMOVED 0x0200 +#define SYSFS_TAG_TYPE_MASK 0xff00 +#define SYSFS_TAG_TYPE_SHIFT 8 + +#define SYSFS_FLAG_MASK ~(SYSFS_TYPE_MASK | SYSFS_TAG_TYPE_MASK) +#define SYSFS_FLAG_REMOVED 0x020000 static inline unsigned int sysfs_type(struct sysfs_dirent *sd) { return sd->s_flags & SYSFS_TYPE_MASK; } +static inline enum sysfs_tag_type sysfs_tag_type(struct sysfs_dirent *sd) +{ + return (sd->s_flags & SYSFS_TAG_TYPE_MASK) >> SYSFS_TAG_TYPE_SHIFT; +} + /* * Context structure to be used while adding/removing nodes. */ @@ -87,6 +96,7 @@ struct sysfs_addrm_cxt { struct sysfs_super_info { int grabbed; + const void *tag[SYSFS_TAG_TYPES]; }; #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) @@ -98,6 +108,7 @@ extern struct sysfs_dirent sysfs_root; extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; extern struct file_system_type sysfs_fs_type; +extern struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; void sysfs_grab_supers(void); void sysfs_release_supers(void); @@ -123,6 +134,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const void *tag, const unsigned char *name); struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name); @@ -155,7 +167,8 @@ static inline void sysfs_put(struct sysfs_dirent *sd) struct inode *sysfs_get_inode(struct sysfs_dirent *sd); int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, + const char *name); int sysfs_inode_init(void); /* diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 60f0d41..6bc38f8 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -105,6 +105,7 @@ struct kobj_type { void (*release)(struct kobject *kobj); struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; + const void *(*sysfs_tag)(struct kobject *kobj); }; struct kobj_uevent_env { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index f7e43ed..8fa97f0 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -78,6 +78,15 @@ struct sysfs_ops { ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); }; +enum sysfs_tag_type { + SYSFS_TAG_TYPE_NONE = 0, + SYSFS_TAG_TYPES +}; + +struct sysfs_tag_type_operations { + const void *(*mount_tag)(void); +}; + #ifdef CONFIG_SYSFS int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), @@ -117,6 +126,10 @@ void sysfs_remove_file_from_group(struct kobject *kobj, void sysfs_notify(struct kobject *kobj, char *dir, char *attr); void sysfs_printk_last_file(void); +int sysfs_make_tagged_dir(struct kobject *, enum sysfs_tag_type tag_type); +int sysfs_register_tag_type(enum sysfs_tag_type type, struct sysfs_tag_type_operations *ops); +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag); + extern int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ @@ -217,6 +230,22 @@ static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr) { } +staticn inline int sysfs_make_tagged_dir(struct kobject *kobj, + enum sysfs_tag_type tag_type) +{ + return 0; +} + +static inline int sysfs_register_tag_type(enum sysfs_tag_type type, + struct sysfs_tag_type_operations *ops) +{ + return 0; +} + +static inline void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) +{ +} + static inline int __must_check sysfs_init(void) { return 0; -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 10/15] sysfs: Merge sysfs_rename_dir and sysfs_move_dir 2008-07-04 1:16 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Eric W. Biederman @ 2008-07-04 1:17 ` Eric W. Biederman 2008-07-04 1:18 ` [PATCH 11/15] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman 2008-08-20 2:17 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Greg KH 1 sibling, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:17 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev These two functions do 90% of the same work and it doesn't significantly obfuscate the function to allow both the parent dir and the name to change at the same time. So merge them together to simplify maintenance, and increase testing. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/dir.c | 121 +++++++++++++++++-------------------------------------- 1 files changed, 38 insertions(+), 83 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6dc3376..fe2bb1c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -924,44 +924,57 @@ err_out: return error; } -int sysfs_rename_dir(struct kobject * kobj, const char *new_name) +static int sysfs_mv_dir(struct sysfs_dirent *sd, + struct sysfs_dirent *new_parent_sd, const char *new_name) { - struct sysfs_dirent *sd = kobj->sd; struct list_head todo; struct sysfs_rename_struct *srs; - struct inode *parent_inode = NULL; + struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; const char *dup_name = NULL; const void *old_tag, *tag; int error; INIT_LIST_HEAD(&todo); + BUG_ON(!sd->s_parent); mutex_lock(&sysfs_rename_mutex); + if (!new_parent_sd) + new_parent_sd = &sysfs_root; + old_tag = sd->s_tag; tag = sysfs_creation_tag(sd->s_parent, sd); error = 0; - if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) - goto out; /* nothing to rename */ + if ((sd->s_parent == new_parent_sd) && (old_tag == tag) && + (strcmp(sd->s_name, new_name) == 0)) + goto out; /* nothing to do */ sysfs_grab_supers(); if (old_tag == tag) { - error = prep_rename(&todo, sd, sd->s_parent, new_name); + error = prep_rename(&todo, sd, new_parent_sd, new_name); if (error) goto out_release; } error = -ENOMEM; mutex_lock(&sysfs_mutex); - parent_inode = sysfs_get_inode(sd->s_parent); + old_parent_inode = sysfs_get_inode(sd->s_parent); + new_parent_inode = sysfs_get_inode(new_parent_sd); mutex_unlock(&sysfs_mutex); - if (!parent_inode) + if (!old_parent_inode || !new_parent_inode) goto out_release; - mutex_lock(&parent_inode->i_mutex); +again: + mutex_lock(&old_parent_inode->i_mutex); + if (old_parent_inode != new_parent_inode) { + if (!mutex_trylock(&new_parent_inode->i_mutex)) { + mutex_unlock(&old_parent_inode->i_mutex); + goto again; + } + } mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(sd->s_parent, tag, new_name)) + if (sysfs_find_dirent(new_parent_sd, tag, new_name)) goto out_unlock; /* rename sysfs_dirent */ @@ -974,7 +987,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) sd->s_name = new_name; sd->s_tag = tag; - /* rename */ + /* rename dcache entries */ list_for_each_entry(srs, &todo, list) { d_add(srs->new_dentry, NULL); d_move(srs->old_dentry, srs->new_dentry); @@ -994,77 +1007,6 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) } } - error = 0; -out_unlock: - mutex_unlock(&sysfs_mutex); - mutex_unlock(&parent_inode->i_mutex); - kfree(dup_name); -out_release: - iput(parent_inode); - post_rename(&todo); - sysfs_release_supers(); -out: - mutex_unlock(&sysfs_rename_mutex); - return error; -} - -int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) -{ - struct sysfs_dirent *sd = kobj->sd; - struct sysfs_dirent *new_parent_sd; - struct list_head todo; - struct sysfs_rename_struct *srs; - struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; - int error; - const void *tag; - - INIT_LIST_HEAD(&todo); - mutex_lock(&sysfs_rename_mutex); - BUG_ON(!sd->s_parent); - new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; - tag = sd->s_tag; - - error = 0; - if (sd->s_parent == new_parent_sd) - goto out; /* nothing to move */ - - sysfs_grab_supers(); - error = prep_rename(&todo, sd, new_parent_sd, sd->s_name); - if (error) - goto out_release; - - error = -ENOMEM; - mutex_lock(&sysfs_mutex); - old_parent_inode = sysfs_get_inode(sd->s_parent); - mutex_unlock(&sysfs_mutex); - if (!old_parent_inode) - goto out_release; - - error = -ENOMEM; - mutex_lock(&sysfs_mutex); - new_parent_inode = sysfs_get_inode(new_parent_sd); - mutex_unlock(&sysfs_mutex); - if (!new_parent_inode) - goto out_release; - -again: - mutex_lock(&old_parent_inode->i_mutex); - if (!mutex_trylock(&new_parent_inode->i_mutex)) { - mutex_unlock(&old_parent_inode->i_mutex); - goto again; - } - mutex_lock(&sysfs_mutex); - - error = -EEXIST; - if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) - goto out_unlock; - - error = 0; - list_for_each_entry(srs, &todo, list) { - d_add(srs->new_dentry, NULL); - d_move(srs->old_dentry, srs->new_dentry); - } - /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); sysfs_get(new_parent_sd); @@ -1072,10 +1014,13 @@ again: sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); + error = 0; out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&new_parent_inode->i_mutex); + if (new_parent_inode != old_parent_inode) + mutex_unlock(&new_parent_inode->i_mutex); mutex_unlock(&old_parent_inode->i_mutex); + kfree(dup_name); out_release: iput(new_parent_inode); @@ -1087,6 +1032,16 @@ out: return error; } +int sysfs_rename_dir(struct kobject * kobj, const char *new_name) +{ + return sysfs_mv_dir(kobj->sd, kobj->sd->s_parent, new_name); +} + +int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) +{ + return sysfs_mv_dir(kobj->sd, new_parent_kobj->sd, kobj->sd->s_name); +} + /* Relationship between s_mode and the DT_xxx types */ static inline unsigned char dt_type(struct sysfs_dirent *sd) { -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 11/15] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-07-04 1:17 ` [PATCH 10/15] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman @ 2008-07-04 1:18 ` Eric W. Biederman 2008-07-04 1:20 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:18 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev When removing a symlink sysfs_remove_link does not provide enough information to figure out which tagged directory the symlink falls in. So I need sysfs_delete_link which is passed the target of the symlink to delete. Further half the time when we are removing a symlink the code is actually renaming the symlink but not doing so explicitly because we don't have a symlink rename method. So I have added sysfs_rename_link as well. Both of these functions now have enough information to find a symlink in a tagged directory. The only restriction is that they must be called before the target kobject is renamed or deleted. If they are called later I loose track of which tag the target kobject was marked with and can no longer find the old symlink to remove it. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> --- fs/sysfs/symlink.c | 31 +++++++++++++++++++++++++++++++ include/linux/sysfs.h | 17 +++++++++++++++++ 2 files changed, 48 insertions(+), 0 deletions(-) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index de9a5c0..ed9c52c 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -80,6 +80,21 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char } /** + * sysfs_delete_link - remove symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @name: name of the symlink to remove. + * + * Unlike sysfs_remove_link sysfs_delete_link has enough information + * to successfully delete symlinks in tagged directories. + */ +void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, + const char *name) +{ + sysfs_hash_and_remove(targ, kobj->sd, name); +} + +/** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for. * @name: name of the symlink to remove. @@ -97,6 +112,22 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) sysfs_hash_and_remove(kobj, parent_sd, name); } +/** + * sysfs_rename_link - rename symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @old: previous name of the symlink. + * @new: new name of the symlink. + * + * A helper function for the common rename symlink idiom. + */ +int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, + const char *old, const char *new) +{ + sysfs_delete_link(kobj, targ, old); + return sysfs_create_link(kobj, targ, new); +} + static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd, char *path) { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 8fa97f0..c3a30ce 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -112,6 +112,12 @@ int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); +int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name); + +void sysfs_delete_link(struct kobject *dir, struct kobject *targ, + const char *name); + int __must_check sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); int sysfs_update_group(struct kobject *kobj, @@ -198,6 +204,17 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } +static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, + const char *old_name, const char *new_name) +{ + return 0; +} + +static inline void sysfs_delete_link(struct kobject *k, struct kobject *t, + const char *name) +{ +} + static inline int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 1:18 ` [PATCH 11/15] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman @ 2008-07-04 1:20 ` Eric W. Biederman 2008-07-04 1:21 ` [PATCH 13/15] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman 2008-07-04 7:50 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Tejun Heo 0 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:20 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev This patch enables tagging on every class directory if struct class has a tag_type. In addition device_del and device_rename were modified to uses sysfs_delete_link and sysfs_rename_link respectively to ensure when these operations happen on devices whose classes have tag_ops that they work properly. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- drivers/base/class.c | 30 ++++++++++++++++++++++--- drivers/base/core.c | 56 +++++++++++++++++++++++++++++++++-------------- include/linux/device.h | 3 ++ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index 839d27c..cf4e03f 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -135,6 +135,17 @@ static void remove_class_attrs(struct class *cls) } } +static int class_setup_tagging(struct class *cls) +{ + enum sysfs_tag_type type; + + type = cls->tag_type; + if (type == SYSFS_TAG_TYPE_NONE) + return 0; + + return sysfs_make_tagged_dir(&cls->p->class_subsys.kobj, type); +} + int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; @@ -171,13 +182,24 @@ int __class_register(struct class *cls, struct lock_class_key *key) cls->p = cp; error = kset_register(&cp->class_subsys); - if (error) { - kfree(cp); - return error; - } + if (error) + goto out_free_cp; + + error = class_setup_tagging(cls); + if (error) + goto out_unregister; + error = add_class_attrs(class_get(cls)); class_put(cls); + if (error) + goto out_unregister; +out: return error; +out_unregister: + kset_unregister(&cp->class_subsys); +out_free_cp: + kfree(cp); + goto out; } EXPORT_SYMBOL_GPL(__class_register); diff --git a/drivers/base/core.c b/drivers/base/core.c index 90621a4..b009d5b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -124,9 +124,21 @@ static void device_release(struct kobject *kobj) } } +static const void *device_sysfs_tag(struct kobject *kobj) +{ + struct device *dev = to_dev(kobj); + const void *tag = NULL; + + if (dev->class && dev->class->tag_type) + tag = dev->class->sysfs_tag(dev); + + return tag; +} + static struct kobj_type device_ktype = { .release = device_release, .sysfs_ops = &dev_sysfs_ops, + .sysfs_tag = device_sysfs_tag, }; @@ -619,6 +631,10 @@ static struct kobject *get_device_parent(struct device *dev, kobject_put(k); return NULL; } + /* If we created a new class-directory setup tagging */ + if (dev->class->tag_type) + sysfs_make_tagged_dir(k, dev->class->tag_type); + /* do not emit an uevent for this simple "glue" directory */ return k; } @@ -709,7 +725,7 @@ out_device: out_busid: if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->class_subsys.kobj, + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #else /* link in the class directory pointing to the device */ @@ -727,7 +743,7 @@ out_busid: return 0; out_busid: - sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #endif out_subsys: @@ -755,13 +771,13 @@ static void device_remove_class_symlinks(struct device *dev) if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->class_subsys.kobj, + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #else if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); - sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #endif sysfs_remove_link(&dev->kobj, "subsystem"); @@ -1344,6 +1360,16 @@ int device_rename(struct device *dev, char *new_name) strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); +#ifndef CONFIG_SYSFS_DEPRECATED + if (dev->class && + (dev->kobj.parent != &dev->class->p->class_subsys.kobj)) { + error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, old_device_name, new_name); + if (error) + goto out; + } +#endif + error = kobject_rename(&dev->kobj, new_name); if (error) { strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); @@ -1352,23 +1378,19 @@ int device_rename(struct device *dev, char *new_name) #ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { + error = -ENOMEM; new_class_name = make_class_name(dev->class->name, &dev->kobj); - if (new_class_name) { - error = sysfs_create_link(&dev->parent->kobj, - &dev->kobj, new_class_name); - if (error) - goto out; - sysfs_remove_link(&dev->parent->kobj, old_class_name); - } + if (new_class_name) + error = sysfs_rename_link(&dev->parent->kobj, + &dev->kobj, + old_class_name, + new_class_name); } #else if (dev->class) { - error = sysfs_create_link(&dev->class->p->class_subsys.kobj, - &dev->kobj, dev->bus_id); - if (error) - goto out; - sysfs_remove_link(&dev->class->p->class_subsys.kobj, - old_device_name); + error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, old_device_name, + dev->bus_id); } #endif diff --git a/include/linux/device.h b/include/linux/device.h index d9886a6..8e84539 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -191,6 +191,9 @@ struct class { int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); + enum sysfs_tag_type tag_type; + const void *(*sysfs_tag)(struct device *dev); + struct class_private *p; }; -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 13/15] Revert "netns: Fix device renaming for sysfs" 2008-07-04 1:20 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Eric W. Biederman @ 2008-07-04 1:21 ` Eric W. Biederman 2008-07-04 1:22 ` [PATCH 14/15] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman 2008-07-04 7:50 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Tejun Heo 1 sibling, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:21 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev This reverts commit aaf8cdc34ddba08122f02217d9d684e2f9f5d575. Drivers like the ipw2100 call device_create_group when they are initialized and device_remove_group when they are shutdown. Moving them between namespaces deletes their sysfs groups early. In particular the following call chain results. netdev_unregister_kobject -> device_del -> kobject_del -> sysfs_remove_dir With sysfs_remove_dir recursively deleting all of it's subdirectories, and nothing adding them back. Ouch! Therefore we need to call something that ultimate calls sysfs_mv_dir as that sysfs function can move sysfs directories between namespaces without deleting their subdirectories or their contents. Allowing us to avoid placing extra boiler plate into every driver that does something interesting with sysfs. Currently the function that provides that capability is device_rename. That is the code works without nasty side effects as originally written. So remove the misguided fix for moving devices between namespaces. The bug in the kobject layer that inspired it has now been recognized and fixed. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- net/core/dev.c | 4 +--- net/core/net-sysfs.c | 7 +------ net/core/net-sysfs.h | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index fca23a3..585584d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3806,7 +3806,6 @@ int register_netdevice(struct net_device *dev) } } - netdev_initialize_kobject(dev); ret = netdev_register_kobject(dev); if (ret) goto err_uninit; @@ -4239,8 +4238,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char } /* Fixup kobjects */ - netdev_unregister_kobject(dev); - err = netdev_register_kobject(dev); + err = device_rename(&dev->dev, dev->name); WARN_ON(err); /* Add the device back in the hashes */ diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 90e2177..4e7b847 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -449,6 +449,7 @@ int netdev_register_kobject(struct net_device *net) struct device *dev = &(net->dev); struct attribute_group **groups = net->sysfs_groups; + device_initialize(dev); dev->class = &net_class; dev->platform_data = net; dev->groups = groups; @@ -469,12 +470,6 @@ int netdev_register_kobject(struct net_device *net) return device_add(dev); } -void netdev_initialize_kobject(struct net_device *net) -{ - struct device *device = &(net->dev); - device_initialize(device); -} - int netdev_kobject_init(void) { return class_register(&net_class); diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h index 14e7524..f5f108d 100644 --- a/net/core/net-sysfs.h +++ b/net/core/net-sysfs.h @@ -4,5 +4,5 @@ int netdev_kobject_init(void); int netdev_register_kobject(struct net_device *); void netdev_unregister_kobject(struct net_device *); -void netdev_initialize_kobject(struct net_device *); + #endif -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 14/15] netns: Enable tagging for net_class directories in sysfs 2008-07-04 1:21 ` [PATCH 13/15] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman @ 2008-07-04 1:22 ` Eric W. Biederman 2008-07-04 1:23 ` [PATCH 15/15] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:22 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev The problem. Network devices show up in sysfs and with the network namespace active multiple devices with the same name can show up in the same directory, ouch! To avoid that problem and allow existing applications in network namespaces to see the same interface that is currently presented in sysfs, this patch enables the tagging directory support in sysfs. By using the network namespace pointers as tags to separate out the the sysfs directory entries we ensure that we don't have conflicts in the directories and applications only see a limited set of the network devices. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- include/linux/sysfs.h | 1 + net/Kconfig | 2 +- net/core/net-sysfs.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletions(-) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c3a30ce..1ed31bb 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -80,6 +80,7 @@ struct sysfs_ops { enum sysfs_tag_type { SYSFS_TAG_TYPE_NONE = 0, + SYSFS_TAG_TYPE_NETNS, SYSFS_TAG_TYPES }; diff --git a/net/Kconfig b/net/Kconfig index acbf7c6..9aad03b 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -30,7 +30,7 @@ menu "Networking options" config NET_NS bool "Network namespace support" default n - depends on EXPERIMENTAL && !SYSFS && NAMESPACES + depends on EXPERIMENTAL && NAMESPACES help Allow user space to create what appear to be multiple instances of the network stack. diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4e7b847..6227a28 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -13,7 +13,9 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/if_arp.h> +#include <linux/nsproxy.h> #include <net/sock.h> +#include <net/net_namespace.h> #include <linux/rtnetlink.h> #include <linux/wireless.h> #include <net/iw_handler.h> @@ -385,6 +387,24 @@ static struct attribute_group wireless_group = { }; #endif +static const void *net_sysfs_mount_tag(void) +{ + return current->nsproxy->net_ns; +} + +static struct sysfs_tag_type_operations net_tag_type_operations = { + .mount_tag = net_sysfs_mount_tag, +}; + +static void net_sysfs_net_exit(struct net *net) +{ + sysfs_exit_tag(SYSFS_TAG_TYPE_NETNS, net); +} + +static struct pernet_operations sysfs_net_ops = { + .exit = net_sysfs_net_exit, +}; + #endif /* CONFIG_SYSFS */ #ifdef CONFIG_HOTPLUG @@ -421,6 +441,13 @@ static void netdev_release(struct device *d) kfree((char *)dev - dev->padded); } +static const void *net_sysfs_tag(struct device *d) +{ + struct net_device *dev; + dev = container_of(d, struct net_device, dev); + return dev_net(dev); +} + static struct class net_class = { .name = "net", .dev_release = netdev_release, @@ -430,6 +457,8 @@ static struct class net_class = { #ifdef CONFIG_HOTPLUG .dev_uevent = netdev_uevent, #endif + .tag_type = SYSFS_TAG_TYPE_NETNS, + .sysfs_tag = net_sysfs_tag, }; /* Delete sysfs entries but hold kobject reference until after all @@ -472,5 +501,9 @@ int netdev_register_kobject(struct net_device *net) int netdev_kobject_init(void) { +#ifdef CONFIG_SYSFS + sysfs_register_tag_type(SYSFS_TAG_TYPE_NETNS, &net_tag_type_operations); + register_pernet_subsys(&sysfs_net_ops); +#endif return class_register(&net_class); } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 15/15] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched 2008-07-04 1:22 ` [PATCH 14/15] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman @ 2008-07-04 1:23 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:23 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Mark the /sys/kernel/uids directory to be tagged so that processes in different user namespaces can remount /sys and see their own uid listings. Without this patch, having CONFIG_FAIR_SCHED=y makes user namespaces unusable, because when you clone(CLONE_NEWUSER) it will auto-create the root userid and try to create /sys/kernel/uids/0. Since that already exists from the parent user namespace, the create fails, and the clone misleadingly ends up returning -ENOMEM. This patch fixes the issue by allowing each user namespace to remount /sys, and having /sys filter the /sys/kernel/uid/ entries by user namespace. Changelong: v2 - Reworked for the updated sysfs api Signed-off-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- include/linux/sched.h | 1 + include/linux/sysfs.h | 1 + kernel/user.c | 22 ++++++++++++++++++++++ kernel/user_namespace.c | 1 + 4 files changed, 25 insertions(+), 0 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index c5d3f84..d2be6a5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -598,6 +598,7 @@ struct user_struct { /* Hash table maintenance information */ struct hlist_node uidhash_node; uid_t uid; + struct user_namespace *user_ns; #ifdef CONFIG_USER_SCHED struct task_group *tg; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 1ed31bb..ecb942c 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -81,6 +81,7 @@ struct sysfs_ops { enum sysfs_tag_type { SYSFS_TAG_TYPE_NONE = 0, SYSFS_TAG_TYPE_NETNS, + SYSFS_TAG_TYPE_USERNS, SYSFS_TAG_TYPES }; diff --git a/kernel/user.c b/kernel/user.c index 865ecf5..ca29fbc 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -53,6 +53,7 @@ struct user_struct root_user = { .files = ATOMIC_INIT(0), .sigpending = ATOMIC_INIT(0), .locked_shm = 0, + .user_ns = &init_user_ns, #ifdef CONFIG_USER_SCHED .tg = &init_task_group, #endif @@ -230,16 +231,33 @@ static struct attribute *uids_attributes[] = { NULL }; +static const void *uids_mount_tag(void) +{ + return current->nsproxy->user_ns; +} + +static struct sysfs_tag_type_operations uids_tag_type_operations = { + .mount_tag = uids_mount_tag, +}; + /* the lifetime of user_struct is not managed by the core (now) */ static void uids_release(struct kobject *kobj) { return; } +static const void *uids_sysfs_tag(struct kobject *kobj) +{ + struct user_struct *up; + up = container_of(kobj, struct user_struct, kobj); + return up->user_ns; +} + static struct kobj_type uids_ktype = { .sysfs_ops = &kobj_sysfs_ops, .default_attrs = uids_attributes, .release = uids_release, + .sysfs_tag = uids_sysfs_tag, }; /* create /sys/kernel/uids/<uid>/cpu_share file for this user */ @@ -272,6 +290,9 @@ int __init uids_sysfs_init(void) if (!uids_kset) return -ENOMEM; + sysfs_register_tag_type(SYSFS_TAG_TYPE_USERNS, &uids_tag_type_operations); + sysfs_make_tagged_dir(&uids_kset->kobj, SYSFS_TAG_TYPE_USERNS); + return uids_user_create(&root_user); } @@ -405,6 +426,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) new->uid = uid; atomic_set(&new->__count, 1); + new->user_ns = ns; if (sched_create_user(new) < 0) goto out_free_user; diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index a9ab059..f67bbe0 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -71,6 +71,7 @@ void free_user_ns(struct kref *kref) struct user_namespace *ns; ns = container_of(kref, struct user_namespace, kref); + sysfs_exit_tag(SYSFS_TAG_TYPE_USERNS, ns); release_uids(ns); kfree(ns); } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 1:20 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Eric W. Biederman 2008-07-04 1:21 ` [PATCH 13/15] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman @ 2008-07-04 7:50 ` Tejun Heo 2008-07-04 13:31 ` Eric W. Biederman 1 sibling, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-04 7:50 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Eric W. Biederman wrote: > This patch enables tagging on every class directory if struct class > has a tag_type. > > In addition device_del and device_rename were modified to uses > sysfs_delete_link and sysfs_rename_link respectively to ensure > when these operations happen on devices whose classes have > tag_ops that they work properly. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> > Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Okay, I went through the users this time but I still think determine-tags-by-callbacks is a bad idea. Please just add const void *tag to kobject and set it during initialization. If you want to move a device from one tag to another, implement kobject_rename_tagged(kobj, new_name, new_tag). The determine-tag-by-callback basically multiplexes basic functions to do tag-specific things which are determined by ktype callback called back from down the layer. It's simply a bad interface. Those operations become something else depending on how those callbacks behave. That's unnecessarily subtle. Advertising what it's gonna do in the function name and as arguments is way more straight forward and it's not like determining or renaming tags should be done asynchronously. I personally think it would be better to make tags explicit in the mount interface too but if extracting ns information from the mounting process is what's currently being done, well... I'm sorry but Nacked-by: Tejun Heo <tj@kernel.org> Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 7:50 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Tejun Heo @ 2008-07-04 13:31 ` Eric W. Biederman 2008-07-04 13:57 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 13:31 UTC (permalink / raw) To: Tejun Heo Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Thank you for your opinion. Incremental patches to make things more beautiful are welcome. Please remember we are not building lisp. The goal is code that works today. Since we are not talking about correctness of the code. Since we are not talking about interfaces with user space. Since we are talking something that is currently about 100 lines of code, and so will be easy to change even after it is merged. I don't understand how discussing this further is useful. Especially when I get a NAK based on the feel that the code is ugly. As for your main objection. Adding a accessor method to an object versus adding a data field that contain the same thing. The two are effectively identical. With the practical difference in my eyes that an accessor method prevents data duplication which reduces maintenance and reduces skew problems, and it keeps the size of struct kobject small. Since you think methods are horrible I must respectfully disagree with you. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 13:31 ` Eric W. Biederman @ 2008-07-04 13:57 ` Tejun Heo 2008-07-04 16:12 ` Greg KH 2008-07-04 22:00 ` Eric W. Biederman 0 siblings, 2 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-04 13:57 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Hello, Eric. Eric W. Biederman wrote: > Thank you for your opinion. > > Incremental patches to make things more beautiful are welcome. > > Please remember we are not building lisp. The goal is code that works today. > > Since we are not talking about correctness of the code. Since we are not > talking about interfaces with user space. Since we are talking something > that is currently about 100 lines of code, and so will be easy to change > even after it is merged. I don't understand how discussing this further > is useful. Especially when I get a NAK based on the feel that the code > is ugly. I'm sorry if I gave you the impression of being draconian. Explanations below. > As for your main objection. Adding a accessor method to an object versus > adding a data field that contain the same thing. The two are effectively > identical. With the practical difference in my eyes that an accessor method > prevents data duplication which reduces maintenance and reduces skew problems, > and it keeps the size of struct kobject small. Since you think methods are > horrible I must respectfully disagree with you. Yeah, it seems we should agree to disagree here. I think using callback for static values is a really bad idea. It obfuscates the code and opens up a big hole for awful misuses. Greg, what do you think? As we're very close to rc1 window, I think we can work out a solution here. The reason why I nack'd was because the change wouldn't take too much effort and I thought it could be done before -rc1. Unless you disagree with making tags static values, I'll try to write up a patch to do so. If you (and Greg) think the callback interface is better, we can merge the code as-is and update (or not) later. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 13:57 ` Tejun Heo @ 2008-07-04 16:12 ` Greg KH 2008-07-04 21:49 ` Eric W. Biederman 2008-07-14 1:54 ` Eric W. Biederman 2008-07-04 22:00 ` Eric W. Biederman 1 sibling, 2 replies; 145+ messages in thread From: Greg KH @ 2008-07-04 16:12 UTC (permalink / raw) To: Tejun Heo Cc: Eric W. Biederman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev On Fri, Jul 04, 2008 at 10:57:15PM +0900, Tejun Heo wrote: > Hello, Eric. > > Eric W. Biederman wrote: > > Thank you for your opinion. > > > > Incremental patches to make things more beautiful are welcome. > > > > Please remember we are not building lisp. The goal is code that works today. > > > > Since we are not talking about correctness of the code. Since we are not > > talking about interfaces with user space. Since we are talking something > > that is currently about 100 lines of code, and so will be easy to change > > even after it is merged. I don't understand how discussing this further > > is useful. Especially when I get a NAK based on the feel that the code > > is ugly. > > I'm sorry if I gave you the impression of being draconian. Explanations > below. > > > As for your main objection. Adding a accessor method to an object versus > > adding a data field that contain the same thing. The two are effectively > > identical. With the practical difference in my eyes that an accessor method > > prevents data duplication which reduces maintenance and reduces skew problems, > > and it keeps the size of struct kobject small. Since you think methods are > > horrible I must respectfully disagree with you. > > Yeah, it seems we should agree to disagree here. I think using callback > for static values is a really bad idea. It obfuscates the code and > opens up a big hole for awful misuses. Greg, what do you think? Sorry, Greg is walking out the door in 30 minutes for a much needed week long vacation and can't look into this right now :( I'll be able to review it next weekend, sorry for the delay. greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 16:12 ` Greg KH @ 2008-07-04 21:49 ` Eric W. Biederman 2008-07-14 1:54 ` Eric W. Biederman 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 21:49 UTC (permalink / raw) To: Greg KH Cc: Tejun Heo, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg KH <gregkh@suse.de> writes: > Sorry, Greg is walking out the door in 30 minutes for a much needed week > long vacation and can't look into this right now :( > > I'll be able to review it next weekend, sorry for the delay. Understood and no problem. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 16:12 ` Greg KH 2008-07-04 21:49 ` Eric W. Biederman @ 2008-07-14 1:54 ` Eric W. Biederman 2008-07-16 3:25 ` Tejun Heo 1 sibling, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-14 1:54 UTC (permalink / raw) To: Greg KH Cc: Tejun Heo, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg KH <gregkh@suse.de> writes: > > Sorry, Greg is walking out the door in 30 minutes for a much needed week > long vacation and can't look into this right now :( > > I'll be able to review it next weekend, sorry for the delay. Any progress in reviewing these changes, and seeing if you can stand to merge them? Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-14 1:54 ` Eric W. Biederman @ 2008-07-16 3:25 ` Tejun Heo 2008-07-16 5:41 ` Eric W. Biederman 2008-07-17 23:08 ` Greg KH 0 siblings, 2 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-16 3:25 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Eric W. Biederman wrote: > Greg KH <gregkh@suse.de> writes: >> Sorry, Greg is walking out the door in 30 minutes for a much needed week >> long vacation and can't look into this right now :( >> >> I'll be able to review it next weekend, sorry for the delay. > > Any progress in reviewing these changes, and seeing if you can stand > to merge them? Greg, please disregard my earlier NACKs and commit the patches if you're okay with them. I'm working on cleaning it up but I don't think I'll be able to make it in time for merge window and as Eric said getting the functionality in place is more important at this point as it doesn't affect user visible interface. Eric, with the multiple superblocks, sysfs now uses inode from the default sysfs_sb with dentries from other sb's. Is this okay? Are there any other filesystems which do this? Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 3:25 ` Tejun Heo @ 2008-07-16 5:41 ` Eric W. Biederman 2008-07-16 5:50 ` Tejun Heo 2008-07-17 23:08 ` Greg KH 1 sibling, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-16 5:41 UTC (permalink / raw) To: Tejun Heo Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Tejun Heo <htejun@gmail.com> writes: > Greg, please disregard my earlier NACKs and commit the patches if you're > okay with them. I'm working on cleaning it up but I don't think I'll be > able to make it in time for merge window and as Eric said getting the > functionality in place is more important at this point as it doesn't > affect user visible interface. > > Eric, with the multiple superblocks, sysfs now uses inode from the > default sysfs_sb with dentries from other sb's. Is this okay? Are > there any other filesystems which do this? I don't know of any other filesystems where this unique challenge arises. /proc almost qualifies but it never needs to be modified. It is certainly ok to go from multiple dentries to a single inode. I'm trying to remember why I choose to do that. I think both because it simplifies the locking and keeps us more efficient in the icache. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 5:41 ` Eric W. Biederman @ 2008-07-16 5:50 ` Tejun Heo 2008-07-16 6:32 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-16 5:50 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Hello, Eric W. Biederman wrote: >> Eric, with the multiple superblocks, sysfs now uses inode from the >> default sysfs_sb with dentries from other sb's. Is this okay? Are >> there any other filesystems which do this? > > I don't know of any other filesystems where this unique challenge arises. > /proc almost qualifies but it never needs to be modified. > > It is certainly ok to go from multiple dentries to a single inode. > I'm trying to remember why I choose to do that. I think both because it simplifies > the locking and keeps us more efficient in the icache. It's a bit scary tho. Working inode->i_dentry or dentry->d_alias crosses multiple sb's. sysfs isn't too greedy about dcache/icache. Only open files and directories hold them and only single copy of sysfs_dirent is there for most nodes. Wouldn't it be better to stay on the safer side and use separate inode hierarchy? Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 5:50 ` Tejun Heo @ 2008-07-16 6:32 ` Eric W. Biederman 2008-07-16 6:48 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-16 6:32 UTC (permalink / raw) To: Tejun Heo Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Tejun Heo <htejun@gmail.com> writes: > It's a bit scary tho. Working inode->i_dentry or dentry->d_alias > crosses multiple sb's. sysfs isn't too greedy about dcache/icache. > Only open files and directories hold them and only single copy of > sysfs_dirent is there for most nodes. Wouldn't it be better to stay on > the safer side and use separate inode hierarchy? To do that I believe we would need to ensure sysfs does not use the inode->i_mutex lock except to keep the VFS layer out. Allowing us to safely change the directory structure, without holding it. You raise a good point about inode->i_dentry and dentry->d_alias. Generally they are used by fat like filesystems but I am starting to see uses in generic pieces of code. I don't see any problems today but yes it would be good to do the refactoring to allow us to duplicate the inodes. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 6:32 ` Eric W. Biederman @ 2008-07-16 6:48 ` Tejun Heo 2008-07-16 7:02 ` Tejun Heo 2008-07-16 21:09 ` Eric W. Biederman 0 siblings, 2 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-16 6:48 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Hello, Eric. Eric W. Biederman wrote: > Tejun Heo <htejun@gmail.com> writes: > >> It's a bit scary tho. Working inode->i_dentry or dentry->d_alias >> crosses multiple sb's. sysfs isn't too greedy about dcache/icache. >> Only open files and directories hold them and only single copy of >> sysfs_dirent is there for most nodes. Wouldn't it be better to stay on >> the safer side and use separate inode hierarchy? > > To do that I believe we would need to ensure sysfs does not use > the inode->i_mutex lock except to keep the VFS layer out. Allowing us > to safely change the directory structure, without holding it. I don't think sysfs is depending on i_mutex anymore but I need to go through the code to make sure. > You raise a good point about inode->i_dentry and dentry->d_alias. > Generally they are used by fat like filesystems but I am starting to > see uses in generic pieces of code. I don't see any problems today > but yes it would be good to do the refactoring to allow us to duplicate > the inodes. Yeah, I can't spot any place which can cause actual problem yet but it's still scary as we're breaking a vfs assumption and even if it's not a problem now, future seemingly unrelated changes can break things subtly. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 6:48 ` Tejun Heo @ 2008-07-16 7:02 ` Tejun Heo 2008-07-16 19:07 ` Eric W. Biederman 2008-07-16 21:09 ` Eric W. Biederman 1 sibling, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-16 7:02 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Tejun Heo wrote: > Hello, Eric. > > Eric W. Biederman wrote: >> Tejun Heo <htejun@gmail.com> writes: >> >>> It's a bit scary tho. Working inode->i_dentry or dentry->d_alias >>> crosses multiple sb's. sysfs isn't too greedy about dcache/icache. >>> Only open files and directories hold them and only single copy of >>> sysfs_dirent is there for most nodes. Wouldn't it be better to stay on >>> the safer side and use separate inode hierarchy? >> To do that I believe we would need to ensure sysfs does not use >> the inode->i_mutex lock except to keep the VFS layer out. Allowing us >> to safely change the directory structure, without holding it. > > I don't think sysfs is depending on i_mutex anymore but I need to go > through the code to make sure. > >> You raise a good point about inode->i_dentry and dentry->d_alias. >> Generally they are used by fat like filesystems but I am starting to >> see uses in generic pieces of code. I don't see any problems today >> but yes it would be good to do the refactoring to allow us to duplicate >> the inodes. > > Yeah, I can't spot any place which can cause actual problem yet but it's > still scary as we're breaking a vfs assumption and even if it's not a > problem now, future seemingly unrelated changes can break things subtly. Okay, one small problem spotted. It seems invalidate_inodes() can fail which will make generic_shutdown_super() complain. It's not a fatal failure tho. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 7:02 ` Tejun Heo @ 2008-07-16 19:07 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-16 19:07 UTC (permalink / raw) To: Tejun Heo Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Tejun Heo <teheo@suse.de> writes: > Okay, one small problem spotted. It seems invalidate_inodes() can fail > which will make generic_shutdown_super() complain. It's not a fatal > failure tho. How when the inode list is empty? We don't unmount the superblock that has the inodes. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 6:48 ` Tejun Heo 2008-07-16 7:02 ` Tejun Heo @ 2008-07-16 21:09 ` Eric W. Biederman 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-16 21:09 UTC (permalink / raw) To: Tejun Heo Cc: Greg KH, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Tejun Heo <htejun@gmail.com> writes: >> To do that I believe we would need to ensure sysfs does not use >> the inode->i_mutex lock except to keep the VFS layer out. Allowing us >> to safely change the directory structure, without holding it. > > I don't think sysfs is depending on i_mutex anymore but I need to go > through the code to make sure. The vfs still does. So at least for directory tree manipulation we need to hold i_mutex before we grab sysfs_mutex. I think that means we need to unscramble the whole set of locking order issues. In lookup we have: local_vfs_lock -> fs_global_lock In modifications we have: fs_global_lock -> local_vfs_lock Which is the definition of a lock ordering problem. Currently we play jump through some significant hoops to keep things in local_vfs_lock -> fs_global_lock order. If we also take the rename_mutex on directory adds and deletes we may be able to keep jumping through those hoops. However I expect we would be in a much better situation if we could figure out how to avoid the problem. It looks like the easy way to handle this is to make the sysfs_dirent list rcu protected. Which means we can fix our lock ordering problem without VFS modifications. Allowing the locking to always be: sysfs_mutex ... i_mutex. After that it would be safe and a good idea to have unshared inodes between superblocks, just so we don't surprise anyone making generic VFS assumptions. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-16 3:25 ` Tejun Heo 2008-07-16 5:41 ` Eric W. Biederman @ 2008-07-17 23:08 ` Greg KH 2008-07-18 12:41 ` Tejun Heo 1 sibling, 1 reply; 145+ messages in thread From: Greg KH @ 2008-07-17 23:08 UTC (permalink / raw) To: Tejun Heo Cc: Eric W. Biederman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev On Wed, Jul 16, 2008 at 12:25:24PM +0900, Tejun Heo wrote: > Eric W. Biederman wrote: > > Greg KH <gregkh@suse.de> writes: > >> Sorry, Greg is walking out the door in 30 minutes for a much needed week > >> long vacation and can't look into this right now :( > >> > >> I'll be able to review it next weekend, sorry for the delay. > > > > Any progress in reviewing these changes, and seeing if you can stand > > to merge them? > > Greg, please disregard my earlier NACKs and commit the patches if you're > okay with them. I'm working on cleaning it up but I don't think I'll be > able to make it in time for merge window and as Eric said getting the > functionality in place is more important at this point as it doesn't > affect user visible interface. Ok, I'll work to get these in where applicable. thanks, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-17 23:08 ` Greg KH @ 2008-07-18 12:41 ` Tejun Heo 2008-07-18 18:49 ` Greg KH 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-07-18 12:41 UTC (permalink / raw) To: Greg KH Cc: Eric W. Biederman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg KH wrote: > Ok, I'll work to get these in where applicable. Did this get into 2.6.27? Or will this have to wait till .28? Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-18 12:41 ` Tejun Heo @ 2008-07-18 18:49 ` Greg KH 2008-07-18 20:19 ` Eric W. Biederman ` (2 more replies) 0 siblings, 3 replies; 145+ messages in thread From: Greg KH @ 2008-07-18 18:49 UTC (permalink / raw) To: Tejun Heo Cc: Eric W. Biederman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev On Fri, Jul 18, 2008 at 09:41:29PM +0900, Tejun Heo wrote: > Greg KH wrote: > > Ok, I'll work to get these in where applicable. > > Did this get into 2.6.27? Or will this have to wait till .28? I haven't sent any patches to Linus yet for 2.6.27, so it hasn't gotten there yet. And due to the intrusiveness, and the fact that this hasn't been tested at all in any build tree yet, I can't in good concious submit this for .27 either. Part of this is my fault, I know, due to vacation and work, but also lots is due to the fact that the code showed up so late in the development cycle. I'll add it to my tree, and get it some testing in the next cycle of linux-next until 2.6.27 is out, and then if it's still looking good, go into .28. Hope this helps, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-18 18:49 ` Greg KH @ 2008-07-18 20:19 ` Eric W. Biederman 2008-07-19 1:07 ` Tejun Heo 2008-08-03 6:59 ` Eric W. Biederman 2 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-18 20:19 UTC (permalink / raw) To: Greg KH Cc: Tejun Heo, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg KH <gregkh@suse.de> writes: > On Fri, Jul 18, 2008 at 09:41:29PM +0900, Tejun Heo wrote: >> Greg KH wrote: >> > Ok, I'll work to get these in where applicable. >> >> Did this get into 2.6.27? Or will this have to wait till .28? > > I haven't sent any patches to Linus yet for 2.6.27, so it hasn't gotten > there yet. > > And due to the intrusiveness, and the fact that this hasn't been tested > at all in any build tree yet, I can't in good concious submit this for > .27 either. > > Part of this is my fault, I know, due to vacation and work, but also > lots is due to the fact that the code showed up so late in the > development cycle. The code showed up at least by the beginning of may, and the code has been around for 9 months or more. I just haven't always had the energy to retransmit every time it has gotten dropped. The last spin of it was very late I agree. > I'll add it to my tree, and get it some testing in the next cycle of > linux-next until 2.6.27 is out, and then if it's still looking good, go > into .28. I think that is unnecessarily precautions but reasonable. That should at least keep other sysfs patches from coming in and causing bit rot. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-18 18:49 ` Greg KH 2008-07-18 20:19 ` Eric W. Biederman @ 2008-07-19 1:07 ` Tejun Heo 2008-08-03 6:59 ` Eric W. Biederman 2 siblings, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-19 1:07 UTC (permalink / raw) To: Greg KH Cc: Eric W. Biederman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Hello, Greg. Greg KH wrote: > On Fri, Jul 18, 2008 at 09:41:29PM +0900, Tejun Heo wrote: >> Greg KH wrote: >>> Ok, I'll work to get these in where applicable. >> Did this get into 2.6.27? Or will this have to wait till .28? > > I haven't sent any patches to Linus yet for 2.6.27, so it hasn't gotten > there yet. > > And due to the intrusiveness, and the fact that this hasn't been tested > at all in any build tree yet, I can't in good concious submit this for > .27 either. > > Part of this is my fault, I know, due to vacation and work, but also > lots is due to the fact that the code showed up so late in the > development cycle. Heh... A lot of it is my fault too. Probably my share is bigger than anyone else's. Sorry Eric. > I'll add it to my tree, and get it some testing in the next cycle of > linux-next until 2.6.27 is out, and then if it's still looking good, go > into .28. I was just curious how the merge will turn out as I'm about to do a refresh pass on the sysfs locking and stuff. I'm not sure yet whether to put those changes on top of or below ns patches but if I'll always keep the ns patches updated. Thank you. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-18 18:49 ` Greg KH 2008-07-18 20:19 ` Eric W. Biederman 2008-07-19 1:07 ` Tejun Heo @ 2008-08-03 6:59 ` Eric W. Biederman 2008-09-11 12:45 ` Jiri Slaby 2 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-08-03 6:59 UTC (permalink / raw) To: Greg KH Cc: Tejun Heo, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg KH <gregkh@suse.de> writes: > I'll add it to my tree, and get it some testing in the next cycle of > linux-next until 2.6.27 is out, and then if it's still looking good, go > into .28. Greg. Where are we at with this? I just looked at your tree and I don't perhaps I'm blind but I don't see this patches, and it looks like you at least refreshed your patches a day or two ago. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-08-03 6:59 ` Eric W. Biederman @ 2008-09-11 12:45 ` Jiri Slaby 2008-09-11 13:05 ` Benjamin Thery 0 siblings, 1 reply; 145+ messages in thread From: Jiri Slaby @ 2008-09-11 12:45 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Tejun Heo, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers Any progress here? Nothing seems reached lkml... Eric W. Biederman napsal(a): > Greg KH <gregkh@suse.de> writes: > >> I'll add it to my tree, and get it some testing in the next cycle of >> linux-next until 2.6.27 is out, and then if it's still looking good, go >> into .28. > > Greg. Where are we at with this? > > I just looked at your tree and I don't perhaps I'm blind but I don't see > this patches, and it looks like you at least refreshed your patches > a day or two ago. ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-09-11 12:45 ` Jiri Slaby @ 2008-09-11 13:05 ` Benjamin Thery 2008-09-12 6:32 ` Jiri Slaby 0 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-09-11 13:05 UTC (permalink / raw) To: Jiri Slaby Cc: Eric W. Biederman, Tejun Heo, Greg KH, linux-kernel, Al Viro, Linux Containers, Daniel Lezcano, Andrew Morton Jiri Slaby wrote: > Any progress here? Nothing seems reached lkml... Have a look at Greg's tree. :) He started to merge the last patches today. Benjamin > > Eric W. Biederman napsal(a): >> Greg KH <gregkh@suse.de> writes: >> >>> I'll add it to my tree, and get it some testing in the next cycle of >>> linux-next until 2.6.27 is out, and then if it's still looking good, go >>> into .28. >> Greg. Where are we at with this? >> >> I just looked at your tree and I don't perhaps I'm blind but I don't see >> this patches, and it looks like you at least refreshed your patches >> a day or two ago. > _______________________________________________ > Containers mailing list > Containers@lists.linux-foundation.org > https://lists.linux-foundation.org/mailman/listinfo/containers > > -- B e n j a m i n T h e r y - BULL/DT/Open Software R&D http://www.bull.com ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-09-11 13:05 ` Benjamin Thery @ 2008-09-12 6:32 ` Jiri Slaby 0 siblings, 0 replies; 145+ messages in thread From: Jiri Slaby @ 2008-09-12 6:32 UTC (permalink / raw) To: Benjamin Thery Cc: Eric W. Biederman, Tejun Heo, Greg KH, linux-kernel, Al Viro, Linux Containers, Daniel Lezcano, Andrew Morton Benjamin Thery napsal(a): > Jiri Slaby wrote: >> Any progress here? Nothing seems reached lkml... > > Have a look at Greg's tree. :) > He started to merge the last patches today. Cool! I pulled it 10 mins before I sent the email and it wasn't there. 5 mins after it, it was... Thanks. ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 12/15] driver core: Implement tagged directory support for device classes. 2008-07-04 13:57 ` Tejun Heo 2008-07-04 16:12 ` Greg KH @ 2008-07-04 22:00 ` Eric W. Biederman 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 22:00 UTC (permalink / raw) To: Tejun Heo Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Tejun Heo <htejun@gmail.com> writes: > Yeah, it seems we should agree to disagree here. I think using callback > for static values is a really bad idea. It obfuscates the code and > opens up a big hole for awful misuses. Greg, what do you think? The misuse argument is small because currently all users must be compiled into the kernel and must add to the static enumeration. I'm afraid we are making the facility over general for the problem at hand. > As we're very close to rc1 window, I think we can work out a solution > here. The reason why I nack'd was because the change wouldn't take too > much effort and I thought it could be done before -rc1. Unless you > disagree with making tags static values, I'll try to write up a patch to > do so. If you (and Greg) think the callback interface is better, we can > merge the code as-is and update (or not) later. Making a change and pushing down into the patches is much more time intensive then I would like. The last round of changes simple as they were took something between 16 and 30 hours, and has left me sapped. Keeping all of the other pieces in flight in all of the other patches so I can't just focus on the change at hand is what makes it difficult at this point. Adding an additional patch on top isn't too bad, but my creativity is sapped on this right now. I agree that a function called device_rename isn't the best possible name when we are changing tags, but I can't think of anything that seems better. I know in the users that the tags are already quite static and that I call kobject_rename in the one case where they change (which is a significant exception). So that part doesn't concern me as I have not intention of using the interface like that. Ultimately I don't care as long as we have code that works. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 09/15] sysfs: Implement sysfs tagged directory support. 2008-07-04 1:16 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Eric W. Biederman 2008-07-04 1:17 ` [PATCH 10/15] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman @ 2008-08-20 2:17 ` Greg KH 2008-08-20 6:58 ` Eric W. Biederman 2008-08-21 6:31 ` [PATCH 0/8] sysfs namespace support Eric W. Biederman 1 sibling, 2 replies; 145+ messages in thread From: Greg KH @ 2008-08-20 2:17 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev On Thu, Jul 03, 2008 at 06:16:08PM -0700, Eric W. Biederman wrote: > > The problem. When implementing a network namespace I need to be able > to have multiple network devices with the same name. Currently this > is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and > potentially a few other directories of the form /sys/ ... /net/*. <snip> I applied the patches up to here (well, patch 8 was no longer needed at all anymore), but this one doesn't apply at all. Care to respin these last few patches? thanks, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 09/15] sysfs: Implement sysfs tagged directory support. 2008-08-20 2:17 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Greg KH @ 2008-08-20 6:58 ` Eric W. Biederman 2008-08-21 6:31 ` [PATCH 0/8] sysfs namespace support Eric W. Biederman 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-20 6:58 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg KH <greg@kroah.com> writes: > On Thu, Jul 03, 2008 at 06:16:08PM -0700, Eric W. Biederman wrote: >> >> The problem. When implementing a network namespace I need to be able >> to have multiple network devices with the same name. Currently this >> is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and >> potentially a few other directories of the form /sys/ ... /net/*. > > <snip> > > I applied the patches up to here (well, patch 8 was no longer needed at > all anymore), but this one doesn't apply at all. > > Care to respin these last few patches? Sounds like a plan. Looks like we are just talking about the driver core patches so while a pain it actually should not be too hard. I will get a copy of your gregkh tree from kernel.org tomorrow and see what I can do. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 0/8] sysfs namespace support 2008-08-20 2:17 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Greg KH 2008-08-20 6:58 ` Eric W. Biederman @ 2008-08-21 6:31 ` Eric W. Biederman 2008-08-21 6:33 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Eric W. Biederman 2008-08-21 6:37 ` [PATCH 0/8] sysfs namespace support David Miller 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:31 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Greg the first 4 patches are the rest of the infrastructure. Everything rebased quite nicely. All of the conflicts appear to have been false positives. With the addition of sysfs_rename_link sysfs_create_link_nowarn is never called so we can remove it. I'm not really certain whose tree the last netns or the user namespace changes should live in, but I am continuing to have those patches in this patchset for completeness. Eric W. Biederman (7): 1 sysfs: Implement sysfs tagged directory support. 2 sysfs: Merge sysfs_rename_dir and sysfs_move_dir 3 sysfs: Implement sysfs_delete_link and sysfs_rename_link 4 driver core: Implement tagged directory support for device classes. 5 sysfs: Remove sysfs_create_link_nowarn 6 Revert "netns: Fix device renaming for sysfs" 7 netns: Enable tagging for net_class directories in sysfs Serge Hallyn (1): 8 sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-08-21 6:31 ` [PATCH 0/8] sysfs namespace support Eric W. Biederman @ 2008-08-21 6:33 ` Eric W. Biederman 2008-08-21 6:34 ` [PATCH 2/8] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman 2008-08-27 15:18 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Benjamin Thery 2008-08-21 6:37 ` [PATCH 0/8] sysfs namespace support David Miller 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:33 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev The problem. When implementing a network namespace I need to be able to have multiple network devices with the same name. Currently this is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and potentially a few other directories of the form /sys/ ... /net/*. What this patch does is to add an additional tag field to the sysfs dirent structure. For directories that should show different contents depending on the context such as /sys/class/net/, and /sys/devices/virtual/net/ this tag field is used to specify the context in which those directories should be visible. Effectively this is the same as creating multiple distinct directories with the same name but internally to sysfs the result is nicer. I am calling the concept of a single directory that looks like multiple directories all at the same path in the filesystem tagged directories. For the networking namespace the set of directories whose contents I need to filter with tags can depend on the presence or absence of hotplug hardware or which modules are currently loaded. Which means I need a simple race free way to setup those directories as tagged. To achieve a reace free design all tagged directories are created and managed by sysfs itself. Users of this interface: - define a type in the sysfs_tag_type enumeration. - call sysfs_register_tag_types with the type and it's operations - call sysfs_make_tagged_dir with the tag type on directories to be managed by this tag type - sysfs_exit_tag when an individual tag is no longer valid - Implement mount_tag() which returns the tag of the calling process so we can attach it to a sysfs superblock. - Implement ktype.sysfs_tag() which returns the tag of a syfs kobject. Everything else is left up to sysfs and the driver layer. For the network namespace mount_tag and sysfs_tag are essentially one line functions, and look to remain that. Tags are currently represented a const void * pointers as that is both generic, prevides enough information for equality comparisons, and is trivial to create for current users, as it is just the existing namespace pointer. The work needed in sysfs is more extensive. At each directory or symlink creating I need to check if the directory it is being created in is a tagged directory and if so generate the appropriate tag to place on the sysfs_dirent. Likewise at each symlink or directory removal I need to check if the sysfs directory it is being removed from is a tagged directory and if so figure out which tag goes along with the name I am deleting. Currently only directories which hold kobjects, and symlinks are supported. There is not enough information in the current file attribute interfaces to give us anything to discriminate on which makes it useless, and there are no potential users which makes it an uninteresting problem to solve. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/bin.c | 2 +- fs/sysfs/dir.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- fs/sysfs/file.c | 11 +++-- fs/sysfs/group.c | 4 +- fs/sysfs/inode.c | 7 ++- fs/sysfs/mount.c | 115 +++++++++++++++++++++++++++++++++++++-- fs/sysfs/symlink.c | 2 +- fs/sysfs/sysfs.h | 19 ++++++- include/linux/kobject.h | 1 + include/linux/sysfs.h | 31 +++++++++++ 10 files changed, 298 insertions(+), 33 deletions(-) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 006fc64..86e1128 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -252,7 +252,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) { - sysfs_hash_and_remove(kobj->sd, attr->attr.name); + sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_create_bin_file); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 4ffcfd2..dec7586 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -30,6 +30,30 @@ DEFINE_SPINLOCK(sysfs_assoc_lock); static DEFINE_SPINLOCK(sysfs_ino_lock); static DEFINE_IDA(sysfs_ino_ida); +static const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, + struct sysfs_dirent *sd) +{ + const void *tag = NULL; + + if (sysfs_tag_type(parent_sd)) { + struct kobject *kobj; + switch (sysfs_type(sd)) { + case SYSFS_DIR: + kobj = sd->s_dir.kobj; + break; + case SYSFS_KOBJ_LINK: + kobj = sd->s_symlink.target_sd->s_dir.kobj; + break; + default: + BUG(); + } + tag = kobj->ktype->sysfs_tag(kobj); + /* NULL tags are reserved for internal use */ + BUG_ON(tag == NULL); + } + return tag; +} + /** * sysfs_link_sibling - link sysfs_dirent into sibling list * @sd: sysfs_dirent of interest @@ -101,8 +125,19 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) struct dentry *sysfs_get_dentry(struct super_block *sb, struct sysfs_dirent *sd) { - struct dentry *dentry = dget(sb->s_root); + struct dentry *dentry; + + /* Bail if this sd won't show up in this superblock */ + if (sd->s_parent) { + enum sysfs_tag_type type; + const void *tag; + type = sysfs_tag_type(sd->s_parent); + tag = sysfs_info(sb)->tag[type]; + if (sd->s_tag != tag) + return ERR_PTR(-EXDEV); + } + dentry = dget(sb->s_root); while (dentry->d_fsdata != sd) { struct sysfs_dirent *cur; struct dentry *parent; @@ -421,10 +456,15 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, */ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) + const void *tag = NULL; + + tag = sysfs_creation_tag(acxt->parent_sd, sd); + + if (sysfs_find_dirent(acxt->parent_sd, tag, sd->s_name)) return -EEXIST; sd->s_parent = sysfs_get(acxt->parent_sd); + sd->s_tag = tag; if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) inc_nlink(acxt->parent_inode); @@ -602,13 +642,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) * Pointer to sysfs_dirent if found, NULL if not. */ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const void *tag, const unsigned char *name) { struct sysfs_dirent *sd; - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { + if (sd->s_tag != tag) + continue; if (!strcmp(sd->s_name, name)) return sd; + } return NULL; } @@ -632,7 +676,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, struct sysfs_dirent *sd; mutex_lock(&sysfs_mutex); - sd = sysfs_find_dirent(parent_sd, name); + sd = sysfs_find_dirent(parent_sd, NULL, name); sysfs_get(sd); mutex_unlock(&sysfs_mutex); @@ -699,13 +743,18 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret = NULL; - struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; + struct dentry *parent = dentry->d_parent; + struct sysfs_dirent *parent_sd = parent->d_fsdata; struct sysfs_dirent *sd; struct inode *inode; + enum sysfs_tag_type type; + const void *tag; mutex_lock(&sysfs_mutex); - sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); + type = sysfs_tag_type(parent_sd); + tag = sysfs_info(parent->d_sb)->tag[type]; + sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); /* no such entry */ if (!sd) { @@ -913,19 +962,24 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) struct sysfs_rename_struct *srs; struct inode *parent_inode = NULL; const char *dup_name = NULL; + const void *old_tag, *tag; int error; INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); + old_tag = sd->s_tag; + tag = sysfs_creation_tag(sd->s_parent, sd); error = 0; - if (strcmp(sd->s_name, new_name) == 0) + if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) goto out; /* nothing to rename */ sysfs_grab_supers(); - error = prep_rename(&todo, sd, sd->s_parent, new_name); - if (error) - goto out_release; + if (old_tag == tag) { + error = prep_rename(&todo, sd, sd->s_parent, new_name); + if (error) + goto out_release; + } error = -ENOMEM; mutex_lock(&sysfs_mutex); @@ -938,7 +992,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(sd->s_parent, new_name)) + if (sysfs_find_dirent(sd->s_parent, tag, new_name)) goto out_unlock; /* rename sysfs_dirent */ @@ -949,6 +1003,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) dup_name = sd->s_name; sd->s_name = new_name; + sd->s_tag = tag; /* rename */ list_for_each_entry(srs, &todo, list) { @@ -956,6 +1011,20 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) d_move(srs->old_dentry, srs->new_dentry); } + /* If we are moving across superblocks drop the dcache entries */ + if (old_tag != tag) { + struct super_block *sb; + struct dentry *dentry; + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + dentry = __sysfs_get_dentry(sb, sd); + if (!dentry) + continue; + shrink_dcache_parent(dentry); + d_drop(dentry); + dput(dentry); + } + } + error = 0; out_unlock: mutex_unlock(&sysfs_mutex); @@ -978,11 +1047,13 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) struct sysfs_rename_struct *srs; struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; int error; + const void *tag; INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; + tag = sd->s_tag; error = 0; if (sd->s_parent == new_parent_sd) @@ -1016,7 +1087,7 @@ again: mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) + if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) goto out_unlock; error = 0; @@ -1055,10 +1126,12 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd) static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_path.dentry; - struct sysfs_dirent * parent_sd = dentry->d_fsdata; + struct dentry *parent = filp->f_path.dentry; + struct sysfs_dirent *parent_sd = parent->d_fsdata; struct sysfs_dirent *pos; ino_t ino; + enum sysfs_tag_type type; + const void *tag; if (filp->f_pos == 0) { ino = parent_sd->s_ino; @@ -1076,6 +1149,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { mutex_lock(&sysfs_mutex); + type = sysfs_tag_type(parent_sd); + tag = sysfs_info(parent->d_sb)->tag[type]; + /* Skip the dentries we have already reported */ pos = parent_sd->s_dir.children; while (pos && (filp->f_pos > pos->s_ino)) @@ -1085,6 +1161,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) const char * name; int len; + if (pos->s_tag != tag) + continue; + name = pos->s_name; len = strlen(name); filp->f_pos = ino = pos->s_ino; @@ -1105,3 +1184,35 @@ const struct file_operations sysfs_dir_operations = { .read = generic_read_dir, .readdir = sysfs_readdir, }; + +/** + * sysfs_make_tagged_dir - Require tags of all the entries in a directory. + * @kobj: object whose children should be filtered by tags + * + * Once tagging has been enabled on a directory the contents + * of the directory become dependent upon context captured when + * sysfs was mounted. + */ +int sysfs_make_tagged_dir(struct kobject *kobj, enum sysfs_tag_type type) +{ + struct sysfs_dirent *sd; + int err; + + err = -ENOENT; + sd = kobj->sd; + + mutex_lock(&sysfs_mutex); + err = -EINVAL; + /* We can only enable tagging when we have a valid tag type + * on empty directories where taggint has not already been + * enabled. + */ + if ((type > SYSFS_TAG_TYPE_NONE) && (type < SYSFS_TAG_TYPES) && + tag_ops[type] && !sysfs_tag_type(sd) && + (sysfs_type(sd) == SYSFS_DIR) && !sd->s_dir.children) { + err = 0; + sd->s_flags |= (type << SYSFS_TAG_TYPE_SHIFT); + } + mutex_unlock(&sysfs_mutex); + return err; +} diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 61c3476..091c0de 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -476,9 +476,12 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr) mutex_lock(&sysfs_mutex); if (sd && dir) - sd = sysfs_find_dirent(sd, dir); + /* Only directories are tagged, so no need to pass + * a tag explicitly. + */ + sd = sysfs_find_dirent(sd, NULL, dir); if (sd && attr) - sd = sysfs_find_dirent(sd, attr); + sd = sysfs_find_dirent(sd, NULL, attr); if (sd) sysfs_notify_dirent(sd); @@ -640,7 +643,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) { - sysfs_hash_and_remove(kobj->sd, attr->name); + sysfs_hash_and_remove(kobj, kobj->sd, attr->name); } @@ -660,7 +663,7 @@ void sysfs_remove_file_from_group(struct kobject *kobj, else dir_sd = sysfs_get(kobj->sd); if (dir_sd) { - sysfs_hash_and_remove(dir_sd, attr->name); + sysfs_hash_and_remove(kobj, dir_sd, attr->name); sysfs_put(dir_sd); } } diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index fe61194..5fba6f2 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, int i; for (i = 0, attr = grp->attrs; *attr; i++, attr++) - sysfs_hash_and_remove(dir_sd, (*attr)->name); + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); } static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, * visibility. Do this by first removing then * re-adding (if required) the file */ if (update) - sysfs_hash_and_remove(dir_sd, (*attr)->name); + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); if (grp->is_visible) { mode = grp->is_visible(kobj, *attr, i); if (!mode) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 80f8fd4..b5fc78a 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -226,17 +226,20 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) return inode; } -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, + const char *name) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; + const void *tag; if (!dir_sd) return -ENOENT; sysfs_addrm_start(&acxt, dir_sd); + tag = kobj->sd->s_tag; - sd = sysfs_find_dirent(dir_sd, name); + sd = sysfs_find_dirent(dir_sd, tag, name); if (sd) sysfs_remove_one(&acxt, sd); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 6ebda1a..8f2237a 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -35,12 +35,15 @@ static const struct super_operations sysfs_ops = { struct sysfs_dirent sysfs_root = { .s_name = "", .s_count = ATOMIC_INIT(1), - .s_flags = SYSFS_DIR, + .s_flags = SYSFS_DIR | (SYSFS_TAG_TYPE_NONE << SYSFS_TAG_TYPE_SHIFT), .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, .s_ino = 1, }; -static int sysfs_fill_super(struct super_block *sb, void *data, int silent) +struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; + +static int sysfs_fill_super(struct super_block *sb, void *data, int silent, + const void *tags[SYSFS_TAG_TYPES]) { struct sysfs_super_info *info = NULL; struct inode *inode = NULL; @@ -76,8 +79,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) goto out_err; } root->d_fsdata = &sysfs_root; + root->d_sb = sb; sb->s_root = root; sb->s_fs_info = info; + memcpy(info->tag, tags, sizeof(info->tag[0])*SYSFS_TAG_TYPES); return 0; out_err: @@ -89,20 +94,74 @@ out_err: return error; } +static int sysfs_test_super(struct super_block *sb, void *ptr) +{ + const void **tag = ptr; + struct sysfs_super_info *info = sysfs_info(sb); + enum sysfs_tag_type type; + int found = 1; + + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { + if (info->tag[type] != tag[type]) { + found = 0; + break; + } + } + + return found; +} + static int sysfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - int rc; + const void *tag[SYSFS_TAG_TYPES]; + struct super_block *sb; + int error; + enum sysfs_tag_type type; + + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { + tag[type] = NULL; + if (!tag_ops[type]) + continue; + tag[type] = tag_ops[type]->mount_tag(); + } + mutex_lock(&sysfs_rename_mutex); - rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + sb = sget(fs_type, sysfs_test_super, set_anon_super, tag); + if (IS_ERR(sb)) { + error = PTR_ERR(sb); + goto out; + } + if (!sb->s_root) { + sb->s_flags = flags; + error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0, + tag); + if (error) { + up_write(&sb->s_umount); + deactivate_super(sb); + goto out; + } + sb->s_flags |= MS_ACTIVE; + } + do_remount_sb(sb, flags, data, 0); + error = simple_set_mnt(mnt, sb); +out: mutex_unlock(&sysfs_rename_mutex); - return rc; + return error; +} + +static void sysfs_kill_sb(struct super_block *sb) +{ + struct sysfs_super_info *info = sysfs_info(sb); + + kill_anon_super(sb); + kfree(info); } struct file_system_type sysfs_fs_type = { .name = "sysfs", .get_sb = sysfs_get_sb, - .kill_sb = kill_anon_super, + .kill_sb = sysfs_kill_sb, }; void sysfs_grab_supers(void) @@ -146,6 +205,50 @@ restart: spin_unlock(&sb_lock); } +int sysfs_register_tag_type(enum sysfs_tag_type type, struct sysfs_tag_type_operations *ops) +{ + int error; + + mutex_lock(&sysfs_rename_mutex); + + error = -EINVAL; + if (type >= SYSFS_TAG_TYPES) + goto out; + + error = -EINVAL; + if (type <= SYSFS_TAG_TYPE_NONE) + goto out; + + error = -EBUSY; + if (tag_ops[type]) + goto out; + + error = 0; + tag_ops[type] = ops; + +out: + mutex_unlock(&sysfs_rename_mutex); + return error; +} + +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) +{ + /* Allow the tag to go away while sysfs is still mounted. */ + struct super_block *sb; + mutex_lock(&sysfs_rename_mutex); + sysfs_grab_supers(); + mutex_lock(&sysfs_mutex); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + struct sysfs_super_info *info = sysfs_info(sb); + if (info->tag[type] != tag) + continue; + info->tag[type] = NULL; + } + mutex_unlock(&sysfs_mutex); + sysfs_release_supers(); + mutex_unlock(&sysfs_rename_mutex); +} + int __init sysfs_init(void) { int err = -ENOMEM; diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index a3ba217..54b2e5f 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -119,7 +119,7 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) else parent_sd = kobj->sd; - sysfs_hash_and_remove(parent_sd, name); + sysfs_hash_and_remove(kobj, parent_sd, name); } static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index f0e5ecb..67115ec 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -45,6 +45,7 @@ struct sysfs_dirent { struct sysfs_dirent *s_sibling; const char *s_name; + const void *s_tag; union { struct sysfs_elem_dir s_dir; struct sysfs_elem_symlink s_symlink; @@ -67,14 +68,22 @@ struct sysfs_dirent { #define SYSFS_KOBJ_LINK 0x0008 #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK -#define SYSFS_FLAG_REMOVED 0x0200 +#define SYSFS_TAG_TYPE_MASK 0xff00 +#define SYSFS_TAG_TYPE_SHIFT 8 + +#define SYSFS_FLAG_MASK ~(SYSFS_TYPE_MASK | SYSFS_TAG_TYPE_MASK) +#define SYSFS_FLAG_REMOVED 0x020000 static inline unsigned int sysfs_type(struct sysfs_dirent *sd) { return sd->s_flags & SYSFS_TYPE_MASK; } +static inline enum sysfs_tag_type sysfs_tag_type(struct sysfs_dirent *sd) +{ + return (sd->s_flags & SYSFS_TAG_TYPE_MASK) >> SYSFS_TAG_TYPE_SHIFT; +} + /* * Context structure to be used while adding/removing nodes. */ @@ -87,6 +96,7 @@ struct sysfs_addrm_cxt { struct sysfs_super_info { int grabbed; + const void *tag[SYSFS_TAG_TYPES]; }; #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) @@ -98,6 +108,7 @@ extern struct sysfs_dirent sysfs_root; extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; extern struct file_system_type sysfs_fs_type; +extern struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; void sysfs_grab_supers(void); void sysfs_release_supers(void); @@ -124,6 +135,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const void *tag, const unsigned char *name); struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name); @@ -158,7 +170,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) struct inode *sysfs_get_inode(struct sysfs_dirent *sd); int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, + const char *name); int sysfs_inode_init(void); /* diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 5437ac0..beb3573 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -105,6 +105,7 @@ struct kobj_type { void (*release)(struct kobject *kobj); struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; + const void *(*sysfs_tag)(struct kobject *kobj); }; struct kobj_uevent_env { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d8e0230..ba68829 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -80,6 +80,15 @@ struct sysfs_ops { struct sysfs_dirent; +enum sysfs_tag_type { + SYSFS_TAG_TYPE_NONE = 0, + SYSFS_TAG_TYPES +}; + +struct sysfs_tag_type_operations { + const void *(*mount_tag)(void); +}; + #ifdef CONFIG_SYSFS int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), @@ -126,6 +135,12 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); void sysfs_put(struct sysfs_dirent *sd); void sysfs_printk_last_file(void); + +int sysfs_make_tagged_dir(struct kobject *, enum sysfs_tag_type tag_type); +int sysfs_register_tag_type(enum sysfs_tag_type type, + struct sysfs_tag_type_operations *ops); +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag); + int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ @@ -249,6 +264,22 @@ static inline void sysfs_put(struct sysfs_dirent *sd) { } +staticn inline int sysfs_make_tagged_dir(struct kobject *kobj, + enum sysfs_tag_type tag_type) +{ + return 0; +} + +static inline int sysfs_register_tag_type(enum sysfs_tag_type type, + struct sysfs_tag_type_operations *ops) +{ + return 0; +} + +static inline void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) +{ +} + static inline int __must_check sysfs_init(void) { return 0; -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 2/8] sysfs: Merge sysfs_rename_dir and sysfs_move_dir 2008-08-21 6:33 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Eric W. Biederman @ 2008-08-21 6:34 ` Eric W. Biederman 2008-08-21 6:35 ` [PATCH 3/8] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman 2008-08-27 15:18 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Benjamin Thery 1 sibling, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:34 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev These two functions do 90% of the same work and it doesn't significantly obfuscate the function to allow both the parent dir and the name to change at the same time. So merge them together to simplify maintenance, and increase testing. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/dir.c | 121 +++++++++++++++++-------------------------------------- 1 files changed, 38 insertions(+), 83 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index dec7586..a76fb54 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -955,44 +955,57 @@ err_out: return error; } -int sysfs_rename_dir(struct kobject * kobj, const char *new_name) +static int sysfs_mv_dir(struct sysfs_dirent *sd, + struct sysfs_dirent *new_parent_sd, const char *new_name) { - struct sysfs_dirent *sd = kobj->sd; struct list_head todo; struct sysfs_rename_struct *srs; - struct inode *parent_inode = NULL; + struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; const char *dup_name = NULL; const void *old_tag, *tag; int error; INIT_LIST_HEAD(&todo); + BUG_ON(!sd->s_parent); mutex_lock(&sysfs_rename_mutex); + if (!new_parent_sd) + new_parent_sd = &sysfs_root; + old_tag = sd->s_tag; tag = sysfs_creation_tag(sd->s_parent, sd); error = 0; - if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) - goto out; /* nothing to rename */ + if ((sd->s_parent == new_parent_sd) && (old_tag == tag) && + (strcmp(sd->s_name, new_name) == 0)) + goto out; /* nothing to do */ sysfs_grab_supers(); if (old_tag == tag) { - error = prep_rename(&todo, sd, sd->s_parent, new_name); + error = prep_rename(&todo, sd, new_parent_sd, new_name); if (error) goto out_release; } error = -ENOMEM; mutex_lock(&sysfs_mutex); - parent_inode = sysfs_get_inode(sd->s_parent); + old_parent_inode = sysfs_get_inode(sd->s_parent); + new_parent_inode = sysfs_get_inode(new_parent_sd); mutex_unlock(&sysfs_mutex); - if (!parent_inode) + if (!old_parent_inode || !new_parent_inode) goto out_release; - mutex_lock(&parent_inode->i_mutex); +again: + mutex_lock(&old_parent_inode->i_mutex); + if (old_parent_inode != new_parent_inode) { + if (!mutex_trylock(&new_parent_inode->i_mutex)) { + mutex_unlock(&old_parent_inode->i_mutex); + goto again; + } + } mutex_lock(&sysfs_mutex); error = -EEXIST; - if (sysfs_find_dirent(sd->s_parent, tag, new_name)) + if (sysfs_find_dirent(new_parent_sd, tag, new_name)) goto out_unlock; /* rename sysfs_dirent */ @@ -1005,7 +1018,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) sd->s_name = new_name; sd->s_tag = tag; - /* rename */ + /* rename dcache entries */ list_for_each_entry(srs, &todo, list) { d_add(srs->new_dentry, NULL); d_move(srs->old_dentry, srs->new_dentry); @@ -1025,77 +1038,6 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) } } - error = 0; -out_unlock: - mutex_unlock(&sysfs_mutex); - mutex_unlock(&parent_inode->i_mutex); - kfree(dup_name); -out_release: - iput(parent_inode); - post_rename(&todo); - sysfs_release_supers(); -out: - mutex_unlock(&sysfs_rename_mutex); - return error; -} - -int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) -{ - struct sysfs_dirent *sd = kobj->sd; - struct sysfs_dirent *new_parent_sd; - struct list_head todo; - struct sysfs_rename_struct *srs; - struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; - int error; - const void *tag; - - INIT_LIST_HEAD(&todo); - mutex_lock(&sysfs_rename_mutex); - BUG_ON(!sd->s_parent); - new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; - tag = sd->s_tag; - - error = 0; - if (sd->s_parent == new_parent_sd) - goto out; /* nothing to move */ - - sysfs_grab_supers(); - error = prep_rename(&todo, sd, new_parent_sd, sd->s_name); - if (error) - goto out_release; - - error = -ENOMEM; - mutex_lock(&sysfs_mutex); - old_parent_inode = sysfs_get_inode(sd->s_parent); - mutex_unlock(&sysfs_mutex); - if (!old_parent_inode) - goto out_release; - - error = -ENOMEM; - mutex_lock(&sysfs_mutex); - new_parent_inode = sysfs_get_inode(new_parent_sd); - mutex_unlock(&sysfs_mutex); - if (!new_parent_inode) - goto out_release; - -again: - mutex_lock(&old_parent_inode->i_mutex); - if (!mutex_trylock(&new_parent_inode->i_mutex)) { - mutex_unlock(&old_parent_inode->i_mutex); - goto again; - } - mutex_lock(&sysfs_mutex); - - error = -EEXIST; - if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) - goto out_unlock; - - error = 0; - list_for_each_entry(srs, &todo, list) { - d_add(srs->new_dentry, NULL); - d_move(srs->old_dentry, srs->new_dentry); - } - /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); sysfs_get(new_parent_sd); @@ -1103,10 +1045,13 @@ again: sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); + error = 0; out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&new_parent_inode->i_mutex); + if (new_parent_inode != old_parent_inode) + mutex_unlock(&new_parent_inode->i_mutex); mutex_unlock(&old_parent_inode->i_mutex); + kfree(dup_name); out_release: iput(new_parent_inode); @@ -1118,6 +1063,16 @@ out: return error; } +int sysfs_rename_dir(struct kobject * kobj, const char *new_name) +{ + return sysfs_mv_dir(kobj->sd, kobj->sd->s_parent, new_name); +} + +int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) +{ + return sysfs_mv_dir(kobj->sd, new_parent_kobj->sd, kobj->sd->s_name); +} + /* Relationship between s_mode and the DT_xxx types */ static inline unsigned char dt_type(struct sysfs_dirent *sd) { -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 3/8] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-08-21 6:34 ` [PATCH 2/8] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman @ 2008-08-21 6:35 ` Eric W. Biederman 2008-08-21 6:36 ` [PATCH 5/8] sysfs: Remove sysfs_create_link_nowarn Eric W. Biederman 2008-08-21 6:37 ` [PATCH 4/8] driver core: Implement tagged directory support for device classes Eric W. Biederman 0 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:35 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev When removing a symlink sysfs_remove_link does not provide enough information to figure out which tagged directory the symlink falls in. So I need sysfs_delete_link which is passed the target of the symlink to delete. Further half the time when we are removing a symlink the code is actually renaming the symlink but not doing so explicitly because we don't have a symlink rename method. So I have added sysfs_rename_link as well. Both of these functions now have enough information to find a symlink in a tagged directory. The only restriction is that they must be called before the target kobject is renamed or deleted. If they are called later I loose track of which tag the target kobject was marked with and can no longer find the old symlink to remove it. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> --- fs/sysfs/symlink.c | 31 +++++++++++++++++++++++++++++++ include/linux/sysfs.h | 17 +++++++++++++++++ 2 files changed, 48 insertions(+), 0 deletions(-) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 54b2e5f..2a64645 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -105,6 +105,21 @@ int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, } /** + * sysfs_delete_link - remove symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @name: name of the symlink to remove. + * + * Unlike sysfs_remove_link sysfs_delete_link has enough information + * to successfully delete symlinks in tagged directories. + */ +void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, + const char *name) +{ + sysfs_hash_and_remove(targ, kobj->sd, name); +} + +/** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for. * @name: name of the symlink to remove. @@ -122,6 +137,22 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) sysfs_hash_and_remove(kobj, parent_sd, name); } +/** + * sysfs_rename_link - rename symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @old: previous name of the symlink. + * @new: new name of the symlink. + * + * A helper function for the common rename symlink idiom. + */ +int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, + const char *old, const char *new) +{ + sysfs_delete_link(kobj, targ, old); + return sysfs_create_link(kobj, targ, new); +} + static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd, char *path) { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index ba68829..1204d45 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -117,6 +117,12 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj, const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); +int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name); + +void sysfs_delete_link(struct kobject *dir, struct kobject *targ, + const char *name); + int __must_check sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); int sysfs_update_group(struct kobject *kobj, @@ -216,6 +222,17 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } +static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, + const char *old_name, const char *new_name) +{ + return 0; +} + +static inline void sysfs_delete_link(struct kobject *k, struct kobject *t, + const char *name) +{ +} + static inline int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 5/8] sysfs: Remove sysfs_create_link_nowarn 2008-08-21 6:35 ` [PATCH 3/8] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman @ 2008-08-21 6:36 ` Eric W. Biederman 2008-08-21 6:38 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman 2008-08-21 6:37 ` [PATCH 4/8] driver core: Implement tagged directory support for device classes Eric W. Biederman 1 sibling, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:36 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev All of the uses have been replaced by sysfs_rename_link which is a clearer primitive to is also needed for the tagged directory support. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/symlink.c | 15 --------------- include/linux/sysfs.h | 10 ---------- 2 files changed, 0 insertions(+), 25 deletions(-) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 2a64645..3c7a338 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -90,21 +90,6 @@ int sysfs_create_link(struct kobject *kobj, struct kobject *target, } /** - * sysfs_create_link_nowarn - create symlink between two objects. - * @kobj: object whose directory we're creating the link in. - * @target: object we're pointing to. - * @name: name of the symlink. - * - * This function does the same as sysf_create_link(), but it - * doesn't warn if the link already exists. - */ -int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, - const char *name) -{ - return sysfs_do_create_link(kobj, target, name, 0); -} - -/** * sysfs_delete_link - remove symlink in object's directory. * @kobj: object we're acting for. * @targ: object we're pointing to. diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 1204d45..4e1bfdb 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -112,9 +112,6 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name); -int __must_check sysfs_create_link_nowarn(struct kobject *kobj, - struct kobject *target, - const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); int sysfs_rename_link(struct kobject *kobj, struct kobject *target, @@ -211,13 +208,6 @@ static inline int sysfs_create_link(struct kobject *kobj, return 0; } -static inline int sysfs_create_link_nowarn(struct kobject *kobj, - struct kobject *target, - const char *name) -{ - return 0; -} - static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" 2008-08-21 6:36 ` [PATCH 5/8] sysfs: Remove sysfs_create_link_nowarn Eric W. Biederman @ 2008-08-21 6:38 ` Eric W. Biederman 2008-08-21 6:39 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman 2008-08-21 6:47 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" David Miller 0 siblings, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:38 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev This reverts commit aaf8cdc34ddba08122f02217d9d684e2f9f5d575. Drivers like the ipw2100 call device_create_group when they are initialized and device_remove_group when they are shutdown. Moving them between namespaces deletes their sysfs groups early. In particular the following call chain results. netdev_unregister_kobject -> device_del -> kobject_del -> sysfs_remove_dir With sysfs_remove_dir recursively deleting all of it's subdirectories, and nothing adding them back. Ouch! Therefore we need to call something that ultimate calls sysfs_mv_dir as that sysfs function can move sysfs directories between namespaces without deleting their subdirectories or their contents. Allowing us to avoid placing extra boiler plate into every driver that does something interesting with sysfs. Currently the function that provides that capability is device_rename. That is the code works without nasty side effects as originally written. So remove the misguided fix for moving devices between namespaces. The bug in the kobject layer that inspired it has now been recognized and fixed. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- net/core/dev.c | 4 +--- net/core/net-sysfs.c | 7 +------ net/core/net-sysfs.h | 1 - 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 600bb23..a7e236c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3989,7 +3989,6 @@ int register_netdevice(struct net_device *dev) if (dev->features & NETIF_F_SG) dev->features |= NETIF_F_GSO; - netdev_initialize_kobject(dev); ret = netdev_register_kobject(dev); if (ret) goto err_uninit; @@ -4451,8 +4450,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char } /* Fixup kobjects */ - netdev_unregister_kobject(dev); - err = netdev_register_kobject(dev); + err = device_rename(&dev->dev, dev->name); WARN_ON(err); /* Add the device back in the hashes */ diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c1f4e0d..c9968f1 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -449,6 +449,7 @@ int netdev_register_kobject(struct net_device *net) struct device *dev = &(net->dev); struct attribute_group **groups = net->sysfs_groups; + device_initialize(dev); dev->class = &net_class; dev->platform_data = net; dev->groups = groups; @@ -481,12 +482,6 @@ void netdev_class_remove_file(struct class_attribute *class_attr) EXPORT_SYMBOL(netdev_class_create_file); EXPORT_SYMBOL(netdev_class_remove_file); -void netdev_initialize_kobject(struct net_device *net) -{ - struct device *device = &(net->dev); - device_initialize(device); -} - int netdev_kobject_init(void) { return class_register(&net_class); diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h index 14e7524..805555e 100644 --- a/net/core/net-sysfs.h +++ b/net/core/net-sysfs.h @@ -4,5 +4,4 @@ int netdev_kobject_init(void); int netdev_register_kobject(struct net_device *); void netdev_unregister_kobject(struct net_device *); -void netdev_initialize_kobject(struct net_device *); #endif -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs 2008-08-21 6:38 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman @ 2008-08-21 6:39 ` Eric W. Biederman 2008-08-21 6:40 ` [PATCH 8/8] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Eric W. Biederman 2008-08-21 6:47 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs David Miller 2008-08-21 6:47 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" David Miller 1 sibling, 2 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:39 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev The problem. Network devices show up in sysfs and with the network namespace active multiple devices with the same name can show up in the same directory, ouch! To avoid that problem and allow existing applications in network namespaces to see the same interface that is currently presented in sysfs, this patch enables the tagging directory support in sysfs. By using the network namespace pointers as tags to separate out the the sysfs directory entries we ensure that we don't have conflicts in the directories and applications only see a limited set of the network devices. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- include/linux/sysfs.h | 1 + net/Kconfig | 2 +- net/core/net-sysfs.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletions(-) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 4e1bfdb..6d7eb50 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -82,6 +82,7 @@ struct sysfs_dirent; enum sysfs_tag_type { SYSFS_TAG_TYPE_NONE = 0, + SYSFS_TAG_TYPE_NETNS, SYSFS_TAG_TYPES }; diff --git a/net/Kconfig b/net/Kconfig index 7612cc8..29e7e09 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -27,7 +27,7 @@ menu "Networking options" config NET_NS bool "Network namespace support" default n - depends on EXPERIMENTAL && !SYSFS && NAMESPACES + depends on EXPERIMENTAL && NAMESPACES help Allow user space to create what appear to be multiple instances of the network stack. diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c9968f1..e4687af 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -13,7 +13,9 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/if_arp.h> +#include <linux/nsproxy.h> #include <net/sock.h> +#include <net/net_namespace.h> #include <linux/rtnetlink.h> #include <linux/wireless.h> #include <net/iw_handler.h> @@ -385,6 +387,24 @@ static struct attribute_group wireless_group = { }; #endif +static const void *net_sysfs_mount_tag(void) +{ + return current->nsproxy->net_ns; +} + +static struct sysfs_tag_type_operations net_tag_type_operations = { + .mount_tag = net_sysfs_mount_tag, +}; + +static void net_sysfs_net_exit(struct net *net) +{ + sysfs_exit_tag(SYSFS_TAG_TYPE_NETNS, net); +} + +static struct pernet_operations sysfs_net_ops = { + .exit = net_sysfs_net_exit, +}; + #endif /* CONFIG_SYSFS */ #ifdef CONFIG_HOTPLUG @@ -421,6 +441,13 @@ static void netdev_release(struct device *d) kfree((char *)dev - dev->padded); } +static const void *net_sysfs_tag(struct device *d) +{ + struct net_device *dev; + dev = container_of(d, struct net_device, dev); + return dev_net(dev); +} + static struct class net_class = { .name = "net", .dev_release = netdev_release, @@ -430,6 +457,8 @@ static struct class net_class = { #ifdef CONFIG_HOTPLUG .dev_uevent = netdev_uevent, #endif + .tag_type = SYSFS_TAG_TYPE_NETNS, + .sysfs_tag = net_sysfs_tag, }; /* Delete sysfs entries but hold kobject reference until after all @@ -484,5 +513,9 @@ EXPORT_SYMBOL(netdev_class_remove_file); int netdev_kobject_init(void) { +#ifdef CONFIG_SYSFS + sysfs_register_tag_type(SYSFS_TAG_TYPE_NETNS, &net_tag_type_operations); + register_pernet_subsys(&sysfs_net_ops); +#endif return class_register(&net_class); } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* [PATCH 8/8] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched 2008-08-21 6:39 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman @ 2008-08-21 6:40 ` Eric W. Biederman 2008-08-21 6:47 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs David Miller 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:40 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev From: Serge Hallyn <serge@us.ibm.com> Mark the /sys/kernel/uids directory to be tagged so that processes in different user namespaces can remount /sys and see their own uid listings. Without this patch, having CONFIG_FAIR_SCHED=y makes user namespaces unusable, because when you clone(CLONE_NEWUSER) it will auto-create the root userid and try to create /sys/kernel/uids/0. Since that already exists from the parent user namespace, the create fails, and the clone misleadingly ends up returning -ENOMEM. This patch fixes the issue by allowing each user namespace to remount /sys, and having /sys filter the /sys/kernel/uid/ entries by user namespace. Changelong: v2 - Reworked for the updated sysfs api Signed-off-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- include/linux/sched.h | 1 + include/linux/sysfs.h | 1 + kernel/user.c | 22 ++++++++++++++++++++++ kernel/user_namespace.c | 1 + 4 files changed, 25 insertions(+), 0 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 5850bfb..b0fe15a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -600,6 +600,7 @@ struct user_struct { /* Hash table maintenance information */ struct hlist_node uidhash_node; uid_t uid; + struct user_namespace *user_ns; #ifdef CONFIG_USER_SCHED struct task_group *tg; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 6d7eb50..ac88374 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -83,6 +83,7 @@ struct sysfs_dirent; enum sysfs_tag_type { SYSFS_TAG_TYPE_NONE = 0, SYSFS_TAG_TYPE_NETNS, + SYSFS_TAG_TYPE_USERNS, SYSFS_TAG_TYPES }; diff --git a/kernel/user.c b/kernel/user.c index 865ecf5..ca29fbc 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -53,6 +53,7 @@ struct user_struct root_user = { .files = ATOMIC_INIT(0), .sigpending = ATOMIC_INIT(0), .locked_shm = 0, + .user_ns = &init_user_ns, #ifdef CONFIG_USER_SCHED .tg = &init_task_group, #endif @@ -230,16 +231,33 @@ static struct attribute *uids_attributes[] = { NULL }; +static const void *uids_mount_tag(void) +{ + return current->nsproxy->user_ns; +} + +static struct sysfs_tag_type_operations uids_tag_type_operations = { + .mount_tag = uids_mount_tag, +}; + /* the lifetime of user_struct is not managed by the core (now) */ static void uids_release(struct kobject *kobj) { return; } +static const void *uids_sysfs_tag(struct kobject *kobj) +{ + struct user_struct *up; + up = container_of(kobj, struct user_struct, kobj); + return up->user_ns; +} + static struct kobj_type uids_ktype = { .sysfs_ops = &kobj_sysfs_ops, .default_attrs = uids_attributes, .release = uids_release, + .sysfs_tag = uids_sysfs_tag, }; /* create /sys/kernel/uids/<uid>/cpu_share file for this user */ @@ -272,6 +290,9 @@ int __init uids_sysfs_init(void) if (!uids_kset) return -ENOMEM; + sysfs_register_tag_type(SYSFS_TAG_TYPE_USERNS, &uids_tag_type_operations); + sysfs_make_tagged_dir(&uids_kset->kobj, SYSFS_TAG_TYPE_USERNS); + return uids_user_create(&root_user); } @@ -405,6 +426,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) new->uid = uid; atomic_set(&new->__count, 1); + new->user_ns = ns; if (sched_create_user(new) < 0) goto out_free_user; diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index a9ab059..f67bbe0 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -71,6 +71,7 @@ void free_user_ns(struct kref *kref) struct user_namespace *ns; ns = container_of(kref, struct user_namespace, kref); + sysfs_exit_tag(SYSFS_TAG_TYPE_USERNS, ns); release_uids(ns); kfree(ns); } -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* Re: [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs 2008-08-21 6:39 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman 2008-08-21 6:40 ` [PATCH 8/8] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Eric W. Biederman @ 2008-08-21 6:47 ` David Miller 1 sibling, 0 replies; 145+ messages in thread From: David Miller @ 2008-08-21 6:47 UTC (permalink / raw) To: ebiederm Cc: greg, gregkh, akpm, htejun, dlezcano, linux-kernel, viro, containers, benjamin.thery, netdev From: ebiederm@xmission.com (Eric W. Biederman) Date: Wed, 20 Aug 2008 23:39:13 -0700 > > The problem. Network devices show up in sysfs and with the network > namespace active multiple devices with the same name can show up in > the same directory, ouch! > > To avoid that problem and allow existing applications in network namespaces > to see the same interface that is currently presented in sysfs, this > patch enables the tagging directory support in sysfs. > > By using the network namespace pointers as tags to separate out the > the sysfs directory entries we ensure that we don't have conflicts > in the directories and applications only see a limited set of > the network devices. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: David S. Miller <davem@davemloft.net> ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" 2008-08-21 6:38 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman 2008-08-21 6:39 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman @ 2008-08-21 6:47 ` David Miller 1 sibling, 0 replies; 145+ messages in thread From: David Miller @ 2008-08-21 6:47 UTC (permalink / raw) To: ebiederm Cc: greg, gregkh, akpm, htejun, dlezcano, linux-kernel, viro, containers, benjamin.thery, netdev From: ebiederm@xmission.com (Eric W. Biederman) Date: Wed, 20 Aug 2008 23:38:31 -0700 > > This reverts commit aaf8cdc34ddba08122f02217d9d684e2f9f5d575. > > Drivers like the ipw2100 call device_create_group when they > are initialized and device_remove_group when they are shutdown. > Moving them between namespaces deletes their sysfs groups early. > > In particular the following call chain results. > netdev_unregister_kobject -> device_del -> kobject_del -> sysfs_remove_dir > With sysfs_remove_dir recursively deleting all of it's subdirectories, > and nothing adding them back. > > Ouch! > > Therefore we need to call something that ultimate calls sysfs_mv_dir > as that sysfs function can move sysfs directories between namespaces > without deleting their subdirectories or their contents. Allowing > us to avoid placing extra boiler plate into every driver that does > something interesting with sysfs. > > Currently the function that provides that capability is device_rename. > That is the code works without nasty side effects as originally written. > > So remove the misguided fix for moving devices between namespaces. The > bug in the kobject layer that inspired it has now been recognized and > fixed. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: David S. Miller <davem@davemloft.net> ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 4/8] driver core: Implement tagged directory support for device classes. 2008-08-21 6:35 ` [PATCH 3/8] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman 2008-08-21 6:36 ` [PATCH 5/8] sysfs: Remove sysfs_create_link_nowarn Eric W. Biederman @ 2008-08-21 6:37 ` Eric W. Biederman 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-08-21 6:37 UTC (permalink / raw) To: Greg KH Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev This patch enables tagging on every class directory if struct class has a tag_type. In addition device_del and device_rename were modified to use sysfs_delete_link and sysfs_rename_link respectively to ensure when these operations happen on devices whose classes have tag_ops that they work properly. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- drivers/base/class.c | 30 ++++++++++++++++++++++--- drivers/base/core.c | 56 ++++++++++++++++++++++++++++++------------------ include/linux/device.h | 3 ++ 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index cc5e28c..0cd5704 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -135,6 +135,17 @@ static void remove_class_attrs(struct class *cls) } } +static int class_setup_tagging(struct class *cls) +{ + enum sysfs_tag_type type; + + type = cls->tag_type; + if (type == SYSFS_TAG_TYPE_NONE) + return 0; + + return sysfs_make_tagged_dir(&cls->p->class_subsys.kobj, type); +} + int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; @@ -171,13 +182,24 @@ int __class_register(struct class *cls, struct lock_class_key *key) cls->p = cp; error = kset_register(&cp->class_subsys); - if (error) { - kfree(cp); - return error; - } + if (error) + goto out_free_cp; + + error = class_setup_tagging(cls); + if (error) + goto out_unregister; + error = add_class_attrs(class_get(cls)); class_put(cls); + if (error) + goto out_unregister; +out: return error; +out_unregister: + kset_unregister(&cp->class_subsys); +out_free_cp: + kfree(cp); + goto out; } EXPORT_SYMBOL_GPL(__class_register); diff --git a/drivers/base/core.c b/drivers/base/core.c index 2bf7116..4fb9b00 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -122,9 +122,21 @@ static void device_release(struct kobject *kobj) dev->bus_id); } +static const void *device_sysfs_tag(struct kobject *kobj) +{ + struct device *dev = to_dev(kobj); + const void *tag = NULL; + + if (dev->class && dev->class->tag_type) + tag = dev->class->sysfs_tag(dev); + + return tag; +} + static struct kobj_type device_ktype = { .release = device_release, .sysfs_ops = &dev_sysfs_ops, + .sysfs_tag = device_sysfs_tag, }; @@ -617,6 +629,10 @@ static struct kobject *get_device_parent(struct device *dev, kobject_put(k); return NULL; } + /* If we created a new class-directory setup tagging */ + if (dev->class->tag_type) + sysfs_make_tagged_dir(k, dev->class->tag_type); + /* do not emit an uevent for this simple "glue" directory */ return k; } @@ -707,7 +723,7 @@ out_device: out_busid: if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->class_subsys.kobj, + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #else /* link in the class directory pointing to the device */ @@ -725,7 +741,7 @@ out_busid: return 0; out_busid: - sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #endif out_subsys: @@ -753,13 +769,13 @@ static void device_remove_class_symlinks(struct device *dev) if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->class_subsys.kobj, + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #else if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); - sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev->bus_id); #endif sysfs_remove_link(&dev->kobj, "subsystem"); @@ -1347,6 +1363,15 @@ int device_rename(struct device *dev, char *new_name) strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); +#ifndef CONFIG_SYSFS_DEPRECATED + if (dev->class) { + error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, old_device_name, new_name); + if (error) + goto out; + } +#endif + error = kobject_rename(&dev->kobj, new_name); if (error) { strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); @@ -1355,24 +1380,13 @@ int device_rename(struct device *dev, char *new_name) #ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { + error = -ENOMEM; new_class_name = make_class_name(dev->class->name, &dev->kobj); - if (new_class_name) { - error = sysfs_create_link_nowarn(&dev->parent->kobj, - &dev->kobj, - new_class_name); - if (error) - goto out; - sysfs_remove_link(&dev->parent->kobj, old_class_name); - } - } -#else - if (dev->class) { - error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, - &dev->kobj, dev->bus_id); - if (error) - goto out; - sysfs_remove_link(&dev->class->p->class_subsys.kobj, - old_device_name); + if (new_class_name) + error = sysfs_rename_link(&dev->parent->kobj, + &dev->kobj, + old_class_name, + new_class_name); } #endif diff --git a/include/linux/device.h b/include/linux/device.h index d6fdd60..8d65016 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -195,6 +195,9 @@ struct class { int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); + enum sysfs_tag_type tag_type; + const void *(*sysfs_tag)(struct device *dev); + struct pm_ops *pm; struct class_private *p; }; -- 1.5.3.rc6.17.g1911 ^ permalink raw reply related [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-08-21 6:33 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Eric W. Biederman 2008-08-21 6:34 ` [PATCH 2/8] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman @ 2008-08-27 15:18 ` Benjamin Thery 2008-09-02 13:54 ` Mark Ryden 1 sibling, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-08-27 15:18 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Eric W. Biederman wrote: > The problem. When implementing a network namespace I need to be able > to have multiple network devices with the same name. Currently this > is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and > potentially a few other directories of the form /sys/ ... /net/*. > > What this patch does is to add an additional tag field to the > sysfs dirent structure. For directories that should show different > contents depending on the context such as /sys/class/net/, and > /sys/devices/virtual/net/ this tag field is used to specify the > context in which those directories should be visible. Effectively > this is the same as creating multiple distinct directories with > the same name but internally to sysfs the result is nicer. > > I am calling the concept of a single directory that looks like multiple > directories all at the same path in the filesystem tagged directories. > > For the networking namespace the set of directories whose contents I need > to filter with tags can depend on the presence or absence of hotplug > hardware or which modules are currently loaded. Which means I need > a simple race free way to setup those directories as tagged. > > To achieve a reace free design all tagged directories are created > and managed by sysfs itself. > > Users of this interface: > - define a type in the sysfs_tag_type enumeration. > - call sysfs_register_tag_types with the type and it's operations > - call sysfs_make_tagged_dir with the tag type on directories > to be managed by this tag type > - sysfs_exit_tag when an individual tag is no longer valid > > - Implement mount_tag() which returns the tag of the calling process > so we can attach it to a sysfs superblock. > - Implement ktype.sysfs_tag() which returns the tag of a syfs kobject. > > Everything else is left up to sysfs and the driver layer. > > For the network namespace mount_tag and sysfs_tag are essentially > one line functions, and look to remain that. > > Tags are currently represented a const void * pointers as that is > both generic, prevides enough information for equality comparisons, > and is trivial to create for current users, as it is just the > existing namespace pointer. > > The work needed in sysfs is more extensive. At each directory > or symlink creating I need to check if the directory it is being > created in is a tagged directory and if so generate the appropriate > tag to place on the sysfs_dirent. Likewise at each symlink or > directory removal I need to check if the sysfs directory it is > being removed from is a tagged directory and if so figure out > which tag goes along with the name I am deleting. > > Currently only directories which hold kobjects, and > symlinks are supported. There is not enough information > in the current file attribute interfaces to give us anything > to discriminate on which makes it useless, and there are > no potential users which makes it an uninteresting problem > to solve. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> > Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> > --- > fs/sysfs/bin.c | 2 +- > fs/sysfs/dir.c | 139 ++++++++++++++++++++++++++++++++++++++++++----- > fs/sysfs/file.c | 11 +++-- > fs/sysfs/group.c | 4 +- > fs/sysfs/inode.c | 7 ++- > fs/sysfs/mount.c | 115 +++++++++++++++++++++++++++++++++++++-- > fs/sysfs/symlink.c | 2 +- > fs/sysfs/sysfs.h | 19 ++++++- > include/linux/kobject.h | 1 + > include/linux/sysfs.h | 31 +++++++++++ > 10 files changed, 298 insertions(+), 33 deletions(-) > > diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c > index 006fc64..86e1128 100644 > --- a/fs/sysfs/bin.c > +++ b/fs/sysfs/bin.c > @@ -252,7 +252,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) > > void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) > { > - sysfs_hash_and_remove(kobj->sd, attr->attr.name); > + sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name); > } > > EXPORT_SYMBOL_GPL(sysfs_create_bin_file); > diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c > index 4ffcfd2..dec7586 100644 > --- a/fs/sysfs/dir.c > +++ b/fs/sysfs/dir.c > @@ -30,6 +30,30 @@ DEFINE_SPINLOCK(sysfs_assoc_lock); > static DEFINE_SPINLOCK(sysfs_ino_lock); > static DEFINE_IDA(sysfs_ino_ida); > > +static const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, > + struct sysfs_dirent *sd) > +{ > + const void *tag = NULL; > + > + if (sysfs_tag_type(parent_sd)) { > + struct kobject *kobj; > + switch (sysfs_type(sd)) { > + case SYSFS_DIR: > + kobj = sd->s_dir.kobj; > + break; > + case SYSFS_KOBJ_LINK: > + kobj = sd->s_symlink.target_sd->s_dir.kobj; > + break; > + default: > + BUG(); > + } > + tag = kobj->ktype->sysfs_tag(kobj); > + /* NULL tags are reserved for internal use */ > + BUG_ON(tag == NULL); > + } > + return tag; > +} > + > /** > * sysfs_link_sibling - link sysfs_dirent into sibling list > * @sd: sysfs_dirent of interest > @@ -101,8 +125,19 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) > struct dentry *sysfs_get_dentry(struct super_block *sb, > struct sysfs_dirent *sd) > { > - struct dentry *dentry = dget(sb->s_root); > + struct dentry *dentry; > + > + /* Bail if this sd won't show up in this superblock */ > + if (sd->s_parent) { > + enum sysfs_tag_type type; > + const void *tag; > + type = sysfs_tag_type(sd->s_parent); > + tag = sysfs_info(sb)->tag[type]; > + if (sd->s_tag != tag) > + return ERR_PTR(-EXDEV); > + } > > + dentry = dget(sb->s_root); > while (dentry->d_fsdata != sd) { > struct sysfs_dirent *cur; > struct dentry *parent; > @@ -421,10 +456,15 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, > */ > int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) > { > - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) > + const void *tag = NULL; > + > + tag = sysfs_creation_tag(acxt->parent_sd, sd); > + > + if (sysfs_find_dirent(acxt->parent_sd, tag, sd->s_name)) > return -EEXIST; > > sd->s_parent = sysfs_get(acxt->parent_sd); > + sd->s_tag = tag; > > if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) > inc_nlink(acxt->parent_inode); > @@ -602,13 +642,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) > * Pointer to sysfs_dirent if found, NULL if not. > */ > struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, > + const void *tag, > const unsigned char *name) > { > struct sysfs_dirent *sd; > > - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) > + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { > + if (sd->s_tag != tag) > + continue; > if (!strcmp(sd->s_name, name)) > return sd; > + } > return NULL; > } > > @@ -632,7 +676,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, > struct sysfs_dirent *sd; > > mutex_lock(&sysfs_mutex); > - sd = sysfs_find_dirent(parent_sd, name); > + sd = sysfs_find_dirent(parent_sd, NULL, name); > sysfs_get(sd); > mutex_unlock(&sysfs_mutex); > > @@ -699,13 +743,18 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, > struct nameidata *nd) > { > struct dentry *ret = NULL; > - struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; > + struct dentry *parent = dentry->d_parent; > + struct sysfs_dirent *parent_sd = parent->d_fsdata; > struct sysfs_dirent *sd; > struct inode *inode; > + enum sysfs_tag_type type; > + const void *tag; > > mutex_lock(&sysfs_mutex); > > - sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); > + type = sysfs_tag_type(parent_sd); > + tag = sysfs_info(parent->d_sb)->tag[type]; > + sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); > > /* no such entry */ > if (!sd) { > @@ -913,19 +962,24 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) > struct sysfs_rename_struct *srs; > struct inode *parent_inode = NULL; > const char *dup_name = NULL; > + const void *old_tag, *tag; > int error; > > INIT_LIST_HEAD(&todo); > mutex_lock(&sysfs_rename_mutex); > + old_tag = sd->s_tag; > + tag = sysfs_creation_tag(sd->s_parent, sd); > > error = 0; > - if (strcmp(sd->s_name, new_name) == 0) > + if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) > goto out; /* nothing to rename */ > > sysfs_grab_supers(); > - error = prep_rename(&todo, sd, sd->s_parent, new_name); > - if (error) > - goto out_release; > + if (old_tag == tag) { > + error = prep_rename(&todo, sd, sd->s_parent, new_name); > + if (error) > + goto out_release; > + } > > error = -ENOMEM; > mutex_lock(&sysfs_mutex); > @@ -938,7 +992,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) > mutex_lock(&sysfs_mutex); > > error = -EEXIST; > - if (sysfs_find_dirent(sd->s_parent, new_name)) > + if (sysfs_find_dirent(sd->s_parent, tag, new_name)) > goto out_unlock; > > /* rename sysfs_dirent */ > @@ -949,6 +1003,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) > > dup_name = sd->s_name; > sd->s_name = new_name; > + sd->s_tag = tag; > > /* rename */ > list_for_each_entry(srs, &todo, list) { > @@ -956,6 +1011,20 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) > d_move(srs->old_dentry, srs->new_dentry); > } > > + /* If we are moving across superblocks drop the dcache entries */ > + if (old_tag != tag) { > + struct super_block *sb; > + struct dentry *dentry; > + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { > + dentry = __sysfs_get_dentry(sb, sd); > + if (!dentry) > + continue; > + shrink_dcache_parent(dentry); > + d_drop(dentry); > + dput(dentry); > + } > + } > + > error = 0; > out_unlock: > mutex_unlock(&sysfs_mutex); > @@ -978,11 +1047,13 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) > struct sysfs_rename_struct *srs; > struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; > int error; > + const void *tag; > > INIT_LIST_HEAD(&todo); > mutex_lock(&sysfs_rename_mutex); > BUG_ON(!sd->s_parent); > new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; > + tag = sd->s_tag; > > error = 0; > if (sd->s_parent == new_parent_sd) > @@ -1016,7 +1087,7 @@ again: > mutex_lock(&sysfs_mutex); > > error = -EEXIST; > - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) > + if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) > goto out_unlock; > > error = 0; > @@ -1055,10 +1126,12 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd) > > static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) > { > - struct dentry *dentry = filp->f_path.dentry; > - struct sysfs_dirent * parent_sd = dentry->d_fsdata; > + struct dentry *parent = filp->f_path.dentry; > + struct sysfs_dirent *parent_sd = parent->d_fsdata; > struct sysfs_dirent *pos; > ino_t ino; > + enum sysfs_tag_type type; > + const void *tag; > > if (filp->f_pos == 0) { > ino = parent_sd->s_ino; > @@ -1076,6 +1149,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) > if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { > mutex_lock(&sysfs_mutex); > > + type = sysfs_tag_type(parent_sd); > + tag = sysfs_info(parent->d_sb)->tag[type]; > + > /* Skip the dentries we have already reported */ > pos = parent_sd->s_dir.children; > while (pos && (filp->f_pos > pos->s_ino)) > @@ -1085,6 +1161,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) > const char * name; > int len; > > + if (pos->s_tag != tag) > + continue; > + > name = pos->s_name; > len = strlen(name); > filp->f_pos = ino = pos->s_ino; > @@ -1105,3 +1184,35 @@ const struct file_operations sysfs_dir_operations = { > .read = generic_read_dir, > .readdir = sysfs_readdir, > }; > + > +/** > + * sysfs_make_tagged_dir - Require tags of all the entries in a directory. > + * @kobj: object whose children should be filtered by tags > + * > + * Once tagging has been enabled on a directory the contents > + * of the directory become dependent upon context captured when > + * sysfs was mounted. > + */ > +int sysfs_make_tagged_dir(struct kobject *kobj, enum sysfs_tag_type type) > +{ > + struct sysfs_dirent *sd; > + int err; > + > + err = -ENOENT; > + sd = kobj->sd; > + > + mutex_lock(&sysfs_mutex); > + err = -EINVAL; > + /* We can only enable tagging when we have a valid tag type > + * on empty directories where taggint has not already been > + * enabled. > + */ > + if ((type > SYSFS_TAG_TYPE_NONE) && (type < SYSFS_TAG_TYPES) && > + tag_ops[type] && !sysfs_tag_type(sd) && > + (sysfs_type(sd) == SYSFS_DIR) && !sd->s_dir.children) { > + err = 0; > + sd->s_flags |= (type << SYSFS_TAG_TYPE_SHIFT); > + } > + mutex_unlock(&sysfs_mutex); > + return err; > +} > diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c > index 61c3476..091c0de 100644 > --- a/fs/sysfs/file.c > +++ b/fs/sysfs/file.c > @@ -476,9 +476,12 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr) > mutex_lock(&sysfs_mutex); > > if (sd && dir) > - sd = sysfs_find_dirent(sd, dir); > + /* Only directories are tagged, so no need to pass > + * a tag explicitly. > + */ > + sd = sysfs_find_dirent(sd, NULL, dir); > if (sd && attr) > - sd = sysfs_find_dirent(sd, attr); > + sd = sysfs_find_dirent(sd, NULL, attr); > if (sd) > sysfs_notify_dirent(sd); > > @@ -640,7 +643,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); > > void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) > { > - sysfs_hash_and_remove(kobj->sd, attr->name); > + sysfs_hash_and_remove(kobj, kobj->sd, attr->name); > } > > > @@ -660,7 +663,7 @@ void sysfs_remove_file_from_group(struct kobject *kobj, > else > dir_sd = sysfs_get(kobj->sd); > if (dir_sd) { > - sysfs_hash_and_remove(dir_sd, attr->name); > + sysfs_hash_and_remove(kobj, dir_sd, attr->name); > sysfs_put(dir_sd); > } > } > diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c > index fe61194..5fba6f2 100644 > --- a/fs/sysfs/group.c > +++ b/fs/sysfs/group.c > @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, > int i; > > for (i = 0, attr = grp->attrs; *attr; i++, attr++) > - sysfs_hash_and_remove(dir_sd, (*attr)->name); > + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); > } > > static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, > @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, > * visibility. Do this by first removing then > * re-adding (if required) the file */ > if (update) > - sysfs_hash_and_remove(dir_sd, (*attr)->name); > + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); > if (grp->is_visible) { > mode = grp->is_visible(kobj, *attr, i); > if (!mode) > diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c > index 80f8fd4..b5fc78a 100644 > --- a/fs/sysfs/inode.c > +++ b/fs/sysfs/inode.c > @@ -226,17 +226,20 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) > return inode; > } > > -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) > +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, > + const char *name) > { > struct sysfs_addrm_cxt acxt; > struct sysfs_dirent *sd; > + const void *tag; > > if (!dir_sd) > return -ENOENT; > > sysfs_addrm_start(&acxt, dir_sd); > + tag = kobj->sd->s_tag; > > - sd = sysfs_find_dirent(dir_sd, name); > + sd = sysfs_find_dirent(dir_sd, tag, name); > if (sd) > sysfs_remove_one(&acxt, sd); > > diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c > index 6ebda1a..8f2237a 100644 > --- a/fs/sysfs/mount.c > +++ b/fs/sysfs/mount.c > @@ -35,12 +35,15 @@ static const struct super_operations sysfs_ops = { > struct sysfs_dirent sysfs_root = { > .s_name = "", > .s_count = ATOMIC_INIT(1), > - .s_flags = SYSFS_DIR, > + .s_flags = SYSFS_DIR | (SYSFS_TAG_TYPE_NONE << SYSFS_TAG_TYPE_SHIFT), > .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, > .s_ino = 1, > }; > > -static int sysfs_fill_super(struct super_block *sb, void *data, int silent) > +struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; > + > +static int sysfs_fill_super(struct super_block *sb, void *data, int silent, > + const void *tags[SYSFS_TAG_TYPES]) > { > struct sysfs_super_info *info = NULL; > struct inode *inode = NULL; > @@ -76,8 +79,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) > goto out_err; > } > root->d_fsdata = &sysfs_root; > + root->d_sb = sb; > sb->s_root = root; > sb->s_fs_info = info; > + memcpy(info->tag, tags, sizeof(info->tag[0])*SYSFS_TAG_TYPES); > return 0; > > out_err: > @@ -89,20 +94,74 @@ out_err: > return error; > } > > +static int sysfs_test_super(struct super_block *sb, void *ptr) > +{ > + const void **tag = ptr; > + struct sysfs_super_info *info = sysfs_info(sb); > + enum sysfs_tag_type type; > + int found = 1; > + > + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { > + if (info->tag[type] != tag[type]) { > + found = 0; > + break; > + } > + } > + > + return found; > +} > + > static int sysfs_get_sb(struct file_system_type *fs_type, > int flags, const char *dev_name, void *data, struct vfsmount *mnt) > { > - int rc; > + const void *tag[SYSFS_TAG_TYPES]; > + struct super_block *sb; > + int error; > + enum sysfs_tag_type type; > + > + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { > + tag[type] = NULL; > + if (!tag_ops[type]) > + continue; > + tag[type] = tag_ops[type]->mount_tag(); > + } > + > mutex_lock(&sysfs_rename_mutex); > - rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); > + sb = sget(fs_type, sysfs_test_super, set_anon_super, tag); > + if (IS_ERR(sb)) { > + error = PTR_ERR(sb); > + goto out; > + } > + if (!sb->s_root) { > + sb->s_flags = flags; > + error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0, > + tag); > + if (error) { > + up_write(&sb->s_umount); > + deactivate_super(sb); > + goto out; > + } > + sb->s_flags |= MS_ACTIVE; > + } > + do_remount_sb(sb, flags, data, 0); > + error = simple_set_mnt(mnt, sb); > +out: > mutex_unlock(&sysfs_rename_mutex); > - return rc; > + return error; > +} > + > +static void sysfs_kill_sb(struct super_block *sb) > +{ > + struct sysfs_super_info *info = sysfs_info(sb); > + > + kill_anon_super(sb); > + kfree(info); > } > > struct file_system_type sysfs_fs_type = { > .name = "sysfs", > .get_sb = sysfs_get_sb, > - .kill_sb = kill_anon_super, > + .kill_sb = sysfs_kill_sb, > }; > > void sysfs_grab_supers(void) > @@ -146,6 +205,50 @@ restart: > spin_unlock(&sb_lock); > } > > +int sysfs_register_tag_type(enum sysfs_tag_type type, struct sysfs_tag_type_operations *ops) > +{ > + int error; > + > + mutex_lock(&sysfs_rename_mutex); > + > + error = -EINVAL; > + if (type >= SYSFS_TAG_TYPES) > + goto out; > + > + error = -EINVAL; > + if (type <= SYSFS_TAG_TYPE_NONE) > + goto out; > + > + error = -EBUSY; > + if (tag_ops[type]) > + goto out; > + > + error = 0; > + tag_ops[type] = ops; > + > +out: > + mutex_unlock(&sysfs_rename_mutex); > + return error; > +} > + > +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) > +{ > + /* Allow the tag to go away while sysfs is still mounted. */ > + struct super_block *sb; > + mutex_lock(&sysfs_rename_mutex); > + sysfs_grab_supers(); > + mutex_lock(&sysfs_mutex); > + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { > + struct sysfs_super_info *info = sysfs_info(sb); > + if (info->tag[type] != tag) > + continue; > + info->tag[type] = NULL; > + } > + mutex_unlock(&sysfs_mutex); > + sysfs_release_supers(); > + mutex_unlock(&sysfs_rename_mutex); > +} > + > int __init sysfs_init(void) > { > int err = -ENOMEM; > diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c > index a3ba217..54b2e5f 100644 > --- a/fs/sysfs/symlink.c > +++ b/fs/sysfs/symlink.c > @@ -119,7 +119,7 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) > else > parent_sd = kobj->sd; > > - sysfs_hash_and_remove(parent_sd, name); > + sysfs_hash_and_remove(kobj, parent_sd, name); > } > > static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, > diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h > index f0e5ecb..67115ec 100644 > --- a/fs/sysfs/sysfs.h > +++ b/fs/sysfs/sysfs.h > @@ -45,6 +45,7 @@ struct sysfs_dirent { > struct sysfs_dirent *s_sibling; > const char *s_name; > > + const void *s_tag; > union { > struct sysfs_elem_dir s_dir; > struct sysfs_elem_symlink s_symlink; > @@ -67,14 +68,22 @@ struct sysfs_dirent { > #define SYSFS_KOBJ_LINK 0x0008 > #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) > > -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK > -#define SYSFS_FLAG_REMOVED 0x0200 > +#define SYSFS_TAG_TYPE_MASK 0xff00 > +#define SYSFS_TAG_TYPE_SHIFT 8 > + > +#define SYSFS_FLAG_MASK ~(SYSFS_TYPE_MASK | SYSFS_TAG_TYPE_MASK) > +#define SYSFS_FLAG_REMOVED 0x020000 > > static inline unsigned int sysfs_type(struct sysfs_dirent *sd) > { > return sd->s_flags & SYSFS_TYPE_MASK; > } > > +static inline enum sysfs_tag_type sysfs_tag_type(struct sysfs_dirent *sd) > +{ > + return (sd->s_flags & SYSFS_TAG_TYPE_MASK) >> SYSFS_TAG_TYPE_SHIFT; > +} > + > /* > * Context structure to be used while adding/removing nodes. > */ > @@ -87,6 +96,7 @@ struct sysfs_addrm_cxt { > > struct sysfs_super_info { > int grabbed; > + const void *tag[SYSFS_TAG_TYPES]; > }; > > #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) > @@ -98,6 +108,7 @@ extern struct sysfs_dirent sysfs_root; > extern struct super_block *sysfs_sb; > extern struct kmem_cache *sysfs_dir_cachep; > extern struct file_system_type sysfs_fs_type; > +extern struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; > > void sysfs_grab_supers(void); > void sysfs_release_supers(void); > @@ -124,6 +135,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); > void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); > > struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, > + const void *tag, > const unsigned char *name); > struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, > const unsigned char *name); > @@ -158,7 +170,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) > struct inode *sysfs_get_inode(struct sysfs_dirent *sd); > int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct iattr *iattr); > int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); > -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); > +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, > + const char *name); > int sysfs_inode_init(void); > > /* > diff --git a/include/linux/kobject.h b/include/linux/kobject.h > index 5437ac0..beb3573 100644 > --- a/include/linux/kobject.h > +++ b/include/linux/kobject.h > @@ -105,6 +105,7 @@ struct kobj_type { > void (*release)(struct kobject *kobj); > struct sysfs_ops *sysfs_ops; > struct attribute **default_attrs; > + const void *(*sysfs_tag)(struct kobject *kobj); > }; > > struct kobj_uevent_env { > diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h > index d8e0230..ba68829 100644 > --- a/include/linux/sysfs.h > +++ b/include/linux/sysfs.h > @@ -80,6 +80,15 @@ struct sysfs_ops { > > struct sysfs_dirent; > > +enum sysfs_tag_type { > + SYSFS_TAG_TYPE_NONE = 0, > + SYSFS_TAG_TYPES > +}; > + > +struct sysfs_tag_type_operations { > + const void *(*mount_tag)(void); > +}; > + > #ifdef CONFIG_SYSFS > > int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), > @@ -126,6 +135,12 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, > struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); > void sysfs_put(struct sysfs_dirent *sd); > void sysfs_printk_last_file(void); > + > +int sysfs_make_tagged_dir(struct kobject *, enum sysfs_tag_type tag_type); > +int sysfs_register_tag_type(enum sysfs_tag_type type, > + struct sysfs_tag_type_operations *ops); > +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag); > + > int __must_check sysfs_init(void); > > #else /* CONFIG_SYSFS */ > @@ -249,6 +264,22 @@ static inline void sysfs_put(struct sysfs_dirent *sd) > { > } > > +staticn inline int sysfs_make_tagged_dir(struct kobject *kobj, ______^ This typo is still present in your patch in the CONFIG_SYSFS=n case. Otherwise the patchset, combined with the patches Greg has already merged in his tree, still works great for me with network namespaces. --Benjamin > + enum sysfs_tag_type tag_type) > +{ > + return 0; > +} > + > +static inline int sysfs_register_tag_type(enum sysfs_tag_type type, > + struct sysfs_tag_type_operations *ops) > +{ > + return 0; > +} > + > +static inline void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) > +{ > +} > + > static inline int __must_check sysfs_init(void) > { > return 0; -- B e n j a m i n T h e r y - BULL/DT/Open Software R&D http://www.bull.com ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-08-27 15:18 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Benjamin Thery @ 2008-09-02 13:54 ` Mark Ryden 2008-09-02 14:03 ` Benjamin Thery 0 siblings, 1 reply; 145+ messages in thread From: Mark Ryden @ 2008-09-02 13:54 UTC (permalink / raw) To: Benjamin Thery Cc: Eric W. Biederman, Greg KH, Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Hello, I hope that this patch (from 4.7.08) was not forgetten... I don't see it for example in linux-net (I have an up-to-date linux-next git tree). Regards, Mark On Wed, Aug 27, 2008 at 6:18 PM, Benjamin Thery <benjamin.thery@bull.net> wrote: > Eric W. Biederman wrote: >> >> The problem. When implementing a network namespace I need to be able >> to have multiple network devices with the same name. Currently this >> is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and >> potentially a few other directories of the form /sys/ ... /net/*. >> >> What this patch does is to add an additional tag field to the >> sysfs dirent structure. For directories that should show different >> contents depending on the context such as /sys/class/net/, and >> /sys/devices/virtual/net/ this tag field is used to specify the >> context in which those directories should be visible. Effectively >> this is the same as creating multiple distinct directories with >> the same name but internally to sysfs the result is nicer. >> >> I am calling the concept of a single directory that looks like multiple >> directories all at the same path in the filesystem tagged directories. >> >> For the networking namespace the set of directories whose contents I need >> to filter with tags can depend on the presence or absence of hotplug >> hardware or which modules are currently loaded. Which means I need >> a simple race free way to setup those directories as tagged. >> >> To achieve a reace free design all tagged directories are created >> and managed by sysfs itself. >> >> Users of this interface: >> - define a type in the sysfs_tag_type enumeration. >> - call sysfs_register_tag_types with the type and it's operations >> - call sysfs_make_tagged_dir with the tag type on directories >> to be managed by this tag type >> - sysfs_exit_tag when an individual tag is no longer valid >> >> - Implement mount_tag() which returns the tag of the calling process >> so we can attach it to a sysfs superblock. >> - Implement ktype.sysfs_tag() which returns the tag of a syfs kobject. >> >> Everything else is left up to sysfs and the driver layer. >> >> For the network namespace mount_tag and sysfs_tag are essentially >> one line functions, and look to remain that. >> >> Tags are currently represented a const void * pointers as that is >> both generic, prevides enough information for equality comparisons, >> and is trivial to create for current users, as it is just the >> existing namespace pointer. >> >> The work needed in sysfs is more extensive. At each directory >> or symlink creating I need to check if the directory it is being >> created in is a tagged directory and if so generate the appropriate >> tag to place on the sysfs_dirent. Likewise at each symlink or >> directory removal I need to check if the sysfs directory it is >> being removed from is a tagged directory and if so figure out >> which tag goes along with the name I am deleting. >> >> Currently only directories which hold kobjects, and >> symlinks are supported. There is not enough information >> in the current file attribute interfaces to give us anything >> to discriminate on which makes it useless, and there are >> no potential users which makes it an uninteresting problem >> to solve. >> >> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> >> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> >> --- >> fs/sysfs/bin.c | 2 +- >> fs/sysfs/dir.c | 139 >> ++++++++++++++++++++++++++++++++++++++++++----- >> fs/sysfs/file.c | 11 +++-- >> fs/sysfs/group.c | 4 +- >> fs/sysfs/inode.c | 7 ++- >> fs/sysfs/mount.c | 115 +++++++++++++++++++++++++++++++++++++-- >> fs/sysfs/symlink.c | 2 +- >> fs/sysfs/sysfs.h | 19 ++++++- >> include/linux/kobject.h | 1 + >> include/linux/sysfs.h | 31 +++++++++++ >> 10 files changed, 298 insertions(+), 33 deletions(-) >> >> diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c >> index 006fc64..86e1128 100644 >> --- a/fs/sysfs/bin.c >> +++ b/fs/sysfs/bin.c >> @@ -252,7 +252,7 @@ int sysfs_create_bin_file(struct kobject * kobj, >> struct bin_attribute * attr) >> void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * >> attr) >> { >> - sysfs_hash_and_remove(kobj->sd, attr->attr.name); >> + sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name); >> } >> EXPORT_SYMBOL_GPL(sysfs_create_bin_file); >> diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c >> index 4ffcfd2..dec7586 100644 >> --- a/fs/sysfs/dir.c >> +++ b/fs/sysfs/dir.c >> @@ -30,6 +30,30 @@ DEFINE_SPINLOCK(sysfs_assoc_lock); >> static DEFINE_SPINLOCK(sysfs_ino_lock); >> static DEFINE_IDA(sysfs_ino_ida); >> +static const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, >> + struct sysfs_dirent *sd) >> +{ >> + const void *tag = NULL; >> + >> + if (sysfs_tag_type(parent_sd)) { >> + struct kobject *kobj; >> + switch (sysfs_type(sd)) { >> + case SYSFS_DIR: >> + kobj = sd->s_dir.kobj; >> + break; >> + case SYSFS_KOBJ_LINK: >> + kobj = sd->s_symlink.target_sd->s_dir.kobj; >> + break; >> + default: >> + BUG(); >> + } >> + tag = kobj->ktype->sysfs_tag(kobj); >> + /* NULL tags are reserved for internal use */ >> + BUG_ON(tag == NULL); >> + } >> + return tag; >> +} >> + >> /** >> * sysfs_link_sibling - link sysfs_dirent into sibling list >> * @sd: sysfs_dirent of interest >> @@ -101,8 +125,19 @@ static void sysfs_unlink_sibling(struct sysfs_dirent >> *sd) >> struct dentry *sysfs_get_dentry(struct super_block *sb, >> struct sysfs_dirent *sd) >> { >> - struct dentry *dentry = dget(sb->s_root); >> + struct dentry *dentry; >> + >> + /* Bail if this sd won't show up in this superblock */ >> + if (sd->s_parent) { >> + enum sysfs_tag_type type; >> + const void *tag; >> + type = sysfs_tag_type(sd->s_parent); >> + tag = sysfs_info(sb)->tag[type]; >> + if (sd->s_tag != tag) >> + return ERR_PTR(-EXDEV); >> + } >> + dentry = dget(sb->s_root); >> while (dentry->d_fsdata != sd) { >> struct sysfs_dirent *cur; >> struct dentry *parent; >> @@ -421,10 +456,15 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, >> */ >> int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent >> *sd) >> { >> - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) >> + const void *tag = NULL; >> + >> + tag = sysfs_creation_tag(acxt->parent_sd, sd); >> + >> + if (sysfs_find_dirent(acxt->parent_sd, tag, sd->s_name)) >> return -EEXIST; >> sd->s_parent = sysfs_get(acxt->parent_sd); >> + sd->s_tag = tag; >> if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) >> inc_nlink(acxt->parent_inode); >> @@ -602,13 +642,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt >> *acxt) >> * Pointer to sysfs_dirent if found, NULL if not. >> */ >> struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, >> + const void *tag, >> const unsigned char *name) >> { >> struct sysfs_dirent *sd; >> - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) >> + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { >> + if (sd->s_tag != tag) >> + continue; >> if (!strcmp(sd->s_name, name)) >> return sd; >> + } >> return NULL; >> } >> @@ -632,7 +676,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct >> sysfs_dirent *parent_sd, >> struct sysfs_dirent *sd; >> mutex_lock(&sysfs_mutex); >> - sd = sysfs_find_dirent(parent_sd, name); >> + sd = sysfs_find_dirent(parent_sd, NULL, name); >> sysfs_get(sd); >> mutex_unlock(&sysfs_mutex); >> @@ -699,13 +743,18 @@ static struct dentry * sysfs_lookup(struct inode >> *dir, struct dentry *dentry, >> struct nameidata *nd) >> { >> struct dentry *ret = NULL; >> - struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; >> + struct dentry *parent = dentry->d_parent; >> + struct sysfs_dirent *parent_sd = parent->d_fsdata; >> struct sysfs_dirent *sd; >> struct inode *inode; >> + enum sysfs_tag_type type; >> + const void *tag; >> mutex_lock(&sysfs_mutex); >> - sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); >> + type = sysfs_tag_type(parent_sd); >> + tag = sysfs_info(parent->d_sb)->tag[type]; >> + sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); >> /* no such entry */ >> if (!sd) { >> @@ -913,19 +962,24 @@ int sysfs_rename_dir(struct kobject * kobj, const >> char *new_name) >> struct sysfs_rename_struct *srs; >> struct inode *parent_inode = NULL; >> const char *dup_name = NULL; >> + const void *old_tag, *tag; >> int error; >> INIT_LIST_HEAD(&todo); >> mutex_lock(&sysfs_rename_mutex); >> + old_tag = sd->s_tag; >> + tag = sysfs_creation_tag(sd->s_parent, sd); >> error = 0; >> - if (strcmp(sd->s_name, new_name) == 0) >> + if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) >> goto out; /* nothing to rename */ >> sysfs_grab_supers(); >> - error = prep_rename(&todo, sd, sd->s_parent, new_name); >> - if (error) >> - goto out_release; >> + if (old_tag == tag) { >> + error = prep_rename(&todo, sd, sd->s_parent, new_name); >> + if (error) >> + goto out_release; >> + } >> error = -ENOMEM; >> mutex_lock(&sysfs_mutex); >> @@ -938,7 +992,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char >> *new_name) >> mutex_lock(&sysfs_mutex); >> error = -EEXIST; >> - if (sysfs_find_dirent(sd->s_parent, new_name)) >> + if (sysfs_find_dirent(sd->s_parent, tag, new_name)) >> goto out_unlock; >> /* rename sysfs_dirent */ >> @@ -949,6 +1003,7 @@ int sysfs_rename_dir(struct kobject * kobj, const >> char *new_name) >> dup_name = sd->s_name; >> sd->s_name = new_name; >> + sd->s_tag = tag; >> /* rename */ >> list_for_each_entry(srs, &todo, list) { >> @@ -956,6 +1011,20 @@ int sysfs_rename_dir(struct kobject * kobj, const >> char *new_name) >> d_move(srs->old_dentry, srs->new_dentry); >> } >> + /* If we are moving across superblocks drop the dcache entries */ >> + if (old_tag != tag) { >> + struct super_block *sb; >> + struct dentry *dentry; >> + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, >> s_instances) { >> + dentry = __sysfs_get_dentry(sb, sd); >> + if (!dentry) >> + continue; >> + shrink_dcache_parent(dentry); >> + d_drop(dentry); >> + dput(dentry); >> + } >> + } >> + >> error = 0; >> out_unlock: >> mutex_unlock(&sysfs_mutex); >> @@ -978,11 +1047,13 @@ int sysfs_move_dir(struct kobject *kobj, struct >> kobject *new_parent_kobj) >> struct sysfs_rename_struct *srs; >> struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; >> int error; >> + const void *tag; >> INIT_LIST_HEAD(&todo); >> mutex_lock(&sysfs_rename_mutex); >> BUG_ON(!sd->s_parent); >> new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : >> &sysfs_root; >> + tag = sd->s_tag; >> error = 0; >> if (sd->s_parent == new_parent_sd) >> @@ -1016,7 +1087,7 @@ again: >> mutex_lock(&sysfs_mutex); >> error = -EEXIST; >> - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) >> + if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) >> goto out_unlock; >> error = 0; >> @@ -1055,10 +1126,12 @@ static inline unsigned char dt_type(struct >> sysfs_dirent *sd) >> static int sysfs_readdir(struct file * filp, void * dirent, filldir_t >> filldir) >> { >> - struct dentry *dentry = filp->f_path.dentry; >> - struct sysfs_dirent * parent_sd = dentry->d_fsdata; >> + struct dentry *parent = filp->f_path.dentry; >> + struct sysfs_dirent *parent_sd = parent->d_fsdata; >> struct sysfs_dirent *pos; >> ino_t ino; >> + enum sysfs_tag_type type; >> + const void *tag; >> if (filp->f_pos == 0) { >> ino = parent_sd->s_ino; >> @@ -1076,6 +1149,9 @@ static int sysfs_readdir(struct file * filp, void * >> dirent, filldir_t filldir) >> if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { >> mutex_lock(&sysfs_mutex); >> + type = sysfs_tag_type(parent_sd); >> + tag = sysfs_info(parent->d_sb)->tag[type]; >> + >> /* Skip the dentries we have already reported */ >> pos = parent_sd->s_dir.children; >> while (pos && (filp->f_pos > pos->s_ino)) >> @@ -1085,6 +1161,9 @@ static int sysfs_readdir(struct file * filp, void * >> dirent, filldir_t filldir) >> const char * name; >> int len; >> + if (pos->s_tag != tag) >> + continue; >> + >> name = pos->s_name; >> len = strlen(name); >> filp->f_pos = ino = pos->s_ino; >> @@ -1105,3 +1184,35 @@ const struct file_operations sysfs_dir_operations = >> { >> .read = generic_read_dir, >> .readdir = sysfs_readdir, >> }; >> + >> +/** >> + * sysfs_make_tagged_dir - Require tags of all the entries in a >> directory. >> + * @kobj: object whose children should be filtered by tags >> + * >> + * Once tagging has been enabled on a directory the contents >> + * of the directory become dependent upon context captured when >> + * sysfs was mounted. >> + */ >> +int sysfs_make_tagged_dir(struct kobject *kobj, enum sysfs_tag_type type) >> +{ >> + struct sysfs_dirent *sd; >> + int err; >> + >> + err = -ENOENT; >> + sd = kobj->sd; >> + >> + mutex_lock(&sysfs_mutex); >> + err = -EINVAL; >> + /* We can only enable tagging when we have a valid tag type >> + * on empty directories where taggint has not already been >> + * enabled. >> + */ >> + if ((type > SYSFS_TAG_TYPE_NONE) && (type < SYSFS_TAG_TYPES) && >> + tag_ops[type] && !sysfs_tag_type(sd) && >> + (sysfs_type(sd) == SYSFS_DIR) && !sd->s_dir.children) { >> + err = 0; >> + sd->s_flags |= (type << SYSFS_TAG_TYPE_SHIFT); >> + } >> + mutex_unlock(&sysfs_mutex); >> + return err; >> +} >> diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c >> index 61c3476..091c0de 100644 >> --- a/fs/sysfs/file.c >> +++ b/fs/sysfs/file.c >> @@ -476,9 +476,12 @@ void sysfs_notify(struct kobject *k, char *dir, char >> *attr) >> mutex_lock(&sysfs_mutex); >> if (sd && dir) >> - sd = sysfs_find_dirent(sd, dir); >> + /* Only directories are tagged, so no need to pass >> + * a tag explicitly. >> + */ >> + sd = sysfs_find_dirent(sd, NULL, dir); >> if (sd && attr) >> - sd = sysfs_find_dirent(sd, attr); >> + sd = sysfs_find_dirent(sd, NULL, attr); >> if (sd) >> sysfs_notify_dirent(sd); >> @@ -640,7 +643,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); >> void sysfs_remove_file(struct kobject * kobj, const struct attribute * >> attr) >> { >> - sysfs_hash_and_remove(kobj->sd, attr->name); >> + sysfs_hash_and_remove(kobj, kobj->sd, attr->name); >> } >> @@ -660,7 +663,7 @@ void sysfs_remove_file_from_group(struct kobject >> *kobj, >> else >> dir_sd = sysfs_get(kobj->sd); >> if (dir_sd) { >> - sysfs_hash_and_remove(dir_sd, attr->name); >> + sysfs_hash_and_remove(kobj, dir_sd, attr->name); >> sysfs_put(dir_sd); >> } >> } >> diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c >> index fe61194..5fba6f2 100644 >> --- a/fs/sysfs/group.c >> +++ b/fs/sysfs/group.c >> @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, >> struct kobject *kobj, >> int i; >> for (i = 0, attr = grp->attrs; *attr; i++, attr++) >> - sysfs_hash_and_remove(dir_sd, (*attr)->name); >> + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); >> } >> static int create_files(struct sysfs_dirent *dir_sd, struct kobject >> *kobj, >> @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd, >> struct kobject *kobj, >> * visibility. Do this by first removing then >> * re-adding (if required) the file */ >> if (update) >> - sysfs_hash_and_remove(dir_sd, (*attr)->name); >> + sysfs_hash_and_remove(kobj, dir_sd, >> (*attr)->name); >> if (grp->is_visible) { >> mode = grp->is_visible(kobj, *attr, i); >> if (!mode) >> diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c >> index 80f8fd4..b5fc78a 100644 >> --- a/fs/sysfs/inode.c >> +++ b/fs/sysfs/inode.c >> @@ -226,17 +226,20 @@ struct inode * sysfs_get_inode(struct sysfs_dirent >> *sd) >> return inode; >> } >> -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) >> +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent >> *dir_sd, >> + const char *name) >> { >> struct sysfs_addrm_cxt acxt; >> struct sysfs_dirent *sd; >> + const void *tag; >> if (!dir_sd) >> return -ENOENT; >> sysfs_addrm_start(&acxt, dir_sd); >> + tag = kobj->sd->s_tag; >> - sd = sysfs_find_dirent(dir_sd, name); >> + sd = sysfs_find_dirent(dir_sd, tag, name); >> if (sd) >> sysfs_remove_one(&acxt, sd); >> diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c >> index 6ebda1a..8f2237a 100644 >> --- a/fs/sysfs/mount.c >> +++ b/fs/sysfs/mount.c >> @@ -35,12 +35,15 @@ static const struct super_operations sysfs_ops = { >> struct sysfs_dirent sysfs_root = { >> .s_name = "", >> .s_count = ATOMIC_INIT(1), >> - .s_flags = SYSFS_DIR, >> + .s_flags = SYSFS_DIR | (SYSFS_TAG_TYPE_NONE << >> SYSFS_TAG_TYPE_SHIFT), >> .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, >> .s_ino = 1, >> }; >> -static int sysfs_fill_super(struct super_block *sb, void *data, int >> silent) >> +struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; >> + >> +static int sysfs_fill_super(struct super_block *sb, void *data, int >> silent, >> + const void *tags[SYSFS_TAG_TYPES]) >> { >> struct sysfs_super_info *info = NULL; >> struct inode *inode = NULL; >> @@ -76,8 +79,10 @@ static int sysfs_fill_super(struct super_block *sb, >> void *data, int silent) >> goto out_err; >> } >> root->d_fsdata = &sysfs_root; >> + root->d_sb = sb; >> sb->s_root = root; >> sb->s_fs_info = info; >> + memcpy(info->tag, tags, sizeof(info->tag[0])*SYSFS_TAG_TYPES); >> return 0; >> out_err: >> @@ -89,20 +94,74 @@ out_err: >> return error; >> } >> +static int sysfs_test_super(struct super_block *sb, void *ptr) >> +{ >> + const void **tag = ptr; >> + struct sysfs_super_info *info = sysfs_info(sb); >> + enum sysfs_tag_type type; >> + int found = 1; >> + >> + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { >> + if (info->tag[type] != tag[type]) { >> + found = 0; >> + break; >> + } >> + } >> + >> + return found; >> +} >> + >> static int sysfs_get_sb(struct file_system_type *fs_type, >> int flags, const char *dev_name, void *data, struct vfsmount *mnt) >> { >> - int rc; >> + const void *tag[SYSFS_TAG_TYPES]; >> + struct super_block *sb; >> + int error; >> + enum sysfs_tag_type type; >> + >> + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { >> + tag[type] = NULL; >> + if (!tag_ops[type]) >> + continue; >> + tag[type] = tag_ops[type]->mount_tag(); >> + } >> + >> mutex_lock(&sysfs_rename_mutex); >> - rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); >> + sb = sget(fs_type, sysfs_test_super, set_anon_super, tag); >> + if (IS_ERR(sb)) { >> + error = PTR_ERR(sb); >> + goto out; >> + } >> + if (!sb->s_root) { >> + sb->s_flags = flags; >> + error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : >> 0, >> + tag); >> + if (error) { >> + up_write(&sb->s_umount); >> + deactivate_super(sb); >> + goto out; >> + } >> + sb->s_flags |= MS_ACTIVE; >> + } >> + do_remount_sb(sb, flags, data, 0); >> + error = simple_set_mnt(mnt, sb); >> +out: >> mutex_unlock(&sysfs_rename_mutex); >> - return rc; >> + return error; >> +} >> + >> +static void sysfs_kill_sb(struct super_block *sb) >> +{ >> + struct sysfs_super_info *info = sysfs_info(sb); >> + >> + kill_anon_super(sb); >> + kfree(info); >> } >> struct file_system_type sysfs_fs_type = { >> .name = "sysfs", >> .get_sb = sysfs_get_sb, >> - .kill_sb = kill_anon_super, >> + .kill_sb = sysfs_kill_sb, >> }; >> void sysfs_grab_supers(void) >> @@ -146,6 +205,50 @@ restart: >> spin_unlock(&sb_lock); >> } >> +int sysfs_register_tag_type(enum sysfs_tag_type type, struct >> sysfs_tag_type_operations *ops) >> +{ >> + int error; >> + >> + mutex_lock(&sysfs_rename_mutex); >> + >> + error = -EINVAL; >> + if (type >= SYSFS_TAG_TYPES) >> + goto out; >> + >> + error = -EINVAL; >> + if (type <= SYSFS_TAG_TYPE_NONE) >> + goto out; >> + >> + error = -EBUSY; >> + if (tag_ops[type]) >> + goto out; >> + >> + error = 0; >> + tag_ops[type] = ops; >> + >> +out: >> + mutex_unlock(&sysfs_rename_mutex); >> + return error; >> +} >> + >> +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) >> +{ >> + /* Allow the tag to go away while sysfs is still mounted. */ >> + struct super_block *sb; >> + mutex_lock(&sysfs_rename_mutex); >> + sysfs_grab_supers(); >> + mutex_lock(&sysfs_mutex); >> + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { >> + struct sysfs_super_info *info = sysfs_info(sb); >> + if (info->tag[type] != tag) >> + continue; >> + info->tag[type] = NULL; >> + } >> + mutex_unlock(&sysfs_mutex); >> + sysfs_release_supers(); >> + mutex_unlock(&sysfs_rename_mutex); >> +} >> + >> int __init sysfs_init(void) >> { >> int err = -ENOMEM; >> diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c >> index a3ba217..54b2e5f 100644 >> --- a/fs/sysfs/symlink.c >> +++ b/fs/sysfs/symlink.c >> @@ -119,7 +119,7 @@ void sysfs_remove_link(struct kobject * kobj, const >> char * name) >> else >> parent_sd = kobj->sd; >> - sysfs_hash_and_remove(parent_sd, name); >> + sysfs_hash_and_remove(kobj, parent_sd, name); >> } >> static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, >> diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h >> index f0e5ecb..67115ec 100644 >> --- a/fs/sysfs/sysfs.h >> +++ b/fs/sysfs/sysfs.h >> @@ -45,6 +45,7 @@ struct sysfs_dirent { >> struct sysfs_dirent *s_sibling; >> const char *s_name; >> + const void *s_tag; >> union { >> struct sysfs_elem_dir s_dir; >> struct sysfs_elem_symlink s_symlink; >> @@ -67,14 +68,22 @@ struct sysfs_dirent { >> #define SYSFS_KOBJ_LINK 0x0008 >> #define SYSFS_COPY_NAME (SYSFS_DIR | >> SYSFS_KOBJ_LINK) >> -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK >> -#define SYSFS_FLAG_REMOVED 0x0200 >> +#define SYSFS_TAG_TYPE_MASK 0xff00 >> +#define SYSFS_TAG_TYPE_SHIFT 8 >> + >> +#define SYSFS_FLAG_MASK ~(SYSFS_TYPE_MASK | >> SYSFS_TAG_TYPE_MASK) >> +#define SYSFS_FLAG_REMOVED 0x020000 >> static inline unsigned int sysfs_type(struct sysfs_dirent *sd) >> { >> return sd->s_flags & SYSFS_TYPE_MASK; >> } >> +static inline enum sysfs_tag_type sysfs_tag_type(struct sysfs_dirent >> *sd) >> +{ >> + return (sd->s_flags & SYSFS_TAG_TYPE_MASK) >> >> SYSFS_TAG_TYPE_SHIFT; >> +} >> + >> /* >> * Context structure to be used while adding/removing nodes. >> */ >> @@ -87,6 +96,7 @@ struct sysfs_addrm_cxt { >> struct sysfs_super_info { >> int grabbed; >> + const void *tag[SYSFS_TAG_TYPES]; >> }; >> #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) >> @@ -98,6 +108,7 @@ extern struct sysfs_dirent sysfs_root; >> extern struct super_block *sysfs_sb; >> extern struct kmem_cache *sysfs_dir_cachep; >> extern struct file_system_type sysfs_fs_type; >> +extern struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; >> void sysfs_grab_supers(void); >> void sysfs_release_supers(void); >> @@ -124,6 +135,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, >> struct sysfs_dirent *sd); >> void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); >> struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, >> + const void *tag, >> const unsigned char *name); >> struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, >> const unsigned char *name); >> @@ -158,7 +170,8 @@ static inline void __sysfs_put(struct sysfs_dirent >> *sd) >> struct inode *sysfs_get_inode(struct sysfs_dirent *sd); >> int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct >> iattr *iattr); >> int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); >> -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); >> +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent >> *dir_sd, >> + const char *name); >> int sysfs_inode_init(void); >> /* >> diff --git a/include/linux/kobject.h b/include/linux/kobject.h >> index 5437ac0..beb3573 100644 >> --- a/include/linux/kobject.h >> +++ b/include/linux/kobject.h >> @@ -105,6 +105,7 @@ struct kobj_type { >> void (*release)(struct kobject *kobj); >> struct sysfs_ops *sysfs_ops; >> struct attribute **default_attrs; >> + const void *(*sysfs_tag)(struct kobject *kobj); >> }; >> struct kobj_uevent_env { >> diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h >> index d8e0230..ba68829 100644 >> --- a/include/linux/sysfs.h >> +++ b/include/linux/sysfs.h >> @@ -80,6 +80,15 @@ struct sysfs_ops { >> struct sysfs_dirent; >> +enum sysfs_tag_type { >> + SYSFS_TAG_TYPE_NONE = 0, >> + SYSFS_TAG_TYPES >> +}; >> + >> +struct sysfs_tag_type_operations { >> + const void *(*mount_tag)(void); >> +}; >> + >> #ifdef CONFIG_SYSFS >> int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), >> @@ -126,6 +135,12 @@ struct sysfs_dirent *sysfs_get_dirent(struct >> sysfs_dirent *parent_sd, >> struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); >> void sysfs_put(struct sysfs_dirent *sd); >> void sysfs_printk_last_file(void); >> + >> +int sysfs_make_tagged_dir(struct kobject *, enum sysfs_tag_type >> tag_type); >> +int sysfs_register_tag_type(enum sysfs_tag_type type, >> + struct sysfs_tag_type_operations *ops); >> +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag); >> + >> int __must_check sysfs_init(void); >> #else /* CONFIG_SYSFS */ >> @@ -249,6 +264,22 @@ static inline void sysfs_put(struct sysfs_dirent *sd) >> { >> } >> +staticn inline int sysfs_make_tagged_dir(struct kobject *kobj, > > ______^ > > This typo is still present in your patch in the CONFIG_SYSFS=n case. > > Otherwise the patchset, combined with the patches Greg has already > merged in his tree, still works great for me with network namespaces. > > --Benjamin > >> + enum sysfs_tag_type >> tag_type) >> +{ >> + return 0; >> +} >> + >> +static inline int sysfs_register_tag_type(enum sysfs_tag_type type, >> + struct sysfs_tag_type_operations >> *ops) >> +{ >> + return 0; >> +} >> + >> +static inline void sysfs_exit_tag(enum sysfs_tag_type type, const void >> *tag) >> +{ >> +} >> + >> static inline int __must_check sysfs_init(void) >> { >> return 0; > > > -- > B e n j a m i n T h e r y - BULL/DT/Open Software R&D > > http://www.bull.com > -- > To unsubscribe from this list: send the line "unsubscribe netdev" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-09-02 13:54 ` Mark Ryden @ 2008-09-02 14:03 ` Benjamin Thery 2008-09-02 17:01 ` Greg KH 0 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-09-02 14:03 UTC (permalink / raw) To: Greg KH Cc: Mark Ryden, Eric W. Biederman, Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Mark Ryden wrote: > Hello, > I hope that this patch (from 4.7.08) was not forgetten... I don't see > it for example in linux-net (I have an up-to-date linux-next git > tree). I was about to ask the same thing. Greg, what is the plan with these remaining patches for sysfs tagged dirs? Will you have some time to merge them in your tree soon? I ran my network namespace tests last week with this latest patchset from Eric applied on top of your tree (which already contains the first batch of patches). Everything looked good. Regards, Benjamin > > Regards, > Mark > > On Wed, Aug 27, 2008 at 6:18 PM, Benjamin Thery <benjamin.thery@bull.net> wrote: >> Eric W. Biederman wrote: >>> The problem. When implementing a network namespace I need to be able >>> to have multiple network devices with the same name. Currently this >>> is a problem for /sys/class/net/*, /sys/devices/virtual/net/*, and >>> potentially a few other directories of the form /sys/ ... /net/*. >>> >>> What this patch does is to add an additional tag field to the >>> sysfs dirent structure. For directories that should show different >>> contents depending on the context such as /sys/class/net/, and >>> /sys/devices/virtual/net/ this tag field is used to specify the >>> context in which those directories should be visible. Effectively >>> this is the same as creating multiple distinct directories with >>> the same name but internally to sysfs the result is nicer. >>> >>> I am calling the concept of a single directory that looks like multiple >>> directories all at the same path in the filesystem tagged directories. >>> >>> For the networking namespace the set of directories whose contents I need >>> to filter with tags can depend on the presence or absence of hotplug >>> hardware or which modules are currently loaded. Which means I need >>> a simple race free way to setup those directories as tagged. >>> >>> To achieve a reace free design all tagged directories are created >>> and managed by sysfs itself. >>> >>> Users of this interface: >>> - define a type in the sysfs_tag_type enumeration. >>> - call sysfs_register_tag_types with the type and it's operations >>> - call sysfs_make_tagged_dir with the tag type on directories >>> to be managed by this tag type >>> - sysfs_exit_tag when an individual tag is no longer valid >>> >>> - Implement mount_tag() which returns the tag of the calling process >>> so we can attach it to a sysfs superblock. >>> - Implement ktype.sysfs_tag() which returns the tag of a syfs kobject. >>> >>> Everything else is left up to sysfs and the driver layer. >>> >>> For the network namespace mount_tag and sysfs_tag are essentially >>> one line functions, and look to remain that. >>> >>> Tags are currently represented a const void * pointers as that is >>> both generic, prevides enough information for equality comparisons, >>> and is trivial to create for current users, as it is just the >>> existing namespace pointer. >>> >>> The work needed in sysfs is more extensive. At each directory >>> or symlink creating I need to check if the directory it is being >>> created in is a tagged directory and if so generate the appropriate >>> tag to place on the sysfs_dirent. Likewise at each symlink or >>> directory removal I need to check if the sysfs directory it is >>> being removed from is a tagged directory and if so figure out >>> which tag goes along with the name I am deleting. >>> >>> Currently only directories which hold kobjects, and >>> symlinks are supported. There is not enough information >>> in the current file attribute interfaces to give us anything >>> to discriminate on which makes it useless, and there are >>> no potential users which makes it an uninteresting problem >>> to solve. >>> >>> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> >>> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> >>> --- >>> fs/sysfs/bin.c | 2 +- >>> fs/sysfs/dir.c | 139 >>> ++++++++++++++++++++++++++++++++++++++++++----- >>> fs/sysfs/file.c | 11 +++-- >>> fs/sysfs/group.c | 4 +- >>> fs/sysfs/inode.c | 7 ++- >>> fs/sysfs/mount.c | 115 +++++++++++++++++++++++++++++++++++++-- >>> fs/sysfs/symlink.c | 2 +- >>> fs/sysfs/sysfs.h | 19 ++++++- >>> include/linux/kobject.h | 1 + >>> include/linux/sysfs.h | 31 +++++++++++ >>> 10 files changed, 298 insertions(+), 33 deletions(-) >>> >>> diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c >>> index 006fc64..86e1128 100644 >>> --- a/fs/sysfs/bin.c >>> +++ b/fs/sysfs/bin.c >>> @@ -252,7 +252,7 @@ int sysfs_create_bin_file(struct kobject * kobj, >>> struct bin_attribute * attr) >>> void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * >>> attr) >>> { >>> - sysfs_hash_and_remove(kobj->sd, attr->attr.name); >>> + sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name); >>> } >>> EXPORT_SYMBOL_GPL(sysfs_create_bin_file); >>> diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c >>> index 4ffcfd2..dec7586 100644 >>> --- a/fs/sysfs/dir.c >>> +++ b/fs/sysfs/dir.c >>> @@ -30,6 +30,30 @@ DEFINE_SPINLOCK(sysfs_assoc_lock); >>> static DEFINE_SPINLOCK(sysfs_ino_lock); >>> static DEFINE_IDA(sysfs_ino_ida); >>> +static const void *sysfs_creation_tag(struct sysfs_dirent *parent_sd, >>> + struct sysfs_dirent *sd) >>> +{ >>> + const void *tag = NULL; >>> + >>> + if (sysfs_tag_type(parent_sd)) { >>> + struct kobject *kobj; >>> + switch (sysfs_type(sd)) { >>> + case SYSFS_DIR: >>> + kobj = sd->s_dir.kobj; >>> + break; >>> + case SYSFS_KOBJ_LINK: >>> + kobj = sd->s_symlink.target_sd->s_dir.kobj; >>> + break; >>> + default: >>> + BUG(); >>> + } >>> + tag = kobj->ktype->sysfs_tag(kobj); >>> + /* NULL tags are reserved for internal use */ >>> + BUG_ON(tag == NULL); >>> + } >>> + return tag; >>> +} >>> + >>> /** >>> * sysfs_link_sibling - link sysfs_dirent into sibling list >>> * @sd: sysfs_dirent of interest >>> @@ -101,8 +125,19 @@ static void sysfs_unlink_sibling(struct sysfs_dirent >>> *sd) >>> struct dentry *sysfs_get_dentry(struct super_block *sb, >>> struct sysfs_dirent *sd) >>> { >>> - struct dentry *dentry = dget(sb->s_root); >>> + struct dentry *dentry; >>> + >>> + /* Bail if this sd won't show up in this superblock */ >>> + if (sd->s_parent) { >>> + enum sysfs_tag_type type; >>> + const void *tag; >>> + type = sysfs_tag_type(sd->s_parent); >>> + tag = sysfs_info(sb)->tag[type]; >>> + if (sd->s_tag != tag) >>> + return ERR_PTR(-EXDEV); >>> + } >>> + dentry = dget(sb->s_root); >>> while (dentry->d_fsdata != sd) { >>> struct sysfs_dirent *cur; >>> struct dentry *parent; >>> @@ -421,10 +456,15 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, >>> */ >>> int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent >>> *sd) >>> { >>> - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) >>> + const void *tag = NULL; >>> + >>> + tag = sysfs_creation_tag(acxt->parent_sd, sd); >>> + >>> + if (sysfs_find_dirent(acxt->parent_sd, tag, sd->s_name)) >>> return -EEXIST; >>> sd->s_parent = sysfs_get(acxt->parent_sd); >>> + sd->s_tag = tag; >>> if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) >>> inc_nlink(acxt->parent_inode); >>> @@ -602,13 +642,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt >>> *acxt) >>> * Pointer to sysfs_dirent if found, NULL if not. >>> */ >>> struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, >>> + const void *tag, >>> const unsigned char *name) >>> { >>> struct sysfs_dirent *sd; >>> - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) >>> + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { >>> + if (sd->s_tag != tag) >>> + continue; >>> if (!strcmp(sd->s_name, name)) >>> return sd; >>> + } >>> return NULL; >>> } >>> @@ -632,7 +676,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct >>> sysfs_dirent *parent_sd, >>> struct sysfs_dirent *sd; >>> mutex_lock(&sysfs_mutex); >>> - sd = sysfs_find_dirent(parent_sd, name); >>> + sd = sysfs_find_dirent(parent_sd, NULL, name); >>> sysfs_get(sd); >>> mutex_unlock(&sysfs_mutex); >>> @@ -699,13 +743,18 @@ static struct dentry * sysfs_lookup(struct inode >>> *dir, struct dentry *dentry, >>> struct nameidata *nd) >>> { >>> struct dentry *ret = NULL; >>> - struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; >>> + struct dentry *parent = dentry->d_parent; >>> + struct sysfs_dirent *parent_sd = parent->d_fsdata; >>> struct sysfs_dirent *sd; >>> struct inode *inode; >>> + enum sysfs_tag_type type; >>> + const void *tag; >>> mutex_lock(&sysfs_mutex); >>> - sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); >>> + type = sysfs_tag_type(parent_sd); >>> + tag = sysfs_info(parent->d_sb)->tag[type]; >>> + sd = sysfs_find_dirent(parent_sd, tag, dentry->d_name.name); >>> /* no such entry */ >>> if (!sd) { >>> @@ -913,19 +962,24 @@ int sysfs_rename_dir(struct kobject * kobj, const >>> char *new_name) >>> struct sysfs_rename_struct *srs; >>> struct inode *parent_inode = NULL; >>> const char *dup_name = NULL; >>> + const void *old_tag, *tag; >>> int error; >>> INIT_LIST_HEAD(&todo); >>> mutex_lock(&sysfs_rename_mutex); >>> + old_tag = sd->s_tag; >>> + tag = sysfs_creation_tag(sd->s_parent, sd); >>> error = 0; >>> - if (strcmp(sd->s_name, new_name) == 0) >>> + if ((old_tag == tag) && (strcmp(sd->s_name, new_name) == 0)) >>> goto out; /* nothing to rename */ >>> sysfs_grab_supers(); >>> - error = prep_rename(&todo, sd, sd->s_parent, new_name); >>> - if (error) >>> - goto out_release; >>> + if (old_tag == tag) { >>> + error = prep_rename(&todo, sd, sd->s_parent, new_name); >>> + if (error) >>> + goto out_release; >>> + } >>> error = -ENOMEM; >>> mutex_lock(&sysfs_mutex); >>> @@ -938,7 +992,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char >>> *new_name) >>> mutex_lock(&sysfs_mutex); >>> error = -EEXIST; >>> - if (sysfs_find_dirent(sd->s_parent, new_name)) >>> + if (sysfs_find_dirent(sd->s_parent, tag, new_name)) >>> goto out_unlock; >>> /* rename sysfs_dirent */ >>> @@ -949,6 +1003,7 @@ int sysfs_rename_dir(struct kobject * kobj, const >>> char *new_name) >>> dup_name = sd->s_name; >>> sd->s_name = new_name; >>> + sd->s_tag = tag; >>> /* rename */ >>> list_for_each_entry(srs, &todo, list) { >>> @@ -956,6 +1011,20 @@ int sysfs_rename_dir(struct kobject * kobj, const >>> char *new_name) >>> d_move(srs->old_dentry, srs->new_dentry); >>> } >>> + /* If we are moving across superblocks drop the dcache entries */ >>> + if (old_tag != tag) { >>> + struct super_block *sb; >>> + struct dentry *dentry; >>> + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, >>> s_instances) { >>> + dentry = __sysfs_get_dentry(sb, sd); >>> + if (!dentry) >>> + continue; >>> + shrink_dcache_parent(dentry); >>> + d_drop(dentry); >>> + dput(dentry); >>> + } >>> + } >>> + >>> error = 0; >>> out_unlock: >>> mutex_unlock(&sysfs_mutex); >>> @@ -978,11 +1047,13 @@ int sysfs_move_dir(struct kobject *kobj, struct >>> kobject *new_parent_kobj) >>> struct sysfs_rename_struct *srs; >>> struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; >>> int error; >>> + const void *tag; >>> INIT_LIST_HEAD(&todo); >>> mutex_lock(&sysfs_rename_mutex); >>> BUG_ON(!sd->s_parent); >>> new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : >>> &sysfs_root; >>> + tag = sd->s_tag; >>> error = 0; >>> if (sd->s_parent == new_parent_sd) >>> @@ -1016,7 +1087,7 @@ again: >>> mutex_lock(&sysfs_mutex); >>> error = -EEXIST; >>> - if (sysfs_find_dirent(new_parent_sd, sd->s_name)) >>> + if (sysfs_find_dirent(new_parent_sd, tag, sd->s_name)) >>> goto out_unlock; >>> error = 0; >>> @@ -1055,10 +1126,12 @@ static inline unsigned char dt_type(struct >>> sysfs_dirent *sd) >>> static int sysfs_readdir(struct file * filp, void * dirent, filldir_t >>> filldir) >>> { >>> - struct dentry *dentry = filp->f_path.dentry; >>> - struct sysfs_dirent * parent_sd = dentry->d_fsdata; >>> + struct dentry *parent = filp->f_path.dentry; >>> + struct sysfs_dirent *parent_sd = parent->d_fsdata; >>> struct sysfs_dirent *pos; >>> ino_t ino; >>> + enum sysfs_tag_type type; >>> + const void *tag; >>> if (filp->f_pos == 0) { >>> ino = parent_sd->s_ino; >>> @@ -1076,6 +1149,9 @@ static int sysfs_readdir(struct file * filp, void * >>> dirent, filldir_t filldir) >>> if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { >>> mutex_lock(&sysfs_mutex); >>> + type = sysfs_tag_type(parent_sd); >>> + tag = sysfs_info(parent->d_sb)->tag[type]; >>> + >>> /* Skip the dentries we have already reported */ >>> pos = parent_sd->s_dir.children; >>> while (pos && (filp->f_pos > pos->s_ino)) >>> @@ -1085,6 +1161,9 @@ static int sysfs_readdir(struct file * filp, void * >>> dirent, filldir_t filldir) >>> const char * name; >>> int len; >>> + if (pos->s_tag != tag) >>> + continue; >>> + >>> name = pos->s_name; >>> len = strlen(name); >>> filp->f_pos = ino = pos->s_ino; >>> @@ -1105,3 +1184,35 @@ const struct file_operations sysfs_dir_operations = >>> { >>> .read = generic_read_dir, >>> .readdir = sysfs_readdir, >>> }; >>> + >>> +/** >>> + * sysfs_make_tagged_dir - Require tags of all the entries in a >>> directory. >>> + * @kobj: object whose children should be filtered by tags >>> + * >>> + * Once tagging has been enabled on a directory the contents >>> + * of the directory become dependent upon context captured when >>> + * sysfs was mounted. >>> + */ >>> +int sysfs_make_tagged_dir(struct kobject *kobj, enum sysfs_tag_type type) >>> +{ >>> + struct sysfs_dirent *sd; >>> + int err; >>> + >>> + err = -ENOENT; >>> + sd = kobj->sd; >>> + >>> + mutex_lock(&sysfs_mutex); >>> + err = -EINVAL; >>> + /* We can only enable tagging when we have a valid tag type >>> + * on empty directories where taggint has not already been >>> + * enabled. >>> + */ >>> + if ((type > SYSFS_TAG_TYPE_NONE) && (type < SYSFS_TAG_TYPES) && >>> + tag_ops[type] && !sysfs_tag_type(sd) && >>> + (sysfs_type(sd) == SYSFS_DIR) && !sd->s_dir.children) { >>> + err = 0; >>> + sd->s_flags |= (type << SYSFS_TAG_TYPE_SHIFT); >>> + } >>> + mutex_unlock(&sysfs_mutex); >>> + return err; >>> +} >>> diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c >>> index 61c3476..091c0de 100644 >>> --- a/fs/sysfs/file.c >>> +++ b/fs/sysfs/file.c >>> @@ -476,9 +476,12 @@ void sysfs_notify(struct kobject *k, char *dir, char >>> *attr) >>> mutex_lock(&sysfs_mutex); >>> if (sd && dir) >>> - sd = sysfs_find_dirent(sd, dir); >>> + /* Only directories are tagged, so no need to pass >>> + * a tag explicitly. >>> + */ >>> + sd = sysfs_find_dirent(sd, NULL, dir); >>> if (sd && attr) >>> - sd = sysfs_find_dirent(sd, attr); >>> + sd = sysfs_find_dirent(sd, NULL, attr); >>> if (sd) >>> sysfs_notify_dirent(sd); >>> @@ -640,7 +643,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); >>> void sysfs_remove_file(struct kobject * kobj, const struct attribute * >>> attr) >>> { >>> - sysfs_hash_and_remove(kobj->sd, attr->name); >>> + sysfs_hash_and_remove(kobj, kobj->sd, attr->name); >>> } >>> @@ -660,7 +663,7 @@ void sysfs_remove_file_from_group(struct kobject >>> *kobj, >>> else >>> dir_sd = sysfs_get(kobj->sd); >>> if (dir_sd) { >>> - sysfs_hash_and_remove(dir_sd, attr->name); >>> + sysfs_hash_and_remove(kobj, dir_sd, attr->name); >>> sysfs_put(dir_sd); >>> } >>> } >>> diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c >>> index fe61194..5fba6f2 100644 >>> --- a/fs/sysfs/group.c >>> +++ b/fs/sysfs/group.c >>> @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, >>> struct kobject *kobj, >>> int i; >>> for (i = 0, attr = grp->attrs; *attr; i++, attr++) >>> - sysfs_hash_and_remove(dir_sd, (*attr)->name); >>> + sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name); >>> } >>> static int create_files(struct sysfs_dirent *dir_sd, struct kobject >>> *kobj, >>> @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd, >>> struct kobject *kobj, >>> * visibility. Do this by first removing then >>> * re-adding (if required) the file */ >>> if (update) >>> - sysfs_hash_and_remove(dir_sd, (*attr)->name); >>> + sysfs_hash_and_remove(kobj, dir_sd, >>> (*attr)->name); >>> if (grp->is_visible) { >>> mode = grp->is_visible(kobj, *attr, i); >>> if (!mode) >>> diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c >>> index 80f8fd4..b5fc78a 100644 >>> --- a/fs/sysfs/inode.c >>> +++ b/fs/sysfs/inode.c >>> @@ -226,17 +226,20 @@ struct inode * sysfs_get_inode(struct sysfs_dirent >>> *sd) >>> return inode; >>> } >>> -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) >>> +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent >>> *dir_sd, >>> + const char *name) >>> { >>> struct sysfs_addrm_cxt acxt; >>> struct sysfs_dirent *sd; >>> + const void *tag; >>> if (!dir_sd) >>> return -ENOENT; >>> sysfs_addrm_start(&acxt, dir_sd); >>> + tag = kobj->sd->s_tag; >>> - sd = sysfs_find_dirent(dir_sd, name); >>> + sd = sysfs_find_dirent(dir_sd, tag, name); >>> if (sd) >>> sysfs_remove_one(&acxt, sd); >>> diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c >>> index 6ebda1a..8f2237a 100644 >>> --- a/fs/sysfs/mount.c >>> +++ b/fs/sysfs/mount.c >>> @@ -35,12 +35,15 @@ static const struct super_operations sysfs_ops = { >>> struct sysfs_dirent sysfs_root = { >>> .s_name = "", >>> .s_count = ATOMIC_INIT(1), >>> - .s_flags = SYSFS_DIR, >>> + .s_flags = SYSFS_DIR | (SYSFS_TAG_TYPE_NONE << >>> SYSFS_TAG_TYPE_SHIFT), >>> .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, >>> .s_ino = 1, >>> }; >>> -static int sysfs_fill_super(struct super_block *sb, void *data, int >>> silent) >>> +struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; >>> + >>> +static int sysfs_fill_super(struct super_block *sb, void *data, int >>> silent, >>> + const void *tags[SYSFS_TAG_TYPES]) >>> { >>> struct sysfs_super_info *info = NULL; >>> struct inode *inode = NULL; >>> @@ -76,8 +79,10 @@ static int sysfs_fill_super(struct super_block *sb, >>> void *data, int silent) >>> goto out_err; >>> } >>> root->d_fsdata = &sysfs_root; >>> + root->d_sb = sb; >>> sb->s_root = root; >>> sb->s_fs_info = info; >>> + memcpy(info->tag, tags, sizeof(info->tag[0])*SYSFS_TAG_TYPES); >>> return 0; >>> out_err: >>> @@ -89,20 +94,74 @@ out_err: >>> return error; >>> } >>> +static int sysfs_test_super(struct super_block *sb, void *ptr) >>> +{ >>> + const void **tag = ptr; >>> + struct sysfs_super_info *info = sysfs_info(sb); >>> + enum sysfs_tag_type type; >>> + int found = 1; >>> + >>> + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { >>> + if (info->tag[type] != tag[type]) { >>> + found = 0; >>> + break; >>> + } >>> + } >>> + >>> + return found; >>> +} >>> + >>> static int sysfs_get_sb(struct file_system_type *fs_type, >>> int flags, const char *dev_name, void *data, struct vfsmount *mnt) >>> { >>> - int rc; >>> + const void *tag[SYSFS_TAG_TYPES]; >>> + struct super_block *sb; >>> + int error; >>> + enum sysfs_tag_type type; >>> + >>> + for (type = SYSFS_TAG_TYPE_NONE; type < SYSFS_TAG_TYPES; type++) { >>> + tag[type] = NULL; >>> + if (!tag_ops[type]) >>> + continue; >>> + tag[type] = tag_ops[type]->mount_tag(); >>> + } >>> + >>> mutex_lock(&sysfs_rename_mutex); >>> - rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); >>> + sb = sget(fs_type, sysfs_test_super, set_anon_super, tag); >>> + if (IS_ERR(sb)) { >>> + error = PTR_ERR(sb); >>> + goto out; >>> + } >>> + if (!sb->s_root) { >>> + sb->s_flags = flags; >>> + error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : >>> 0, >>> + tag); >>> + if (error) { >>> + up_write(&sb->s_umount); >>> + deactivate_super(sb); >>> + goto out; >>> + } >>> + sb->s_flags |= MS_ACTIVE; >>> + } >>> + do_remount_sb(sb, flags, data, 0); >>> + error = simple_set_mnt(mnt, sb); >>> +out: >>> mutex_unlock(&sysfs_rename_mutex); >>> - return rc; >>> + return error; >>> +} >>> + >>> +static void sysfs_kill_sb(struct super_block *sb) >>> +{ >>> + struct sysfs_super_info *info = sysfs_info(sb); >>> + >>> + kill_anon_super(sb); >>> + kfree(info); >>> } >>> struct file_system_type sysfs_fs_type = { >>> .name = "sysfs", >>> .get_sb = sysfs_get_sb, >>> - .kill_sb = kill_anon_super, >>> + .kill_sb = sysfs_kill_sb, >>> }; >>> void sysfs_grab_supers(void) >>> @@ -146,6 +205,50 @@ restart: >>> spin_unlock(&sb_lock); >>> } >>> +int sysfs_register_tag_type(enum sysfs_tag_type type, struct >>> sysfs_tag_type_operations *ops) >>> +{ >>> + int error; >>> + >>> + mutex_lock(&sysfs_rename_mutex); >>> + >>> + error = -EINVAL; >>> + if (type >= SYSFS_TAG_TYPES) >>> + goto out; >>> + >>> + error = -EINVAL; >>> + if (type <= SYSFS_TAG_TYPE_NONE) >>> + goto out; >>> + >>> + error = -EBUSY; >>> + if (tag_ops[type]) >>> + goto out; >>> + >>> + error = 0; >>> + tag_ops[type] = ops; >>> + >>> +out: >>> + mutex_unlock(&sysfs_rename_mutex); >>> + return error; >>> +} >>> + >>> +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag) >>> +{ >>> + /* Allow the tag to go away while sysfs is still mounted. */ >>> + struct super_block *sb; >>> + mutex_lock(&sysfs_rename_mutex); >>> + sysfs_grab_supers(); >>> + mutex_lock(&sysfs_mutex); >>> + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { >>> + struct sysfs_super_info *info = sysfs_info(sb); >>> + if (info->tag[type] != tag) >>> + continue; >>> + info->tag[type] = NULL; >>> + } >>> + mutex_unlock(&sysfs_mutex); >>> + sysfs_release_supers(); >>> + mutex_unlock(&sysfs_rename_mutex); >>> +} >>> + >>> int __init sysfs_init(void) >>> { >>> int err = -ENOMEM; >>> diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c >>> index a3ba217..54b2e5f 100644 >>> --- a/fs/sysfs/symlink.c >>> +++ b/fs/sysfs/symlink.c >>> @@ -119,7 +119,7 @@ void sysfs_remove_link(struct kobject * kobj, const >>> char * name) >>> else >>> parent_sd = kobj->sd; >>> - sysfs_hash_and_remove(parent_sd, name); >>> + sysfs_hash_and_remove(kobj, parent_sd, name); >>> } >>> static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, >>> diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h >>> index f0e5ecb..67115ec 100644 >>> --- a/fs/sysfs/sysfs.h >>> +++ b/fs/sysfs/sysfs.h >>> @@ -45,6 +45,7 @@ struct sysfs_dirent { >>> struct sysfs_dirent *s_sibling; >>> const char *s_name; >>> + const void *s_tag; >>> union { >>> struct sysfs_elem_dir s_dir; >>> struct sysfs_elem_symlink s_symlink; >>> @@ -67,14 +68,22 @@ struct sysfs_dirent { >>> #define SYSFS_KOBJ_LINK 0x0008 >>> #define SYSFS_COPY_NAME (SYSFS_DIR | >>> SYSFS_KOBJ_LINK) >>> -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK >>> -#define SYSFS_FLAG_REMOVED 0x0200 >>> +#define SYSFS_TAG_TYPE_MASK 0xff00 >>> +#define SYSFS_TAG_TYPE_SHIFT 8 >>> + >>> +#define SYSFS_FLAG_MASK ~(SYSFS_TYPE_MASK | >>> SYSFS_TAG_TYPE_MASK) >>> +#define SYSFS_FLAG_REMOVED 0x020000 >>> static inline unsigned int sysfs_type(struct sysfs_dirent *sd) >>> { >>> return sd->s_flags & SYSFS_TYPE_MASK; >>> } >>> +static inline enum sysfs_tag_type sysfs_tag_type(struct sysfs_dirent >>> *sd) >>> +{ >>> + return (sd->s_flags & SYSFS_TAG_TYPE_MASK) >> >>> SYSFS_TAG_TYPE_SHIFT; >>> +} >>> + >>> /* >>> * Context structure to be used while adding/removing nodes. >>> */ >>> @@ -87,6 +96,7 @@ struct sysfs_addrm_cxt { >>> struct sysfs_super_info { >>> int grabbed; >>> + const void *tag[SYSFS_TAG_TYPES]; >>> }; >>> #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) >>> @@ -98,6 +108,7 @@ extern struct sysfs_dirent sysfs_root; >>> extern struct super_block *sysfs_sb; >>> extern struct kmem_cache *sysfs_dir_cachep; >>> extern struct file_system_type sysfs_fs_type; >>> +extern struct sysfs_tag_type_operations *tag_ops[SYSFS_TAG_TYPES]; >>> void sysfs_grab_supers(void); >>> void sysfs_release_supers(void); >>> @@ -124,6 +135,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, >>> struct sysfs_dirent *sd); >>> void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); >>> struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, >>> + const void *tag, >>> const unsigned char *name); >>> struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, >>> const unsigned char *name); >>> @@ -158,7 +170,8 @@ static inline void __sysfs_put(struct sysfs_dirent >>> *sd) >>> struct inode *sysfs_get_inode(struct sysfs_dirent *sd); >>> int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct >>> iattr *iattr); >>> int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); >>> -int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); >>> +int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent >>> *dir_sd, >>> + const char *name); >>> int sysfs_inode_init(void); >>> /* >>> diff --git a/include/linux/kobject.h b/include/linux/kobject.h >>> index 5437ac0..beb3573 100644 >>> --- a/include/linux/kobject.h >>> +++ b/include/linux/kobject.h >>> @@ -105,6 +105,7 @@ struct kobj_type { >>> void (*release)(struct kobject *kobj); >>> struct sysfs_ops *sysfs_ops; >>> struct attribute **default_attrs; >>> + const void *(*sysfs_tag)(struct kobject *kobj); >>> }; >>> struct kobj_uevent_env { >>> diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h >>> index d8e0230..ba68829 100644 >>> --- a/include/linux/sysfs.h >>> +++ b/include/linux/sysfs.h >>> @@ -80,6 +80,15 @@ struct sysfs_ops { >>> struct sysfs_dirent; >>> +enum sysfs_tag_type { >>> + SYSFS_TAG_TYPE_NONE = 0, >>> + SYSFS_TAG_TYPES >>> +}; >>> + >>> +struct sysfs_tag_type_operations { >>> + const void *(*mount_tag)(void); >>> +}; >>> + >>> #ifdef CONFIG_SYSFS >>> int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), >>> @@ -126,6 +135,12 @@ struct sysfs_dirent *sysfs_get_dirent(struct >>> sysfs_dirent *parent_sd, >>> struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); >>> void sysfs_put(struct sysfs_dirent *sd); >>> void sysfs_printk_last_file(void); >>> + >>> +int sysfs_make_tagged_dir(struct kobject *, enum sysfs_tag_type >>> tag_type); >>> +int sysfs_register_tag_type(enum sysfs_tag_type type, >>> + struct sysfs_tag_type_operations *ops); >>> +void sysfs_exit_tag(enum sysfs_tag_type type, const void *tag); >>> + >>> int __must_check sysfs_init(void); >>> #else /* CONFIG_SYSFS */ >>> @@ -249,6 +264,22 @@ static inline void sysfs_put(struct sysfs_dirent *sd) >>> { >>> } >>> +staticn inline int sysfs_make_tagged_dir(struct kobject *kobj, >> ______^ >> >> This typo is still present in your patch in the CONFIG_SYSFS=n case. >> >> Otherwise the patchset, combined with the patches Greg has already >> merged in his tree, still works great for me with network namespaces. >> >> --Benjamin >> >>> + enum sysfs_tag_type >>> tag_type) >>> +{ >>> + return 0; >>> +} >>> + >>> +static inline int sysfs_register_tag_type(enum sysfs_tag_type type, >>> + struct sysfs_tag_type_operations >>> *ops) >>> +{ >>> + return 0; >>> +} >>> + >>> +static inline void sysfs_exit_tag(enum sysfs_tag_type type, const void >>> *tag) >>> +{ >>> +} >>> + >>> static inline int __must_check sysfs_init(void) >>> { >>> return 0; >> >> -- >> B e n j a m i n T h e r y - BULL/DT/Open Software R&D >> >> http://www.bull.com >> -- >> To unsubscribe from this list: send the line "unsubscribe netdev" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > > -- B e n j a m i n T h e r y - BULL/DT/Open Software R&D http://www.bull.com ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-09-02 14:03 ` Benjamin Thery @ 2008-09-02 17:01 ` Greg KH 2008-09-04 5:33 ` David Shwatrz 0 siblings, 1 reply; 145+ messages in thread From: Greg KH @ 2008-09-02 17:01 UTC (permalink / raw) To: Benjamin Thery Cc: Greg KH, Mark Ryden, Eric W. Biederman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev On Tue, Sep 02, 2008 at 04:03:20PM +0200, Benjamin Thery wrote: > Mark Ryden wrote: >> Hello, >> I hope that this patch (from 4.7.08) was not forgetten... I don't see >> it for example in linux-net (I have an up-to-date linux-next git >> tree). > > I was about to ask the same thing. > > Greg, what is the plan with these remaining patches for sysfs tagged > dirs? Will you have some time to merge them in your tree soon? Yes, they should go into my tree this week, sorry been busy with 2.6.27 work and Novell's Hackweek. thanks, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-09-02 17:01 ` Greg KH @ 2008-09-04 5:33 ` David Shwatrz 2008-09-04 6:44 ` Benjamin Thery 0 siblings, 1 reply; 145+ messages in thread From: David Shwatrz @ 2008-09-04 5:33 UTC (permalink / raw) To: Greg KH Cc: Benjamin Thery, Greg KH, Mark Ryden, Eric W. Biederman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Hi, >go into my tree this week, I am also interested in this patch; may I ask - what do you mean by "my tree" ?I am a little newbie in the kernel, as you might understand. I looked into http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ for candidates for this git tree you are talking about. May I ask: what is the **exact** URL for this git tree you are talking about ? Thanks, Regards, DS On Tue, Sep 2, 2008 at 8:01 PM, Greg KH <gregkh@suse.de> wrote: > On Tue, Sep 02, 2008 at 04:03:20PM +0200, Benjamin Thery wrote: >> Mark Ryden wrote: >>> Hello, >>> I hope that this patch (from 4.7.08) was not forgetten... I don't see >>> it for example in linux-net (I have an up-to-date linux-next git >>> tree). >> >> I was about to ask the same thing. >> >> Greg, what is the plan with these remaining patches for sysfs tagged >> dirs? Will you have some time to merge them in your tree soon? > > Yes, they should go into my tree this week, sorry been busy with 2.6.27 > work and Novell's Hackweek. > > thanks, > > greg k-h > -- > To unsubscribe from this list: send the line "unsubscribe netdev" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-09-04 5:33 ` David Shwatrz @ 2008-09-04 6:44 ` Benjamin Thery 2008-09-08 18:39 ` Mark Ryden 2008-10-07 16:39 ` Mark Ryden 0 siblings, 2 replies; 145+ messages in thread From: Benjamin Thery @ 2008-09-04 6:44 UTC (permalink / raw) To: David Shwatrz Cc: Greg KH, Greg KH, Mark Ryden, Eric W. Biederman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev David Shwatrz wrote: > Hi, >> go into my tree this week, > > I am also interested in this patch; may I ask - what do you mean by > "my tree" ?I am a little newbie in the kernel, as you might understand. > I looked into http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ > for candidates for this git tree you are talking about. > > May I ask: what is the **exact** URL for this git tree you are talking about ? Greg's tree is there: http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=summary You can clone it from here: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/patches.git It contains the patches serie to be applied on top of linux-2.6 (with 'quilt' for example). Benjamin > > Thanks, > > Regards, > DS > > > On Tue, Sep 2, 2008 at 8:01 PM, Greg KH <gregkh@suse.de> wrote: >> On Tue, Sep 02, 2008 at 04:03:20PM +0200, Benjamin Thery wrote: >>> Mark Ryden wrote: >>>> Hello, >>>> I hope that this patch (from 4.7.08) was not forgetten... I don't see >>>> it for example in linux-net (I have an up-to-date linux-next git >>>> tree). >>> I was about to ask the same thing. >>> >>> Greg, what is the plan with these remaining patches for sysfs tagged >>> dirs? Will you have some time to merge them in your tree soon? >> Yes, they should go into my tree this week, sorry been busy with 2.6.27 >> work and Novell's Hackweek. >> >> thanks, >> >> greg k-h >> -- >> To unsubscribe from this list: send the line "unsubscribe netdev" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > > -- B e n j a m i n T h e r y - BULL/DT/Open Software R&D http://www.bull.com ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-09-04 6:44 ` Benjamin Thery @ 2008-09-08 18:39 ` Mark Ryden 2008-10-07 16:39 ` Mark Ryden 1 sibling, 0 replies; 145+ messages in thread From: Mark Ryden @ 2008-09-08 18:39 UTC (permalink / raw) To: Benjamin Thery Cc: David Shwatrz, Greg KH, Greg KH, Eric W. Biederman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Hi, Well, I believe that again it was somehow forgotten or was not applied for other reasons, since polling the following URL several times in last days did not show this patch (url: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/patches.git) Regards, MR On Thu, Sep 4, 2008 at 9:44 AM, Benjamin Thery <benjamin.thery@bull.net> wrote: > David Shwatrz wrote: >> >> Hi, >>> >>> go into my tree this week, >> >> I am also interested in this patch; may I ask - what do you mean by >> "my tree" ?I am a little newbie in the kernel, as you might understand. >> I looked into >> http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ >> for candidates for this git tree you are talking about. >> >> May I ask: what is the **exact** URL for this git tree you are talking >> about ? > > Greg's tree is there: > http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=summary > > You can clone it from here: > git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/patches.git > > It contains the patches serie to be applied on top of > linux-2.6 (with 'quilt' for example). > > Benjamin > >> >> Thanks, >> >> Regards, >> DS >> >> >> On Tue, Sep 2, 2008 at 8:01 PM, Greg KH <gregkh@suse.de> wrote: >>> >>> On Tue, Sep 02, 2008 at 04:03:20PM +0200, Benjamin Thery wrote: >>>> >>>> Mark Ryden wrote: >>>>> >>>>> Hello, >>>>> I hope that this patch (from 4.7.08) was not forgetten... I don't see >>>>> it for example in linux-net (I have an up-to-date linux-next git >>>>> tree). >>>> >>>> I was about to ask the same thing. >>>> >>>> Greg, what is the plan with these remaining patches for sysfs tagged >>>> dirs? Will you have some time to merge them in your tree soon? >>> >>> Yes, they should go into my tree this week, sorry been busy with 2.6.27 >>> work and Novell's Hackweek. >>> >>> thanks, >>> >>> greg k-h >>> -- >>> To unsubscribe from this list: send the line "unsubscribe netdev" in >>> the body of a message to majordomo@vger.kernel.org >>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>> >> >> > > > -- > B e n j a m i n T h e r y - BULL/DT/Open Software R&D > > http://www.bull.com > ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-09-04 6:44 ` Benjamin Thery 2008-09-08 18:39 ` Mark Ryden @ 2008-10-07 16:39 ` Mark Ryden 2008-10-07 16:48 ` Greg KH 2008-10-07 16:52 ` Daniel Lezcano 1 sibling, 2 replies; 145+ messages in thread From: Mark Ryden @ 2008-10-07 16:39 UTC (permalink / raw) To: Benjamin Thery Cc: David Shwatrz, Greg KH, Greg KH, Eric W. Biederman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Hello, So I wonder: the sysfs tagged directory support patch is in GerKH tree for more than a month. I cloned today latest Linus tree (2.6.27-rc9) and it is not there as far as I can see. It is also not in linux-next tree (from september). Now, I wonder what is the process of merging this GregKH tree ? should I watch the LKML list for a pull request from GregKH? or will it be first merged into the linux-next tree? Regards, Mark On Thu, Sep 4, 2008 at 8:44 AM, Benjamin Thery <benjamin.thery@bull.net> wrote: > David Shwatrz wrote: >> >> Hi, >>> >>> go into my tree this week, >> >> I am also interested in this patch; may I ask - what do you mean by >> "my tree" ?I am a little newbie in the kernel, as you might understand. >> I looked into >> http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ >> for candidates for this git tree you are talking about. >> >> May I ask: what is the **exact** URL for this git tree you are talking >> about ? > > Greg's tree is there: > http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=summary > > You can clone it from here: > git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/patches.git > > It contains the patches serie to be applied on top of > linux-2.6 (with 'quilt' for example). > > Benjamin > >> >> Thanks, >> >> Regards, >> DS >> >> >> On Tue, Sep 2, 2008 at 8:01 PM, Greg KH <gregkh@suse.de> wrote: >>> >>> On Tue, Sep 02, 2008 at 04:03:20PM +0200, Benjamin Thery wrote: >>>> >>>> Mark Ryden wrote: >>>>> >>>>> Hello, >>>>> I hope that this patch (from 4.7.08) was not forgetten... I don't see >>>>> it for example in linux-net (I have an up-to-date linux-next git >>>>> tree). >>>> >>>> I was about to ask the same thing. >>>> >>>> Greg, what is the plan with these remaining patches for sysfs tagged >>>> dirs? Will you have some time to merge them in your tree soon? >>> >>> Yes, they should go into my tree this week, sorry been busy with 2.6.27 >>> work and Novell's Hackweek. >>> >>> thanks, >>> >>> greg k-h >>> -- >>> To unsubscribe from this list: send the line "unsubscribe netdev" in >>> the body of a message to majordomo@vger.kernel.org >>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>> >> >> > > > -- > B e n j a m i n T h e r y - BULL/DT/Open Software R&D > > http://www.bull.com > ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-07 16:39 ` Mark Ryden @ 2008-10-07 16:48 ` Greg KH 2008-10-07 20:31 ` Eric W. Biederman 2008-10-07 16:52 ` Daniel Lezcano 1 sibling, 1 reply; 145+ messages in thread From: Greg KH @ 2008-10-07 16:48 UTC (permalink / raw) To: Mark Ryden Cc: Benjamin Thery, David Shwatrz, Greg KH, Eric W. Biederman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev On Tue, Oct 07, 2008 at 06:39:04PM +0200, Mark Ryden wrote: > Hello, > So I wonder: the sysfs tagged directory support patch is in GerKH > tree for more than a month. I dropped it from my tree 2 days ago, see the thread on lkml for why. thanks, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-07 16:48 ` Greg KH @ 2008-10-07 20:31 ` Eric W. Biederman 2008-10-07 21:09 ` Greg KH 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-10-07 20:31 UTC (permalink / raw) To: Greg KH Cc: Mark Ryden, Benjamin Thery, David Shwatrz, Greg KH, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Greg KH <gregkh@suse.de> writes: > On Tue, Oct 07, 2008 at 06:39:04PM +0200, Mark Ryden wrote: >> Hello, >> So I wonder: the sysfs tagged directory support patch is in GerKH >> tree for more than a month. > > I dropped it from my tree 2 days ago, see the thread on lkml for why. Greg why did you drop it? Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-07 20:31 ` Eric W. Biederman @ 2008-10-07 21:09 ` Greg KH 2008-10-07 22:27 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Greg KH @ 2008-10-07 21:09 UTC (permalink / raw) To: Eric W. Biederman Cc: Mark Ryden, Benjamin Thery, David Shwatrz, Greg KH, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev On Tue, Oct 07, 2008 at 01:31:52PM -0700, Eric W. Biederman wrote: > Greg KH <gregkh@suse.de> writes: > > > On Tue, Oct 07, 2008 at 06:39:04PM +0200, Mark Ryden wrote: > >> Hello, > >> So I wonder: the sysfs tagged directory support patch is in GerKH > >> tree for more than a month. > > > > I dropped it from my tree 2 days ago, see the thread on lkml for why. > > Greg why did you drop it? Because Al said it was full of problems and for us not to accept it. thanks, greg k-h ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-07 21:09 ` Greg KH @ 2008-10-07 22:27 ` Eric W. Biederman 2008-10-08 13:00 ` Christoph Hellwig 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-10-07 22:27 UTC (permalink / raw) To: Greg KH Cc: Mark Ryden, Benjamin Thery, David Shwatrz, Greg KH, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Greg KH <gregkh@suse.de> writes: > On Tue, Oct 07, 2008 at 01:31:52PM -0700, Eric W. Biederman wrote: >> Greg KH <gregkh@suse.de> writes: >> >> > On Tue, Oct 07, 2008 at 06:39:04PM +0200, Mark Ryden wrote: >> >> Hello, >> >> So I wonder: the sysfs tagged directory support patch is in GerKH >> >> tree for more than a month. >> > >> > I dropped it from my tree 2 days ago, see the thread on lkml for why. >> >> Greg why did you drop it? > > Because Al said it was full of problems and for us not to accept it. Yes. Al found problems. Al reviewed sysfs with my patchset on top of it. Al's review found problems in sysfs with my patchset on top of it. If you look at what Al found the majority of those problems exist in sysfs without my patches. Does the following sound like a workable path going forward? - Not merge for 2.6.28 (we are to close to the merge window for everyone's comfort). - Fix the small issues specific to tagged directory support that showed up in Al's review (patches sent). - Keep the patches the entire time in a public tree that merges into linux-next so that people treat this code base seriously. - Resolve the sysfs/vfs lock ordering problem mess that makes locking in sysfs excruciatingly difficult. - Merge other patches to fix Als other issues with sysfs. - Merge to 2.6.29 or wherever we are. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-07 22:27 ` Eric W. Biederman @ 2008-10-08 13:00 ` Christoph Hellwig 2008-10-14 3:20 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Christoph Hellwig @ 2008-10-08 13:00 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg KH, Mark Ryden, Benjamin Thery, David Shwatrz, Greg KH, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev On Tue, Oct 07, 2008 at 03:27:12PM -0700, Eric W. Biederman wrote: > Al reviewed sysfs with my patchset on top of it. > > Al's review found problems in sysfs with my patchset on top of it. > > If you look at what Al found the majority of those problems exist in sysfs > without my patches. And when something is crap your fix it firdt before piling up more shit on top of it. And sysfs is a really severe case of that, and you're piling a _lot_ of shit ontop. ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-08 13:00 ` Christoph Hellwig @ 2008-10-14 3:20 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-10-14 3:20 UTC (permalink / raw) To: Christoph Hellwig Cc: Greg KH, Mark Ryden, Benjamin Thery, David Shwatrz, Greg KH, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, netdev Christoph Hellwig <hch@infradead.org> writes: > On Tue, Oct 07, 2008 at 03:27:12PM -0700, Eric W. Biederman wrote: >> Al reviewed sysfs with my patchset on top of it. >> >> Al's review found problems in sysfs with my patchset on top of it. >> >> If you look at what Al found the majority of those problems exist in sysfs >> without my patches. > > And when something is crap your fix it firdt before piling up more shit > on top of it. And sysfs is a really severe case of that, and you're > piling a _lot_ of shit ontop. Chistoph, your comments and Al's would have been much more productive if you have had said: "I didn't like sysfs because it doesn't do things the way other filesystems with similar problems do things. Can you please use common idioms? Making the code easier to read and making the code easier to maintain. Some of those constructs look awfully complex can you recheck you code and see if there is a simpler way to implement them." That would have been honest and productive. As it sits. I have partially inaccurate feedback from Al, useless feedback from you, and only my own tough skin and determination to keep me going.. The fact that you and Al look at the code and can't easily make sense of is a good sign that the code as written will be hard to maintain. Al's recent breakage of sysctl is a good example of that. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 1/8] sysfs: Implement sysfs tagged directory support. 2008-10-07 16:39 ` Mark Ryden 2008-10-07 16:48 ` Greg KH @ 2008-10-07 16:52 ` Daniel Lezcano 1 sibling, 0 replies; 145+ messages in thread From: Daniel Lezcano @ 2008-10-07 16:52 UTC (permalink / raw) To: Mark Ryden Cc: Benjamin Thery, David Shwatrz, Greg KH, Greg KH, Eric W. Biederman, Andrew Morton, Tejun Heo, linux-kernel, Al Viro, Linux Containers, netdev Mark Ryden wrote: > Hello, > So I wonder: the sysfs tagged directory support patch is in GerKH > tree for more than a month. > I cloned today latest Linus tree (2.6.27-rc9) and > it is not there as far as I can see. > It is also not in linux-next tree (from september). > Now, I wonder what is the process of merging this > GregKH tree ? should I watch the LKML list for a pull request > from GregKH? or will it be first merged into the linux-next tree? They have been dropped. http://marc.info/?l=linux-kernel&m=122318517411596&w=2 ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 0/8] sysfs namespace support 2008-08-21 6:31 ` [PATCH 0/8] sysfs namespace support Eric W. Biederman 2008-08-21 6:33 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Eric W. Biederman @ 2008-08-21 6:37 ` David Miller 1 sibling, 0 replies; 145+ messages in thread From: David Miller @ 2008-08-21 6:37 UTC (permalink / raw) To: ebiederm Cc: greg, gregkh, akpm, htejun, dlezcano, linux-kernel, viro, containers, benjamin.thery, netdev From: ebiederm@xmission.com (Eric W. Biederman) Date: Wed, 20 Aug 2008 23:31:00 -0700 > > Greg the first 4 patches are the rest of the infrastructure. > Everything rebased quite nicely. All of the conflicts appear > to have been false positives. > > With the addition of sysfs_rename_link sysfs_create_link_nowarn > is never called so we can remove it. > > I'm not really certain whose tree the last netns or the user > namespace changes should live in, but I am continuing to > have those patches in this patchset for completeness. You can send it all through Greg or whoever, don't feel obligated to push it through me since it depends upon the earlier bits in this series. ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 08/15] sysfs: Make sysfs_mount static once again. 2008-07-04 1:14 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Eric W. Biederman 2008-07-04 1:16 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Eric W. Biederman @ 2008-07-04 6:44 ` Tejun Heo 1 sibling, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-04 6:44 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Eric W. Biederman wrote: > Accessing the internal sysfs_mount is error prone in the context > of multiple super blocks, and nothing needs it. Not even the > sysfs crash debugging patch (although it did in an earlier version). > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Tejun Heo <tj@kernel.org> -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks 2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman 2008-07-04 1:14 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Eric W. Biederman @ 2008-07-04 6:44 ` Tejun Heo 2008-08-20 2:16 ` patch sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch added to gregkh-2.6 tree gregkh 2 siblings, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-04 6:44 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Eric W. Biederman wrote: > Teach sysfs_chmod_file how to handle multiple sysfs superblocks. > Since we only have one inode per sd the only thing we have to deal > with is multiple dentries for sending fs notifications. This might > dup the inode notifications oh well. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Great, Acked-by: Tejun Heo <tj@kernel.org> -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* patch sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch added to gregkh-2.6 tree 2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman 2008-07-04 1:14 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Eric W. Biederman 2008-07-04 6:44 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Tejun Heo @ 2008-08-20 2:16 ` gregkh 2 siblings, 0 replies; 145+ messages in thread From: gregkh @ 2008-08-20 2:16 UTC (permalink / raw) To: ebiederm, akpm, benjamin.thery, containers, dlezcano, gregkh, htejun, netdev, tj This is a note to let you know that I've just added the patch titled Subject: sysfs: sysfs_chmod_file handle multiple superblocks to my gregkh-2.6 tree. Its filename is sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm@xmission.com Thu Jul 3 18:21:56 2008 From: Eric W. Biederman <ebiederm@xmission.com> Date: Thu, 03 Jul 2008 18:13:05 -0700 Subject: sysfs: sysfs_chmod_file handle multiple superblocks To: Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org> Cc: Tejun Heo <htejun@gmail.com>, Daniel Lezcano <dlezcano@fr.ibm.com>, linux-kernel@vger.kernel.org, Al Viro <viro@ftp.linux.org.uk>, Linux Containers <containers@lists.osdl.org>, Benjamin Thery <benjamin.thery@bull.net>, <netdev@vger.kernel.org> Message-ID: <m14p76ih9a.fsf_-_@frodo.ebiederm.org> From: Eric W. Biederman <ebiederm@xmission.com> Teach sysfs_chmod_file how to handle multiple sysfs superblocks. Since we only have one inode per sd the only thing we have to deal with is multiple dentries for sending fs notifications. This might dup the inode notifications oh well. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/file.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -578,8 +578,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_grou int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct sysfs_dirent *victim_sd = NULL; - struct dentry *victim = NULL; - struct inode * inode; + struct super_block *sb; + struct inode * inode = NULL; struct iattr newattrs; int rc; @@ -588,31 +588,42 @@ int sysfs_chmod_file(struct kobject *kob if (!victim_sd) goto out; - mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(sysfs_sb, victim_sd); - mutex_unlock(&sysfs_rename_mutex); - if (IS_ERR(victim)) { - rc = PTR_ERR(victim); - victim = NULL; - goto out; - } - - inode = victim->d_inode; + rc = -ENOENT; + mutex_lock(&sysfs_mutex); + inode = sysfs_get_inode(victim_sd); + mutex_unlock(&sysfs_mutex); + if (!inode) + goto out; + mutex_lock(&sysfs_rename_mutex); + sysfs_grab_supers(); mutex_lock(&inode->i_mutex); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_ctime = current_fs_time(inode->i_sb); rc = sysfs_sd_setattr(victim_sd, inode, &newattrs); + if (rc) + goto out_unlock; + + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + /* Ignore it when the dentry does not exist on the + * target superblock. + */ + struct dentry * victim = sysfs_get_dentry(sb, victim_sd); + if (IS_ERR(victim)) + continue; - if (rc == 0) { fsnotify_change(victim, newattrs.ia_valid); + dput(victim); } + out_unlock: mutex_unlock(&inode->i_mutex); + sysfs_release_supers(); + mutex_unlock(&sysfs_rename_mutex); out: - dput(victim); + iput(inode); sysfs_put(victim_sd); return rc; } Patches currently in gregkh-2.6 which might be from ebiederm@xmission.com are driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/sysfs-implement-__sysfs_get_dentry.patch driver-core/sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch driver-core/sysfs-sysfs_get_dentry-add-a-sb-parameter.patch driver-core/sysfs-rename-support-multiple-superblocks.patch driver-core/sysfs-support-for-preventing-unmounts.patch driver-core/sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod 2008-07-04 1:11 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Eric W. Biederman 2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman @ 2008-07-04 6:40 ` Tejun Heo 2008-08-20 2:16 ` patch sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch added to gregkh-2.6 tree gregkh 2 siblings, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-04 6:40 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Eric W. Biederman wrote: > Currently sysfs_chmod calls sys_setattr which in turn calls > inode_change_ok which checks to see if it is ok for the current user > space process to change tha attributes. Since sysfs_chmod_file has > only kernel mode clients denying them permission if user space is the > problem is completely inappropriate. > > Therefore factor out sysfs_sd_setattr which does not call > inode_change_ok and modify sysfs_chmod_file to call it. > > In addition setting victim_sd->s_mode explicitly in sysfs_chmod_file > is redundant so remove that as well. > > Thanks to Tejun Heo <htejun@gmail.com>, and > Daniel Lezcano <dlezcano@fr.ibm.com> for working on this > and spotting this case. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Tejun Heo <tj@kernel.org> -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* patch sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch added to gregkh-2.6 tree 2008-07-04 1:11 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Eric W. Biederman 2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman 2008-07-04 6:40 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Tejun Heo @ 2008-08-20 2:16 ` gregkh 2 siblings, 0 replies; 145+ messages in thread From: gregkh @ 2008-08-20 2:16 UTC (permalink / raw) To: ebiederm, akpm, benjamin.thery, containers, dlezcano, gregkh, htejun, netdev, tj This is a note to let you know that I've just added the patch titled Subject: sysfs: Introduce sysfs_sd_setattr and fix sysfs_chmod to my gregkh-2.6 tree. Its filename is sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm@xmission.com Thu Jul 3 18:21:56 2008 From: Eric W. Biederman <ebiederm@xmission.com> Date: Thu, 03 Jul 2008 18:11:40 -0700 Subject: sysfs: Introduce sysfs_sd_setattr and fix sysfs_chmod To: Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org> Cc: Tejun Heo <htejun@gmail.com>, Daniel Lezcano <dlezcano@fr.ibm.com>, linux-kernel@vger.kernel.org, Al Viro <viro@ftp.linux.org.uk>, Linux Containers <containers@lists.osdl.org>, Benjamin Thery <benjamin.thery@bull.net>, <netdev@vger.kernel.org> Message-ID: <m18wwiihbn.fsf_-_@frodo.ebiederm.org> From: Eric W. Biederman <ebiederm@xmission.com> Currently sysfs_chmod calls sys_setattr which in turn calls inode_change_ok which checks to see if it is ok for the current user space process to change tha attributes. Since sysfs_chmod_file has only kernel mode clients denying them permission if user space is the problem is completely inappropriate. Therefore factor out sysfs_sd_setattr which does not call inode_change_ok and modify sysfs_chmod_file to call it. In addition setting victim_sd->s_mode explicitly in sysfs_chmod_file is redundant so remove that as well. Thanks to Tejun Heo <htejun@gmail.com>, and Daniel Lezcano <dlezcano@fr.ibm.com> for working on this and spotting this case. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/file.c | 5 +---- fs/sysfs/inode.c | 23 ++++++++++++++++------- fs/sysfs/sysfs.h | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -604,13 +604,10 @@ int sysfs_chmod_file(struct kobject *kob newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_ctime = current_fs_time(inode->i_sb); - rc = sysfs_setattr(victim, &newattrs); + rc = sysfs_sd_setattr(victim_sd, inode, &newattrs); if (rc == 0) { fsnotify_change(victim, newattrs.ia_valid); - mutex_lock(&sysfs_mutex); - victim_sd->s_mode = newattrs.ia_mode; - mutex_unlock(&sysfs_mutex); } mutex_unlock(&inode->i_mutex); --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -42,10 +42,9 @@ int __init sysfs_inode_init(void) return bdi_init(&sysfs_backing_dev_info); } -int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, + struct iattr * iattr) { - struct inode * inode = dentry->d_inode; - struct sysfs_dirent * sd = dentry->d_fsdata; struct iattr * sd_iattr; unsigned int ia_valid = iattr->ia_valid; int error; @@ -55,10 +54,6 @@ int sysfs_setattr(struct dentry * dentry sd_iattr = sd->s_iattr; - error = inode_change_ok(inode, iattr); - if (error) - return error; - iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ error = inode_setattr(inode, iattr); @@ -104,6 +99,20 @@ int sysfs_setattr(struct dentry * dentry return error; } +int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) +{ + struct inode * inode = dentry->d_inode; + struct sysfs_dirent * sd = dentry->d_fsdata; + int error; + + error = inode_change_ok(inode, iattr); + if (error) + return error; + + return sysfs_sd_setattr(sd, inode, iattr); +} + + static inline void set_default_inode_attr(struct inode * inode, mode_t mode) { inode->i_mode = mode; --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -156,6 +156,7 @@ static inline void __sysfs_put(struct sy * inode.c */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct inode *inode, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_inode_init(void); Patches currently in gregkh-2.6 which might be from ebiederm@xmission.com are driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/sysfs-implement-__sysfs_get_dentry.patch driver-core/sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch driver-core/sysfs-sysfs_get_dentry-add-a-sb-parameter.patch driver-core/sysfs-rename-support-multiple-superblocks.patch driver-core/sysfs-support-for-preventing-unmounts.patch driver-core/sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
* patch sysfs-rename-support-multiple-superblocks.patch added to gregkh-2.6 tree 2008-07-04 1:10 ` [PATCH 05/15] sysfs: Rename Support multiple superblocks Eric W. Biederman 2008-07-04 1:11 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Eric W. Biederman @ 2008-08-20 2:16 ` gregkh 1 sibling, 0 replies; 145+ messages in thread From: gregkh @ 2008-08-20 2:16 UTC (permalink / raw) To: ebiederm, akpm, benjamin.thery, containers, dlezcano, gregkh, htejun, netdev, tj This is a note to let you know that I've just added the patch titled Subject: sysfs: Rename Support multiple superblocks to my gregkh-2.6 tree. Its filename is sysfs-rename-support-multiple-superblocks.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm@xmission.com Thu Jul 3 18:11:52 2008 From: Eric W. Biederman <ebiederm@xmission.com> Date: Thu, 03 Jul 2008 18:10:05 -0700 Subject: sysfs: Rename Support multiple superblocks To: Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org> Cc: Tejun Heo <htejun@gmail.com>, Daniel Lezcano <dlezcano@fr.ibm.com>, linux-kernel@vger.kernel.org, Al Viro <viro@ftp.linux.org.uk>, Linux Containers <containers@lists.osdl.org>, Benjamin Thery <benjamin.thery@bull.net>, <netdev@vger.kernel.org> Message-ID: <m1d4luihea.fsf_-_@frodo.ebiederm.org> From: Eric W. Biederman <ebiederm@xmission.com> This patch modifies the sysfs_rename_dir and sysfs_move_dir routines to support multiple sysfs dentry tries rooted in different sysfs superblocks. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/dir.c | 195 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 137 insertions(+), 58 deletions(-) --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -834,43 +834,113 @@ static struct dentry *__sysfs_get_dentry return dentry; } +struct sysfs_rename_struct { + struct list_head list; + struct dentry *old_dentry; + struct dentry *new_dentry; + struct dentry *old_parent; + struct dentry *new_parent; +}; + +static void post_rename(struct list_head *head) +{ + struct sysfs_rename_struct *srs; + while (!list_empty(head)) { + srs = list_entry(head->next, struct sysfs_rename_struct, list); + dput(srs->old_dentry); + dput(srs->new_dentry); + dput(srs->old_parent); + dput(srs->new_parent); + list_del(&srs->list); + kfree(srs); + } +} + +static int prep_rename(struct list_head *head, + struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd, + const char *name) +{ + struct sysfs_rename_struct *srs; + struct super_block *sb; + struct dentry *dentry; + int error; + + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + dentry = sysfs_get_dentry(sb, sd); + if (dentry == ERR_PTR(-EXDEV)) + continue; + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto err_out; + } + + srs = kzalloc(sizeof(*srs), GFP_KERNEL); + if (!srs) { + error = -ENOMEM; + dput(dentry); + goto err_out; + } + + INIT_LIST_HEAD(&srs->list); + list_add(head, &srs->list); + srs->old_dentry = dentry; + srs->old_parent = dget(dentry->d_parent); + + dentry = sysfs_get_dentry(sb, new_parent_sd); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto err_out; + } + srs->new_parent = dentry; + + error = -ENOMEM; + dentry = d_alloc_name(srs->new_parent, name); + if (!dentry) + goto err_out; + srs->new_dentry = dentry; + } + return 0; + +err_out: + post_rename(head); + return error; +} + int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; - struct dentry *parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct list_head todo; + struct sysfs_rename_struct *srs; + struct inode *parent_inode = NULL; const char *dup_name = NULL; int error; + INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); error = 0; if (strcmp(sd->s_name, new_name) == 0) goto out; /* nothing to rename */ - /* get the original dentry */ - old_dentry = sysfs_get_dentry(sysfs_sb, sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } + sysfs_grab_supers(); + error = prep_rename(&todo, sd, sd->s_parent, new_name); + if (error) + goto out_release; - parent = old_dentry->d_parent; + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + parent_inode = sysfs_get_inode(sd->s_parent); + mutex_unlock(&sysfs_mutex); + if (!parent_inode) + goto out_release; - /* lock parent and get dentry for new name */ - mutex_lock(&parent->d_inode->i_mutex); + mutex_lock(&parent_inode->i_mutex); mutex_lock(&sysfs_mutex); error = -EEXIST; if (sysfs_find_dirent(sd->s_parent, new_name)) goto out_unlock; - error = -ENOMEM; - new_dentry = d_alloc_name(parent, new_name); - if (!new_dentry) - goto out_unlock; - /* rename sysfs_dirent */ error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); @@ -881,17 +951,21 @@ int sysfs_rename_dir(struct kobject * ko sd->s_name = new_name; /* rename */ - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + list_for_each_entry(srs, &todo, list) { + d_add(srs->new_dentry, NULL); + d_move(srs->old_dentry, srs->new_dentry); + } error = 0; - out_unlock: +out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&parent->d_inode->i_mutex); + mutex_unlock(&parent_inode->i_mutex); kfree(dup_name); - dput(old_dentry); - dput(new_dentry); - out: +out_release: + iput(parent_inode); + post_rename(&todo); + sysfs_release_supers(); +out: mutex_unlock(&sysfs_rename_mutex); return error; } @@ -900,10 +974,12 @@ int sysfs_move_dir(struct kobject *kobj, { struct sysfs_dirent *sd = kobj->sd; struct sysfs_dirent *new_parent_sd; - struct dentry *old_parent, *new_parent = NULL; - struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct list_head todo; + struct sysfs_rename_struct *srs; + struct inode *old_parent_inode = NULL, *new_parent_inode = NULL; int error; + INIT_LIST_HEAD(&todo); mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; @@ -912,26 +988,29 @@ int sysfs_move_dir(struct kobject *kobj, if (sd->s_parent == new_parent_sd) goto out; /* nothing to move */ - /* get dentries */ - old_dentry = sysfs_get_dentry(sysfs_sb, sd); - if (IS_ERR(old_dentry)) { - error = PTR_ERR(old_dentry); - old_dentry = NULL; - goto out; - } - old_parent = old_dentry->d_parent; - - new_parent = sysfs_get_dentry(sysfs_sb, new_parent_sd); - if (IS_ERR(new_parent)) { - error = PTR_ERR(new_parent); - new_parent = NULL; - goto out; - } + sysfs_grab_supers(); + error = prep_rename(&todo, sd, new_parent_sd, sd->s_name); + if (error) + goto out_release; + + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + old_parent_inode = sysfs_get_inode(sd->s_parent); + mutex_unlock(&sysfs_mutex); + if (!old_parent_inode) + goto out_release; + + error = -ENOMEM; + mutex_lock(&sysfs_mutex); + new_parent_inode = sysfs_get_inode(new_parent_sd); + mutex_unlock(&sysfs_mutex); + if (!new_parent_inode) + goto out_release; again: - mutex_lock(&old_parent->d_inode->i_mutex); - if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { - mutex_unlock(&old_parent->d_inode->i_mutex); + mutex_lock(&old_parent_inode->i_mutex); + if (!mutex_trylock(&new_parent_inode->i_mutex)) { + mutex_unlock(&old_parent_inode->i_mutex); goto again; } mutex_lock(&sysfs_mutex); @@ -940,14 +1019,11 @@ again: if (sysfs_find_dirent(new_parent_sd, sd->s_name)) goto out_unlock; - error = -ENOMEM; - new_dentry = d_alloc_name(new_parent, sd->s_name); - if (!new_dentry) - goto out_unlock; - error = 0; - d_add(new_dentry, NULL); - d_move(old_dentry, new_dentry); + list_for_each_entry(srs, &todo, list) { + d_add(srs->new_dentry, NULL); + d_move(srs->old_dentry, srs->new_dentry); + } /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); @@ -956,14 +1032,17 @@ again: sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); - out_unlock: +out_unlock: mutex_unlock(&sysfs_mutex); - mutex_unlock(&new_parent->d_inode->i_mutex); - mutex_unlock(&old_parent->d_inode->i_mutex); - out: - dput(new_parent); - dput(old_dentry); - dput(new_dentry); + mutex_unlock(&new_parent_inode->i_mutex); + mutex_unlock(&old_parent_inode->i_mutex); + +out_release: + iput(new_parent_inode); + iput(old_parent_inode); + post_rename(&todo); + sysfs_release_supers(); +out: mutex_unlock(&sysfs_rename_mutex); return error; } Patches currently in gregkh-2.6 which might be from ebiederm@xmission.com are driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/sysfs-implement-__sysfs_get_dentry.patch driver-core/sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch driver-core/sysfs-sysfs_get_dentry-add-a-sb-parameter.patch driver-core/sysfs-rename-support-multiple-superblocks.patch driver-core/sysfs-support-for-preventing-unmounts.patch driver-core/sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
* patch sysfs-implement-__sysfs_get_dentry.patch added to gregkh-2.6 tree 2008-07-04 1:09 ` [PATCH 04/15] sysfs: Implement __sysfs_get_dentry Eric W. Biederman 2008-07-04 1:10 ` [PATCH 05/15] sysfs: Rename Support multiple superblocks Eric W. Biederman @ 2008-08-20 2:16 ` gregkh 1 sibling, 0 replies; 145+ messages in thread From: gregkh @ 2008-08-20 2:16 UTC (permalink / raw) To: gregkh, akpm, benjamin.thery, containers, dlezcano, ebiederm, htejun, netdev, tj This is a note to let you know that I've just added the patch titled Subject: sysfs: Implement __sysfs_get_dentry to my gregkh-2.6 tree. Its filename is sysfs-implement-__sysfs_get_dentry.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm@xmission.com Thu Jul 3 18:11:48 2008 From: ebiederm@xmission.com (Eric W. Biederman) Date: Thu, 03 Jul 2008 18:09:04 -0700 Subject: sysfs: Implement __sysfs_get_dentry To: Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org> Cc: Tejun Heo <htejun@gmail.com>, Daniel Lezcano <dlezcano@fr.ibm.com>, linux-kernel@vger.kernel.org, Al Viro <viro@ftp.linux.org.uk>, Linux Containers <containers@lists.osdl.org>, Benjamin Thery <benjamin.thery@bull.net>, <netdev@vger.kernel.org> Message-ID: <m1hcb6ihfz.fsf_-_@frodo.ebiederm.org> From: Eric W. Biederman <ebiederm@xmission.com> This function is similar but much simpler to sysfs_get_dentry returns a sysfs dentry if one curently exists. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/dir.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -795,6 +795,45 @@ void sysfs_remove_dir(struct kobject * k __sysfs_remove_dir(sd); } +/** + * __sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sb: superblock of the dentry to return + * @sd: sysfs_dirent of interest + * + * Get dentry for @sd. Only return a dentry if one currently + * exists. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * Pointer to found dentry on success, NULL on failure. + */ +static struct dentry *__sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd) +{ + struct inode *inode; + struct dentry *dentry = NULL; + + inode = ilookup5_nowait(sysfs_sb, sd->s_ino, sysfs_ilookup_test, sd); + if (inode && !(inode->i_state & I_NEW)) { + struct dentry *alias; + spin_lock(&dcache_lock); + list_for_each_entry(alias, &inode->i_dentry, d_alias) { + if (!IS_ROOT(alias) && d_unhashed(alias)) + continue; + if (alias->d_sb != sb) + continue; + dentry = alias; + dget_locked(dentry); + break; + } + spin_unlock(&dcache_lock); + } + iput(inode); + return dentry; +} + int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; Patches currently in gregkh-2.6 which might be from gregkh@suse.de are .git/logs/refs/heads/master .git/logs/refs/heads/origin .git/logs/refs/remotes/aria/master .git/logs/refs/remotes/aria/origin .git/logs/HEAD bad/pci-domain/pci-device-ensure-sysdata-initialised.patch bad/pci-domain/pci-fix-the-x86-pci-domain-support-fix.patch bad/pci-domain/x86-pci-domain-support-struct-pci_sysdata.patch bad/pci-domain/x86-pci-domain-support-a-humble-fix.patch bad/pci-domain/x86-pci-domain-support-the-meat.patch bad/relayfs/relay-consolidate-relayfs-core-into-kernel-relay.c.patch bad/relayfs/relay-relay-header-cleanup.patch bad/relayfs/sysfs-add-__attr_relay-helper-for-relay-attributes.patch bad/relayfs/sysfs-relay-channel-buffers-as-sysfs-attributes.patch bad/usbip/usb-usbip-more-dead-code-fix.patch bad/usbip/usb-usbip-build-fix.patch bad/usbip/usb-usbip-warning-fixes.patch bad/ndevfs.patch bad/driver-sample.sh.patch bad/driver-model-convert-driver-model-to-mutexes.patch bad/gpl_future-test.patch bad/gregkh-debugfs_example.patch bad/i2c-device-id-lm75.patch bad/speakup-kconfig-fix.patch bad/speakup-build-fix.patch bad/pci-test-that-drivers-properly-call-pci_set_master.patch bad/pci-use-new-multi-phase-suspend-infrastructure.patch bad/speakup-core.patch bad/uio.patch bad/usbfs2.patch bad/no-more-non-gpl-modules.patch bad/usb-serial-serqt_usb.patch bad/spi-device.patch bad/ata_piix-multithread.patch bad/uio-irq.patch bad/sysfs-crash-debugging.patch bad/pci-dynamic-id-cleanup.patch bad/pci-piggy-bus.patch bad/input-device_type.patch bad/usb-iphone-charge.patch bad/sysfs-test.patch bad/ohci-fix-toggle-bit-desynchronization-when-canceling-urbs.patch bad/ldp/dvb-add-firesat-driver.patch bad/ldp/video-add-the-go7007-driver.patch bad/ldp/framebuffer-add-the-via-framebuffer-driver.patch bad/ldp/net-add-alacritech-slicoss-driver.patch bad/ldp/aectc-add-the-aectc-driver.patch bad/ldp/me4000-firmware-file.patch bad/ldp/novfs-add-the-novell-filesystem-client-kernel-module.patch bad/ldp/net-add-et131x-driver.patch bad/ldp/oms-add-oms-maxp-driver.patch bad/ldp/me4000-add-pci-data-collection-driver.patch bad/ldp/usb-add-usb-test-and-measurement-class-driver.patch bad/ldp/kolter_1616-add-kolter_1616-pci-i-o-driver.patch bad/ldp.next/usb-add-option-hso-driver.patch bad/ldp.next/usb-add-sensoray-2255-v4l-driver.patch bad/ldp.next/input-add-appleir-driver.patch gregkh/gkh-version.patch gregkh/sysrq-u-laptop.patch usb/usb-gotemp.patch usb/hso-fix-oops-in-read-write-callbacks.patch usb/hso-fix-refcounting-on-the-ttyhsx-devices.patch usb/usb-hso-make-tty_operations-const.patch usb/usb-hso-minor-fixes-due-to-code-review.patch usb/usb-add-config_usb_debug_messages-and-usb_dbg.patch usb/usb-convert-the-usb-core-code-to-use-usb_dbg.patch usb/usb-remove-config_usb_debug.patch usb/usb-convert-the-usb-host-controller-code-to-use-usb_dbg.patch usb/usb-remove-warn-macro-from-usb.h.patch usb/usb-remove-info-macro-from-usb.h.patch usb/hso-icon-322-detection-fix.patch usb/hso-dev_kfree_skb-crash-fix.patch usb/usb-add-new-pm-callback-methods-for-usb.patch usb/drivers-usb-class-usblp.c-adjust-error-handling-code.patch usb/usb-kill-urbs-permanently.patch usb/usb-extend-poisoning-to-anchors.patch usb/ub-remove-sg_stat.patch usb/usb-added-driver-for-a-delcom-usb-7-segment-led-display.patch usb/usb-add-udev-argument-to-interface-suspend-resume-functions.patch usb/usb-defer-set-interface-for-suspended-devices.patch usb/usb-don-t-rebind-before-complete-callback.patch usb/usb-gadget-dummy_hcd-implement-set_wedge.patch usb/usb-gadget-kconfig-cleanup.patch usb/usb-gadget-net2280-implement-set_wedge.patch usb/usb-let-some-usb-host-controllers-get-irq-flags-from-resource.patch usb/usb-removed-unused-include-version.h.patch usb.current/usb-cdc-acm-quirk-for-conexant-cx93010-usb-modem.patch usb.current/usb-fix-bug-in-usb_unlink_anchored_urbs.patch usb.current/usb-fix-pxa27x_udc-usb-speed-handling.patch usb.current/usb-isp1760-fixed-trivial-math-in-comment.patch usb.current/usb-serial-option-support-hsdpa-modem-a2502.patch HOWTO driver-core/sysfs-crash-debugging.patch driver-core/warn-when-statically-allocated-kobjects-are-used.patch driver-core/usb-gadget-make-gadget_core.ko.patch driver-core/net-convert-the-phy_device-file-to-use-bus_find_device_by_name.patch driver-core/s390-bus_id-dev_set_name-for-css-and-ccw-busses.patch driver-core/driver-core-make-struct-platform_pm_ops-static.patch driver-core/sysfs-support-sysfs_notify-from-atomic-context-with-new-sysfs_notify_dirent.patch driver-core/driver-core-basic-infrastructure-for-per-module-dynamic-debug-messages.patch driver-core/usb-gadget-move-f_acm.c-and-u_serial.c-gadget_acm_core.ko.patch driver-core/usb-gadget-move-f_ecm.c-to-gadget_ecm_core.ko.patch driver-core/usb-gadget-move-u_ether.c-to-gadget_ether_core.ko.patch driver-core/usb-gadget-move-library-files-into-g_cdc.ko.patch driver-core/usb-gadget-move-library-files-into-g_ether.ko.patch driver-core/usb-gadget-move-library-files-into-g_file_storage.ko.patch driver-core/usb-gadget-move-library-files-into-g_midi.ko.patch driver-core/usb-gadget-move-library-files-into-g_printer.ko.patch driver-core/usb-gadget-move-library-files-into-g_serial-ko.patch driver-core/usb-gadget-move-library-files-into-g_zero.ko.patch driver-core/device-create-block-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-char-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-ide-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-ieee1394-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-infiniband-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-misc-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-net-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-remove-device_create_drvdata.patch driver-core/device-create-s390-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-scsi-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-sound-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-usb-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-video-convert-device_create_drvdata-to-device_create.patch driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/sysfs-implement-__sysfs_get_dentry.patch driver-core/sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch driver-core/sysfs-sysfs_get_dentry-add-a-sb-parameter.patch driver-core/sysfs-rename-support-multiple-superblocks.patch driver-core/sysfs-support-for-preventing-unmounts.patch driver-core/sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch driver-core/driver-core-convert-to-new-device-api-to-allow-names-longer-than-20-chars.patch driver-core/driver-core-lguest-convert-to-new-device-api-to-allow-names-longer-than-20-chars.patch driver-core/driver-core-prepare-for-removal-of-20-char-limit-from-struct-device.patch driver-core/s390-bus_id-dev_set_name-changes.patch driver-core/s390-more-bus_id-dev_name-conversions.patch driver-core/s390-use-s390_root_dev_-in-kvm_virtio.patch driver-core/s390-bus_id-dev_name-conversions.patch driver-core/driver-core-provide-a-dev_set_name-that-handles-names-longer-than-20-chars.patch pending/perfmon-fix-up-some-static-kobject-usages.patch pending/kobject-change-sys-kernel-uids-to-not-use-a-kset.patch pending/kobjects-hook-them-up-to-the-debugobjects-infrastructure.patch pending/firmware-add-kconfig-and-makefile-to-build-the-firmware-samples.patch driver-core.current/dev_printk-constify-the-dev-argument.patch driver-core.current/drivers-base-driver.c-remove-unused-to_dev-macro.patch driver-core.current/japanese-translation-of-documentation-submitchecklist.patch driver-core.current/kobject-replace-all-occurrences-of-with-instead-of-only-the-first-one.patch driver-core.current/driver-model-anti-oopsing-medicine.patch driver-core.current/pm-don-t-skip-device-pm-init-when-config_pm_sleep-isn-t-set-and-config_pm-is-set.patch driver-core.current/driver-core-add-init_name-to-struct-device.patch driver-core.current/pm-remove-warn_on-from-device_pm_add.patch driver-core.current/block-drop-references-taken-by-class_find_device.patch driver-core.current/block-fix-partial-read-of-proc-partitions-diskstats.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
* patch sysfs-sysfs_get_dentry-add-a-sb-parameter.patch added to gregkh-2.6 tree 2008-07-04 1:08 ` [PATCH 03/15] sysfs: sysfs_get_dentry add a sb parameter Eric W. Biederman 2008-07-04 1:09 ` [PATCH 04/15] sysfs: Implement __sysfs_get_dentry Eric W. Biederman @ 2008-08-20 2:16 ` gregkh 1 sibling, 0 replies; 145+ messages in thread From: gregkh @ 2008-08-20 2:16 UTC (permalink / raw) To: ebiederm, akpm, benjamin.thery, containers, dlezcano, gregkh, htejun, netdev, tj This is a note to let you know that I've just added the patch titled Subject: sysfs: sysfs_get_dentry add a sb parameter to my gregkh-2.6 tree. Its filename is sysfs-sysfs_get_dentry-add-a-sb-parameter.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm@xmission.com Thu Jul 3 18:11:49 2008 From: Eric W. Biederman <ebiederm@xmission.com> Date: Thu, 03 Jul 2008 18:08:02 -0700 Subject: sysfs: sysfs_get_dentry add a sb parameter To: Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org> Cc: Tejun Heo <htejun@gmail.com>, Daniel Lezcano <dlezcano@fr.ibm.com>, linux-kernel@vger.kernel.org, Al Viro <viro@ftp.linux.org.uk>, Linux Containers <containers@lists.osdl.org>, Benjamin Thery <benjamin.thery@bull.net>, <netdev@vger.kernel.org> Message-ID: <m1lk0iihhp.fsf_-_@frodo.ebiederm.org> From: Eric W. Biederman <ebiederm@xmission.com> In preparation for multiple mounts of sysfs add a superblock parameter to sysfs_get_dentry. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/dir.c | 12 +++++++----- fs/sysfs/file.c | 2 +- fs/sysfs/sysfs.h | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -85,6 +85,7 @@ static void sysfs_unlink_sibling(struct /** * sysfs_get_dentry - get dentry for the given sysfs_dirent + * @sb: superblock of the dentry to return * @sd: sysfs_dirent of interest * * Get dentry for @sd. Dentry is looked up if currently not @@ -97,9 +98,10 @@ static void sysfs_unlink_sibling(struct * RETURNS: * Pointer to found dentry on success, ERR_PTR() value on error. */ -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) +struct dentry *sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd) { - struct dentry *dentry = dget(sysfs_sb->s_root); + struct dentry *dentry = dget(sb->s_root); while (dentry->d_fsdata != sd) { struct sysfs_dirent *cur; @@ -808,7 +810,7 @@ int sysfs_rename_dir(struct kobject * ko goto out; /* nothing to rename */ /* get the original dentry */ - old_dentry = sysfs_get_dentry(sd); + old_dentry = sysfs_get_dentry(sysfs_sb, sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); old_dentry = NULL; @@ -872,7 +874,7 @@ int sysfs_move_dir(struct kobject *kobj, goto out; /* nothing to move */ /* get dentries */ - old_dentry = sysfs_get_dentry(sd); + old_dentry = sysfs_get_dentry(sysfs_sb, sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); old_dentry = NULL; @@ -880,7 +882,7 @@ int sysfs_move_dir(struct kobject *kobj, } old_parent = old_dentry->d_parent; - new_parent = sysfs_get_dentry(new_parent_sd); + new_parent = sysfs_get_dentry(sysfs_sb, new_parent_sd); if (IS_ERR(new_parent)) { error = PTR_ERR(new_parent); new_parent = NULL; --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -589,7 +589,7 @@ int sysfs_chmod_file(struct kobject *kob goto out; mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(victim_sd); + victim = sysfs_get_dentry(sysfs_sb, victim_sd); mutex_unlock(&sysfs_rename_mutex); if (IS_ERR(victim)) { rc = PTR_ERR(victim); --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -112,7 +112,8 @@ extern spinlock_t sysfs_assoc_lock; extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; -struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); +struct dentry *sysfs_get_dentry(struct super_block *sb, + struct sysfs_dirent *sd); struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); void sysfs_put_active_two(struct sysfs_dirent *sd); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, Patches currently in gregkh-2.6 which might be from ebiederm@xmission.com are driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/sysfs-implement-__sysfs_get_dentry.patch driver-core/sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch driver-core/sysfs-sysfs_get_dentry-add-a-sb-parameter.patch driver-core/sysfs-rename-support-multiple-superblocks.patch driver-core/sysfs-support-for-preventing-unmounts.patch driver-core/sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <m1prpuihjb.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>]
* patch sysfs-support-for-preventing-unmounts.patch added to gregkh-2.6 tree [not found] ` <m1prpuihjb.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-08-20 2:16 ` gregkh-l3A5Bk7waGM 0 siblings, 0 replies; 145+ messages in thread From: gregkh-l3A5Bk7waGM @ 2008-08-20 2:16 UTC (permalink / raw) To: ebiederm-aS9lmoZGLiVWk0Htik3J/w, akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b, benjamin.thery-6ktuUTfB/bM, containers-qjLDD68F18O7TbgM5vRIOg, dlezcano-NmTC/0ZBporQT0dZR+AlfA, gregkh-l3A5Bk7waGM, htejun-Re5JQEeQqe8AvxtiuMwx3w, tj-DgEjT+Ai2ygdnm+yROfE0A This is a note to let you know that I've just added the patch titled Subject: sysfs: Support for preventing unmounts. to my gregkh-2.6 tree. Its filename is sysfs-support-for-preventing-unmounts.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org Thu Jul 3 18:11:50 2008 From: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> Date: Thu, 03 Jul 2008 18:07:04 -0700 Subject: sysfs: Support for preventing unmounts. To: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>, Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> Cc: Tejun Heo <htejun-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Al Viro <viro-rfM+Q5joDG/XmaaqVzeoHQ@public.gmane.org>, Linux Containers <containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org>, Benjamin Thery <benjamin.thery-6ktuUTfB/bM@public.gmane.org> Message-ID: <m1prpuihjb.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> From: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> To support mounting multiple instances of sysfs occassionally I need to walk through all of the currently present sysfs super blocks. To allow this iteration this patch adds sysfs_grab_supers and sysfs_release_supers. While a piece of code is in a section surrounded by these no more sysfs super blocks will be either created or destroyed. So the fundamentals. - The data in sysfs fundamentally changes behind the back of the VFS and we need to keep the VFS in sync. Essentially this is the distributed filesystem problem. - In particular for sysfs_rename and sysfs_move_dir we need to support finding the dcache entries and calling d_move. So that the dcache does not get into an inconsistent state. Timeouts and invalidates like NFS uses are to be avoided if at all possible. - Coming through the vfs we are guaranteed that the filesystem will not be unmounted while we have a reference on a dentry, and with multiple mounts we do not get that guarantee. Therefore to get that guarantee for all of the superblocks we need the blunt instrument. - Since mount/unmount are rare blocking them is no big deal. I believe any distributed filesystem that is together enough to tell us about renames (so we can update the dcache) instead of doing the NFS timeout will need the ability to block mount/unmount while it is executing d_move. Currently sysfs does not need to block mounts only because we perform an internal mount and then never unmount sysfs. Signed-off-by: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> Signed-off-by: Benjamin Thery <benjamin.thery-6ktuUTfB/bM@public.gmane.org> Signed-off-by: Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org> Acked-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> --- fs/sysfs/mount.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++------ fs/sysfs/sysfs.h | 10 ++++++ 2 files changed, 81 insertions(+), 8 deletions(-) --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -42,47 +42,110 @@ struct sysfs_dirent sysfs_root = { static int sysfs_fill_super(struct super_block *sb, void *data, int silent) { - struct inode *inode; - struct dentry *root; + struct sysfs_super_info *info = NULL; + struct inode *inode = NULL; + struct dentry *root = NULL; + int error; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = SYSFS_MAGIC; sb->s_op = &sysfs_ops; sb->s_time_gran = 1; - sysfs_sb = sb; + if (!sysfs_sb) + sysfs_sb = sb; + + error = -ENOMEM; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out_err; /* get root inode, initialize and unlock it */ + error = -ENOMEM; inode = sysfs_get_inode(&sysfs_root); if (!inode) { pr_debug("sysfs: could not get root inode\n"); - return -ENOMEM; + goto out_err; } /* instantiate and link root dentry */ + error = -ENOMEM; root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); - iput(inode); - return -ENOMEM; + goto out_err; } root->d_fsdata = &sysfs_root; sb->s_root = root; + sb->s_fs_info = info; return 0; + +out_err: + dput(root); + iput(inode); + kfree(info); + if (sysfs_sb == sb) + sysfs_sb = NULL; + return error; } static int sysfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + int rc; + mutex_lock(&sysfs_rename_mutex); + rc = get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); + mutex_unlock(&sysfs_rename_mutex); + return rc; } -static struct file_system_type sysfs_fs_type = { +struct file_system_type sysfs_fs_type = { .name = "sysfs", .get_sb = sysfs_get_sb, .kill_sb = kill_anon_super, }; +void sysfs_grab_supers(void) +{ + /* must hold sysfs_rename_mutex */ + struct super_block *sb; + /* Loop until I have taken s_umount on all sysfs superblocks */ +restart: + spin_lock(&sb_lock); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + if (sysfs_info(sb)->grabbed) + continue; + /* Wait for unmount activity to complete. */ + if (sb->s_count < S_BIAS) { + sb->s_count += 1; + spin_unlock(&sb_lock); + down_read(&sb->s_umount); + drop_super(sb); + goto restart; + } + atomic_inc(&sb->s_active); + sysfs_info(sb)->grabbed = 1; + } + spin_unlock(&sb_lock); +} + +void sysfs_release_supers(void) +{ + /* must hold sysfs_rename_mutex */ + struct super_block *sb; +restart: + spin_lock(&sb_lock); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + if (!sysfs_info(sb)->grabbed) + continue; + sysfs_info(sb)->grabbed = 0; + spin_unlock(&sb_lock); + deactivate_super(sb); + goto restart; + } + spin_unlock(&sb_lock); +} + int __init sysfs_init(void) { int err = -ENOMEM; --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -85,12 +85,22 @@ struct sysfs_addrm_cxt { int cnt; }; +struct sysfs_super_info { + int grabbed; +}; + +#define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info) + /* * mount.c */ extern struct sysfs_dirent sysfs_root; extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; +extern struct file_system_type sysfs_fs_type; + +void sysfs_grab_supers(void); +void sysfs_release_supers(void); /* * dir.c Patches currently in gregkh-2.6 which might be from ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org are driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/sysfs-implement-__sysfs_get_dentry.patch driver-core/sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch driver-core/sysfs-sysfs_get_dentry-add-a-sb-parameter.patch driver-core/sysfs-rename-support-multiple-superblocks.patch driver-core/sysfs-support-for-preventing-unmounts.patch driver-core/sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS 2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman 2008-07-04 1:07 ` [PATCH 02/15] sysfs: Support for preventing unmounts Eric W. Biederman @ 2008-07-04 6:33 ` Tejun Heo 2008-08-20 1:48 ` patch kobject-cleanup-kobject_rename-and-config_sysfs.patch added to gregkh-2.6 tree gregkh 2 siblings, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-07-04 6:33 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Eric W. Biederman wrote: > It finally dawned on me what the clean fix to sysfs_rename_dir > calling kobject_set_name is. Move the work into kobject_rename > where it belongs. The callers serialize us anyway so this is > safe. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Nice clean up. Acked-by: Tejun Heo <tj@kernel.org> -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* patch kobject-cleanup-kobject_rename-and-config_sysfs.patch added to gregkh-2.6 tree 2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman 2008-07-04 1:07 ` [PATCH 02/15] sysfs: Support for preventing unmounts Eric W. Biederman 2008-07-04 6:33 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Tejun Heo @ 2008-08-20 1:48 ` gregkh 2 siblings, 0 replies; 145+ messages in thread From: gregkh @ 2008-08-20 1:48 UTC (permalink / raw) To: gregkh, akpm, benjamin.thery, containers, dlezcano, ebiederm, htejun, netdev, tj This is a note to let you know that I've just added the patch titled Subject: kobject: Cleanup kobject_rename and !CONFIG_SYSFS to my gregkh-2.6 tree. Its filename is kobject-cleanup-kobject_rename-and-config_sysfs.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ From ebiederm@xmission.com Thu Jul 3 18:11:54 2008 From: ebiederm@xmission.com (Eric W. Biederman) Date: Thu, 03 Jul 2008 18:05:28 -0700 Subject: kobject: Cleanup kobject_rename and !CONFIG_SYSFS To: ebiederm@xmission.com (Eric W. Biederman) Cc: Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org>, Tejun Heo <htejun@gmail.com>, Daniel Lezcano <dlezcano@fr.ibm.com>, linux-kernel@vger.kernel.org, Al Viro <viro@ftp.linux.org.uk>, Linux Containers <containers@lists.osdl.org>, Benjamin Thery <benjamin.thery@bull.net>, <netdev@vger.kernel.org> Message-ID: <m1tzf6ihlz.fsf_-_@frodo.ebiederm.org> It finally dawned on me what the clean fix to sysfs_rename_dir calling kobject_set_name is. Move the work into kobject_rename where it belongs. The callers serialize us anyway so this is safe. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/sysfs/dir.c | 6 +----- include/linux/sysfs.h | 4 +--- lib/kobject.c | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -830,16 +830,12 @@ int sysfs_rename_dir(struct kobject * ko if (!new_dentry) goto out_unlock; - /* rename kobject and sysfs_dirent */ + /* rename sysfs_dirent */ error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); if (!new_name) goto out_unlock; - error = kobject_set_name(kobj, "%s", new_name); - if (error) - goto out_unlock; - dup_name = sd->s_name; sd->s_name = new_name; --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -20,8 +20,6 @@ struct kobject; struct module; -extern int kobject_set_name(struct kobject *kobj, const char *name, ...) - __attribute__((format(printf, 2, 3))); /* FIXME * The *owner field is no longer used, but leave around * until the tree gets cleaned up fully. @@ -149,7 +147,7 @@ static inline void sysfs_remove_dir(stru static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name) { - return kobject_set_name(kobj, "%s", new_name); + return 0; } static inline int sysfs_move_dir(struct kobject *kobj, --- a/lib/kobject.c +++ b/lib/kobject.c @@ -447,6 +447,7 @@ int kobject_rename(struct kobject *kobj, { int error = 0; const char *devpath = NULL; + const char *dup_name = NULL, *name; char *devpath_string = NULL; char *envp[2]; @@ -470,15 +471,27 @@ int kobject_rename(struct kobject *kobj, envp[0] = devpath_string; envp[1] = NULL; + name = dup_name = kstrdup(new_name, GFP_KERNEL); + if (!name) { + error = -ENOMEM; + goto out; + } + error = sysfs_rename_dir(kobj, new_name); + if (error) + goto out; + + /* Install the new kobject name */ + dup_name = kobj->name; + kobj->name = name; /* This function is mostly/only used for network interface. * Some hotplug package track interfaces by their name and * therefore want to know when the name is changed by the user. */ - if (!error) - kobject_uevent_env(kobj, KOBJ_MOVE, envp); + kobject_uevent_env(kobj, KOBJ_MOVE, envp); out: + kfree(dup_name); kfree(devpath_string); kfree(devpath); kobject_put(kobj); Patches currently in gregkh-2.6 which might be from gregkh@suse.de are .git/logs/refs/heads/master .git/logs/refs/heads/origin .git/logs/refs/remotes/aria/master .git/logs/refs/remotes/aria/origin .git/logs/HEAD bad/pci-domain/pci-device-ensure-sysdata-initialised.patch bad/pci-domain/pci-fix-the-x86-pci-domain-support-fix.patch bad/pci-domain/x86-pci-domain-support-struct-pci_sysdata.patch bad/pci-domain/x86-pci-domain-support-a-humble-fix.patch bad/pci-domain/x86-pci-domain-support-the-meat.patch bad/relayfs/relay-consolidate-relayfs-core-into-kernel-relay.c.patch bad/relayfs/relay-relay-header-cleanup.patch bad/relayfs/sysfs-add-__attr_relay-helper-for-relay-attributes.patch bad/relayfs/sysfs-relay-channel-buffers-as-sysfs-attributes.patch bad/usbip/usb-usbip-more-dead-code-fix.patch bad/usbip/usb-usbip-build-fix.patch bad/usbip/usb-usbip-warning-fixes.patch bad/ndevfs.patch bad/driver-sample.sh.patch bad/driver-model-convert-driver-model-to-mutexes.patch bad/gpl_future-test.patch bad/gregkh-debugfs_example.patch bad/i2c-device-id-lm75.patch bad/speakup-kconfig-fix.patch bad/speakup-build-fix.patch bad/pci-test-that-drivers-properly-call-pci_set_master.patch bad/pci-use-new-multi-phase-suspend-infrastructure.patch bad/speakup-core.patch bad/uio.patch bad/usbfs2.patch bad/no-more-non-gpl-modules.patch bad/usb-serial-serqt_usb.patch bad/spi-device.patch bad/ata_piix-multithread.patch bad/uio-irq.patch bad/sysfs-crash-debugging.patch bad/pci-dynamic-id-cleanup.patch bad/pci-piggy-bus.patch bad/input-device_type.patch bad/usb-iphone-charge.patch bad/sysfs-test.patch bad/ohci-fix-toggle-bit-desynchronization-when-canceling-urbs.patch bad/ldp/dvb-add-firesat-driver.patch bad/ldp/video-add-the-go7007-driver.patch bad/ldp/framebuffer-add-the-via-framebuffer-driver.patch bad/ldp/net-add-alacritech-slicoss-driver.patch bad/ldp/aectc-add-the-aectc-driver.patch bad/ldp/me4000-firmware-file.patch bad/ldp/novfs-add-the-novell-filesystem-client-kernel-module.patch bad/ldp/net-add-et131x-driver.patch bad/ldp/oms-add-oms-maxp-driver.patch bad/ldp/me4000-add-pci-data-collection-driver.patch bad/ldp/usb-add-usb-test-and-measurement-class-driver.patch bad/ldp/kolter_1616-add-kolter_1616-pci-i-o-driver.patch bad/ldp.next/usb-add-option-hso-driver.patch bad/ldp.next/usb-add-sensoray-2255-v4l-driver.patch bad/ldp.next/input-add-appleir-driver.patch gregkh/gkh-version.patch gregkh/sysrq-u-laptop.patch usb/usb-gotemp.patch usb/hso-fix-oops-in-read-write-callbacks.patch usb/hso-fix-refcounting-on-the-ttyhsx-devices.patch usb/usb-hso-make-tty_operations-const.patch usb/usb-hso-minor-fixes-due-to-code-review.patch usb/usb-add-config_usb_debug_messages-and-usb_dbg.patch usb/usb-convert-the-usb-core-code-to-use-usb_dbg.patch usb/usb-remove-config_usb_debug.patch usb/usb-convert-the-usb-host-controller-code-to-use-usb_dbg.patch usb/usb-remove-warn-macro-from-usb.h.patch usb/usb-remove-info-macro-from-usb.h.patch usb/hso-icon-322-detection-fix.patch usb/hso-dev_kfree_skb-crash-fix.patch usb/usb-add-new-pm-callback-methods-for-usb.patch usb/drivers-usb-class-usblp.c-adjust-error-handling-code.patch usb/usb-kill-urbs-permanently.patch usb/usb-extend-poisoning-to-anchors.patch usb/ub-remove-sg_stat.patch usb/usb-added-driver-for-a-delcom-usb-7-segment-led-display.patch usb/usb-add-udev-argument-to-interface-suspend-resume-functions.patch usb/usb-defer-set-interface-for-suspended-devices.patch usb/usb-don-t-rebind-before-complete-callback.patch usb/usb-gadget-dummy_hcd-implement-set_wedge.patch usb/usb-gadget-kconfig-cleanup.patch usb/usb-gadget-net2280-implement-set_wedge.patch usb/usb-let-some-usb-host-controllers-get-irq-flags-from-resource.patch usb/usb-removed-unused-include-version.h.patch usb.current/usb-cdc-acm-quirk-for-conexant-cx93010-usb-modem.patch usb.current/usb-fix-bug-in-usb_unlink_anchored_urbs.patch usb.current/usb-fix-pxa27x_udc-usb-speed-handling.patch usb.current/usb-isp1760-fixed-trivial-math-in-comment.patch usb.current/usb-serial-option-support-hsdpa-modem-a2502.patch HOWTO driver-core/put_device-might_sleep.patch driver-core/sysfs-crash-debugging.patch driver-core/warn-when-statically-allocated-kobjects-are-used.patch driver-core/usb-gadget-make-gadget_core.ko.patch driver-core/net-convert-the-phy_device-file-to-use-bus_find_device_by_name.patch driver-core/s390-bus_id-dev_set_name-for-css-and-ccw-busses.patch driver-core/driver-core-make-struct-platform_pm_ops-static.patch driver-core/sysfs-support-sysfs_notify-from-atomic-context-with-new-sysfs_notify_dirent.patch driver-core/driver-core-basic-infrastructure-for-per-module-dynamic-debug-messages.patch driver-core/usb-gadget-move-f_acm.c-and-u_serial.c-gadget_acm_core.ko.patch driver-core/usb-gadget-move-f_ecm.c-to-gadget_ecm_core.ko.patch driver-core/usb-gadget-move-u_ether.c-to-gadget_ether_core.ko.patch driver-core/usb-gadget-move-library-files-into-g_cdc.ko.patch driver-core/usb-gadget-move-library-files-into-g_ether.ko.patch driver-core/usb-gadget-move-library-files-into-g_file_storage.ko.patch driver-core/usb-gadget-move-library-files-into-g_midi.ko.patch driver-core/usb-gadget-move-library-files-into-g_printer.ko.patch driver-core/usb-gadget-move-library-files-into-g_serial-ko.patch driver-core/usb-gadget-move-library-files-into-g_zero.ko.patch driver-core/device-create-block-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-char-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-ide-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-ieee1394-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-infiniband-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-misc-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-net-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-remove-device_create_drvdata.patch driver-core/device-create-s390-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-scsi-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-sound-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-usb-convert-device_create_drvdata-to-device_create.patch driver-core/device-create-video-convert-device_create_drvdata-to-device_create.patch driver-core/kobject-fix-kobject_rename-and-config_sysfs.patch driver-core/kobject-cleanup-kobject_rename-and-config_sysfs.patch driver-core/driver-core-convert-to-new-device-api-to-allow-names-longer-than-20-chars.patch driver-core/driver-core-lguest-convert-to-new-device-api-to-allow-names-longer-than-20-chars.patch driver-core/driver-core-prepare-for-removal-of-20-char-limit-from-struct-device.patch driver-core/s390-bus_id-dev_set_name-changes.patch driver-core/s390-more-bus_id-dev_name-conversions.patch driver-core/s390-use-s390_root_dev_-in-kvm_virtio.patch driver-core/s390-bus_id-dev_name-conversions.patch driver-core/driver-core-provide-a-dev_set_name-that-handles-names-longer-than-20-chars.patch pending/perfmon-fix-up-some-static-kobject-usages.patch pending/kobject-change-sys-kernel-uids-to-not-use-a-kset.patch pending/kobjects-hook-them-up-to-the-debugobjects-infrastructure.patch pending/firmware-add-kconfig-and-makefile-to-build-the-firmware-samples.patch driver-core.current/dev_printk-constify-the-dev-argument.patch driver-core.current/drivers-base-driver.c-remove-unused-to_dev-macro.patch driver-core.current/japanese-translation-of-documentation-submitchecklist.patch driver-core.current/kobject-replace-all-occurrences-of-with-instead-of-only-the-first-one.patch driver-core.current/driver-model-anti-oopsing-medicine.patch driver-core.current/pm-don-t-skip-device-pm-init-when-config_pm_sleep-isn-t-set-and-config_pm-is-set.patch driver-core.current/driver-core-add-init_name-to-struct-device.patch driver-core.current/pm-remove-warn_on-from-device_pm_add.patch driver-core.current/block-drop-references-taken-by-class_find_device.patch driver-core.current/block-fix-partial-read-of-proc-partitions-diskstats.patch ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 00/15] sysfs support for namespaces 2008-07-04 0:48 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman 2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman @ 2008-07-04 1:27 ` Eric W. Biederman 2008-07-06 4:42 ` Eric W. Biederman 2 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-04 1:27 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev I should mention patches 1-12 are the core of the work. Patches 13-15 are the users. Included in complete form primarily to aid review. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 00/15] sysfs support for namespaces 2008-07-04 0:48 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman 2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman 2008-07-04 1:27 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman @ 2008-07-06 4:42 ` Eric W. Biederman 2008-07-07 11:41 ` Cornelia Huck 2 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-07-06 4:42 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev, Cornelia Huck > These patches are based off of 2.6.26-rc8 + the -gregkh tree from > last night. Hopefully that means they apply -mm -gregkh and > -linux-next. A quick update. My patchset conflicts with the recently added driver-core-suppress-sysfs-warnings-for-device_rename.patch > driver core: Suppress sysfs warnings for device_rename(). > > Renaming network devices to an already existing name is not > something we want sysfs to print a scary warning for, since the > callers can deal with this correctly. So let's introduce > sysfs_create_link_nowarn() which gets rid of the common warning. This patch is unnecessary as that path is never exercised anymore. as: dev_change_name returns early in the case of a noop rename. In addition my introduction sysfs_rename_link handles this case cleanly by first removing the old link and then creating the new link. Preventing false positives when the link names are the same. So it should be safe to drop Cornelia patch without a reoccurance of scary errors. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 00/15] sysfs support for namespaces 2008-07-06 4:42 ` Eric W. Biederman @ 2008-07-07 11:41 ` Cornelia Huck 2008-07-07 12:22 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Cornelia Huck @ 2008-07-07 11:41 UTC (permalink / raw) To: Eric W. Biederman Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev On Sat, 05 Jul 2008 21:42:57 -0700, ebiederm@xmission.com (Eric W. Biederman) wrote: > > > These patches are based off of 2.6.26-rc8 + the -gregkh tree from > > last night. Hopefully that means they apply -mm -gregkh and > > -linux-next. > > A quick update. My patchset conflicts with the recently added > driver-core-suppress-sysfs-warnings-for-device_rename.patch > > > driver core: Suppress sysfs warnings for device_rename(). > > > > Renaming network devices to an already existing name is not > > something we want sysfs to print a scary warning for, since the > > callers can deal with this correctly. So let's introduce > > sysfs_create_link_nowarn() which gets rid of the common warning. > > This patch is unnecessary as that path is never exercised anymore. > as: dev_change_name returns early in the case of a noop rename. My impression was that the networking folks didn't want any warnings for renaming failures, not just not for renaming a device to the same name. > > In addition my introduction sysfs_rename_link handles this case > cleanly by first removing the old link and then creating the new > link. Preventing false positives when the link names are the same. sysfs_rename_link() looks cleaner, I agree. > > So it should be safe to drop Cornelia patch without a reoccurance > of scary errors. Hm, the description looks badly worded - I unfortunately left the old text unchanged when I respun the patch :( The patch re-introduces the warning in sysfs_add_one() which had been removed in the meanwhile and makes device_rename() use a non-warning version. I still think we want a warning for the general case since this is usually caused be some problems in the calling code (and the alternative would be to add checks to all callers.) ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 00/15] sysfs support for namespaces 2008-07-07 11:41 ` Cornelia Huck @ 2008-07-07 12:22 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-07-07 12:22 UTC (permalink / raw) To: Cornelia Huck Cc: Greg Kroah-Hartman, Andrew Morton, Tejun Heo, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers, Benjamin Thery, netdev Cornelia Huck <cornelia.huck@de.ibm.com> writes: > My impression was that the networking folks didn't want any warnings for > renaming failures, not just not for renaming a device to the same name. Which would be reasonable. Because all of the checks have been done before sysfs is called so if sysfs sees a problem it is a sysfs bug. >> In addition my introduction sysfs_rename_link handles this case >> cleanly by first removing the old link and then creating the new >> link. Preventing false positives when the link names are the same. > > sysfs_rename_link() looks cleaner, I agree. > >> >> So it should be safe to drop Cornelia patch without a reoccurance >> of scary errors. > > Hm, the description looks badly worded - I unfortunately left the old > text unchanged when I respun the patch :( The patch re-introduces the > warning in sysfs_add_one() which had been removed in the meanwhile and > makes device_rename() use a non-warning version. I still think we want > a warning for the general case since this is usually caused be some > problems in the calling code (and the alternative would be to add > checks to all callers.) Right. We just need to get the sysfs paths clean enough that we don't emit false positives. I think I have accomplished that for rename. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (5 preceding siblings ...) 2008-06-18 17:08 ` [PATCH 06/11] sysfs: Implement sysfs tagged directory support Benjamin Thery @ 2008-06-18 17:08 ` Benjamin Thery 2008-06-23 2:13 ` Tejun Heo 2008-06-18 17:08 ` [PATCH 08/11] driver core: Implement tagged directory support for device classes Benjamin Thery ` (3 subsequent siblings) 10 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: Implement sysfs_delete_link and sysfs_rename_link When removing a symlink sysfs_remove_link does not provide enough information to figure out which tagged directory the symlink falls in. So I need sysfs_delete_link which is passed the target of the symlink to delete. Further half the time when we are removing a symlink the code is actually renaming the symlink but not doing so explicitly because we don't have a symlink rename method. So I have added sysfs_rename_link as well. Both of these functions now have enough information to find a symlink in a tagged directory. The only restriction is that they must be called before the target kobject is renamed or deleted. If they are called later I loose track of which tag the target kobject was marked with and can no longer find the old symlink to remove it. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/symlink.c | 31 +++++++++++++++++++++++++++++++ include/linux/sysfs.h | 17 +++++++++++++++++ 2 files changed, 48 insertions(+) Index: linux-mm/fs/sysfs/symlink.c =================================================================== --- linux-mm.orig/fs/sysfs/symlink.c +++ linux-mm/fs/sysfs/symlink.c @@ -80,6 +80,21 @@ int sysfs_create_link(struct kobject * k } /** + * sysfs_delete_link - remove symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @name: name of the symlink to remove. + * + * Unlike sysfs_remove_link sysfs_delete_link has enough information + * to successfully delete symlinks in tagged directories. + */ +void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, + const char *name) +{ + sysfs_hash_and_remove(targ, kobj->sd, name); +} + +/** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for. * @name: name of the symlink to remove. @@ -97,6 +112,22 @@ void sysfs_remove_link(struct kobject * sysfs_hash_and_remove(kobj, parent_sd, name); } +/** + * sysfs_rename_link - rename symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @old: previous name of the symlink. + * @new: new name of the symlink. + * + * A helper function for the common rename symlink idiom. + */ +int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, + const char *old, const char *new) +{ + sysfs_delete_link(kobj, targ, old); + return sysfs_create_link(kobj, targ, new); +} + static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd, char *path) { Index: linux-mm/include/linux/sysfs.h =================================================================== --- linux-mm.orig/include/linux/sysfs.h +++ linux-mm/include/linux/sysfs.h @@ -113,6 +113,12 @@ int __must_check sysfs_create_link(struc const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); +int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name); + +void sysfs_delete_link(struct kobject *dir, struct kobject *targ, + const char *name); + int __must_check sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); int sysfs_update_group(struct kobject *kobj, @@ -194,6 +200,17 @@ static inline void sysfs_remove_link(str { } +static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, + const char *old_name, const char *new_name) +{ + return 0; +} + +static inline void sysfs_delete_link(struct kobject *k, struct kobject *t, + const char *name) +{ +} + static inline int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-06-18 17:08 ` [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link Benjamin Thery @ 2008-06-23 2:13 ` Tejun Heo 2008-06-26 20:24 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-06-23 2:13 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Benjamin Thery wrote: > sysfs: Implement sysfs_delete_link and sysfs_rename_link > > When removing a symlink sysfs_remove_link does not provide > enough information to figure out which tagged directory the symlink > falls in. So I need sysfs_delete_link which is passed the target > of the symlink to delete. > > Further half the time when we are removing a symlink the code is > actually renaming the symlink but not doing so explicitly because > we don't have a symlink rename method. So I have added sysfs_rename_link > as well. > > Both of these functions now have enough information to find a symlink > in a tagged directory. The only restriction is that they must be called > before the target kobject is renamed or deleted. If they are called > later I loose track of which tag the target kobject was marked with > and can no longer find the old symlink to remove it. > > Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> > Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Ugly but given the current interface limitations... Acked-by: Tejun Heo <tj@kernel.org> -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-06-23 2:13 ` Tejun Heo @ 2008-06-26 20:24 ` Eric W. Biederman 2008-06-29 3:35 ` Tejun Heo 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-06-26 20:24 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > Ugly but given the current interface limitations... Yep. I have been thinking it might be nice to look at what you did with magic symlink handling. Otherwise we either need to convert everything from sysfs_remove_link to sysfs_delete_link if we don't want to play whack a mole. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-06-26 20:24 ` Eric W. Biederman @ 2008-06-29 3:35 ` Tejun Heo 2008-06-30 3:02 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-06-29 3:35 UTC (permalink / raw) To: Eric W. Biederman Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Eric W. Biederman wrote: > Tejun Heo <htejun@gmail.com> writes: > >> Ugly but given the current interface limitations... > > Yep. I have been thinking it might be nice to look at what you did with magic symlink > handling. Otherwise we either need to convert everything from sysfs_remove_link to > sysfs_delete_link if we don't want to play whack a mole. I think the current one should do for now. Changing to managed links requires pervasive changes to locking and stuff. I'll clean them up when I refresh the patches I posted a while back. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-06-29 3:35 ` Tejun Heo @ 2008-06-30 3:02 ` Eric W. Biederman 0 siblings, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-06-30 3:02 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Tejun Heo <htejun@gmail.com> writes: > > I think the current one should do for now. Changing to managed links > requires pervasive changes to locking and stuff. I'll clean them up > when I refresh the patches I posted a while back. Sounds good. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 08/11] driver core: Implement tagged directory support for device classes. 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (6 preceding siblings ...) 2008-06-18 17:08 ` [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link Benjamin Thery @ 2008-06-18 17:08 ` Benjamin Thery 2008-06-18 17:08 ` [PATCH 09/11] sysfs: add sysfs_ns_exit routine Benjamin Thery ` (2 subsequent siblings) 10 siblings, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery driver core: Implement tagged directory support for device classes. This patch enables tagging on every class directory if struct class has tag_ops. In addition device_del and device_rename were modified to use sysfs_delete_link and sysfs_rename_link respectively to ensure when these operations happen on devices whose classes have tag_ops that they work properly. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- drivers/base/class.c | 30 ++++++++++++++++++++++++++---- drivers/base/core.c | 41 +++++++++++++++++++++++------------------ include/linux/device.h | 2 ++ 3 files changed, 51 insertions(+), 22 deletions(-) Index: linux-mm/drivers/base/class.c =================================================================== --- linux-mm.orig/drivers/base/class.c +++ linux-mm/drivers/base/class.c @@ -135,6 +135,17 @@ static void remove_class_attrs(struct cl } } +static int class_setup_tagging(struct class *cls) +{ + const struct sysfs_tagged_dir_operations *tag_ops; + + tag_ops = cls->tag_ops; + if (!tag_ops) + return 0; + + return sysfs_enable_tagging(&cls->p->class_subsys.kobj, tag_ops); +} + int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; @@ -171,13 +182,24 @@ int __class_register(struct class *cls, cls->p = cp; error = kset_register(&cp->class_subsys); - if (error) { - kfree(cp); - return error; - } + if (error) + goto out_free_cp; + + error = class_setup_tagging(cls); + if (error) + goto out_unregister; + error = add_class_attrs(class_get(cls)); class_put(cls); + if (error) + goto out_unregister; +out: return error; +out_unregister: + kset_unregister(&cp->class_subsys); +out_free_cp: + kfree(cp); + goto out; } EXPORT_SYMBOL_GPL(__class_register); Index: linux-mm/drivers/base/core.c =================================================================== --- linux-mm.orig/drivers/base/core.c +++ linux-mm/drivers/base/core.c @@ -618,6 +618,10 @@ static struct kobject *get_device_parent kobject_put(k); return NULL; } + /* If we created a new class-directory setup tagging */ + if (dev->class->tag_ops) + sysfs_enable_tagging(k, dev->class->tag_ops); + /* do not emit an uevent for this simple "glue" directory */ return k; } @@ -754,13 +758,14 @@ static void device_remove_class_symlinks if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && device_is_not_partition(dev)) - sysfs_remove_link(&dev->class->p->class_subsys.kobj, + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev)); #else if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); - sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev_name(dev)); + sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, + dev_name(dev)); #endif sysfs_remove_link(&dev->kobj, "subsystem"); @@ -1349,6 +1354,16 @@ int device_rename(struct device *dev, ch strlcpy(old_device_name, dev_name(dev), BUS_ID_SIZE); strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); +#ifndef CONFIG_SYSFS_DEPRECATED + if (dev->class && + (dev->kobj.parent != &dev->class->p->class_subsys.kobj)) { + error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, old_device_name, new_name); + if (error) + goto out; + } +#endif + error = kobject_rename(&dev->kobj, new_name); if (error) { strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); @@ -1357,23 +1372,13 @@ int device_rename(struct device *dev, ch #ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { + error = -ENOMEM; new_class_name = make_class_name(dev->class->name, &dev->kobj); - if (new_class_name) { - error = sysfs_create_link(&dev->parent->kobj, - &dev->kobj, new_class_name); - if (error) - goto out; - sysfs_remove_link(&dev->parent->kobj, old_class_name); - } - } -#else - if (dev->class) { - error = sysfs_create_link(&dev->class->p->class_subsys.kobj, - &dev->kobj, dev_name(dev)); - if (error) - goto out; - sysfs_remove_link(&dev->class->p->class_subsys.kobj, - old_device_name); + if (new_class_name) + error = sysfs_rename_link(&dev->parent->kobj, + &dev->kobj, + old_class_name, + new_class_name); } #endif Index: linux-mm/include/linux/device.h =================================================================== --- linux-mm.orig/include/linux/device.h +++ linux-mm/include/linux/device.h @@ -195,6 +195,8 @@ struct class { int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); + const struct sysfs_tagged_dir_operations *tag_ops; + struct pm_ops *pm; struct class_private *p; }; -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 09/11] sysfs: add sysfs_ns_exit routine 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (7 preceding siblings ...) 2008-06-18 17:08 ` [PATCH 08/11] driver core: Implement tagged directory support for device classes Benjamin Thery @ 2008-06-18 17:08 ` Benjamin Thery 2008-06-18 20:19 ` Eric W. Biederman 2008-06-23 2:16 ` Tejun Heo 2008-06-18 17:09 ` [PATCH 10/11] netns: Enable tagging for net_class directories in sysfs Benjamin Thery 2008-06-18 17:09 ` [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Benjamin Thery 10 siblings, 2 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:08 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery Add sysfs routine sysfs_ns_exit() to allow a namespace to go away while sysfs is still mounted. The exiting namespace calls this routine and pass it a callback to be called for every sysfs superblocks present. The callback contains the necessary code to clean the superblock tag data associated with this namespace. Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/mount.c | 21 +++++++++++++++++++++ include/linux/sysfs.h | 8 ++++++++ 2 files changed, 29 insertions(+) Index: linux-mm/fs/sysfs/mount.c =================================================================== --- linux-mm.orig/fs/sysfs/mount.c +++ linux-mm/fs/sysfs/mount.c @@ -181,6 +181,27 @@ restart: spin_unlock(&sb_lock); } +/* Clean sysfs tags related to a given namespace when it exits */ +void sysfs_ns_exit(void (*func)(struct sysfs_tag_info *, void *), void *data) +{ + /* Allow the namespace to go away while sysfs is still mounted. */ + struct super_block *sb; + mutex_lock(&sysfs_rename_mutex); + sysfs_grab_supers(); + mutex_lock(&sysfs_mutex); + list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + + struct sysfs_super_info *info = sysfs_info(sb); + /* Call the cleaning routine provided by the namespace. + * data is the current namespace id passed by the namespace. + */ + func(&info->tag, data); + } + mutex_unlock(&sysfs_mutex); + sysfs_release_supers(); + mutex_unlock(&sysfs_rename_mutex); +} + int __init sysfs_init(void) { int err = -ENOMEM; Index: linux-mm/include/linux/sysfs.h =================================================================== --- linux-mm.orig/include/linux/sysfs.h +++ linux-mm/include/linux/sysfs.h @@ -136,6 +136,9 @@ void sysfs_printk_last_file(void); int sysfs_enable_tagging(struct kobject *kobj, const struct sysfs_tagged_dir_operations *tag_ops); +void sysfs_ns_exit(void (*func)(struct sysfs_tag_info *, void *), + void *data); + extern int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ @@ -249,6 +252,11 @@ static inline int sysfs_enable_tagging(s return 0; } +static inline void sysfs_ns_exit(void (*func)(struct sysfs_tag_info *, void *), + void *data) +{ +} + static inline int __must_check sysfs_init(void) { return 0; -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 09/11] sysfs: add sysfs_ns_exit routine 2008-06-18 17:08 ` [PATCH 09/11] sysfs: add sysfs_ns_exit routine Benjamin Thery @ 2008-06-18 20:19 ` Eric W. Biederman 2008-06-23 2:16 ` Tejun Heo 1 sibling, 0 replies; 145+ messages in thread From: Eric W. Biederman @ 2008-06-18 20:19 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers Benjamin Thery <benjamin.thery@bull.net> writes: > Add sysfs routine sysfs_ns_exit() to allow a namespace to go away while > sysfs is still mounted. > > The exiting namespace calls this routine and pass it a callback to be > called for every sysfs superblocks present. The callback contains the > necessary code to clean the superblock tag data associated with this > namespace. My apologies for not looking at this earlier. This is a nice cleanup. Thank you. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 09/11] sysfs: add sysfs_ns_exit routine 2008-06-18 17:08 ` [PATCH 09/11] sysfs: add sysfs_ns_exit routine Benjamin Thery 2008-06-18 20:19 ` Eric W. Biederman @ 2008-06-23 2:16 ` Tejun Heo 1 sibling, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-06-23 2:16 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Benjamin Thery wrote: > Add sysfs routine sysfs_ns_exit() to allow a namespace to go away while > sysfs is still mounted. > > The exiting namespace calls this routine and pass it a callback to be > called for every sysfs superblocks present. The callback contains the > necessary code to clean the superblock tag data associated with this > namespace. > > Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Similar object to earlier dynamic tag thing. Can't we just have something like sysfs_murder_sb(sb) where @sb represents a ns? -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 10/11] netns: Enable tagging for net_class directories in sysfs 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (8 preceding siblings ...) 2008-06-18 17:08 ` [PATCH 09/11] sysfs: add sysfs_ns_exit routine Benjamin Thery @ 2008-06-18 17:09 ` Benjamin Thery 2008-06-23 2:18 ` Tejun Heo 2008-06-18 17:09 ` [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Benjamin Thery 10 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:09 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery net: Enable tagging for net_class directories in sysfs The problem. Network devices show up in sysfs and with the network namespace active multiple devices with the same name can show up in the same directory, ouch! To avoid that problem and allow existing applications in network namespaces to see the same interface that is currently presented in sysfs, this patch enables the tagging directory support in sysfs. By using the network namespace pointers as tags to separate out the the sysfs directory entries we ensure that we don't have conflicts in the directories and applications only see a limited set of the network devices. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/mount.c | 8 ++++++++ include/linux/sysfs.h | 2 ++ net/Kconfig | 2 +- net/core/net-sysfs.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) Index: linux-mm/fs/sysfs/mount.c =================================================================== --- linux-mm.orig/fs/sysfs/mount.c +++ linux-mm/fs/sysfs/mount.c @@ -16,6 +16,8 @@ #include <linux/mount.h> #include <linux/pagemap.h> #include <linux/init.h> +#include <linux/nsproxy.h> +#include <net/net_namespace.h> #include "sysfs.h" @@ -78,6 +80,7 @@ static int sysfs_fill_super(struct super root->d_sb = sb; sb->s_root = root; sb->s_fs_info = info; + info->tag.net_ns = hold_net(current->nsproxy->net_ns); return 0; out_err: @@ -95,6 +98,9 @@ static int sysfs_test_super(struct super struct sysfs_super_info *info = sysfs_info(sb); int found = 1; + if (task->nsproxy->net_ns != info->tag.net_ns) + found = 0; + return found; } @@ -131,6 +137,8 @@ static void sysfs_kill_sb(struct super_b struct sysfs_super_info *info = sysfs_info(sb); kill_anon_super(sb); + if (info->tag.net_ns) + release_net(info->tag.net_ns); kfree(info); } Index: linux-mm/include/linux/sysfs.h =================================================================== --- linux-mm.orig/include/linux/sysfs.h +++ linux-mm/include/linux/sysfs.h @@ -19,6 +19,7 @@ struct kobject; struct module; +struct net; extern int kobject_set_name(struct kobject *kobj, const char *name, ...) __attribute__((format(printf, 2, 3))); @@ -81,6 +82,7 @@ struct sysfs_ops { }; struct sysfs_tag_info { + struct net *net_ns; }; struct sysfs_tagged_dir_operations { Index: linux-mm/net/Kconfig =================================================================== --- linux-mm.orig/net/Kconfig +++ linux-mm/net/Kconfig @@ -30,7 +30,7 @@ menu "Networking options" config NET_NS bool "Network namespace support" default n - depends on EXPERIMENTAL && !SYSFS && NAMESPACES + depends on EXPERIMENTAL && NAMESPACES help Allow user space to create what appear to be multiple instances of the network stack. Index: linux-mm/net/core/net-sysfs.c =================================================================== --- linux-mm.orig/net/core/net-sysfs.c +++ linux-mm/net/core/net-sysfs.c @@ -13,7 +13,9 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/if_arp.h> +#include <linux/nsproxy.h> #include <net/sock.h> +#include <net/net_namespace.h> #include <linux/rtnetlink.h> #include <linux/wireless.h> #include <net/iw_handler.h> @@ -385,6 +387,28 @@ static struct attribute_group wireless_g }; #endif +/* + * sysfs: allow the net namespace to go away while sysfs is still mounted. + */ +static void net_sysfs_net_exit_cb(struct sysfs_tag_info *tag_info, void *data) +{ + struct net *net = (struct net *)data; + + if (tag_info->net_ns != net) + return; + release_net(tag_info->net_ns); + tag_info->net_ns = NULL; +} + +void net_sysfs_net_exit(struct net *net) +{ + sysfs_ns_exit(net_sysfs_net_exit_cb, net); +} + +static struct pernet_operations net_sysfs_ops = { + .exit = net_sysfs_net_exit, +}; + #endif /* CONFIG_SYSFS */ #ifdef CONFIG_HOTPLUG @@ -421,6 +445,23 @@ static void netdev_release(struct device kfree((char *)dev - dev->padded); } +static const void *net_sb_tag(struct sysfs_tag_info *info) +{ + return info->net_ns; +} + +static const void *net_kobject_tag(struct kobject *kobj) +{ + struct net_device *dev; + dev = container_of(kobj, struct net_device, dev.kobj); + return dev_net(dev); +} + +static const struct sysfs_tagged_dir_operations net_tagged_dir_operations = { + .sb_tag = net_sb_tag, + .kobject_tag = net_kobject_tag, +}; + static struct class net_class = { .name = "net", .dev_release = netdev_release, @@ -430,6 +471,7 @@ static struct class net_class = { #ifdef CONFIG_HOTPLUG .dev_uevent = netdev_uevent, #endif + .tag_ops = &net_tagged_dir_operations, }; /* Delete sysfs entries but hold kobject reference until after all @@ -475,5 +517,8 @@ void netdev_initialize_kobject(struct ne int netdev_kobject_init(void) { +#ifdef CONFIG_SYSFS + register_pernet_subsys(&net_sysfs_ops); +#endif return class_register(&net_class); } -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 10/11] netns: Enable tagging for net_class directories in sysfs 2008-06-18 17:09 ` [PATCH 10/11] netns: Enable tagging for net_class directories in sysfs Benjamin Thery @ 2008-06-23 2:18 ` Tejun Heo 0 siblings, 0 replies; 145+ messages in thread From: Tejun Heo @ 2008-06-23 2:18 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Benjamin Thery wrote: > --- linux-mm.orig/fs/sysfs/mount.c > +++ linux-mm/fs/sysfs/mount.c > @@ -16,6 +16,8 @@ > #include <linux/mount.h> > #include <linux/pagemap.h> > #include <linux/init.h> > +#include <linux/nsproxy.h> > +#include <net/net_namespace.h> > > #include "sysfs.h" > > @@ -78,6 +80,7 @@ static int sysfs_fill_super(struct super > root->d_sb = sb; > sb->s_root = root; > sb->s_fs_info = info; > + info->tag.net_ns = hold_net(current->nsproxy->net_ns); > return 0; > > out_err: > @@ -95,6 +98,9 @@ static int sysfs_test_super(struct super > struct sysfs_super_info *info = sysfs_info(sb); > int found = 1; > > + if (task->nsproxy->net_ns != info->tag.net_ns) > + found = 0; > + > return found; > } > > @@ -131,6 +137,8 @@ static void sysfs_kill_sb(struct super_b > struct sysfs_super_info *info = sysfs_info(sb); > > kill_anon_super(sb); > + if (info->tag.net_ns) > + release_net(info->tag.net_ns); > kfree(info); > } Ouch... Please don't hard code net_ns functions directly from sysfs. Please make a proper abstraction for ns, make net_ns register it and sysfs test the abstract ns. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched 2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery ` (9 preceding siblings ...) 2008-06-18 17:09 ` [PATCH 10/11] netns: Enable tagging for net_class directories in sysfs Benjamin Thery @ 2008-06-18 17:09 ` Benjamin Thery 2008-06-23 2:18 ` Tejun Heo 10 siblings, 1 reply; 145+ messages in thread From: Benjamin Thery @ 2008-06-18 17:09 UTC (permalink / raw) To: Greg Kroah-Hartman, Andrew Morton Cc: Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery Mark the /sys/kernel/uids directory to be tagged so that processes in different user namespaces can remount /sys and see their own uid listings. Without this patch, having CONFIG_FAIR_SCHED=y makes user namespaces unusable, because when you clone(CLONE_NEWUSER) it will auto-create the root userid and try to create /sys/kernel/uids/0. Since that already exists from the parent user namespace, the create fails, and the clone misleadingly ends up returning -ENOMEM. This patch fixes the issue by allowing each user namespace to remount /sys, and having /sys filter the /sys/kernel/uid/ entries by user namespace. Signed-off-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/mount.c | 3 +++ include/linux/sched.h | 1 + include/linux/sysfs.h | 2 ++ kernel/user.c | 21 +++++++++++++++++++++ kernel/user_namespace.c | 13 ++++++++++++- 5 files changed, 39 insertions(+), 1 deletion(-) Index: linux-mm/fs/sysfs/mount.c =================================================================== --- linux-mm.orig/fs/sysfs/mount.c +++ linux-mm/fs/sysfs/mount.c @@ -81,6 +81,7 @@ static int sysfs_fill_super(struct super sb->s_root = root; sb->s_fs_info = info; info->tag.net_ns = hold_net(current->nsproxy->net_ns); + info->tag.user_ns = current->nsproxy->user_ns; return 0; out_err: @@ -100,6 +101,8 @@ static int sysfs_test_super(struct super if (task->nsproxy->net_ns != info->tag.net_ns) found = 0; + if (task->nsproxy->user_ns != info->tag.user_ns) + found = 0; return found; } Index: linux-mm/include/linux/sched.h =================================================================== --- linux-mm.orig/include/linux/sched.h +++ linux-mm/include/linux/sched.h @@ -604,6 +604,7 @@ struct user_struct { /* Hash table maintenance information */ struct hlist_node uidhash_node; uid_t uid; + struct user_namespace *user_ns; #ifdef CONFIG_USER_SCHED struct task_group *tg; Index: linux-mm/include/linux/sysfs.h =================================================================== --- linux-mm.orig/include/linux/sysfs.h +++ linux-mm/include/linux/sysfs.h @@ -20,6 +20,7 @@ struct kobject; struct module; struct net; +struct user_namespace; extern int kobject_set_name(struct kobject *kobj, const char *name, ...) __attribute__((format(printf, 2, 3))); @@ -83,6 +84,7 @@ struct sysfs_ops { struct sysfs_tag_info { struct net *net_ns; + struct user_namespace *user_ns; }; struct sysfs_tagged_dir_operations { Index: linux-mm/kernel/user.c =================================================================== --- linux-mm.orig/kernel/user.c +++ linux-mm/kernel/user.c @@ -53,6 +53,7 @@ struct user_struct root_user = { .files = ATOMIC_INIT(0), .sigpending = ATOMIC_INIT(0), .locked_shm = 0, + .user_ns = &init_user_ns, #ifdef CONFIG_USER_SCHED .tg = &init_task_group, #endif @@ -236,6 +237,23 @@ static void uids_release(struct kobject return; } +static const void *userns_sb_tag(struct sysfs_tag_info *info) +{ + return info->user_ns; +} + +static const void *userns_kobject_tag(struct kobject *kobj) +{ + struct user_struct *up; + up = container_of(kobj, struct user_struct, kobj); + return up->user_ns; +} + +static struct sysfs_tagged_dir_operations userns_tagged_dir_operations = { + .sb_tag = userns_sb_tag, + .kobject_tag = userns_kobject_tag, +}; + static struct kobj_type uids_ktype = { .sysfs_ops = &kobj_sysfs_ops, .default_attrs = uids_attributes, @@ -272,6 +290,8 @@ int __init uids_sysfs_init(void) if (!uids_kset) return -ENOMEM; + sysfs_enable_tagging(&uids_kset->kobj, &userns_tagged_dir_operations); + return uids_user_create(&root_user); } @@ -404,6 +424,7 @@ struct user_struct *alloc_uid(struct use goto out_unlock; new->uid = uid; + new->user_ns = ns; atomic_set(&new->__count, 1); if (sched_create_user(new) < 0) Index: linux-mm/kernel/user_namespace.c =================================================================== --- linux-mm.orig/kernel/user_namespace.c +++ linux-mm/kernel/user_namespace.c @@ -22,7 +22,7 @@ static struct user_namespace *clone_user struct user_struct *new_user; int n; - ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL); + ns = kzalloc(sizeof(struct user_namespace), GFP_KERNEL); if (!ns) return ERR_PTR(-ENOMEM); @@ -66,11 +66,22 @@ struct user_namespace * copy_user_ns(int return new_ns; } +/* clear sysfs tag when user namespace exits */ +static void sysfs_userns_exit(struct sysfs_tag_info *tag_info, void *data) +{ + struct user_namespace *ns = (struct user_namespace *)data; + + if (tag_info->user_ns != ns) + return; + tag_info->user_ns = NULL; +} + void free_user_ns(struct kref *kref) { struct user_namespace *ns; ns = container_of(kref, struct user_namespace, kref); + sysfs_ns_exit(sysfs_userns_exit, ns); release_uids(ns); kfree(ns); } -- ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched 2008-06-18 17:09 ` [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Benjamin Thery @ 2008-06-23 2:18 ` Tejun Heo 2008-06-25 18:44 ` Serge E. Hallyn 0 siblings, 1 reply; 145+ messages in thread From: Tejun Heo @ 2008-06-23 2:18 UTC (permalink / raw) To: Benjamin Thery Cc: Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Benjamin Thery wrote: > Mark the /sys/kernel/uids directory to be tagged so that processes in > different user namespaces can remount /sys and see their own uid > listings. > > Without this patch, having CONFIG_FAIR_SCHED=y makes user namespaces > unusable, because when you > clone(CLONE_NEWUSER) > it will auto-create the root userid and try to create > /sys/kernel/uids/0. Since that already exists from the parent user > namespace, the create fails, and the clone misleadingly ends up > returning -ENOMEM. > > This patch fixes the issue by allowing each user namespace to remount > /sys, and having /sys filter the /sys/kernel/uid/ entries by user > namespace. > > Signed-off-by: Serge Hallyn <serue@us.ibm.com> > Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Ditto as patch #10. Thanks. -- tejun ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched 2008-06-23 2:18 ` Tejun Heo @ 2008-06-25 18:44 ` Serge E. Hallyn 2008-06-25 21:11 ` Eric W. Biederman 0 siblings, 1 reply; 145+ messages in thread From: Serge E. Hallyn @ 2008-06-25 18:44 UTC (permalink / raw) To: Tejun Heo Cc: Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Eric Biederman, Daniel Lezcano, Serge Hallyn, linux-kernel, Al Viro, Linux Containers Quoting Tejun Heo (htejun@gmail.com): > Benjamin Thery wrote: > > Mark the /sys/kernel/uids directory to be tagged so that processes in > > different user namespaces can remount /sys and see their own uid > > listings. > > > > Without this patch, having CONFIG_FAIR_SCHED=y makes user namespaces > > unusable, because when you > > clone(CLONE_NEWUSER) > > it will auto-create the root userid and try to create > > /sys/kernel/uids/0. Since that already exists from the parent user > > namespace, the create fails, and the clone misleadingly ends up > > returning -ENOMEM. > > > > This patch fixes the issue by allowing each user namespace to remount > > /sys, and having /sys filter the /sys/kernel/uid/ entries by user > > namespace. > > > > Signed-off-by: Serge Hallyn <serue@us.ibm.com> > > Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> > > Ditto as patch #10. Except the sysfs mount holds no refcount on the userns. So as long as we do the ida tagging as you suggested in your response to patch 6, there should be no reference to the user_ns left in sysfs code. The extra reference in patch #9 is for a light ref on the network namespace. I'm still not sure that needs to be there, since if the network namespace goes away, it will properly unregister its sysfs mounts. Eric, Benjamin, I really don't see any use for the hold_net() from sysfs. What is it doing? -serge ^ permalink raw reply [flat|nested] 145+ messages in thread
* Re: [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched 2008-06-25 18:44 ` Serge E. Hallyn @ 2008-06-25 21:11 ` Eric W. Biederman [not found] ` <m1wskd43uc.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> 0 siblings, 1 reply; 145+ messages in thread From: Eric W. Biederman @ 2008-06-25 21:11 UTC (permalink / raw) To: Serge E. Hallyn Cc: Tejun Heo, Benjamin Thery, Greg Kroah-Hartman, Andrew Morton, Daniel Lezcano, linux-kernel, Al Viro, Linux Containers "Serge E. Hallyn" <serue@us.ibm.com> writes: > Except the sysfs mount holds no refcount on the userns. So as long as we > do the ida tagging as you suggested in your response to patch 6, there > should be no reference to the user_ns left in sysfs code. > > The extra reference in patch #9 is for a light ref on the network > namespace. I'm still not sure that needs to be there, since if the > network namespace goes away, it will properly unregister its sysfs > mounts. Eric, Benjamin, I really don't see any use for the hold_net() > from sysfs. What is it doing? Mostly just being a sanity check. We can remove that if it easier. Eric ^ permalink raw reply [flat|nested] 145+ messages in thread
[parent not found: <m1wskd43uc.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>]
* Re: [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched [not found] ` <m1wskd43uc.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org> @ 2008-06-26 13:07 ` Serge E. Hallyn 0 siblings, 0 replies; 145+ messages in thread From: Serge E. Hallyn @ 2008-06-26 13:07 UTC (permalink / raw) To: Eric W. Biederman Cc: Tejun Heo, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Linux Containers, Andrew Morton, Daniel Lezcano, Benjamin Thery Quoting Eric W. Biederman (ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org): > "Serge E. Hallyn" <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org> writes: > > > Except the sysfs mount holds no refcount on the userns. So as long as we > > do the ida tagging as you suggested in your response to patch 6, there > > should be no reference to the user_ns left in sysfs code. > > > > The extra reference in patch #9 is for a light ref on the network > > namespace. I'm still not sure that needs to be there, since if the > > network namespace goes away, it will properly unregister its sysfs > > mounts. Eric, Benjamin, I really don't see any use for the hold_net() > > from sysfs. What is it doing? > > Mostly just being a sanity check. We can remove that if it easier. > > Eric In itself it seems an ok check (temporarily) to make sure that the net_ns hook to unset the tag.netns at netns release is properly working, but given that it's only checking for net_ns coding errors, and Tejun wants a whole generic hooking infrastructure for net_ns to register with so as to keep mention of net_ns out of sysfs code, yeah I think the sane thing is to just remove it. But the first thing (after Daniel is finished with the patch 5 fallout) is to address the patch 6 comments about using ida. At first I didn't like it (seemed like too much bookkeeping) but I think it'll actually work out very nicely. -serge ^ permalink raw reply [flat|nested] 145+ messages in thread
* [PATCH 00/11] sysfs tagged directories V5
@ 2008-06-06 15:46 Benjamin Thery
2008-06-06 15:48 ` [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link Benjamin Thery
0 siblings, 1 reply; 145+ messages in thread
From: Benjamin Thery @ 2008-06-06 15:46 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel,
Tejun Heo, Al Viro, Linux Containers, Benjamin Thery
Greg,
Here is an updated version of the sysfs tagged directories that improves
a bit the situation over the previous one.
I've modified the patch 09 ("Enable tagging for net_class directories in
sysfs") to be a bit less intrusive in sysfs core. I removed the #ifdef'd
parts you didn't like in fs/sysfs/mount.c, and replaced it by a generic
routine sysfs_ns_exit() that is called, if needed, by the namespace when
it exits. This routine goes through every sysfs super blocks and calls
the callback passed by the namespace to clean its tag.
The patch is now splitted in two:
* 09/11: the generic routine,
* 10/11: the remaining network parts.
The generic part can be merge with patch 05 ("sysfs: Implement sysfs
tagged directory support.") but I left it separate for now to ease
reviews.
Serge's patch for user namespace is modified to use this new service too.
No more #ifdef CONFIG_NET or #ifdef CONFIG_USER_NS in fs/sysfs/mount.c
now.
But, currently, a new namespace that wants to add its tag to sysfs dirs
still need to modify fs/sysfs/mount.c in a few routines to manage the
new tag member added in struct sysfs_tag_info: sysfs_fill_super(),
sysfs_test_super(), sysfs_kill_sb() (see the last two patches).
These changes are only the initialization and a bunch of comparisons.
If we really want to go further, to get rid of these, I've thought
about:
* Extending sysfs_tagged_dir_operations with super blocks operations:
- fill_sb_tag, test_sb_tag, kill_sb_tag
* Add routines in sysfs to allow registration/unregistration of these
operations structs in a list:
- sysfs_register_tagged_dir_ops()...
* Each subsystem concerned implements and registers its operations at
boot.
* In sysfs_fill_super(), sysfs_test_super() and sysfs_kill_sb(), add
loops to go through all registered operations structs and calls the
corresponding operations if it's present.
But... I thought it was a bit overkill for the few namespaces that will
actually need sysfs tagged directories.
(Below you'll find the traditional introduction for sysfs tagged dirs
and the updated changelog)
Thanks,
Benjamin
--
Here is an updated version of Eric Biederman's patchset to implement
tagged directories in sysfs ported on top of 2.6.26-rc2-mm1.
With the introduction of network namespaces, there can be duplicate
network interface names on the same machine. Indeed, two network
interfaces can have the same name if they reside in different network
namespaces.
* Network interfaces names show up in sysfs.
* Today there is nothing in sysfs that is currently per namespace.
* Therefore we need to support multiple mounts of sysfs each showing a
different network namespace.
We introduce tagged directories in sysfs for this purpose.
Of course the usefulness of this feature is not limited to network stuff:
Serge Hallyn wrote a patch to fix a similar issue with user namespaces based
on this patchset. His patch is included at the end of the patchset.
Tested with and without SYSFS_DEPRECATED. No regression found so far.
Changelog
---------
* V5:
- Make namespace tags a bit less intrusive in sysfs core:
- New patch 09: Added a generic sysfs_ns_exit routine called by
exiting namespaces. A callback is passed to this routine to
execute the subsystem specific code.
- Modified patches 09 and 10 (now 10 and 11) ("netns tagging" and
"userns tagging") to use this new routine instead of adding
#ifdef'd code in fs/sysfs/mount.c.
- Added missing -ENOMEM in fs/sysfs/dir.c:prep_rename() (Roel Kluin)
* V4:
- Ported to 2.6.26-rc2-mm1
- Updated patch for user namespace by Serge Hallyn (patch 10).
* V3:
- Removed patch 10 ("avoid kobject name conflict with different
namespaces"), a better one was provided by Eric.
- Removed patch 11 ("sysfs: user namespaces: add ns to user_struct"),
Serge needs to rework some parts of it.
- Change Acked-by: to Signed-off-by:, someone told me it is more
appropriate (as I'm in the delivery path).
Here is the announcement Eric wrote back in December to introduce his
patchset:
"
Now that we have network namespace support merged it is time to
revisit the sysfs support so we can remove the dependency on !SYSFS.
[...]
The bulk of the patches are the changes to allow multiple sysfs
superblocks.
Then comes the tagged directory sysfs support which uses information
captured at mount time to decide which object with which tag will
appear in a directory.
Then the support for renaming and deleting objects where the source
may be ambiguous because of tagging.
Then finally the network namespace support so it is clear how all
of this tied together.
"
Regards,
Benjamin
--
^ permalink raw reply [flat|nested] 145+ messages in thread* [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link 2008-06-06 15:46 [PATCH 00/11] sysfs tagged directories V5 Benjamin Thery @ 2008-06-06 15:48 ` Benjamin Thery 0 siblings, 0 replies; 145+ messages in thread From: Benjamin Thery @ 2008-06-06 15:48 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Andrew Morton, Eric Biederman, Serge Hallyn, linux-kernel, Tejun Heo, Al Viro, Linux Containers, Benjamin Thery sysfs: Implement sysfs_delete_link and sysfs_rename_link When removing a symlink sysfs_remove_link does not provide enough information to figure out which tagged directory the symlink falls in. So I need sysfs_delete_link which is passed the target of the symlink to delete. Further half the time when we are removing a symlink the code is actually renaming the symlink but not doing so explicitly because we don't have a symlink rename method. So I have added sysfs_rename_link as well. Both of these functions now have enough information to find a symlink in a tagged directory. The only restriction is that they must be called before the target kobject is renamed or deleted. If they are called later I loose track of which tag the target kobject was marked with and can no longer find the old symlink to remove it. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> --- fs/sysfs/symlink.c | 31 +++++++++++++++++++++++++++++++ include/linux/sysfs.h | 17 +++++++++++++++++ 2 files changed, 48 insertions(+) Index: linux-mm/fs/sysfs/symlink.c =================================================================== --- linux-mm.orig/fs/sysfs/symlink.c +++ linux-mm/fs/sysfs/symlink.c @@ -80,6 +80,21 @@ int sysfs_create_link(struct kobject * k } /** + * sysfs_delete_link - remove symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @name: name of the symlink to remove. + * + * Unlike sysfs_remove_link sysfs_delete_link has enough information + * to successfully delete symlinks in tagged directories. + */ +void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, + const char *name) +{ + sysfs_hash_and_remove(targ, kobj->sd, name); +} + +/** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for. * @name: name of the symlink to remove. @@ -97,6 +112,22 @@ void sysfs_remove_link(struct kobject * sysfs_hash_and_remove(kobj, parent_sd, name); } +/** + * sysfs_rename_link - rename symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @old: previous name of the symlink. + * @new: new name of the symlink. + * + * A helper function for the common rename symlink idiom. + */ +int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, + const char *old, const char *new) +{ + sysfs_delete_link(kobj, targ, old); + return sysfs_create_link(kobj, targ, new); +} + static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd, char *path) { Index: linux-mm/include/linux/sysfs.h =================================================================== --- linux-mm.orig/include/linux/sysfs.h +++ linux-mm/include/linux/sysfs.h @@ -111,6 +111,12 @@ int __must_check sysfs_create_link(struc const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); +int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name); + +void sysfs_delete_link(struct kobject *dir, struct kobject *targ, + const char *name); + int __must_check sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); int sysfs_update_group(struct kobject *kobj, @@ -192,6 +198,17 @@ static inline void sysfs_remove_link(str { } +static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, + const char *old_name, const char *new_name) +{ + return 0; +} + +static inline void sysfs_delete_link(struct kobject *k, struct kobject *t, + const char *name) +{ +} + static inline int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { -- ^ permalink raw reply [flat|nested] 145+ messages in thread
end of thread, other threads:[~2008-10-14 3:20 UTC | newest]
Thread overview: 145+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-18 17:07 [PATCH 00/11] sysfs tagged directories V6 Benjamin Thery
2008-06-18 17:07 ` [PATCH 01/11] sysfs: Support for preventing unmounts Benjamin Thery
[not found] ` <20080618170730.256129077-4vkkeT0zb4ZEtYaxpPmRp1aPQRlvutdw@public.gmane.org>
2008-06-18 17:44 ` Dave Hansen
2008-06-18 20:12 ` Eric W. Biederman
2008-06-19 8:54 ` Benjamin Thery
2008-06-19 16:32 ` Dave Hansen
2008-06-19 20:19 ` Benjamin Thery
2008-06-18 17:07 ` [PATCH 02/11] sysfs: sysfs_get_dentry add a sb parameter Benjamin Thery
2008-06-18 17:07 ` [PATCH 03/11] sysfs: Implement __sysfs_get_dentry Benjamin Thery
2008-06-18 17:08 ` [PATCH 04/11] sysfs: Rename Support multiple superblocks Benjamin Thery
2008-06-18 17:08 ` [PATCH 05/11] sysfs: sysfs_chmod_file handle " Benjamin Thery
2008-06-22 4:46 ` Tejun Heo
2008-06-23 21:42 ` Daniel Lezcano
2008-06-24 4:45 ` Tejun Heo
2008-06-24 10:39 ` Daniel Lezcano
2008-06-24 13:37 ` Daniel Lezcano
2008-06-25 12:31 ` Tejun Heo
2008-06-18 17:08 ` [PATCH 06/11] sysfs: Implement sysfs tagged directory support Benjamin Thery
2008-06-23 2:05 ` Tejun Heo
2008-06-26 20:21 ` Eric W. Biederman
2008-06-29 3:51 ` Tejun Heo
2008-06-30 18:56 ` Eric W. Biederman
[not found] ` <m18wwmsqdv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-06-30 21:44 ` Serge E. Hallyn
2008-07-01 7:50 ` Eric W. Biederman
2008-07-01 6:47 ` Tejun Heo
2008-07-01 9:20 ` Eric W. Biederman
2008-07-01 10:30 ` Tejun Heo
2008-07-01 12:30 ` Eric W. Biederman
2008-07-02 3:24 ` Tejun Heo
2008-07-02 3:53 ` Eric W. Biederman
2008-07-02 4:37 ` Tejun Heo
[not found] ` <486B060C.7030607-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2008-07-02 7:18 ` Andreas B Aaen
2008-07-02 16:49 ` Eric W. Biederman
2008-07-03 0:15 ` Greg KH
[not found] ` <m14p78s02q.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-07-03 3:18 ` Tejun Heo
[not found] ` <486C4515.1070007-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2008-07-03 5:11 ` Eric W. Biederman
[not found] ` <m1hcb7o8lv.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-07-03 10:56 ` Daniel Lezcano
[not found] ` <486CB051.5000507-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2008-07-03 12:27 ` Eric W. Biederman
[not found] ` <m14p77m9uy.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-07-03 12:37 ` Benjamin Thery
2008-07-03 19:57 ` Eric W. Biederman
2008-07-03 12:55 ` Daniel Lezcano
2008-07-03 15:58 ` Tejun Heo
2008-07-03 18:29 ` Daniel Lezcano
2008-07-03 20:08 ` Eric W. Biederman
2008-07-04 0:48 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman
2008-07-04 1:05 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Eric W. Biederman
2008-07-04 1:07 ` [PATCH 02/15] sysfs: Support for preventing unmounts Eric W. Biederman
2008-07-04 1:08 ` [PATCH 03/15] sysfs: sysfs_get_dentry add a sb parameter Eric W. Biederman
2008-07-04 1:09 ` [PATCH 04/15] sysfs: Implement __sysfs_get_dentry Eric W. Biederman
2008-07-04 1:10 ` [PATCH 05/15] sysfs: Rename Support multiple superblocks Eric W. Biederman
2008-07-04 1:11 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Eric W. Biederman
2008-07-04 1:13 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Eric W. Biederman
2008-07-04 1:14 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Eric W. Biederman
2008-07-04 1:16 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Eric W. Biederman
2008-07-04 1:17 ` [PATCH 10/15] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman
2008-07-04 1:18 ` [PATCH 11/15] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman
2008-07-04 1:20 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Eric W. Biederman
2008-07-04 1:21 ` [PATCH 13/15] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman
2008-07-04 1:22 ` [PATCH 14/15] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman
2008-07-04 1:23 ` [PATCH 15/15] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Eric W. Biederman
2008-07-04 7:50 ` [PATCH 12/15] driver core: Implement tagged directory support for device classes Tejun Heo
2008-07-04 13:31 ` Eric W. Biederman
2008-07-04 13:57 ` Tejun Heo
2008-07-04 16:12 ` Greg KH
2008-07-04 21:49 ` Eric W. Biederman
2008-07-14 1:54 ` Eric W. Biederman
2008-07-16 3:25 ` Tejun Heo
2008-07-16 5:41 ` Eric W. Biederman
2008-07-16 5:50 ` Tejun Heo
2008-07-16 6:32 ` Eric W. Biederman
2008-07-16 6:48 ` Tejun Heo
2008-07-16 7:02 ` Tejun Heo
2008-07-16 19:07 ` Eric W. Biederman
2008-07-16 21:09 ` Eric W. Biederman
2008-07-17 23:08 ` Greg KH
2008-07-18 12:41 ` Tejun Heo
2008-07-18 18:49 ` Greg KH
2008-07-18 20:19 ` Eric W. Biederman
2008-07-19 1:07 ` Tejun Heo
2008-08-03 6:59 ` Eric W. Biederman
2008-09-11 12:45 ` Jiri Slaby
2008-09-11 13:05 ` Benjamin Thery
2008-09-12 6:32 ` Jiri Slaby
2008-07-04 22:00 ` Eric W. Biederman
2008-08-20 2:17 ` [PATCH 09/15] sysfs: Implement sysfs tagged directory support Greg KH
2008-08-20 6:58 ` Eric W. Biederman
2008-08-21 6:31 ` [PATCH 0/8] sysfs namespace support Eric W. Biederman
2008-08-21 6:33 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Eric W. Biederman
2008-08-21 6:34 ` [PATCH 2/8] sysfs: Merge sysfs_rename_dir and sysfs_move_dir Eric W. Biederman
2008-08-21 6:35 ` [PATCH 3/8] sysfs: Implement sysfs_delete_link and sysfs_rename_link Eric W. Biederman
2008-08-21 6:36 ` [PATCH 5/8] sysfs: Remove sysfs_create_link_nowarn Eric W. Biederman
2008-08-21 6:38 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" Eric W. Biederman
2008-08-21 6:39 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs Eric W. Biederman
2008-08-21 6:40 ` [PATCH 8/8] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Eric W. Biederman
2008-08-21 6:47 ` [PATCH 7/8] netns: Enable tagging for net_class directories in sysfs David Miller
2008-08-21 6:47 ` [PATCH 6/8] Revert "netns: Fix device renaming for sysfs" David Miller
2008-08-21 6:37 ` [PATCH 4/8] driver core: Implement tagged directory support for device classes Eric W. Biederman
2008-08-27 15:18 ` [PATCH 1/8] sysfs: Implement sysfs tagged directory support Benjamin Thery
2008-09-02 13:54 ` Mark Ryden
2008-09-02 14:03 ` Benjamin Thery
2008-09-02 17:01 ` Greg KH
2008-09-04 5:33 ` David Shwatrz
2008-09-04 6:44 ` Benjamin Thery
2008-09-08 18:39 ` Mark Ryden
2008-10-07 16:39 ` Mark Ryden
2008-10-07 16:48 ` Greg KH
2008-10-07 20:31 ` Eric W. Biederman
2008-10-07 21:09 ` Greg KH
2008-10-07 22:27 ` Eric W. Biederman
2008-10-08 13:00 ` Christoph Hellwig
2008-10-14 3:20 ` Eric W. Biederman
2008-10-07 16:52 ` Daniel Lezcano
2008-08-21 6:37 ` [PATCH 0/8] sysfs namespace support David Miller
2008-07-04 6:44 ` [PATCH 08/15] sysfs: Make sysfs_mount static once again Tejun Heo
2008-07-04 6:44 ` [PATCH 07/15] sysfs: sysfs_chmod_file handle multiple superblocks Tejun Heo
2008-08-20 2:16 ` patch sysfs-sysfs_chmod_file-handle-multiple-superblocks.patch added to gregkh-2.6 tree gregkh
2008-07-04 6:40 ` [PATCH 06/15] Introduce sysfs_sd_setattr and fix sysfs_chmod Tejun Heo
2008-08-20 2:16 ` patch sysfs-introduce-sysfs_sd_setattr-and-fix-sysfs_chmod.patch added to gregkh-2.6 tree gregkh
2008-08-20 2:16 ` patch sysfs-rename-support-multiple-superblocks.patch " gregkh
2008-08-20 2:16 ` patch sysfs-implement-__sysfs_get_dentry.patch " gregkh
2008-08-20 2:16 ` patch sysfs-sysfs_get_dentry-add-a-sb-parameter.patch " gregkh
[not found] ` <m1prpuihjb.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-08-20 2:16 ` patch sysfs-support-for-preventing-unmounts.patch " gregkh-l3A5Bk7waGM
2008-07-04 6:33 ` [PATCH 01/15] kobject: Cleanup kobject_rename and !CONFIG_SYSFS Tejun Heo
2008-08-20 1:48 ` patch kobject-cleanup-kobject_rename-and-config_sysfs.patch added to gregkh-2.6 tree gregkh
2008-07-04 1:27 ` [PATCH 00/15] sysfs support for namespaces Eric W. Biederman
2008-07-06 4:42 ` Eric W. Biederman
2008-07-07 11:41 ` Cornelia Huck
2008-07-07 12:22 ` Eric W. Biederman
2008-06-18 17:08 ` [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link Benjamin Thery
2008-06-23 2:13 ` Tejun Heo
2008-06-26 20:24 ` Eric W. Biederman
2008-06-29 3:35 ` Tejun Heo
2008-06-30 3:02 ` Eric W. Biederman
2008-06-18 17:08 ` [PATCH 08/11] driver core: Implement tagged directory support for device classes Benjamin Thery
2008-06-18 17:08 ` [PATCH 09/11] sysfs: add sysfs_ns_exit routine Benjamin Thery
2008-06-18 20:19 ` Eric W. Biederman
2008-06-23 2:16 ` Tejun Heo
2008-06-18 17:09 ` [PATCH 10/11] netns: Enable tagging for net_class directories in sysfs Benjamin Thery
2008-06-23 2:18 ` Tejun Heo
2008-06-18 17:09 ` [PATCH 11/11] sysfs: user namespaces: fix bug with clone(CLONE_NEWUSER) with fairsched Benjamin Thery
2008-06-23 2:18 ` Tejun Heo
2008-06-25 18:44 ` Serge E. Hallyn
2008-06-25 21:11 ` Eric W. Biederman
[not found] ` <m1wskd43uc.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-06-26 13:07 ` Serge E. Hallyn
-- strict thread matches above, loose matches on Subject: below --
2008-06-06 15:46 [PATCH 00/11] sysfs tagged directories V5 Benjamin Thery
2008-06-06 15:48 ` [PATCH 07/11] sysfs: Implement sysfs_delete_link and sysfs_rename_link Benjamin Thery
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox