The commit is pushed to "branch-rh9-5.14.0-427.44.1.vz9.80.x-ovz" and will 
appear at g...@bitbucket.org:openvz/vzkernel.git
after rh9-5.14.0-427.44.1.vz9.80.23
------>
commit dd6421ab35d0cf479033061b28f055404d7a16c7
Author: Alexey Kuznetsov <kuz...@virtuozzo.com>
Date:   Fri Mar 28 20:00:58 2025 +0800

    fs/fuse/kio: keep kio requests on revoke list at all times
    
    Before kio request is submitted downstream is it off revoke list.
    This was a bug, but it was directly required by bogus revoke
    logic which stole page cache pages from requests. So, we processed
    pages while the req was isolated from revocation, which would
    result in deadlock. Now we keep pages accounted as they should,
    so we can move adding to revocation list as early as possible.
    
    Note: also this means requests queued for expand/truncate
    were invisible to pending request list, now we fix this.
    
    Note2: we should consider adding request to revocation list
    immediately when it is created and becomes parsable. This would
    make fuse_invalidate_files() a lot simpler and less bug prone,
    yet there is danger to clash with place where abort is skipped
    intentionally due to being of the lists. This work is already
    done, but it is still not in a state appropriate for release.
    
    Affects: #VSTOR-100953
    https://virtuozzo.atlassian.net/browse/VSTOR-100953
    
    Signed-off-by: Alexey Kuznetsov <kuz...@virtuozzo.com>
    
    Feature: vStorage
---
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 44 +++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c 
b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index e3049ddaa091..1b3bc8f45563 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -849,14 +849,18 @@ static bool kqueue_insert(struct pcs_dentry_info *di, 
struct fuse_req *req)
        return true;
 }
 
+static void kqueue_remove(struct pcs_dentry_info *di, struct fuse_req *req)
+{
+       spin_lock(&di->kq_lock);
+       list_del_init(&req->list);
+       spin_unlock(&di->kq_lock);
+}
+
 static inline int req_wait_grow_queue(struct pcs_fuse_req *r, off_t offset, 
size_t size)
 {
        struct pcs_dentry_info *di = get_pcs_inode(r->req.args->io_inode);
        struct fuse_inode *fi = get_fuse_inode(r->req.args->io_inode);
 
-       if (!kqueue_insert(di, &r->req))
-               return -EIO;
-
        BUG_ON(r->req.in.h.opcode != FUSE_WRITE && r->req.in.h.opcode != 
FUSE_FALLOCATE);
        fuse_write_dio_begin(fi);
 
@@ -980,9 +984,10 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
                BUG();
        }
 
-       if (!kqueue_insert(di, req))
+       if (req->args->ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, 
&req->args->ff->ff_state))
                ret = -EIO;
-       else if (req->in.h.opcode == FUSE_READ || req->in.h.opcode == 
FUSE_FSYNC || req->in.h.opcode == FUSE_FLUSH)
+       else if (req->in.h.opcode == FUSE_READ || req->in.h.opcode == 
FUSE_FSYNC ||
+           req->in.h.opcode == FUSE_FLUSH)
                fuse_read_dio_begin(fi);
        else
                fuse_write_dio_begin(fi);
@@ -992,14 +997,13 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
        return ret;
 }
 
-static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, struct fuse_req *req)
+static int pcs_fuse_submit_prepare(struct pcs_fuse_cluster *pfc, struct 
fuse_req *req)
 {
        struct pcs_fuse_req *r = pcs_req_from_fuse(req);
        struct fuse_args *args = req->args;
        struct fuse_inode *fi = get_fuse_inode(args->io_inode);
        struct pcs_dentry_info *di = pcs_inode_from_fuse(fi);
-       struct pcs_int_request* ireq;
-       int ret;
+       int ret = 0;
 
        BUG_ON(!di);
        BUG_ON(req->cache != pcs_fuse_req_cachep);
@@ -1007,8 +1011,21 @@ static void pcs_fuse_submit(struct pcs_fuse_cluster 
*pfc, struct fuse_req *req)
        /* Init pcs_fuse_req */
        memset(&r->exec, 0, sizeof(r->exec));
        /* Use inline request structure */
-       ireq = &r->exec.ireq;
-       ireq_init(di, ireq);
+       ireq_init(di, &r->exec.ireq);
+
+       spin_lock(&di->lock);
+       if (!kqueue_insert(di, req))
+               ret = -EIO;
+       spin_unlock(&di->lock);
+       return ret;
+}
+
+static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, struct fuse_req *req)
+{
+       struct pcs_fuse_req *r = pcs_req_from_fuse(req);
+       struct pcs_int_request *ireq = &r->exec.ireq;
+       struct pcs_dentry_info *di = ireq->dentry;
+       int ret;
 
        switch (req->in.h.opcode) {
        case FUSE_WRITE:
@@ -1026,7 +1043,7 @@ static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, 
struct fuse_req *req)
                }
                break;
        case FUSE_FALLOCATE: {
-               struct fuse_fallocate_in *inarg = (void*) 
args->in_args[0].value;
+               struct fuse_fallocate_in *inarg = (void 
*)req->args->in_args[0].value;
                size_t sz = READ_ONCE(di->fileinfo.attr.size);
 
                if (pfc->fc->no_fallocate) {
@@ -1062,7 +1079,7 @@ static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, 
struct fuse_req *req)
                         * and as i_size is still not advanced all the 
following ones are.
                         */
                        WARN_ON_ONCE(inarg->offset + inarg->length > sz &&
-                                    !inode_is_locked(&fi->inode));
+                                    !inode_is_locked(req->args->io_inode));
                }
 
                ret = pcs_fuse_prep_rw(r);
@@ -1097,6 +1114,7 @@ static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, 
struct fuse_req *req)
 error:
        DTRACE("do fuse_request_end req:%p op:%d err:%d\n", req, 
req->in.h.opcode, req->out.h.error);
 
+       kqueue_remove(di, req);
        __fuse_request_end(req, false);
        return;
 
@@ -1320,6 +1338,8 @@ static void kpcs_req_send(struct fuse_req *req, bool bg)
                refcount_inc(&req->count);
        __clear_bit(FR_PENDING, &req->flags);
 
+       pcs_fuse_submit_prepare(pfc, req);
+
        pcs_fuse_submit(pfc, req);
        if (!bg)
                wait_event(req->waitq,
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to