[RHEL7,COMMIT] fs/fuse kio_pcs: make pcs_map_truncate() easier

Submitted by Konstantin Khorenko on Nov. 13, 2018, 10:57 a.m.

Details

Message ID 201811131057.wADAvHlF018343@finist-ce7.sw.ru
State New
Series "fs/fuse kio_pcs: make pcs_map_truncate() easier"
Headers show

Commit Message

Konstantin Khorenko Nov. 13, 2018, 10:57 a.m.
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@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@virtuozzo.com>
    Acked-by: Alexey Kuznetsov <kuznet@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(-)

Patch hide | download patch | download mbox

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);