ANDROID: fuse-bpf: Fix read_iter

We had a size mismatch for the return value, leading to EIOCBQUEUED
getting interpreted as a return size instead of an error code.

Test: generic/467, generic/013, and fuse_test
Bug: 217570523
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: I64f9d5263f8b37d3c0e286467f9351997b294cc2
This commit is contained in:
Daniel Rosenberg
2022-04-08 19:09:50 -07:00
parent 128ed57bca
commit 8be6e93244
3 changed files with 25 additions and 11 deletions

View File

@@ -846,29 +846,33 @@ static void fuse_bpf_aio_rw_complete(struct kiocb *iocb, long res, long res2)
int fuse_file_read_iter_initialize(
struct fuse_args *fa, struct fuse_read_in *fri,
struct fuse_args *fa, struct fuse_file_read_iter_io *fri,
struct kiocb *iocb, struct iov_iter *to)
{
struct file *file = iocb->ki_filp;
struct fuse_file *ff = file->private_data;
*fri = (struct fuse_read_in) {
fri->fri = (struct fuse_read_in) {
.fh = ff->fh,
.offset = iocb->ki_pos,
.size = to->count,
};
fri->frio = (struct fuse_read_iter_out) {
.ret = fri->fri.size,
};
/* TODO we can't assume 'to' is a kvec */
/* TODO we also can't assume the vector has only one component */
*fa = (struct fuse_args) {
.opcode = FUSE_READ,
.nodeid = ff->nodeid,
.in_numargs = 1,
.in_args[0].size = sizeof(*fri),
.in_args[0].value = fri,
.in_args[0].size = sizeof(fri->fri),
.in_args[0].value = &fri->fri,
.out_numargs = 1,
.out_args[0].size = fri->size,
.out_args[0].value = to->kvec->iov_base,
.out_args[0].size = sizeof(fri->frio),
.out_args[0].value = &fri->frio,
/*
* TODO Design this properly.
* Possible approach: do not pass buf to bpf
@@ -884,6 +888,7 @@ int fuse_file_read_iter_initialize(
int fuse_file_read_iter_backing(struct fuse_args *fa,
struct kiocb *iocb, struct iov_iter *to)
{
struct fuse_read_iter_out *frio = fa->out_args[0].value;
struct file *file = iocb->ki_filp;
struct fuse_file *ff = file->private_data;
ssize_t ret;
@@ -918,8 +923,7 @@ int fuse_file_read_iter_backing(struct fuse_args *fa,
fuse_bpf_aio_cleanup_handler(aio_req);
}
if (ret >= 0)
fa->out_args[0].size = ret;
frio->ret = ret;
/* TODO Need to point value at the buffer for post-modification */
@@ -932,7 +936,9 @@ out:
void *fuse_file_read_iter_finalize(struct fuse_args *fa,
struct kiocb *iocb, struct iov_iter *to)
{
return ERR_PTR(fa->out_args[0].size);
struct fuse_read_iter_out *frio = fa->out_args[0].value;
return ERR_PTR(frio->ret);
}
int fuse_file_write_iter_initialize(

View File

@@ -1643,7 +1643,7 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_read_in,
fer = fuse_bpf_backing(inode, struct fuse_file_read_iter_io,
fuse_file_read_iter_initialize,
fuse_file_read_iter_backing,
fuse_file_read_iter_finalize,

View File

@@ -1512,8 +1512,16 @@ int fuse_removexattr_backing(struct fuse_args *fa,
void *fuse_removexattr_finalize(struct fuse_args *fa,
struct dentry *dentry, const char *name);
struct fuse_read_iter_out {
uint64_t ret;
};
struct fuse_file_read_iter_io {
struct fuse_read_in fri;
struct fuse_read_iter_out frio;
};
int fuse_file_read_iter_initialize(
struct fuse_args *fa, struct fuse_read_in *fri,
struct fuse_args *fa, struct fuse_file_read_iter_io *fri,
struct kiocb *iocb, struct iov_iter *to);
int fuse_file_read_iter_backing(struct fuse_args *fa,
struct kiocb *iocb, struct iov_iter *to);