[Devel] [PATCH VZ9 04/20] fuse: direct access to journaled cs

Alexey Kuznetsov kuznet at virtuozzo.com
Fri Oct 6 13:42:35 MSK 2023


Data checksumming was requied. The patch implements required modficiations
to communication protocol and io engine.

Also, the patch implements two ioctls which are present in user space
but were ignored in kio, PCS_IOC_NOWRITEDELAY and PCS_IOC_NOCSUMONREAD.
The last one is especially important from user viewpoint, it can be used
in places where user has its own integrity protection and can relieve
vstorage.

Signed-off-by: Alexey Kuznetsov <kuznet at acronis.com>
---
 fs/fuse/ioctl.c                    |   7 ++
 fs/fuse/kio/pcs/pcs_client_types.h |   2 +
 fs/fuse/kio/pcs/pcs_cs.c           |  12 ++-
 fs/fuse/kio/pcs/pcs_cs_accel.c     | 189 ++++++++++++++++++++++++++++++++++++-
 fs/fuse/kio/pcs/pcs_cs_prot.h      |   3 +
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c |  58 ++++++++++--
 fs/fuse/kio/pcs/pcs_ioctl.h        |   9 +-
 fs/fuse/kio/pcs/pcs_req.h          |   8 ++
 8 files changed, 266 insertions(+), 22 deletions(-)

diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c
index 310cd25..ee3b882 100644
--- a/fs/fuse/ioctl.c
+++ b/fs/fuse/ioctl.c
@@ -356,6 +356,13 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd,
 		return fc->kio.op->ioctl(file, inode, req.cmd, req.data, req.len);
 	}
 
+	if (fc->kio.op && fc->kio.op->ioctl) {
+		int err;
+		err = fc->kio.op->ioctl(file, inode, cmd, arg, -1);
+		if (err != -ENOIOCTLCMD)
+			return err;
+	}
+
 	return fuse_do_ioctl(file, cmd, arg, flags);
 }
 
diff --git a/fs/fuse/kio/pcs/pcs_client_types.h b/fs/fuse/kio/pcs/pcs_client_types.h
index 10ffa14..0b06a0e 100644
--- a/fs/fuse/kio/pcs/pcs_client_types.h
+++ b/fs/fuse/kio/pcs/pcs_client_types.h
@@ -78,6 +78,8 @@ struct pcs_dentry_info {
 	struct fuse_inode	*inode;
 	struct list_head	kq;
 	spinlock_t		kq_lock;
+	unsigned char		no_csum_on_read;
+	unsigned char		no_write_delay;
 
 	struct fuse_io_cnt stat;
 };
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index 7e5070d..4af8f16 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -609,7 +609,8 @@ void pcs_cs_submit(struct pcs_cs *cs, struct pcs_int_request *ireq)
 	int storage_version = atomic_read(&ireq->cc->storage_version);
 	int aligned_msg;
 
-	if (ireq->iochunk.cmd == PCS_REQ_T_READ && !((ireq->iochunk.size|ireq->iochunk.offset) & 511)) {
+	if (ireq->iochunk.cmd == PCS_REQ_T_READ && !((ireq->iochunk.size|ireq->iochunk.offset) & 511) &&
+	    !(ireq->flags & IREQ_F_NO_ACCEL)) {
 		if (pcs_csa_cs_submit(cs, ireq))
 			return;
 	}
@@ -631,8 +632,8 @@ void pcs_cs_submit(struct pcs_cs *cs, struct pcs_int_request *ireq)
 		if (aligned_msg)
 			ioh->hdr.type = PCS_CS_WRITE_AL_REQ;
 		else
-			ioh->hdr.type = (ireq->dentry->fileinfo.attr.attrib & PCS_FATTR_IMMEDIATE_WRITE) ?
-					PCS_CS_WRITE_SYNC_REQ : PCS_CS_WRITE_REQ;
+			ioh->hdr.type = ((ireq->dentry->fileinfo.attr.attrib & PCS_FATTR_IMMEDIATE_WRITE) ||
+					 ireq->dentry->no_write_delay) ? PCS_CS_WRITE_SYNC_REQ : PCS_CS_WRITE_REQ;
 		ioh->hdr.len = pcs_cs_msg_size(ioh->hdr.len + ireq->iochunk.size,
 					       storage_version);
 		break;
@@ -657,8 +658,9 @@ void pcs_cs_submit(struct pcs_cs *cs, struct pcs_int_request *ireq)
 
 	if (ireq->flags & IREQ_F_SEQ)
 		ioh->sync.misc = PCS_CS_IO_SEQ;
-
-	if (ireq->dentry->fileinfo.attr.attrib & PCS_FATTR_IMMEDIATE_WRITE)
+	if (ireq->dentry->no_csum_on_read)
+                ioh->sync.misc |= PCS_CS_IO_NOCSUM;
+	if ((ireq->dentry->fileinfo.attr.attrib & PCS_FATTR_IMMEDIATE_WRITE) || ireq->dentry->no_write_delay)
 		ioh->sync.misc |= PCS_CS_IO_SYNC;
 
 	msg->size = ioh->hdr.len;
diff --git a/fs/fuse/kio/pcs/pcs_cs_accel.c b/fs/fuse/kio/pcs/pcs_cs_accel.c
index 9444f75..24a962f 100644
--- a/fs/fuse/kio/pcs/pcs_cs_accel.c
+++ b/fs/fuse/kio/pcs/pcs_cs_accel.c
@@ -5,6 +5,8 @@
 #include <linux/log2.h>
 #include <linux/module.h>
 #include <linux/anon_inodes.h>
+#include <linux/pagemap.h>
+#include <crypto/hash.h>
 
 #include "pcs_types.h"
 #include "pcs_sock_io.h"
@@ -52,6 +54,7 @@ struct pcs_csa_entry
 	unsigned int		flags;
 	int			dead;
 	struct file		*file;
+	struct file		*cfile;
 };
 
 static inline void __cse_destroy(struct pcs_csa_entry * cse)
@@ -60,6 +63,10 @@ static inline void __cse_destroy(struct pcs_csa_entry * cse)
 		fput(cse->file);
 		cse->file = NULL;
 	}
+	if (cse->cfile) {
+		fput(cse->cfile);
+		cse->cfile = NULL;
+	}
 	kmem_cache_free(pcs_csa_cachep, cse);
 }
 
@@ -139,7 +146,7 @@ static inline struct pcs_csa_entry * cse_lookup(struct pcs_csa_context * ctx, u6
 }
 
 static int csa_update(struct pcs_csa_context * ctx, PCS_CHUNK_UID_T chunk_id, u32 flags, PCS_MAP_VERSION_T * vers,
-		      struct file * file)
+		      struct file * file, struct file * cfile)
 {
 	struct pcs_csa_entry * csa, * csb;
 
@@ -157,6 +164,9 @@ static int csa_update(struct pcs_csa_context * ctx, PCS_CHUNK_UID_T chunk_id, u3
 		return 0;
 	}
 
+	if ((flags & PCS_CSA_FL_CSUM) && !crc_tfm)
+		return -EOPNOTSUPP;
+
 	csb = kmem_cache_zalloc(pcs_csa_cachep, GFP_NOIO);
 	if (!csb)
 		return -ENOMEM;
@@ -166,6 +176,10 @@ static int csa_update(struct pcs_csa_context * ctx, PCS_CHUNK_UID_T chunk_id, u3
 	csb->flags = flags;
 	csb->file = file;
 	get_file(file);
+	if (cfile) {
+		csb->cfile = cfile;
+		get_file(cfile);
+	}
 
 again:
 	if (radix_tree_preload(GFP_NOIO)) {
@@ -174,6 +188,10 @@ static int csa_update(struct pcs_csa_context * ctx, PCS_CHUNK_UID_T chunk_id, u3
 	}
 
 	spin_lock(&ctx->lock);
+	/* This is wrong to delete entry before insert. rcu lookup will see
+	 * the gap. Not disasterous for us but dirty yet.
+	 * But I do not see appropriate function in lib/radix-tree.c
+	 */
 	csa = radix_tree_lookup(&ctx->tree, chunk_id);
 	if (csa) {
 		void *ret;
@@ -202,6 +220,51 @@ static int csa_update(struct pcs_csa_context * ctx, PCS_CHUNK_UID_T chunk_id, u3
 	return 0;
 }
 
+static int verify_crc(struct pcs_int_request * ireq, u32 * crc)
+{
+	struct iov_iter it;
+	struct pcs_int_request *parent = ireq->completion_data.parent;
+	pcs_api_iorequest_t *ar = parent->apireq.req;
+	char crc_desc[sizeof(struct shash_desc) + 4] __aligned(__alignof__(struct shash_desc));
+	struct shash_desc *shash = (struct shash_desc *)crc_desc;
+	int i;
+
+	shash->tfm = crc_tfm;
+
+	ar->get_iter(ar->datasource, ireq->iochunk.dio_offset, &it, 0);
+
+	for (i = 0; i < ireq->iochunk.size/4096; i++) {
+		unsigned int left = 4096;
+		u32 ccrc;
+
+		*(u32*)shash->__ctx = ~0U;
+
+		do {
+			size_t offset;
+			int len;
+			struct page * page;
+
+			len = iov_iter_get_pages(&it, &page, left, 1, &offset);
+			BUG_ON(len <= 0);
+
+			crypto_shash_alg(crc_tfm)->update(shash, kmap(page) + offset, len);
+			kunmap(page);
+			put_page(page);
+			iov_iter_advance(&it, len);
+			left -= len;
+		} while (left > 0);
+
+		crypto_shash_alg(crc_tfm)->final(shash, (u8*)&ccrc);
+
+		if (ccrc != crc[i]) {
+			FUSE_KTRACE(ireq->cc->fc, "CRC error pg=%d@%u %08x %08x\n", i,
+				    (unsigned)ireq->iochunk.offset, ccrc, crc[i]);
+			return 1;
+		}
+	}
+	return 0;
+}
+
 static void pcs_csa_do_completion(struct pcs_aio_req *areq)
 {
 	struct pcs_int_request * ireq;
@@ -213,6 +276,21 @@ static void pcs_csa_do_completion(struct pcs_aio_req *areq)
 
 	ireq = container_of(areq, struct pcs_int_request, iochunk.ar);
 
+	if (areq->crc) {
+		if (!pcs_if_error(&ireq->error)) {
+			if (verify_crc(ireq, areq->crc)) {
+				ireq->error.remote = 1;
+				ireq->error.offender = ireq->iochunk.csl->cs[ireq->iochunk.cs_index].info.id;
+				ireq->error.value = PCS_ERR_IO;
+			}
+		}
+
+		if (areq->crc && areq->crc != areq->crcb) {
+			kfree(areq->crc);
+			areq->crc = NULL;
+		}
+	}
+
 	if (!pcs_if_error(&ireq->error)) {
 		struct fuse_conn * fc = ireq->cc->fc;
 
@@ -250,6 +328,7 @@ static void pcs_csa_do_completion(struct pcs_aio_req *areq)
 		      ireq, (unsigned long long)ireq->iochunk.chunk,
 		      (unsigned)ireq->iochunk.offset,
 		      (unsigned)ireq->iochunk.size);
+		ireq->flags |= IREQ_F_NO_ACCEL;
 	}
 
 	ireq_complete(ireq);
@@ -262,6 +341,66 @@ static void csa_complete_work(struct work_struct *w)
 	pcs_csa_do_completion(areq);
 }
 
+static inline int quick_crc_fetch(struct pcs_int_request * ireq, struct file * cfile)
+{
+	unsigned offset = (ireq->iochunk.offset / 4096) * 4;
+	unsigned sz = (ireq->iochunk.size / 4096) * 4;
+	pgoff_t idx = offset / PAGE_SIZE;
+	struct page * page;
+
+	if (idx != ((offset + sz - 1) / PAGE_SIZE) || sz > sizeof(ireq->iochunk.ar.crcb))
+		return 0;
+
+	page = find_get_page(cfile->f_mapping, idx);
+	if (!page)
+		return 0;
+
+	memcpy(ireq->iochunk.ar.crcb, kmap(page) + (offset & (PAGE_SIZE-1)), sz);
+	ireq->iochunk.ar.crc = ireq->iochunk.ar.crcb;
+	kunmap(page);
+	put_page(page);
+	return 1;
+}
+
+static void csa_crc_work(struct work_struct *w)
+{
+	struct pcs_aio_req * areq = container_of(w, struct pcs_aio_req, work);
+	struct pcs_int_request * ireq = container_of(areq, struct pcs_int_request, iochunk.ar);
+	int ncrc = (ireq->iochunk.size / 4096) * 4;
+	ssize_t sz;
+	loff_t pos;
+
+	if (ncrc <= PCS_MAX_INLINE_CRC)
+		areq->crc = areq->crcb;
+	else {
+		areq->crc = kmalloc(ncrc, GFP_KERNEL);
+		if (areq->crc == NULL) {
+out:
+			if (!ireq->error.value) {
+				ireq->error.remote = 1;
+				ireq->error.offender = ireq->iochunk.csl->cs[ireq->iochunk.cs_index].info.id;
+				ireq->error.value = PCS_ERR_NORES;
+			}
+			fput(areq->cfile);
+			if (areq->crc && areq->crc != areq->crcb) {
+				kfree(areq->crc);
+				areq->crc = NULL;
+			}
+			pcs_csa_do_completion(areq);
+			return;
+		}
+	}
+
+	pos = (ireq->iochunk.offset / 4096) * 4;
+	sz = kernel_read(areq->cfile, areq->crc, ncrc, &pos);
+	if (sz != ncrc) {
+		FUSE_KTRACE(ireq->cc->fc, "Did not read crc res=%u expected=%u", (unsigned)sz, (unsigned)ncrc);
+		goto out;
+	}
+	fput(areq->cfile);
+	pcs_csa_do_completion(areq);
+}
+
 static void pcs_csa_complete(struct kiocb *iocb, long ret)
 {
 	struct pcs_aio_req * areq;
@@ -283,7 +422,7 @@ static void pcs_csa_complete(struct kiocb *iocb, long ret)
 	queue_work(ireq->cc->wq, &areq->work);
 }
 
-static inline int csa_submit(struct file * file, struct pcs_int_request * ireq)
+static inline int csa_submit(struct file * file, struct file *cfile, int do_csum, struct pcs_int_request * ireq)
 {
 	struct pcs_aio_req * areq =  &ireq->iochunk.ar;
 	struct kiocb * iocb = &areq->iocb;
@@ -311,9 +450,40 @@ static inline int csa_submit(struct file * file, struct pcs_int_request * ireq)
 
 	atomic_set(&areq->iocount, 2);
 
+	areq->cfile = NULL;
+	areq->crc = NULL;
+
+	if (do_csum) {
+		if (cfile == NULL)
+			return -EINVAL;
+
+		if ((ireq->iochunk.size|ireq->iochunk.offset) & 4095)
+			return -EINVAL;
+
+		if (!quick_crc_fetch(ireq, cfile)) {
+			INIT_WORK(&areq->work, csa_crc_work);
+			atomic_inc(&areq->iocount);
+			areq->cfile = cfile;
+			get_file(cfile);
+		}
+	}
+
 	ireq->ts_sent = ktime_get();
 	ret = call_read_iter(file, iocb, it);
 
+	if (do_csum) {
+		if (ret == -EIOCBQUEUED || ret == ireq->iochunk.size) {
+			if (!areq->crc) {
+				FUSE_KTRACE(ireq->cc->fc, "Not a quicky");
+				queue_work(ireq->cc->wq, &areq->work);
+			}
+			pcs_csa_do_completion(areq);
+			return 0;
+		}
+		if (!areq->crc)
+			pcs_csa_do_completion(areq);
+	}
+
 	pcs_csa_do_completion(areq);
 
 	if (ret == -EIOCBQUEUED)
@@ -343,7 +513,7 @@ int pcs_csa_cs_submit(struct pcs_cs * cs, struct pcs_int_request * ireq)
 		    (csa->flags & PCS_CSA_FL_READ)) {
 			/* XXX Paranoia? Verify! */
 			if (!(map->state & PCS_MAP_DEAD) && map->cs_list == ireq->iochunk.csl) {
-				if (!csa_submit(csa->file, ireq))
+				if (!csa_submit(csa->file, csa->cfile, csa->flags&PCS_CSA_FL_CSUM, ireq))
 					return 1;
 			}
 		}
@@ -355,6 +525,7 @@ static long csa_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct pcs_csa_context *ctx = file->private_data;
 	struct file * filp = NULL;
+	struct file * cfilp = NULL;
 	int err;
 	struct pcs_csa_setmap req;
 
@@ -365,12 +536,22 @@ static long csa_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case PCS_CSA_IOC_SETMAP:
 		if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
 			return -EFAULT;
+
 		if (req.fd >= 0) {
 			filp = fget(req.fd);
 			if (filp == NULL)
 				return -EBADF;
 		}
-		err = csa_update(ctx, req.chunk_id, req.flags, &req.version, filp);
+		if (req.cfd >= 0) {
+			cfilp = fget(req.cfd);
+			err = -EBADF;
+			if (cfilp == NULL)
+				goto out;
+		}
+		err = csa_update(ctx, req.chunk_id, req.flags, &req.version, filp, cfilp);
+		if (cfilp)
+			fput(cfilp);
+out:
 		if (filp)
 			fput(filp);
 		return err;
diff --git a/fs/fuse/kio/pcs/pcs_cs_prot.h b/fs/fuse/kio/pcs/pcs_cs_prot.h
index d823426..6e0d371 100644
--- a/fs/fuse/kio/pcs/pcs_cs_prot.h
+++ b/fs/fuse/kio/pcs/pcs_cs_prot.h
@@ -37,6 +37,9 @@ struct pcs_cs_sync_data
 						 *	This means that at the req completion time, the output
 						 *	data will be transferred to disk.
 						 */
+#define PCS_CS_IO_NOCSUM	(1ULL<<61)	/* Req: skip crc verification */
+#define PCS_CS_IO_SYNC		(1ULL<<60)	/* Req: DSYNC request */
+#define PCS_CS_IO_BACKGROUND	(1ULL<<59)	/* Req: low priority request */
 
 #define PCS_CS_RESET_TS_RECV(sdata, ts)	do { (sdata)->misc = ((u64)ts & 0xFFFFFFFFFFFFFULL); } while (0)
 #define PCS_CS_SET_TS_RECV(sdata, ts)	do { (sdata)->misc = ((sdata)->misc & ~0xFFFFFFFFFFFFFULL) | ((u64)ts & 0xFFFFFFFFFFFFFULL); } while (0)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 29ccabd..4bbabfd 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -28,6 +28,7 @@
 #include <linux/net.h>
 #include <linux/debugfs.h>
 #include <linux/fiemap.h>
+#include <crypto/hash.h>
 
 #include "pcs_ioctl.h"
 #include "pcs_cluster.h"
@@ -72,6 +73,8 @@
 static LIST_HEAD(pcs_client_list);
 spinlock_t pcs_clients_lock;
 
+struct crypto_shash *crc_tfm;
+
 static void register_client(struct pcs_fuse_cluster * pfc)
 {
 	spin_lock(&pcs_clients_lock);
@@ -217,7 +220,7 @@ static void process_pcs_init_reply(struct fuse_mount *fm, struct fuse_args *args
 
 }
 
-int kpcs_conn_init(struct fuse_mount *fm)
+static int kpcs_conn_init(struct fuse_mount *fm)
 {
 	struct fuse_conn *fc = fm->fc;
 	struct fuse_io_args *ia;
@@ -268,7 +271,7 @@ int kpcs_conn_init(struct fuse_mount *fm)
 	return 0;
 }
 
-void kpcs_conn_fini(struct fuse_mount *fm)
+static void kpcs_conn_fini(struct fuse_mount *fm)
 {
 	struct fuse_conn *fc = fm->fc;
 
@@ -284,7 +287,7 @@ void kpcs_conn_fini(struct fuse_mount *fm)
 	pcs_cluster_fini((struct pcs_fuse_cluster *) fc->kio.ctx);
 }
 
-void kpcs_conn_abort(struct fuse_conn *fc)
+static void kpcs_conn_abort(struct fuse_conn *fc)
 {
 	/* XXX: Implement abort pending kio */
 }
@@ -450,7 +453,7 @@ static int kpcs_do_file_open(struct file *file, struct inode *inode)
 	return 0;
 }
 
-int kpcs_file_open(struct file *file, struct inode *inode)
+static int kpcs_file_open(struct file *file, struct inode *inode)
 {
 	struct fuse_inode *fi = get_fuse_inode(inode);
 	struct pcs_dentry_info *di = fi->private;
@@ -501,7 +504,7 @@ static void kpcs_file_close(struct file *file, struct inode *inode)
 	pcs_mapping_invalidate(&di->mapping);
 }
 
-void kpcs_inode_release(struct fuse_inode *fi)
+static void kpcs_inode_release(struct fuse_inode *fi)
 {
 	struct pcs_dentry_info *di = fi->private;
 
@@ -648,7 +651,7 @@ int fuse_map_resolve(struct pcs_map_entry *m, int direction)
 	return 0;
 }
 
-struct fuse_req *kpcs_req_alloc(struct fuse_mount *fm, gfp_t flags)
+static struct fuse_req *kpcs_req_alloc(struct fuse_mount *fm, gfp_t flags)
 {
 	return fuse_generic_request_alloc(fm, pcs_fuse_req_cachep, flags);
 }
@@ -1567,7 +1570,7 @@ static ssize_t prometheus_file_read(struct file *filp,
 	return count;
 }
 
-const struct file_operations prometheus_file_operations = {
+static const struct file_operations prometheus_file_operations = {
 	.open		= prometheus_file_open,
 	.read		= prometheus_file_read,
 	.release	= prometheus_file_release,
@@ -1745,13 +1748,39 @@ static void kpcs_kill_requests(struct fuse_conn *fc, struct inode *inode)
 
 static int kpcs_ioctl(struct file *file, struct inode *inode, unsigned int cmd, unsigned long arg, int len)
 {
-	struct fuse_conn *fc = inode ? get_fuse_conn(inode) : NULL;
+	struct fuse_conn * fc = NULL;
+	struct fuse_inode *fi = NULL;
+	struct pcs_dentry_info *di = NULL;
 	struct pcs_fuse_cluster *pfc;
 	struct fuse_pcs_ioc_register req;
 	int res;
 
-	if (cmd != PCS_KIO_CALL_REG)
-		return -EINVAL;
+	if (inode) {
+		fc = get_fuse_conn(inode);
+		fi = get_fuse_inode(inode);
+		if (fi)
+			di = fi->private;
+	}
+
+	switch (cmd) {
+	case PCS_KIO_CALL_REG:
+		break;
+	case PCS_IOC_NOCSUMONREAD:
+	case PCS_IOC_NOWRITEDELAY:
+		if (di) {
+			u32 data;
+			if (copy_from_user(&data, (void __user *)arg, 4))
+				return -EFAULT;
+			if (cmd == PCS_IOC_NOCSUMONREAD)
+				di->no_csum_on_read = !!data;
+			else
+				di->no_write_delay = !!data;
+			return 0;
+		}
+		fallthrough;
+	default:
+		return -ENOIOCTLCMD;
+	}
 
 	if (len != sizeof(req))
 		return -EINVAL;
@@ -1759,6 +1788,9 @@ static int kpcs_ioctl(struct file *file, struct inode *inode, unsigned int cmd,
 	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
 		return -EFAULT;
 
+	if (req.crypto_algo)
+		return -EOPNOTSUPP;
+
 	if (fc) {
 		pfc = (struct pcs_fuse_cluster*)fc->kio.ctx;
 		if (memcmp(&req.cluster_id, &pfc->cc.eng.cluster_id, sizeof(PCS_CLUSTER_ID_T)))
@@ -1843,6 +1875,10 @@ static int __init kpcs_mod_init(void)
 
 	fuse_trace_root = debugfs_create_dir("fuse", NULL);
 
+	crc_tfm = crypto_alloc_shash("crc32c", 0, 0);
+	if (IS_ERR(crc_tfm))
+		crc_tfm = NULL;
+
 	printk("%s fuse_c:%p ireq_c:%p pcs_wq:%p\n", __FUNCTION__,
 	       pcs_fuse_req_cachep, pcs_ireq_cachep, pcs_wq);
 
@@ -1866,6 +1902,8 @@ static void __exit kpcs_mod_exit(void)
 {
 	if (fuse_trace_root)
 		debugfs_remove(fuse_trace_root);
+	if (crc_tfm)
+		crypto_free_shash(crc_tfm);
 
 	fuse_unregister_kio(&kio_pcs_ops);
 	destroy_workqueue(pcs_cleanup_wq);
diff --git a/fs/fuse/kio/pcs/pcs_ioctl.h b/fs/fuse/kio/pcs/pcs_ioctl.h
index 24e6b0b..5972873 100644
--- a/fs/fuse/kio/pcs/pcs_ioctl.h
+++ b/fs/fuse/kio/pcs/pcs_ioctl.h
@@ -88,7 +88,6 @@ struct pcs_ioc_getmap
 #define PCS_IOC_GETMAP		_IOWR('V',37, struct pcs_ioc_getmap)
 
 
-#define PCS_KIO_CALL_REG	1
 
 struct fuse_pcs_ioc_register
 {
@@ -96,7 +95,8 @@ struct fuse_pcs_ioc_register
 	PCS_NODE_ID_T 		client_id;
 	PCS_CLUSTER_ID_T	cluster_id;
 	PCS_INTEGRITY_SEQ_T	integrity_seq;
-	u32			reserved;
+	u32			crypto_algo;
+	u64			key_data;
 };
 
 struct pcs_csa_setmap
@@ -104,14 +104,17 @@ struct pcs_csa_setmap
 	PCS_CHUNK_UID_T		chunk_id;
 	PCS_MAP_VERSION_T	version;
 	int			fd;
+	int			cfd;
 	u32			flags;
+	u32			reserved;
 #define PCS_CSA_FL_READ		1
 #define PCS_CSA_FL_WRITE	2
+#define PCS_CSA_FL_CSUM         4
 	PCS_SYNC_SEQ_T		sync_epoch;
 	PCS_SYNC_SEQ_T		sync_seq;
-	u64			reserved;
 };
 
 #define PCS_CSA_IOC_SETMAP	_IOR('V',38, struct pcs_csa_setmap)
+#define PCS_KIO_CALL_REG	_IOR('V',39, struct fuse_pcs_ioc_register)
 
 #endif /* _PCS_IOCTL_H_ */
diff --git a/fs/fuse/kio/pcs/pcs_req.h b/fs/fuse/kio/pcs/pcs_req.h
index 8c0bd3e..7c86f5d 100644
--- a/fs/fuse/kio/pcs/pcs_req.h
+++ b/fs/fuse/kio/pcs/pcs_req.h
@@ -52,6 +52,12 @@ struct pcs_aio_req
 	atomic_t		iocount;
 	struct iov_iter 	iter;
 	struct work_struct	work;
+
+#define PCS_MAX_INLINE_CRC	2
+	u32    			crcb[PCS_MAX_INLINE_CRC];
+	u32    			*crc;
+	struct file		*cfile;
+	struct work_struct	cwork;
 };
 
 struct pcs_int_request
@@ -76,6 +82,7 @@ struct pcs_int_request
 #define IREQ_F_NOFLUSH		0x200
 #define IREQ_F_WB_SUSP		0x400
 #define IREQ_F_RECV_SPLICE	0x800
+#define IREQ_F_NO_ACCEL		0x1000
 
 	atomic_t		iocount;
 
@@ -362,5 +369,6 @@ typedef void (*kio_file_itr)(struct fuse_file *ff, struct pcs_dentry_info *di,
 typedef void (*kio_req_itr)(struct fuse_file *ff, struct fuse_req *req,
 			    void *ctx);
 void pcs_kio_req_list(struct fuse_conn *fc, kio_req_itr kreq_cb, void *ctx);
+extern struct crypto_shash *crc_tfm;
 
 #endif /* _PCS_REQ_H_ */
-- 
1.8.3.1



More information about the Devel mailing list