[Devel] [PATCH 1/2] fuse: add a new async operation to unmap regions
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Feb 6 23:49:30 MSK 2018
Andrey, this seems to be a feature and it should be tested.
Please post here a jira id with the feature description, QA task, etc.
And whom to review?
--
Best regards,
Konstantin Khorenko,
Virtuozzo Linux Kernel Team
On 02/06/2018 03:25 AM, Andrei Vagin wrote:
> The fuse interface allows to run any operation asynchronously, because
> the kernel redirect all operations to an user daemon and then waits an
> answer.
>
> In ploop, we want to handle discard requests via fallocate and
> a simplest way to do this is to run fallocate(FALLOC_FL_PUNCH_HOLE)
> asynchronously like the write command.
>
> This patch adds a new async command IOCB_CMD_UNMAP_ITER, which sends
> fallocate(FALLOC_FL_PUNCH_HOLE) to a fuse user daemon.
>
> Signed-off-by: Andrei Vagin <avagin at openvz.org>
> ---
> fs/aio.c | 1 +
> fs/fuse/file.c | 63 ++++++++++++++++++++++++++++++++++++++------
> fs/fuse/fuse_i.h | 3 +++
> include/uapi/linux/aio_abi.h | 1 +
> 4 files changed, 60 insertions(+), 8 deletions(-)
>
> diff --git a/fs/aio.c b/fs/aio.c
> index 3a6a9b0..cdc7558 100644
> --- a/fs/aio.c
> +++ b/fs/aio.c
> @@ -1492,6 +1492,7 @@ rw_common:
> ret = aio_read_iter(req);
> break;
>
> + case IOCB_CMD_UNMAP_ITER:
> case IOCB_CMD_WRITE_ITER:
> ret = aio_write_iter(req);
> break;
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 877c41f..83ea9da 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -920,6 +920,19 @@ static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req)
> if (!req->bvec)
> fuse_release_user_pages(req, !io->write);
>
> + if (req->in.h.opcode == FUSE_FALLOCATE) {
> + if (req->out.h.error)
> + printk("fuse_aio_complete_req: request (fallocate fh=0x%llx "
> + "offset=%lld length=%lld mode=%x) completed with err=%d\n",
> + req->misc.fallocate.in.fh,
> + req->misc.fallocate.in.offset,
> + req->misc.fallocate.in.length,
> + req->misc.fallocate.in.mode,
> + req->out.h.error);
> + fuse_aio_complete(io, req->out.h.error, -1);
> + return;
> + }
> +
> if (io->write) {
> if (req->misc.write.in.size != req->misc.write.out.size)
> pos = req->misc.write.in.offset - io->offset +
> @@ -1322,6 +1335,33 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
> req->out.args[0].value = outarg;
> }
>
> +static size_t fuse_send_unmap(struct fuse_req *req, struct fuse_io_priv *io,
> + loff_t pos, size_t count, fl_owner_t owner)
> +{
> + struct file *file = io->file;
> + struct fuse_file *ff = file->private_data;
> + struct fuse_conn *fc = ff->fc;
> + struct fuse_fallocate_in *inarg = &req->misc.fallocate.in;
> +
> + inarg->fh = ff->fh;
> + inarg->offset = pos;
> + inarg->length = count;
> + inarg->mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE;
> + req->in.h.opcode = FUSE_FALLOCATE;
> + req->in.h.nodeid = ff->nodeid;
> + req->in.numargs = 1;
> + req->in.args[0].size = sizeof(struct fuse_fallocate_in);
> + req->in.args[0].value = inarg;
> +
> + fuse_account_request(fc, count);
> +
> + if (io->async)
> + return fuse_async_req_send(fc, req, count, io);
> +
> + fuse_request_send(fc, req);
> + return count;
> +}
> +
> static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
> loff_t pos, size_t count, fl_owner_t owner)
> {
> @@ -3455,7 +3495,7 @@ static ssize_t fuse_direct_IO_bvec(int rw, struct kiocb *iocb,
> req->bvec = bvec;
> }
>
> - if (filled + bvec->bv_len <= nmax) {
> + if (bvec_len && filled + bvec->bv_len <= nmax) {
> filled += bvec->bv_len;
> req->num_bvecs++;
> bvec++;
> @@ -3465,14 +3505,21 @@ static ssize_t fuse_direct_IO_bvec(int rw, struct kiocb *iocb,
> continue;
> }
>
> - BUG_ON(!filled);
>
> - if (rw == WRITE)
> - nres = fuse_send_write(req, io, pos,
> - filled, NULL);
> - else
> - nres = fuse_send_read(req, io, pos,
> - filled, NULL);
> + if (iocb->ki_opcode == IOCB_CMD_UNMAP_ITER) {
> + req->in.argbvec = 0;
> + nres = fuse_send_unmap(req, io, pos,
> + iocb->ki_nbytes, NULL);
> + filled = nres;
> + } else {
> + BUG_ON(!filled);
> + if (rw == WRITE)
> + nres = fuse_send_write(req, io, pos,
> + filled, NULL);
> + else
> + nres = fuse_send_read(req, io, pos,
> + filled, NULL);
> + }
>
> BUG_ON(nres != filled);
> fuse_put_request(fc, req);
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 2da4520..b2edcf9 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -364,6 +364,9 @@ struct fuse_req {
> struct fuse_write_in in;
> struct fuse_write_out out;
> } write;
> + struct {
> + struct fuse_fallocate_in in;
> + } fallocate;
> struct fuse_notify_retrieve_in retrieve_in;
> struct fuse_lk_in lk_in;
> } misc;
> diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
> index 22ce4bd..ea2c346 100644
> --- a/include/uapi/linux/aio_abi.h
> +++ b/include/uapi/linux/aio_abi.h
> @@ -46,6 +46,7 @@ enum {
> IOCB_CMD_PWRITEV = 8,
> IOCB_CMD_READ_ITER = 9,
> IOCB_CMD_WRITE_ITER = 10,
> + IOCB_CMD_UNMAP_ITER = 11,
> };
>
> /*
>
More information about the Devel
mailing list