Whamcloud - gitweb
LU-14194 cksum: add lprocfs checksum support in MDC/MDT 71/40971/5
authorMikhail Pershin <mpershin@whamcloud.com>
Tue, 15 Dec 2020 13:56:21 +0000 (16:56 +0300)
committerOleg Drokin <green@whamcloud.com>
Mon, 18 Jan 2021 14:59:46 +0000 (14:59 +0000)
Add missed support for checksum parameters in MDC and MDT
Handle T10-PI parameters in MDT similar to OFD, move all
functionality to target code and unify its usage in both
targets

Signed-off-by: Mikhail Pershin <mpershin@whamcloud.com>
Change-Id: I7d397067304e028bf597d5c3ab16250731ccba9d
Reviewed-on: https://review.whamcloud.com/40971
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
lustre/include/lu_target.h
lustre/mdc/lproc_mdc.c
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_lproc.c
lustre/ofd/lproc_ofd.c
lustre/ofd/ofd_dev.c
lustre/ofd/ofd_internal.h
lustre/ofd/ofd_obd.c
lustre/osc/lproc_osc.c
lustre/target/tgt_main.c

index 97ba236..2a109b0 100644 (file)
@@ -173,7 +173,10 @@ struct lu_target {
                                 /* e.g. OST node */
                                 lut_no_reconstruct:1,
                                 /* enforce recovery for local clients */
-                                lut_local_recovery:1;
+                                lut_local_recovery:1,
+                                lut_cksum_t10pi_enforce:1;
+       /* checksum types supported on this node */
+       enum cksum_types         lut_cksum_types_supported;
        /** last_rcvd file */
        struct dt_object        *lut_last_rcvd;
        /* transaction callbacks */
@@ -506,6 +509,7 @@ struct tg_reply_data *tgt_lookup_reply_by_xid(struct tg_export_data *ted,
                                               __u64 xid);
 int tgt_tunables_init(struct lu_target *lut);
 void tgt_tunables_fini(struct lu_target *lut);
+void tgt_mask_cksum_types(struct lu_target *lut, enum cksum_types *cksum_types);
 
 /* target/tgt_grant.c */
 static inline int exp_grant_param_supp(struct obd_export *exp)
index b52f241..3498334 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/vfs.h>
 #include <obd_class.h>
+#include <obd_cksum.h>
 #include <lprocfs_status.h>
 #include <lustre_osc.h>
 #include <cl_object.h>
@@ -192,6 +193,127 @@ static ssize_t mdc_max_dirty_mb_seq_write(struct file *file,
 }
 LPROC_SEQ_FOPS(mdc_max_dirty_mb);
 
+DECLARE_CKSUM_NAME;
+
+static int mdc_checksum_type_seq_show(struct seq_file *m, void *v)
+{
+       struct obd_device *obd = m->private;
+       int i;
+
+       if (obd == NULL)
+               return 0;
+
+       for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
+               if ((BIT(i) & obd->u.cli.cl_supp_cksum_types) == 0)
+                       continue;
+               if (obd->u.cli.cl_cksum_type == BIT(i))
+                       seq_printf(m, "[%s] ", cksum_name[i]);
+               else
+                       seq_printf(m, "%s ", cksum_name[i]);
+       }
+       seq_puts(m, "\n");
+
+       return 0;
+}
+
+static ssize_t mdc_checksum_type_seq_write(struct file *file,
+                                          const char __user *buffer,
+                                          size_t count, loff_t *off)
+{
+       struct seq_file *m = file->private_data;
+       struct obd_device *obd = m->private;
+       char kernbuf[10];
+       int rc = -EINVAL;
+       int i;
+
+       if (obd == NULL)
+               return 0;
+
+       if (count > sizeof(kernbuf) - 1)
+               return -EINVAL;
+       if (copy_from_user(kernbuf, buffer, count))
+               return -EFAULT;
+
+       if (count > 0 && kernbuf[count - 1] == '\n')
+               kernbuf[count - 1] = '\0';
+       else
+               kernbuf[count] = '\0';
+
+       for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
+               if (strcmp(kernbuf, cksum_name[i]) == 0) {
+                       obd->u.cli.cl_preferred_cksum_type = BIT(i);
+                       if (obd->u.cli.cl_supp_cksum_types & BIT(i)) {
+                               obd->u.cli.cl_cksum_type = BIT(i);
+                               rc = count;
+                       } else {
+                               rc = -ENOTSUPP;
+                       }
+                       break;
+               }
+       }
+
+       return rc;
+}
+LPROC_SEQ_FOPS(mdc_checksum_type);
+
+static ssize_t checksums_show(struct kobject *kobj,
+                             struct attribute *attr, char *buf)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!obd->u.cli.cl_checksum);
+}
+
+static ssize_t checksums_store(struct kobject *kobj,
+                              struct attribute *attr,
+                              const char *buffer,
+                              size_t count)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       bool val;
+       int rc;
+
+       rc = kstrtobool(buffer, &val);
+       if (rc)
+               return rc;
+
+       obd->u.cli.cl_checksum = val;
+
+       return count;
+}
+LUSTRE_RW_ATTR(checksums);
+
+static ssize_t checksum_dump_show(struct kobject *kobj,
+                                 struct attribute *attr, char *buf)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!obd->u.cli.cl_checksum_dump);
+}
+
+static ssize_t checksum_dump_store(struct kobject *kobj,
+                                  struct attribute *attr,
+                                  const char *buffer,
+                                  size_t count)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       bool val;
+       int rc;
+
+       rc = kstrtobool(buffer, &val);
+       if (rc)
+               return rc;
+
+       obd->u.cli.cl_checksum_dump = val;
+
+       return count;
+}
+LUSTRE_RW_ATTR(checksum_dump);
+
 static ssize_t contention_seconds_show(struct kobject *kobj,
                                       struct attribute *attr,
                                       char *buf)
@@ -500,6 +622,8 @@ struct lprocfs_vars lprocfs_mdc_obd_vars[] = {
          .fops =       &mdc_max_dirty_mb_fops          },
        { .name =       "mdc_cached_mb",
          .fops =       &mdc_cached_mb_fops             },
+       { .name =       "checksum_type",
+         .fops =       &mdc_checksum_type_fops         },
        { .name =       "timeouts",
          .fops =       &mdc_timeouts_fops              },
        { .name =       "import",
@@ -521,6 +645,8 @@ struct lprocfs_vars lprocfs_mdc_obd_vars[] = {
 
 static struct attribute *mdc_attrs[] = {
        &lustre_attr_active.attr,
+       &lustre_attr_checksums.attr,
+       &lustre_attr_checksum_dump.attr,
        &lustre_attr_max_rpcs_in_flight.attr,
        &lustre_attr_max_mod_rpcs_in_flight.attr,
        &lustre_attr_contention_seconds.attr,
index c7aea8d..8576a71 100644 (file)
@@ -6317,11 +6317,7 @@ static int mdt_connect_internal(const struct lu_env *env,
        if (OCD_HAS_FLAG(data, CKSUM)) {
                __u32 cksum_types = data->ocd_cksum_types;
 
-               /* The client set in ocd_cksum_types the checksum types it
-                * supports. We have to mask off the algorithms that we don't
-                * support */
-               data->ocd_cksum_types &=
-                       obd_cksum_types_supported_server(obd_name);
+               tgt_mask_cksum_types(&mdt->mdt_lut, &data->ocd_cksum_types);
 
                if (unlikely(data->ocd_cksum_types == 0)) {
                        CERROR("%s: Connect with checksum support but no "
index 3dc1b07..113a9b1 100644 (file)
@@ -1230,8 +1230,71 @@ static ssize_t dir_restripe_nsonly_store(struct kobject *kobj,
 }
 LUSTRE_RW_ATTR(dir_restripe_nsonly);
 
+/**
+ * Show if the OFD enforces T10PI checksum.
+ *
+ * \param[in] m                seq_file handle
+ * \param[in] data     unused for single entry
+ *
+ * \retval             0 on success
+ * \retval             negative value on error
+ */
+static ssize_t checksum_t10pi_enforce_show(struct kobject *kobj,
+                                          struct attribute *attr,
+                                          char *buf)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       struct lu_target *lut = obd->u.obt.obt_lut;
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n", lut->lut_cksum_t10pi_enforce);
+}
+
+/**
+ * Force specific T10PI checksum modes to be enabled
+ *
+ * If T10PI *is* supported in hardware, allow only the supported T10PI type
+ * to be used. If T10PI is *not* supported by the OSD, setting the enforce
+ * parameter forces all T10PI types to be enabled (even if slower) for
+ * testing.
+ *
+ * The final determination of which algorithm to be used depends whether
+ * the client supports T10PI or not, and is handled at client connect time.
+ *
+ * \param[in] file     proc file
+ * \param[in] buffer   string which represents mode
+ *                     1: set T10PI checksums enforced
+ *                     0: unset T10PI checksums enforced
+ * \param[in] count    \a buffer length
+ * \param[in] off      unused for single entry
+ *
+ * \retval             \a count on success
+ * \retval             negative number on error
+ */
+static ssize_t checksum_t10pi_enforce_store(struct kobject *kobj,
+                                           struct attribute *attr,
+                                           const char *buffer, size_t count)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       struct lu_target *lut = obd->u.obt.obt_lut;
+       bool enforce;
+       int rc;
+
+       rc = kstrtobool(buffer, &enforce);
+       if (rc)
+               return rc;
+
+       spin_lock(&lut->lut_flags_lock);
+       lut->lut_cksum_t10pi_enforce = enforce;
+       spin_unlock(&lut->lut_flags_lock);
+       return count;
+}
+LUSTRE_RW_ATTR(checksum_t10pi_enforce);
+
 LPROC_SEQ_FOPS_RO_TYPE(mdt, hash);
 LPROC_SEQ_FOPS_WR_ONLY(mdt, mds_evict_client);
+LPROC_SEQ_FOPS_RW_TYPE(mdt, checksum_dump);
 LUSTRE_RW_ATTR(job_cleanup_interval);
 LPROC_SEQ_FOPS_RW_TYPE(mdt, nid_stats_clear);
 LUSTRE_RW_ATTR(hsm_control);
@@ -1285,6 +1348,7 @@ static struct attribute *mdt_attrs[] = {
        &lustre_attr_dir_split_count.attr,
        &lustre_attr_dir_split_delta.attr,
        &lustre_attr_dir_restripe_nsonly.attr,
+       &lustre_attr_checksum_t10pi_enforce.attr,
        NULL,
 };
 
@@ -1297,6 +1361,8 @@ static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
          .fops =       &mdt_site_stats_fops                    },
        { .name =       "evict_client",
          .fops =       &mdt_mds_evict_client_fops              },
+       { .name =       "checksum_dump",
+         .fops =       &mdt_checksum_dump_fops                 },
        { .name =       "hash_stats",
          .fops =       &mdt_hash_fops                          },
        { .name =       "root_squash",
index 04aa829..5c27fa3 100644 (file)
@@ -811,9 +811,9 @@ static ssize_t checksum_t10pi_enforce_show(struct kobject *kobj,
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
                                              obd_kset.kobj);
-       struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev);
+       struct lu_target *lut = obd->u.obt.obt_lut;
 
-       return sprintf(buf, "%u\n", ofd->ofd_checksum_t10pi_enforce);
+       return scnprintf(buf, PAGE_SIZE, "%u\n", lut->lut_cksum_t10pi_enforce);
 }
 
 /**
@@ -843,7 +843,7 @@ static ssize_t checksum_t10pi_enforce_store(struct kobject *kobj,
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
                                              obd_kset.kobj);
-       struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev);
+       struct lu_target *lut = obd->u.obt.obt_lut;
        bool enforce;
        int rc;
 
@@ -851,9 +851,9 @@ static ssize_t checksum_t10pi_enforce_store(struct kobject *kobj,
        if (rc)
                return rc;
 
-       spin_lock(&ofd->ofd_flags_lock);
-       ofd->ofd_checksum_t10pi_enforce = enforce;
-       spin_unlock(&ofd->ofd_flags_lock);
+       spin_lock(&lut->lut_flags_lock);
+       lut->lut_cksum_t10pi_enforce = enforce;
+       spin_unlock(&lut->lut_flags_lock);
        return count;
 }
 LUSTRE_RW_ATTR(checksum_t10pi_enforce);
index 738d836..8b76814 100644 (file)
@@ -2953,7 +2953,6 @@ static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
 
        spin_lock_init(&m->ofd_flags_lock);
        m->ofd_raid_degraded = 0;
-       m->ofd_checksum_t10pi_enforce = 0;
        m->ofd_sync_journal = 0;
        ofd_slc_set(m);
        m->ofd_soft_sync_limit = OFD_SOFT_SYNC_LIMIT_DEFAULT;
@@ -3037,8 +3036,6 @@ static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
        tgd->tgd_reserved_pcnt = 0;
 
        m->ofd_brw_size = m->ofd_lut.lut_dt_conf.ddp_brw_size;
-       m->ofd_cksum_types_supported =
-               obd_cksum_types_supported_server(obd->obd_name);
        m->ofd_precreate_batch = OFD_PRECREATE_BATCH_DEFAULT;
        if (tgd->tgd_osfs.os_bsize * tgd->tgd_osfs.os_blocks <
            OFD_PRECREATE_SMALL_FS)
index d7ac1da..8bdb4c9 100644 (file)
@@ -135,9 +135,6 @@ struct ofd_device {
 
        /* preferred BRW size, decided by storage type and capability */
        __u32                    ofd_brw_size;
-       /* checksum types supported on this node */
-       enum cksum_types         ofd_cksum_types_supported;
-
        spinlock_t               ofd_flags_lock;
        unsigned long            ofd_raid_degraded:1,
                                 /* sync journal on writes */
@@ -147,9 +144,7 @@ struct ofd_device {
                                 ofd_record_fid_accessed:1,
                                 ofd_lfsck_verify_pfid:1,
                                 ofd_no_precreate:1,
-                                ofd_skip_lfsck:1,
-                                /* Whether to enforce T10PI checksum of RPC */
-                                ofd_checksum_t10pi_enforce:1;
+                                ofd_skip_lfsck:1;
        struct seq_server_site   ofd_seq_site;
        /* the limit of SOFT_SYNC RPCs that will trigger a soft sync */
        unsigned int             ofd_soft_sync_limit;
index 05e8293..d30f6da 100644 (file)
@@ -105,93 +105,6 @@ out:
 }
 
 /**
- * Decide which checksums both client and OST support, possibly forcing
- * the use of T10PI checksums if the hardware supports this.
- *
- * The clients that have no T10-PI RPC checksum support will use the same
- * mechanism to select checksum type as before, and will not be affected by
- * the following logic.
- *
- * For the clients that have T10-PI RPC checksum support:
- *
- * If the OST supports T10-PI feature and T10-PI checksum is enforced, clients
- * will have no other choice for RPC checksum type other than using the T10PI
- * checksum type. This is useful for enforcing end-to-end integrity in the
- * whole system.
- *
- * If the OST doesn't support T10-PI feature and T10-PI checksum is enforced,
- * together with other checksum with reasonably good speeds (e.g. crc32,
- * crc32c, adler, etc.), all T10-PI checksum types understood by the client
- * (t10ip512, t10ip4K, t10crc512, t10crc4K) will be added to the available
- * checksum types, regardless of the speeds of T10-PI checksums. This is
- * useful for testing T10-PI checksum of RPC.
- *
- * If the OST supports T10-PI feature and T10-PI checksum is NOT enforced,
- * the corresponding T10-PI checksum type will be added to the checksum type
- * list, regardless of the speed of the T10-PI checksum. This provides clients
- * the flexibility to choose whether to enable end-to-end integrity or not.
- *
- * If the OST does NOT supports T10-PI feature and T10-PI checksum is NOT
- * enforced, together with other checksums with reasonably good speeds,
- * all the T10-PI checksum types with good speeds will be added into the
- * checksum type list. Note that a T10-PI checksum type with a speed worse
- * than half of Alder will NOT be added as a option. In this circumstance,
- * T10-PI checksum types has the same behavior like other normal checksum
- * types.
- *
- */
-static void
-ofd_mask_cksum_types(struct ofd_device *ofd, enum cksum_types *cksum_types)
-{
-       bool enforce = ofd->ofd_checksum_t10pi_enforce;
-       enum cksum_types ofd_t10_cksum_type;
-       enum cksum_types client_t10_types = *cksum_types & OBD_CKSUM_T10_ALL;
-       enum cksum_types server_t10_types;
-
-       /*
-        * The client set in ocd_cksum_types the checksum types it
-        * supports. We have to mask off the algorithms that we don't
-        * support. T10PI checksum types will be added later.
-        */
-       *cksum_types &= (ofd->ofd_cksum_types_supported & ~OBD_CKSUM_T10_ALL);
-       server_t10_types = ofd->ofd_cksum_types_supported & OBD_CKSUM_T10_ALL;
-       ofd_t10_cksum_type = ofd->ofd_lut.lut_dt_conf.ddp_t10_cksum_type;
-
-       /* Quick exit if no T10-PI support on client */
-       if (!client_t10_types)
-               return;
-
-       /*
-        * This OST has NO T10-PI feature. Add all supported T10-PI checksums
-        * as options if T10-PI checksum is enforced. If the T10-PI checksum is
-        * not enforced, only add them as options when speed is good.
-        */
-       if (ofd_t10_cksum_type == 0) {
-               /*
-                * Server allows all T10PI checksums, and server_t10_types
-                * include quick ones.
-                */
-               if (enforce)
-                       *cksum_types |= client_t10_types;
-               else
-                       *cksum_types |= client_t10_types & server_t10_types;
-               return;
-       }
-
-       /*
-        * This OST has T10-PI feature. Disable all other checksum types if
-        * T10-PI checksum is enforced. If the T10-PI checksum is not enforced,
-        * add the checksum type as an option.
-        */
-       if (client_t10_types & ofd_t10_cksum_type) {
-               if (enforce)
-                       *cksum_types = ofd_t10_cksum_type;
-               else
-                       *cksum_types |= ofd_t10_cksum_type;
-       }
-}
-
-/**
  * Match client and OST server connection feature flags.
  *
  * Compute the compatibility flags for a connection request based on
@@ -323,7 +236,7 @@ static int ofd_parse_connect_data(const struct lu_env *env,
        if (data->ocd_connect_flags & OBD_CONNECT_CKSUM) {
                __u32 cksum_types = data->ocd_cksum_types;
 
-               ofd_mask_cksum_types(ofd, &data->ocd_cksum_types);
+               tgt_mask_cksum_types(&ofd->ofd_lut, &data->ocd_cksum_types);
 
                if (unlikely(data->ocd_cksum_types == 0)) {
                        CERROR("%s: Connect with checksum support but no ocd_cksum_types is set\n",
index 85180ac..3bd71dd 100644 (file)
@@ -365,7 +365,7 @@ static ssize_t checksums_show(struct kobject *kobj,
        struct obd_device *obd = container_of(kobj, struct obd_device,
                                              obd_kset.kobj);
 
-       return sprintf(buf, "%d\n", obd->u.cli.cl_checksum ? 1 : 0);
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!obd->u.cli.cl_checksum);
 }
 
 static ssize_t checksums_store(struct kobject *kobj,
@@ -388,14 +388,15 @@ static ssize_t checksums_store(struct kobject *kobj,
 }
 LUSTRE_RW_ATTR(checksums);
 
+DECLARE_CKSUM_NAME;
+
 static int osc_checksum_type_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *obd = m->private;
        int i;
-       DECLARE_CKSUM_NAME;
 
-        if (obd == NULL)
-                return 0;
+       if (obd == NULL)
+               return 0;
 
        for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
                if ((BIT(i) & obd->u.cli.cl_supp_cksum_types) == 0)
@@ -405,7 +406,8 @@ static int osc_checksum_type_seq_show(struct seq_file *m, void *v)
                else
                        seq_printf(m, "%s ", cksum_name[i]);
        }
-       seq_printf(m, "\n");
+       seq_puts(m, "\n");
+
        return 0;
 }
 
@@ -415,10 +417,9 @@ static ssize_t osc_checksum_type_seq_write(struct file *file,
 {
        struct seq_file *m = file->private_data;
        struct obd_device *obd = m->private;
-       int i;
-       DECLARE_CKSUM_NAME;
        char kernbuf[10];
        int rc = -EINVAL;
+       int i;
 
        if (obd == NULL)
                return 0;
@@ -486,7 +487,7 @@ static ssize_t checksum_dump_show(struct kobject *kobj,
        struct obd_device *obd = container_of(kobj, struct obd_device,
                                              obd_kset.kobj);
 
-       return sprintf(buf, "%d\n", obd->u.cli.cl_checksum_dump ? 1 : 0);
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!obd->u.cli.cl_checksum_dump);
 }
 
 static ssize_t checksum_dump_store(struct kobject *kobj,
index b774eb0..76ccece 100644 (file)
@@ -34,6 +34,7 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 #include <obd.h>
+#include <obd_cksum.h>
 #include "tgt_internal.h"
 #include "../ptlrpc/ptlrpc_internal.h"
 
@@ -253,6 +254,92 @@ static const struct attribute *tgt_attrs[] = {
        NULL,
 };
 
+/**
+ * Decide which checksums both client and OST support, possibly forcing
+ * the use of T10PI checksums if the hardware supports this.
+ *
+ * The clients that have no T10-PI RPC checksum support will use the same
+ * mechanism to select checksum type as before, and will not be affected by
+ * the following logic.
+ *
+ * For the clients that have T10-PI RPC checksum support:
+ *
+ * If the target supports T10-PI feature and T10-PI checksum is enforced,
+ * clients will have no other choice for RPC checksum type other than using
+ * the T10PI checksum type. This is useful for enforcing end-to-end integrity
+ * in the whole system.
+ *
+ * If the target doesn't support T10-PI feature and T10-PI checksum is
+ * enforced, together with other checksum with reasonably good speeds (e.g.
+ * crc32, crc32c, adler, etc.), all T10-PI checksum types understood by the
+ * client (t10ip512, t10ip4K, t10crc512, t10crc4K) will be added to the
+ * available checksum types, regardless of the speeds of T10-PI checksums.
+ * This is useful for testing T10-PI checksum of RPC.
+ *
+ * If the target supports T10-PI feature and T10-PI checksum is NOT enforced,
+ * the corresponding T10-PI checksum type will be added to the checksum type
+ * list, regardless of the speed of the T10-PI checksum. This provides clients
+ * the flexibility to choose whether to enable end-to-end integrity or not.
+ *
+ * If the target does NOT supports T10-PI feature and T10-PI checksum is NOT
+ * enforced, together with other checksums with reasonably good speeds,
+ * all the T10-PI checksum types with good speeds will be added into the
+ * checksum type list. Note that a T10-PI checksum type with a speed worse
+ * than half of Alder will NOT be added as a option. In this circumstance,
+ * T10-PI checksum types has the same behavior like other normal checksum
+ * types.
+ */
+void tgt_mask_cksum_types(struct lu_target *lut, enum cksum_types *cksum_types)
+{
+       bool enforce = lut->lut_cksum_t10pi_enforce;
+       enum cksum_types tgt_t10_cksum_type;
+       enum cksum_types client_t10_types = *cksum_types & OBD_CKSUM_T10_ALL;
+       enum cksum_types server_t10_types;
+
+       /*
+        * The client set in ocd_cksum_types the checksum types it
+        * supports. We have to mask off the algorithms that we don't
+        * support. T10PI checksum types will be added later.
+        */
+       *cksum_types &= (lut->lut_cksum_types_supported & ~OBD_CKSUM_T10_ALL);
+       server_t10_types = lut->lut_cksum_types_supported & OBD_CKSUM_T10_ALL;
+       tgt_t10_cksum_type = lut->lut_dt_conf.ddp_t10_cksum_type;
+
+       /* Quick exit if no T10-PI support on client */
+       if (!client_t10_types)
+               return;
+
+       /*
+        * This OST has NO T10-PI feature. Add all supported T10-PI checksums
+        * as options if T10-PI checksum is enforced. If the T10-PI checksum is
+        * not enforced, only add them as options when speed is good.
+        */
+       if (tgt_t10_cksum_type == 0) {
+               /*
+                * Server allows all T10PI checksums, and server_t10_types
+                * include quick ones.
+                */
+               if (enforce)
+                       *cksum_types |= client_t10_types;
+               else
+                       *cksum_types |= client_t10_types & server_t10_types;
+               return;
+       }
+
+       /*
+        * This OST has T10-PI feature. Disable all other checksum types if
+        * T10-PI checksum is enforced. If the T10-PI checksum is not enforced,
+        * add the checksum type as an option.
+        */
+       if (client_t10_types & tgt_t10_cksum_type) {
+               if (enforce)
+                       *cksum_types = tgt_t10_cksum_type;
+               else
+                       *cksum_types |= tgt_t10_cksum_type;
+       }
+}
+EXPORT_SYMBOL(tgt_mask_cksum_types);
+
 int tgt_tunables_init(struct lu_target *lut)
 {
        int rc;
@@ -419,6 +506,9 @@ int tgt_init(const struct lu_env *env, struct lu_target *lut,
 
        spin_lock_init(&lut->lut_flags_lock);
        lut->lut_sync_lock_cancel = SYNC_LOCK_CANCEL_NEVER;
+       lut->lut_cksum_t10pi_enforce = 0;
+       lut->lut_cksum_types_supported =
+               obd_cksum_types_supported_server(obd->obd_name);
 
        spin_lock_init(&lut->lut_slc_locks_guard);
        INIT_LIST_HEAD(&lut->lut_slc_locks);