fs/fuse kio: add support jumbo chunks

Submitted by Pavel Butsykin on June 5, 2019, 10:47 a.m.

Details

Message ID 20190605104700.15274-1-pbutsykin@virtuozzo.com
State New
Series "fs/fuse kio: add support jumbo chunks"
Headers show

Commit Message

Pavel Butsykin June 5, 2019, 10:47 a.m.
This patch adds support for chunks size > 4G in FPath.

#VSTOR-20454

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
---
 fs/fuse/kio/pcs/pcs_client_types.h |  6 +++---
 fs/fuse/kio/pcs/pcs_cs_prot.h      |  6 ++++--
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c |  9 ---------
 fs/fuse/kio/pcs/pcs_map.c          | 15 ++++++++++-----
 fs/fuse/kio/pcs/pcs_mds_prot.h     |  6 +++---
 fs/fuse/kio/pcs/pcs_prot_types.h   |  9 +++++++++
 fs/fuse/kio/pcs/pcs_req.c          |  3 +--
 7 files changed, 30 insertions(+), 24 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/kio/pcs/pcs_client_types.h b/fs/fuse/kio/pcs/pcs_client_types.h
index 5e72eb0fac3e..ec180b41cee4 100644
--- a/fs/fuse/kio/pcs/pcs_client_types.h
+++ b/fs/fuse/kio/pcs/pcs_client_types.h
@@ -90,9 +90,9 @@  static inline void pcs_set_fileinfo(struct pcs_dentry_info *i, const struct pcs_
 
 	if (mi->sys.stripe_depth == 0) {
 		mi->sys.stripe_depth = 1;
-		mi->sys.strip_width = mi->sys.chunk_size_lo;
+		mi->sys.strip_width = PCS_DEF_STRIP_WIDTH;
 	}
-	i->mapping.chunk_size_bits = ilog2(mi->sys.chunk_size_lo);
+	i->mapping.chunk_size_bits = ilog2(pcs_sys_info_get_chunk_size(&mi->sys));
 
 }
 
@@ -173,7 +173,7 @@  typedef struct _pcs_api_csconnreq_t {
 #define DENTRY_ARGS(de)	      PCS_FILE_ID_ARGS((de)->id.parent), PCS_FILE_ID_ARGS((de)->fileinfo.attr.id)
 
 #define DENTRY_SIZE(de)       ((de)->fileinfo.attr.size)
-#define DENTRY_CHUNK_SIZE(de) ((de)->fileinfo.sys.chunk_size_lo)
+#define DENTRY_CHUNK_SIZE(de) pcs_sys_info_get_chunk_size(&(de)->fileinfo.sys)
 #define DENTRY_CHUNK_SIZE_BITS(de) ((de)->mapping.chunk_size_bits)
 
 void pcs_mapset_limit(struct pcs_map_set *maps, int limit);
diff --git a/fs/fuse/kio/pcs/pcs_cs_prot.h b/fs/fuse/kio/pcs/pcs_cs_prot.h
index 8ca6cbabf741..e7545c55923d 100644
--- a/fs/fuse/kio/pcs/pcs_cs_prot.h
+++ b/fs/fuse/kio/pcs/pcs_cs_prot.h
@@ -67,6 +67,7 @@  struct pcs_cs_iohdr {
 	struct pcs_cs_sync_resp sync_resp[0];	/* Used only in response to write/sync */
 } __attribute__((aligned(8)));
 
+#define PCS_CS_MAX_IOSIZE      ((u32)-4096)
 
 /* Maximal message size. Actually, random */
 #define PCS_CS_MSG_MAX_SIZE	(1024*1024 + sizeof(struct pcs_cs_iohdr))
@@ -139,10 +140,11 @@  struct pcs_cs_map_prop {
 	/* During replication this version indicates the newest dirty mask version allowed to be using for recovery. */
 	PCS_MAP_VERSION_T	dirty_version;
 	u32			flags;	/* CS_MAPF_XXX */
-	u32			chunk_size;
+	u32			chunk_size_lo;
 	/* The maximum number of nodes in the chain. Intended to be using in timeout calculation. */
 	u16			chain_nodes;
-	u16			reserved;
+	u8			chunk_size_hi;
+	u8			reserved;
 	u32			nnodes;
 	struct pcs_cs_node_desc	nodes[0];
 } __attribute__((aligned(8)));
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 0d8cb3a751e2..ac5616e5cc1e 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -326,15 +326,6 @@  static int kpcs_do_file_open(struct fuse_conn *fc, struct file *file, struct ino
 
 	if (info.sys.map_type != PCS_MAP_PLAIN) {
 		TRACE("Unsupported map_type:%x, ignore\n", info.sys.map_type);
-
-		if (info.sys.map_type & PCS_JUMBO_CHUNK_FLAG)
-			pr_warn_once("kio: fpath doesn't support jumbo chunks\n");
-		return 0;
-	}
-
-	if (info.sys.chunk_size_hi) {
-		TRACE("Unsupported chunk_size_hi:%x\n", info.sys.chunk_size_hi);
-		pr_warn_once("kio: fpath doesn't support jumbo chunks\n");
 		return 0;
 	}
 
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index 273697b840ff..2ff07b773fe8 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -242,7 +242,7 @@  void pcs_mapping_dump(struct pcs_mapping * mapping)
 
 void map_truncate_tail(struct pcs_mapping * mapping, u64 offset)
 {
-	unsigned long pos = DIV_ROUND_UP(offset, 1 << mapping->chunk_size_bits);
+	unsigned long pos = DIV_ROUND_UP(offset, 1LLU << mapping->chunk_size_bits);
 	struct pcs_map_entry *maps[MAP_BATCH];
 	int nr_maps;
 	LIST_HEAD(dispose);
@@ -2337,17 +2337,22 @@  void map_submit(struct pcs_map_entry * m, struct pcs_int_request *ireq)
 
 		if (ireq->type != PCS_IREQ_FLUSH && !(ireq->flags & IREQ_F_MAPPED)) {
 			u64 pos = ireq->iochunk.chunk + ireq->iochunk.offset;
+			u64 iochunk;
 			BUG_ON(pos < map_start);
 			ireq->iochunk.chunk = map_start;
 			ireq->iochunk.offset = pos - ireq->iochunk.chunk;
-			if (pos + ireq->iochunk.size > map_end) {
+			iochunk = ireq->iochunk.size;
+			if (pos + ireq->iochunk.size > map_end)
+				iochunk = map_end - pos;
+			if (iochunk > PCS_CS_MAX_IOSIZE)
+				iochunk = PCS_CS_MAX_IOSIZE;
+			if (iochunk < ireq->iochunk.size) {
 				if (ireq->iochunk.cmd == PCS_REQ_T_FIEMAP) {
 					pcs_api_iorequest_t *ar = ireq->completion_data.parent->apireq.req;
-					ireq->iochunk.size = map_end - pos;
-					ar->size = ireq->iochunk.size;
+					ireq->iochunk.size = ar->size = iochunk;
 				} else {
 					struct pcs_int_request *sreq;
-					sreq = pcs_ireq_split(ireq, map_end - pos, 0);
+					sreq = pcs_ireq_split(ireq, iochunk, 0);
 					if (ireq->iochunk.map) {
 						pcs_map_put(ireq->iochunk.map);
 						ireq->iochunk.map = NULL;
diff --git a/fs/fuse/kio/pcs/pcs_mds_prot.h b/fs/fuse/kio/pcs/pcs_mds_prot.h
index 1dc1724fa94d..962b8296732c 100644
--- a/fs/fuse/kio/pcs/pcs_mds_prot.h
+++ b/fs/fuse/kio/pcs/pcs_mds_prot.h
@@ -1312,7 +1312,7 @@  struct pcs_mds_disk_info_msg {
 /* The function translates bytes offset in file to byte offset in actual storage.
  * This map is identical for plain layout and non trivial for RAID0 layout.
  */
-static inline u64 map_file_to_chunk(u64 pos, unsigned int chunk_size, unsigned int stripe_depth, unsigned int strip_width)
+static inline u64 map_file_to_chunk(u64 pos, u64 chunk_size, unsigned int stripe_depth, unsigned int strip_width)
 {
 	unsigned int strip_off, chunk_idx;
 	u64 base, strip_idx, chunk_off;
@@ -1321,9 +1321,9 @@  static inline u64 map_file_to_chunk(u64 pos, unsigned int chunk_size, unsigned i
 	if (stripe_depth == 1)
 		return pos;
 
-	group_size = (u64)chunk_size * stripe_depth;
+	group_size = chunk_size * stripe_depth;
 
-	base = (pos / group_size) * group_size;
+	base = round_down(pos, group_size);
 	pos -= base;
 
 	strip_off = pos % strip_width;
diff --git a/fs/fuse/kio/pcs/pcs_prot_types.h b/fs/fuse/kio/pcs/pcs_prot_types.h
index 11986252f23c..5a2adb7b62e5 100644
--- a/fs/fuse/kio/pcs/pcs_prot_types.h
+++ b/fs/fuse/kio/pcs/pcs_prot_types.h
@@ -120,6 +120,15 @@  struct __pre_aligned(8) pcs_mds_sys_info {
 	u32	reserved3;
 } __aligned(8);
 
+static inline u64 pcs_sys_info_get_chunk_size(struct pcs_mds_sys_info const *si)
+{
+	return ((u64)si->chunk_size_hi << 32) | si->chunk_size_lo;
+}
+
+/* Defaults and limits */
+#define PCS_DEF_CHUNK_SIZE 0x10000000 /* 256Mb */
+#define PCS_DEF_STRIP_WIDTH (1*1024*1024)
+
 #define PCS_CHUNK_SIZE_MIN 4096u
 #define PCS_CHUNK_SIZE_MAX 2147483648u
 #define PCS_STRIPE_DEPTH_MAX 64
diff --git a/fs/fuse/kio/pcs/pcs_req.c b/fs/fuse/kio/pcs/pcs_req.c
index 55fb39e91b93..d533e2d79bf5 100644
--- a/fs/fuse/kio/pcs/pcs_req.c
+++ b/fs/fuse/kio/pcs/pcs_req.c
@@ -83,8 +83,7 @@  void ireq_delay(struct pcs_int_request *ireq)
 
 void ireq_handle_hole(struct pcs_int_request *ireq)
 {
-	unsigned int len;
-	unsigned int offset;
+	u64 offset, len;
 	struct iov_iter it;
 	pcs_api_iorequest_t * ar = ireq->completion_data.parent->apireq.req;