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
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
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,
22 .compat_ioctl = ext4_compat_ioctl,
24 diff --git a/fs/ext4/file.c b/fs/ext4/file.c
25 index ac35ec5..c586a81 100644
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,
35 .compat_ioctl = ext4_compat_ioctl,
37 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
38 index 2ed7c37..7689d2e 100644
42 #include <linux/smp_lock.h>
43 #include <asm/uaccess.h>
45 -int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
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;
53 unsigned short rsv_window_size;
58 + inode = filp->f_path.dentry->d_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);
70 case EXT4_IOC_SETFLAGS: {
71 handle_t *handle = NULL;
73 struct ext4_iloc iloc;
74 unsigned int oldflags;
77 - if (IS_RDONLY(inode))
79 + if (IS_RDONLY(inode)) {
84 - if (!is_owner_or_cap(inode))
86 + if (!is_owner_or_cap(inode)) {
91 - if (get_user(flags, (int __user *) arg))
93 + if (get_user(flags, (int __user *) arg)) {
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);
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);
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);
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);
140 - err = ext4_reserve_inode_write(handle, inode, &iloc);
142 + retval = ext4_reserve_inode_write(handle, inode, &iloc);
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);
154 ext4_journal_stop(handle);
157 mutex_unlock(&inode->i_mutex);
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);
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);
174 case EXT4_IOC_SETVERSION:
175 case EXT4_IOC_SETVERSION_OLD: {
177 struct ext4_iloc iloc;
181 - if (!is_owner_or_cap(inode))
183 - if (IS_RDONLY(inode))
185 - if (get_user(generation, (int __user *) arg))
187 + if (!is_owner_or_cap(inode)) {
191 + if (IS_RDONLY(inode)) {
195 + if (get_user(generation, (int __user *) arg)) {
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);
205 + if (IS_ERR(handle)) {
206 + retval = PTR_ERR(handle);
209 + retval = ext4_reserve_inode_write(handle, inode, &iloc);
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);
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);
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)) {
235 remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
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);
252 case EXT4_IOC_SETRSVSZ: {
254 - if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
256 + if (!test_opt(inode->i_sb, RESERVATION) ||
257 + !S_ISREG(inode->i_mode)) {
262 - if (IS_RDONLY(inode))
264 + if (IS_RDONLY(inode)) {
269 - if (!is_owner_or_cap(inode))
271 + if (!is_owner_or_cap(inode)) {
276 - if (get_user(rsv_window_size, (int __user *)arg))
278 + if (get_user(rsv_window_size, (int __user *)arg)) {
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);
292 case EXT4_IOC_GROUP_EXTEND: {
293 ext4_fsblk_t n_blocks_count;
294 struct super_block *sb = inode->i_sb;
297 - if (!capable(CAP_SYS_RESOURCE))
299 + if (!capable(CAP_SYS_RESOURCE)) {
304 - if (IS_RDONLY(inode))
306 + if (IS_RDONLY(inode)) {
311 - if (get_user(n_blocks_count, (__u32 __user *)arg))
313 + if (get_user(n_blocks_count, (__u32 __user *)arg)) {
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,
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);
328 case EXT4_IOC_GROUP_ADD: {
329 struct ext4_new_group_data input;
330 struct super_block *sb = inode->i_sb;
333 - if (!capable(CAP_SYS_RESOURCE))
335 + if (!capable(CAP_SYS_RESOURCE)) {
340 - if (IS_RDONLY(inode))
342 + if (IS_RDONLY(inode)) {
347 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
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);
365 case EXT4_IOC_MIGRATE:
366 - return ext4_ext_migrate(inode, filp, cmd, arg);
367 + retval = ext4_ext_migrate(inode, filp, cmd, arg);
380 @@ -307,9 +358,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
385 ret = ext4_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
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);
398 -extern int ext4_ioctl (struct inode *, struct file *, unsigned int,
400 +extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
401 extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);