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

Reply via email to