Whamcloud - gitweb
EX-6245 csdc: define compress component layout
authorBobi Jam <bobijam@whamcloud.com>
Mon, 14 Nov 2022 08:25:05 +0000 (16:25 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Mon, 12 Jun 2023 23:34:01 +0000 (23:34 +0000)
Define a layout containing compress component with a compress
pattern so that old client cannot process it.

Add a client parameter to enable file compression support.

lctl get_param llite.*.enable_compression
lctl set_param llite.*.enable_compression={0,1}

Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: If88d446fc7425644ea9484004ffa4e6d2a05f7e6
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/49508
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
12 files changed:
lustre/include/lustre_lib.h
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/llite/lproc_llite.c
lustre/lod/lod_internal.h
lustre/lod/lod_lov.c
lustre/lod/lod_object.c
lustre/lod/lod_qos.c
lustre/lov/lov_ea.c
lustre/lov/lov_internal.h
lustre/ptlrpc/pack_generic.c
lustre/tests/sanity-pfl.sh
lustre/utils/liblustreapi_layout.c

index fa6306e..5a8ced1 100644 (file)
@@ -67,6 +67,8 @@ struct lu_target;
 #endif
 #define LP_POISON ((void *)LL_POISON)
 
+extern int llite_enable_compression;
+
 #ifdef HAVE_SERVER_SUPPORT
 int rev_import_init(struct obd_export *exp);
 int target_handle_connect(struct ptlrpc_request *req);
index 572c8aa..977fc92 100644 (file)
@@ -735,10 +735,12 @@ struct fsxattr {
 
 static inline bool lov_pattern_supported(__u32 pattern)
 {
-       pattern &= ~LOV_PATTERN_F_RELEASED;
-       return pattern == LOV_PATTERN_RAID0 ||
-              pattern == (LOV_PATTERN_RAID0 | LOV_PATTERN_OVERSTRIPING) ||
-              pattern == LOV_PATTERN_MDT;
+       __u32 pattern_base = pattern & ~LOV_PATTERN_F_RELEASED;
+
+       return pattern_base == LOV_PATTERN_RAID0 ||
+              pattern_base == (LOV_PATTERN_RAID0 | LOV_PATTERN_OVERSTRIPING) ||
+              pattern_base == (LOV_PATTERN_RAID0 | LOV_PATTERN_COMPRESS) ||
+              pattern_base == LOV_PATTERN_MDT;
 }
 
 /* RELEASED and MDT patterns are not valid in many places, so rather than
@@ -883,7 +885,7 @@ enum lov_comp_md_entry_flags {
 
 #define LCME_KNOWN_FLAGS       (LCME_FL_NEG | LCME_FL_INIT | LCME_FL_STALE | \
                                 LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
-                                LCME_FL_EXTENSION)
+                                LCME_FL_EXTENSION | LCME_FL_NOCOMPR)
 
 /* The component flags can be set by users at creation/modification time. */
 #define LCME_USER_COMP_FLAGS   (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
@@ -893,7 +895,8 @@ enum lov_comp_md_entry_flags {
 #define LCME_USER_MIRROR_FLAGS (LCME_FL_PREF_RW)
 
 /* The allowed flags obtained from the client at component creation time. */
-#define LCME_CL_COMP_FLAGS     (LCME_USER_MIRROR_FLAGS | LCME_FL_EXTENSION)
+#define LCME_CL_COMP_FLAGS     (LCME_USER_MIRROR_FLAGS | LCME_FL_EXTENSION | \
+                                LCME_FL_NOCOMPR)
 
 /* The mirror flags sent by client */
 #define LCME_MIRROR_FLAGS      (LCME_FL_NOSYNC)
@@ -902,7 +905,7 @@ enum lov_comp_md_entry_flags {
  * from the default/template layout set on a directory.
  */
 #define LCME_TEMPLATE_FLAGS    (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
-                                LCME_FL_EXTENSION)
+                                LCME_FL_EXTENSION | LCME_FL_NOCOMPR)
 
 /* lcme_id can be specified as certain flags, and the the first
  * bit of lcme_id is used to indicate that the ID is representing
index e1f781b..cd28ab1 100644 (file)
@@ -2016,6 +2016,29 @@ out_free_kernbuff:
 }
 LDEBUGFS_SEQ_FOPS(ll_pcc);
 
+static int ll_enable_compression_seq_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "%d\n", llite_enable_compression ? 1 : 0);
+       return 0;
+}
+
+static ssize_t ll_enable_compression_seq_write(struct file *file,
+                                              const char __user *buffer,
+                                              size_t count, loff_t *off)
+{
+       int val;
+       int rc;
+
+       rc = kstrtoint_from_user(buffer, count, 0, &val);
+       if (rc < 0)
+               return rc;
+
+       llite_enable_compression = !!val;
+
+       return count;
+}
+LDEBUGFS_SEQ_FOPS(ll_enable_compression);
+
 struct ldebugfs_vars lprocfs_llite_obd_vars[] = {
        { .name =       "site",
          .fops =       &ll_site_stats_fops                     },
@@ -2033,6 +2056,8 @@ struct ldebugfs_vars lprocfs_llite_obd_vars[] = {
          .fops =       &ll_nosquash_nids_fops                  },
        { .name =       "pcc",
          .fops =       &ll_pcc_fops,                           },
+       { .name =       "enable_compression",
+         .fops =       &ll_enable_compression_fops,            },
        { NULL }
 };
 
index 5218d67..5c8ec48 100644 (file)
@@ -173,6 +173,11 @@ struct lod_layout_component {
        __u32                     llc_flags;
        __u32                     llc_magic;
        __u64                     llc_timestamp; /* snapshot time */
+       __u8                      llc_compr_type;
+       __u8                      llc_compr_lvl:4;
+       __u16                     llc_compr_chunk_log_bits; /* chunk_size =
+                                                      * 2^chunk_log_bits
+                                                      */
        union {
                struct { /* plain layout V1/V3. */
                        __u32                     llc_pattern;
index 4686bc3..06bdec1 100644 (file)
@@ -981,6 +981,13 @@ int lod_generate_lovea(const struct lu_env *env, struct lod_object *lo,
                        cpu_to_le64(lod_comp->llc_extent.e_end);
                lcme->lcme_offset = cpu_to_le32(offset);
 
+               if (lod_comp->llc_pattern & LOV_PATTERN_COMPRESS) {
+                       lcme->lcme_compr_type = lod_comp->llc_compr_type;
+                       lcme->lcme_compr_lvl = lod_comp->llc_compr_lvl;
+                       lcme->lcme_compr_chunk_log_bits =
+                               lod_comp->llc_compr_chunk_log_bits - 16;
+               }
+
                sub_md = (struct lov_mds_md *)((char *)lcm + offset);
                if (lod_comp->llc_magic == LOV_MAGIC_FOREIGN) {
                        if (!lov_hsm_type_supported(lod_comp->llc_type)) {
index 8dc7b81..a21f874 100644 (file)
@@ -2971,6 +2971,12 @@ static int lod_declare_layout_set(const struct lu_env *env,
                                                        &lo->ldo_layout_mutex);
                                                RETURN(-EUCLEAN);
                                        }
+                                       if (flags & LCME_FL_NOCOMPR &&
+                                           lod_comp->llc_compr_type != 0) {
+                                               mutex_unlock(
+                                                       &lo->ldo_layout_mutex);
+                                               RETURN(-EINVAL);
+                                       }
                                        lod_comp->llc_flags |= flags;
                                }
                                if (mirror_flag) {
index daba7b4..3ba7524 100644 (file)
@@ -2381,20 +2381,21 @@ int lod_qos_parse_config(const struct lu_env *env, struct lod_object *lo,
        LASSERT(lo->ldo_comp_entries);
 
        for (i = 0; i < comp_cnt; i++) {
-               struct pool_desc        *pool;
-               struct lu_extent        *ext;
-               char    *pool_name;
+               struct pool_desc *pool;
+               struct lu_extent *ext;
+               char *pool_name;
+               struct lov_comp_md_entry_v1 *lcme = NULL;
 
                lod_comp = &lo->ldo_comp_entries[i];
 
                if (lo->ldo_is_composite) {
-                       v1 = (struct lov_user_md *)((char *)comp_v1 +
-                                       comp_v1->lcm_entries[i].lcme_offset);
-                       ext = &comp_v1->lcm_entries[i].lcme_extent;
+                       lcme = &comp_v1->lcm_entries[i];
+                       v1 = (struct lov_user_md *)
+                               ((char *)comp_v1 + lcme->lcme_offset);
+                       ext = &lcme->lcme_extent;
                        lod_comp->llc_extent = *ext;
-                       lod_comp->llc_flags =
-                               comp_v1->lcm_entries[i].lcme_flags &
-                                       LCME_CL_COMP_FLAGS;
+                       lod_comp->llc_flags = lcme->lcme_flags &
+                                             LCME_CL_COMP_FLAGS;
                }
 
                pool_name = NULL;
@@ -2419,6 +2420,8 @@ int lod_qos_parse_config(const struct lu_env *env, struct lod_object *lo,
                if (lov_pattern(v1->lmm_pattern) != LOV_PATTERN_RAID0 &&
                    lov_pattern(v1->lmm_pattern) != LOV_PATTERN_MDT &&
                    lov_pattern(v1->lmm_pattern) !=
+                       (LOV_PATTERN_RAID0 | LOV_PATTERN_COMPRESS) &&
+                   lov_pattern(v1->lmm_pattern) !=
                        (LOV_PATTERN_RAID0 | LOV_PATTERN_OVERSTRIPING)) {
                        CDEBUG(D_LAYOUT, "%s: invalid pattern: %x\n",
                               lod2obd(d)->obd_name, v1->lmm_pattern);
@@ -2442,6 +2445,13 @@ int lod_qos_parse_config(const struct lu_env *env, struct lod_object *lo,
                        GOTO(free_comp, rc = -EINVAL);
                }
 
+               if (lov_pattern(lod_comp->llc_pattern) & LOV_PATTERN_COMPRESS) {
+                       lod_comp->llc_compr_type = lcme->lcme_compr_type;
+                       lod_comp->llc_compr_lvl = lcme->lcme_compr_lvl;
+                       lod_comp->llc_compr_chunk_log_bits =
+                                       lcme->lcme_compr_chunk_log_bits + 16;
+               }
+
                lod_comp->llc_stripe_offset = v1->lmm_stripe_offset;
                lod_obj_set_pool(lo, i, pool_name);
 
index 821c943..cf88734 100644 (file)
 #include <libcfs/libcfs.h>
 
 #include <obd_class.h>
+#include <lustre_lib.h>
 #include "lov_internal.h"
 
+int llite_enable_compression;
+EXPORT_SYMBOL(llite_enable_compression);
+
 static inline void
 lu_extent_le_to_cpu(struct lu_extent *dst, const struct lu_extent *src)
 {
@@ -106,6 +110,14 @@ static int lsm_lmm_verify_v1v3(struct lov_mds_md *lmm, size_t lmm_size,
                goto out;
        }
 
+       if ((lov_pattern(pattern) & ~LOV_PATTERN_F_RELEASED &
+            LOV_PATTERN_COMPRESS) && !llite_enable_compression) {
+               rc = -EINVAL;
+               CERROR("lov: file compression not enabled: rc = %d\n", rc);
+               lov_dump_lmm_common(D_WARNING, lmm);
+               goto out;
+       }
+
        if (lmm->lmm_stripe_size == 0 ||
            (le32_to_cpu(lmm->lmm_stripe_size)&(LOV_MIN_STRIPE_SIZE-1)) != 0) {
                rc = -EINVAL;
@@ -573,6 +585,13 @@ lsm_unpackmd_comp_md_v1(struct lov_obd *lov, void *buf, size_t buf_size)
                                le64_to_cpu(lcme->lcme_timestamp);
                lu_extent_le_to_cpu(&lsme->lsme_extent, &lcme->lcme_extent);
 
+               if (lsme->lsme_pattern & LOV_PATTERN_COMPRESS) {
+                       lsme->lsme_compr_type = lcme->lcme_compr_type;
+                       lsme->lsme_compr_lvl = lcme->lcme_compr_lvl;
+                       lsme->lsme_compr_chunk_log_bits =
+                                       lcme->lcme_compr_chunk_log_bits;
+               }
+
                if (i == entry_count - 1) {
                        lsm->lsm_maxbytes = (loff_t)lsme->lsme_extent.e_start +
                                            maxbytes;
index b05fb56..43a280b 100644 (file)
@@ -48,6 +48,10 @@ struct lov_stripe_md_entry {
        u32                     lsme_flags;
        u32                     lsme_pattern;
        u64                     lsme_timestamp;
+       u8                      lsme_compr_type;
+       u8                      lsme_compr_lvl;
+       u8                      lsme_compr_chunk_log_bits;
+                                       /* chunk_size = 2^(16+chunk_log_bits) */
        union {
                struct { /* For stripe objects */
                        u32     lsme_stripe_size;
index c273ee8..4838de7 100644 (file)
@@ -2378,6 +2378,15 @@ void lustre_print_user_md(unsigned int lvl, struct lov_user_md *lum,
 
                v1 = (struct lov_user_md *)((char *)comp_v1 +
                                comp_v1->lcm_entries[i].lcme_offset);
+
+               if (v1->lmm_pattern & LOV_PATTERN_COMPRESS) {
+                       CDEBUG(lvl, "\tlcme_compr_type: %u\n",
+                              ent->lcme_compr_type);
+                       CDEBUG(lvl, "\tlcme_compr_lvl: %u\n",
+                              ent->lcme_compr_lvl);
+                       CDEBUG(lvl, "\tlcme_compr_chunk_log_bits: %u\n",
+                              ent->lcme_compr_chunk_log_bits);
+               }
                if (v1->lmm_magic == LOV_MAGIC_FOREIGN)
                        lustre_print_foreign(lvl, (struct lov_foreign_md *)v1,
                                             msg);
@@ -2485,6 +2494,9 @@ void lustre_swab_lov_comp_md_v1(struct lov_comp_md_v1 *lum)
                __swab32s(&ent->lcme_size);
                __swab32s(&ent->lcme_layout_gen);
                BUILD_BUG_ON(offsetof(typeof(*ent), lcme_padding_1) == 0);
+               /* no need to swab lcme_compr_type */
+               /* no need to swab lcme_compr_lvl */
+               /* no need to swab lcme_compr_chunk_log_bits */
 
                v1 = (struct lov_user_md_v1 *)((char *)lum + off);
                if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_FOREIGN) ||
index 5bb04c8..5268d86 100644 (file)
@@ -2432,6 +2432,34 @@ test_25() {
 }
 run_test 25 "Verify old lov stripe API with PFL files"
 
+test_100a() {
+       (( $MDS1_VERSION >= $(version_code 2.14.0.85) )) ||
+               skip "Need MDS >= 2.14.0.85 for compression support"
+
+       local tf=$DIR/$tdir/$tfile
+       local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
+
+       test_mkdir $DIR/$tdir
+       save_lustre_params client "llite.*.enable_compression" > $p
+       stack_trap "restore_lustre_params < $p" EXIT
+
+       $LCTL set_param llite.*.enable_compression=1
+
+       $LFS setstripe -Eeof --comp-flags=nocompr $tf ||
+               error "set a component with nocompr failed"
+       $LFS setstripe --comp-set -I1 --comp-flags=compress $tf &&
+               error "setstrpe to set a compress component should not be allowed"
+       $LFS setstripe --comp-set -I1 --comp-flags=partial $tf &&
+               error "setstrpe to set a partial compress component should not be allowed"
+
+       $LFS getstripe $tf
+
+       local comp_flags=$($LFS getstripe -I1 --comp-flags $tf)
+
+       [[ "$comp_flags" =~ "nocompr" ]] || error "$comp_flags do not have nocompr"
+}
+run_test 100a "set stripe coponent with nocompr"
+
 complete $SECONDS
 check_and_cleanup_lustre
 exit_status
index d760cf4..f249f63 100644 (file)
@@ -3462,7 +3462,8 @@ static int llapi_layout_sanity_cb(struct llapi_layout *layout,
                                args->lsa_rc = LSE_FLAGS;
                } else {
                        if (comp->llc_flags &
-                           ~(LCME_FL_EXTENSION | LCME_FL_PREF_RW))
+                           ~(LCME_FL_EXTENSION | LCME_FL_PREF_RW |
+                             LCME_FL_NOCOMPR))
                                args->lsa_rc = LSE_FLAGS;
                }
        }