[Devel] [PATCH RHEL9] fs/fuse kio: implement zeroing page tails

Alexey Kuznetsov kuznet at virtuozzo.com
Fri Sep 22 13:25:10 MSK 2023


Due to changes in internal fuse conventions in rhel9 we must zero
unread areas ourselves now.

https://pmc.acronis.work/browse/VSTOR-75108

Affects: #VSTOR-75108

Signed-off-by: Alexey Kuznetsov <kuznet at acronis.com>
---
 fs/fuse/kio/pcs/fuse_io.c          | 50 ++++++++++++++++++++----------
 fs/fuse/kio/pcs/pcs_cluster.h      |  2 ++
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c |  2 ++
 3 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/fs/fuse/kio/pcs/fuse_io.c b/fs/fuse/kio/pcs/fuse_io.c
index e345be7c44d5..0562809e8bee 100644
--- a/fs/fuse/kio/pcs/fuse_io.c
+++ b/fs/fuse/kio/pcs/fuse_io.c
@@ -26,6 +26,29 @@
 
 #include "../../fuse_i.h"
 
+void pcs_zero_fill_read_resp(struct fuse_req * req, unsigned int start, unsigned int end)
+{
+	struct fuse_io_args *ia = container_of(req->args, typeof(*ia), ap.args);
+	int i;
+	unsigned int off = 0;
+
+	for (i = 0; i < ia->ap.num_pages; i++) {
+		unsigned where = 0;
+		unsigned copy = ia->ap.descs[i].length;
+		unsigned next_off = off + copy;
+		if (start < next_off && end > off) {
+			if (start > off) {
+				where += start - off;
+				copy -= start - off;
+			}
+			if (end < next_off)
+				copy -= (next_off - end);
+			zero_user(ia->ap.pages[i], ia->ap.descs[i].offset + where, copy);
+		}
+		off = next_off;
+	}
+}
+
 static void intreq_complete(struct pcs_int_request *ireq)
 {
 	pcs_api_iorequest_t *req = ireq->apireq.req;
@@ -45,16 +68,16 @@ static void on_read_done(struct pcs_fuse_req *r, size_t size)
 {
 	struct pcs_fuse_cluster *pfc = cl_from_req(r);
 	struct fuse_inode *fi = get_fuse_inode(r->req.args->io_inode);
+	struct fuse_io_args *ia = container_of(r->req.args, typeof(*ia), ap.args);
+	struct fuse_read_in * in = &ia->read.in;
 
 	DTRACE("do fuse_request_end req:%p op:%d err:%d\n", &r->req, r->req.in.h.opcode, r->req.out.h.error);
 
 	if (r->req.out.h.error && r->req.args->page_zeroing) {
-		int i;
-		for (i = 0; i < r->exec.io.num_bvecs; i++) {
-			BUG_ON(!r->exec.io.bvec[i].bv_page);
-			clear_highpage(r->exec.io.bvec[i].bv_page);
-		}
-	}
+		pcs_zero_fill_read_resp(&r->req, 0, in->size);
+	} else if (size < in->size && r->req.args->page_zeroing)
+		pcs_zero_fill_read_resp(&r->req, size, in->size);
+
 	fuse_stat_observe(pfc->fc, KFUSE_OP_READ, ktime_sub(ktime_get(), r->exec.ireq.ts));
 	fuse_stat_account(pfc->fc, KFUSE_OP_READ, size);
 	r->req.args->out_args[0].size = size;
@@ -139,8 +162,7 @@ static void req_fiemap_get_iter(void *data, unsigned int offset, struct iov_iter
 	iov_iter_advance(it, offset);
 }
 
-static inline void set_io_buff(struct pcs_fuse_req *r, off_t offset, size_t size,
-			       int zeroing)
+static inline void set_io_buff(struct pcs_fuse_req *r, off_t offset, size_t size)
 {
 	struct fuse_args *args = r->req.args;
 	struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
@@ -156,12 +178,6 @@ static inline void set_io_buff(struct pcs_fuse_req *r, off_t offset, size_t size
 		bvec->bv_len = ia->ap.descs[i].length;
 		if (bvec->bv_len > count)
 			bvec->bv_len = count;
-		if (zeroing && bvec->bv_page &&
-				bvec->bv_len != PAGE_SIZE)
-			zero_user_segments(bvec->bv_page,
-					0, bvec->bv_offset,
-					bvec->bv_offset + bvec->bv_len,
-					PAGE_SIZE);
 		count -= bvec->bv_len;
 		bvec++;
 	}
@@ -182,10 +198,10 @@ static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offse
 	switch (type)
 	{
 	case PCS_REQ_T_READ:
-		set_io_buff(r, offset, size, r->req.args->page_zeroing);
+		set_io_buff(r, offset, size);
 		break;
 	case PCS_REQ_T_WRITE:
-		set_io_buff(r, offset, size, 0);
+		set_io_buff(r, offset, size);
 		break;
 	case PCS_REQ_T_WRITE_ZERO:
 	case PCS_REQ_T_WRITE_HOLE:
@@ -193,7 +209,7 @@ static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offse
 		r->exec.io.req.size = size;
 		break;
 	case PCS_REQ_T_FIEMAP:
-		set_io_buff(r, offset, size, 0);
+		set_io_buff(r, offset, size);
 		break;
 	}
 
diff --git a/fs/fuse/kio/pcs/pcs_cluster.h b/fs/fuse/kio/pcs/pcs_cluster.h
index 99f72602640d..31a5830cf30c 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.h
+++ b/fs/fuse/kio/pcs/pcs_cluster.h
@@ -130,6 +130,8 @@ void pcs_cc_fini(struct pcs_cluster_core *cc);
 void pcs_fuse_prep_io(struct pcs_fuse_req *r, unsigned short type, off_t offset, size_t size, u64 aux);
 void pcs_fuse_prep_fallocate(struct pcs_fuse_req *r);
 
+void pcs_zero_fill_read_resp(struct fuse_req * req, unsigned int start, unsigned int end);
+
 
 static inline void pcs_cc_set_abort_timeout(struct pcs_cluster_core *cc, int timeout)
 {
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index e122a6d1f6cb..a8d68fc35de7 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -828,6 +828,8 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
 		if (in->offset + in->size > di->fileinfo.attr.size) {
 			if (in->offset >= di->fileinfo.attr.size) {
 				args->out_args[0].size = 0;
+				if (req->args->page_zeroing)
+					pcs_zero_fill_read_resp(req, 0, in->size);
 				ret = -EPERM;
 				goto out;
 			}
-- 
2.38.1



More information about the Devel mailing list