[Devel] [PATCH RHEL9 COMMIT] fuse: direct access to journaled cs
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Nov 1 22:23:55 MSK 2023
The commit is pushed to "branch-rh9-5.14.0-284.25.1.vz9.30.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-284.25.1.vz9.30.8
------>
commit f18b0a63779ca7b0e129aeed6877be7e606bb21f
Author: Alexey Kuznetsov <kuznet at virtuozzo.com>
Date: Fri Oct 6 18:42:35 2023 +0800
fuse: direct access to journaled cs
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.
https://pmc.acronis.work/browse/VSTOR-54040
Signed-off-by: Alexey Kuznetsov <kuznet at acronis.com>
Feature: vStorage
---
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 310cd258e8f4..ee3b882ee89c 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 10ffa14a15a7..0b06a0e20898 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 7e5070d1ee86..4af8f1697d3c 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 9444f751fe10..24a962f8beb9 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 d823426a56f2..6e0d37157cb0 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 29ccabd083f3..4bbabfd3d5fc 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 @@ MODULE_PARM_DESC(rdmaio_queue_depth, "RDMA queue depth");
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 24e6b0be9743..5972873c9208 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 8c0bd3e43079..7c86f5dc73d3 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 @@ void pcs_kio_file_list(struct fuse_conn *fc, kio_file_itr kfile_cb, void *ctx);
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_ */
More information about the Devel
mailing list