aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2016-09-23 11:38:11 +0300
committerMiklos Szeredi <mszeredi@redhat.com>2016-12-16 11:02:54 +0100
commit031a072a0b8ac2646def77aa310a95016c884bb0 (patch)
tree26e34c8c636fe13aa0d4e14cf16226333f6f43dd
parent913b86e92e1f68ab9db00ccb0fecf594732511e5 (diff)
downloadlinux-031a072a0b8ac2646def77aa310a95016c884bb0.tar.gz
vfs: call vfs_clone_file_range() under freeze protection
Move sb_start_write()/sb_end_write() out of the vfs helper and up into the ioctl handler. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/ioctl.c2
-rw-r--r--fs/nfsd/vfs.c3
-rw-r--r--fs/read_write.c3
-rw-r--r--include/linux/fs.h13
4 files changed, 15 insertions, 6 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 6715b7208835cb..cb9b02940805cb 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -226,7 +226,7 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
ret = -EXDEV;
if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
goto fdput;
- ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen);
+ ret = do_clone_file_range(src_file.file, off, dst_file, destoff, olen);
fdput:
fdput(src_file);
return ret;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8ca642fe9b21f5..357e844aee8440 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -509,8 +509,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
u64 dst_pos, u64 count)
{
- return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos,
- count));
+ return nfserrno(do_clone_file_range(src, src_pos, dst, dst_pos, count));
}
ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
diff --git a/fs/read_write.c b/fs/read_write.c
index 175d30e3b603be..c4e206b875d024 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1687,8 +1687,6 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
if (pos_in + len > i_size_read(inode_in))
return -EINVAL;
- sb_start_write(inode_out->i_sb);
-
ret = file_in->f_op->clone_file_range(file_in, pos_in,
file_out, pos_out, len);
if (!ret) {
@@ -1696,7 +1694,6 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
fsnotify_modify(file_out);
}
- sb_end_write(inode_out->i_sb);
return ret;
}
EXPORT_SYMBOL(vfs_clone_file_range);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dc0478c07b2abd..52663f1f308454 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1783,6 +1783,19 @@ extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
extern int vfs_dedupe_file_range(struct file *file,
struct file_dedupe_range *same);
+static inline int do_clone_file_range(struct file *file_in, loff_t pos_in,
+ struct file *file_out, loff_t pos_out,
+ u64 len)
+{
+ int ret;
+
+ sb_start_write(file_inode(file_out)->i_sb);
+ ret = vfs_clone_file_range(file_in, pos_in, file_out, pos_out, len);
+ sb_end_write(file_inode(file_out)->i_sb);
+
+ return ret;
+}
+
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *);