LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [patch 1/13] signal/timer/event fds v6 - anonymous inode source ...
@ 2007-03-16 0:22 Davide Libenzi
2007-03-17 20:58 ` Arnd Bergmann
0 siblings, 1 reply; 3+ messages in thread
From: Davide Libenzi @ 2007-03-16 0:22 UTC (permalink / raw)
To: Linux Kernel Mailing List
Cc: Andrew Morton, Linus Torvalds, Thomas Gleixner, Oleg Nesterov
This patch add an anonymous inode source, to be used for files that need
and inode only in order to create a file*. We do not care of having an
inode for each file, and we do not even care of having different names in
the associated dentries (dentry names will be same for classes of file*).
This allow code reuse, and will be used by epoll, signalfd and timerfd
(and whatever else there'll be).
Signed-off-by: Davide Libenzi <davidel@xmailserver.org>
- Davide
Index: linux-2.6.21-rc3.quilt/fs/anon_inodes.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21-rc3.quilt/fs/anon_inodes.c 2007-03-15 15:32:33.000000000 -0700
@@ -0,0 +1,203 @@
+/*
+ * fs/anon_inodes.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/magic.h>
+#include <linux/anon_inodes.h>
+
+#include <asm/uaccess.h>
+
+
+
+static int ainofs_delete_dentry(struct dentry *dentry);
+static struct inode *aino_getinode(void);
+static struct inode *aino_mkinode(void);
+static int ainofs_get_sb(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data, struct vfsmount *mnt);
+
+
+
+static struct vfsmount *aino_mnt __read_mostly;
+static struct inode *aino_inode;
+static struct file_operations aino_fops = { };
+static struct file_system_type aino_fs_type = {
+ .name = "ainofs",
+ .get_sb = ainofs_get_sb,
+ .kill_sb = kill_anon_super,
+};
+static struct dentry_operations ainofs_dentry_operations = {
+ .d_delete = ainofs_delete_dentry,
+};
+
+
+
+int aino_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+ char const *name, const struct file_operations *fops, void *priv)
+{
+ struct qstr this;
+ struct dentry *dentry;
+ struct inode *inode;
+ struct file *file;
+ int error, fd;
+
+ error = -ENFILE;
+ file = get_empty_filp();
+ if (!file)
+ goto eexit_1;
+
+ inode = aino_getinode();
+ if (IS_ERR(inode)) {
+ error = PTR_ERR(inode);
+ goto eexit_2;
+ }
+
+ error = get_unused_fd();
+ if (error < 0)
+ goto eexit_3;
+ fd = error;
+
+ /*
+ * Link the inode to a directory entry by creating a unique name
+ * using the inode sequence number.
+ */
+ error = -ENOMEM;
+ this.name = name;
+ this.len = strlen(name);
+ this.hash = 0;
+ dentry = d_alloc(aino_mnt->mnt_sb->s_root, &this);
+ if (!dentry)
+ goto eexit_4;
+ dentry->d_op = &ainofs_dentry_operations;
+ /* Do not publish this dentry inside the global dentry hash table */
+ dentry->d_flags &= ~DCACHE_UNHASHED;
+ d_instantiate(dentry, inode);
+
+ file->f_path.mnt = mntget(aino_mnt);
+ file->f_path.dentry = dentry;
+ file->f_mapping = inode->i_mapping;
+
+ file->f_pos = 0;
+ file->f_flags = O_RDWR;
+ file->f_op = fops;
+ file->f_mode = FMODE_READ | FMODE_WRITE;
+ file->f_version = 0;
+ file->private_data = priv;
+
+ fd_install(fd, file);
+
+ *pfd = fd;
+ *pinode = inode;
+ *pfile = file;
+ return 0;
+
+eexit_4:
+ put_unused_fd(fd);
+eexit_3:
+ iput(inode);
+eexit_2:
+ put_filp(file);
+eexit_1:
+ return error;
+}
+
+
+static int ainofs_delete_dentry(struct dentry *dentry)
+{
+ /*
+ * We faked vfs to believe the dentry was hashed when we created it.
+ * Now we restore the flag so that dput() will work correctly.
+ */
+ dentry->d_flags |= DCACHE_UNHASHED;
+ return 1;
+}
+
+
+static struct inode *aino_getinode(void)
+{
+ return igrab(aino_inode);
+}
+
+
+/*
+ * A single inode exist for all aino files. On the contrary of pipes,
+ * aino inodes has no per-instance data associated, so we can avoid
+ * the allocation of multiple of them.
+ */
+static struct inode *aino_mkinode(void)
+{
+ int error = -ENOMEM;
+ struct inode *inode = new_inode(aino_mnt->mnt_sb);
+
+ if (!inode)
+ goto eexit_1;
+
+ inode->i_fop = &aino_fops;
+
+ /*
+ * Mark the inode dirty from the very beginning,
+ * that way it will never be moved to the dirty
+ * list because mark_inode_dirty() will think
+ * that it already _is_ on the dirty list.
+ */
+ inode->i_state = I_DIRTY;
+ inode->i_mode = S_IRUSR | S_IWUSR;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ return inode;
+
+eexit_1:
+ return ERR_PTR(error);
+}
+
+
+static int ainofs_get_sb(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data, struct vfsmount *mnt)
+{
+ return get_sb_pseudo(fs_type, "aino:", NULL, AINOFS_MAGIC, mnt);
+}
+
+
+static int __init aino_init(void)
+{
+
+ if (register_filesystem(&aino_fs_type))
+ goto epanic;
+
+ aino_mnt = kern_mount(&aino_fs_type);
+ if (IS_ERR(aino_mnt))
+ goto epanic;
+
+ aino_inode = aino_mkinode();
+ if (IS_ERR(aino_inode))
+ goto epanic;
+
+ return 0;
+
+epanic:
+ panic("aino_init() failed\n");
+}
+
+
+static void __exit aino_exit(void)
+{
+ iput(aino_inode);
+ unregister_filesystem(&aino_fs_type);
+ mntput(aino_mnt);
+}
+
+module_init(aino_init);
+module_exit(aino_exit);
+
+MODULE_LICENSE("GPL");
Index: linux-2.6.21-rc3.quilt/include/linux/anon_inodes.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21-rc3.quilt/include/linux/anon_inodes.h 2007-03-15 15:32:33.000000000 -0700
@@ -0,0 +1,15 @@
+/*
+ * include/linux/anon_inodes.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_ANON_INODES_H
+#define _LINUX_ANON_INODES_H
+
+int aino_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+ char const *name, const struct file_operations *fops, void *priv);
+
+#endif /* _LINUX_ANON_INODES_H */
+
Index: linux-2.6.21-rc3.quilt/fs/Makefile
===================================================================
--- linux-2.6.21-rc3.quilt.orig/fs/Makefile 2007-03-15 15:19:22.000000000 -0700
+++ linux-2.6.21-rc3.quilt/fs/Makefile 2007-03-15 15:32:33.000000000 -0700
@@ -11,7 +11,7 @@
attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
seq_file.o xattr.o libfs.o fs-writeback.o \
pnode.o drop_caches.o splice.o sync.o utimes.o \
- stack.o
+ stack.o anon_inodes.o
ifeq ($(CONFIG_BLOCK),y)
obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
Index: linux-2.6.21-rc3.quilt/include/linux/magic.h
===================================================================
--- linux-2.6.21-rc3.quilt.orig/include/linux/magic.h 2007-03-15 15:19:22.000000000 -0700
+++ linux-2.6.21-rc3.quilt/include/linux/magic.h 2007-03-15 15:33:16.000000000 -0700
@@ -14,6 +14,7 @@
#define ISOFS_SUPER_MAGIC 0x9660
#define JFFS2_SUPER_MAGIC 0x72b6
#define KVMFS_SUPER_MAGIC 0x19700426
+#define AINOFS_MAGIC 0x09041934
#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [patch 1/13] signal/timer/event fds v6 - anonymous inode source ...
2007-03-16 0:22 [patch 1/13] signal/timer/event fds v6 - anonymous inode source Davide Libenzi
@ 2007-03-17 20:58 ` Arnd Bergmann
2007-03-18 20:11 ` Davide Libenzi
0 siblings, 1 reply; 3+ messages in thread
From: Arnd Bergmann @ 2007-03-17 20:58 UTC (permalink / raw)
To: Davide Libenzi
Cc: Linux Kernel Mailing List, Andrew Morton, Linus Torvalds,
Thomas Gleixner, Oleg Nesterov
On Friday 16 March 2007 01:22:15 Davide Libenzi wrote:
> +
> +static int ainofs_delete_dentry(struct dentry *dentry);
> +static struct inode *aino_getinode(void);
> +static struct inode *aino_mkinode(void);
> +static int ainofs_get_sb(struct file_system_type *fs_type, int flags,
> + const char *dev_name, void *data, struct vfsmount *mnt);
> +
In general, it would be good if you could just reorder your functions
so that you don't need any forward declarations like these. It makes
reviewing from bottom to top a little easier and it becomes obvious
that there are no recursions in the code.
> +static struct vfsmount *aino_mnt __read_mostly;
> +static struct inode *aino_inode;
> +static struct file_operations aino_fops = { };
Iirc, file_operations should be const.
> +int aino_getfd(int *pfd, struct inode **pinode, struct file **pfile,
> + char const *name, const struct file_operations *fops, void *priv)
> +{
Since this is meant to be a generic interface that can be used
from other subsystems, a kerneldoc style comment would be nice
> +static int __init aino_init(void)
> +{
> +
> + if (register_filesystem(&aino_fs_type))
> + goto epanic;
> +
> + aino_mnt = kern_mount(&aino_fs_type);
> + if (IS_ERR(aino_mnt))
> + goto epanic;
> +
> + aino_inode = aino_mkinode();
> + if (IS_ERR(aino_inode))
> + goto epanic;
> +
> + return 0;
> +
> +epanic:
> + panic("aino_init() failed\n");
> +}
panic() is a little harsh from a loadable module. If you mean
the aino support to be used as a module, this should probably
just return an error.
> +static void __exit aino_exit(void)
> +{
> + iput(aino_inode);
> + unregister_filesystem(&aino_fs_type);
> + mntput(aino_mnt);
> +}
but since the Makefile always has it as built-in, maybe you should
instead just kill the exit function and use fs_initcall instead
of init_module().
Arnd <><
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [patch 1/13] signal/timer/event fds v6 - anonymous inode source ...
2007-03-17 20:58 ` Arnd Bergmann
@ 2007-03-18 20:11 ` Davide Libenzi
0 siblings, 0 replies; 3+ messages in thread
From: Davide Libenzi @ 2007-03-18 20:11 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Linux Kernel Mailing List, Andrew Morton, Linus Torvalds,
Thomas Gleixner, Oleg Nesterov
On Sat, 17 Mar 2007, Arnd Bergmann wrote:
> On Friday 16 March 2007 01:22:15 Davide Libenzi wrote:
>
> > +
> > +static int ainofs_delete_dentry(struct dentry *dentry);
> > +static struct inode *aino_getinode(void);
> > +static struct inode *aino_mkinode(void);
> > +static int ainofs_get_sb(struct file_system_type *fs_type, int flags,
> > + const char *dev_name, void *data, struct vfsmount *mnt);
> > +
>
> In general, it would be good if you could just reorder your functions
> so that you don't need any forward declarations like these. It makes
> reviewing from bottom to top a little easier and it becomes obvious
> that there are no recursions in the code.
I personally prefer to have them always on top so I don't have to figure
out where to place a new function, or to re-arrange the order of the
functions if the implementation changes. Plus I like to keep all the data
declarations on top, and this would still require some of the
static functions declarations to preceed it in any case. I really don't
want to waste time with counter-argouments that are most definitely a
personal taste, so if lots of ppl feel raw about that, and it goes in the
coding standard, I'll be happily change it.
> > +static struct vfsmount *aino_mnt __read_mostly;
> > +static struct inode *aino_inode;
> > +static struct file_operations aino_fops = { };
>
> Iirc, file_operations should be const.
Ack! It should, yes.
> > +int aino_getfd(int *pfd, struct inode **pinode, struct file **pfile,
> > + char const *name, const struct file_operations *fops, void *priv)
> > +{
>
> Since this is meant to be a generic interface that can be used
> from other subsystems, a kerneldoc style comment would be nice
Done!
> > +static int __init aino_init(void)
> > +{
> > +
> > + if (register_filesystem(&aino_fs_type))
> > + goto epanic;
> > +
> > + aino_mnt = kern_mount(&aino_fs_type);
> > + if (IS_ERR(aino_mnt))
> > + goto epanic;
> > +
> > + aino_inode = aino_mkinode();
> > + if (IS_ERR(aino_inode))
> > + goto epanic;
> > +
> > + return 0;
> > +
> > +epanic:
> > + panic("aino_init() failed\n");
> > +}
>
> panic() is a little harsh from a loadable module. If you mean
> the aino support to be used as a module, this should probably
> just return an error.
>
> > +static void __exit aino_exit(void)
> > +{
> > + iput(aino_inode);
> > + unregister_filesystem(&aino_fs_type);
> > + mntput(aino_mnt);
> > +}
>
> but since the Makefile always has it as built-in, maybe you should
> instead just kill the exit function and use fs_initcall instead
> of init_module().
Indeed, it can't be a module, so no exit function and fs_initcall.
Thx!
- Davide
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-03-18 20:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-16 0:22 [patch 1/13] signal/timer/event fds v6 - anonymous inode source Davide Libenzi
2007-03-17 20:58 ` Arnd Bergmann
2007-03-18 20:11 ` Davide Libenzi
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).