[Devel] [PATCH RHEL7 COMMIT] fs/fuse kio_pcs: drop old mapping after size growth
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Oct 18 13:26:28 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.11
------>
commit 02c5c75b59e403209d9bc23071cb884aff34ff60
Author: Pavel Butsykin <pbutsykin at virtuozzo.com>
Date: Wed Jul 25 18:40:21 2018 +0300
fs/fuse kio_pcs: drop old mapping after size growth
With kio FUSE_SETATTR sends request to MDS to expand file size. Then
vstorage-mount queries new map from MDS. MDS pushes updates to CSes,
which makes current map cached in kio invalid, CSes will reject all IO
with PCS_ERR_CSD_STALE_MAP.
This behavior leads to the fact that all requests waiting for a grow size will
do extra work and will be sent twice to CS. Let's drop the mapping from cache
immediately after submit_size_grow() to avoid slow writes during file growth.
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 30 ++++++++++++++++++++++++++----
fs/fuse/kio/pcs/pcs_req.h | 1 +
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index b286a956a751..e30463233e8a 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -706,18 +706,29 @@ static int submit_size_grow(struct inode *inode, unsigned long long size)
}
+static void truncate_complete(struct pcs_int_request *treq)
+{
+ if (pcs_if_error(&treq->error)) {
+ TRACE("truncate offs: %llu error: %d \n",
+ treq->truncreq.offset, treq->error.value);
+ }
+ pcs_cc_requeue(treq->cc, &treq->truncreq.waiters);
+ ireq_destroy(treq);
+}
+
static void fuse_size_grow_work(struct work_struct *w)
{
struct pcs_dentry_info* di = container_of(w, struct pcs_dentry_info, size.work);
struct inode *inode = &di->inode->inode;
- struct pcs_int_request* ireq, *next;
- unsigned long long size;
+ struct pcs_int_request *ireq, *next, *treq;
+ u64 size, old_size;
int err;
LIST_HEAD(pending_reqs);
spin_lock(&di->lock);
BUG_ON(di->size.op != PCS_SIZE_INACTION);
+ old_size = DENTRY_SIZE(di);
size = di->size.required;
if (!size) {
BUG_ON(!list_empty(&di->size.queue));
@@ -725,7 +736,7 @@ static void fuse_size_grow_work(struct work_struct *w)
TRACE("No more pending writes\n");
return;
}
- BUG_ON(di->fileinfo.attr.size >= size);
+ BUG_ON(old_size >= size);
list_splice_tail_init(&di->size.queue, &pending_reqs);
di->size.op = PCS_SIZE_GROW;
@@ -762,7 +773,18 @@ static void fuse_size_grow_work(struct work_struct *w)
di->size.required = 0;
spin_unlock(&di->lock);
- pcs_cc_requeue(di->cluster, &pending_reqs);
+ treq = ireq_alloc(di);
+ if (!treq) {
+ TRACE("Can't allocate treq\n");
+ pcs_cc_requeue(di->cluster, &pending_reqs);
+ return;
+ }
+ /* Drop old mapping from cache */
+ treq->type = PCS_IREQ_TRUNCATE;
+ treq->complete_cb = truncate_complete;
+ INIT_LIST_HEAD(&treq->truncreq.waiters);
+ list_splice(&pending_reqs, &treq->truncreq.waiters);
+ pcs_mapping_truncate(treq, old_size);
}
static void wait_grow(struct pcs_fuse_req *r, struct pcs_dentry_info *di, unsigned long long required)
diff --git a/fs/fuse/kio/pcs/pcs_req.h b/fs/fuse/kio/pcs/pcs_req.h
index e4b66d142734..e668e55f0b71 100644
--- a/fs/fuse/kio/pcs/pcs_req.h
+++ b/fs/fuse/kio/pcs/pcs_req.h
@@ -131,6 +131,7 @@ struct pcs_int_request
u64 offset;
int phase;
PCS_MAP_VERSION_T version;
+ struct list_head waiters;
} truncreq;
struct {
More information about the Devel
mailing list