Whamcloud - gitweb
EX-7600 osc: save compressed object size
authorArtem Blagodarenko <ablagodarenko@ddn.com>
Wed, 11 Oct 2023 16:23:56 +0000 (12:23 -0400)
committerAndreas Dilger <adilger@whamcloud.com>
Sun, 5 Nov 2023 10:41:36 +0000 (10:41 +0000)
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 <ablagodarenko@ddn.com>
Change-Id: I387c282e1cf788c3b8f6230ef555d73ffffe49c1
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51595
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/osc/osc_compress.c
lustre/osc/osc_request.c
lustre/osd-ldiskfs/osd_io.c

index ef1cf49..98c1b1d 100644 (file)
@@ -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++;
index 2cca646..cb07d28 100644 (file)
@@ -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++;
index a4a6c6e..2d5596b 100644 (file)
@@ -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) {