aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-10-14 17:08:43 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-10-14 17:27:57 -0400
commitac78a07893d24d95ff5f39d0433c25210f224f07 (patch)
treeac48d2a828ef6daa62d5f5373cc14ba658b2a945 /fs
parent48f6ba5e691948caba2e7bc362153fb28e4f1e09 (diff)
kill-the-bkl/reiserfs: always lock the ioctl path
Reiserfs uses the ioctl callback for its file operations, which means that its ioctl path is still locked by the bkl, this was synchronizing with the rest of the filsystem operations. We have changed that by locking it with the new reiserfs lock but we do that only from the compat_ioctl callback. Fix that by locking reiserfs_ioctl() everytime. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Chris Mason <chris.mason@oracle.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Alexander Beregalov <a.beregalov@gmail.com> Cc: Laurent Riffard <laurent.riffard@free.fr> Cc: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/reiserfs/ioctl.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 5e40b0cd4c3d..e30e8be09179 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -13,44 +13,52 @@
13#include <linux/compat.h> 13#include <linux/compat.h>
14 14
15/* 15/*
16** reiserfs_ioctl - handler for ioctl for inode 16 * reiserfs_ioctl - handler for ioctl for inode
17** supported commands: 17 * supported commands:
18** 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect 18 * 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
19** and prevent packing file (argument arg has to be non-zero) 19 * and prevent packing file (argument arg has to be non-zero)
20** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION 20 * 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
21** 3) That's all for a while ... 21 * 3) That's all for a while ...
22*/ 22 */
23int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 23int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
24 unsigned long arg) 24 unsigned long arg)
25{ 25{
26 unsigned int flags; 26 unsigned int flags;
27 int err = 0; 27 int err = 0;
28 28
29 reiserfs_write_lock(inode->i_sb);
30
29 switch (cmd) { 31 switch (cmd) {
30 case REISERFS_IOC_UNPACK: 32 case REISERFS_IOC_UNPACK:
31 if (S_ISREG(inode->i_mode)) { 33 if (S_ISREG(inode->i_mode)) {
32 if (arg) 34 if (arg)
33 return reiserfs_unpack(inode, filp); 35 err = reiserfs_unpack(inode, filp);
34 else
35 return 0;
36 } else 36 } else
37 return -ENOTTY; 37 err = -ENOTTY;
38 /* following two cases are taken from fs/ext2/ioctl.c by Remy 38 break;
39 Card (card@masi.ibp.fr) */ 39 /*
40 * following two cases are taken from fs/ext2/ioctl.c by Remy
41 * Card (card@masi.ibp.fr)
42 */
40 case REISERFS_IOC_GETFLAGS: 43 case REISERFS_IOC_GETFLAGS:
41 if (!reiserfs_attrs(inode->i_sb)) 44 if (!reiserfs_attrs(inode->i_sb)) {
42 return -ENOTTY; 45 err = -ENOTTY;
46 break;
47 }
43 48
44 flags = REISERFS_I(inode)->i_attrs; 49 flags = REISERFS_I(inode)->i_attrs;
45 i_attrs_to_sd_attrs(inode, (__u16 *) & flags); 50 i_attrs_to_sd_attrs(inode, (__u16 *) & flags);
46 return put_user(flags, (int __user *)arg); 51 err = put_user(flags, (int __user *)arg);
52 break;
47 case REISERFS_IOC_SETFLAGS:{ 53 case REISERFS_IOC_SETFLAGS:{
48 if (!reiserfs_attrs(inode->i_sb)) 54 if (!reiserfs_attrs(inode->i_sb)) {
49 return -ENOTTY; 55 err = -ENOTTY;
56 break;
57 }
50 58
51 err = mnt_want_write(filp->f_path.mnt); 59 err = mnt_want_write(filp->f_path.mnt);
52 if (err) 60 if (err)
53 return err; 61 break;
54 62
55 if (!is_owner_or_cap(inode)) { 63 if (!is_owner_or_cap(inode)) {
56 err = -EPERM; 64 err = -EPERM;
@@ -90,16 +98,18 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
90 mark_inode_dirty(inode); 98 mark_inode_dirty(inode);
91setflags_out: 99setflags_out:
92 mnt_drop_write(filp->f_path.mnt); 100 mnt_drop_write(filp->f_path.mnt);
93 return err; 101 break;
94 } 102 }
95 case REISERFS_IOC_GETVERSION: 103 case REISERFS_IOC_GETVERSION:
96 return put_user(inode->i_generation, (int __user *)arg); 104 err = put_user(inode->i_generation, (int __user *)arg);
105 break;
97 case REISERFS_IOC_SETVERSION: 106 case REISERFS_IOC_SETVERSION:
98 if (!is_owner_or_cap(inode)) 107 if (!is_owner_or_cap(inode))
99 return -EPERM; 108 err = -EPERM;
109 break;
100 err = mnt_want_write(filp->f_path.mnt); 110 err = mnt_want_write(filp->f_path.mnt);
101 if (err) 111 if (err)
102 return err; 112 break;
103 if (get_user(inode->i_generation, (int __user *)arg)) { 113 if (get_user(inode->i_generation, (int __user *)arg)) {
104 err = -EFAULT; 114 err = -EFAULT;
105 goto setversion_out; 115 goto setversion_out;
@@ -108,10 +118,14 @@ setflags_out:
108 mark_inode_dirty(inode); 118 mark_inode_dirty(inode);
109setversion_out: 119setversion_out:
110 mnt_drop_write(filp->f_path.mnt); 120 mnt_drop_write(filp->f_path.mnt);
111 return err; 121 break;
112 default: 122 default:
113 return -ENOTTY; 123 err = -ENOTTY;
114 } 124 }
125
126 reiserfs_write_unlock(inode->i_sb);
127
128 return err;
115} 129}
116 130
117#ifdef CONFIG_COMPAT 131#ifdef CONFIG_COMPAT
@@ -142,9 +156,7 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
142 return -ENOIOCTLCMD; 156 return -ENOIOCTLCMD;
143 } 157 }
144 158
145 reiserfs_write_lock(inode->i_sb);
146 ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); 159 ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
147 reiserfs_write_unlock(inode->i_sb);
148 160
149 return ret; 161 return ret;
150} 162}