[Devel] [PATCH RHEL7 COMMIT] fs/fuse: add non-blocking request flag
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Jul 25 18:05:15 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.9.1.vz7.63.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.9.1.vz7.63.2
------>
commit 735fe2738a862ede3b5b6880789d3d5dd107d812
Author: Pavel Butsykin <pbutsykin at virtuozzo.com>
Date: Wed Jul 25 18:05:14 2018 +0300
fs/fuse: add non-blocking request flag
This patch adds the ability to create non-blocking requests, it's necessary for
the implementation of throttling in kio. The active r/w kio requests can wait
for a pcs_map resolving, but in case when the inflight kio becomes equal to
fc->max_background, we will not be able to send PCS_IOC_GETMAP request,
as a result, it can lead to the hanging of kio requests that will endlessly wait
for pcs_map resolving. The same situation with PCS_IOC_CSCONN, cs_connect() is
performed under ep->mutex, so blocking PCS_IOC_CSCONN request could lead to
deadlock. In general, this patch is aimed to protect against such kind of hangs
when fc->max_background limit will work for kio requests.
https://pmc.acronis.com/browse/VSTOR-12335
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/dev.c | 26 ++++++++++++++++++++++++++
fs/fuse/fuse_i.h | 4 ++++
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 5 ++---
3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 707ac13ca52d..f7aca3094a83 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -216,6 +216,21 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
}
EXPORT_SYMBOL_GPL(fuse_get_req_for_background);
+struct fuse_req *fuse_get_nonblock_req_for_background(struct fuse_conn *fc,
+ unsigned npages)
+{
+ struct fuse_req *req = __fuse_get_req(fc, npages, false);
+ if (IS_ERR(req))
+ return req;
+
+ __set_bit(FR_BACKGROUND, &req->flags);
+ __set_bit(FR_NONBLOCKING, &req->flags);
+
+ return req;
+}
+
+EXPORT_SYMBOL_GPL(fuse_get_nonblock_req_for_background);
+
/*
* Return request in fuse_file->reserved_req. However that may
* currently be in use. If that is the case, wait for it to become
@@ -562,6 +577,17 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
set_bdi_congested(&fc->bdi, BLK_RW_SYNC);
set_bdi_congested(&fc->bdi, BLK_RW_ASYNC);
}
+
+ if (test_bit(FR_NONBLOCKING, &req->flags)) {
+ fc->active_background++;
+ spin_lock(&fiq->waitq.lock);
+ req->in.h.unique = fuse_get_unique(fiq);
+ queue_request(fiq, req);
+ spin_unlock(&fiq->waitq.lock);
+
+ return;
+ }
+
list_add_tail(&req->list, &fc->bg_queue);
flush_bg_queue(fc, fiq);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index da5cf0aed3ba..9069cddc42a2 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -297,6 +297,7 @@ struct fuse_io_priv {
* FR_SENT: request is in userspace, waiting for an answer
* FR_FINISHED: request is finished
* FR_PRIVATE: request is on private list
+ * FR_NONBLOCKING: non-blocking request (only needed for KIO)
*/
enum fuse_req_flag {
FR_ISREPLY,
@@ -310,6 +311,7 @@ enum fuse_req_flag {
FR_SENT,
FR_FINISHED,
FR_PRIVATE,
+ FR_NONBLOCKING,
};
/**
@@ -920,6 +922,8 @@ void fuse_request_free(struct fuse_conn *fc, struct fuse_req *req);
struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages);
struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
unsigned npages);
+struct fuse_req *fuse_get_nonblock_req_for_background(struct fuse_conn *fc,
+ unsigned npages);
/*
* Increment reference count on request
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 8a6f9e60fece..105869d6f81f 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -411,14 +411,13 @@ int fuse_map_resolve(struct pcs_map_entry *m, int direction)
kfree(map_ioc);
return -ENOMEM;
}
- req = fuse_get_req_for_background(fc, 0);
+ req = fuse_get_nonblock_req_for_background(fc, 0);
if (IS_ERR(req)) {
kfree(map_ioc);
kfree(reply_work);
return PTR_ERR(req);
}
-
memset(&req->misc.ioctl, 0, sizeof(req->misc.ioctl));
inarg = &req->misc.ioctl.in;
outarg = &req->misc.ioctl.out;
@@ -543,7 +542,7 @@ int fuse_pcs_csconn_send(struct fuse_conn *fc, struct pcs_rpc *ep, int flags)
return -ENOMEM;
}
- req = fuse_get_req_for_background(fc, 0);
+ req = fuse_get_nonblock_req_for_background(fc, 0);
if (IS_ERR(req)) {
kfree(csconn);
kfree(reply_work);
More information about the Devel
mailing list