UPSTREAM: ANDROID: fuse-bpf: support FUSE_LSEEK

Adds support for lseek via fuse-bpf

Bug: 224855060
Test: bpf_test_lseek
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: Ic282940d53b9bb44a291cb3a5dfe09847b4e5c9a
This commit is contained in:
Daniel Rosenberg 2022-03-14 18:21:02 -07:00 • committed by Alexander Martinz
commit c49b8607f2
No known key found for this signature in database
GPG key ID: CF15BDD9A321A9B2
3 changed files with 80 additions and 0 deletions

View file

@ -403,6 +403,65 @@ void *fuse_flush_finalize(struct fuse_args *fa, struct file *file, fl_owner_t id
return NULL;
}
int fuse_lseek_initialize(struct fuse_args *fa, struct fuse_lseek_io *flio,
struct file *file, loff_t offset, int whence)
{
struct fuse_file *fuse_file = file->private_data;
flio->fli = (struct fuse_lseek_in) {
.fh = fuse_file->fh,
.offset = offset,
.whence = whence,
};
*fa = (struct fuse_args) {
.nodeid = get_node_id(file->f_inode),
.opcode = FUSE_LSEEK,
.in_numargs = 1,
.in_args[0].size = sizeof(flio->fli),
.in_args[0].value = &flio->fli,
.out_numargs = 1,
.out_args[0].size = sizeof(flio->flo),
.out_args[0].value = &flio->flo,
};
return 0;
}
int fuse_lseek_backing(struct fuse_args *fa, struct file *file, loff_t offset, int whence)
{
const struct fuse_lseek_in *fli = fa->in_args[0].value;
struct fuse_lseek_out *flo = fa->out_args[0].value;
struct fuse_file *fuse_file = file->private_data;
struct file *backing_file = fuse_file->backing_file;
loff_t ret;
/* TODO: Handle changing of the file handle */
if (offset == 0) {
if (whence == SEEK_CUR)
return file->f_pos;
if (whence == SEEK_SET)
return vfs_setpos(file, 0, 0);
}
inode_lock(file->f_inode);
backing_file->f_pos = file->f_pos;
ret = vfs_llseek(backing_file, fli->offset, fli->whence);
flo->offset = ret;
inode_unlock(file->f_inode);
return ret;
}
void *fuse_lseek_finalize(struct fuse_args *fa, struct file *file, loff_t offset, int whence)
{
struct fuse_lseek_out *flo = fa->out_args[0].value;
if (!fa->error_in)
file->f_pos = flo->offset;
return ERR_PTR(flo->offset);
}
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)

View file

@ -2779,6 +2779,17 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
{
loff_t retval;
struct inode *inode = file_inode(file);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_lseek_io,
fuse_lseek_initialize,
fuse_lseek_backing,
fuse_lseek_finalize,
file, offset, whence);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
switch (whence) {
case SEEK_SET:

View file

@ -1431,6 +1431,16 @@ 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_lseek_io {
struct fuse_lseek_in fli;
struct fuse_lseek_out flo;
};
int fuse_lseek_initialize(struct fuse_args *fa, struct fuse_lseek_io *fli,
struct file *file, loff_t offset, int whence);
int fuse_lseek_backing(struct fuse_args *fa, struct file *file, loff_t offset, int whence);
void *fuse_lseek_finalize(struct fuse_args *fa, struct file *file, loff_t offset, int whence);
struct fuse_copy_file_range_io {
struct fuse_copy_file_range_in fci;
struct fuse_write_out fwo;