LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC 00/11] possible debugfs/libfs consolidation
@ 2008-02-19  4:04 Arnd Bergmann
  2008-02-19  4:04 ` [RFC 01/11] add generic versions of debugfs file operations Arnd Bergmann
                   ` (11 more replies)
  0 siblings, 12 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

I noticed that there is a lot of duplication in pseudo
file systems, so I started looking into how to consolidate
them. I ended up with a largish rework of the structure
of libfs and moving almost all of debugfs in there as well.

As an example, I also have patches that reduce debugfs,
securityfs and usbfs to the point where they are mostly
thin wrappers around libfs, with large comment blocks.
Other file systems could be changed in the same way, but
I first like to see if people agree that I'm on the right
track.

These patches have seen practically no testing so far,
so don't expect them to work, but please tell me what
you think about the concept.

	Arnd <><


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

* [RFC 01/11] add generic versions of debugfs file operations
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-23 12:24   ` Al Viro
  2008-02-23 12:33   ` Al Viro
  2008-02-19  4:04 ` [RFC 02/11] introduce simple_fs_type Arnd Bergmann
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: introduce-libfs-files.diff --]
[-- Type: text/plain, Size: 6352 bytes --]

The file operations in debugfs are rather generic and can
be used by other file systems, so it can be interesting to
include them in libfs, with more generic names, and exported
to modules.

This patch adds a new copy of these operations to libfs,
so that the debugfs version can later be cut down.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Index: linux-2.6/fs/Makefile
===================================================================
--- linux-2.6.orig/fs/Makefile
+++ linux-2.6/fs/Makefile
@@ -13,6 +13,8 @@ obj-y :=	open.o read_write.o file_table.
 		pnode.o drop_caches.o splice.o sync.o utimes.o \
 		stack.o
 
+obj-$(CONFIG_LIBFS) += libfs/
+
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=	buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
 else
Index: linux-2.6/include/linux/libfs.h
===================================================================
--- /dev/null
+++ linux-2.6/include/linux/libfs.h
@@ -0,0 +1,21 @@
+#ifndef __LIBFS_H__
+#define __LIBFS_H__
+
+#include <linux/fs.h>
+
+extern const struct file_operations simple_fops_u8;
+extern const struct file_operations simple_fops_x8;
+extern const struct file_operations simple_fops_u16;
+extern const struct file_operations simple_fops_x16;
+extern const struct file_operations simple_fops_u32;
+extern const struct file_operations simple_fops_x32;
+extern const struct file_operations simple_fops_u64;
+extern const struct file_operations simple_fops_bool;
+extern const struct file_operations simple_fops_blob;
+
+struct simple_blob_wrapper {
+	void *data;
+	unsigned long size;
+};
+
+#endif /* __LIBFS_H__ */
Index: linux-2.6/fs/libfs/Makefile
===================================================================
--- /dev/null
+++ linux-2.6/fs/libfs/Makefile
@@ -0,0 +1,3 @@
+libfs-y += file.o
+
+obj-$(CONFIG_LIBFS) += libfs.o
Index: linux-2.6/fs/libfs/file.c
===================================================================
--- /dev/null
+++ linux-2.6/fs/libfs/file.c
@@ -0,0 +1,126 @@
+/*
+ *	fs/libfs/file.c
+ *	Library for filesystems writers.
+ */
+
+#include <linux/fs.h>
+#include <linux/libfs.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+
+/* commonly used attribute file operations */
+static int simple_u8_set(void *data, u64 val)
+{
+	*(u8 *)data = val;
+	return 0;
+}
+static int simple_u8_get(void *data, u64 *val)
+{
+	*val = *(u8 *)data;
+	return 0;
+}
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_u8, simple_u8_get, simple_u8_set, "%llu\n");
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_x8, simple_u8_get, simple_u8_set, "0x%02llx\n");
+
+static int simple_u16_set(void *data, u64 val)
+{
+	*(u16 *)data = val;
+	return 0;
+}
+static int simple_u16_get(void *data, u64 *val)
+{
+	*val = *(u16 *)data;
+	return 0;
+}
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_u16, simple_u16_get, simple_u16_set, "%llu\n");
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_x16, simple_u16_get, simple_u16_set, "0x%04llx\n");
+
+static int simple_u32_set(void *data, u64 val)
+{
+	*(u32 *)data = val;
+	return 0;
+}
+static int simple_u32_get(void *data, u64 *val)
+{
+	*val = *(u32 *)data;
+	return 0;
+}
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_u32, simple_u32_get, simple_u32_set, "%llu\n");
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_x32, simple_u32_get, simple_u32_set, "0x%08llx\n");
+
+static int simple_u64_set(void *data, u64 val)
+{
+	*(u64 *)data = val;
+	return 0;
+}
+
+static int simple_u64_get(void *data, u64 *val)
+{
+	return *(u64 *)data;
+	return 0;
+}
+DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(simple_fops_u64, simple_u64_get, simple_u64_set, "%llu\n");
+
+static ssize_t read_file_bool(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	char buf[3];
+	u32 *val = file->private_data;
+
+	if (*val)
+		buf[0] = 'Y';
+	else
+		buf[0] = 'N';
+	buf[1] = '\n';
+	buf[2] = 0x00;
+	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
+			       size_t count, loff_t *ppos)
+{
+	char buf[32];
+	int buf_size;
+	u32 *val = file->private_data;
+
+	buf_size = min(count, (sizeof(buf)-1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+
+	switch (buf[0]) {
+	case 'y':
+	case 'Y':
+	case '1':
+		*val = 1;
+		break;
+	case 'n':
+	case 'N':
+	case '0':
+		*val = 0;
+		break;
+	}
+
+	return count;
+}
+
+const struct file_operations simple_fops_bool = {
+	.read =		read_file_bool,
+	.write =	write_file_bool,
+	.open =		simple_open,
+};
+EXPORT_SYMBOL_GPL(simple_fops_bool);
+
+static ssize_t read_file_blob(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	struct simple_blob_wrapper *blob = file->private_data;
+	return simple_read_from_buffer(user_buf, count, ppos, blob->data,
+			blob->size);
+}
+
+const struct file_operations simple_fops_blob = {
+	.read =		read_file_blob,
+	.open =		simple_open,
+};
+EXPORT_SYMBOL_GPL(simple_fops_blob);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -2042,19 +2042,26 @@ static inline void simple_transaction_se
  * All attributes contain a text representation of a numeric value
  * that are accessed with the get() and set() functions.
  */
-#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
+#define __DEFINE_SIMPLE_ATTRIBUTE(__static, __fops, __get, __set, __fmt)\
 static int __fops ## _open(struct inode *inode, struct file *file)	\
 {									\
 	__simple_attr_check_format(__fmt, 0ull);			\
 	return simple_attr_open(inode, file, __get, __set, __fmt);	\
 }									\
-static struct file_operations __fops = {				\
+__static const struct file_operations __fops = {			\
 	.owner	 = THIS_MODULE,						\
 	.open	 = __fops ## _open,					\
 	.release = simple_attr_release,					\
 	.read	 = simple_attr_read,					\
 	.write	 = simple_attr_write,					\
-};
+}
+
+#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
+	__DEFINE_SIMPLE_ATTRIBUTE(static, __fops, __get, __set, __fmt)
+
+#define DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(__fops, __get, __set, __fmt)	\
+	__DEFINE_SIMPLE_ATTRIBUTE(/**/, __fops, __get, __set, __fmt);	\
+	EXPORT_SYMBOL_GPL(__fops)
 
 static inline void __attribute__((format(printf, 1, 2)))
 __simple_attr_check_format(const char *fmt, ...)

-- 


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

* [RFC 02/11] introduce simple_fs_type
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
  2008-02-19  4:04 ` [RFC 01/11] add generic versions of debugfs file operations Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-23 12:28   ` Al Viro
  2008-02-19  4:04 ` [RFC 03/11] slim down debugfs Arnd Bergmann
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-super.diff --]
[-- Type: text/plain, Size: 24993 bytes --]

There is a number of pseudo file systems in the kernel
that are basically copies of debugfs, all implementing the
same boilerplate code, just with different bugs.

This adds yet another copy to the kernel in the libfs directory,
with generalized helpers that can be used by any of them.

The most interesting function here is the new "struct dentry *
simple_register_filesystem(struct simple_fs_type *type)", which
returns the root directory of a new file system that can then
be passed to simple_create_file() and similar functions as a
parent.

Signed-off-by: Arnd Bergman <arnd@arndb.de>
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -263,11 +263,6 @@ int simple_link(struct dentry *old_dentr
 	return 0;
 }
 
-static inline int simple_positive(struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
 int simple_empty(struct dentry *dentry)
 {
 	struct dentry *child;
@@ -409,109 +404,6 @@ int simple_write_end(struct file *file, 
 	return copied;
 }
 
-/*
- * the inodes created here are not hashed. If you use iunique to generate
- * unique inode values later for this filesystem, then you must take care
- * to pass it an appropriate max_reserved value to avoid collisions.
- */
-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
-{
-	struct inode *inode;
-	struct dentry *root;
-	struct dentry *dentry;
-	int i;
-
-	s->s_blocksize = PAGE_CACHE_SIZE;
-	s->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	s->s_magic = magic;
-	s->s_op = &simple_super_operations;
-	s->s_time_gran = 1;
-
-	inode = new_inode(s);
-	if (!inode)
-		return -ENOMEM;
-	/*
-	 * because the root inode is 1, the files array must not contain an
-	 * entry at index 1
-	 */
-	inode->i_ino = 1;
-	inode->i_mode = S_IFDIR | 0755;
-	inode->i_uid = inode->i_gid = 0;
-	inode->i_blocks = 0;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_op = &simple_dir_inode_operations;
-	inode->i_fop = &simple_dir_operations;
-	inode->i_nlink = 2;
-	root = d_alloc_root(inode);
-	if (!root) {
-		iput(inode);
-		return -ENOMEM;
-	}
-	for (i = 0; !files->name || files->name[0]; i++, files++) {
-		if (!files->name)
-			continue;
-
-		/* warn if it tries to conflict with the root inode */
-		if (unlikely(i == 1))
-			printk(KERN_WARNING "%s: %s passed in a files array"
-				"with an index of 1!\n", __func__,
-				s->s_type->name);
-
-		dentry = d_alloc_name(root, files->name);
-		if (!dentry)
-			goto out;
-		inode = new_inode(s);
-		if (!inode)
-			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;
-	return 0;
-out:
-	d_genocide(root);
-	dput(root);
-	return -ENOMEM;
-}
-
-static DEFINE_SPINLOCK(pin_fs_lock);
-
-int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
-{
-	struct vfsmount *mnt = NULL;
-	spin_lock(&pin_fs_lock);
-	if (unlikely(!*mount)) {
-		spin_unlock(&pin_fs_lock);
-		mnt = vfs_kern_mount(type, 0, type->name, NULL);
-		if (IS_ERR(mnt))
-			return PTR_ERR(mnt);
-		spin_lock(&pin_fs_lock);
-		if (!*mount)
-			*mount = mnt;
-	}
-	mntget(*mount);
-	++*count;
-	spin_unlock(&pin_fs_lock);
-	mntput(mnt);
-	return 0;
-}
-
-void simple_release_fs(struct vfsmount **mount, int *count)
-{
-	struct vfsmount *mnt;
-	spin_lock(&pin_fs_lock);
-	mnt = *mount;
-	if (!--*count)
-		*mount = NULL;
-	spin_unlock(&pin_fs_lock);
-	mntput(mnt);
-}
-
 ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
 				const void *from, size_t available)
 {
@@ -786,14 +678,11 @@ 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_getattr);
 EXPORT_SYMBOL(simple_link);
 EXPORT_SYMBOL(simple_lookup);
-EXPORT_SYMBOL(simple_pin_fs);
 EXPORT_SYMBOL(simple_prepare_write);
 EXPORT_SYMBOL(simple_readpage);
-EXPORT_SYMBOL(simple_release_fs);
 EXPORT_SYMBOL(simple_rename);
 EXPORT_SYMBOL(simple_rmdir);
 EXPORT_SYMBOL(simple_statfs);
Index: linux-2.6/fs/libfs/super.c
===================================================================
--- /dev/null
+++ linux-2.6/fs/libfs/super.c
@@ -0,0 +1,179 @@
+/*
+ *	fs/libfs/super.c
+ *	Library for filesystems writers -- superblock operations
+ */
+
+#include <linux/libfs.h>
+#include <linux/fsnotify.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/mount.h>
+#include <linux/vfs.h>
+#include <linux/mutex.h>
+#include <linux/exportfs.h>
+
+#include <asm/uaccess.h>
+
+static DEFINE_SPINLOCK(pin_fs_lock);
+
+int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
+{
+	struct vfsmount *mnt = NULL;
+	spin_lock(&pin_fs_lock);
+	if (unlikely(!*mount)) {
+		spin_unlock(&pin_fs_lock);
+		mnt = vfs_kern_mount(type, 0, type->name, NULL);
+		if (IS_ERR(mnt))
+			return PTR_ERR(mnt);
+		spin_lock(&pin_fs_lock);
+		if (!*mount)
+			*mount = mnt;
+	}
+	mntget(*mount);
+	++*count;
+	spin_unlock(&pin_fs_lock);
+	mntput(mnt);
+	return 0;
+}
+EXPORT_SYMBOL(simple_pin_fs);
+
+void simple_release_fs(struct vfsmount **mount, int *count)
+{
+	struct vfsmount *mnt;
+	spin_lock(&pin_fs_lock);
+	mnt = *mount;
+	if (!--*count)
+		*mount = NULL;
+	spin_unlock(&pin_fs_lock);
+	mntput(mnt);
+}
+EXPORT_SYMBOL(simple_release_fs);
+
+static const struct super_operations simple_super_operations = {
+	.statfs		= simple_statfs,
+};
+
+/*
+ * the inodes created here are not hashed. If you use iunique to generate
+ * unique inode values later for this filesystem, then you must take care
+ * to pass it an appropriate max_reserved value to avoid collisions.
+ */
+int simple_fill_super(struct super_block *s, int magic, const struct tree_descr *files)
+{
+	struct inode *inode;
+	struct dentry *root;
+	struct dentry *dentry;
+	int i;
+
+	s->s_blocksize = PAGE_CACHE_SIZE;
+	s->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	s->s_magic = magic;
+	if (!s->s_op)
+		s->s_op = &simple_super_operations;
+	s->s_time_gran = 1;
+
+	inode = new_inode(s);
+	if (!inode)
+		return -ENOMEM;
+	/*
+	 * because the root inode is 1, the files array must not contain an
+	 * entry at index 1
+	 */
+	inode->i_ino = 1;
+	inode->i_mode = S_IFDIR | 0755;
+	inode->i_uid = inode->i_gid = 0;
+	inode->i_blocks = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->i_op = &simple_dir_inode_operations;
+	inode->i_fop = &simple_dir_operations;
+	inode->i_nlink = 2;
+	root = d_alloc_root(inode);
+	if (!root) {
+		iput(inode);
+		return -ENOMEM;
+	}
+	for (i = 0; !files->name || files->name[0]; i++, files++) {
+		if (!files->name)
+			continue;
+
+		/* warn if it tries to conflict with the root inode */
+		if (unlikely(i == 1))
+			printk(KERN_WARNING "%s: %s passed in a files array"
+				"with an index of 1!\n", __func__,
+				s->s_type->name);
+
+		dentry = d_alloc_name(root, files->name);
+		if (!dentry)
+			goto out;
+		inode = new_inode(s);
+		if (!inode)
+			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;
+	return 0;
+out:
+	d_genocide(root);
+	dput(root);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(simple_fill_super);
+
+static int __simple_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct simple_fs_type *type;
+	static struct tree_descr simple_files[] = { { "" } };
+	struct tree_descr *files = simple_files;
+
+	type = container_of(sb->s_type, struct simple_fs_type, fstype);
+	if (type->super_ops)
+		sb->s_op = type->super_ops;
+	if (type->files)
+		files = type->files;
+
+	return simple_fill_super(sb, type->magic, files);
+}
+
+static int simple_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, __simple_fill_super, mnt);
+}
+
+struct dentry *simple_register_filesystem(struct simple_fs_type *type)
+{
+	int retval;
+
+	type->fstype.get_sb = simple_get_sb;
+	type->fstype.kill_sb = kill_litter_super,
+
+	retval = register_filesystem(&type->fstype);
+	if (retval)
+		goto out;
+
+	retval = simple_pin_fs(&type->fstype, &type->mount,
+			       &type->mount_count);
+	if (retval)
+		goto unregister;
+	return type->mount->mnt_root;
+
+unregister:
+	unregister_filesystem(&type->fstype);
+out:
+	return ERR_PTR(retval);
+}
+EXPORT_SYMBOL_GPL(simple_register_filesystem);
+
+void simple_unregister_filesystem(struct simple_fs_type *type)
+{
+	simple_release_fs(&type->mount, &type->mount_count);
+	unregister_filesystem(&type->fstype);
+}
+EXPORT_SYMBOL_GPL(simple_unregister_filesystem);
Index: linux-2.6/fs/libfs/inode.c
===================================================================
--- /dev/null
+++ linux-2.6/fs/libfs/inode.c
@@ -0,0 +1,420 @@
+/*
+ *	fs/libfs/inode.c
+ *	Library for filesystems writers -- inode operations
+ */
+
+#include <linux/libfs.h>
+#include <linux/fsnotify.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/mount.h>
+#include <linux/vfs.h>
+#include <linux/mutex.h>
+#include <linux/exportfs.h>
+
+#include <asm/uaccess.h>
+
+static inline struct simple_fs_type *to_simple_fs(struct dentry *dentry)
+{
+	return container_of(dentry->d_sb->s_type,
+				struct simple_fs_type, fstype);
+}
+
+static ssize_t simple_read_file(struct file *file, char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t simple_write_file(struct file *file, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+int simple_open(struct inode *inode, struct file *file)
+{
+	if (inode->i_private)
+		file->private_data = inode->i_private;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(simple_open);
+
+const struct file_operations simple_file_operations = {
+	.read =		simple_read_file,
+	.write =	simple_write_file,
+	.open =		simple_open,
+};
+
+static void *simple_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	nd_set_link(nd, dentry->d_inode->i_private);
+	return NULL;
+}
+
+const struct inode_operations simple_link_operations = {
+	.readlink       = generic_readlink,
+	.follow_link    = simple_follow_link,
+};
+
+static struct inode *simple_get_inode(struct super_block *sb, int mode, dev_t dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = 0;
+		inode->i_gid = 0;
+		inode->i_blocks = 0;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+		case S_IFREG:
+			inode->i_fop = &simple_file_operations;
+			break;
+		case S_IFLNK:
+			inode->i_op = &simple_link_operations;
+			break;
+		case S_IFDIR:
+			inode->i_op = &simple_dir_inode_operations;
+			inode->i_fop = &simple_dir_operations;
+
+			/* directory inodes start off with i_nlink == 2
+			 * (for "." entry) */
+			inc_nlink(inode);
+			break;
+		}
+	}
+	return inode;
+}
+
+/* SMP-safe */
+static int simple_mknod(struct inode *dir, struct dentry *dentry,
+			 int mode, dev_t dev)
+{
+	struct inode *inode;
+	int error = -EPERM;
+
+	if (dentry->d_inode)
+		return -EEXIST;
+
+	inode = simple_get_inode(dir->i_sb, mode, dev);
+	if (inode) {
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+static int simple_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int res;
+
+	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
+	res = simple_mknod(dir, dentry, mode, 0);
+	if (!res) {
+		inc_nlink(dir);
+		fsnotify_mkdir(dir, dentry);
+	}
+	return res;
+}
+
+static int simple_symlink(struct inode *dir, struct dentry *dentry, int mode)
+{
+	mode = (mode & S_IALLUGO) | S_IFLNK;
+	return simple_mknod(dir, dentry, mode, 0);
+}
+
+static int simple_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int res;
+
+	mode = (mode & S_IALLUGO) | S_IFREG;
+	res = simple_mknod(dir, dentry, mode, 0);
+	if (!res)
+		fsnotify_create(dir, dentry);
+	return res;
+}
+
+static int simple_create_by_name(const char *name, mode_t mode,
+				  struct dentry *parent,
+				  struct dentry **dentry)
+{
+	int error = 0;
+
+	*dentry = NULL;
+	mutex_lock(&parent->d_inode->i_mutex);
+	*dentry = lookup_one_len(name, parent, strlen(name));
+	if (!IS_ERR(*dentry)) {
+		switch (mode & S_IFMT) {
+		case S_IFDIR:
+			error = simple_mkdir(parent->d_inode, *dentry, mode);
+			break;
+		case S_IFLNK:
+			error = simple_symlink(parent->d_inode, *dentry, mode);
+			break;
+		default:
+			error = simple_create(parent->d_inode, *dentry, mode);
+			break;
+		}
+		dput(*dentry);
+	} else
+		error = PTR_ERR(*dentry);
+	mutex_unlock(&parent->d_inode->i_mutex);
+
+	return error;
+}
+
+/**
+ * simple_create_file - create a file in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this paramater is NULL, then the
+ *          file will be created in the root of the debugfs filesystem.
+ * @data: a pointer to something that the caller will want to get to later
+ *        on.  The inode.i_private pointer will point to this value on
+ *        the open() call.
+ * @fops: a pointer to a struct file_operations that should be used for
+ *        this file.
+ *
+ * This is the basic "create a file" function for debugfs.  It allows for a
+ * wide range of flexibility in createing a file, or a directory (if you
+ * want to create a directory, the debugfs_create_dir() function is
+ * recommended to be used instead.)
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the simple_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, %NULL will be returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *simple_create_file(const char *name, mode_t mode,
+				   struct dentry *parent, void *data,
+				   const struct file_operations *fops)
+{
+	struct dentry *dentry = NULL;
+	struct simple_fs_type *type;
+	int error;
+
+	pr_debug("debugfs: creating file '%s'\n", name);
+
+	if (!parent) {
+		pr_debug("debugfs: Ah! can not find a parent!\n");
+		goto exit;
+	}
+
+	type = to_simple_fs(parent);
+	error = simple_pin_fs(&type->fstype, &type->mount,
+			      &type->mount_count);
+	if (error)
+		goto exit;
+
+	error = simple_create_by_name(name, mode, parent, &dentry);
+	if (error) {
+		struct simple_fs_type *type = to_simple_fs(parent);
+		dentry = NULL;
+		simple_release_fs(&type->mount, &type->mount_count);
+		goto exit;
+	}
+
+	if (dentry->d_inode) {
+		if (data)
+			dentry->d_inode->i_private = data;
+		if (fops)
+			dentry->d_inode->i_fop = fops;
+	}
+exit:
+	return dentry;
+}
+EXPORT_SYMBOL_GPL(simple_create_file);
+
+/**
+ * simple_create_dir - create a directory in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the directory to
+ *        create.
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory will be created in the root of the debugfs filesystem.
+ *
+ * This function creates a directory in debugfs with the given name.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the debugfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, %NULL will be returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *simple_create_dir(const char *name, struct dentry *parent)
+{
+	return simple_create_file(name,
+				   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+				   parent, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(simple_create_dir);
+
+/**
+ * simple_create_symlink- create a symbolic link in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the symbolic link to
+ *        create.
+ * @parent: a pointer to the parent dentry for this symbolic link.  This
+ *          should be a directory dentry if set.  If this paramater is NULL,
+ *          then the symbolic link will be created in the root of the debugfs
+ *          filesystem.
+ * @target: a pointer to a string containing the path to the target of the
+ *          symbolic link.
+ *
+ * This function creates a symbolic link with the given name in debugfs that
+ * links to the given target path.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the debugfs_remove() function when the symbolic
+ * link is to be removed (no automatic cleanup happens if your module is
+ * unloaded, you are responsible here.)  If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *simple_create_symlink(const char *name, struct dentry *parent,
+				      const char *target)
+{
+	struct dentry *result;
+	char *link;
+
+	link = kstrdup(target, GFP_KERNEL);
+	if (!link)
+		return NULL;
+
+	result = simple_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
+				     NULL);
+	if (!result)
+		kfree(link);
+	return result;
+}
+EXPORT_SYMBOL_GPL(simple_create_symlink);
+
+/**
+ * simple_remove - removes a file or directory from the debugfs filesystem
+ * @dentry: a pointer to a the dentry of the file or directory to be
+ *          removed.
+ *
+ * This function removes a file or directory in debugfs that was previously
+ * created with a call to another debugfs function (like
+ * debugfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void simple_remove(struct dentry *dentry)
+{
+	struct dentry *parent;
+	int ret = 0;
+	struct simple_fs_type *type = to_simple_fs(dentry);
+
+	if (!dentry)
+		return;
+
+	parent = dentry->d_parent;
+	if (!parent || !parent->d_inode)
+		return;
+
+	mutex_lock(&parent->d_inode->i_mutex);
+	if (simple_positive(dentry)) {
+		if (dentry->d_inode) {
+			dget(dentry);
+			switch (dentry->d_inode->i_mode & S_IFMT) {
+			case S_IFDIR:
+				ret = simple_rmdir(parent->d_inode, dentry);
+				break;
+			case S_IFLNK:
+				kfree(dentry->d_inode->i_private);
+				/* fall through */
+			default:
+				simple_unlink(parent->d_inode, dentry);
+				break;
+			}
+			if (!ret)
+				d_delete(dentry);
+			dput(dentry);
+		}
+	}
+	mutex_unlock(&parent->d_inode->i_mutex);
+	simple_release_fs(&type->mount, &type->mount_count);
+}
+EXPORT_SYMBOL_GPL(simple_remove);
+
+/**
+ * simple_rename - rename a file/directory in the debugfs filesystem
+ * @old_dir: a pointer to the parent dentry for the renamed object. This
+ *          should be a directory dentry.
+ * @old_dentry: dentry of an object to be renamed.
+ * @new_dir: a pointer to the parent dentry where the object should be
+ *          moved. This should be a directory dentry.
+ * @new_name: a pointer to a string containing the target name.
+ *
+ * This function renames a file/directory in debugfs.  The target must not
+ * exist for rename to succeed.
+ *
+ * This function will return a pointer to old_dentry (which is updated to
+ * reflect renaming) if it succeeds. If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *simple_rename_named(struct dentry *old_dir,
+		struct dentry *old_dentry, struct dentry *new_dir,
+		const char *new_name)
+{
+	int error;
+	struct dentry *dentry = NULL, *trap;
+	const char *old_name;
+
+	trap = lock_rename(new_dir, old_dir);
+	/* Source or destination directories don't exist? */
+	if (!old_dir->d_inode || !new_dir->d_inode)
+		goto exit;
+	/* Source does not exist, cyclic rename, or mountpoint? */
+	if (!old_dentry->d_inode || old_dentry == trap ||
+	    d_mountpoint(old_dentry))
+		goto exit;
+	dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
+	/* Lookup failed, cyclic rename or target exists? */
+	if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
+		goto exit;
+
+	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+
+	error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
+		dentry);
+	if (error) {
+		fsnotify_oldname_free(old_name);
+		goto exit;
+	}
+	d_move(old_dentry, dentry);
+	fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
+		old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
+		NULL, old_dentry);
+	fsnotify_oldname_free(old_name);
+	unlock_rename(new_dir, old_dir);
+	dput(dentry);
+	return old_dentry;
+exit:
+	if (dentry && !IS_ERR(dentry))
+		dput(dentry);
+	unlock_rename(new_dir, old_dir);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(simple_rename_named);
+
+
Index: linux-2.6/include/linux/libfs.h
===================================================================
--- linux-2.6.orig/include/linux/libfs.h
+++ linux-2.6/include/linux/libfs.h
@@ -3,6 +3,29 @@
 
 #include <linux/fs.h>
 
+/* simple_fs interface */
+struct simple_fs_type {
+	struct file_system_type fstype;
+	struct tree_descr *files;
+	unsigned long magic;
+	struct vfsmount *mount;
+	int mount_count;
+	struct super_operations *super_ops;
+};
+
+#define DEFINE_SIMPLE_FS(_type, _name, _files, _magic)	\
+struct simple_fs_type _type = {		\
+	.fstype = {			\
+		.owner = THIS_MODULE,	\
+		.name  = (_name),	\
+	},				\
+	.files = (_files),		\
+	.magic = (_magic),		\
+};
+
+extern struct dentry *simple_register_filesystem(struct simple_fs_type *type);
+extern void simple_unregister_filesystem(struct simple_fs_type *type);
+
 extern const struct file_operations simple_fops_u8;
 extern const struct file_operations simple_fops_x8;
 extern const struct file_operations simple_fops_u16;
@@ -18,4 +41,26 @@ struct simple_blob_wrapper {
 	unsigned long size;
 };
 
+/* high-level dentry management */
+struct dentry *simple_create_file(const char *name, mode_t mode,
+				  struct dentry *parent, void *data,
+				  const struct file_operations *fops);
+struct dentry *simple_create_dir(const char *name,
+				 struct dentry *parent);
+struct dentry *simple_create_symlink(const char *name, struct dentry *parent,
+				     const char *target);
+void simple_remove(struct dentry *dentry);
+struct dentry *simple_rename_named(struct dentry *old_dir,
+				   struct dentry *old_dentry,
+				   struct dentry *new_dir,
+				   const char *new_name);
+
+int simple_open(struct inode *, struct file *);
+
+static inline int simple_positive(struct dentry *dentry)
+{
+	return dentry->d_inode && !d_unhashed(dentry);
+}
+
+
 #endif /* __LIBFS_H__ */
Index: linux-2.6/fs/autofs4/autofs_i.h
===================================================================
--- linux-2.6.orig/fs/autofs4/autofs_i.h
+++ linux-2.6/fs/autofs4/autofs_i.h
@@ -214,11 +214,6 @@ static inline u64 autofs4_get_ino(struct
 	return sbi->sb->s_root->d_inode->i_ino;
 }
 
-static inline int simple_positive(struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
 static inline int __simple_empty(struct dentry *dentry)
 {
 	struct dentry *child;
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1959,7 +1959,7 @@ extern const struct file_operations simp
 extern const 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 *, int, const struct tree_descr *);
 extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
 extern void simple_release_fs(struct vfsmount **mount, int *count);
 
Index: linux-2.6/fs/libfs/Makefile
===================================================================
--- linux-2.6.orig/fs/libfs/Makefile
+++ linux-2.6/fs/libfs/Makefile
@@ -1,3 +1,3 @@
 libfs-y += file.o
 
-obj-$(CONFIG_LIBFS) += libfs.o
+obj-$(CONFIG_LIBFS) += libfs.o inode.o super.o

-- 


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

* [RFC 03/11] slim down debugfs
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
  2008-02-19  4:04 ` [RFC 01/11] add generic versions of debugfs file operations Arnd Bergmann
  2008-02-19  4:04 ` [RFC 02/11] introduce simple_fs_type Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-23 12:37   ` Al Viro
  2008-02-19  4:04 ` [RFC 04/11] slim down securityfs Arnd Bergmann
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: slim-down-debugfs.diff --]
[-- Type: text/plain, Size: 20050 bytes --]

With most of debugfs now copied to generic code in libfs,
we can remove the original copy and replace it with thin
wrappers around libfs.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Index: linux-2.6/fs/Kconfig
===================================================================
--- linux-2.6.orig/fs/Kconfig
+++ linux-2.6/fs/Kconfig
@@ -1001,6 +1001,14 @@ config CONFIGFS_FS
 	  Both sysfs and configfs can and should exist together on the
 	  same system. One is not a replacement for the other.
 
+config LIBFS
+	tristate
+	default m
+	help
+	  libfs is a helper library used by many of the simpler file
+	  systems. Parts of libfs can be modular when all of its users
+	  are modules as well, and the users should select this symbol.
+
 endmenu
 
 menu "Miscellaneous filesystems"
Index: linux-2.6/fs/debugfs/file.c
===================================================================
--- linux-2.6.orig/fs/debugfs/file.c
+++ linux-2.6/fs/debugfs/file.c
@@ -19,55 +19,6 @@
 #include <linux/namei.h>
 #include <linux/debugfs.h>
 
-static ssize_t default_read_file(struct file *file, char __user *buf,
-				 size_t count, loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t default_write_file(struct file *file, const char __user *buf,
-				   size_t count, loff_t *ppos)
-{
-	return count;
-}
-
-static int default_open(struct inode *inode, struct file *file)
-{
-	if (inode->i_private)
-		file->private_data = inode->i_private;
-
-	return 0;
-}
-
-const struct file_operations debugfs_file_operations = {
-	.read =		default_read_file,
-	.write =	default_write_file,
-	.open =		default_open,
-};
-
-static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	nd_set_link(nd, dentry->d_inode->i_private);
-	return NULL;
-}
-
-const struct inode_operations debugfs_link_operations = {
-	.readlink       = generic_readlink,
-	.follow_link    = debugfs_follow_link,
-};
-
-static int debugfs_u8_set(void *data, u64 val)
-{
-	*(u8 *)data = val;
-	return 0;
-}
-static int debugfs_u8_get(void *data, u64 *val)
-{
-	*val = *(u8 *)data;
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
-
 /**
  * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value
  * @name: a pointer to a string containing the name of the file to create.
@@ -95,22 +46,10 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs
 struct dentry *debugfs_create_u8(const char *name, mode_t mode,
 				 struct dentry *parent, u8 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_u8);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_u8);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u8);
 
-static int debugfs_u16_set(void *data, u64 val)
-{
-	*(u16 *)data = val;
-	return 0;
-}
-static int debugfs_u16_get(void *data, u64 *val)
-{
-	*val = *(u16 *)data;
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
-
 /**
  * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value
  * @name: a pointer to a string containing the name of the file to create.
@@ -138,22 +77,10 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugf
 struct dentry *debugfs_create_u16(const char *name, mode_t mode,
 				  struct dentry *parent, u16 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_u16);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_u16);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u16);
 
-static int debugfs_u32_set(void *data, u64 val)
-{
-	*(u32 *)data = val;
-	return 0;
-}
-static int debugfs_u32_get(void *data, u64 *val)
-{
-	*val = *(u32 *)data;
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
-
 /**
  * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value
  * @name: a pointer to a string containing the name of the file to create.
@@ -181,23 +108,10 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugf
 struct dentry *debugfs_create_u32(const char *name, mode_t mode,
 				 struct dentry *parent, u32 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_u32);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_u32);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u32);
 
-static int debugfs_u64_set(void *data, u64 val)
-{
-	*(u64 *)data = val;
-	return 0;
-}
-
-static int debugfs_u64_get(void *data, u64 *val)
-{
-	*val = *(u64 *)data;
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n");
-
 /**
  * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value
  * @name: a pointer to a string containing the name of the file to create.
@@ -225,16 +139,10 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugf
 struct dentry *debugfs_create_u64(const char *name, mode_t mode,
 				 struct dentry *parent, u64 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_u64);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_u64);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u64);
 
-DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n");
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n");
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n");
-
 /*
  * debugfs_create_x{8,16,32} - create a debugfs file that is used to read and write an unsigned {8,16,32}-bit value
  *
@@ -256,7 +164,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugf
 struct dentry *debugfs_create_x8(const char *name, mode_t mode,
 				 struct dentry *parent, u8 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_x8);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_x8);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_x8);
 
@@ -273,7 +181,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x8);
 struct dentry *debugfs_create_x16(const char *name, mode_t mode,
 				 struct dentry *parent, u16 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_x16);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_x16);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_x16);
 
@@ -290,58 +198,10 @@ EXPORT_SYMBOL_GPL(debugfs_create_x16);
 struct dentry *debugfs_create_x32(const char *name, mode_t mode,
 				 struct dentry *parent, u32 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_x32);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_x32);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_x32);
 
-static ssize_t read_file_bool(struct file *file, char __user *user_buf,
-			      size_t count, loff_t *ppos)
-{
-	char buf[3];
-	u32 *val = file->private_data;
-	
-	if (*val)
-		buf[0] = 'Y';
-	else
-		buf[0] = 'N';
-	buf[1] = '\n';
-	buf[2] = 0x00;
-	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
-}
-
-static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
-			       size_t count, loff_t *ppos)
-{
-	char buf[32];
-	int buf_size;
-	u32 *val = file->private_data;
-
-	buf_size = min(count, (sizeof(buf)-1));
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-
-	switch (buf[0]) {
-	case 'y':
-	case 'Y':
-	case '1':
-		*val = 1;
-		break;
-	case 'n':
-	case 'N':
-	case '0':
-		*val = 0;
-		break;
-	}
-	
-	return count;
-}
-
-static const struct file_operations fops_bool = {
-	.read =		read_file_bool,
-	.write =	write_file_bool,
-	.open =		default_open,
-};
-
 /**
  * debugfs_create_bool - create a debugfs file that is used to read and write a boolean value
  * @name: a pointer to a string containing the name of the file to create.
@@ -369,23 +229,10 @@ static const struct file_operations fops
 struct dentry *debugfs_create_bool(const char *name, mode_t mode,
 				   struct dentry *parent, u32 *value)
 {
-	return debugfs_create_file(name, mode, parent, value, &fops_bool);
+	return debugfs_create_file(name, mode, parent, value, &simple_fops_bool);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_bool);
 
-static ssize_t read_file_blob(struct file *file, char __user *user_buf,
-			      size_t count, loff_t *ppos)
-{
-	struct debugfs_blob_wrapper *blob = file->private_data;
-	return simple_read_from_buffer(user_buf, count, ppos, blob->data,
-			blob->size);
-}
-
-static const struct file_operations fops_blob = {
-	.read =		read_file_blob,
-	.open =		default_open,
-};
-
 /**
  * debugfs_create_blob - create a debugfs file that is used to read and write a binary blob
  * @name: a pointer to a string containing the name of the file to create.
@@ -412,8 +259,8 @@ static const struct file_operations fops
  */
 struct dentry *debugfs_create_blob(const char *name, mode_t mode,
 				   struct dentry *parent,
-				   struct debugfs_blob_wrapper *blob)
+				   struct simple_blob_wrapper *blob)
 {
-	return debugfs_create_file(name, mode, parent, blob, &fops_blob);
+	return debugfs_create_file(name, mode, parent, blob, &simple_fops_blob);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_blob);
Index: linux-2.6/fs/debugfs/inode.c
===================================================================
--- linux-2.6.orig/fs/debugfs/inode.c
+++ linux-2.6/fs/debugfs/inode.c
@@ -29,164 +29,7 @@
 
 #define DEBUGFS_MAGIC	0x64626720
 
-/* declared over in file.c */
-extern struct file_operations debugfs_file_operations;
-extern struct inode_operations debugfs_link_operations;
-
-static struct vfsmount *debugfs_mount;
-static int debugfs_mount_count;
-
-static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
-{
-	struct inode *inode = new_inode(sb);
-
-	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = 0;
-		inode->i_gid = 0;
-		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		switch (mode & S_IFMT) {
-		default:
-			init_special_inode(inode, mode, dev);
-			break;
-		case S_IFREG:
-			inode->i_fop = &debugfs_file_operations;
-			break;
-		case S_IFLNK:
-			inode->i_op = &debugfs_link_operations;
-			break;
-		case S_IFDIR:
-			inode->i_op = &simple_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
-
-			/* directory inodes start off with i_nlink == 2
-			 * (for "." entry) */
-			inc_nlink(inode);
-			break;
-		}
-	}
-	return inode; 
-}
-
-/* SMP-safe */
-static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
-			 int mode, dev_t dev)
-{
-	struct inode *inode;
-	int error = -EPERM;
-
-	if (dentry->d_inode)
-		return -EEXIST;
-
-	inode = debugfs_get_inode(dir->i_sb, mode, dev);
-	if (inode) {
-		d_instantiate(dentry, inode);
-		dget(dentry);
-		error = 0;
-	}
-	return error;
-}
-
-static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	int res;
-
-	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
-	res = debugfs_mknod(dir, dentry, mode, 0);
-	if (!res) {
-		inc_nlink(dir);
-		fsnotify_mkdir(dir, dentry);
-	}
-	return res;
-}
-
-static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
-{
-	mode = (mode & S_IALLUGO) | S_IFLNK;
-	return debugfs_mknod(dir, dentry, mode, 0);
-}
-
-static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
-{
-	int res;
-
-	mode = (mode & S_IALLUGO) | S_IFREG;
-	res = debugfs_mknod(dir, dentry, mode, 0);
-	if (!res)
-		fsnotify_create(dir, dentry);
-	return res;
-}
-
-static inline int debugfs_positive(struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
-static int debug_fill_super(struct super_block *sb, void *data, int silent)
-{
-	static struct tree_descr debug_files[] = {{""}};
-
-	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
-}
-
-static int debug_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, debug_fill_super, mnt);
-}
-
-static struct file_system_type debug_fs_type = {
-	.owner =	THIS_MODULE,
-	.name =		"debugfs",
-	.get_sb =	debug_get_sb,
-	.kill_sb =	kill_litter_super,
-};
-
-static int debugfs_create_by_name(const char *name, mode_t mode,
-				  struct dentry *parent,
-				  struct dentry **dentry)
-{
-	int error = 0;
-
-	/* If the parent is not specified, we create it in the root.
-	 * We need the root dentry to do this, which is in the super 
-	 * block. A pointer to that is in the struct vfsmount that we
-	 * have around.
-	 */
-	if (!parent) {
-		if (debugfs_mount && debugfs_mount->mnt_sb) {
-			parent = debugfs_mount->mnt_sb->s_root;
-		}
-	}
-	if (!parent) {
-		pr_debug("debugfs: Ah! can not find a parent!\n");
-		return -EFAULT;
-	}
-
-	*dentry = NULL;
-	mutex_lock(&parent->d_inode->i_mutex);
-	*dentry = lookup_one_len(name, parent, strlen(name));
-	if (!IS_ERR(*dentry)) {
-		switch (mode & S_IFMT) {
-		case S_IFDIR:
-			error = debugfs_mkdir(parent->d_inode, *dentry, mode);
-			break;
-		case S_IFLNK:
-			error = debugfs_link(parent->d_inode, *dentry, mode);
-			break;
-		default:
-			error = debugfs_create(parent->d_inode, *dentry, mode);
-			break;
-		}
-		dput(*dentry);
-	} else
-		error = PTR_ERR(*dentry);
-	mutex_unlock(&parent->d_inode->i_mutex);
-
-	return error;
-}
+static struct dentry *debugfs_root;
 
 /**
  * debugfs_create_file - create a file in the debugfs filesystem
@@ -219,28 +62,20 @@ struct dentry *debugfs_create_file(const
 				   const struct file_operations *fops)
 {
 	struct dentry *dentry = NULL;
-	int error;
 
 	pr_debug("debugfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
-			      &debugfs_mount_count);
-	if (error)
-		goto exit;
+	/* If the parent is not specified, we create it in the root.
+	 * of the standard debugfs */
+	if (!parent)
+		parent = debugfs_root;
 
-	error = debugfs_create_by_name(name, mode, parent, &dentry);
-	if (error) {
-		dentry = NULL;
-		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+	if (!parent) {
+		pr_debug("debugfs: Ah! can not find a parent!\n");
 		goto exit;
 	}
 
-	if (dentry->d_inode) {
-		if (data)
-			dentry->d_inode->i_private = data;
-		if (fops)
-			dentry->d_inode->i_fop = fops;
-	}
+	dentry = simple_create_file(name, mode, parent, data, fops);
 exit:
 	return dentry;
 }
@@ -266,7 +101,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
  */
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 {
-	return debugfs_create_file(name, 
+	return debugfs_create_file(name,
 				   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
 				   parent, NULL, NULL);
 }
@@ -328,38 +163,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_symlink
  */
 void debugfs_remove(struct dentry *dentry)
 {
-	struct dentry *parent;
-	int ret = 0;
-	
-	if (!dentry)
-		return;
-
-	parent = dentry->d_parent;
-	if (!parent || !parent->d_inode)
-		return;
-
-	mutex_lock(&parent->d_inode->i_mutex);
-	if (debugfs_positive(dentry)) {
-		if (dentry->d_inode) {
-			dget(dentry);
-			switch (dentry->d_inode->i_mode & S_IFMT) {
-			case S_IFDIR:
-				ret = simple_rmdir(parent->d_inode, dentry);
-				break;
-			case S_IFLNK:
-				kfree(dentry->d_inode->i_private);
-				/* fall through */
-			default:
-				simple_unlink(parent->d_inode, dentry);
-				break;
-			}
-			if (!ret)
-				d_delete(dentry);
-			dput(dentry);
-		}
-	}
-	mutex_unlock(&parent->d_inode->i_mutex);
-	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+	return simple_remove(dentry);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
@@ -385,48 +189,12 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
 struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
 		struct dentry *new_dir, const char *new_name)
 {
-	int error;
-	struct dentry *dentry = NULL, *trap;
-	const char *old_name;
-
-	trap = lock_rename(new_dir, old_dir);
-	/* Source or destination directories don't exist? */
-	if (!old_dir->d_inode || !new_dir->d_inode)
-		goto exit;
-	/* Source does not exist, cyclic rename, or mountpoint? */
-	if (!old_dentry->d_inode || old_dentry == trap ||
-	    d_mountpoint(old_dentry))
-		goto exit;
-	dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
-	/* Lookup failed, cyclic rename or target exists? */
-	if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
-		goto exit;
-
-	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
-
-	error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
-		dentry);
-	if (error) {
-		fsnotify_oldname_free(old_name);
-		goto exit;
-	}
-	d_move(old_dentry, dentry);
-	fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
-		old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
-		NULL, old_dentry);
-	fsnotify_oldname_free(old_name);
-	unlock_rename(new_dir, old_dir);
-	dput(dentry);
-	return old_dentry;
-exit:
-	if (dentry && !IS_ERR(dentry))
-		dput(dentry);
-	unlock_rename(new_dir, old_dir);
-	return NULL;
+	return simple_rename_named(old_dir, old_dentry, new_dir, new_name);
 }
 EXPORT_SYMBOL_GPL(debugfs_rename);
 
 static struct kobject *debug_kobj;
+static DEFINE_SIMPLE_FS(debug_fs_type, "debugfs", NULL, DEBUGFS_MAGIC);
 
 static int __init debugfs_init(void)
 {
@@ -436,16 +204,18 @@ static int __init debugfs_init(void)
 	if (!debug_kobj)
 		return -EINVAL;
 
-	retval = register_filesystem(&debug_fs_type);
-	if (retval)
+	retval = 0;
+	debugfs_root = simple_register_filesystem(&debug_fs_type);
+	if (IS_ERR(debugfs_root)) {
 		kobject_put(debug_kobj);
+		retval = PTR_ERR(debugfs_root);
+	}
 	return retval;
 }
 
 static void __exit debugfs_exit(void)
 {
-	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-	unregister_filesystem(&debug_fs_type);
+	simple_unregister_filesystem(&debug_fs_type);
 	kobject_put(debug_kobj);
 }
 
Index: linux-2.6/include/linux/debugfs.h
===================================================================
--- linux-2.6.orig/include/linux/debugfs.h
+++ linux-2.6/include/linux/debugfs.h
@@ -15,18 +15,14 @@
 #ifndef _DEBUGFS_H_
 #define _DEBUGFS_H_
 
+#include <linux/libfs.h>
 #include <linux/fs.h>
 
 #include <linux/types.h>
 
 struct file_operations;
 
-struct debugfs_blob_wrapper {
-	void *data;
-	unsigned long size;
-};
-
-#if defined(CONFIG_DEBUG_FS)
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEBUG_FS_MODULE)
 struct dentry *debugfs_create_file(const char *name, mode_t mode,
 				   struct dentry *parent, void *data,
 				   const struct file_operations *fops);
@@ -60,7 +56,7 @@ struct dentry *debugfs_create_bool(const
 
 struct dentry *debugfs_create_blob(const char *name, mode_t mode,
 				  struct dentry *parent,
-				  struct debugfs_blob_wrapper *blob);
+				  struct simple_blob_wrapper *blob);
 #else
 
 #include <linux/err.h>
@@ -158,7 +154,7 @@ static inline struct dentry *debugfs_cre
 
 static inline struct dentry *debugfs_create_blob(const char *name, mode_t mode,
 				  struct dentry *parent,
-				  struct debugfs_blob_wrapper *blob)
+				  struct simple_blob_wrapper *blob)
 {
 	return ERR_PTR(-ENODEV);
 }
Index: linux-2.6/drivers/net/wireless/rt2x00/rt2x00debug.c
===================================================================
--- linux-2.6.orig/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ linux-2.6/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -100,8 +100,8 @@ struct rt2x00debug_intf {
 	 * that has been created in advance. This will simplify
 	 * the code since we can use the debugfs functions.
 	 */
-	struct debugfs_blob_wrapper driver_blob;
-	struct debugfs_blob_wrapper chipset_blob;
+	struct simple_blob_wrapper driver_blob;
+	struct simple_blob_wrapper chipset_blob;
 
 	/*
 	 * Requested offset for each register type.
@@ -381,7 +381,7 @@ static const struct file_operations rt2x
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 						     struct rt2x00debug_intf
 						     *intf,
-						     struct debugfs_blob_wrapper
+						     struct simple_blob_wrapper
 						     *blob)
 {
 	char *data;
@@ -403,7 +403,7 @@ static struct dentry *rt2x00debug_create
 						      struct rt2x00debug_intf
 						      *intf,
 						      struct
-						      debugfs_blob_wrapper
+						      simple_blob_wrapper
 						      *blob)
 {
 	const struct rt2x00debug *debug = intf->debug;

-- 


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

* [RFC 04/11] slim down securityfs
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (2 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 03/11] slim down debugfs Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 05/11] slim down usbfs Arnd Bergmann
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: slim-down-securityfs.diff --]
[-- Type: text/plain, Size: 6571 bytes --]

With the new simple_fs_type in place, securityfs practically
becomes a nop and we just need to leave code around to manage
its mount point.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Index: linux-2.6/security/inode.c
===================================================================
--- linux-2.6.orig/security/inode.c
+++ linux-2.6/security/inode.c
@@ -13,176 +13,14 @@
  */
 
 /* #define DEBUG */
+
 #include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
 #include <linux/init.h>
-#include <linux/namei.h>
 #include <linux/security.h>
 
 #define SECURITYFS_MAGIC	0x73636673
 
-static struct vfsmount *mount;
-static int mount_count;
-
-/*
- * TODO:
- *   I think I can get rid of these default_file_ops, but not quite sure...
- */
-static ssize_t default_read_file(struct file *file, char __user *buf,
-				 size_t count, loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t default_write_file(struct file *file, const char __user *buf,
-				   size_t count, loff_t *ppos)
-{
-	return count;
-}
-
-static int default_open(struct inode *inode, struct file *file)
-{
-	if (inode->i_private)
-		file->private_data = inode->i_private;
-
-	return 0;
-}
-
-static const struct file_operations default_file_ops = {
-	.read =		default_read_file,
-	.write =	default_write_file,
-	.open =		default_open,
-};
-
-static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
-{
-	struct inode *inode = new_inode(sb);
-
-	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = 0;
-		inode->i_gid = 0;
-		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		switch (mode & S_IFMT) {
-		default:
-			init_special_inode(inode, mode, dev);
-			break;
-		case S_IFREG:
-			inode->i_fop = &default_file_ops;
-			break;
-		case S_IFDIR:
-			inode->i_op = &simple_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
-
-			/* directory inodes start off with i_nlink == 2 (for "." entry) */
-			inc_nlink(inode);
-			break;
-		}
-	}
-	return inode;
-}
-
-/* SMP-safe */
-static int mknod(struct inode *dir, struct dentry *dentry,
-			 int mode, dev_t dev)
-{
-	struct inode *inode;
-	int error = -EPERM;
-
-	if (dentry->d_inode)
-		return -EEXIST;
-
-	inode = get_inode(dir->i_sb, mode, dev);
-	if (inode) {
-		d_instantiate(dentry, inode);
-		dget(dentry);
-		error = 0;
-	}
-	return error;
-}
-
-static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	int res;
-
-	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
-	res = mknod(dir, dentry, mode, 0);
-	if (!res)
-		inc_nlink(dir);
-	return res;
-}
-
-static int create(struct inode *dir, struct dentry *dentry, int mode)
-{
-	mode = (mode & S_IALLUGO) | S_IFREG;
-	return mknod(dir, dentry, mode, 0);
-}
-
-static inline int positive(struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
-static int fill_super(struct super_block *sb, void *data, int silent)
-{
-	static struct tree_descr files[] = {{""}};
-
-	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
-}
-
-static int 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, fill_super, mnt);
-}
-
-static struct file_system_type fs_type = {
-	.owner =	THIS_MODULE,
-	.name =		"securityfs",
-	.get_sb =	get_sb,
-	.kill_sb =	kill_litter_super,
-};
-
-static int create_by_name(const char *name, mode_t mode,
-			  struct dentry *parent,
-			  struct dentry **dentry)
-{
-	int error = 0;
-
-	*dentry = NULL;
-
-	/* If the parent is not specified, we create it in the root.
-	 * We need the root dentry to do this, which is in the super
-	 * block. A pointer to that is in the struct vfsmount that we
-	 * have around.
-	 */
-	if (!parent ) {
-		if (mount && mount->mnt_sb) {
-			parent = mount->mnt_sb->s_root;
-		}
-	}
-	if (!parent) {
-		pr_debug("securityfs: Ah! can not find a parent!\n");
-		return -EFAULT;
-	}
-
-	mutex_lock(&parent->d_inode->i_mutex);
-	*dentry = lookup_one_len(name, parent, strlen(name));
-	if (!IS_ERR(dentry)) {
-		if ((mode & S_IFMT) == S_IFDIR)
-			error = mkdir(parent->d_inode, *dentry, mode);
-		else
-			error = create(parent->d_inode, *dentry, mode);
-	} else
-		error = PTR_ERR(dentry);
-	mutex_unlock(&parent->d_inode->i_mutex);
-
-	return error;
-}
+static struct dentry *securityfs_root;
 
 /**
  * securityfs_create_file - create a file in the securityfs filesystem
@@ -217,32 +55,12 @@ struct dentry *securityfs_create_file(co
 				   struct dentry *parent, void *data,
 				   const struct file_operations *fops)
 {
-	struct dentry *dentry = NULL;
-	int error;
+	if (!parent)
+		parent = securityfs_root;
 
 	pr_debug("securityfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs(&fs_type, &mount, &mount_count);
-	if (error) {
-		dentry = ERR_PTR(error);
-		goto exit;
-	}
-
-	error = create_by_name(name, mode, parent, &dentry);
-	if (error) {
-		dentry = ERR_PTR(error);
-		simple_release_fs(&mount, &mount_count);
-		goto exit;
-	}
-
-	if (dentry->d_inode) {
-		if (fops)
-			dentry->d_inode->i_fop = fops;
-		if (data)
-			dentry->d_inode->i_private = data;
-	}
-exit:
-	return dentry;
+	return simple_create_file(name, mode, parent, data, fops);
 }
 EXPORT_SYMBOL_GPL(securityfs_create_file);
 
@@ -291,31 +109,12 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir)
  */
 void securityfs_remove(struct dentry *dentry)
 {
-	struct dentry *parent;
-
-	if (!dentry)
-		return;
-
-	parent = dentry->d_parent;
-	if (!parent || !parent->d_inode)
-		return;
-
-	mutex_lock(&parent->d_inode->i_mutex);
-	if (positive(dentry)) {
-		if (dentry->d_inode) {
-			if (S_ISDIR(dentry->d_inode->i_mode))
-				simple_rmdir(parent->d_inode, dentry);
-			else
-				simple_unlink(parent->d_inode, dentry);
-			dput(dentry);
-		}
-	}
-	mutex_unlock(&parent->d_inode->i_mutex);
-	simple_release_fs(&mount, &mount_count);
+	return simple_remove(dentry);
 }
 EXPORT_SYMBOL_GPL(securityfs_remove);
 
 static struct kobject *security_kobj;
+static DEFINE_SIMPLE_FS(fs_type, "securityfs", NULL, SECURITYFS_MAGIC);
 
 static int __init securityfs_init(void)
 {
@@ -325,12 +124,14 @@ static int __init securityfs_init(void)
 	if (!security_kobj)
 		return -EINVAL;
 
-	retval = register_filesystem(&fs_type);
-	if (retval)
+	retval = 0;
+	securityfs_root = simple_register_filesystem(&fs_type);
+	if (IS_ERR(securityfs_root)) {
 		kobject_put(security_kobj);
+		retval = PTR_ERR(securityfs_root);
+	}
 	return retval;
 }
 
 core_initcall(securityfs_init);
 MODULE_LICENSE("GPL");
-

-- 


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

* [RFC 05/11] slim down usbfs
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (3 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 04/11] slim down securityfs Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 06/11] split out linux/libfs.h from linux/fs.h Arnd Bergmann
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: slim-down-usbfs.diff --]
[-- Type: text/plain, Size: 11825 bytes --]

Half of the usbfs code is the same as debugfs, so we can
replace it now with calls to the generic libfs versions.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Index: linux-2.6/drivers/usb/core/inode.c
===================================================================
--- linux-2.6.orig/drivers/usb/core/inode.c
+++ linux-2.6/drivers/usb/core/inode.c
@@ -47,11 +47,10 @@
 #define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO)
 #define USBFS_DEFAULT_LISTMODE S_IRUGO
 
-static struct super_operations usbfs_ops;
-static const struct file_operations default_file_operations;
-static struct vfsmount *usbfs_mount;
-static int usbfs_mount_count;	/* = 0 */
-static int ignore_mount = 0;
+static DEFINE_SIMPLE_FS(usb_fs_type, "usbfs", NULL, USBDEVICE_SUPER_MAGIC);
+static struct dentry *usbfs_root;
+
+static int ignore_mount = 1;
 
 static struct dentry *devices_usbfs_dentry;
 static int num_buses;	/* = 0 */
@@ -263,186 +262,11 @@ static int remount(struct super_block *s
 		return -EINVAL;
 	}
 
-	if (usbfs_mount && usbfs_mount->mnt_sb)
-		update_sb(usbfs_mount->mnt_sb);
-
-	return 0;
-}
-
-static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t dev)
-{
-	struct inode *inode = new_inode(sb);
-
-	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
-		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		switch (mode & S_IFMT) {
-		default:
-			init_special_inode(inode, mode, dev);
-			break;
-		case S_IFREG:
-			inode->i_fop = &default_file_operations;
-			break;
-		case S_IFDIR:
-			inode->i_op = &simple_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
-
-			/* directory inodes start off with i_nlink == 2 (for "." entry) */
-			inc_nlink(inode);
-			break;
-		}
-	}
-	return inode; 
-}
-
-/* SMP-safe */
-static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
-			dev_t dev)
-{
-	struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev);
-	int error = -EPERM;
-
-	if (dentry->d_inode)
-		return -EEXIST;
-
-	if (inode) {
-		d_instantiate(dentry, inode);
-		dget(dentry);
-		error = 0;
-	}
-	return error;
-}
-
-static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
-{
-	int res;
-
-	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
-	res = usbfs_mknod (dir, dentry, mode, 0);
-	if (!res)
-		inc_nlink(dir);
-	return res;
-}
-
-static int usbfs_create (struct inode *dir, struct dentry *dentry, int mode)
-{
-	mode = (mode & S_IALLUGO) | S_IFREG;
-	return usbfs_mknod (dir, dentry, mode, 0);
-}
-
-static inline int usbfs_positive (struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
-static int usbfs_empty (struct dentry *dentry)
-{
-	struct list_head *list;
-
-	spin_lock(&dcache_lock);
-
-	list_for_each(list, &dentry->d_subdirs) {
-		struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
-		if (usbfs_positive(de)) {
-			spin_unlock(&dcache_lock);
-			return 0;
-		}
-	}
-
-	spin_unlock(&dcache_lock);
-	return 1;
-}
-
-static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
-{
-	struct inode *inode = dentry->d_inode;
-	mutex_lock(&inode->i_mutex);
-	drop_nlink(dentry->d_inode);
-	dput(dentry);
-	mutex_unlock(&inode->i_mutex);
-	d_delete(dentry);
-	return 0;
-}
-
-static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	int error = -ENOTEMPTY;
-	struct inode * inode = dentry->d_inode;
-
-	mutex_lock(&inode->i_mutex);
-	dentry_unhash(dentry);
-	if (usbfs_empty(dentry)) {
-		drop_nlink(dentry->d_inode);
-		drop_nlink(dentry->d_inode);
-		dput(dentry);
-		inode->i_flags |= S_DEAD;
-		drop_nlink(dir);
-		error = 0;
-	}
-	mutex_unlock(&inode->i_mutex);
-	if (!error)
-		d_delete(dentry);
-	dput(dentry);
-	return error;
-}
-
-
-/* default file operations */
-static ssize_t default_read_file (struct file *file, char __user *buf,
-				  size_t count, loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t default_write_file (struct file *file, const char __user *buf,
-				   size_t count, loff_t *ppos)
-{
-	return count;
-}
-
-static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
-{
-	loff_t retval = -EINVAL;
-
-	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
-	switch(orig) {
-	case 0:
-		if (offset > 0) {
-			file->f_pos = offset;
-			retval = file->f_pos;
-		} 
-		break;
-	case 1:
-		if ((offset + file->f_pos) > 0) {
-			file->f_pos += offset;
-			retval = file->f_pos;
-		} 
-		break;
-	default:
-		break;
-	}
-	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
-	return retval;
-}
-
-static int default_open (struct inode *inode, struct file *file)
-{
-	if (inode->i_private)
-		file->private_data = inode->i_private;
+	update_sb(usb_fs_type.mount->mnt_sb);
 
 	return 0;
 }
 
-static const struct file_operations default_file_operations = {
-	.read =		default_read_file,
-	.write =	default_write_file,
-	.open =		default_open,
-	.llseek =	default_file_lseek,
-};
-
 static struct super_operations usbfs_ops = {
 	.statfs =	simple_statfs,
 	.drop_inode =	generic_delete_inode,
@@ -450,145 +274,32 @@ static struct super_operations usbfs_ops
 	.show_options = usbfs_show_options,
 };
 
-static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
-{
-	struct inode *inode;
-	struct dentry *root;
-
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = USBDEVICE_SUPER_MAGIC;
-	sb->s_op = &usbfs_ops;
-	sb->s_time_gran = 1;
-	inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
-
-	if (!inode) {
-		dbg("%s: could not get inode!",__FUNCTION__);
-		return -ENOMEM;
-	}
-
-	root = d_alloc_root(inode);
-	if (!root) {
-		dbg("%s: could not get root dentry!",__FUNCTION__);
-		iput(inode);
-		return -ENOMEM;
-	}
-	sb->s_root = root;
-	return 0;
-}
-
-/*
- * fs_create_by_name - create a file, given a name
- * @name:	name of file
- * @mode:	type of file
- * @parent:	dentry of directory to create it in
- * @dentry:	resulting dentry of file
- *
- * This function handles both regular files and directories.
- */
-static int fs_create_by_name (const char *name, mode_t mode,
-			      struct dentry *parent, struct dentry **dentry)
-{
-	int error = 0;
-
-	/* If the parent is not specified, we create it in the root.
-	 * We need the root dentry to do this, which is in the super 
-	 * block. A pointer to that is in the struct vfsmount that we
-	 * have around.
-	 */
-	if (!parent ) {
-		if (usbfs_mount && usbfs_mount->mnt_sb) {
-			parent = usbfs_mount->mnt_sb->s_root;
-		}
-	}
-
-	if (!parent) {
-		dbg("Ah! can not find a parent!");
-		return -EFAULT;
-	}
-
-	*dentry = NULL;
-	mutex_lock(&parent->d_inode->i_mutex);
-	*dentry = lookup_one_len(name, parent, strlen(name));
-	if (!IS_ERR(dentry)) {
-		if ((mode & S_IFMT) == S_IFDIR)
-			error = usbfs_mkdir (parent->d_inode, *dentry, mode);
-		else 
-			error = usbfs_create (parent->d_inode, *dentry, mode);
-	} else
-		error = PTR_ERR(dentry);
-	mutex_unlock(&parent->d_inode->i_mutex);
-
-	return error;
-}
-
 static struct dentry *fs_create_file (const char *name, mode_t mode,
 				      struct dentry *parent, void *data,
 				      const struct file_operations *fops,
 				      uid_t uid, gid_t gid)
 {
 	struct dentry *dentry;
-	int error;
 
 	dbg("creating file '%s'",name);
 
-	error = fs_create_by_name (name, mode, parent, &dentry);
-	if (error) {
-		dentry = NULL;
-	} else {
-		if (dentry->d_inode) {
-			if (data)
-				dentry->d_inode->i_private = data;
-			if (fops)
-				dentry->d_inode->i_fop = fops;
-			dentry->d_inode->i_uid = uid;
-			dentry->d_inode->i_gid = gid;
-		}
+	/* If the parent is not specified, we create it in the root.  */
+	if (!parent)
+		parent = usbfs_root;
+
+	dentry = simple_create_file(name, mode, parent, data, fops);
+	if (dentry && dentry->d_inode) {
+		dentry->d_inode->i_uid = uid;
+		dentry->d_inode->i_gid = gid;
 	}
 
 	return dentry;
 }
 
-static void fs_remove_file (struct dentry *dentry)
-{
-	struct dentry *parent = dentry->d_parent;
-	
-	if (!parent || !parent->d_inode)
-		return;
-
-	mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_PARENT);
-	if (usbfs_positive(dentry)) {
-		if (dentry->d_inode) {
-			if (S_ISDIR(dentry->d_inode->i_mode))
-				usbfs_rmdir(parent->d_inode, dentry);
-			else
-				usbfs_unlink(parent->d_inode, dentry);
-		dput(dentry);
-		}
-	}
-	mutex_unlock(&parent->d_inode->i_mutex);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int usb_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, usbfs_fill_super, mnt);
-}
-
-static struct file_system_type usb_fs_type = {
-	.owner =	THIS_MODULE,
-	.name =		"usbfs",
-	.get_sb =	usb_get_sb,
-	.kill_sb =	kill_litter_super,
-};
-
 /* --------------------------------------------------------------------- */
 
 static int create_special_files (void)
 {
-	struct dentry *parent;
 	int retval;
 
 	/* the simple_pin_fs calls will call remount with no options
@@ -596,8 +307,7 @@ static int create_special_files (void)
 	 */
 	ignore_mount = 1;
 
-	/* create the devices special file */
-	retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
+	retval = simple_pin_fs(&usb_fs_type.fstype, &usb_fs_type.mount, &usb_fs_type.mount_count);
 	if (retval) {
 		err ("Unable to get usbfs mount");
 		goto exit;
@@ -605,9 +315,8 @@ static int create_special_files (void)
 
 	ignore_mount = 0;
 
-	parent = usbfs_mount->mnt_sb->s_root;
 	devices_usbfs_dentry = fs_create_file ("devices",
-					       listmode | S_IFREG, parent,
+					       listmode | S_IFREG, usbfs_root,
 					       NULL, &usbfs_devices_fops,
 					       listuid, listgid);
 	if (devices_usbfs_dentry == NULL) {
@@ -617,9 +326,9 @@ static int create_special_files (void)
 	}
 
 	goto exit;
-	
+
 error_clean_mounts:
-	simple_release_fs(&usbfs_mount, &usbfs_mount_count);
+	simple_release_fs(&usb_fs_type.mount, &usb_fs_type.mount_count);
 exit:
 	return retval;
 }
@@ -627,9 +336,8 @@ exit:
 static void remove_special_files (void)
 {
 	if (devices_usbfs_dentry)
-		fs_remove_file (devices_usbfs_dentry);
+		simple_remove(devices_usbfs_dentry);
 	devices_usbfs_dentry = NULL;
-	simple_release_fs(&usbfs_mount, &usbfs_mount_count);
 }
 
 void usbfs_update_special (void)
@@ -659,7 +367,7 @@ static void usbfs_add_bus(struct usb_bus
 
 	sprintf (name, "%03d", bus->busnum);
 
-	parent = usbfs_mount->mnt_sb->s_root;
+	parent = usbfs_root;
 	bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent,
 					    bus, NULL, busuid, busgid);
 	if (bus->usbfs_dentry == NULL) {
@@ -671,7 +379,7 @@ static void usbfs_add_bus(struct usb_bus
 static void usbfs_remove_bus(struct usb_bus *bus)
 {
 	if (bus->usbfs_dentry) {
-		fs_remove_file (bus->usbfs_dentry);
+		simple_remove(bus->usbfs_dentry);
 		bus->usbfs_dentry = NULL;
 	}
 
@@ -716,7 +424,7 @@ static void usbfs_remove_device(struct u
 	struct siginfo sinfo;
 
 	if (dev->usbfs_dentry) {
-		fs_remove_file (dev->usbfs_dentry);
+		simple_remove(dev->usbfs_dentry);
 		dev->usbfs_dentry = NULL;
 	}
 	while (!list_empty(&dev->filelist)) {
@@ -764,11 +472,11 @@ static struct proc_dir_entry *usbdir = N
 
 int __init usbfs_init(void)
 {
-	int retval;
-
-	retval = register_filesystem(&usb_fs_type);
-	if (retval)
-		return retval;
+	usb_fs_type.super_ops = &usbfs_ops;
+	usbfs_root = simple_register_filesystem(&usb_fs_type);
+	if (IS_ERR(usbfs_root))
+		return PTR_ERR(usbfs_root);
+	ignore_mount = 0;
 
 	usb_register_notify(&usbfs_nb);
 
@@ -781,7 +489,7 @@ int __init usbfs_init(void)
 void usbfs_cleanup(void)
 {
 	usb_unregister_notify(&usbfs_nb);
-	unregister_filesystem(&usb_fs_type);
+	simple_unregister_filesystem(&usb_fs_type);
 	if (usbdir)
 		remove_proc_entry("usb", proc_bus);
 }

-- 


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

* [RFC 06/11] split out linux/libfs.h from linux/fs.h
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (4 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 05/11] slim down usbfs Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 07/11] split out libfs/file.c from libfs.c Arnd Bergmann
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-header.diff --]
[-- Type: text/plain, Size: 13278 bytes --]

With libfs turning into a larger subsystem, it makes
sense to have a separate header that is not included
by the low-level vfs code.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Index: linux-2.6/fs/debugfs/inode.c
===================================================================
--- linux-2.6.orig/fs/debugfs/inode.c
+++ linux-2.6/fs/debugfs/inode.c
@@ -18,6 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/libfs.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c
+++ linux-2.6/fs/dcache.c
@@ -947,6 +947,7 @@ struct dentry *d_alloc_name(struct dentr
 	q.hash = full_name_hash(q.name, q.len);
 	return d_alloc(parent, &q);
 }
+EXPORT_SYMBOL(d_alloc_name);
 
 /**
  * d_instantiate - fill in inode information for a dentry
Index: linux-2.6/drivers/usb/core/inode.c
===================================================================
--- linux-2.6.orig/drivers/usb/core/inode.c
+++ linux-2.6/drivers/usb/core/inode.c
@@ -27,6 +27,7 @@
 
 /*****************************************************************************/
 
+#include <linux/libfs.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
Index: linux-2.6/fs/binfmt_misc.c
===================================================================
--- linux-2.6.orig/fs/binfmt_misc.c
+++ linux-2.6/fs/binfmt_misc.c
@@ -16,6 +16,7 @@
  *  2001-02-28 AV: rewritten into something that resembles C. Original didn't.
  */
 
+#include <linux/libfs.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
Index: linux-2.6/fs/configfs/mount.c
===================================================================
--- linux-2.6.orig/fs/configfs/mount.c
+++ linux-2.6/fs/configfs/mount.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/libfs.h>
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
Index: linux-2.6/fs/debugfs/file.c
===================================================================
--- linux-2.6.orig/fs/debugfs/file.c
+++ linux-2.6/fs/debugfs/file.c
@@ -15,6 +15,7 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/libfs.h>
 #include <linux/pagemap.h>
 #include <linux/namei.h>
 #include <linux/debugfs.h>
Index: linux-2.6/fs/fuse/control.c
===================================================================
--- linux-2.6.orig/fs/fuse/control.c
+++ linux-2.6/fs/fuse/control.c
@@ -9,6 +9,7 @@
 #include "fuse_i.h"
 
 #include <linux/init.h>
+#include <linux/libfs.h>
 #include <linux/module.h>
 
 #define FUSE_CTL_SUPER_MAGIC 0x65735543
Index: linux-2.6/fs/nfsd/nfsctl.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfsctl.c
+++ linux-2.6/fs/nfsd/nfsctl.c
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 
+#include <linux/libfs.h>
 #include <linux/linkage.h>
 #include <linux/time.h>
 #include <linux/errno.h>
Index: linux-2.6/net/sunrpc/rpc_pipe.c
===================================================================
--- linux-2.6.orig/net/sunrpc/rpc_pipe.c
+++ linux-2.6/net/sunrpc/rpc_pipe.c
@@ -8,6 +8,7 @@
  * Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no>
  *
  */
+#include <linux/libfs.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/string.h>
Index: linux-2.6/security/inode.c
===================================================================
--- linux-2.6.orig/security/inode.c
+++ linux-2.6/security/inode.c
@@ -16,6 +16,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/libfs.h>
 #include <linux/security.h>
 
 #define SECURITYFS_MAGIC	0x73636673
Index: linux-2.6/security/selinux/selinuxfs.c
===================================================================
--- linux-2.6.orig/security/selinux/selinuxfs.c
+++ linux-2.6/security/selinux/selinuxfs.c
@@ -14,6 +14,7 @@
  *	the Free Software Foundation, version 2.
  */
 
+#include <linux/libfs.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
Index: linux-2.6/virt/kvm/kvm_main.c
===================================================================
--- linux-2.6.orig/virt/kvm/kvm_main.c
+++ linux-2.6/virt/kvm/kvm_main.c
@@ -40,6 +40,7 @@
 #include <linux/kvm_para.h>
 #include <linux/pagemap.h>
 #include <linux/mman.h>
+#include <linux/libfs.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/fs.h>
 #include <linux/cpumask.h>
+#include <linux/libfs.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
Index: linux-2.6/fs/autofs4/autofs_i.h
===================================================================
--- linux-2.6.orig/fs/autofs4/autofs_i.h
+++ linux-2.6/fs/autofs4/autofs_i.h
@@ -22,6 +22,7 @@
 #define AUTOFS_IOC_COUNT     32
 
 #include <linux/kernel.h>
+#include <linux/libfs.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/string.h>
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1957,12 +1957,7 @@ extern struct dentry *simple_lookup(stru
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern const struct file_operations simple_dir_operations;
 extern const 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, const struct tree_descr *);
-extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
-extern void simple_release_fs(struct vfsmount **mount, int *count);
-
 extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);
 
 #ifdef CONFIG_MIGRATION
@@ -1993,92 +1988,6 @@ static inline ino_t parent_ino(struct de
 /* kernel/fork.c */
 extern int unshare_files(void);
 
-/* Transaction based IO helpers */
-
-/*
- * An argresp is stored in an allocated page and holds the
- * size of the argument or response, along with its content
- */
-struct simple_transaction_argresp {
-	ssize_t size;
-	char data[0];
-};
-
-#define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp))
-
-char *simple_transaction_get(struct file *file, const char __user *buf,
-				size_t size);
-ssize_t simple_transaction_read(struct file *file, char __user *buf,
-				size_t size, loff_t *pos);
-int simple_transaction_release(struct inode *inode, struct file *file);
-
-static inline void simple_transaction_set(struct file *file, size_t n)
-{
-	struct simple_transaction_argresp *ar = file->private_data;
-
-	BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
-
-	/*
-	 * The barrier ensures that ar->size will really remain zero until
-	 * ar->data is ready for reading.
-	 */
-	smp_mb();
-	ar->size = n;
-}
-
-/*
- * simple attribute files
- *
- * These attributes behave similar to those in sysfs:
- *
- * Writing to an attribute immediately sets a value, an open file can be
- * written to multiple times.
- *
- * Reading from an attribute creates a buffer from the value that might get
- * read with multiple read calls. When the attribute has been read
- * completely, no further read calls are possible until the file is opened
- * again.
- *
- * All attributes contain a text representation of a numeric value
- * that are accessed with the get() and set() functions.
- */
-#define __DEFINE_SIMPLE_ATTRIBUTE(__static, __fops, __get, __set, __fmt)\
-static int __fops ## _open(struct inode *inode, struct file *file)	\
-{									\
-	__simple_attr_check_format(__fmt, 0ull);			\
-	return simple_attr_open(inode, file, __get, __set, __fmt);	\
-}									\
-__static const struct file_operations __fops = {			\
-	.owner	 = THIS_MODULE,						\
-	.open	 = __fops ## _open,					\
-	.release = simple_attr_release,					\
-	.read	 = simple_attr_read,					\
-	.write	 = simple_attr_write,					\
-}
-
-#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
-	__DEFINE_SIMPLE_ATTRIBUTE(static, __fops, __get, __set, __fmt)
-
-#define DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(__fops, __get, __set, __fmt)	\
-	__DEFINE_SIMPLE_ATTRIBUTE(/**/, __fops, __get, __set, __fmt);	\
-	EXPORT_SYMBOL_GPL(__fops)
-
-static inline void __attribute__((format(printf, 1, 2)))
-__simple_attr_check_format(const char *fmt, ...)
-{
-	/* don't do anything, just let the compiler check the arguments; */
-}
-
-int simple_attr_open(struct inode *inode, struct file *file,
-		     int (*get)(void *, u64 *), int (*set)(void *, u64),
-		     const char *fmt);
-int simple_attr_release(struct inode *inode, struct file *file);
-ssize_t simple_attr_read(struct file *file, char __user *buf,
-			 size_t len, loff_t *ppos);
-ssize_t simple_attr_write(struct file *file, const char __user *buf,
-			  size_t len, loff_t *ppos);
-
-
 #ifdef CONFIG_SECURITY
 static inline char *alloc_secdata(void)
 {
Index: linux-2.6/include/linux/libfs.h
===================================================================
--- linux-2.6.orig/include/linux/libfs.h
+++ linux-2.6/include/linux/libfs.h
@@ -3,6 +3,11 @@
 
 #include <linux/fs.h>
 
+struct tree_descr { char *name; const struct file_operations *ops; int mode; };
+extern int simple_fill_super(struct super_block *, int, const struct tree_descr *);
+extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
+extern void simple_release_fs(struct vfsmount **mount, int *count);
+
 /* simple_fs interface */
 struct simple_fs_type {
 	struct file_system_type fstype;
@@ -26,6 +31,91 @@ struct simple_fs_type _type = {		\
 extern struct dentry *simple_register_filesystem(struct simple_fs_type *type);
 extern void simple_unregister_filesystem(struct simple_fs_type *type);
 
+/* Transaction based IO helpers */
+
+/*
+ * An argresp is stored in an allocated page and holds the
+ * size of the argument or response, along with its content
+ */
+struct simple_transaction_argresp {
+	ssize_t size;
+	char data[0];
+};
+
+#define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp))
+
+char *simple_transaction_get(struct file *file, const char __user *buf,
+				size_t size);
+ssize_t simple_transaction_read(struct file *file, char __user *buf,
+				size_t size, loff_t *pos);
+int simple_transaction_release(struct inode *inode, struct file *file);
+
+static inline void simple_transaction_set(struct file *file, size_t n)
+{
+	struct simple_transaction_argresp *ar = file->private_data;
+
+	BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
+
+	/*
+	 * The barrier ensures that ar->size will really remain zero until
+	 * ar->data is ready for reading.
+	 */
+	smp_mb();
+	ar->size = n;
+}
+
+/*
+ * simple attribute files
+ *
+ * These attributes behave similar to those in sysfs:
+ *
+ * Writing to an attribute immediately sets a value, an open file can be
+ * written to multiple times.
+ *
+ * Reading from an attribute creates a buffer from the value that might get
+ * read with multiple read calls. When the attribute has been read
+ * completely, no further read calls are possible until the file is opened
+ * again.
+ *
+ * All attributes contain a text representation of a numeric value
+ * that are accessed with the get() and set() functions.
+ */
+#define __DEFINE_SIMPLE_ATTRIBUTE(__static, __fops, __get, __set, __fmt)\
+static int __fops ## _open(struct inode *inode, struct file *file)	\
+{									\
+	__simple_attr_check_format(__fmt, 0ull);			\
+	return simple_attr_open(inode, file, __get, __set, __fmt);	\
+}									\
+__static const struct file_operations __fops = {			\
+	.owner	 = THIS_MODULE,						\
+	.open	 = __fops ## _open,					\
+	.release = simple_attr_release,					\
+	.read	 = simple_attr_read,					\
+	.write	 = simple_attr_write,					\
+}
+
+#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
+	__DEFINE_SIMPLE_ATTRIBUTE(static, __fops, __get, __set, __fmt)
+
+#define DEFINE_SIMPLE_EXPORTED_ATTRIBUTE(__fops, __get, __set, __fmt)	\
+	__DEFINE_SIMPLE_ATTRIBUTE(/**/, __fops, __get, __set, __fmt);	\
+	EXPORT_SYMBOL_GPL(__fops)
+
+static inline void __attribute__((format(printf, 1, 2)))
+__simple_attr_check_format(const char *fmt, ...)
+{
+	/* don't do anything, just let the compiler check the arguments; */
+}
+
+int simple_attr_open(struct inode *inode, struct file *file,
+		     int (*get)(void *, u64 *), int (*set)(void *, u64),
+		     const char *fmt);
+int simple_attr_release(struct inode *inode, struct file *file);
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+			 size_t len, loff_t *ppos);
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+			  size_t len, loff_t *ppos);
+
 extern const struct file_operations simple_fops_u8;
 extern const struct file_operations simple_fops_x8;
 extern const struct file_operations simple_fops_u16;

-- 


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

* [RFC 07/11] split out libfs/file.c from libfs.c
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (5 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 06/11] split out linux/libfs.h from linux/fs.h Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 08/11] split out libfs/dentry.c " Arnd Bergmann
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-file.diff --]
[-- Type: text/plain, Size: 9343 bytes --]

Consolidate all file manipulation code in libfs in a single
source file.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -421,165 +421,6 @@ ssize_t simple_read_from_buffer(void __u
 }
 
 /*
- * Transaction based IO.
- * The file expects a single write which triggers the transaction, and then
- * possibly a read which collects the result - which is stored in a
- * file-local buffer.
- */
-char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
-{
-	struct simple_transaction_argresp *ar;
-	static DEFINE_SPINLOCK(simple_transaction_lock);
-
-	if (size > SIMPLE_TRANSACTION_LIMIT - 1)
-		return ERR_PTR(-EFBIG);
-
-	ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
-	if (!ar)
-		return ERR_PTR(-ENOMEM);
-
-	spin_lock(&simple_transaction_lock);
-
-	/* only one write allowed per open */
-	if (file->private_data) {
-		spin_unlock(&simple_transaction_lock);
-		free_page((unsigned long)ar);
-		return ERR_PTR(-EBUSY);
-	}
-
-	file->private_data = ar;
-
-	spin_unlock(&simple_transaction_lock);
-
-	if (copy_from_user(ar->data, buf, size))
-		return ERR_PTR(-EFAULT);
-
-	return ar->data;
-}
-
-ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
-{
-	struct simple_transaction_argresp *ar = file->private_data;
-
-	if (!ar)
-		return 0;
-	return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
-}
-
-int simple_transaction_release(struct inode *inode, struct file *file)
-{
-	free_page((unsigned long)file->private_data);
-	return 0;
-}
-
-/* Simple attribute files */
-
-struct simple_attr {
-	int (*get)(void *, u64 *);
-	int (*set)(void *, u64);
-	char get_buf[24];	/* enough to store a u64 and "\n\0" */
-	char set_buf[24];
-	void *data;
-	const char *fmt;	/* format for read operation */
-	struct mutex mutex;	/* protects access to these buffers */
-};
-
-/* simple_attr_open is called by an actual attribute open file operation
- * to set the attribute specific access operations. */
-int simple_attr_open(struct inode *inode, struct file *file,
-		     int (*get)(void *, u64 *), int (*set)(void *, u64),
-		     const char *fmt)
-{
-	struct simple_attr *attr;
-
-	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
-	if (!attr)
-		return -ENOMEM;
-
-	attr->get = get;
-	attr->set = set;
-	attr->data = inode->i_private;
-	attr->fmt = fmt;
-	mutex_init(&attr->mutex);
-
-	file->private_data = attr;
-
-	return nonseekable_open(inode, file);
-}
-
-int simple_attr_release(struct inode *inode, struct file *file)
-{
-	kfree(file->private_data);
-	return 0;
-}
-
-/* read from the buffer that is filled with the get function */
-ssize_t simple_attr_read(struct file *file, char __user *buf,
-			 size_t len, loff_t *ppos)
-{
-	struct simple_attr *attr;
-	size_t size;
-	ssize_t ret;
-
-	attr = file->private_data;
-
-	if (!attr->get)
-		return -EACCES;
-
-	ret = mutex_lock_interruptible(&attr->mutex);
-	if (ret)
-		return ret;
-
-	if (*ppos) {		/* continued read */
-		size = strlen(attr->get_buf);
-	} else {		/* first read */
-		u64 val;
-		ret = attr->get(attr->data, &val);
-		if (ret)
-			goto out;
-
-		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
-				 attr->fmt, (unsigned long long)val);
-	}
-
-	ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
-out:
-	mutex_unlock(&attr->mutex);
-	return ret;
-}
-
-/* interpret the buffer as a number to call the set function with */
-ssize_t simple_attr_write(struct file *file, const char __user *buf,
-			  size_t len, loff_t *ppos)
-{
-	struct simple_attr *attr;
-	u64 val;
-	size_t size;
-	ssize_t ret;
-
-	attr = file->private_data;
-	if (!attr->set)
-		return -EACCES;
-
-	ret = mutex_lock_interruptible(&attr->mutex);
-	if (ret)
-		return ret;
-
-	ret = -EFAULT;
-	size = min(sizeof(attr->set_buf) - 1, len);
-	if (copy_from_user(attr->set_buf, buf, size))
-		goto out;
-
-	ret = len; /* claim we got the whole input */
-	attr->set_buf[size] = '\0';
-	val = simple_strtol(attr->set_buf, NULL, 0);
-	attr->set(attr->data, val);
-out:
-	mutex_unlock(&attr->mutex);
-	return ret;
-}
-
-/*
  * This is what d_alloc_anon should have been.  Once the exportfs
  * argument transition has been finished I will update d_alloc_anon
  * to this prototype and this wrapper will go away.   --hch
@@ -689,10 +530,3 @@ EXPORT_SYMBOL(simple_statfs);
 EXPORT_SYMBOL(simple_sync_file);
 EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
-EXPORT_SYMBOL(simple_transaction_get);
-EXPORT_SYMBOL(simple_transaction_read);
-EXPORT_SYMBOL(simple_transaction_release);
-EXPORT_SYMBOL_GPL(simple_attr_open);
-EXPORT_SYMBOL_GPL(simple_attr_release);
-EXPORT_SYMBOL_GPL(simple_attr_read);
-EXPORT_SYMBOL_GPL(simple_attr_write);
Index: linux-2.6/fs/libfs/file.c
===================================================================
--- linux-2.6.orig/fs/libfs/file.c
+++ linux-2.6/fs/libfs/file.c
@@ -9,6 +9,172 @@
 
 #include <asm/uaccess.h>
 
+/*
+ * Transaction based IO.
+ * The file expects a single write which triggers the transaction, and then
+ * possibly a read which collects the result - which is stored in a
+ * file-local buffer.
+ */
+char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
+{
+	struct simple_transaction_argresp *ar;
+	static DEFINE_SPINLOCK(simple_transaction_lock);
+
+	if (size > SIMPLE_TRANSACTION_LIMIT - 1)
+		return ERR_PTR(-EFBIG);
+
+	ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
+	if (!ar)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&simple_transaction_lock);
+
+	/* only one write allowed per open */
+	if (file->private_data) {
+		spin_unlock(&simple_transaction_lock);
+		free_page((unsigned long)ar);
+		return ERR_PTR(-EBUSY);
+	}
+
+	file->private_data = ar;
+
+	spin_unlock(&simple_transaction_lock);
+
+	if (copy_from_user(ar->data, buf, size))
+		return ERR_PTR(-EFAULT);
+
+	return ar->data;
+}
+EXPORT_SYMBOL(simple_transaction_get);
+
+ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
+{
+	struct simple_transaction_argresp *ar = file->private_data;
+
+	if (!ar)
+		return 0;
+	return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
+}
+EXPORT_SYMBOL(simple_transaction_read);
+
+int simple_transaction_release(struct inode *inode, struct file *file)
+{
+	free_page((unsigned long)file->private_data);
+	return 0;
+}
+EXPORT_SYMBOL(simple_transaction_release);
+
+/* Simple attribute files */
+
+struct simple_attr {
+	int (*get)(void *, u64 *);
+	int (*set)(void *, u64);
+	char get_buf[24];	/* enough to store a u64 and "\n\0" */
+	char set_buf[24];
+	void *data;
+	const char *fmt;	/* format for read operation */
+	struct mutex mutex;	/* protects access to these buffers */
+};
+
+/* simple_attr_open is called by an actual attribute open file operation
+ * to set the attribute specific access operations. */
+int simple_attr_open(struct inode *inode, struct file *file,
+		     int (*get)(void *, u64 *), int (*set)(void *, u64),
+		     const char *fmt)
+{
+	struct simple_attr *attr;
+
+	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr)
+		return -ENOMEM;
+
+	attr->get = get;
+	attr->set = set;
+	attr->data = inode->i_private;
+	attr->fmt = fmt;
+	mutex_init(&attr->mutex);
+
+	file->private_data = attr;
+
+	return nonseekable_open(inode, file);
+}
+EXPORT_SYMBOL_GPL(simple_attr_open);
+
+int simple_attr_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(simple_attr_release);
+
+/* read from the buffer that is filled with the get function */
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+			 size_t len, loff_t *ppos)
+{
+	struct simple_attr *attr;
+	size_t size;
+	ssize_t ret;
+
+	attr = file->private_data;
+
+	if (!attr->get)
+		return -EACCES;
+
+	ret = mutex_lock_interruptible(&attr->mutex);
+	if (ret)
+		return ret;
+
+	if (*ppos) {		/* continued read */
+		size = strlen(attr->get_buf);
+	} else {		/* first read */
+		u64 val;
+		ret = attr->get(attr->data, &val);
+		if (ret)
+			goto out;
+
+		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+				 attr->fmt, (unsigned long long)val);
+	}
+
+	ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+out:
+	mutex_unlock(&attr->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(simple_attr_read);
+
+/* interpret the buffer as a number to call the set function with */
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+			  size_t len, loff_t *ppos)
+{
+	struct simple_attr *attr;
+	u64 val;
+	size_t size;
+	ssize_t ret;
+
+	attr = file->private_data;
+	if (!attr->set)
+		return -EACCES;
+
+	ret = mutex_lock_interruptible(&attr->mutex);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	size = min(sizeof(attr->set_buf) - 1, len);
+	if (copy_from_user(attr->set_buf, buf, size))
+		goto out;
+
+	ret = len; /* claim we got the whole input */
+	attr->set_buf[size] = '\0';
+	val = simple_strtol(attr->set_buf, NULL, 0);
+	attr->set(attr->data, val);
+out:
+	mutex_unlock(&attr->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(simple_attr_write);
+
 /* commonly used attribute file operations */
 static int simple_u8_set(void *data, u64 val)
 {

-- 


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

* [RFC 08/11] split out libfs/dentry.c from libfs.c
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (6 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 07/11] split out libfs/file.c from libfs.c Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 09/11] split out libfs/super.c " Arnd Bergmann
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-dentry.diff --]
[-- Type: text/plain, Size: 17022 bytes --]

Consolidate all dentry manipulation code in libfs in a single
source file.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -12,188 +12,6 @@
 
 #include <asm/uaccess.h>
 
-int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
-		   struct kstat *stat)
-{
-	struct inode *inode = dentry->d_inode;
-	generic_fillattr(inode, stat);
-	stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
-	return 0;
-}
-
-int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-	buf->f_type = dentry->d_sb->s_magic;
-	buf->f_bsize = PAGE_CACHE_SIZE;
-	buf->f_namelen = NAME_MAX;
-	return 0;
-}
-
-/*
- * Retaining negative dentries for an in-memory filesystem just wastes
- * memory and lookup time: arrange for them to be deleted immediately.
- */
-static int simple_delete_dentry(struct dentry *dentry)
-{
-	return 1;
-}
-
-/*
- * Lookup the data. This is trivial - if the dentry didn't already
- * exist, we know it is negative.  Set d_op to delete negative dentries.
- */
-struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-	static struct dentry_operations simple_dentry_operations = {
-		.d_delete = simple_delete_dentry,
-	};
-
-	if (dentry->d_name.len > NAME_MAX)
-		return ERR_PTR(-ENAMETOOLONG);
-	dentry->d_op = &simple_dentry_operations;
-	d_add(dentry, NULL);
-	return NULL;
-}
-
-int simple_sync_file(struct file * file, struct dentry *dentry, int datasync)
-{
-	return 0;
-}
- 
-int dcache_dir_open(struct inode *inode, struct file *file)
-{
-	static struct qstr cursor_name = {.len = 1, .name = "."};
-
-	file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
-
-	return file->private_data ? 0 : -ENOMEM;
-}
-
-int dcache_dir_close(struct inode *inode, struct file *file)
-{
-	dput(file->private_data);
-	return 0;
-}
-
-loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
-{
-	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
-	switch (origin) {
-		case 1:
-			offset += file->f_pos;
-		case 0:
-			if (offset >= 0)
-				break;
-		default:
-			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
-			return -EINVAL;
-	}
-	if (offset != file->f_pos) {
-		file->f_pos = offset;
-		if (file->f_pos >= 2) {
-			struct list_head *p;
-			struct dentry *cursor = file->private_data;
-			loff_t n = file->f_pos - 2;
-
-			spin_lock(&dcache_lock);
-			list_del(&cursor->d_u.d_child);
-			p = file->f_path.dentry->d_subdirs.next;
-			while (n && p != &file->f_path.dentry->d_subdirs) {
-				struct dentry *next;
-				next = list_entry(p, struct dentry, d_u.d_child);
-				if (!d_unhashed(next) && next->d_inode)
-					n--;
-				p = p->next;
-			}
-			list_add_tail(&cursor->d_u.d_child, p);
-			spin_unlock(&dcache_lock);
-		}
-	}
-	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
-	return offset;
-}
-
-/* Relationship between i_mode and the DT_xxx types */
-static inline unsigned char dt_type(struct inode *inode)
-{
-	return (inode->i_mode >> 12) & 15;
-}
-
-/*
- * Directory is locked and all positive dentries in it are safe, since
- * for ramfs-type trees they can't go away without unlink() or rmdir(),
- * both impossible due to the lock on directory.
- */
-
-int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
-{
-	struct dentry *dentry = filp->f_path.dentry;
-	struct dentry *cursor = filp->private_data;
-	struct list_head *p, *q = &cursor->d_u.d_child;
-	ino_t ino;
-	int i = filp->f_pos;
-
-	switch (i) {
-		case 0:
-			ino = dentry->d_inode->i_ino;
-			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
-				break;
-			filp->f_pos++;
-			i++;
-			/* fallthrough */
-		case 1:
-			ino = parent_ino(dentry);
-			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
-				break;
-			filp->f_pos++;
-			i++;
-			/* fallthrough */
-		default:
-			spin_lock(&dcache_lock);
-			if (filp->f_pos == 2)
-				list_move(q, &dentry->d_subdirs);
-
-			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
-				struct dentry *next;
-				next = list_entry(p, struct dentry, d_u.d_child);
-				if (d_unhashed(next) || !next->d_inode)
-					continue;
-
-				spin_unlock(&dcache_lock);
-				if (filldir(dirent, next->d_name.name, 
-					    next->d_name.len, filp->f_pos, 
-					    next->d_inode->i_ino, 
-					    dt_type(next->d_inode)) < 0)
-					return 0;
-				spin_lock(&dcache_lock);
-				/* next is still alive */
-				list_move(q, p);
-				p = q;
-				filp->f_pos++;
-			}
-			spin_unlock(&dcache_lock);
-	}
-	return 0;
-}
-
-ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
-{
-	return -EISDIR;
-}
-
-const struct file_operations simple_dir_operations = {
-	.open		= dcache_dir_open,
-	.release	= dcache_dir_close,
-	.llseek		= dcache_dir_lseek,
-	.read		= generic_read_dir,
-	.readdir	= dcache_readdir,
-	.fsync		= simple_sync_file,
-};
-
-const struct inode_operations simple_dir_inode_operations = {
-	.lookup		= simple_lookup,
-};
-
 static const struct super_operations simple_super_operations = {
 	.statfs		= simple_statfs,
 };
@@ -420,113 +238,14 @@ ssize_t simple_read_from_buffer(void __u
 	return count;
 }
 
-/*
- * This is what d_alloc_anon should have been.  Once the exportfs
- * argument transition has been finished I will update d_alloc_anon
- * to this prototype and this wrapper will go away.   --hch
- */
-static struct dentry *exportfs_d_alloc(struct inode *inode)
-{
-	struct dentry *dentry;
-
-	if (!inode)
-		return NULL;
-	if (IS_ERR(inode))
-		return ERR_PTR(PTR_ERR(inode));
-
-	dentry = d_alloc_anon(inode);
-	if (!dentry) {
-		iput(inode);
-		dentry = ERR_PTR(-ENOMEM);
-	}
-	return dentry;
-}
-
-/**
- * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
- * @sb:		filesystem to do the file handle conversion on
- * @fid:	file handle to convert
- * @fh_len:	length of the file handle in bytes
- * @fh_type:	type of file handle
- * @get_inode:	filesystem callback to retrieve inode
- *
- * This function decodes @fid as long as it has one of the well-known
- * Linux filehandle types and calls @get_inode on it to retrieve the
- * inode for the object specified in the file handle.
- */
-struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
-		int fh_len, int fh_type, struct inode *(*get_inode)
-			(struct super_block *sb, u64 ino, u32 gen))
-{
-	struct inode *inode = NULL;
-
-	if (fh_len < 2)
-		return NULL;
-
-	switch (fh_type) {
-	case FILEID_INO32_GEN:
-	case FILEID_INO32_GEN_PARENT:
-		inode = get_inode(sb, fid->i32.ino, fid->i32.gen);
-		break;
-	}
-
-	return exportfs_d_alloc(inode);
-}
-EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
-
-/**
- * generic_fh_to_dentry - generic helper for the fh_to_parent export operation
- * @sb:		filesystem to do the file handle conversion on
- * @fid:	file handle to convert
- * @fh_len:	length of the file handle in bytes
- * @fh_type:	type of file handle
- * @get_inode:	filesystem callback to retrieve inode
- *
- * This function decodes @fid as long as it has one of the well-known
- * Linux filehandle types and calls @get_inode on it to retrieve the
- * inode for the _parent_ object specified in the file handle if it
- * is specified in the file handle, or NULL otherwise.
- */
-struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
-		int fh_len, int fh_type, struct inode *(*get_inode)
-			(struct super_block *sb, u64 ino, u32 gen))
-{
-	struct inode *inode = NULL;
-
-	if (fh_len <= 2)
-		return NULL;
-
-	switch (fh_type) {
-	case FILEID_INO32_GEN_PARENT:
-		inode = get_inode(sb, fid->i32.parent_ino,
-				  (fh_len > 3 ? fid->i32.parent_gen : 0));
-		break;
-	}
-
-	return exportfs_d_alloc(inode);
-}
-EXPORT_SYMBOL_GPL(generic_fh_to_parent);
-
-EXPORT_SYMBOL(dcache_dir_close);
-EXPORT_SYMBOL(dcache_dir_lseek);
-EXPORT_SYMBOL(dcache_dir_open);
-EXPORT_SYMBOL(dcache_readdir);
-EXPORT_SYMBOL(generic_read_dir);
 EXPORT_SYMBOL(get_sb_pseudo);
 EXPORT_SYMBOL(simple_write_begin);
 EXPORT_SYMBOL(simple_write_end);
-EXPORT_SYMBOL(simple_dir_inode_operations);
-EXPORT_SYMBOL(simple_dir_operations);
 EXPORT_SYMBOL(simple_empty);
-EXPORT_SYMBOL(d_alloc_name);
-EXPORT_SYMBOL(simple_getattr);
 EXPORT_SYMBOL(simple_link);
-EXPORT_SYMBOL(simple_lookup);
 EXPORT_SYMBOL(simple_prepare_write);
 EXPORT_SYMBOL(simple_readpage);
 EXPORT_SYMBOL(simple_rename);
 EXPORT_SYMBOL(simple_rmdir);
-EXPORT_SYMBOL(simple_statfs);
-EXPORT_SYMBOL(simple_sync_file);
 EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
Index: linux-2.6/fs/libfs/dentry.c
===================================================================
--- /dev/null
+++ linux-2.6/fs/libfs/dentry.c
@@ -0,0 +1,293 @@
+/*
+ *	fs/libfs/dentry.c
+ *	Library for filesystems writers -- directory operations
+ */
+
+#include <linux/libfs.h>
+#include <linux/fsnotify.h>
+#include <linux/module.h>
+#include <linux/vfs.h>
+#include <linux/mutex.h>
+#include <linux/exportfs.h>
+
+#include <asm/uaccess.h>
+
+int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		   struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	generic_fillattr(inode, stat);
+	stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
+	return 0;
+}
+EXPORT_SYMBOL(simple_getattr);
+
+int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	buf->f_type = dentry->d_sb->s_magic;
+	buf->f_bsize = PAGE_CACHE_SIZE;
+	buf->f_namelen = NAME_MAX;
+	return 0;
+}
+EXPORT_SYMBOL(simple_statfs);
+
+/*
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
+ */
+static int simple_delete_dentry(struct dentry *dentry)
+{
+	return 1;
+}
+
+/*
+ * Lookup the data. This is trivial - if the dentry didn't already
+ * exist, we know it is negative.  Set d_op to delete negative dentries.
+ */
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+	static struct dentry_operations simple_dentry_operations = {
+		.d_delete = simple_delete_dentry,
+	};
+
+	if (dentry->d_name.len > NAME_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+	dentry->d_op = &simple_dentry_operations;
+	d_add(dentry, NULL);
+	return NULL;
+}
+EXPORT_SYMBOL(simple_lookup);
+
+int simple_sync_file(struct file *file, struct dentry *dentry, int datasync)
+{
+	return 0;
+}
+EXPORT_SYMBOL(simple_sync_file);
+
+int dcache_dir_open(struct inode *inode, struct file *file)
+{
+	static struct qstr cursor_name = {.len = 1, .name = "."};
+
+	file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(dcache_dir_open);
+
+int dcache_dir_close(struct inode *inode, struct file *file)
+{
+	dput(file->private_data);
+	return 0;
+}
+EXPORT_SYMBOL(dcache_dir_close);
+
+loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
+{
+	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+	switch (origin) {
+	case 1:
+		offset += file->f_pos;
+	case 0:
+		if (offset >= 0)
+			break;
+	default:
+		mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+		return -EINVAL;
+	}
+	if (offset != file->f_pos) {
+		file->f_pos = offset;
+		if (file->f_pos >= 2) {
+			struct list_head *p;
+			struct dentry *cursor = file->private_data;
+			loff_t n = file->f_pos - 2;
+
+			spin_lock(&dcache_lock);
+			list_del(&cursor->d_u.d_child);
+			p = file->f_path.dentry->d_subdirs.next;
+			while (n && p != &file->f_path.dentry->d_subdirs) {
+				struct dentry *next;
+				next = list_entry(p, struct dentry, d_u.d_child);
+				if (!d_unhashed(next) && next->d_inode)
+					n--;
+				p = p->next;
+			}
+			list_add_tail(&cursor->d_u.d_child, p);
+			spin_unlock(&dcache_lock);
+		}
+	}
+	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+	return offset;
+}
+EXPORT_SYMBOL(dcache_dir_lseek);
+
+/* Relationship between i_mode and the DT_xxx types */
+static inline unsigned char dt_type(struct inode *inode)
+{
+	return (inode->i_mode >> 12) & 15;
+}
+
+/*
+ * Directory is locked and all positive dentries in it are safe, since
+ * for ramfs-type trees they can't go away without unlink() or rmdir(),
+ * both impossible due to the lock on directory.
+ */
+
+int dcache_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct dentry *dentry = filp->f_path.dentry;
+	struct dentry *cursor = filp->private_data;
+	struct list_head *p, *q = &cursor->d_u.d_child;
+	ino_t ino;
+	int i = filp->f_pos;
+
+	switch (i) {
+	case 0:
+		ino = dentry->d_inode->i_ino;
+		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+			break;
+		filp->f_pos++;
+		i++;
+		/* fallthrough */
+	case 1:
+		ino = parent_ino(dentry);
+		if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+			break;
+		filp->f_pos++;
+		i++;
+		/* fallthrough */
+	default:
+		spin_lock(&dcache_lock);
+		if (filp->f_pos == 2)
+			list_move(q, &dentry->d_subdirs);
+
+		for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
+			struct dentry *next;
+			next = list_entry(p, struct dentry, d_u.d_child);
+			if (d_unhashed(next) || !next->d_inode)
+				continue;
+
+			spin_unlock(&dcache_lock);
+			if (filldir(dirent, next->d_name.name,
+				    next->d_name.len, filp->f_pos,
+				    next->d_inode->i_ino,
+				    dt_type(next->d_inode)) < 0)
+				return 0;
+			spin_lock(&dcache_lock);
+			/* next is still alive */
+			list_move(q, p);
+			p = q;
+			filp->f_pos++;
+		}
+		spin_unlock(&dcache_lock);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dcache_readdir);
+
+ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
+{
+	return -EISDIR;
+}
+EXPORT_SYMBOL(generic_read_dir);
+
+const struct file_operations simple_dir_operations = {
+	.open		= dcache_dir_open,
+	.release	= dcache_dir_close,
+	.llseek		= dcache_dir_lseek,
+	.read		= generic_read_dir,
+	.readdir	= dcache_readdir,
+	.fsync		= simple_sync_file,
+};
+EXPORT_SYMBOL(simple_dir_operations);
+
+const struct inode_operations simple_dir_inode_operations = {
+	.lookup		= simple_lookup,
+};
+EXPORT_SYMBOL(simple_dir_inode_operations);
+
+/*
+ * This is what d_alloc_anon should have been.  Once the exportfs
+ * argument transition has been finished I will update d_alloc_anon
+ * to this prototype and this wrapper will go away.   --hch
+ */
+static struct dentry *exportfs_d_alloc(struct inode *inode)
+{
+	struct dentry *dentry;
+
+	if (!inode)
+		return NULL;
+	if (IS_ERR(inode))
+		return ERR_PTR(PTR_ERR(inode));
+
+	dentry = d_alloc_anon(inode);
+	if (!dentry) {
+		iput(inode);
+		dentry = ERR_PTR(-ENOMEM);
+	}
+	return dentry;
+}
+
+/**
+ * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
+ * @sb:		filesystem to do the file handle conversion on
+ * @fid:	file handle to convert
+ * @fh_len:	length of the file handle in bytes
+ * @fh_type:	type of file handle
+ * @get_inode:	filesystem callback to retrieve inode
+ *
+ * This function decodes @fid as long as it has one of the well-known
+ * Linux filehandle types and calls @get_inode on it to retrieve the
+ * inode for the object specified in the file handle.
+ */
+struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
+		int fh_len, int fh_type, struct inode *(*get_inode)
+			(struct super_block *sb, u64 ino, u32 gen))
+{
+	struct inode *inode = NULL;
+
+	if (fh_len < 2)
+		return NULL;
+
+	switch (fh_type) {
+	case FILEID_INO32_GEN:
+	case FILEID_INO32_GEN_PARENT:
+		inode = get_inode(sb, fid->i32.ino, fid->i32.gen);
+		break;
+	}
+
+	return exportfs_d_alloc(inode);
+}
+EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
+
+/**
+ * generic_fh_to_dentry - generic helper for the fh_to_parent export operation
+ * @sb:		filesystem to do the file handle conversion on
+ * @fid:	file handle to convert
+ * @fh_len:	length of the file handle in bytes
+ * @fh_type:	type of file handle
+ * @get_inode:	filesystem callback to retrieve inode
+ *
+ * This function decodes @fid as long as it has one of the well-known
+ * Linux filehandle types and calls @get_inode on it to retrieve the
+ * inode for the _parent_ object specified in the file handle if it
+ * is specified in the file handle, or NULL otherwise.
+ */
+struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
+		int fh_len, int fh_type, struct inode *(*get_inode)
+			(struct super_block *sb, u64 ino, u32 gen))
+{
+	struct inode *inode = NULL;
+
+	if (fh_len <= 2)
+		return NULL;
+
+	switch (fh_type) {
+	case FILEID_INO32_GEN_PARENT:
+		inode = get_inode(sb, fid->i32.parent_ino,
+				  (fh_len > 3 ? fid->i32.parent_gen : 0));
+		break;
+	}
+
+	return exportfs_d_alloc(inode);
+}
+EXPORT_SYMBOL_GPL(generic_fh_to_parent);
Index: linux-2.6/fs/libfs/Makefile
===================================================================
--- linux-2.6.orig/fs/libfs/Makefile
+++ linux-2.6/fs/libfs/Makefile
@@ -1,3 +1,3 @@
 libfs-y += file.o
 
-obj-$(CONFIG_LIBFS) += libfs.o inode.o super.o
+obj-$(CONFIG_LIBFS) += libfs.o inode.o super.o dentry.o

-- 


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

* [RFC 09/11] split out libfs/super.c from libfs.c
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (7 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 08/11] split out libfs/dentry.c " Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 10/11] split out libfs/inode.c " Arnd Bergmann
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-super.o --]
[-- Type: text/plain, Size: 4096 bytes --]

Consolidate all super block manipulation code in libfs in a single
source file.

Signed-off-by: Arnd Bergman <arnd@arndb.de>
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -12,63 +12,6 @@
 
 #include <asm/uaccess.h>
 
-static const struct super_operations simple_super_operations = {
-	.statfs		= simple_statfs,
-};
-
-/*
- * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
- * will never be mountable)
- */
-int get_sb_pseudo(struct file_system_type *fs_type, char *name,
-	const struct super_operations *ops, unsigned long magic,
-	struct vfsmount *mnt)
-{
-	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
-	struct dentry *dentry;
-	struct inode *root;
-	struct qstr d_name = {.name = name, .len = strlen(name)};
-
-	if (IS_ERR(s))
-		return PTR_ERR(s);
-
-	s->s_flags = MS_NOUSER;
-	s->s_maxbytes = ~0ULL;
-	s->s_blocksize = 1024;
-	s->s_blocksize_bits = 10;
-	s->s_magic = magic;
-	s->s_op = ops ? ops : &simple_super_operations;
-	s->s_time_gran = 1;
-	root = new_inode(s);
-	if (!root)
-		goto Enomem;
-	/*
-	 * since this is the first inode, make it number 1. New inodes created
-	 * after this must take care not to collide with it (by passing
-	 * max_reserved of 1 to iunique).
-	 */
-	root->i_ino = 1;
-	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
-	root->i_uid = root->i_gid = 0;
-	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
-	dentry = d_alloc(NULL, &d_name);
-	if (!dentry) {
-		iput(root);
-		goto Enomem;
-	}
-	dentry->d_sb = s;
-	dentry->d_parent = dentry;
-	d_instantiate(dentry, root);
-	s->s_root = dentry;
-	s->s_flags |= MS_ACTIVE;
-	return simple_set_mnt(mnt, s);
-
-Enomem:
-	up_write(&s->s_umount);
-	deactivate_super(s);
-	return -ENOMEM;
-}
-
 int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
@@ -238,7 +181,6 @@ ssize_t simple_read_from_buffer(void __u
 	return count;
 }
 
-EXPORT_SYMBOL(get_sb_pseudo);
 EXPORT_SYMBOL(simple_write_begin);
 EXPORT_SYMBOL(simple_write_end);
 EXPORT_SYMBOL(simple_empty);
Index: linux-2.6/fs/libfs/super.c
===================================================================
--- linux-2.6.orig/fs/libfs/super.c
+++ linux-2.6/fs/libfs/super.c
@@ -54,6 +54,60 @@ static const struct super_operations sim
 };
 
 /*
+ * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
+ * will never be mountable)
+ */
+int get_sb_pseudo(struct file_system_type *fs_type, char *name,
+	const struct super_operations *ops, unsigned long magic,
+	struct vfsmount *mnt)
+{
+	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
+	struct dentry *dentry;
+	struct inode *root;
+	struct qstr d_name = {.name = name, .len = strlen(name)};
+
+	if (IS_ERR(s))
+		return PTR_ERR(s);
+
+	s->s_flags = MS_NOUSER;
+	s->s_maxbytes = ~0ULL;
+	s->s_blocksize = 1024;
+	s->s_blocksize_bits = 10;
+	s->s_magic = magic;
+	s->s_op = ops ? ops : &simple_super_operations;
+	s->s_time_gran = 1;
+	root = new_inode(s);
+	if (!root)
+		goto Enomem;
+	/*
+	 * since this is the first inode, make it number 1. New inodes created
+	 * after this must take care not to collide with it (by passing
+	 * max_reserved of 1 to iunique).
+	 */
+	root->i_ino = 1;
+	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
+	root->i_uid = root->i_gid = 0;
+	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
+	dentry = d_alloc(NULL, &d_name);
+	if (!dentry) {
+		iput(root);
+		goto Enomem;
+	}
+	dentry->d_sb = s;
+	dentry->d_parent = dentry;
+	d_instantiate(dentry, root);
+	s->s_root = dentry;
+	s->s_flags |= MS_ACTIVE;
+	return simple_set_mnt(mnt, s);
+
+Enomem:
+	up_write(&s->s_umount);
+	deactivate_super(s);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(get_sb_pseudo);
+
+/*
  * the inodes created here are not hashed. If you use iunique to generate
  * unique inode values later for this filesystem, then you must take care
  * to pass it an appropriate max_reserved value to avoid collisions.

-- 


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

* [RFC 10/11] split out libfs/inode.c from libfs.c
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (8 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 09/11] split out libfs/super.c " Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19  4:04 ` [RFC 11/11] split out libfs/aops.c " Arnd Bergmann
  2008-02-19 16:38 ` [RFC 00/11] possible debugfs/libfs consolidation Greg KH
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-inode.diff --]
[-- Type: text/plain, Size: 4508 bytes --]

Consolidate all inode manipulation code in libfs in a single
source file.

Signed-off-by: Arnd Bergman <arnd@arndb.de>

Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -12,78 +12,6 @@
 
 #include <asm/uaccess.h>
 
-int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
-{
-	struct inode *inode = old_dentry->d_inode;
-
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	inc_nlink(inode);
-	atomic_inc(&inode->i_count);
-	dget(dentry);
-	d_instantiate(dentry, inode);
-	return 0;
-}
-
-int simple_empty(struct dentry *dentry)
-{
-	struct dentry *child;
-	int ret = 0;
-
-	spin_lock(&dcache_lock);
-	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
-		if (simple_positive(child))
-			goto out;
-	ret = 1;
-out:
-	spin_unlock(&dcache_lock);
-	return ret;
-}
-
-int simple_unlink(struct inode *dir, struct dentry *dentry)
-{
-	struct inode *inode = dentry->d_inode;
-
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	drop_nlink(inode);
-	dput(dentry);
-	return 0;
-}
-
-int simple_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	if (!simple_empty(dentry))
-		return -ENOTEMPTY;
-
-	drop_nlink(dentry->d_inode);
-	simple_unlink(dir, dentry);
-	drop_nlink(dir);
-	return 0;
-}
-
-int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
-		struct inode *new_dir, struct dentry *new_dentry)
-{
-	struct inode *inode = old_dentry->d_inode;
-	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
-
-	if (!simple_empty(new_dentry))
-		return -ENOTEMPTY;
-
-	if (new_dentry->d_inode) {
-		simple_unlink(new_dir, new_dentry);
-		if (they_are_dirs)
-			drop_nlink(old_dir);
-	} else if (they_are_dirs) {
-		drop_nlink(old_dir);
-		inc_nlink(new_dir);
-	}
-
-	old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
-		new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
-
-	return 0;
-}
-
 int simple_readpage(struct file *file, struct page *page)
 {
 	clear_highpage(page);
@@ -183,11 +111,6 @@ ssize_t simple_read_from_buffer(void __u
 
 EXPORT_SYMBOL(simple_write_begin);
 EXPORT_SYMBOL(simple_write_end);
-EXPORT_SYMBOL(simple_empty);
-EXPORT_SYMBOL(simple_link);
 EXPORT_SYMBOL(simple_prepare_write);
 EXPORT_SYMBOL(simple_readpage);
-EXPORT_SYMBOL(simple_rename);
-EXPORT_SYMBOL(simple_rmdir);
-EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
Index: linux-2.6/fs/libfs/inode.c
===================================================================
--- linux-2.6.orig/fs/libfs/inode.c
+++ linux-2.6/fs/libfs/inode.c
@@ -417,4 +417,79 @@ exit:
 }
 EXPORT_SYMBOL_GPL(simple_rename_named);
 
+int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = old_dentry->d_inode;
 
+	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	inc_nlink(inode);
+	atomic_inc(&inode->i_count);
+	dget(dentry);
+	d_instantiate(dentry, inode);
+	return 0;
+}
+EXPORT_SYMBOL(simple_link);
+
+int simple_empty(struct dentry *dentry)
+{
+	struct dentry *child;
+	int ret = 0;
+
+	spin_lock(&dcache_lock);
+	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
+		if (simple_positive(child))
+			goto out;
+	ret = 1;
+out:
+	spin_unlock(&dcache_lock);
+	return ret;
+}
+EXPORT_SYMBOL(simple_empty);
+
+int simple_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+
+	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	drop_nlink(inode);
+	dput(dentry);
+	return 0;
+}
+EXPORT_SYMBOL(simple_unlink);
+
+int simple_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	if (!simple_empty(dentry))
+		return -ENOTEMPTY;
+
+	drop_nlink(dentry->d_inode);
+	simple_unlink(dir, dentry);
+	drop_nlink(dir);
+	return 0;
+}
+EXPORT_SYMBOL(simple_rmdir);
+
+int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
+		struct inode *new_dir, struct dentry *new_dentry)
+{
+	struct inode *inode = old_dentry->d_inode;
+	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
+
+	if (!simple_empty(new_dentry))
+		return -ENOTEMPTY;
+
+	if (new_dentry->d_inode) {
+		simple_unlink(new_dir, new_dentry);
+		if (they_are_dirs)
+			drop_nlink(old_dir);
+	} else if (they_are_dirs) {
+		drop_nlink(old_dir);
+		inc_nlink(new_dir);
+	}
+
+	old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
+		new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+	return 0;
+}
+EXPORT_SYMBOL(simple_rename);

-- 


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

* [RFC 11/11] split out libfs/aops.c from libfs.c
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (9 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 10/11] split out libfs/inode.c " Arnd Bergmann
@ 2008-02-19  4:04 ` Arnd Bergmann
  2008-02-19 16:38 ` [RFC 00/11] possible debugfs/libfs consolidation Greg KH
  11 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-19  4:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, Alexander Viro, Christoph Hellwig, Greg KH, David Howells

[-- Attachment #1: libfs-aops.diff --]
[-- Type: text/plain, Size: 6325 bytes --]

Consolidate all address space manipulation code in libfs in a single
source file.

Signed-off-by: Arnd Bergman <arnd@arndb.de>


Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *	fs/libfs.c
- *	Library for filesystems writers.
- */
-
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/mount.h>
-#include <linux/vfs.h>
-#include <linux/mutex.h>
-#include <linux/exportfs.h>
-
-#include <asm/uaccess.h>
-
-int simple_readpage(struct file *file, struct page *page)
-{
-	clear_highpage(page);
-	flush_dcache_page(page);
-	SetPageUptodate(page);
-	unlock_page(page);
-	return 0;
-}
-
-int simple_prepare_write(struct file *file, struct page *page,
-			unsigned from, unsigned to)
-{
-	if (!PageUptodate(page)) {
-		if (to - from != PAGE_CACHE_SIZE)
-			zero_user_segments(page,
-				0, from,
-				to, PAGE_CACHE_SIZE);
-	}
-	return 0;
-}
-
-int simple_write_begin(struct file *file, struct address_space *mapping,
-			loff_t pos, unsigned len, unsigned flags,
-			struct page **pagep, void **fsdata)
-{
-	struct page *page;
-	pgoff_t index;
-	unsigned from;
-
-	index = pos >> PAGE_CACHE_SHIFT;
-	from = pos & (PAGE_CACHE_SIZE - 1);
-
-	page = __grab_cache_page(mapping, index);
-	if (!page)
-		return -ENOMEM;
-
-	*pagep = page;
-
-	return simple_prepare_write(file, page, from, from+len);
-}
-
-static int simple_commit_write(struct file *file, struct page *page,
-			       unsigned from, unsigned to)
-{
-	struct inode *inode = page->mapping->host;
-	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-
-	if (!PageUptodate(page))
-		SetPageUptodate(page);
-	/*
-	 * No need to use i_size_read() here, the i_size
-	 * cannot change under us because we hold the i_mutex.
-	 */
-	if (pos > inode->i_size)
-		i_size_write(inode, pos);
-	set_page_dirty(page);
-	return 0;
-}
-
-int simple_write_end(struct file *file, struct address_space *mapping,
-			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
-{
-	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-
-	/* zero the stale part of the page if we did a short copy */
-	if (copied < len) {
-		void *kaddr = kmap_atomic(page, KM_USER0);
-		memset(kaddr + from + copied, 0, len - copied);
-		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
-	}
-
-	simple_commit_write(file, page, from, from+copied);
-
-	unlock_page(page);
-	page_cache_release(page);
-
-	return copied;
-}
-
-ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
-				const void *from, size_t available)
-{
-	loff_t pos = *ppos;
-	if (pos < 0)
-		return -EINVAL;
-	if (pos >= available)
-		return 0;
-	if (count > available - pos)
-		count = available - pos;
-	if (copy_to_user(to, from + pos, count))
-		return -EFAULT;
-	*ppos = pos + count;
-	return count;
-}
-
-EXPORT_SYMBOL(simple_write_begin);
-EXPORT_SYMBOL(simple_write_end);
-EXPORT_SYMBOL(simple_prepare_write);
-EXPORT_SYMBOL(simple_readpage);
-EXPORT_SYMBOL(simple_read_from_buffer);
Index: linux-2.6/fs/libfs/Makefile
===================================================================
--- linux-2.6.orig/fs/libfs/Makefile
+++ linux-2.6/fs/libfs/Makefile
@@ -1,3 +1,3 @@
 libfs-y += file.o
 
-obj-$(CONFIG_LIBFS) += libfs.o inode.o super.o dentry.o
+obj-$(CONFIG_LIBFS) += libfs.o inode.o super.o dentry.o aops.o
Index: linux-2.6/fs/libfs/aops.c
===================================================================
--- /dev/null
+++ linux-2.6/fs/libfs/aops.c
@@ -0,0 +1,113 @@
+/*
+ *	fs/libfs/aops.c
+ *	Library for filesystems writers -- address space operations
+ */
+
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/mount.h>
+#include <linux/vfs.h>
+
+#include <asm/uaccess.h>
+
+int simple_readpage(struct file *file, struct page *page)
+{
+	clear_highpage(page);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+	return 0;
+}
+EXPORT_SYMBOL(simple_readpage);
+
+int simple_prepare_write(struct file *file, struct page *page,
+			unsigned from, unsigned to)
+{
+	if (!PageUptodate(page)) {
+		if (to - from != PAGE_CACHE_SIZE)
+			zero_user_segments(page,
+				0, from,
+				to, PAGE_CACHE_SIZE);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(simple_prepare_write);
+
+int simple_write_begin(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned flags,
+			struct page **pagep, void **fsdata)
+{
+	struct page *page;
+	pgoff_t index;
+	unsigned from;
+
+	index = pos >> PAGE_CACHE_SHIFT;
+	from = pos & (PAGE_CACHE_SIZE - 1);
+
+	page = __grab_cache_page(mapping, index);
+	if (!page)
+		return -ENOMEM;
+
+	*pagep = page;
+
+	return simple_prepare_write(file, page, from, from+len);
+}
+EXPORT_SYMBOL(simple_write_begin);
+
+static int simple_commit_write(struct file *file, struct page *page,
+			       unsigned from, unsigned to)
+{
+	struct inode *inode = page->mapping->host;
+	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+
+	if (!PageUptodate(page))
+		SetPageUptodate(page);
+	/*
+	 * No need to use i_size_read() here, the i_size
+	 * cannot change under us because we hold the i_mutex.
+	 */
+	if (pos > inode->i_size)
+		i_size_write(inode, pos);
+	set_page_dirty(page);
+	return 0;
+}
+
+int simple_write_end(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned copied,
+			struct page *page, void *fsdata)
+{
+	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+	/* zero the stale part of the page if we did a short copy */
+	if (copied < len) {
+		void *kaddr = kmap_atomic(page, KM_USER0);
+		memset(kaddr + from + copied, 0, len - copied);
+		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
+	}
+
+	simple_commit_write(file, page, from, from+copied);
+
+	unlock_page(page);
+	page_cache_release(page);
+
+	return copied;
+}
+EXPORT_SYMBOL(simple_write_end);
+
+ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
+				const void *from, size_t available)
+{
+	loff_t pos = *ppos;
+	if (pos < 0)
+		return -EINVAL;
+	if (pos >= available)
+		return 0;
+	if (count > available - pos)
+		count = available - pos;
+	if (copy_to_user(to, from + pos, count))
+		return -EFAULT;
+	*ppos = pos + count;
+	return count;
+}
+EXPORT_SYMBOL(simple_read_from_buffer);

-- 


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

* Re: [RFC 00/11] possible debugfs/libfs consolidation
  2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
                   ` (10 preceding siblings ...)
  2008-02-19  4:04 ` [RFC 11/11] split out libfs/aops.c " Arnd Bergmann
@ 2008-02-19 16:38 ` Greg KH
  11 siblings, 0 replies; 22+ messages in thread
From: Greg KH @ 2008-02-19 16:38 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-fsdevel, Alexander Viro, Christoph Hellwig,
	David Howells

On Tue, Feb 19, 2008 at 05:04:35AM +0100, Arnd Bergmann wrote:
> I noticed that there is a lot of duplication in pseudo
> file systems, so I started looking into how to consolidate
> them. I ended up with a largish rework of the structure
> of libfs and moving almost all of debugfs in there as well.
> 
> As an example, I also have patches that reduce debugfs,
> securityfs and usbfs to the point where they are mostly
> thin wrappers around libfs, with large comment blocks.
> Other file systems could be changed in the same way, but
> I first like to see if people agree that I'm on the right
> track.

I like the idea, and have no objection to these patches at all.  Please
feel free to test them and send them again :)

thanks,

greg k-h

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

* Re: [RFC 01/11] add generic versions of debugfs file operations
  2008-02-19  4:04 ` [RFC 01/11] add generic versions of debugfs file operations Arnd Bergmann
@ 2008-02-23 12:24   ` Al Viro
  2008-02-24 10:46     ` Arnd Bergmann
  2008-02-23 12:33   ` Al Viro
  1 sibling, 1 reply; 22+ messages in thread
From: Al Viro @ 2008-02-23 12:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Tue, Feb 19, 2008 at 05:04:36AM +0100, Arnd Bergmann wrote:
> +	char buf[3];
> +	u32 *val = file->private_data;
> +
> +	if (*val)
> +		buf[0] = 'Y';
> +	else
> +		buf[0] = 'N';
> +	buf[1] = '\n';
> +	buf[2] = 0x00;
> +	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);

Ewww - caps, \n...  BTW, \0 is pointless here - simple_read_from_buffer() will
not access it with these arguments)...

> +{
> +	char buf[32];
> +	int buf_size;
> +	u32 *val = file->private_data;
> +
> +	buf_size = min(count, (sizeof(buf)-1));
> +	if (copy_from_user(buf, user_buf, buf_size))
> +		return -EFAULT;
> +
> +	switch (buf[0]) {
> +	case 'y':
> +	case 'Y':
> +	case '1':
> +		*val = 1;
> +		break;
> +	case 'n':
> +	case 'N':
> +	case '0':
> +		*val = 0;
> +		break;

Please, check the length; sloppy input grammar is a bad idea.  Hell, at the
very least you want -EINVAL if input is not recognized...

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

* Re: [RFC 02/11] introduce simple_fs_type
  2008-02-19  4:04 ` [RFC 02/11] introduce simple_fs_type Arnd Bergmann
@ 2008-02-23 12:28   ` Al Viro
  2008-02-24 10:55     ` Arnd Bergmann
  0 siblings, 1 reply; 22+ messages in thread
From: Al Viro @ 2008-02-23 12:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Tue, Feb 19, 2008 at 05:04:37AM +0100, Arnd Bergmann wrote:
> There is a number of pseudo file systems in the kernel
> that are basically copies of debugfs, all implementing the
> same boilerplate code, just with different bugs.
> 
> This adds yet another copy to the kernel in the libfs directory,
> with generalized helpers that can be used by any of them.
> 
> The most interesting function here is the new "struct dentry *
> simple_register_filesystem(struct simple_fs_type *type)", which
> returns the root directory of a new file system that can then
> be passed to simple_create_file() and similar functions as a
> parent.

Don't mix "split the file" with "add new stuff", please.  And frankly,
I'm not convinced that embedding file_system_type into another struct
is a good idea.

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

* Re: [RFC 01/11] add generic versions of debugfs file operations
  2008-02-19  4:04 ` [RFC 01/11] add generic versions of debugfs file operations Arnd Bergmann
  2008-02-23 12:24   ` Al Viro
@ 2008-02-23 12:33   ` Al Viro
  1 sibling, 0 replies; 22+ messages in thread
From: Al Viro @ 2008-02-23 12:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Tue, Feb 19, 2008 at 05:04:36AM +0100, Arnd Bergmann wrote:
> The file operations in debugfs are rather generic and can
> be used by other file systems, so it can be interesting to
> include them in libfs, with more generic names, and exported
> to modules.
> 
> This patch adds a new copy of these operations to libfs,
> so that the debugfs version can later be cut down.

BTW, where does CONFIG_LIBFS come from?

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

* Re: [RFC 03/11] slim down debugfs
  2008-02-19  4:04 ` [RFC 03/11] slim down debugfs Arnd Bergmann
@ 2008-02-23 12:37   ` Al Viro
  2008-02-23 19:55     ` Hugh Dickins
  2008-02-24 10:59     ` Arnd Bergmann
  0 siblings, 2 replies; 22+ messages in thread
From: Al Viro @ 2008-02-23 12:37 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Tue, Feb 19, 2008 at 05:04:38AM +0100, Arnd Bergmann wrote:
> With most of debugfs now copied to generic code in libfs,
> we can remove the original copy and replace it with thin
> wrappers around libfs.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Index: linux-2.6/fs/Kconfig
> ===================================================================
> --- linux-2.6.orig/fs/Kconfig
> +++ linux-2.6/fs/Kconfig
> @@ -1001,6 +1001,14 @@ config CONFIGFS_FS
>  	  Both sysfs and configfs can and should exist together on the
>  	  same system. One is not a replacement for the other.
>  
> +config LIBFS
> +	tristate
> +	default m
> +	help
> +	  libfs is a helper library used by many of the simpler file
> +	  systems. Parts of libfs can be modular when all of its users
> +	  are modules as well, and the users should select this symbol.

NAK.  For one thing, you need dependencies or selects and none of the
patches later in the series introduces them.  For another, neither
dependencies nor selects work well if you have non-modular users of
that sucker.  Seriously, try to add those and do allmodconfig.  Then
look what a mess it produces.

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

* Re: [RFC 03/11] slim down debugfs
  2008-02-23 12:37   ` Al Viro
@ 2008-02-23 19:55     ` Hugh Dickins
  2008-02-24 10:59     ` Arnd Bergmann
  1 sibling, 0 replies; 22+ messages in thread
From: Hugh Dickins @ 2008-02-23 19:55 UTC (permalink / raw)
  To: Al Viro
  Cc: Arnd Bergmann, linux-kernel, linux-fsdevel, Christoph Hellwig,
	Greg KH, David Howells

On Sat, 23 Feb 2008, Al Viro wrote:
> On Tue, Feb 19, 2008 at 05:04:38AM +0100, Arnd Bergmann wrote:
> > With most of debugfs now copied to generic code in libfs,
> > we can remove the original copy and replace it with thin
> > wrappers around libfs.
> > 
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > Index: linux-2.6/fs/Kconfig
> > ===================================================================
> > --- linux-2.6.orig/fs/Kconfig
> > +++ linux-2.6/fs/Kconfig
> > @@ -1001,6 +1001,14 @@ config CONFIGFS_FS
> >  	  Both sysfs and configfs can and should exist together on the
> >  	  same system. One is not a replacement for the other.
> >  
> > +config LIBFS
> > +	tristate
> > +	default m
> > +	help
> > +	  libfs is a helper library used by many of the simpler file
> > +	  systems. Parts of libfs can be modular when all of its users
> > +	  are modules as well, and the users should select this symbol.
> 
> NAK.  For one thing, you need dependencies or selects and none of the
> patches later in the series introduces them.  For another, neither
> dependencies nor selects work well if you have non-modular users of
> that sucker.  Seriously, try to add those and do allmodconfig.  Then
> look what a mess it produces.

For sure.  Luckily, ramfs makes extensive use of simple_ libfs functions
(ramfs is where they came from originally), and is always configured in,
so libfs should always be in (unless Arnd's patches change things around
and ramfs no longer uses it).

Hugh

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

* Re: [RFC 01/11] add generic versions of debugfs file operations
  2008-02-23 12:24   ` Al Viro
@ 2008-02-24 10:46     ` Arnd Bergmann
  2008-02-24 18:00       ` Greg KH
  0 siblings, 1 reply; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-24 10:46 UTC (permalink / raw)
  To: Al Viro
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Saturday 23 February 2008, Al Viro wrote:

> Ewww - caps, \n...  BTW, \0 is pointless here - simple_read_from_buffer() will
> not access it with these arguments)...

> ... 

> Please, check the length; sloppy input grammar is a bad idea.  Hell, at the
> very least you want -EINVAL if input is not recognized...

Ok, these two come straight from debugfs, but of course I can fix them
anyway. Should I do a fix for debugfs in 2.6.25 first, or rather do a
patch on top of the libfs rework?

I'd rather not have any semantic changes during the conversion, so
it would be better to keep that separate imho.

	Arnd <><

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

* Re: [RFC 02/11] introduce simple_fs_type
  2008-02-23 12:28   ` Al Viro
@ 2008-02-24 10:55     ` Arnd Bergmann
  0 siblings, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-24 10:55 UTC (permalink / raw)
  To: Al Viro
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Saturday 23 February 2008, Al Viro wrote:
> On Tue, Feb 19, 2008 at 05:04:37AM +0100, Arnd Bergmann wrote:
> > The most interesting function here is the new "struct dentry *
> > simple_register_filesystem(struct simple_fs_type *type)", which
> > returns the root directory of a new file system that can then
> > be passed to simple_create_file() and similar functions as a
> > parent.
> 
> Don't mix "split the file" with "add new stuff", please. 

Ok, I'll introduce it in libfs.c first then.

> And frankly, I'm not convinced that embedding file_system_type
> into another struct is a good idea.

Right, that has been one of the areas I've been thinking about
myself without coming to a good solution. One alternative I
thought about is to have the news members as part of file_system_type
itself, but that would cost a bit of memory for every single 
file system, and might lead to unintended misuse of these members
by non-simple file systems.

Do you think it would be better to dynamically allocate the
file_system_type and have a pointer in struct simple_fs_type to
it?

	Arnd <><

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

* Re: [RFC 03/11] slim down debugfs
  2008-02-23 12:37   ` Al Viro
  2008-02-23 19:55     ` Hugh Dickins
@ 2008-02-24 10:59     ` Arnd Bergmann
  1 sibling, 0 replies; 22+ messages in thread
From: Arnd Bergmann @ 2008-02-24 10:59 UTC (permalink / raw)
  To: Al Viro
  Cc: linux-kernel, linux-fsdevel, Christoph Hellwig, Greg KH, David Howells

On Saturday 23 February 2008, Al Viro wrote:
> > +config LIBFS
> > +     tristate
> > +     default m
> > +     help
> > +       libfs is a helper library used by many of the simpler file
> > +       systems. Parts of libfs can be modular when all of its users
> > +       are modules as well, and the users should select this symbol.
> 
> NAK.  For one thing, you need dependencies or selects and none of the
> patches later in the series introduces them.  For another, neither
> dependencies nor selects work well if you have non-modular users of
> that sucker.  Seriously, try to add those and do allmodconfig.  Then
> look what a mess it produces.

Sorry about that hunk, I didn't mean to keep that in there. In
my testing, I used the newly introduced parts as a loadable
module, and at one point the intention was to keep the existing
libfs functions as builtin and add a new Kconfig dependency in every
user of the new stuff whenever a file system gets converted.

I figured out later that hardly anyone could even try to build
without them as soon as all the trival file systems are moved
over, but forgot to make it always builtin.

	Arnd <><

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

* Re: [RFC 01/11] add generic versions of debugfs file operations
  2008-02-24 10:46     ` Arnd Bergmann
@ 2008-02-24 18:00       ` Greg KH
  0 siblings, 0 replies; 22+ messages in thread
From: Greg KH @ 2008-02-24 18:00 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Al Viro, linux-kernel, linux-fsdevel, Christoph Hellwig, David Howells

On Sun, Feb 24, 2008 at 11:46:07AM +0100, Arnd Bergmann wrote:
> On Saturday 23 February 2008, Al Viro wrote:
> 
> > Ewww - caps, \n...  BTW, \0 is pointless here - simple_read_from_buffer() will
> > not access it with these arguments)...
> 
> > ... 
> 
> > Please, check the length; sloppy input grammar is a bad idea.  Hell, at the
> > very least you want -EINVAL if input is not recognized...
> 
> Ok, these two come straight from debugfs, but of course I can fix them
> anyway. Should I do a fix for debugfs in 2.6.25 first, or rather do a
> patch on top of the libfs rework?

I'll gladly take a patch to debugfs for it :)

thanks,

greg k-h

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

end of thread, other threads:[~2008-02-24 18:01 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-19  4:04 [RFC 00/11] possible debugfs/libfs consolidation Arnd Bergmann
2008-02-19  4:04 ` [RFC 01/11] add generic versions of debugfs file operations Arnd Bergmann
2008-02-23 12:24   ` Al Viro
2008-02-24 10:46     ` Arnd Bergmann
2008-02-24 18:00       ` Greg KH
2008-02-23 12:33   ` Al Viro
2008-02-19  4:04 ` [RFC 02/11] introduce simple_fs_type Arnd Bergmann
2008-02-23 12:28   ` Al Viro
2008-02-24 10:55     ` Arnd Bergmann
2008-02-19  4:04 ` [RFC 03/11] slim down debugfs Arnd Bergmann
2008-02-23 12:37   ` Al Viro
2008-02-23 19:55     ` Hugh Dickins
2008-02-24 10:59     ` Arnd Bergmann
2008-02-19  4:04 ` [RFC 04/11] slim down securityfs Arnd Bergmann
2008-02-19  4:04 ` [RFC 05/11] slim down usbfs Arnd Bergmann
2008-02-19  4:04 ` [RFC 06/11] split out linux/libfs.h from linux/fs.h Arnd Bergmann
2008-02-19  4:04 ` [RFC 07/11] split out libfs/file.c from libfs.c Arnd Bergmann
2008-02-19  4:04 ` [RFC 08/11] split out libfs/dentry.c " Arnd Bergmann
2008-02-19  4:04 ` [RFC 09/11] split out libfs/super.c " Arnd Bergmann
2008-02-19  4:04 ` [RFC 10/11] split out libfs/inode.c " Arnd Bergmann
2008-02-19  4:04 ` [RFC 11/11] split out libfs/aops.c " Arnd Bergmann
2008-02-19 16:38 ` [RFC 00/11] possible debugfs/libfs consolidation Greg KH

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).