[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