mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
fs: fork splice_file_range() from do_splice_direct()
In preparation of calling do_splice_direct() without file_start_write() held, create a new helper splice_file_range(), to be called from context of ->copy_file_range() methods instead of do_splice_direct(). Currently, the only difference is that splice_file_range() does not take flags argument and that it asserts that file_start_write() is held, but we factor out a common helper do_splice_direct_actor() that will be used later. Use the new helper from __ceph_copy_file_range(), that was incorrectly passing to do_splice_direct() the copy flags argument as splice flags. The value of copy flags in ceph is always 0, so it is a smenatic bug fix. Move the declaration of both helpers to linux/splice.h. Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://lore.kernel.org/r/20231130141624.3338942-2-amir73il@gmail.com Acked-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
21b32e6a0a
commit
488e8f6852
@ -12,6 +12,7 @@
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/iversion.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/splice.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "mds_client.h"
|
||||
@ -3010,8 +3011,8 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
|
||||
* {read,write}_iter, which will get caps again.
|
||||
*/
|
||||
put_rd_wr_caps(src_ci, src_got, dst_ci, dst_got);
|
||||
ret = do_splice_direct(src_file, &src_off, dst_file,
|
||||
&dst_off, src_objlen, flags);
|
||||
ret = splice_file_range(src_file, &src_off, dst_file, &dst_off,
|
||||
src_objlen);
|
||||
/* Abort on short copies or on error */
|
||||
if (ret < (long)src_objlen) {
|
||||
doutc(cl, "Failed partial copy (%zd)\n", ret);
|
||||
@ -3065,8 +3066,8 @@ out_caps:
|
||||
*/
|
||||
if (len && (len < src_ci->i_layout.object_size)) {
|
||||
doutc(cl, "Final partial copy of %zu bytes\n", len);
|
||||
bytes = do_splice_direct(src_file, &src_off, dst_file,
|
||||
&dst_off, len, flags);
|
||||
bytes = splice_file_range(src_file, &src_off, dst_file,
|
||||
&dst_off, len);
|
||||
if (bytes > 0)
|
||||
ret += bytes;
|
||||
else
|
||||
|
@ -1423,10 +1423,8 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
struct file *file_out, loff_t pos_out,
|
||||
size_t len, unsigned int flags)
|
||||
{
|
||||
lockdep_assert(file_write_started(file_out));
|
||||
|
||||
return do_splice_direct(file_in, &pos_in, file_out, &pos_out,
|
||||
len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
|
||||
return splice_file_range(file_in, &pos_in, file_out, &pos_out,
|
||||
min_t(size_t, len, MAX_RW_COUNT));
|
||||
}
|
||||
EXPORT_SYMBOL(generic_copy_file_range);
|
||||
|
||||
|
75
fs/splice.c
75
fs/splice.c
@ -1170,6 +1170,34 @@ static void direct_file_splice_eof(struct splice_desc *sd)
|
||||
file->f_op->splice_eof(file);
|
||||
}
|
||||
|
||||
static long do_splice_direct_actor(struct file *in, loff_t *ppos,
|
||||
struct file *out, loff_t *opos,
|
||||
size_t len, unsigned int flags,
|
||||
splice_direct_actor *actor)
|
||||
{
|
||||
struct splice_desc sd = {
|
||||
.len = len,
|
||||
.total_len = len,
|
||||
.flags = flags,
|
||||
.pos = *ppos,
|
||||
.u.file = out,
|
||||
.splice_eof = direct_file_splice_eof,
|
||||
.opos = opos,
|
||||
};
|
||||
long ret;
|
||||
|
||||
if (unlikely(!(out->f_mode & FMODE_WRITE)))
|
||||
return -EBADF;
|
||||
|
||||
if (unlikely(out->f_flags & O_APPEND))
|
||||
return -EINVAL;
|
||||
|
||||
ret = splice_direct_to_actor(in, &sd, actor);
|
||||
if (ret > 0)
|
||||
*ppos = sd.pos;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* do_splice_direct - splices data directly between two files
|
||||
* @in: file to splice from
|
||||
@ -1190,31 +1218,34 @@ static void direct_file_splice_eof(struct splice_desc *sd)
|
||||
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
||||
loff_t *opos, size_t len, unsigned int flags)
|
||||
{
|
||||
struct splice_desc sd = {
|
||||
.len = len,
|
||||
.total_len = len,
|
||||
.flags = flags,
|
||||
.pos = *ppos,
|
||||
.u.file = out,
|
||||
.splice_eof = direct_file_splice_eof,
|
||||
.opos = opos,
|
||||
};
|
||||
long ret;
|
||||
|
||||
if (unlikely(!(out->f_mode & FMODE_WRITE)))
|
||||
return -EBADF;
|
||||
|
||||
if (unlikely(out->f_flags & O_APPEND))
|
||||
return -EINVAL;
|
||||
|
||||
ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
|
||||
if (ret > 0)
|
||||
*ppos = sd.pos;
|
||||
|
||||
return ret;
|
||||
return do_splice_direct_actor(in, ppos, out, opos, len, flags,
|
||||
direct_splice_actor);
|
||||
}
|
||||
EXPORT_SYMBOL(do_splice_direct);
|
||||
|
||||
/**
|
||||
* splice_file_range - splices data between two files for copy_file_range()
|
||||
* @in: file to splice from
|
||||
* @ppos: input file offset
|
||||
* @out: file to splice to
|
||||
* @opos: output file offset
|
||||
* @len: number of bytes to splice
|
||||
*
|
||||
* Description:
|
||||
* For use by generic_copy_file_range() and ->copy_file_range() methods.
|
||||
*
|
||||
* Callers already called rw_verify_area() on the entire range.
|
||||
*/
|
||||
long splice_file_range(struct file *in, loff_t *ppos, struct file *out,
|
||||
loff_t *opos, size_t len)
|
||||
{
|
||||
lockdep_assert(file_write_started(out));
|
||||
|
||||
return do_splice_direct_actor(in, ppos, out, opos, len, 0,
|
||||
direct_splice_actor);
|
||||
}
|
||||
EXPORT_SYMBOL(splice_file_range);
|
||||
|
||||
static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags)
|
||||
{
|
||||
for (;;) {
|
||||
|
@ -3052,8 +3052,6 @@ ssize_t copy_splice_read(struct file *in, loff_t *ppos,
|
||||
size_t len, unsigned int flags);
|
||||
extern ssize_t iter_file_splice_write(struct pipe_inode_info *,
|
||||
struct file *, loff_t *, size_t, unsigned int);
|
||||
extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
||||
loff_t *opos, size_t len, unsigned int flags);
|
||||
|
||||
|
||||
extern void
|
||||
|
@ -80,11 +80,14 @@ extern ssize_t add_to_pipe(struct pipe_inode_info *,
|
||||
long vfs_splice_read(struct file *in, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t len,
|
||||
unsigned int flags);
|
||||
extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
|
||||
splice_direct_actor *);
|
||||
extern long do_splice(struct file *in, loff_t *off_in,
|
||||
struct file *out, loff_t *off_out,
|
||||
size_t len, unsigned int flags);
|
||||
ssize_t splice_direct_to_actor(struct file *file, struct splice_desc *sd,
|
||||
splice_direct_actor *actor);
|
||||
long do_splice(struct file *in, loff_t *off_in, struct file *out,
|
||||
loff_t *off_out, size_t len, unsigned int flags);
|
||||
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
||||
loff_t *opos, size_t len, unsigned int flags);
|
||||
long splice_file_range(struct file *in, loff_t *ppos, struct file *out,
|
||||
loff_t *opos, size_t len);
|
||||
|
||||
extern long do_tee(struct file *in, struct file *out, size_t len,
|
||||
unsigned int flags);
|
||||
|
Loading…
Reference in New Issue
Block a user