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