[Devel] [PATCH RHEL7 COMMIT] fuse kio: Round down extent start in fiemap_process_one()
Konstantin Khorenko
khorenko at virtuozzo.com
Sat Nov 24 17:49:35 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.20.2.vz7.73.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.20.2.vz7.73.8
------>
commit e195927ada4bd9afb1a00015b113d48726606e14
Author: Alexey Kuznetsov <kuznet at virtuozzo.com>
Date: Sat Nov 24 17:49:33 2018 +0300
fuse kio: Round down extent start in fiemap_process_one()
Argument fiemap::fm_start are passed directly from userspace,
and it doesn't have to be aligned to dentry size. If so,
we submit a request with a chunk, which is not equal to map
start, and the BUG_ON() inside map_submit() fires:
[516315.236213] kernel BUG at fs/fuse/kio/pcs/pcs_map.c:2326!
[516315.248305] RIP: 0010:[<ffffffffc06d8588>] [<ffffffffc06d8588>] map_submit+0x2e8/0x310 [fuse_kio_pcs]
[516315.257547] Call Trace:
[516315.258523] [<ffffffffc06dab4c>] pcs_cc_process_ireq_chunk+0x7c/0xa0 [fuse_kio_pcs]
[516315.259538] [<ffffffffc06dadea>] fiemap_work_func+0x27a/0x2e0 [fuse_kio_pcs]
[516315.260559] [<ffffffff968b7532>] process_one_work+0x182/0x440
[516315.261577] [<ffffffff968b86e6>] worker_thread+0x126/0x3c0
[516315.262600] [<ffffffff968b85c0>] ? manage_workers.isra.24+0x2a0/0x2a0
[516315.263635] [<ffffffff968bf681>] kthread+0xd1/0xe0
[516315.264665] [<ffffffff968bf5b0>] ? create_kthread+0x60/0x60
[516315.265700] [<ffffffff96f54677>] ret_from_fork_nospec_begin+0x21/0x21
[516315.266750] [<ffffffff968bf5b0>] ? create_kthread+0x60/0x60
This patch aligns requested chunk down to dentry size, as this is
the behavior described in fiemap documentation:
> the logical offset of the 1st returned extent may start before fm_start,
> and the range covered by the last returned extent may end after fm_length.
https://pmc.acronis.com/browse/VSTOR-15535
Signed-off-by: Alexey Kuznetsov <kuznet at virtuozzo.com>
[ktkhai: comment written]
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
fs/fuse/kio/pcs/pcs_cluster.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_cluster.c b/fs/fuse/kio/pcs/pcs_cluster.c
index ee66adda3c2d..5df263f01f98 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.c
+++ b/fs/fuse/kio/pcs/pcs_cluster.c
@@ -83,7 +83,9 @@ struct fiemap_iterator
char *buffer;
unsigned int fiemap_max;
u32 *mapped;
+ int first_iter;
+ u64 pos;
struct pcs_int_request ireq;
pcs_api_iorequest_t apireq;
struct iov_iter it;
@@ -190,15 +192,12 @@ static void fiemap_process_one(struct fiemap_iterator *fiter)
struct pcs_int_request *sreq;
u64 pos, end;
- pos = fiter->apireq.pos;
+ pos = fiter->pos;
end = orig_ireq->apireq.req->pos + orig_ireq->apireq.req->size;
- /*
- * We reuse zeroed fiter->apireq.size to detect first
- * iteration of the fiter. In this case we do not have
- * completed extents and just skip this business.
- */
- if (fiter->apireq.size != 0) {
+ if (fiter->first_iter) {
+ fiter->first_iter = 0;
+ } else {
/* Xfer previous chunk and advance pos */
if (pcs_if_error(&fiter->ireq.error)) {
fiter->orig_ireq->error = fiter->ireq.error;
@@ -208,6 +207,7 @@ static void fiemap_process_one(struct fiemap_iterator *fiter)
xfer_fiemap_extents(fiter, pos, fiter->buffer,
fiter->ireq.apireq.aux);
pos += fiter->apireq.size;
+ fiter->pos = pos;
}
if (pos >= end)
@@ -234,10 +234,12 @@ static void fiemap_process_one(struct fiemap_iterator *fiter)
sreq->iochunk.flow = pcs_flow_record(&di->mapping.ftab, 0, pos, end-pos, &di->cluster->maps.ftab);
sreq->iochunk.cmd = PCS_REQ_T_FIEMAP;
sreq->iochunk.cs_index = 0;
- sreq->iochunk.chunk = pos;
- sreq->iochunk.offset = 0;
+ sreq->iochunk.chunk = round_down(pos, DENTRY_CHUNK_SIZE(di));
+ sreq->iochunk.offset = pos - sreq->iochunk.chunk;
sreq->iochunk.dio_offset = 0;
sreq->iochunk.size = end - pos;
+ if (sreq->iochunk.offset + sreq->iochunk.size > DENTRY_CHUNK_SIZE(di))
+ fiter->apireq.size = sreq->iochunk.size = DENTRY_CHUNK_SIZE(di) - sreq->iochunk.offset;
sreq->iochunk.csl = NULL;
sreq->iochunk.banned_cs.val = 0;
sreq->iochunk.msg.destructor = NULL;
@@ -308,9 +310,8 @@ static void process_ireq_fiemap(struct pcs_int_request *orig_ireq)
orig_ireq->apireq.req->get_iter(orig_ireq->apireq.req->datasource, 0, it);
fiter->mapped = &((struct fiemap*)it->data)->fm_mapped_extents;
- /* fiemap_process_one() uses this 0 to detect first iteration */
- fiter->apireq.size = 0;
- fiter->apireq.pos = orig_ireq->apireq.req->pos;
+ fiter->first_iter = 1;
+ fiter->pos = orig_ireq->apireq.req->pos;
queue_fiter_work(fiter);
}
More information about the Devel
mailing list