[Devel] [PATCH RHEL7 COMMIT] fs/fuse kio_pcs: split kpcs_req_send()
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Oct 9 12:19:01 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.4
------>
commit c849be3b4414fdcbff6a53bfa88ad0797c3ffb4d
Author: Pavel Butsykin <pbutsykin at virtuozzo.com>
Date: Tue Oct 9 12:18:59 2018 +0300
fs/fuse kio_pcs: split kpcs_req_send()
Cosmetic patch, aimed at improving code readability.
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai at virtuozzo.com>
=====================
Patchset description:
Fuse: Fix IOCB_CMD_UNMAP_ITER handling to prevent cache inconsistency
https://pmc.acronis.com/browse/VSTOR-15447
Ploop can asynchronously unmap regions by sending IOCB_CMD_UNMAP_ITER, but this
command isn't quite correctly interpreted in Fuse. Moreover, in Fast-path mode,
fallocate(FALLOC_FL_PUNCH_HOLE|FALLOC_FL_ZERO_RANGE) falls to fuse user daemon
and it can lead to data corruption.
Let's fix it.
Pavel Butsykin (4):
fs/fuse: fix mutually exclusive flags in fuse_send_unmap()
fs/fuse: initialize req->io_inode in fuse_send_unmap()
fs/fuse kio_pcs: split kpcs_req_send()
fs/fuse kio_pcs: prevention of falling kio reqs to usermode
---
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 104 +++++++++++++++++++++----------------
1 file changed, 60 insertions(+), 44 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 0d2ce6b8828c..3143d24d7544 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -1028,65 +1028,55 @@ static void _pcs_grow_end(struct fuse_conn *fc, struct fuse_req *req)
kpcs_setattr_end(fc, req);
}
-static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bool lk)
+static void pcs_kio_setattr_handle(struct fuse_req *req)
{
- struct pcs_fuse_cluster *pfc = (struct pcs_fuse_cluster*)fc->kio.ctx;
struct fuse_inode *fi = get_fuse_inode(req->io_inode);
+ struct pcs_fuse_req *r = pcs_req_from_fuse(req);
+ struct fuse_setattr_in *inarg = (void*) req->in.args[0].value;
+ struct pcs_dentry_info *di;
- if (!fc->initialized || fc->conn_error)
- return 1;
+ if (!(inarg->valid & FATTR_SIZE))
+ return;
- BUG_ON(!pfc);
- /* HYPOTHESIS #1
- * IFAIU at this point request can not belongs to any list
- * so I cant avoid grab fc->lock here at all
- */
- BUG_ON(!list_empty(&req->list));
+ BUG_ON(!fi);
- TRACE(" Enter req:%p op:%d end:%p bg:%d lk:%d\n", req, req->in.h.opcode, req->end, bg, lk);
+ di = pcs_inode_from_fuse(fi);
+ spin_lock(&di->lock);
+ if (inarg->size < di->fileinfo.attr.size) {
+ BUG_ON(di->size.op != PCS_SIZE_INACTION);
+ di->size.op = PCS_SIZE_SHRINK;
+ }
+ spin_unlock(&di->lock);
- if (!fi || !fi->private)
- return 1;
+ r->end = req->end;
+ if (di->size.op == PCS_SIZE_SHRINK) {
+ BUG_ON(!mutex_is_locked(&req->io_inode->i_mutex));
+ /* wait for aio reads in flight */
+ inode_dio_wait(req->io_inode);
+ /*
+ * Writebackcache was flushed already so it is safe to
+ * drop pcs_mapping
+ */
+ pcs_map_invalidate_tail(&di->mapping, inarg->size);
+ req->end = _pcs_shrink_end;
+ } else
+ req->end = _pcs_grow_end;
+}
+static int pcs_kio_classify_req(struct fuse_conn *fc, struct fuse_req *req)
+{
switch (req->in.h.opcode) {
- case FUSE_SETATTR: {
- struct pcs_fuse_req *r = pcs_req_from_fuse(req);
- struct fuse_setattr_in *inarg = (void*) req->in.args[0].value;
- struct pcs_dentry_info *di;
-
- if (!(inarg->valid & FATTR_SIZE))
- return 1;
-
- di = pcs_inode_from_fuse(fi);
- spin_lock(&di->lock);
- if (inarg->size < di->fileinfo.attr.size) {
- BUG_ON(di->size.op != PCS_SIZE_INACTION);
- di->size.op = PCS_SIZE_SHRINK;
- }
- spin_unlock(&di->lock);
- r->end = req->end;
- if (di->size.op == PCS_SIZE_SHRINK) {
- BUG_ON(!mutex_is_locked(&req->io_inode->i_mutex));
- /* wait for aio reads in flight */
- inode_dio_wait(req->io_inode);
- /*
- * Writebackcache was flushed already so it is safe to
- * drop pcs_mapping
- */
- pcs_map_invalidate_tail(&di->mapping, inarg->size);
- req->end = _pcs_shrink_end;
- } else
- req->end = _pcs_grow_end;
- return 1;
- }
case FUSE_READ:
case FUSE_WRITE:
case FUSE_FSYNC:
case FUSE_FLUSH:
case FUSE_FALLOCATE:
break;
+ case FUSE_SETATTR:
+ pcs_kio_setattr_handle(req);
+ return 1;
case FUSE_IOCTL: {
- struct fuse_ioctl_in const * inarg = req->in.args[0].value;
+ struct fuse_ioctl_in const *inarg = req->in.args[0].value;
if (inarg->cmd != FS_IOC_FIEMAP)
return 1;
@@ -1097,6 +1087,32 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
return 1;
}
+ return 0;
+}
+
+static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bool lk)
+{
+ struct pcs_fuse_cluster *pfc = (struct pcs_fuse_cluster*)fc->kio.ctx;
+ struct fuse_inode *fi = get_fuse_inode(req->io_inode);
+
+ if (!fc->initialized || fc->conn_error)
+ return 1;
+
+ BUG_ON(!pfc);
+ /* HYPOTHESIS #1
+ * IFAIU at this point request can not belongs to any list
+ * so I cant avoid grab fc->lock here at all
+ */
+ BUG_ON(!list_empty(&req->list));
+
+ TRACE(" Enter req:%p op:%d end:%p bg:%d lk:%d\n", req, req->in.h.opcode, req->end, bg, lk);
+
+ if (!fi || !fi->private)
+ return 1;
+
+ if (pcs_kio_classify_req(fc, req))
+ return 1;
+
/* request_end below will do fuse_put_request() */
if (!bg)
atomic_inc(&req->count);
More information about the Devel
mailing list