diff options
author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2012-05-14 15:51:52 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-14 09:25:44 -0700 |
commit | 581791f5c7a480b2cc3431af9a6e799ffd51eb5e (patch) | |
tree | 3284544e5a67e91ec612fc0a715cff66b250a283 /drivers/usb/gadget/f_fs.c | |
parent | 304f0b2453ea377b8f987aa5f9e1ccda0e3adfa7 (diff) |
FunctionFS: enable multiple functions
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/gadget/f_fs.c')
-rw-r--r-- | drivers/usb/gadget/f_fs.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 1d4c535671a..dcd1c7fbb01 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1031,6 +1031,12 @@ struct ffs_sb_fill_data { struct ffs_file_perms perms; umode_t root_mode; const char *dev_name; + union { + /* set by ffs_fs_mount(), read by ffs_sb_fill() */ + void *private_data; + /* set by ffs_sb_fill(), read by ffs_fs_mount */ + struct ffs_data *ffs_data; + }; }; static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) @@ -1047,8 +1053,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) goto Enomem; ffs->sb = sb; - ffs->dev_name = data->dev_name; + ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL); + if (unlikely(!ffs->dev_name)) + goto Enomem; ffs->file_perms = data->perms; + ffs->private_data = data->private_data; + + /* used by the caller of this function */ + data->ffs_data = ffs; sb->s_fs_info = ffs; sb->s_blocksize = PAGE_CACHE_SIZE; @@ -1167,20 +1179,29 @@ ffs_fs_mount(struct file_system_type *t, int flags, }, .root_mode = S_IFDIR | 0500, }; + struct dentry *rv; int ret; + void *ffs_dev; ENTER(); - ret = functionfs_check_dev_callback(dev_name); - if (unlikely(ret < 0)) - return ERR_PTR(ret); - ret = ffs_fs_parse_opts(&data, opts); if (unlikely(ret < 0)) return ERR_PTR(ret); + ffs_dev = functionfs_acquire_dev_callback(dev_name); + if (IS_ERR(ffs_dev)) + return ffs_dev; + data.dev_name = dev_name; - return mount_single(t, flags, &data, ffs_sb_fill); + data.private_data = ffs_dev; + rv = mount_nodev(t, flags, &data, ffs_sb_fill); + + /* data.ffs_data is set by ffs_sb_fill */ + if (IS_ERR(rv)) + functionfs_release_dev_callback(data.ffs_data); + + return rv; } static void @@ -1189,8 +1210,10 @@ ffs_fs_kill_sb(struct super_block *sb) ENTER(); kill_litter_super(sb); - if (sb->s_fs_info) + if (sb->s_fs_info) { + functionfs_release_dev_callback(sb->s_fs_info); ffs_data_put(sb->s_fs_info); + } } static struct file_system_type ffs_fs_type = { @@ -1256,6 +1279,7 @@ static void ffs_data_put(struct ffs_data *ffs) ffs_data_clear(ffs); BUG_ON(waitqueue_active(&ffs->ev.waitq) || waitqueue_active(&ffs->ep0req_completion.wait)); + kfree(ffs->dev_name); kfree(ffs); } } |