From 41b1dd730148c21b02466e2c3f63451dcc6d6309 Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Thu, 28 Sep 2023 17:40:55 -0400 Subject: [PATCH] EX-8245 osc: use correct count Using the number of bytes in the compressed page creates gaps in the RDMA, which IB memory registration cannot accept. Fix this by always setting count to PAGE_SIZE for compressed pages and otherwise using the count from the original source page. Setting PAGE_SIZE for compressed pages is valid because client only does compression for aligned IO, except for the trailing chunk. For the trailing chunk, the file size is set on the server, so any trailing bytes are ignored. Signed-off-by: Patrick Farrell Change-Id: Ied89d3ac328fb6020079392f5a8812ad5637b4a4 Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/52550 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Artem Blagodarenko Reviewed-by: Andreas Dilger --- lustre/osc/osc_compress.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/lustre/osc/osc_compress.c b/lustre/osc/osc_compress.c index e8a181d..ef1cf49 100644 --- a/lustre/osc/osc_compress.c +++ b/lustre/osc/osc_compress.c @@ -133,20 +133,41 @@ int fill_cpga(struct brw_page **cpga, struct brw_page **pga, pg = cpga[dst_page]; pg->off = pga[src_from]->off + chunk_offset; - if ((dst_size - chunk_offset) < PAGE_SIZE) - pg->count = dst_size - chunk_offset; - else + /* this asserts that every page in a compressed IO starts at + * a page aligned offset, which means 'the client only does + * compression for aligned IO' + */ + LASSERTF((pg->off & ~PAGE_MASK) == 0, + "pg->off %llu\n", pg->off); + /* infiniband requires there be no gaps in memory when + * mapping an RDMA, so if we're doing compression, we just set + * the reported size to PAGE_SIZE. Technically this means we + * will copy extra data for the last page, but this isn't a big + * deal, and the compression header saves us from reading + * garbage. + * + * The interesting case is compression of the last chunk, which + * may be a partial chunk. In this case, we still just send the + * whole page, because the actual file size is set on the + * server, so any trailing bytes are ignored. + * + * TODO: After doing compression, we should zero the remaining + * part of the incomplete pages. This is a TODO for another + * patch. + */ + if (dst) { pg->count = PAGE_SIZE; + pg->pg = mem_to_page(dst + chunk_offset); + } else { + pg->count = pga[src_page]->count; + pg->pg = pga[src_page]->pg; + } /* * Compressed pages, flags are lost * Let's choose first page in chunk * flag to set to all pages */ pg->flag = pga[src_from]->flag; - if (dst) - pg->pg = mem_to_page(dst + chunk_offset); - else - pg->pg = pga[src_page]->pg; if (fill_bits & CPGA_FILL_ENCRYPTED) { if (fill_bits & CPGA_FILL_DIRECTIO) { -- 1.8.3.1