From b489a2a39745eedb40261802b0f81b6ffa6495e4 Mon Sep 17 00:00:00 2001 From: Artem Blagodarenko Date: Wed, 11 Oct 2023 12:23:56 -0400 Subject: [PATCH] EX-7600 osc: save compressed object size CSDC uses a sparse file feature. A client writes compressed data chunks to the original offsets so the same data is expected to be read from the same offsets. There are no writes after the last compressed chunk, so no "hole" after the last compressed chunk. Compressed file size (based on OST objects size) is smaller than the original on the "original last chunk size - compressed last chunk size" delta. Object size should be set to uncompressed size. This size is used to calculate file size and to remove the workaround of not compressing the last chunk in the file. Fixes: caee1c5 ("EX-7818 osc: don't check for start inside the chunk) Signed-off-by: Artem Blagodarenko Change-Id: I387c282e1cf788c3b8f6230ef555d73ffffe49c1 Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51595 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger --- lustre/osc/osc_compress.c | 20 +++++++++----------- lustre/osc/osc_request.c | 6 ++++++ lustre/osd-ldiskfs/osd_io.c | 11 +++++++++++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/lustre/osc/osc_compress.c b/lustre/osc/osc_compress.c index ef1cf49..98c1b1d 100644 --- a/lustre/osc/osc_compress.c +++ b/lustre/osc/osc_compress.c @@ -255,11 +255,9 @@ int compress_request(const char *obd_name, struct obdo *oa, /* * - applied_type == 0 if no supported algorithms * found during the previous compress_chunk call - * - last chunk in the request is not compressed to - * preserve the right size of object */ if (clpage->cp_comp_type != LL_COMPR_TYPE_NONE && - applied_type && (pga_i != *page_count - 1)) { + applied_type) { done = compress_chunk(obd_name, src, src_size, dst, &dst_size, wrkmem, @@ -270,8 +268,7 @@ int compress_request(const char *obd_name, struct obdo *oa, CDEBUG(D_SEC, "%s: rc %d: inode "DFID"\n", obd_name, rc, oa->o_parent_seq, - oa->o_parent_oid, - oa->o_parent_ver); + oa->o_parent_oid, oa->o_parent_ver); CDEBUG(D_SEC, "Compressed %u, plain %u\n", @@ -327,6 +324,7 @@ int decompress_request(struct osc_brw_async_args *aa, int page_count) unsigned int src_size; unsigned int dst_size; int pages_in_chunk; + int pages_left; char *src = NULL; char *dst = NULL; int chunk_bits; @@ -375,12 +373,12 @@ int decompress_request(struct osc_brw_async_args *aa, int page_count) if (src == NULL || dst == NULL) GOTO(out, rc = -ENOMEM); } + pages_left = ((page_count - i) > pages_in_chunk) ? + pages_in_chunk : page_count - i; - LASSERT((page_count - i) >= pages_in_chunk); - CDEBUG(D_SEC, "Merge chunk start %i, src: %px\n", i, src); - - merge_chunk(pga, i, pages_in_chunk, src, - &src_size); + CDEBUG(D_SEC, "Merge chunk [%i, %i], src: %px\n", i, + i + pages_left - 1, src); + merge_chunk(pga, i, pages_left, src, &src_size); LASSERT(src_size <= chunk_size); dst_size = 2 * chunk_size; CDEBUG(D_SEC, "Compressed size %lu, type %i\n", @@ -400,7 +398,7 @@ int decompress_request(struct osc_brw_async_args *aa, int page_count) dst_size, done); LASSERT(dst_size <= chunk_size); - unmerge_chunk(pga, i, pages_in_chunk, + unmerge_chunk(pga, i, pages_left, dst, dst_size); count++; diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 2cca646..cb07d28 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -1768,6 +1768,12 @@ retry_encrypt: } } + if (opc == OST_WRITE && compressed) { + struct brw_page *brwpg = ncpga[ncpcount - 1]; + oa->o_size = brwpg->off + brwpg->count; + oa->o_valid |= OBD_MD_FLSIZE; + } + for (niocount = i = 1; i < page_count; i++) { if (!can_merge_pages(pga[i - 1], pga[i])) niocount++; diff --git a/lustre/osd-ldiskfs/osd_io.c b/lustre/osd-ldiskfs/osd_io.c index a4a6c6e..2d5596b 100644 --- a/lustre/osd-ldiskfs/osd_io.c +++ b/lustre/osd-ldiskfs/osd_io.c @@ -1125,6 +1125,8 @@ static int osd_ldiskfs_map_inode_pages(struct inode *inode, if (fp == NULL) { /* start new extent */ fp = *page++; + compressed |= iobuf->dr_lnbs[i - clen]->lnb_flags & + OBD_BRW_COMPRESSED; clen = 1; if (++i != pages) continue; @@ -1261,6 +1263,15 @@ cont_map: fp = NULL; blocks += blocks_per_page * clen; } + + /* + * Compressed files can have holes at the + * object's end. This is required for correct + * file size. + */ + if (compressed && user_size > disk_size) + disk_size = user_size; + cleanup: if (rc == 0 && create && start_blocks < pages * blocks_per_page) { -- 1.8.3.1