Commit 7fb17fe4 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

f2fs: use mnt_{want,drop}_write_file in ioctl

In interfaces of ioctl, mnt_{want,drop}_write_file should be used for:
- get exclusion against file system freezing which may used by lvm
  snapshot.
- do telling filesystem that a write is about to be performed on it, and
  make sure that the writes are permitted.
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 0080c507
...@@ -1307,20 +1307,16 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg) ...@@ -1307,20 +1307,16 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
unsigned int oldflags; unsigned int oldflags;
int ret; int ret;
if (!inode_owner_or_capable(inode))
return -EACCES;
if (get_user(flags, (int __user *)arg))
return -EFAULT;
ret = mnt_want_write_file(filp); ret = mnt_want_write_file(filp);
if (ret) if (ret)
return ret; return ret;
if (!inode_owner_or_capable(inode)) {
ret = -EACCES;
goto out;
}
if (get_user(flags, (int __user *)arg)) {
ret = -EFAULT;
goto out;
}
flags = f2fs_mask_flags(inode->i_mode, flags); flags = f2fs_mask_flags(inode->i_mode, flags);
inode_lock(inode); inode_lock(inode);
...@@ -1363,18 +1359,22 @@ static int f2fs_ioc_start_atomic_write(struct file *filp) ...@@ -1363,18 +1359,22 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
if (f2fs_is_atomic_file(inode)) if (f2fs_is_atomic_file(inode))
return 0; goto out;
ret = f2fs_convert_inline_inode(inode); ret = f2fs_convert_inline_inode(inode);
if (ret) if (ret)
return ret; goto out;
set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
if (!get_dirty_pages(inode)) if (!get_dirty_pages(inode))
return 0; goto out;
f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING, f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
"Unexpected flush for atomic writes: ino=%lu, npages=%u", "Unexpected flush for atomic writes: ino=%lu, npages=%u",
...@@ -1382,6 +1382,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp) ...@@ -1382,6 +1382,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
if (ret) if (ret)
clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
out:
mnt_drop_write_file(filp);
return ret; return ret;
} }
...@@ -1393,13 +1395,13 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) ...@@ -1393,13 +1395,13 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
if (f2fs_is_volatile_file(inode))
return 0;
ret = mnt_want_write_file(filp); ret = mnt_want_write_file(filp);
if (ret) if (ret)
return ret; return ret;
if (f2fs_is_volatile_file(inode))
goto err_out;
if (f2fs_is_atomic_file(inode)) { if (f2fs_is_atomic_file(inode)) {
clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
ret = commit_inmem_pages(inode); ret = commit_inmem_pages(inode);
...@@ -1423,32 +1425,48 @@ static int f2fs_ioc_start_volatile_write(struct file *filp) ...@@ -1423,32 +1425,48 @@ static int f2fs_ioc_start_volatile_write(struct file *filp)
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
if (f2fs_is_volatile_file(inode)) if (f2fs_is_volatile_file(inode))
return 0; goto out;
ret = f2fs_convert_inline_inode(inode); ret = f2fs_convert_inline_inode(inode);
if (ret) if (ret)
return ret; goto out;
set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return 0; out:
mnt_drop_write_file(filp);
return ret;
} }
static int f2fs_ioc_release_volatile_write(struct file *filp) static int f2fs_ioc_release_volatile_write(struct file *filp)
{ {
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
int ret;
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
if (!f2fs_is_volatile_file(inode)) if (!f2fs_is_volatile_file(inode))
return 0; goto out;
if (!f2fs_is_first_block_written(inode)) if (!f2fs_is_first_block_written(inode)) {
return truncate_partial_data_page(inode, 0, true); ret = truncate_partial_data_page(inode, 0, true);
goto out;
}
return punch_hole(inode, 0, F2FS_BLKSIZE); ret = punch_hole(inode, 0, F2FS_BLKSIZE);
out:
mnt_drop_write_file(filp);
return ret;
} }
static int f2fs_ioc_abort_volatile_write(struct file *filp) static int f2fs_ioc_abort_volatile_write(struct file *filp)
...@@ -1481,6 +1499,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -1481,6 +1499,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct super_block *sb = sbi->sb; struct super_block *sb = sbi->sb;
__u32 in; __u32 in;
int ret;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
...@@ -1488,6 +1507,10 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -1488,6 +1507,10 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
if (get_user(in, (__u32 __user *)arg)) if (get_user(in, (__u32 __user *)arg))
return -EFAULT; return -EFAULT;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
switch (in) { switch (in) {
case F2FS_GOING_DOWN_FULLSYNC: case F2FS_GOING_DOWN_FULLSYNC:
sb = freeze_bdev(sb->s_bdev); sb = freeze_bdev(sb->s_bdev);
...@@ -1509,10 +1532,13 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -1509,10 +1532,13 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
f2fs_stop_checkpoint(sbi); f2fs_stop_checkpoint(sbi);
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
f2fs_update_time(sbi, REQ_TIME); f2fs_update_time(sbi, REQ_TIME);
return 0; out:
mnt_drop_write_file(filp);
return ret;
} }
static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
...@@ -1533,9 +1559,14 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) ...@@ -1533,9 +1559,14 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
sizeof(range))) sizeof(range)))
return -EFAULT; return -EFAULT;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
range.minlen = max((unsigned int)range.minlen, range.minlen = max((unsigned int)range.minlen,
q->limits.discard_granularity); q->limits.discard_granularity);
ret = f2fs_trim_fs(F2FS_SB(sb), &range); ret = f2fs_trim_fs(F2FS_SB(sb), &range);
mnt_drop_write_file(filp);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1560,13 +1591,21 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) ...@@ -1560,13 +1591,21 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
{ {
struct fscrypt_policy policy; struct fscrypt_policy policy;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
int ret;
if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg, if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg,
sizeof(policy))) sizeof(policy)))
return -EFAULT; return -EFAULT;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return fscrypt_process_policy(inode, &policy); ret = fscrypt_process_policy(inode, &policy);
mnt_drop_write_file(filp);
return ret;
} }
static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg) static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
...@@ -1623,6 +1662,7 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg) ...@@ -1623,6 +1662,7 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
__u32 sync; __u32 sync;
int ret;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
...@@ -1633,20 +1673,30 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg) ...@@ -1633,20 +1673,30 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
if (f2fs_readonly(sbi->sb)) if (f2fs_readonly(sbi->sb))
return -EROFS; return -EROFS;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
if (!sync) { if (!sync) {
if (!mutex_trylock(&sbi->gc_mutex)) if (!mutex_trylock(&sbi->gc_mutex)) {
return -EBUSY; ret = -EBUSY;
goto out;
}
} else { } else {
mutex_lock(&sbi->gc_mutex); mutex_lock(&sbi->gc_mutex);
} }
return f2fs_gc(sbi, sync); ret = f2fs_gc(sbi, sync);
out:
mnt_drop_write_file(filp);
return ret;
} }
static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg) static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg)
{ {
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int ret;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
...@@ -1654,7 +1704,14 @@ static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg) ...@@ -1654,7 +1704,14 @@ static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg)
if (f2fs_readonly(sbi->sb)) if (f2fs_readonly(sbi->sb))
return -EROFS; return -EROFS;
return f2fs_sync_fs(sbi->sb, 1); ret = mnt_want_write_file(filp);
if (ret)
return ret;
ret = f2fs_sync_fs(sbi->sb, 1);
mnt_drop_write_file(filp);
return ret;
} }
static int f2fs_defragment_range(struct f2fs_sb_info *sbi, static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment