Commit patches which move ext 2/3/4 to use unlocked_ioctl().
[ext4-patch-queue.git] / ext4-unlocked-ioctl.patch
blob0b92b74bbf3c6c8a091104792fca96b0d8f12317
1 Convert ext4_ioctl to an unlocked_ioctl
3 From: Mathieu Segaud <mathieu.segaud@regala.cx>
5 Change ext4_ioctl() to be an unlocked_ioctl(), explicitly
6 exposing BKL's uses.
8 Signed-off-by: Mathieu Segaud <mathieu.segaud@regala.cx>
9 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
11 diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
12 index 33888bb..56e6608 100644
13 --- a/fs/ext4/dir.c
14 +++ b/fs/ext4/dir.c
15 @@ -42,7 +42,7 @@ const struct file_operations ext4_dir_operations = {
16 .llseek = generic_file_llseek,
17 .read = generic_read_dir,
18 .readdir = ext4_readdir, /* we take BKL. needed?*/
19 - .ioctl = ext4_ioctl, /* BKL held */
20 + .unlocked_ioctl = ext4_ioctl,
21 #ifdef CONFIG_COMPAT
22 .compat_ioctl = ext4_compat_ioctl,
23 #endif
24 diff --git a/fs/ext4/file.c b/fs/ext4/file.c
25 index ac35ec5..c586a81 100644
26 --- a/fs/ext4/file.c
27 +++ b/fs/ext4/file.c
28 @@ -129,7 +129,7 @@ const struct file_operations ext4_file_operations = {
29 .write = do_sync_write,
30 .aio_read = generic_file_aio_read,
31 .aio_write = ext4_file_write,
32 - .ioctl = ext4_ioctl,
33 + .unlocked_ioctl = ext4_ioctl,
34 #ifdef CONFIG_COMPAT
35 .compat_ioctl = ext4_compat_ioctl,
36 #endif
37 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
38 index 2ed7c37..7689d2e 100644
39 --- a/fs/ext4/ioctl.c
40 +++ b/fs/ext4/ioctl.c
41 @@ -17,12 +17,18 @@
42 #include <linux/smp_lock.h>
43 #include <asm/uaccess.h>
45 -int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
46 - unsigned long arg)
47 +long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
49 - struct ext4_inode_info *ei = EXT4_I(inode);
50 + struct ext4_inode_info *ei;
51 + struct inode *inode;
52 unsigned int flags;
53 unsigned short rsv_window_size;
54 + long retval = 0;
56 + lock_kernel();
58 + inode = filp->f_path.dentry->d_inode;
59 + ei = EXT4_I(inode);
61 ext4_debug ("cmd = %u, arg = %lu\n", cmd, arg);
63 @@ -30,22 +36,28 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
64 case EXT4_IOC_GETFLAGS:
65 ext4_get_inode_flags(ei);
66 flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
67 - return put_user(flags, (int __user *) arg);
68 + retval = put_user(flags, (int __user *) arg);
69 + goto out;
70 case EXT4_IOC_SETFLAGS: {
71 handle_t *handle = NULL;
72 - int err;
73 struct ext4_iloc iloc;
74 unsigned int oldflags;
75 unsigned int jflag;
77 - if (IS_RDONLY(inode))
78 - return -EROFS;
79 + if (IS_RDONLY(inode)) {
80 + retval = -EROFS;
81 + goto out;
82 + }
84 - if (!is_owner_or_cap(inode))
85 - return -EACCES;
86 + if (!is_owner_or_cap(inode)) {
87 + retval = -EACCES;
88 + goto out;
89 + }
91 - if (get_user(flags, (int __user *) arg))
92 - return -EFAULT;
93 + if (get_user(flags, (int __user *) arg)) {
94 + retval = -EFAULT;
95 + goto out;
96 + }
98 if (!S_ISDIR(inode->i_mode))
99 flags &= ~EXT4_DIRSYNC_FL;
100 @@ -54,7 +66,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
101 /* Is it quota file? Do not allow user to mess with it */
102 if (IS_NOQUOTA(inode)) {
103 mutex_unlock(&inode->i_mutex);
104 - return -EPERM;
105 + retval = -EPERM;
106 + goto out;
108 oldflags = ei->i_flags;
110 @@ -70,7 +83,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
111 if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
112 if (!capable(CAP_LINUX_IMMUTABLE)) {
113 mutex_unlock(&inode->i_mutex);
114 - return -EPERM;
115 + retval = -EPERM;
116 + goto out;
120 @@ -81,7 +95,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
121 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
122 if (!capable(CAP_SYS_RESOURCE)) {
123 mutex_unlock(&inode->i_mutex);
124 - return -EPERM;
125 + retval = -EPERM;
126 + goto out;
130 @@ -89,12 +104,13 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
131 handle = ext4_journal_start(inode, 1);
132 if (IS_ERR(handle)) {
133 mutex_unlock(&inode->i_mutex);
134 - return PTR_ERR(handle);
135 + retval = PTR_ERR(handle);
136 + goto out;
138 if (IS_SYNC(inode))
139 handle->h_sync = 1;
140 - err = ext4_reserve_inode_write(handle, inode, &iloc);
141 - if (err)
142 + retval = ext4_reserve_inode_write(handle, inode, &iloc);
143 + if (retval)
144 goto flags_err;
146 flags = flags & EXT4_FL_USER_MODIFIABLE;
147 @@ -104,47 +120,55 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
148 ext4_set_inode_flags(inode);
149 inode->i_ctime = ext4_current_time(inode);
151 - err = ext4_mark_iloc_dirty(handle, inode, &iloc);
152 + retval = ext4_mark_iloc_dirty(handle, inode, &iloc);
153 flags_err:
154 ext4_journal_stop(handle);
155 - if (err) {
156 + if (retval) {
157 mutex_unlock(&inode->i_mutex);
158 - return err;
159 + goto out;
162 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
163 - err = ext4_change_inode_journal_flag(inode, jflag);
164 + retval = ext4_change_inode_journal_flag(inode, jflag);
165 mutex_unlock(&inode->i_mutex);
166 - return err;
167 + goto out;
169 case EXT4_IOC_GETVERSION:
170 case EXT4_IOC_GETVERSION_OLD:
171 - return put_user(inode->i_generation, (int __user *) arg);
172 + retval = put_user(inode->i_generation, (int __user *) arg);
173 + goto out;
174 case EXT4_IOC_SETVERSION:
175 case EXT4_IOC_SETVERSION_OLD: {
176 handle_t *handle;
177 struct ext4_iloc iloc;
178 __u32 generation;
179 - int err;
181 - if (!is_owner_or_cap(inode))
182 - return -EPERM;
183 - if (IS_RDONLY(inode))
184 - return -EROFS;
185 - if (get_user(generation, (int __user *) arg))
186 - return -EFAULT;
187 + if (!is_owner_or_cap(inode)) {
188 + retval = -EPERM;
189 + goto out;
191 + if (IS_RDONLY(inode)) {
192 + retval = -EROFS;
193 + goto out;
195 + if (get_user(generation, (int __user *) arg)) {
196 + retval = -EFAULT;
197 + goto out;
200 handle = ext4_journal_start(inode, 1);
201 - if (IS_ERR(handle))
202 - return PTR_ERR(handle);
203 - err = ext4_reserve_inode_write(handle, inode, &iloc);
204 - if (err == 0) {
205 + if (IS_ERR(handle)) {
206 + retval = PTR_ERR(handle);
207 + goto out;
209 + retval = ext4_reserve_inode_write(handle, inode, &iloc);
210 + if (retval == 0) {
211 inode->i_ctime = ext4_current_time(inode);
212 inode->i_generation = generation;
213 - err = ext4_mark_iloc_dirty(handle, inode, &iloc);
214 + retval = ext4_mark_iloc_dirty(handle, inode, &iloc);
216 ext4_journal_stop(handle);
217 - return err;
218 + goto out;
220 #ifdef CONFIG_JBD2_DEBUG
221 case EXT4_IOC_WAIT_FOR_READONLY:
222 @@ -158,16 +182,15 @@ flags_err:
224 struct super_block *sb = inode->i_sb;
225 DECLARE_WAITQUEUE(wait, current);
226 - int ret = 0;
228 set_current_state(TASK_INTERRUPTIBLE);
229 add_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
230 if (timer_pending(&EXT4_SB(sb)->turn_ro_timer)) {
231 schedule();
232 - ret = 1;
233 + retval = 1;
235 remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
236 - return ret;
237 + goto out;
239 #endif
240 case EXT4_IOC_GETRSVSZ:
241 @@ -175,22 +198,33 @@ flags_err:
242 && S_ISREG(inode->i_mode)
243 && ei->i_block_alloc_info) {
244 rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
245 - return put_user(rsv_window_size, (int __user *)arg);
246 + retval = put_user(rsv_window_size, (int __user *)arg);
247 + goto out;
249 - return -ENOTTY;
250 + retval = -ENOTTY;
251 + goto out;
252 case EXT4_IOC_SETRSVSZ: {
254 - if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
255 - return -ENOTTY;
256 + if (!test_opt(inode->i_sb, RESERVATION) ||
257 + !S_ISREG(inode->i_mode)) {
258 + retval = -ENOTTY;
259 + goto out;
262 - if (IS_RDONLY(inode))
263 - return -EROFS;
264 + if (IS_RDONLY(inode)) {
265 + retval = -EROFS;
266 + goto out;
269 - if (!is_owner_or_cap(inode))
270 - return -EACCES;
271 + if (!is_owner_or_cap(inode)) {
272 + retval = -EACCES;
273 + goto out;
276 - if (get_user(rsv_window_size, (int __user *)arg))
277 - return -EFAULT;
278 + if (get_user(rsv_window_size, (int __user *)arg)) {
279 + retval = -EFAULT;
280 + goto out;
283 if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS)
284 rsv_window_size = EXT4_MAX_RESERVE_BLOCKS;
285 @@ -208,58 +242,75 @@ flags_err:
286 rsv->rsv_goal_size = rsv_window_size;
288 up_write(&ei->i_data_sem);
289 - return 0;
290 + goto out;
292 case EXT4_IOC_GROUP_EXTEND: {
293 ext4_fsblk_t n_blocks_count;
294 struct super_block *sb = inode->i_sb;
295 int err;
297 - if (!capable(CAP_SYS_RESOURCE))
298 - return -EPERM;
299 + if (!capable(CAP_SYS_RESOURCE)) {
300 + retval = -EPERM;
301 + goto out;
304 - if (IS_RDONLY(inode))
305 - return -EROFS;
306 + if (IS_RDONLY(inode)) {
307 + retval = -EROFS;
308 + goto out;
311 - if (get_user(n_blocks_count, (__u32 __user *)arg))
312 - return -EFAULT;
313 + if (get_user(n_blocks_count, (__u32 __user *)arg)) {
314 + retval = -EFAULT;
315 + goto out;
318 - err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
319 + retval = ext4_group_extend(sb, EXT4_SB(sb)->s_es,
320 + n_blocks_count);
321 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
322 jbd2_journal_flush(EXT4_SB(sb)->s_journal);
323 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
325 - return err;
326 + goto out;
328 case EXT4_IOC_GROUP_ADD: {
329 struct ext4_new_group_data input;
330 struct super_block *sb = inode->i_sb;
331 int err;
333 - if (!capable(CAP_SYS_RESOURCE))
334 - return -EPERM;
335 + if (!capable(CAP_SYS_RESOURCE)) {
336 + retval = -EPERM;
337 + goto out;
340 - if (IS_RDONLY(inode))
341 - return -EROFS;
342 + if (IS_RDONLY(inode)) {
343 + retval = -EROFS;
344 + goto out;
347 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
348 - sizeof(input)))
349 - return -EFAULT;
350 + sizeof(input))) {
351 + retval = -EFAULT;
352 + goto out;
355 - err = ext4_group_add(sb, &input);
356 + retval = ext4_group_add(sb, &input);
357 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
358 jbd2_journal_flush(EXT4_SB(sb)->s_journal);
359 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
361 - return err;
362 + goto out;
365 case EXT4_IOC_MIGRATE:
366 - return ext4_ext_migrate(inode, filp, cmd, arg);
367 + retval = ext4_ext_migrate(inode, filp, cmd, arg);
368 + goto out;
370 default:
371 - return -ENOTTY;
372 + retval = -ENOTTY;
374 +out:
375 + unlock_kernel();
376 + return retval;
379 #ifdef CONFIG_COMPAT
380 @@ -307,9 +358,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
381 default:
382 return -ENOIOCTLCMD;
384 - lock_kernel();
385 ret = ext4_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
386 - unlock_kernel();
387 return ret;
389 #endif
390 diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
391 index 1852313..0eb31e3 100644
392 --- a/include/linux/ext4_fs.h
393 +++ b/include/linux/ext4_fs.h
394 @@ -1042,8 +1042,7 @@ extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
395 struct address_space *mapping, loff_t from);
397 /* ioctl.c */
398 -extern int ext4_ioctl (struct inode *, struct file *, unsigned int,
399 - unsigned long);
400 +extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
401 extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
403 /* migrate.c */