[Devel] [PATCH 4/4] fs/fuse kio: keep fuse_file for requests waiting for shrink
Pavel Butsykin
pbutsykin at virtuozzo.com
Wed May 15 11:53:58 MSK 2019
A pending request due to shrink operation may lose passed fuse_file. To fix it,
let's take the reference and save ff pointer to req->ff and then release it in
req->end() callback.
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/file.c | 1 +
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 7929f4b6b346..611955c8ea7f 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -120,6 +120,7 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff)
atomic_inc(&ff->count);
return ff;
}
+EXPORT_SYMBOL_GPL(fuse_file_get);
static void fuse_release_async(struct work_struct *work)
{
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index ba53a7ac6472..7d1de6f86a4a 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -815,6 +815,17 @@ static void wait_shrink(struct pcs_fuse_req *r, struct pcs_dentry_info *di)
list_add_tail(&r->exec.ireq.list, &di->size.queue);
}
+static void _pcs_ff_free_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+ struct pcs_fuse_req *r = pcs_req_from_fuse(req);
+
+ BUG_ON(!req->ff);
+ fuse_release_ff(req->inode, req->ff);
+
+ if (r->end)
+ r->end(fc, req);
+}
+
static bool kqueue_insert(struct pcs_dentry_info *di, struct fuse_file *ff,
struct fuse_req *req)
{
@@ -844,6 +855,11 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r, struct fuse_file *ff)
spin_lock(&di->lock);
/* Deffer all requests if shrink requested to prevent livelock */
if (di->size.op == PCS_SIZE_SHRINK) {
+ if (ff && !r->req.ff) {
+ r->end = r->req.end;
+ r->req.ff = fuse_file_get(ff);
+ r->req.end = _pcs_ff_free_end;
+ }
wait_shrink(r, di);
ret = 1;
goto out;
--
2.15.1
More information about the Devel
mailing list