[Devel] [PATCH 1/4] fs/fuse kio: forward fuse_file pointer to kpcs_req_send()
Pavel Butsykin
pbutsykin at virtuozzo.com
Wed May 15 11:53:55 MSK 2019
Unfortunately, synchronous requests don't reference ff, and at the same time use
page cache. In such a situation, it's just not possible to check ff->ff_state
inside pcs_fuse_submit(), that may lead to a race bug and as result deadlock
with fuse_invalidate_files(). To fix this, let's forward fuse_file pointer to
kpcs_req_send() for synchronous requests with pages.
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/dev.c | 6 +++---
fs/fuse/fuse_i.h | 4 ++--
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 12 +++++++-----
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index a43d0bfd8025..4a2cf4d236a9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -401,7 +401,7 @@ static void flush_bg_queue(struct fuse_conn *fc, struct fuse_iqueue *fiq)
list_del_init(&req->list);
fc->active_background++;
- if (fc->kio.op && !fc->kio.op->req_send(fc, req, true, true))
+ if (fc->kio.op && !fc->kio.op->req_send(fc, req, NULL, true, true))
continue;
spin_lock(&fiq->waitq.lock);
@@ -540,7 +540,7 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req,
BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
- if (fc->kio.op && !fc->kio.op->req_send(fc, req, false, false))
+ if (fc->kio.op && !fc->kio.op->req_send(fc, req, ff, false, false))
return;
spin_lock(&fiq->waitq.lock);
@@ -630,7 +630,7 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
bool fail;
WARN_ON(!req->end);
- if (fc->kio.op && !fc->kio.op->req_send(fc, req, true, false))
+ if (fc->kio.op && !fc->kio.op->req_send(fc, req, NULL, true, false))
return;
spin_lock(&fc->lock);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0ea0340c6b70..ab81131585d1 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -527,8 +527,8 @@ struct fuse_kio_ops {
/* Request handling hooks */
struct fuse_req *(*req_alloc)(struct fuse_conn *fc, unsigned nrpages,
gfp_t flags);
- int (*req_send)(struct fuse_conn *fc, struct fuse_req *req, bool bg,
- bool locked);
+ int (*req_send)(struct fuse_conn *fc, struct fuse_req *req,
+ struct fuse_file *ff, bool bg, bool locked);
/* Inode scope hooks */
int (*file_open)(struct fuse_conn *fc, struct file *file,
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 75bd8c6b91bc..efa2b4054215 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -903,7 +903,8 @@ 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, bool async, bool lk)
+static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, struct fuse_req *req,
+ struct fuse_file *ff, bool async, bool lk)
{
struct pcs_fuse_req *r = pcs_req_from_fuse(req);
struct fuse_inode *fi = get_fuse_inode(req->io_inode);
@@ -996,7 +997,7 @@ error:
submit:
spin_lock(&di->kq_lock);
- if (req->ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, &req->ff->ff_state)) {
+ if (ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state)) {
spin_unlock(&di->kq_lock);
req->out.h.error = -EIO;
goto error;
@@ -1070,7 +1071,7 @@ static void _pcs_shrink_end(struct fuse_conn *fc, struct fuse_req *req)
TRACE("resubmit %p\n", &r->req);
list_del_init(&ireq->list);
- pcs_fuse_submit(pfc, &r->req, true, false);
+ pcs_fuse_submit(pfc, &r->req, NULL, true, false);
}
}
@@ -1173,7 +1174,8 @@ fail:
return -EINVAL;
}
-static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bool lk)
+static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req,
+ struct fuse_file *ff, bool bg, bool lk)
{
struct pcs_fuse_cluster *pfc = (struct pcs_fuse_cluster*)fc->kio.ctx;
int ret;
@@ -1229,7 +1231,7 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
}
__clear_bit(FR_PENDING, &req->flags);
- pcs_fuse_submit(pfc, req, lk, lk);
+ pcs_fuse_submit(pfc, req, ff ? : req->ff, lk, lk);
if (!bg)
wait_event(req->waitq,
test_bit(FR_FINISHED, &req->flags) && !req->end);
--
2.15.1
More information about the Devel
mailing list