@@ -101,18 +101,35 @@ static int ubifs2ioctl(int ubifs_flags)
return ioctl_flags;
}
-static int setflags(struct inode *inode, int flags)
+static int setflags(struct file *file, int flags)
{
int oldflags, err, release;
+ struct inode *inode = file_inode(file);
struct ubifs_inode *ui = ubifs_inode(inode);
struct ubifs_info *c = inode->i_sb->s_fs_info;
struct ubifs_budget_req req = { .dirtied_ino = 1,
.dirtied_ino_d = ui->data_len };
- err = ubifs_budget_space(c, &req);
+ if (IS_RDONLY(inode))
+ return -EROFS;
+
+ if (!inode_owner_or_capable(&init_user_ns, inode))
+ return -EACCES;
+
+ /*
+ * Make sure the file-system is read-write and make sure it
+ * will not become read-only while we are changing the flags.
+ */
+ err = mnt_want_write_file(file);
if (err)
return err;
+ dbg_gen("set flags: %#x, i_flags %#x", flags, inode->i_flags);
+
+ err = ubifs_budget_space(c, &req);
+ if (err)
+ goto out_drop;
+
mutex_lock(&ui->ui_mutex);
oldflags = ubifs2ioctl(ui->flags);
err = vfs_ioc_setflags_prepare(inode, oldflags, flags);
@@ -131,11 +148,17 @@ static int setflags(struct inode *inode, int flags)
ubifs_release_budget(c, &req);
if (IS_SYNC(inode))
err = write_inode_now(inode, 1);
+
+ mnt_drop_write_file(file);
+
return err;
out_unlock:
mutex_unlock(&ui->ui_mutex);
ubifs_release_budget(c, &req);
+out_drop:
+ mnt_drop_write_file(file);
+
return err;
}
@@ -152,12 +175,6 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return put_user(flags, (int __user *) arg);
case FS_IOC_SETFLAGS: {
- if (IS_RDONLY(inode))
- return -EROFS;
-
- if (!inode_owner_or_capable(&init_user_ns, inode))
- return -EACCES;
-
if (get_user(flags, (int __user *) arg))
return -EFAULT;
@@ -168,17 +185,8 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (!S_ISDIR(inode->i_mode))
flags &= ~FS_DIRSYNC_FL;
- /*
- * Make sure the file-system is read-write and make sure it
- * will not become read-only while we are changing the flags.
- */
- err = mnt_want_write_file(file);
- if (err)
- return err;
- dbg_gen("set flags: %#x, i_flags %#x", flags, inode->i_flags);
- err = setflags(inode, flags);
- mnt_drop_write_file(file);
- return err;
+
+ return setflags(file, flags);
}
case FS_IOC_SET_ENCRYPTION_POLICY: {
struct ubifs_info *c = inode->i_sb->s_fs_info;
setflags() can be reused for upcoming FS_IOC_FS[SG]ETXATTR ioctl support. In preparation for that move the checks and preparation into that function so we can reuse them as well. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- fs/ubifs/ioctl.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-)