OpenVZ Forum


Home » Mailing lists » Devel » [PATCH 0/25] Sysfs cleanups & tagged directory support
Re: alternative approached at tagged nodes [message #19661 is a reply to message #19585] Wed, 08 August 2007 16:31 Go to previous messageGo to previous message
Tejun Heo is currently offline  Tejun Heo
Messages: 184
Registered: November 2006
Senior Member
Okay, here's a different implementation of tagged nodes.  I just
compile tested it so I can guarantee it's broken.  I don't think
there's anything fundamentally wrong but I'm wrong fairly often, so if
you find something moronic, feel free to scream at me.

1. there's no enable_tagging() or fundamental restrictions on which
   types of nodes can be tagged.

2. no callback.  tags are set by sysfs_rename_dir_tagged().  symlinks
   follow the tag of its target_sd.  This limits taggable node types
   to dirs and symlinks.

3. in all paths between the root and leaf nodes, only zero or one
   tagged sd exists.  all children of a tagged sd have NULL s_tag but
   are considered tagged the same as the tagged ancestor.

4. untagged entries are visible in all supers unless there's a
   matching tagged entry overshadowing it.  tagged entry is only
   visible in the  matching tagged super.

5. due to #3, children in a directory which belong to the same tag can
   be looked up using NULL tag.  Most leaf node ops don't need to be
   changed.

6. symlink removal is different.  we either need to modify the
   interface to take target_sd or implement new one.  actually, I
   think linking symlinks to target_sd and renaming/removing them
   automagically would be pretty good.

Thanks.  What do you think?

JUST FOR BRAIN STORMING.  DO NOT APPLY.
---
 fs/sysfs/bin.c        |    2 
 fs/sysfs/dir.c        |  122 ++++++++++++++++++++++++++++++++++++++++----------
 fs/sysfs/file.c       |    4 -
 fs/sysfs/group.c      |    2 
 fs/sysfs/inode.c      |    5 +-
 fs/sysfs/mount.c      |   44 ++++++++++++++++--
 fs/sysfs/symlink.c    |    8 ++-
 fs/sysfs/sysfs.h      |   11 +++-
 include/linux/sysfs.h |    4 +
 9 files changed, 167 insertions(+), 35 deletions(-)

Index: work/fs/sysfs/dir.c
===================================================================
--- work.orig/fs/sysfs/dir.c
+++ work/fs/sysfs/dir.c
@@ -387,7 +387,7 @@ 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))
+	if (__sysfs_find_dirent(acxt->parent_sd, sd->s_name, sd->s_tag, 0))
 		return -EEXIST;
 
 	sd->s_parent = sysfs_get(acxt->parent_sd);
@@ -526,6 +526,24 @@ void sysfs_addrm_finish(struct sysfs_add
 	}
 }
 
+struct sysfs_dirent *__sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+					 const unsigned char *name,
+					 const void *tag, int match_null)
+{
+	struct sysfs_dirent *null_sd = NULL, *sd;
+
+	for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
+		if (strcmp(sd->s_name, name))
+			continue;
+		if (sd->s_tag == tag)
+			return sd;
+		if (!sd->s_tag && match_null)
+			null_sd = sd;
+	}
+
+	return null_sd;
+}
+
 /**
  *	sysfs_find_dirent - find sysfs_dirent with the given name
  *	@parent_sd: sysfs_dirent to search under
@@ -542,12 +560,7 @@ void sysfs_addrm_finish(struct sysfs_add
 struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
 				       const unsigned char *name)
 {
-	struct sysfs_dirent *sd;
-
-	for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
-		if (!strcmp(sd->s_name, name))
-			return sd;
-	return NULL;
+	return __sysfs_find_dirent(parent_sd, name, NULL, 0);
 }
 
 /**
@@ -642,7 +655,8 @@ static struct dentry * sysfs_lookup(stru
 
 	mutex_lock(&sysfs_mutex);
 
-	sd = sysfs_find_dirent(parent_sd, dentry->d_name.name);
+	sd = __sysfs_find_dirent(parent_sd, dentry->d_name.name,
+				 sysfs_info(dentry->d_sb)->tag, 1);
 
 	/* no such entry */
 	if (!sd)
@@ -803,9 +817,19 @@ out:
 	return dentry;
 }
 
+const void *sysfs_dirent_tag(struct sysfs_dirent *sd)
+{
+	while (sd) {
+		if (sd->s_tag)
+			return sd->s_tag;
+		sd = sd->s_parent;
+	}
+	return sd->s_tag;
+}
+
 /**
  *	sysfs_get_dentry - get dentry for the given sysfs_dirent
- *	@sb: superblock of the dentry to return
+ *	@super: superblock of the dentry to return
  *	@sd: sysfs_dirent of interest
  *
  *	Get dentry for @sd.  Dentry is looked up if currently not
@@ -820,16 +844,23 @@ out:
  *	Pointer to found dentry on success, ERR_PTR() value on error.
  *	NULL if the sysfs dentry does not appear in the specified superblock
  */
-struct dentry *sysfs_get_dentry(struct super_block *sb, struct sysfs_dirent *sd)
+struct dentry *sysfs_get_dentry(struct super_block *super,
+				struct sysfs_dirent *sd)
 {
+	const void *tag;
 	struct sysfs_dirent *cur;
 	struct dentry *parent_dentry, *dentry;
 
+	/* bail if this sd won't show up in this superblock */
+	tag = sysfs_dirent_tag(sd);
+	if (tag && tag != sysfs_info(super)->tag)
+		return ERR_PTR(-ENOENT);
+
 	/* Find the first parent which has valid dentry.
 	 */
 	dentry = NULL;
 	cur = sd;
-	while (!(dentry = __sysfs_get_dentry(sb, cur))) {
+	while (!(dentry = __sysfs_get_dentry(super, cur))) {
 		if (cur->s_flags & SYSFS_FLAG_REMOVED) {
 			dentry = ERR_PTR(-ENOENT);
 			break;
@@ -926,27 +957,44 @@ err_out:
 	return error;
 }
 
-
-int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+int sysfs_rename_dir_tagged(struct kobject * kobj, const char *new_name,
+			    const void *new_tag)
 {
 	struct sysfs_dirent *sd = kobj->sd;
 	struct list_head todo;
 	struct sysfs_rename_struct *srs;
 	struct inode *parent_inode = NULL;
 	const char *dup_name = NULL;
-	int error;
+	const void *old_tag;
+	int tag = 0, error;
 
 	INIT_LIST_HEAD(&todo);
 	mutex_lock(&sysfs_rename_mutex);
 
+	old_tag = sysfs_dirent_tag(sd);
+
+	/* need tagging? */
+	if (old_tag != new_tag) {
+		tag = 1;
+
+		/* can't tag again in tagged subtree */
+		error = -EINVAL;
+		if (old_tag != new_tag)
+			goto out;
+	} else
+		/* sd->s_tag can be either old_tag or NULL */
+		new_tag = sd->s_tag;
+
 	error = 0;
-	if (strcmp(sd->s_name, new_name) == 0)
+	if (!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 (!tag) {
+		error = prep_rename(&todo, sd, sd->s_parent, new_name);
+		if (error)
+			goto out_release;
+	}
 
 	error = -ENOMEM;
 	mutex_lock(&sysfs_mutex);
@@ -959,7 +1007,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, new_name, new_tag, 0))
 		goto out_unlock;
 
 	/* rename kobject and sysfs_dirent */
@@ -974,6 +1022,7 @@ int sysfs_rename_dir(struct kobject * ko
 
 	dup_name = sd->s_name;
 	sd->s_name = new_name;
+	sd->s_tag = new_tag;
 
 	/* rename */
 	list_for_each_entry(srs, &todo, list) {
@@ -981,6 +1030,21 @@ 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 (tag) {
+		struct super_block *super;
+		struct dentry *dentry;
+
+		list_for_each_entry(super, &sysfs_fs_type.fs_supers, s_instances) {
+			dentry = __sysfs_get_dentry(super, sd);
+			if (!dentry)
+				continue;
+			shrink_dcache_parent(dentry);
+			d_drop(dentry);
+			dput(dentry);
+		}
+	}
+
 	error = 0;
 out_unlock:
 	mutex_unlock(&sysfs_mutex);
@@ -995,6 +1059,11 @@ out:
 	return error;
 }
 
+int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+{
+	return sysfs_rename_dir_tagged(kobj, new_name, kobj->sd->s_tag);
+}
+
 int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
 {
 	struct sysfs_dirent *sd = kobj->sd;
@@ -1013,6 +1082,11 @@ int sysfs_move_dir(struct kobject *kobj,
 	if (sd->s_parent == new_parent_sd)
 		goto out;	/* nothing to move */
 
+	/* can't move between parents belonging to different tags */
+	error = -EINVAL;
+	if (sysfs_dirent_tag(sd->s_parent) != sysfs_dirent_tag(new_parent_sd))
+		goto out;
+
 	sysfs_grab_supers();
 	error = prep_rename(&todo, sd, new_parent_sd, sd->s_name);
 	if (error)
@@ -1041,7 +1115,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, sd->s_name, sd->s_tag, 0))
 		goto out_unlock;
 
 	error = 0;
@@ -1080,8 +1154,9 @@ 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;
+	const void *tag = sysfs_info(filp->f_dentry->d_sb)->tag;
 	struct sysfs_dirent *pos;
 	ino_t ino;
 
@@ -1110,6 +1185,9 @@ static int sysfs_readdir(struct file * f
 			const char * name;
 			int len;
 
+			if (pos->s_tag && pos->s_tag != tag)
+				continue;
+
 			name = pos->s_name;
 			len = strlen(name);
 			filp->f_pos = ino = pos->s_ino;
Index: work/fs/sysfs/sysfs.h
===================================================================
--- work.orig/fs/sysfs/sysfs.h
+++ work/fs/sysfs/sysfs.h
@@ -26,6 +26,7 @@ struct sysfs_dirent {
 	struct sysfs_dirent	* s_sibling;
 	struct sysfs_dirent	* s_children;
 	const char		* s_name;
+	const void		* s_tag;
 
 	union {
 		struct sysfs_elem_dir		dir;
@@ -51,7 +52,8 @@ struct sysfs_addrm_cxt {
 };
 
 struct sysfs_super_info {
-	int	grabbed;
+	int		grabbed;
+	const void	*tag;
 };
 
 #define sysfs_info(SB) ((struct sysfs_super_info *)(SB)->s_fs_info)
@@ -63,6 +65,7 @@ extern struct file_system_type sysfs_fs_
 void sysfs_grab_supers(void);
 void sysfs_release_supers(void);
 
+extern const void *sysfs_dirent_tag(struct sysfs_dirent *sd);
 extern struct dentry *sysfs_get_dentry(struct super_block *sb, struct sysfs_dirent *sd);
 extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
 extern void sysfs_put_active(struct sysfs_dirent *sd);
@@ -79,6 +
...

 
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic: [PATCH] Cleanup oops/bug reports on i386
Next Topic: containers development plans (Aug 8 version)
Goto Forum:
  


Current Time: Tue Oct 15 13:38:19 GMT 2024

Total time taken to generate the page: 0.04898 seconds