Daniel Phillips <phill...@phunq.net> writes:

> Here is my original ddlink writeup, posted a year ago:
>
>    "An alternative interface to device mapper"
>    http://lwn.net/Articles/271805/

I converted the fd allocation code to anon_inode_getfd(). It may clear
the point of ddlink. Well, anyway, the patches is the following.

Thanks.


diff -puN user/kernel/inode.c~ddlink-whitespace user/kernel/inode.c
--- tux3/user/kernel/inode.c~ddlink-whitespace	2009-02-26 18:43:28.000000000 +0900
+++ tux3-hirofumi/user/kernel/inode.c	2009-02-26 18:43:33.000000000 +0900
@@ -410,7 +410,7 @@ static struct file_operations ddlink_exa
 
 long tux3_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-        if (cmd == DDLINK)
+	if (cmd == DDLINK)
 		return ddlink(&ddlink_example_fops, NULL, NULL);
 	return -ENOTTY;
 }
diff -puN user/kernel/namei.c~ddlink-whitespace user/kernel/namei.c
diff -puN user/kernel/ddlink.h~ddlink-whitespace user/kernel/ddlink.h
--- tux3/user/kernel/ddlink.h~ddlink-whitespace	2009-02-26 18:43:55.000000000 +0900
+++ tux3-hirofumi/user/kernel/ddlink.h	2009-02-26 18:43:58.000000000 +0900
@@ -21,7 +21,7 @@ struct ddinode {
 
 static inline struct ddinode *ddinode(struct inode *inode)
 {
-	return container_of(inode, struct ddinode, inode); 
+	return container_of(inode, struct ddinode, inode);
 }
 
 static inline void *ddinfo(struct inode *inode)
diff -puN user/kernel/ddlink.c~ddlink-whitespace user/kernel/ddlink.c
--- tux3/user/kernel/ddlink.c~ddlink-whitespace	2009-02-26 18:44:04.000000000 +0900
+++ tux3-hirofumi/user/kernel/ddlink.c	2009-02-26 18:44:08.000000000 +0900
@@ -296,8 +296,8 @@ void *ddlink_example_create(struct ddino
 
 long example_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-        switch (cmd) {
-        case DDLINK:
+	switch (cmd) {
+	case DDLINK:
 		return ddlink(&ddlink_example_fops, ddlink_example_create, NULL);
 	}
 	return -ENOTTY;
_

diff -puN user/kernel/ddlink.h~use-filp user/kernel/ddlink.h
--- tux3/user/kernel/ddlink.h~use-filp	2009-02-26 18:44:26.000000000 +0900
+++ tux3-hirofumi/user/kernel/ddlink.h	2009-02-26 18:51:36.000000000 +0900
@@ -10,35 +10,36 @@ struct dditem {
 	unsigned char data[];
 };
 
-struct ddinode {
+struct ddctl {
 	struct list_head list;
 	wait_queue_head_t wait;
 	typeof(kmalloc) *create_item;
 	typeof(kfree) *destroy_item;
 	typeof(kfree) *destroy_info;
-	struct inode inode;
+	void *private;
 };
 
-static inline struct ddinode *ddinode(struct inode *inode)
+static inline struct ddctl *ddctl(struct file *file)
 {
-	return container_of(inode, struct ddinode, inode);
+	return file->private_data;
 }
 
-static inline void *ddinfo(struct inode *inode)
+static inline void *ddinfo(struct ddctl *dd)
 {
-	return inode->i_private;
+	return dd->private;
 }
 
-int ddlink(struct file_operations *fops, void *(*create)(struct ddinode *dd, void *info), void *info);
-void ddlink_queue(struct ddinode *dd, struct dditem *item);
-void ddlink_push(struct ddinode *dd, struct dditem *item);
-struct dditem *ddlink_pop(struct ddinode *dd);
-struct dditem *dditem_new(struct ddinode *dd, size_t size);
-void ddlink_clear(struct ddinode *dd);
-int ddlink_ready(struct ddinode *dd);
+int ddlink_file_release(struct inode *inode, struct file *filp);
+int ddlink(const struct file_operations *fops, void *(*create)(struct ddctl *dd, void *info), void *info);
+void ddlink_queue(struct ddctl *dd, struct dditem *item);
+void ddlink_push(struct ddctl *dd, struct dditem *item);
+struct dditem *ddlink_pop(struct ddctl *dd);
+struct dditem *dditem_new(struct ddctl *dd, size_t size);
+void ddlink_clear(struct ddctl *dd);
+int ddlink_ready(struct ddctl *dd);
 
-struct dditem *dditem_in(struct ddinode *dd, const void *buf, size_t len, int z);
-int dditem_out(struct ddinode *dd, void *buf, size_t len, struct dditem *item);
-int ddlink_post(struct ddinode *dd, void *data, unsigned len);
+struct dditem *dditem_in(struct ddctl *dd, const void *buf, size_t len, int z);
+int dditem_out(struct ddctl *dd, void *buf, size_t len, struct dditem *item);
+int ddlink_post(struct ddctl *dd, void *data, unsigned len);
 unsigned ddlink_poll(struct file *file, poll_table *table);
-int ddlink_error(struct ddinode *dd, int err, const char *fmt, ...);
+int ddlink_error(struct ddctl *dd, int err, const char *fmt, ...);
diff -puN user/kernel/ddlink.c~use-filp user/kernel/ddlink.c
--- tux3/user/kernel/ddlink.c~use-filp	2009-02-26 18:44:26.000000000 +0900
+++ tux3-hirofumi/user/kernel/ddlink.c	2009-02-26 18:53:13.000000000 +0900
@@ -2,6 +2,7 @@
 #include <linux/poll.h>
 #include <linux/mount.h>
 #include <linux/module.h>
+#include <linux/anon_inodes.h>
 #include "ddlink.h"
 
 /*
@@ -14,13 +15,13 @@
 // To do:
 //  * need spinlocks on push, pop, queue, ready and ???
 
-int ddlink_ready(struct ddinode *dd)
+int ddlink_ready(struct ddctl *dd)
 {
 	return !list_empty(&dd->list);
 }
 EXPORT_SYMBOL_GPL(ddlink_ready);
 
-struct dditem *ddlink_pop(struct ddinode *dd)
+struct dditem *ddlink_pop(struct ddctl *dd)
 {
 	struct dditem *item;
 	BUG_ON(!ddlink_ready(dd));
@@ -30,147 +31,88 @@ struct dditem *ddlink_pop(struct ddinode
 }
 EXPORT_SYMBOL_GPL(ddlink_pop);
 
-void ddlink_clear(struct ddinode *dd)
+void ddlink_clear(struct ddctl *dd)
 {
 	while (ddlink_ready(dd))
 		dd->destroy_item(ddlink_pop(dd));
 }
 EXPORT_SYMBOL_GPL(ddlink_clear);
 
-static struct inode *ddlink_alloc_inode(struct super_block *sb)
+static struct ddctl *ddlink_alloc_ddctl(void)
 {
-	struct ddinode *dd = kmalloc(sizeof(struct ddinode), GFP_KERNEL);
+	struct ddctl *dd = kmalloc(sizeof(struct ddctl), GFP_KERNEL);
 	if (!dd)
 		return NULL;
 	*dd = (typeof(*dd)){
 		.wait = __WAIT_QUEUE_HEAD_INITIALIZER(dd->wait),
 		.list = LIST_HEAD_INIT(dd->list) };
-	inode_init_once(&dd->inode);
-	return &dd->inode;
+	return dd;
 }
 
-static void ddlink_free_inode(struct inode *inode)
+static void ddlink_free_ddctl(struct ddctl *dd)
 {
-	struct ddinode *dd = ddinode(inode);
 	ddlink_clear(dd);
-	if (ddinfo(inode))
-		dd->destroy_info(ddinfo(inode));
-	kfree(ddinode(inode));
+	if (ddinfo(dd))
+		dd->destroy_info(ddinfo(dd));
+	kfree(dd);
 }
 
-static struct super_operations ddlink_sops = {
-	.alloc_inode = ddlink_alloc_inode,
-	.destroy_inode = ddlink_free_inode
-};
-
-static struct vfsmount *ddlink_mnt;
-
-static int ddlink_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+int ddlink_file_release(struct inode *inode, struct file *filp)
 {
-	return get_sb_pseudo(fs_type, "ddlink", &ddlink_sops, 0x20070318, mnt);
+	ddlink_free_ddctl(ddctl(filp));
+	return 0;
 }
+EXPORT_SYMBOL_GPL(ddlink_file_release);
 
-static struct file_system_type ddlink_type = {
-	.name = "ddlink",
-	.get_sb = ddlink_get_sb,
-	.kill_sb = kill_anon_super };
-
-static int ddlink_delete_dentry(struct dentry *dentry) { return 1; } // vfs bogon
-static struct dentry_operations ddlink_dops = { .d_delete = ddlink_delete_dentry };
-
-int ddlink(struct file_operations *fops, void *(*create)(struct ddinode *dd, void *info), void *info)
+int ddlink(const struct file_operations *fops, void *(*create)(struct ddctl *dd, void *info), void *info)
 {
-	int err = -ENFILE, fd;
-	struct file *file = get_empty_filp();
-	struct inode *inode;
-	struct dentry *dentry;
+	struct ddctl *dd;
 	void *private = NULL;
+	int err;
+
+	BUG_ON(!fops->release);
+
+	dd = ddlink_alloc_ddctl();
+	if (!dd)
+		return -ENOMEM;
+	dd->destroy_info = kfree;
+	dd->create_item = kmalloc;
+	dd->destroy_item = kfree;
 
-	if (!file)
-		goto no_file;
-	inode = new_inode(ddlink_mnt->mnt_sb);
-	if (!inode)
-		goto no_inode;
-	ddinode(inode)->destroy_info = kfree;
-	ddinode(inode)->create_item = kmalloc;
-	ddinode(inode)->destroy_item = kfree;
-	if (create && IS_ERR(private = create(ddinode(inode), info))) {
+	if (create && IS_ERR(private = create(dd, info))) {
 		err = PTR_ERR(private);
-		goto no_inode;
+		goto error;
 	}
-	inode->i_private = private;
+	dd->private = private;
 
-	dentry = d_alloc(ddlink_mnt->mnt_sb->s_root, &(struct qstr){ });
-	if (!dentry)
-		goto no_dentry;
-	if ((fd = err = get_unused_fd()) < 0)
-		goto no_fd;
-	/* Mark inode dirty so it will not be moved to the dirty list */
-	inode->i_state = I_DIRTY;
-	inode->i_mode = S_IFCHR|S_IRWXUGO;
-	inode->i_uid = current_fsuid();
-	inode->i_gid = current_fsgid();
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_fop = fops;
-	dentry->d_op = &ddlink_dops;
-	d_instantiate(dentry, inode); // d_add?
-
-	file->f_dentry = dentry;
-	file->f_vfsmnt = mntget(ddlink_mnt);
-	file->f_mapping = inode->i_mapping;
-	file->f_mode = FMODE_READ|FMODE_WRITE;
-//	file->f_flags = O_RDWR; // not used yet
-	file->f_op = inode->i_fop;
-	fd_install(fd, file);
-	return fd;
-no_fd:
-	dput(dentry);
-no_dentry:
-	iput(inode);
-no_inode:
-	put_filp(file);
-no_file:
+	err = anon_inode_getfd("[ddlink]", fops, dd, 0);
+	if (err < 0)
+		goto error;
 	return err;
-}
-EXPORT_SYMBOL_GPL(ddlink);
-
-static int __init ddlink_init(void)
-{
-	struct vfsmount *mnt;
-	register_filesystem(&ddlink_type);
-	mnt = kern_mount(&ddlink_type);
-	if (IS_ERR(mnt))
-		return PTR_ERR(mnt);
-	ddlink_mnt = mnt;
-	return 0;
-}
 
-static void __exit ddlink_exit(void)
-{
-	mntput(ddlink_mnt);
-	unregister_filesystem(&ddlink_type);
+error:
+	ddlink_free_ddctl(dd);
+	return err;
 }
-
-module_init(ddlink_init);
-module_exit(ddlink_exit);
+EXPORT_SYMBOL_GPL(ddlink);
 
 /* library methods */
 
-void ddlink_push(struct ddinode *dd, struct dditem *item)
+void ddlink_push(struct ddctl *dd, struct dditem *item)
 {
 	list_add(&item->link, &dd->list);
 	wake_up_interruptible(&dd->wait);
 }
 EXPORT_SYMBOL_GPL(ddlink_push);
 
-void ddlink_queue(struct ddinode *dd, struct dditem *item)
+void ddlink_queue(struct ddctl *dd, struct dditem *item)
 {
 	list_add_tail(&item->link, &dd->list);
 	wake_up_interruptible(&dd->wait);
 }
 EXPORT_SYMBOL_GPL(ddlink_queue);
 
-struct dditem *dditem_new(struct ddinode *dd, size_t size)
+struct dditem *dditem_new(struct ddctl *dd, size_t size)
 {
 	struct dditem *item;
 	if (!(item = dd->create_item(sizeof(*item) + size, __GFP_NOFAIL))) // NOFAIL??
@@ -180,7 +122,7 @@ struct dditem *dditem_new(struct ddinode
 }
 EXPORT_SYMBOL_GPL(dditem_new);
 
-struct dditem *dditem_in(struct ddinode *dd, const void *buf, size_t len, int z)
+struct dditem *dditem_in(struct ddctl *dd, const void *buf, size_t len, int z)
 {
 	struct dditem *item = dditem_new(dd, len + z);
 
@@ -198,7 +140,7 @@ struct dditem *dditem_in(struct ddinode 
 }
 EXPORT_SYMBOL_GPL(dditem_in);
 
-int dditem_out(struct ddinode *dd, void *buf, size_t len, struct dditem *item) // !!! not tested
+int dditem_out(struct ddctl *dd, void *buf, size_t len, struct dditem *item) // !!! not tested
 {
 	if (len < item->size)
 		return -EINVAL;
@@ -209,7 +151,7 @@ int dditem_out(struct ddinode *dd, void 
 }
 EXPORT_SYMBOL_GPL(dditem_out);
 
-int ddlink_post(struct ddinode *dd, void *data, unsigned len)
+int ddlink_post(struct ddctl *dd, void *data, unsigned len)
 {
 	struct dditem *item = dditem_new(dd, len);
 	if (!item)
@@ -220,7 +162,7 @@ int ddlink_post(struct ddinode *dd, void
 }
 EXPORT_SYMBOL_GPL(ddlink_post);
 
-int ddlink_error(struct ddinode *dd, int err, const char *fmt, ...)
+int ddlink_error(struct ddctl *dd, int err, const char *fmt, ...)
 {
 	int size = 200; /* enough for any error? */
 	struct dditem *item, *work;
@@ -246,7 +188,7 @@ EXPORT_SYMBOL_GPL(ddlink_error);
 
 unsigned ddlink_poll(struct file *file, poll_table *table)
 {
-	struct ddinode *dd = ddinode(file->f_dentry->d_inode);
+	struct ddctl *dd = ddctl(file);
 	poll_wait(file, &dd->wait, table);
 	return ddlink_ready(dd) ? POLLIN : 0;
 }
@@ -259,14 +201,14 @@ EXPORT_SYMBOL_GPL(ddlink_poll);
 
 static int ddlink_example_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long ptr)
 {
-	struct ddinode *dd = ddinode(inode);
+	struct ddctl *dd = ddctl(file);
 	printk("ddlink_ioctl %i (%lx) on %p\n", cmd, ptr, dd);
 	return 0;
 }
 
 static ssize_t ddlink_example_write(struct file *file, const char *buf, size_t len, loff_t *offset)
 {
-	struct ddinode *dd = ddinode(file->f_dentry->d_inode);
+	struct ddctl *dd = ddctl(file);
 	struct dditem *item = dditem_in(dd, buf, len, 1);
 	if (IS_ERR(item))
 		return PTR_ERR(item);
@@ -276,20 +218,21 @@ static ssize_t ddlink_example_write(stru
 
 static ssize_t ddlink_example_read(struct file *file, char *buf, size_t len, loff_t *offset)
 {
-	struct ddinode *dd = ddinode(file->f_dentry->d_inode);
+	struct ddctl *dd = ddctl(file);
 	if (list_empty(&dd->list))
 		return EFAULT;
 	return dditem_out(dd, buf, len, ddlink_pop(dd));
 }
 
-static struct file_operations ddlink_example_fops = {
+static const struct file_operations ddlink_example_fops = {
 	.read = ddlink_example_read,
 	.write = ddlink_example_write,
 	.ioctl = ddlink_example_ioctl,
 	.poll = ddlink_poll,
+	.release = ddlink_file_release,
 };
 
-void *ddlink_example_create(struct ddinode *dd, void *info)
+void *ddlink_example_create(struct ddctl *dd, void *info)
 {
 	return NULL;
 }
diff -puN user/kernel/inode.c~use-filp user/kernel/inode.c
--- tux3/user/kernel/inode.c~use-filp	2009-02-26 18:44:26.000000000 +0900
+++ tux3-hirofumi/user/kernel/inode.c	2009-02-26 18:52:08.000000000 +0900
@@ -378,14 +378,14 @@ int tux3_setattr(struct dentry *dentry, 
 
 static int ddlink_example_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long ptr)
 {
-	struct ddinode *dd = ddinode(inode);
+	struct ddctl *dd = ddctl(file);
 	printk("ddlink_ioctl %i (%lx) on %p\n", cmd, ptr, dd);
 	return 0;
 }
 
 static ssize_t ddlink_example_write(struct file *file, const char *buf, size_t len, loff_t *offset)
 {
-	struct ddinode *dd = ddinode(file->f_dentry->d_inode);
+	struct ddctl *dd = ddctl(file);
 	struct dditem *item = dditem_in(dd, buf, len, 1);
 	if (IS_ERR(item))
 		return PTR_ERR(item);
@@ -395,17 +395,18 @@ static ssize_t ddlink_example_write(stru
 
 static ssize_t ddlink_example_read(struct file *file, char *buf, size_t len, loff_t *offset)
 {
-	struct ddinode *dd = ddinode(file->f_dentry->d_inode);
+	struct ddctl *dd = ddctl(file);
 	if (list_empty(&dd->list))
 		return EFAULT;
 	return dditem_out(dd, buf, len, ddlink_pop(dd));
 }
 
-static struct file_operations ddlink_example_fops = {
+static const struct file_operations ddlink_example_fops = {
 	.read = ddlink_example_read,
 	.write = ddlink_example_write,
 	.ioctl = ddlink_example_ioctl,
 	.poll = ddlink_poll,
+	.release = ddlink_file_release,
 };
 
 long tux3_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
_
-- 
OGAWA Hirofumi <hirof...@mail.parknet.co.jp>
_______________________________________________
Tux3 mailing list
Tux3@tux3.org
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3

Reply via email to