diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-08 15:38:27 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-08 20:17:17 -0500 |
commit | 5b5f9560354dc5a3a27ce57a86aec6b98531ee21 (patch) | |
tree | 908448da30e77e931f62080e3d836cf0f070d389 /drivers/usb/gadget | |
parent | 48fa57ac2c30a8a0b770b7ad50b4b30c1d12f005 (diff) |
functionfs: unfuck failure exits on mount
* if you do dput() of root dentry, do *not* follow that with iput() of root
inode.
* while we are at it, don't do that dput() at all - you are leaving the pointer
in ->s_root and your ->kill_sb() will be very unhappy with that. It will do
proper dput(), though, so the easiest way is to leave that to it entirely.
* freeing ->s_fs_info is also best left to ->kill_sb() (which will do it
anyway), especially since we leave the pointer in place.
* that xchg() in ->kill_sb() is not a bug per se, but it's a plain and simple
masturbation with fewer excuses than Onan had...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/f_fs.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index acb38004eec..b5f6f9fef9c 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1037,7 +1037,6 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) { struct ffs_sb_fill_data *data = _data; struct inode *inode; - struct dentry *d; struct ffs_data *ffs; ENTER(); @@ -1045,7 +1044,7 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) /* Initialise data */ ffs = ffs_data_new(); if (unlikely(!ffs)) - goto enomem0; + goto Enomem; ffs->sb = sb; ffs->dev_name = data->dev_name; @@ -1065,26 +1064,21 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) &simple_dir_inode_operations, &data->perms); if (unlikely(!inode)) - goto enomem1; - d = d_alloc_root(inode); - if (unlikely(!d)) - goto enomem2; - sb->s_root = d; + goto Enomem; + sb->s_root = d_alloc_root(inode); + if (unlikely(!sb->s_root)) { + iput(inode); + goto Enomem; + } /* EP0 file */ if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations, NULL))) - goto enomem3; + goto Enomem; return 0; -enomem3: - dput(d); -enomem2: - iput(inode); -enomem1: - ffs_data_put(ffs); -enomem0: +Enomem: return -ENOMEM; } @@ -1196,14 +1190,11 @@ ffs_fs_mount(struct file_system_type *t, int flags, static void ffs_fs_kill_sb(struct super_block *sb) { - void *ptr; - ENTER(); kill_litter_super(sb); - ptr = xchg(&sb->s_fs_info, NULL); - if (ptr) - ffs_data_put(ptr); + if (sb->s_fs_info) + ffs_data_put(sb->s_fs_info); } static struct file_system_type ffs_fs_type = { |