The commit is pushed to "branch-rh7-3.10.0-957.12.2.vz7.96.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-957.12.2.vz7.96.10 ------> commit a4c0a32b5b78d6f542003b1917b1ab252db2ae16 Author: Pavel Butsykin <pbutsy...@virtuozzo.com> Date: Fri May 31 19:10:40 2019 +0300
fs/fuse kio: cosmetic changes in pcs_fuse_prep_rw() This is preparation patch with cosmetic changes in pcs_fuse_prep_rw(), it will be needed for the next patch. At first glance it seems there is no reason in performing pcs_fuse_prep_io() under di->lock, but it makes sense when kio request is queued to di->size.queue. If we release di->lock before pcs_fuse_prep_io(), then non-initialized request can begin to be processed in fuse_size_grow_work(). The same goes for inode_dio_begin(). This patch makes this point a little more obvious. Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> --- fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 117 +++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 43 deletions(-) diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c index 4dad29418e0d..50c39c0ab8e7 100644 --- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c +++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c @@ -857,18 +857,34 @@ static bool kqueue_insert(struct pcs_dentry_info *di, struct fuse_file *ff, return true; } +static inline int req_wait_grow_queue(struct pcs_fuse_req *r, + struct fuse_file *ff, u16 type, + off_t offset, size_t size) +{ + struct pcs_dentry_info *di = get_pcs_inode(r->req.io_inode); + + if (!kqueue_insert(di, ff, &r->req)) + return -EIO; + + pcs_fuse_prep_io(r, type, offset, size, 0); + inode_dio_begin(r->req.io_inode); + wait_grow(r, di, offset + size); + return 1; +} + /* * Check i size boundary and deffer request if necessary * Ret code * 0: ready for submission - * -1: should fail request + * -EIO: should fail request + * -EPERM: Nope * 1: request placed to pended queue */ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r, struct fuse_file *ff) { - struct fuse_inode *fi = get_fuse_inode(r->req.io_inode); - struct pcs_dentry_info *di = pcs_inode_from_fuse(fi); - int ret = 0; + struct fuse_req *req = &r->req; + struct pcs_dentry_info *di = get_pcs_inode(req->io_inode); + int ret; spin_lock(&di->lock); /* Deffer all requests if shrink requested to prevent livelock */ @@ -880,38 +896,45 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r, struct fuse_file *ff) } wait_shrink(r, di); ret = 1; - goto out; + goto pending; } - if (r->req.in.h.opcode == FUSE_READ) { + + switch (req->in.h.opcode) { + case FUSE_READ: { size_t size; - struct fuse_read_in *in = &r->req.misc.read.in; + struct fuse_read_in *in = &req->misc.read.in; size = in->size; if (in->offset + in->size > di->fileinfo.attr.size) { if (in->offset >= di->fileinfo.attr.size) { - r->req.out.args[0].size = 0; + req->out.args[0].size = 0; ret = -EPERM; - goto out; + goto fail; } size = di->fileinfo.attr.size - in->offset; } + spin_unlock(&di->lock); + pcs_fuse_prep_io(r, PCS_REQ_T_READ, in->offset, size, 0); - } else if (r->req.in.h.opcode == FUSE_WRITE) { - struct fuse_write_in *in = &r->req.misc.write.in; + break; + } + case FUSE_WRITE: { + struct fuse_write_in *in = &req->misc.write.in; if (in->offset + in->size > di->fileinfo.attr.size) { - if (!kqueue_insert(di, ff, &r->req)) { - ret = -EIO; - goto out; - } - wait_grow(r, di, in->offset + in->size); - ret = 1; + ret = req_wait_grow_queue(r, ff, PCS_REQ_T_WRITE, + in->offset, in->size); + goto pending; } + spin_unlock(&di->lock); + pcs_fuse_prep_io(r, PCS_REQ_T_WRITE, in->offset, in->size, 0); - } else if (r->req.in.h.opcode == FUSE_IOCTL) { + break; + } + case FUSE_IOCTL: { size_t size; - struct fiemap const *in = r->req.in.args[1].value; - struct fiemap *out = r->req.out.args[1].value; + struct fiemap const *in = req->in.args[1].value; + struct fiemap *out = req->out.args[1].value; *out = *in; out->fm_mapped_extents = 0; @@ -920,40 +943,48 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r, struct fuse_file *ff) if (in->fm_start + size > di->fileinfo.attr.size) { if (in->fm_start >= di->fileinfo.attr.size) { ret = -EPERM; - goto out; + goto fail; } size = di->fileinfo.attr.size - in->fm_start; } - pcs_fuse_prep_io(r, PCS_REQ_T_FIEMAP, in->fm_start, in->fm_extent_count*sizeof(struct fiemap_extent), + spin_unlock(&di->lock); + + pcs_fuse_prep_io(r, PCS_REQ_T_FIEMAP, in->fm_start, + in->fm_extent_count*sizeof(struct fiemap_extent), in->fm_extent_count); r->exec.io.req.size = size; - } else { - struct fuse_fallocate_in const *in = r->req.in.args[0].value; - - if (in->offset + in->length > di->fileinfo.attr.size) { - if (!kqueue_insert(di, ff, &r->req)) { - ret = -EIO; - goto out; - } - wait_grow(r, di, in->offset + in->length); - ret = 1; - } + break; + } + case FUSE_FALLOCATE: { + struct fuse_fallocate_in const *in = req->in.args[0].value; + u16 type; if (in->mode & FALLOC_FL_PUNCH_HOLE) - pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_HOLE, in->offset, in->length, 0); + type = PCS_REQ_T_WRITE_HOLE; else if (in->mode & FALLOC_FL_ZERO_RANGE) - pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_ZERO, in->offset, in->length, 0); + type = PCS_REQ_T_WRITE_ZERO; else { - if (ret) { - pcs_fuse_prep_fallocate(r); - } else { - ret = -EPERM; - goto out; - } + ret = -EPERM; + goto fail; } + + if (in->offset + in->length > di->fileinfo.attr.size) { + ret = req_wait_grow_queue(r, ff, type, in->offset, + in->length); + goto pending; + } + spin_unlock(&di->lock); + + pcs_fuse_prep_io(r, type, in->offset, in->length, 0); + break; } - inode_dio_begin(r->req.io_inode); -out: + default: + BUG(); + } + inode_dio_begin(req->io_inode); + return 0; +fail: +pending: spin_unlock(&di->lock); return ret; } _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel