/* 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 */
__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)
#include <linux/vfs.h>
#include <obd_class.h>
+#include <obd_cksum.h>
#include <lprocfs_status.h>
#include <lustre_osc.h>
#include <cl_object.h>
}
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)
.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",
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,
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 "
}
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);
&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,
};
.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",
{
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);
}
/**
{
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;
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);
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;
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)
/* 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 */
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;
}
/**
- * 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
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",
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,
}
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)
else
seq_printf(m, "%s ", cksum_name[i]);
}
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
+
return 0;
}
{
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;
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,
#define DEBUG_SUBSYSTEM S_CLASS
#include <obd.h>
+#include <obd_cksum.h>
#include "tgt_internal.h"
#include "../ptlrpc/ptlrpc_internal.h"
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;
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);