linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
       [not found] <20061210175652.7537.qmail@science.horizon.com>
@ 2006-12-12 16:46 ` Jeff Layton
  2006-12-12 18:02   ` linux
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff Layton @ 2006-12-12 16:46 UTC (permalink / raw)
  To: linux; +Cc: linux-kernel, linux-fsdevel

linux@horizon.com wrote:
 > I'm very fond of <stdbool.h>, since it explicitly documents that there
 > are exactly two options.  It also allows the compiler a few minor
 > opportunities for optimization, but that's not as big a deal.
 >
 > static int __simple_fill_super(struct super_block *s, int magic,
 > 				struct tree_descr *files, bool sequential)
 >
 > Although "true" and "false" aren't the most meaningful #defines either,
 > at least they indicate that it's one of two choices, and there is no
 > option "2" to sorry about.
 >
 > Given your wrappr function names, "bool registered" is another option.
 >
 > You might want to make simple_fill_super() and registered_fill_super()
 > inline functions or #defines rather than making them separate functions.
 > Or is there a particular need for a function pointer?  The code size
 > is negligible, and it saves stack space.
 >

Good catch on the inlining. I had meant to do that and missed it. The point
about the naming of the flag is a good one too. How about this patch? I've
tested it to see that it builds, but don't have good place to test this one
to see that it works. A similar patch did work on a 2.6.18 derivative kernel.

Signed-off-by: Jeff Layton <jlayton@redhat.com>

--- linux-2.6/fs/debugfs/inode.c.super	2006-12-12 08:46:46.000000000 -0500
+++ linux-2.6/fs/debugfs/inode.c	2006-12-12 08:54:14.000000000 -0500
@@ -107,7 +107,7 @@
  {
  	static struct tree_descr debug_files[] = {{""}};

-	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
+	return registered_fill_super(sb, DEBUGFS_MAGIC, debug_files);
  }

  static int debug_get_sb(struct file_system_type *fs_type,
--- linux-2.6/fs/fuse/control.c.super	2006-12-12 08:46:46.000000000 -0500
+++ linux-2.6/fs/fuse/control.c	2006-12-12 08:54:14.000000000 -0500
@@ -163,7 +163,7 @@
  	struct fuse_conn *fc;
  	int err;

-	err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+	err = registered_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
  	if (err)
  		return err;

--- linux-2.6/fs/libfs.c.super	2006-12-12 08:46:46.000000000 -0500
+++ linux-2.6/fs/libfs.c	2006-12-12 11:31:20.000000000 -0500
@@ -215,7 +215,7 @@
  	s->s_op = ops ? ops : &default_ops;
  	s->s_time_gran = 1;
  	root = new_inode(s);
-	if (!root)
+	if (!root || iunique_register(root, 0))
  		goto Enomem;
  	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
  	root->i_uid = root->i_gid = 0;
@@ -356,7 +356,8 @@
  	return 0;
  }

-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+static int __simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files, bool registered)
  {
  	static struct super_operations s_ops = {.statfs = simple_statfs};
  	struct inode *inode;
@@ -380,6 +381,12 @@
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  	inode->i_nlink = 2;
+	/*
+	 * set this as high as a 32 bit val as possible to avoid collisions.
+	 * This is also well above the highest value that iunique_register
+         * will assign to an inode
+	 */
+	inode->i_ino = 0xffffffff;
  	root = d_alloc_root(inode);
  	if (!root) {
  		iput(inode);
@@ -394,12 +401,15 @@
  		inode = new_inode(s);
  		if (!inode)
  			goto out;
+		if (!registered)
+			inode->i_ino = i;
+		else if (iunique_register(inode, 0))
+			goto out;
  		inode->i_mode = S_IFREG | files->mode;
  		inode->i_uid = inode->i_gid = 0;
  		inode->i_blocks = 0;
  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  		inode->i_fop = files->ops;
-		inode->i_ino = i;
  		d_add(dentry, inode);
  	}
  	s->s_root = root;
@@ -410,6 +420,30 @@
  	return -ENOMEM;
  }

+/*
+ * Fill a superblock with a standard set of fields, and add the entries in the
+ * "files" struct. Assign i_ino values to the files sequentially. This function
+ * is appropriate for filesystems that need a particular i_ino value assigned
+ * to a particular "files" entry.
+ */
+inline int simple_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, false);
+}
+
+/*
+ * Just like simple_fill_super, but does an iunique_register on the inodes
+ * created for "files" entries. This function is appropriate when you don't
+ * need a particular i_ino value assigned to each files entry, and when the
+ * filesystem will have other registered inodes.
+ */
+inline int registered_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, true);
+}
+
  static DEFINE_SPINLOCK(pin_fs_lock);

  int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
@@ -619,6 +653,7 @@
  EXPORT_SYMBOL(simple_empty);
  EXPORT_SYMBOL(d_alloc_name);
  EXPORT_SYMBOL(simple_fill_super);
+EXPORT_SYMBOL(registered_fill_super);
  EXPORT_SYMBOL(simple_getattr);
  EXPORT_SYMBOL(simple_link);
  EXPORT_SYMBOL(simple_lookup);
--- linux-2.6/include/linux/fs.h.super	2006-12-12 08:53:34.000000000 -0500
+++ linux-2.6/include/linux/fs.h	2006-12-12 08:54:14.000000000 -0500
@@ -1879,7 +1879,10 @@
  extern struct inode_operations simple_dir_inode_operations;
  struct tree_descr { char *name; const struct file_operations *ops; int mode; };
  struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files);
+extern int registered_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files);
  extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
  extern void simple_release_fs(struct vfsmount **mount, int *count);

--- linux-2.6/security/inode.c.super	2006-12-12 08:46:47.000000000 -0500
+++ linux-2.6/security/inode.c	2006-12-12 08:54:14.000000000 -0500
@@ -130,7 +130,7 @@
  {
  	static struct tree_descr files[] = {{""}};

-	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+	return registered_fill_super(sb, SECURITYFS_MAGIC, files);
  }

  static int get_sb(struct file_system_type *fs_type,



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
  2006-12-12 16:46 ` Jeff Layton
@ 2006-12-12 18:02   ` linux
  2006-12-12 19:19     ` Jeff Layton
  0 siblings, 1 reply; 7+ messages in thread
From: linux @ 2006-12-12 18:02 UTC (permalink / raw)
  To: jlayton, linux; +Cc: linux-fsdevel, linux-kernel

> Good catch on the inlining. I had meant to do that and missed it.

Er... if you want it to *be* inlined, you have to put it into the .h
file so the compiler knows about it at the call site.  "static inline"
tells gcc not avoid emitting a callable version.

Something like this the following.  (You'll also need to add
a "#include <stdbool.h>", unless you expand the "bool", "false" and
"true" macros to their values "_Bool", "0" and "1" by hand.)

--- linux-2.6/include/linux/fs.h.super	2006-12-12 08:53:34.000000000 -0500
+++ linux-2.6/include/linux/fs.h	2006-12-12 08:54:14.000000000 -0500
@@ -1879,7 +1879,32 @@
  extern struct inode_operations simple_dir_inode_operations;
  struct tree_descr { char *name; const struct file_operations *ops; int mode; };
  struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int __simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files, bool registered);
  extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
  extern void simple_release_fs(struct vfsmount **mount, int *count);

+/*
+ * Fill a superblock with a standard set of fields, and add the entries in the
+ * "files" struct. Assign i_ino values to the files sequentially. This function
+ * is appropriate for filesystems that need a particular i_ino value assigned
+ * to a particular "files" entry.
+ */
+static inline int simple_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, false);
+}
+
+/*
+ * Just like simple_fill_super, but does an iunique_register on the inodes
+ * created for "files" entries. This function is appropriate when you don't
+ * need a particular i_ino value assigned to each files entry, and when the
+ * filesystem will have other registered inodes.
+ */
+static inline int registered_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, true);
+}
+


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
  2006-12-12 18:02   ` linux
@ 2006-12-12 19:19     ` Jeff Layton
  0 siblings, 0 replies; 7+ messages in thread
From: Jeff Layton @ 2006-12-12 19:19 UTC (permalink / raw)
  To: linux; +Cc: linux-fsdevel, linux-kernel

linux@horizon.com wrote:
 >> Good catch on the inlining. I had meant to do that and missed it.
 >
 > Er... if you want it to *be* inlined, you have to put it into the .h
 > file so the compiler knows about it at the call site.  "static inline"
 > tells gcc not avoid emitting a callable version.
 >
 > Something like this the following.  (You'll also need to add
 > a "#include <stdbool.h>", unless you expand the "bool", "false" and
 > "true" macros to their values "_Bool", "0" and "1" by hand.)
 >

Doh! Thanks for explaining that. Here's a respun patch with your suggestion
incorporated. Seems to build correctly without stdbool.h. In fact, I don't see
a stdbool.h in Linus' tree as of this morning. Are you sure that it's needed?

Signed-off-by: Jeff Layton <jlayton@redhat.com>

--- linux-2.6/fs/debugfs/inode.c.super
+++ linux-2.6/fs/debugfs/inode.c
@@ -107,7 +107,7 @@ static int debug_fill_super(struct super
  {
  	static struct tree_descr debug_files[] = {{""}};

-	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
+	return registered_fill_super(sb, DEBUGFS_MAGIC, debug_files);
  }

  static int debug_get_sb(struct file_system_type *fs_type,
--- linux-2.6/fs/fuse/control.c.super
+++ linux-2.6/fs/fuse/control.c
@@ -163,7 +163,7 @@ static int fuse_ctl_fill_super(struct su
  	struct fuse_conn *fc;
  	int err;

-	err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+	err = registered_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
  	if (err)
  		return err;

--- linux-2.6/fs/libfs.c.super
+++ linux-2.6/fs/libfs.c
@@ -215,7 +215,7 @@ int get_sb_pseudo(struct file_system_typ
  	s->s_op = ops ? ops : &default_ops;
  	s->s_time_gran = 1;
  	root = new_inode(s);
-	if (!root)
+	if (!root || iunique_register(root, 0))
  		goto Enomem;
  	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
  	root->i_uid = root->i_gid = 0;
@@ -356,7 +356,8 @@ int simple_commit_write(struct file *fil
  	return 0;
  }

-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int __simple_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files, bool registered)
  {
  	static struct super_operations s_ops = {.statfs = simple_statfs};
  	struct inode *inode;
@@ -380,6 +381,12 @@ int simple_fill_super(struct super_block
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  	inode->i_nlink = 2;
+	/*
+	 * set this as high as a 32 bit val as possible to avoid collisions.
+	 * This is also well above the highest value that iunique_register
+         * will assign to an inode
+	 */
+	inode->i_ino = 0xffffffff;
  	root = d_alloc_root(inode);
  	if (!root) {
  		iput(inode);
@@ -394,12 +401,15 @@ int simple_fill_super(struct super_block
  		inode = new_inode(s);
  		if (!inode)
  			goto out;
+		if (!registered)
+			inode->i_ino = i;
+		else if (iunique_register(inode, 0))
+			goto out;
  		inode->i_mode = S_IFREG | files->mode;
  		inode->i_uid = inode->i_gid = 0;
  		inode->i_blocks = 0;
  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  		inode->i_fop = files->ops;
-		inode->i_ino = i;
  		d_add(dentry, inode);
  	}
  	s->s_root = root;
--- linux-2.6/include/linux/fs.h.super
+++ linux-2.6/include/linux/fs.h
@@ -1879,10 +1879,35 @@ extern const struct file_operations simp
  extern struct inode_operations simple_dir_inode_operations;
  struct tree_descr { char *name; const struct file_operations *ops; int mode; };
  struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int __simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files, bool registered);
  extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
  extern void simple_release_fs(struct vfsmount **mount, int *count);

+/*
+ * Fill a superblock with a standard set of fields, and add the entries in the
+ * "files" struct. Assign i_ino values to the files sequentially. This function
+ * is appropriate for filesystems that need a particular i_ino value assigned
+ * to a particular "files" entry.
+ */
+static inline int simple_fill_super(struct super_block *s, int magic,
+					struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, false);
+}
+
+/*
+ * Just like simple_fill_super, but does an iunique_register on the inodes
+ * created for "files" entries. This function is appropriate when you don't
+ * need a particular i_ino value assigned to each files entry, and when the
+ * filesystem will have other registered inodes.
+ */
+static inline int registered_fill_super(struct super_block *s, int magic,
+						struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, true);
+}
+
  extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);

  #ifdef CONFIG_MIGRATION
--- linux-2.6/security/inode.c.super
+++ linux-2.6/security/inode.c
@@ -130,7 +130,7 @@ static int fill_super(struct super_block
  {
  	static struct tree_descr files[] = {{""}};

-	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+	return registered_fill_super(sb, SECURITYFS_MAGIC, files);
  }

  static int get_sb(struct file_system_type *fs_type,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
       [not found] <20061212194708.8359.qmail@science.horizon.com>
@ 2006-12-12 20:06 ` Jeff Layton
  2006-12-12 20:36   ` Peter Staubach
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff Layton @ 2006-12-12 20:06 UTC (permalink / raw)
  To: linux; +Cc: linux-fsdevel, linux-kernel

linux@horizon.com wrote:
 >> Doh! Thanks for explaining that. Here's a respun patch with your suggestion
 >> incorporated. Seems to build correctly without stdbool.h. In fact, I don't see
 >> a stdbool.h in Linus' tree as of this morning. Are you sure that it's needed?
 >
 > include/linux/types.h:36:typedef _Bool                   bool;
 >
 > It's already in there.  And <linux/stddef.h> has false and true.
 >
 > Sorry; I write more user-level code.
 >
 > The'd be built-in, except that C99 didn't want to add a kewords that
 > might conflict with existing code.

Ok, that makes sense. Though I just found a bug that I missed. I forgot to change the
EXPORT_SYMBOL in libfs.c. This should fix it:

Signed-off-by: Jeff Layton <jlayton@redhat.com>

--- linux-2.6/fs/debugfs/inode.c.super
+++ linux-2.6/fs/debugfs/inode.c
@@ -107,7 +107,7 @@ static int debug_fill_super(struct super
  {
  	static struct tree_descr debug_files[] = {{""}};

-	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
+	return registered_fill_super(sb, DEBUGFS_MAGIC, debug_files);
  }

  static int debug_get_sb(struct file_system_type *fs_type,
--- linux-2.6/fs/fuse/control.c.super
+++ linux-2.6/fs/fuse/control.c
@@ -163,7 +163,7 @@ static int fuse_ctl_fill_super(struct su
  	struct fuse_conn *fc;
  	int err;

-	err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+	err = registered_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
  	if (err)
  		return err;

--- linux-2.6/fs/libfs.c.super
+++ linux-2.6/fs/libfs.c
@@ -215,7 +215,7 @@ int get_sb_pseudo(struct file_system_typ
  	s->s_op = ops ? ops : &default_ops;
  	s->s_time_gran = 1;
  	root = new_inode(s);
-	if (!root)
+	if (!root || iunique_register(root, 0))
  		goto Enomem;
  	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
  	root->i_uid = root->i_gid = 0;
@@ -356,7 +356,8 @@ int simple_commit_write(struct file *fil
  	return 0;
  }

-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int __simple_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files, bool registered)
  {
  	static struct super_operations s_ops = {.statfs = simple_statfs};
  	struct inode *inode;
@@ -380,6 +381,12 @@ int simple_fill_super(struct super_block
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  	inode->i_nlink = 2;
+	/*
+	 * set this as high as a 32 bit val as possible to avoid collisions.
+	 * This is also well above the highest value that iunique_register
+         * will assign to an inode
+	 */
+	inode->i_ino = 0xffffffff;
  	root = d_alloc_root(inode);
  	if (!root) {
  		iput(inode);
@@ -394,12 +401,15 @@ int simple_fill_super(struct super_block
  		inode = new_inode(s);
  		if (!inode)
  			goto out;
+		if (!registered)
+			inode->i_ino = i;
+		else if (iunique_register(inode, 0))
+			goto out;
  		inode->i_mode = S_IFREG | files->mode;
  		inode->i_uid = inode->i_gid = 0;
  		inode->i_blocks = 0;
  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  		inode->i_fop = files->ops;
-		inode->i_ino = i;
  		d_add(dentry, inode);
  	}
  	s->s_root = root;
@@ -618,7 +628,7 @@ EXPORT_SYMBOL(simple_dir_inode_operation
  EXPORT_SYMBOL(simple_dir_operations);
  EXPORT_SYMBOL(simple_empty);
  EXPORT_SYMBOL(d_alloc_name);
-EXPORT_SYMBOL(simple_fill_super);
+EXPORT_SYMBOL(__simple_fill_super);
  EXPORT_SYMBOL(simple_getattr);
  EXPORT_SYMBOL(simple_link);
  EXPORT_SYMBOL(simple_lookup);
--- linux-2.6/include/linux/fs.h.super
+++ linux-2.6/include/linux/fs.h
@@ -1879,10 +1879,35 @@ extern const struct file_operations simp
  extern struct inode_operations simple_dir_inode_operations;
  struct tree_descr { char *name; const struct file_operations *ops; int mode; };
  struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int __simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files, bool registered);
  extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
  extern void simple_release_fs(struct vfsmount **mount, int *count);

+/*
+ * Fill a superblock with a standard set of fields, and add the entries in the
+ * "files" struct. Assign i_ino values to the files sequentially. This function
+ * is appropriate for filesystems that need a particular i_ino value assigned
+ * to a particular "files" entry.
+ */
+static inline int simple_fill_super(struct super_block *s, int magic,
+					struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, false);
+}
+
+/*
+ * Just like simple_fill_super, but does an iunique_register on the inodes
+ * created for "files" entries. This function is appropriate when you don't
+ * need a particular i_ino value assigned to each files entry, and when the
+ * filesystem will have other registered inodes.
+ */
+static inline int registered_fill_super(struct super_block *s, int magic,
+						struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, true);
+}
+
  extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);

  #ifdef CONFIG_MIGRATION
--- linux-2.6/security/inode.c.super
+++ linux-2.6/security/inode.c
@@ -130,7 +130,7 @@ static int fill_super(struct super_block
  {
  	static struct tree_descr files[] = {{""}};

-	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+	return registered_fill_super(sb, SECURITYFS_MAGIC, files);
  }

  static int get_sb(struct file_system_type *fs_type,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
  2006-12-12 20:06 ` [PATCH 2/3] ensure unique i_ino in filesystems without permanent Jeff Layton
@ 2006-12-12 20:36   ` Peter Staubach
  2006-12-12 22:45     ` Jeff Layton
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Staubach @ 2006-12-12 20:36 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux, linux-fsdevel, linux-kernel

Jeff Layton wrote:
> linux@horizon.com wrote:
> >> Doh! Thanks for explaining that. Here's a respun patch with your 
> suggestion
> >> incorporated. Seems to build correctly without stdbool.h. In fact, 
> I don't see
> >> a stdbool.h in Linus' tree as of this morning. Are you sure that 
> it's needed?
> >
> > include/linux/types.h:36:typedef _Bool                   bool;
> >
> > It's already in there.  And <linux/stddef.h> has false and true.
> >
> > Sorry; I write more user-level code.
> >
> > The'd be built-in, except that C99 didn't want to add a kewords that
> > might conflict with existing code.
>
> Ok, that makes sense. Though I just found a bug that I missed. I 
> forgot to change the
> EXPORT_SYMBOL in libfs.c. This should fix it:
>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
>
> --- linux-2.6/fs/debugfs/inode.c.super
> +++ linux-2.6/fs/debugfs/inode.c
> @@ -107,7 +107,7 @@ static int debug_fill_super(struct super
>  {
>      static struct tree_descr debug_files[] = {{""}};
>
> -    return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
> +    return registered_fill_super(sb, DEBUGFS_MAGIC, debug_files);
>  }
>
>  static int debug_get_sb(struct file_system_type *fs_type,
> --- linux-2.6/fs/fuse/control.c.super
> +++ linux-2.6/fs/fuse/control.c
> @@ -163,7 +163,7 @@ static int fuse_ctl_fill_super(struct su
>      struct fuse_conn *fc;
>      int err;
>
> -    err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
> +    err = registered_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
>      if (err)
>          return err;
>
> --- linux-2.6/fs/libfs.c.super
> +++ linux-2.6/fs/libfs.c
> @@ -215,7 +215,7 @@ int get_sb_pseudo(struct file_system_typ
>      s->s_op = ops ? ops : &default_ops;
>      s->s_time_gran = 1;
>      root = new_inode(s);
> -    if (!root)
> +    if (!root || iunique_register(root, 0))
>          goto Enomem;
>      root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
>      root->i_uid = root->i_gid = 0;
> @@ -356,7 +356,8 @@ int simple_commit_write(struct file *fil
>      return 0;
>  }
>

If iunique_register() fails, does not this create a memory leak
because root will need to get iput()'d?

> -int simple_fill_super(struct super_block *s, int magic, struct 
> tree_descr *files)
> +int __simple_fill_super(struct super_block *s, int magic,
> +            struct tree_descr *files, bool registered)
>  {
>      static struct super_operations s_ops = {.statfs = simple_statfs};
>      struct inode *inode;
> @@ -380,6 +381,12 @@ int simple_fill_super(struct super_block
>      inode->i_op = &simple_dir_inode_operations;
>      inode->i_fop = &simple_dir_operations;
>      inode->i_nlink = 2;
> +    /*
> +     * set this as high as a 32 bit val as possible to avoid collisions.
> +     * This is also well above the highest value that iunique_register
> +         * will assign to an inode
> +     */
> +    inode->i_ino = 0xffffffff;
>      root = d_alloc_root(inode);
>      if (!root) {
>          iput(inode);
> @@ -394,12 +401,15 @@ int simple_fill_super(struct super_block
>          inode = new_inode(s);
>          if (!inode)
>              goto out;
> +        if (!registered)
> +            inode->i_ino = i;
> +        else if (iunique_register(inode, 0))
> +            goto out;

Does this not create a memory leak as well?

    Thanx...

       ps

>          inode->i_mode = S_IFREG | files->mode;
>          inode->i_uid = inode->i_gid = 0;
>          inode->i_blocks = 0;
>          inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
>          inode->i_fop = files->ops;
> -        inode->i_ino = i;
>          d_add(dentry, inode);
>      }
>      s->s_root = root;
> @@ -618,7 +628,7 @@ EXPORT_SYMBOL(simple_dir_inode_operation
>  EXPORT_SYMBOL(simple_dir_operations);
>  EXPORT_SYMBOL(simple_empty);
>  EXPORT_SYMBOL(d_alloc_name);
> -EXPORT_SYMBOL(simple_fill_super);
> +EXPORT_SYMBOL(__simple_fill_super);
>  EXPORT_SYMBOL(simple_getattr);
>  EXPORT_SYMBOL(simple_link);
>  EXPORT_SYMBOL(simple_lookup);
> --- linux-2.6/include/linux/fs.h.super
> +++ linux-2.6/include/linux/fs.h
> @@ -1879,10 +1879,35 @@ extern const struct file_operations simp
>  extern struct inode_operations simple_dir_inode_operations;
>  struct tree_descr { char *name; const struct file_operations *ops; 
> int mode; };
>  struct dentry *d_alloc_name(struct dentry *, const char *);
> -extern int simple_fill_super(struct super_block *, int, struct 
> tree_descr *);
> +extern int __simple_fill_super(struct super_block *s, int magic,
> +                struct tree_descr *files, bool registered);
>  extern int simple_pin_fs(struct file_system_type *, struct vfsmount 
> **mount, int *count);
>  extern void simple_release_fs(struct vfsmount **mount, int *count);
>
> +/*
> + * Fill a superblock with a standard set of fields, and add the 
> entries in the
> + * "files" struct. Assign i_ino values to the files sequentially. 
> This function
> + * is appropriate for filesystems that need a particular i_ino value 
> assigned
> + * to a particular "files" entry.
> + */
> +static inline int simple_fill_super(struct super_block *s, int magic,
> +                    struct tree_descr *files)
> +{
> +    return __simple_fill_super(s, magic, files, false);
> +}
> +
> +/*
> + * Just like simple_fill_super, but does an iunique_register on the 
> inodes
> + * created for "files" entries. This function is appropriate when you 
> don't
> + * need a particular i_ino value assigned to each files entry, and 
> when the
> + * filesystem will have other registered inodes.
> + */
> +static inline int registered_fill_super(struct super_block *s, int 
> magic,
> +                        struct tree_descr *files)
> +{
> +    return __simple_fill_super(s, magic, files, true);
> +}
> +
>  extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t 
> *, const void *, size_t);
>
>  #ifdef CONFIG_MIGRATION
> --- linux-2.6/security/inode.c.super
> +++ linux-2.6/security/inode.c
> @@ -130,7 +130,7 @@ static int fill_super(struct super_block
>  {
>      static struct tree_descr files[] = {{""}};
>
> -    return simple_fill_super(sb, SECURITYFS_MAGIC, files);
> +    return registered_fill_super(sb, SECURITYFS_MAGIC, files);
>  }
>
>  static int get_sb(struct file_system_type *fs_type,
> -
> To unsubscribe from this list: send the line "unsubscribe 
> linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
  2006-12-12 20:36   ` Peter Staubach
@ 2006-12-12 22:45     ` Jeff Layton
  2006-12-12 22:50       ` Jeff Layton
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff Layton @ 2006-12-12 22:45 UTC (permalink / raw)
  To: Peter Staubach; +Cc: linux-fsdevel, linux-kernel

Peter Staubach wrote:
 >
 > If iunique_register() fails, does not this create a memory leak
 > because root will need to get iput()'d?
 >

Good point, and now that we have a wrapper for new_inode that handles this
error transparently, both places are easy to fix. This patch should do it:

Signed-off-by: Jeff Layton <jlayton@redhat.com>

--- linux-2.6/fs/debugfs/inode.c.super
+++ linux-2.6/fs/debugfs/inode.c
@@ -107,7 +107,7 @@ static int debug_fill_super(struct super
  {
  	static struct tree_descr debug_files[] = {{""}};

-	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
+	return registered_fill_super(sb, DEBUGFS_MAGIC, debug_files);
  }

  static int debug_get_sb(struct file_system_type *fs_type,
--- linux-2.6/fs/fuse/control.c.super
+++ linux-2.6/fs/fuse/control.c
@@ -163,7 +163,7 @@ static int fuse_ctl_fill_super(struct su
  	struct fuse_conn *fc;
  	int err;

-	err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+	err = registered_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
  	if (err)
  		return err;

--- linux-2.6/fs/libfs.c.super
+++ linux-2.6/fs/libfs.c
@@ -214,7 +214,7 @@ int get_sb_pseudo(struct file_system_typ
  	s->s_magic = magic;
  	s->s_op = ops ? ops : &default_ops;
  	s->s_time_gran = 1;
-	root = new_inode(s);
+	root = new_registered_inode(s, 0);
  	if (!root)
  		goto Enomem;
  	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
@@ -356,7 +356,8 @@ int simple_commit_write(struct file *fil
  	return 0;
  }

-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int __simple_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files, bool registered)
  {
  	static struct super_operations s_ops = {.statfs = simple_statfs};
  	struct inode *inode;
@@ -380,6 +381,12 @@ int simple_fill_super(struct super_block
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  	inode->i_nlink = 2;
+	/*
+	 * set this as high as a 32 bit val as possible to avoid collisions.
+	 * This is also well above the highest value that iunique_register
+	 * will assign to an inode
+	 */
+	inode->i_ino = 0xffffffff;
  	root = d_alloc_root(inode);
  	if (!root) {
  		iput(inode);
@@ -391,7 +398,12 @@ int simple_fill_super(struct super_block
  		dentry = d_alloc_name(root, files->name);
  		if (!dentry)
  			goto out;
-		inode = new_inode(s);
+		if (registered)
+			inode = new_registered_inode(s, 0);
+		else {
+			inode = new_inode(s);
+			inode->i_ino = i;
+		}
  		if (!inode)
  			goto out;
  		inode->i_mode = S_IFREG | files->mode;
@@ -399,7 +411,6 @@ int simple_fill_super(struct super_block
  		inode->i_blocks = 0;
  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  		inode->i_fop = files->ops;
-		inode->i_ino = i;
  		d_add(dentry, inode);
  	}
  	s->s_root = root;
@@ -618,7 +629,7 @@ EXPORT_SYMBOL(simple_dir_inode_operation
  EXPORT_SYMBOL(simple_dir_operations);
  EXPORT_SYMBOL(simple_empty);
  EXPORT_SYMBOL(d_alloc_name);
-EXPORT_SYMBOL(simple_fill_super);
+EXPORT_SYMBOL(__simple_fill_super);
  EXPORT_SYMBOL(simple_getattr);
  EXPORT_SYMBOL(simple_link);
  EXPORT_SYMBOL(simple_lookup);
--- linux-2.6/include/linux/fs.h.super
+++ linux-2.6/include/linux/fs.h
@@ -1879,10 +1879,35 @@ extern const struct file_operations simp
  extern struct inode_operations simple_dir_inode_operations;
  struct tree_descr { char *name; const struct file_operations *ops; int mode; };
  struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int __simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files, bool registered);
  extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
  extern void simple_release_fs(struct vfsmount **mount, int *count);

+/*
+ * Fill a superblock with a standard set of fields, and add the entries in the
+ * "files" struct. Assign i_ino values to the files sequentially. This function
+ * is appropriate for filesystems that need a particular i_ino value assigned
+ * to a particular "files" entry.
+ */
+static inline int simple_fill_super(struct super_block *s, int magic,
+					struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, false);
+}
+
+/*
+ * Just like simple_fill_super, but does an iunique_register on the inodes
+ * created for "files" entries. This function is appropriate when you don't
+ * need a particular i_ino value assigned to each files entry, and when the
+ * filesystem will have other registered inodes.
+ */
+static inline int registered_fill_super(struct super_block *s, int magic,
+						struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, true);
+}
+
  extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);

  #ifdef CONFIG_MIGRATION
--- linux-2.6/security/inode.c.super
+++ linux-2.6/security/inode.c
@@ -130,7 +130,7 @@ static int fill_super(struct super_block
  {
  	static struct tree_descr files[] = {{""}};

-	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+	return registered_fill_super(sb, SECURITYFS_MAGIC, files);
  }

  static int get_sb(struct file_system_type *fs_type,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] ensure unique i_ino in filesystems without permanent
  2006-12-12 22:45     ` Jeff Layton
@ 2006-12-12 22:50       ` Jeff Layton
  0 siblings, 0 replies; 7+ messages in thread
From: Jeff Layton @ 2006-12-12 22:50 UTC (permalink / raw)
  To: Peter Staubach; +Cc: linux-fsdevel, linux-kernel

Jeff Layton wrote:
 > Peter Staubach wrote:
 >  >
 >  > If iunique_register() fails, does not this create a memory leak
 >  > because root will need to get iput()'d?
 >  >
 >
 > Good point, and now that we have a wrapper for new_inode that handles this
 > error transparently, both places are easy to fix. This patch should do it:

I really need to proofread better before sending. That patch would crash if
new_inode returned NULL. This should be correct:

Signed-off-by: Jeff Layton <jlayton@redhat.com>

--- linux-2.6/fs/debugfs/inode.c.super
+++ linux-2.6/fs/debugfs/inode.c
@@ -107,7 +107,7 @@ static int debug_fill_super(struct super
  {
  	static struct tree_descr debug_files[] = {{""}};

-	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
+	return registered_fill_super(sb, DEBUGFS_MAGIC, debug_files);
  }

  static int debug_get_sb(struct file_system_type *fs_type,
--- linux-2.6/fs/fuse/control.c.super
+++ linux-2.6/fs/fuse/control.c
@@ -163,7 +163,7 @@ static int fuse_ctl_fill_super(struct su
  	struct fuse_conn *fc;
  	int err;

-	err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+	err = registered_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
  	if (err)
  		return err;

--- linux-2.6/fs/libfs.c.super
+++ linux-2.6/fs/libfs.c
@@ -214,7 +214,7 @@ int get_sb_pseudo(struct file_system_typ
  	s->s_magic = magic;
  	s->s_op = ops ? ops : &default_ops;
  	s->s_time_gran = 1;
-	root = new_inode(s);
+	root = new_registered_inode(s, 0);
  	if (!root)
  		goto Enomem;
  	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
@@ -356,7 +356,8 @@ int simple_commit_write(struct file *fil
  	return 0;
  }

-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int __simple_fill_super(struct super_block *s, int magic,
+			struct tree_descr *files, bool registered)
  {
  	static struct super_operations s_ops = {.statfs = simple_statfs};
  	struct inode *inode;
@@ -380,6 +381,12 @@ int simple_fill_super(struct super_block
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  	inode->i_nlink = 2;
+	/*
+	 * set this as high as a 32 bit val as possible to avoid collisions.
+	 * This is also well above the highest value that iunique_register
+	 * will assign to an inode
+	 */
+	inode->i_ino = 0xffffffff;
  	root = d_alloc_root(inode);
  	if (!root) {
  		iput(inode);
@@ -391,15 +398,21 @@ int simple_fill_super(struct super_block
  		dentry = d_alloc_name(root, files->name);
  		if (!dentry)
  			goto out;
-		inode = new_inode(s);
+		if (registered)
+			inode = new_registered_inode(s, 0);
+		else
+			inode = new_inode(s);
+
  		if (!inode)
  			goto out;
+
+		if (!registered)
+			inode->i_ino = i;	
  		inode->i_mode = S_IFREG | files->mode;
  		inode->i_uid = inode->i_gid = 0;
  		inode->i_blocks = 0;
  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  		inode->i_fop = files->ops;
-		inode->i_ino = i;
  		d_add(dentry, inode);
  	}
  	s->s_root = root;
@@ -618,7 +631,7 @@ EXPORT_SYMBOL(simple_dir_inode_operation
  EXPORT_SYMBOL(simple_dir_operations);
  EXPORT_SYMBOL(simple_empty);
  EXPORT_SYMBOL(d_alloc_name);
-EXPORT_SYMBOL(simple_fill_super);
+EXPORT_SYMBOL(__simple_fill_super);
  EXPORT_SYMBOL(simple_getattr);
  EXPORT_SYMBOL(simple_link);
  EXPORT_SYMBOL(simple_lookup);
--- linux-2.6/include/linux/fs.h.super
+++ linux-2.6/include/linux/fs.h
@@ -1879,10 +1879,35 @@ extern const struct file_operations simp
  extern struct inode_operations simple_dir_inode_operations;
  struct tree_descr { char *name; const struct file_operations *ops; int mode; };
  struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int __simple_fill_super(struct super_block *s, int magic,
+				struct tree_descr *files, bool registered);
  extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
  extern void simple_release_fs(struct vfsmount **mount, int *count);

+/*
+ * Fill a superblock with a standard set of fields, and add the entries in the
+ * "files" struct. Assign i_ino values to the files sequentially. This function
+ * is appropriate for filesystems that need a particular i_ino value assigned
+ * to a particular "files" entry.
+ */
+static inline int simple_fill_super(struct super_block *s, int magic,
+					struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, false);
+}
+
+/*
+ * Just like simple_fill_super, but does an iunique_register on the inodes
+ * created for "files" entries. This function is appropriate when you don't
+ * need a particular i_ino value assigned to each files entry, and when the
+ * filesystem will have other registered inodes.
+ */
+static inline int registered_fill_super(struct super_block *s, int magic,
+						struct tree_descr *files)
+{
+	return __simple_fill_super(s, magic, files, true);
+}
+
  extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);

  #ifdef CONFIG_MIGRATION
--- linux-2.6/security/inode.c.super
+++ linux-2.6/security/inode.c
@@ -130,7 +130,7 @@ static int fill_super(struct super_block
  {
  	static struct tree_descr files[] = {{""}};

-	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+	return registered_fill_super(sb, SECURITYFS_MAGIC, files);
  }

  static int get_sb(struct file_system_type *fs_type,

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2006-12-12 22:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20061212194708.8359.qmail@science.horizon.com>
2006-12-12 20:06 ` [PATCH 2/3] ensure unique i_ino in filesystems without permanent Jeff Layton
2006-12-12 20:36   ` Peter Staubach
2006-12-12 22:45     ` Jeff Layton
2006-12-12 22:50       ` Jeff Layton
     [not found] <20061210175652.7537.qmail@science.horizon.com>
2006-12-12 16:46 ` Jeff Layton
2006-12-12 18:02   ` linux
2006-12-12 19:19     ` Jeff Layton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).