UPSTREAM: ANDROID: fuse-bpf: Add support for FUSE_COPY_FILE_RANGE

Bug: 217570523
Test: generic/075
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: I5feb75c83bc8bca2f44700d731f9f43e1eacf77c
This commit is contained in:
Daniel Rosenberg 2022-03-10 18:05:44 -08:00 • committed by Alexander Martinz
commit 03c20048f7
No known key found for this signature in database
GPG key ID: CF15BDD9A321A9B2
3 changed files with 89 additions and 0 deletions

View file

@ -403,6 +403,64 @@ void *fuse_flush_finalize(struct fuse_args *fa, struct file *file, fl_owner_t id
return NULL;
}
int fuse_copy_file_range_initialize(struct fuse_args *fa, struct fuse_copy_file_range_io *fcf,
struct file *file_in, loff_t pos_in, struct file *file_out,
loff_t pos_out, size_t len, unsigned int flags)
{
struct fuse_file *fuse_file_in = file_in->private_data;
struct fuse_file *fuse_file_out = file_out->private_data;
fcf->fci = (struct fuse_copy_file_range_in) {
.fh_in = fuse_file_in->fh,
.off_in = pos_in,
.nodeid_out = fuse_file_out->nodeid,
.fh_out = fuse_file_out->fh,
.off_out = pos_out,
.len = len,
.flags = flags,
};
*fa = (struct fuse_args) {
.nodeid = get_node_id(file_in->f_inode),
.opcode = FUSE_COPY_FILE_RANGE,
.in_numargs = 1,
.in_args[0].size = sizeof(fcf->fci),
.in_args[0].value = &fcf->fci,
.out_numargs = 1,
.out_args[0].size = sizeof(fcf->fwo),
.out_args[0].value = &fcf->fwo,
};
return 0;
}
int fuse_copy_file_range_backing(struct fuse_args *fa, struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, size_t len,
unsigned int flags)
{
const struct fuse_copy_file_range_in *fci = fa->in_args[0].value;
struct fuse_file *fuse_file_in = file_in->private_data;
struct file *backing_file_in = fuse_file_in->backing_file;
struct fuse_file *fuse_file_out = file_out->private_data;
struct file *backing_file_out = fuse_file_out->backing_file;
/* TODO: Handle changing of in/out files */
if (backing_file_out)
return vfs_copy_file_range(backing_file_in, fci->off_in, backing_file_out,
fci->off_out, fci->len, fci->flags);
else
return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
flags);
}
void *fuse_copy_file_range_finalize(struct fuse_args *fa, struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, size_t len,
unsigned int flags)
{
return NULL;
}
int fuse_fsync_initialize(struct fuse_args *fa, struct fuse_fsync_in *ffi,
struct file *file, loff_t start, loff_t end, int datasync)
{

View file

@ -3540,6 +3540,18 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
bool is_unstable = (!fc->writeback_cache) &&
((pos_out + len) > inode_out->i_size);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(file_in->f_inode, struct fuse_copy_file_range_io,
fuse_copy_file_range_initialize,
fuse_copy_file_range_backing,
fuse_copy_file_range_finalize,
file_in, pos_in, file_out, pos_out, len, flags);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fc->no_copy_file_range)
return -EOPNOTSUPP;

View file

@ -1431,6 +1431,25 @@ int fuse_flush_backing(struct fuse_args *fa, struct file *file, fl_owner_t id);
void *fuse_flush_finalize(struct fuse_args *fa,
struct file *file, fl_owner_t id);
struct fuse_copy_file_range_io {
struct fuse_copy_file_range_in fci;
struct fuse_write_out fwo;
};
int fuse_copy_file_range_initialize(struct fuse_args *fa,
struct fuse_copy_file_range_io *fcf,
struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags);
int fuse_copy_file_range_backing(struct fuse_args *fa,
struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags);
void *fuse_copy_file_range_finalize(struct fuse_args *fa,
struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags);
int fuse_fsync_initialize(struct fuse_args *fa, struct fuse_fsync_in *ffi,
struct file *file, loff_t start, loff_t end, int datasync);
int fuse_fsync_backing(struct fuse_args *fa,