[Devel] [PATCH RHEL7 COMMIT] fs/fuse kio_pcs: make pcs_map_truncate() easier
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Nov 13 13:57:20 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.20.2.vz7.73.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.20.2.vz7.73.3
------>
commit 139fdee0db8cf74456efe77ef49fe63c0c048ed0
Author: Pavel Butsykin <pbutsykin at virtuozzo.com>
Date: Tue Nov 13 13:57:16 2018 +0300
fs/fuse kio_pcs: make pcs_map_truncate() easier
Taking into account that user-client does proper map invalidation at resize,
we don't need to completely copy the functionality of pcs_mapping_truncate().
Instead, it's enough to drop no longer used maps and set STALE_MAP error to
the last map. Then the next io will trigger call to user space and because
user space already has good map with newer version it will return it
immediately and kernel/user will be in sync again.
https://pmc.acronis.com/browse/VSTOR-16863
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
Acked-by: Alexey Kuznetsov <kuznet at virtuozzo.com>
---
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 26 +++---------------
fs/fuse/kio/pcs/pcs_map.c | 55 ++++++++++++++++++++++++--------------
fs/fuse/kio/pcs/pcs_map.h | 2 +-
3 files changed, 39 insertions(+), 44 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index a0225de80c0e..3b9a77cb6550 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -706,21 +706,11 @@ 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, *treq;
+ struct pcs_int_request *ireq, *next;
u64 size, old_size;
int err;
LIST_HEAD(pending_reqs);
@@ -773,18 +763,8 @@ static void fuse_size_grow_work(struct work_struct *w)
di->size.required = 0;
spin_unlock(&di->lock);
- 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);
+ pcs_mapping_truncate(di, old_size);
+ pcs_cc_requeue(di->cluster, &pending_reqs);
}
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_map.c b/fs/fuse/kio/pcs/pcs_map.c
index ec00cf238b1c..86b610fe746d 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -2460,13 +2460,18 @@ void process_ireq_truncate(struct pcs_int_request *ireq)
return;
}
-
-noinline void pcs_mapping_truncate(struct pcs_int_request *ireq, u64 old_size)
+/*
+ * Taking into account that user-client does proper map invalidation at resize,
+ * we don't need to completely copy the functionality of pcs_mapping_truncate().
+ * Instead, it's enough to drop no longer used maps and set STALE_MAP error to
+ * the last map. Then the next io will trigger call to user space and because
+ * user space already has good map with newer version it will return it
+ * immediately and kernel/user will be in sync again.
+ */
+noinline void pcs_mapping_truncate(struct pcs_dentry_info *di, u64 old_size)
{
- struct pcs_dentry_info *di = ireq->dentry;
- u64 new_size = DENTRY_SIZE(di);
- u64 offset;
- struct pcs_map_entry * m = NULL;
+ u64 new_size = DENTRY_SIZE(di), offset;
+ struct pcs_map_entry *m;
di->local_mtime = get_real_time_ms();
@@ -2478,32 +2483,42 @@ noinline void pcs_mapping_truncate(struct pcs_int_request *ireq, u64 old_size)
else
offset = new_size;
- ireq->truncreq.offset = offset;
- ireq->truncreq.phase = 0;
-
map_truncate_tail(&di->mapping, offset);
- if (offset == 0) {
- ireq_complete(ireq);
+ if (offset == 0)
return;
- }
m = pcs_find_get_map(di, offset - 1);
- FUSE_KTRACE(ireq->cc->fc, "mapping truncate %llu->%llu " DENTRY_FMT " %x", (unsigned long long)old_size,
- (unsigned long long)new_size, DENTRY_ARGS(ireq->dentry), m ? m->state : -1);
+ FUSE_KTRACE(di->cluster->fc, "mapping truncate %llu->%llu " DENTRY_FMT " %x",
+ (unsigned long long)old_size, (unsigned long long)new_size,
+ DENTRY_ARGS(di), m ? m->state : -1);
if (m == NULL) {
- map_queue_on_limit(ireq);
+ struct pcs_map_set *maps = &di->cluster->maps;
+ map_gc(maps);
return;
}
- if (map_chunk_end(m) == offset || valid_for_truncate(m, ireq)) {
- map_truncate_tail(&di->mapping, map_chunk_end(m));
- ireq_complete(ireq);
- } else
- pcs_map_queue_resolve(m, ireq, 1);
+ if (offset == map_chunk_end(m))
+ goto truncate_tail;
+ spin_lock(&m->lock);
+ if ((m->state & (PCS_MAP_ERROR|PCS_MAP_RESOLVING|PCS_MAP_NEW|PCS_MAP_READABLE)) ==
+ (PCS_MAP_NEW|PCS_MAP_READABLE)) {
+ spin_unlock(&m->lock);
+ goto truncate_tail;
+ }
+
+ if (!(m->state & (PCS_MAP_ERROR|PCS_MAP_RESOLVING|PCS_MAP_NEW)))
+ map_remote_error_nolock(m, PCS_ERR_CSD_STALE_MAP,
+ m->cs_list ? m->cs_list->cs[0].info.id.val : 0);
+ spin_unlock(&m->lock);
+ pcs_map_put(m);
+ return;
+
+truncate_tail:
+ map_truncate_tail(&di->mapping, map_chunk_end(m));
pcs_map_put(m);
}
diff --git a/fs/fuse/kio/pcs/pcs_map.h b/fs/fuse/kio/pcs/pcs_map.h
index ef8d56de0b30..14ae78af8e27 100644
--- a/fs/fuse/kio/pcs/pcs_map.h
+++ b/fs/fuse/kio/pcs/pcs_map.h
@@ -164,7 +164,7 @@ void pcs_mapping_init(struct pcs_cluster_core *cc, struct pcs_mapping * mapping)
void pcs_mapping_open(struct pcs_mapping * mapping);
void pcs_mapping_invalidate(struct pcs_mapping * mapping);
void pcs_mapping_deinit(struct pcs_mapping * mapping);
-void pcs_mapping_truncate(struct pcs_int_request *ireq, u64 old_size);
+void pcs_mapping_truncate(struct pcs_dentry_info *di, u64 old_size);
void process_ireq_truncate(struct pcs_int_request *ireq);
struct pcs_map_entry * pcs_find_get_map(struct pcs_dentry_info * de, u64 chunk);
More information about the Devel
mailing list