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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> >> Signed-off-by: Benjamin Thery <[EMAIL PROTECTED]> >> --- >> 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 [EMAIL PROTECTED] > More majordomo info at http://vger.kernel.org/majordomo-info.html > _______________________________________________ Containers mailing list [EMAIL PROTECTED] https://lists.linux-foundation.org/mailman/listinfo/containers _______________________________________________ Devel mailing list Devel@openvz.org https://openvz.org/mailman/listinfo/devel