/* Convert a text string to a bitmask */
int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
int *oldmask, int minmask, int allmask, int defmask);
+int cfs_str2mask64(const char *str, const char *(*bit2str)(int bit),
+ __u64 *oldmask, __u64 minmask, __u64 allmask, __u64 defmask);
/* trim leading and trailing space characters */
char *cfs_firststr(char *str, size_t size);
}
EXPORT_SYMBOL(cfs_strrstr);
-/* Convert a text string to a bitmask */
-int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
- int *oldmask, int minmask, int allmask, int defmask)
+/* Convert a text string to a 64bit-mask */
+int cfs_str2mask64(const char *str, const char *(*bit2str)(int bit),
+ __u64 *oldmask, __u64 minmask, __u64 allmask, __u64 defmask)
{
const char *debugstr;
char op = 0;
- int newmask = minmask, i, len, found = 0;
+ __u64 newmask = minmask;
+ int i, len, found = 0;
ENTRY;
/* <str> must be a list of tokens separated by whitespace or comma,
/* match token */
found = 0;
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < 64; i++) {
debugstr = bit2str(i);
if (debugstr != NULL &&
strlen(debugstr) == len &&
*oldmask = newmask;
return 0;
}
+EXPORT_SYMBOL(cfs_str2mask64);
+
+/* Convert a text string to a bitmask */
+int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
+ int *oldmask, int minmask, int allmask, int defmask)
+{
+ __u64 old = *oldmask;
+ __u64 min = minmask;
+ __u64 all = allmask;
+ __u64 def = defmask;
+ int rc;
+
+ rc = cfs_str2mask64(str, bit2str, &old, min, all, def);
+ if (rc == 0)
+ *oldmask = (int)old;
+
+ return rc;
+}
EXPORT_SYMBOL(cfs_str2mask);
/* get the first string out of @str */
lut_no_create:1;
/* checksum types supported on this node */
enum cksum_types lut_cksum_types_supported;
+ /* compression types supported on this node */
+ __u64 lut_compress_types_supported;
/** last_rcvd file */
struct dt_object *lut_last_rcvd;
/* transaction callbacks */
#define OST_CONNECT_SUPPORTED2 (OBD_CONNECT2_LOCKAHEAD | OBD_CONNECT2_INC_XID |\
OBD_CONNECT2_ENCRYPT | OBD_CONNECT2_LSEEK | \
- OBD_CONNECT2_REPLAY_CREATE)
+ OBD_CONNECT2_REPLAY_CREATE | \
+ OBD_CONNECT2_COMPRESS)
#define ECHO_CONNECT_SUPPORTED (OBD_CONNECT_FID)
#define ECHO_CONNECT_SUPPORTED2 0
__u16 padding0; /* READ BELOW! also fix lustre_swab_connect */
__u32 padding1; /* READ BELOW! also fix lustre_swab_connect */
__u64 ocd_connect_flags2;/* OBD_CONNECT2_* per above */
- __u64 ocd_compr_type; /* bitmask of supported compression types */
+ __u64 ocd_compress_types;/* bitmask of supported compression types */
__u64 padding4; /* READ BELOW! also fix lustre_swab_connect */
__u64 padding5; /* READ BELOW! also fix lustre_swab_connect */
__u64 padding6; /* READ BELOW! also fix lustre_swab_connect */
#define OBD_CKSUM_T10_TOP OBD_CKSUM_ADLER
/*
+ * Supported compression algorithms. Up to 64 compression types are supported.
+ */
+#define COMPRESS_TYPE_TO_BIT(ll_compr_type) \
+ ((ll_compr_type == LL_COMPR_TYPE_NONE) ? 0 : \
+ (1U << ((ll_compr_type) - 1)))
+#define COMPRESS_TYPE_MAX_BIT (LL_COMPR_TYPE_MAX - 1)
+
+enum obd_compress_types {
+ OBD_COMPR_NONE = 0,
+ OBD_COMPR_FAST = COMPRESS_TYPE_TO_BIT(LL_COMPR_TYPE_FAST),
+ OBD_COMPR_BEST = COMPRESS_TYPE_TO_BIT(LL_COMPR_TYPE_BEST),
+ OBD_COMPR_GZIP = COMPRESS_TYPE_TO_BIT(LL_COMPR_TYPE_GZIP),
+ OBD_COMPR_LZ4FAST = COMPRESS_TYPE_TO_BIT(LL_COMPR_TYPE_LZ4FAST),
+ OBD_COMPR_LZ4HC = COMPRESS_TYPE_TO_BIT(LL_COMPR_TYPE_LZ4HC),
+ OBD_COMPR_LZO = COMPRESS_TYPE_TO_BIT(LL_COMPR_TYPE_LZO),
+ OBD_COMPR_ALL = OBD_COMPR_FAST | OBD_COMPR_BEST |
+ OBD_COMPR_GZIP | OBD_COMPR_LZ4FAST |
+ OBD_COMPR_LZ4HC | OBD_COMPR_LZO
+};
+
+#define COMPRESS_NAMES { "fast", "best", "gzip", "lz4fast", "lz4hc", "lzo" }
+
+static inline const char *compress_type2str(int type_bit)
+{
+ static const char *const compress_name[] = COMPRESS_NAMES;
+
+ if (type_bit >= COMPRESS_TYPE_MAX_BIT)
+ return NULL;
+
+ return compress_name[type_bit];
+}
+
+/*
* OST requests: OBDO & OBD request records
*/
#define OBD_MAX_FIDS_IN_ARRAY 4096
/**
- * component compress algorithm type
+ * component compress algorithm type, remember to update obd_compress_types
+ * and COMPRESS_NAMES accordingly
*/
enum ll_compr_type {
LL_COMPR_TYPE_NONE = 0,
OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO |
OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK;
data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD |
- OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK;
+ OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK |
+ OBD_CONNECT2_COMPRESS;
if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM))
data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM;
data->ocd_cksum_types = OBD_CKSUM_ADLER;
else
data->ocd_cksum_types = obd_cksum_types_supported_client();
+ data->ocd_compress_types = OBD_COMPR_ALL;
#ifdef HAVE_LRU_RESIZE_SUPPORT
data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE;
exp->exp_obd->obd_name, obd_export_nid2str(exp));
}
+ if (OCD_HAS_FLAG2(data, COMPRESS))
+ data->ocd_compress_types &=
+ mdt->mdt_lut.lut_compress_types_supported;
+
if ((data->ocd_connect_flags & OBD_CONNECT_MDS_MDS) &&
!(data->ocd_connect_flags & OBD_CONNECT_LIGHTWEIGHT)) {
atomic_inc(&mdt->mdt_mds_mds_conns);
LPROC_SEQ_FOPS_RO(mdt_checksum_type);
+/*
+ * mdt_compress_types(server) proc handling
+ */
+static int mdt_compress_types_seq_show(struct seq_file *m, void *data)
+{
+ struct obd_device *obd = m->private;
+ struct lu_target *lut;
+ bool first = true;
+ int i;
+
+ if (!obd)
+ return 0;
+
+ lut = obd->u.obt.obt_lut;
+
+ for (i = 0; i < COMPRESS_TYPE_MAX_BIT; i++) {
+ if ((BIT(i) & lut->lut_compress_types_supported) == 0)
+ continue;
+
+ seq_printf(m, "%s%s", first ? "" : ",", compress_type2str(i));
+ first = false;
+ }
+ seq_puts(m, "\n");
+
+ return 0;
+}
+
+static ssize_t mdt_compress_types_seq_write(struct file *file,
+ const char __user *buffer,
+ size_t count, loff_t *off)
+{
+ struct seq_file *seq = file->private_data;
+ struct obd_device *obd = seq->private;
+ struct lu_target *lut;
+ char *kbuf;
+ int rc = 0;
+
+ lut = obd->u.obt.obt_lut;
+
+ OBD_ALLOC(kbuf, count + 1);
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(kbuf, buffer, count))
+ GOTO(out, rc = -EFAULT);
+ kbuf[count] = 0;
+
+ rc = cfs_str2mask64(kbuf, compress_type2str,
+ &lut->lut_compress_types_supported, 0, ~0, ~0);
+
+out:
+ OBD_FREE(kbuf, count + 1);
+ return rc < 0 ? rc : count;
+}
+LPROC_SEQ_FOPS(mdt_compress_types);
+
LPROC_SEQ_FOPS_RO_TYPE(mdt, hash);
LPROC_SEQ_FOPS_WR_ONLY(mdt, mds_evict_client);
LPROC_SEQ_FOPS_RW_TYPE(mdt, checksum_dump);
.fops = &mdt_nosquash_nids_fops },
{ .name = "checksum_type",
.fops = &mdt_checksum_type_fops },
+ { .name = "compress_types",
+ .fops = &mdt_compress_types_fops },
{ NULL }
};
flag2str(imp, connect_tried);
}
+static void obd_compress_type2str(struct seq_file *m, __u64 compress_types)
+{
+ bool first = true;
+ int i;
+
+ for (i = 0; i < COMPRESS_TYPE_MAX_BIT; i++) {
+ if ((BIT(i) & compress_types)) {
+ seq_printf(m, "%s%s",
+ first ? "" : ",", compress_type2str(i));
+ first = false;
+ }
+ }
+}
+
static const char *const obd_connect_names[] = {
"read_only", /* 0x01 */
"lov_index", /* 0x02 */
obd_connect_data_seqprint(struct seq_file *m, struct obd_connect_data *ocd)
{
__u64 flags;
+ __u64 flags2;
LASSERT(ocd != NULL);
flags = ocd->ocd_connect_flags;
+ flags2 = ocd->ocd_connect_flags2;
seq_printf(m, " connect_data:\n"
" flags: %#llx\n"
if (flags & OBD_CONNECT_CKSUM)
seq_printf(m, " cksum_types: %#x\n",
ocd->ocd_cksum_types);
+ if (flags2 & OBD_CONNECT2_COMPRESS) {
+ seq_printf(m, " compress_types: [ ");
+ obd_compress_type2str(m, ocd->ocd_compress_types);
+ seq_printf(m, " ]\n");
+ }
if (flags & OBD_CONNECT_MAX_EASIZE)
seq_printf(m, " max_easize: %d\n", ocd->ocd_max_easize);
if (flags & OBD_CONNECT_MAXBYTES)
LPROC_SEQ_FOPS_RO(ofd_checksum_type);
+/*
+ * ofd_compress_types(server) proc handling
+ */
+static int ofd_compress_types_seq_show(struct seq_file *m, void *data)
+{
+ struct obd_device *obd = m->private;
+ struct lu_target *lut;
+ bool first = true;
+ int i;
+
+ if (!obd)
+ return 0;
+
+ lut = obd->u.obt.obt_lut;
+
+ for (i = 0; i < COMPRESS_TYPE_MAX_BIT; i++) {
+ if ((BIT(i) & lut->lut_compress_types_supported) == 0)
+ continue;
+
+ seq_printf(m, "%s%s", first ? "" : ",", compress_type2str(i));
+ first = false;
+ }
+ seq_puts(m, "\n");
+
+ return 0;
+}
+
+static ssize_t ofd_compress_types_seq_write(struct file *file,
+ const char __user *buffer,
+ size_t count, loff_t *off)
+{
+ struct seq_file *seq = file->private_data;
+ struct obd_device *obd = seq->private;
+ struct lu_target *lut;
+ char *kbuf;
+ int rc = 0;
+
+ lut = obd->u.obt.obt_lut;
+
+ OBD_ALLOC(kbuf, count + 1);
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(kbuf, buffer, count))
+ GOTO(out, rc = -EFAULT);
+ kbuf[count] = 0;
+
+ rc = cfs_str2mask64(kbuf, compress_type2str,
+ &lut->lut_compress_types_supported, 0, ~0, ~0);
+out:
+ OBD_FREE(kbuf, count + 1);
+ return rc < 0 ? rc : count;
+}
+LPROC_SEQ_FOPS(ofd_compress_types);
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 16, 53, 0)
static ssize_t sync_on_lock_cancel_show(struct kobject *kobj,
.fops = &ofd_site_stats_fops },
{ .name = "checksum_type",
.fops = &ofd_checksum_type_fops },
+ { .name = "compress_types",
+ .fops = &ofd_compress_types_fops },
{ NULL }
};
exp->exp_obd->obd_name, obd_export_nid2str(exp));
}
+ if (OCD_HAS_FLAG2(data, COMPRESS))
+ data->ocd_compress_types &=
+ ofd->ofd_lut.lut_compress_types_supported;
+
if (data->ocd_connect_flags & OBD_CONNECT_MAXBYTES)
data->ocd_maxbytes = ofd->ofd_lut.lut_dt_conf.ddp_maxbytes;
struct req_capsule *pill;
struct brw_page *pg_prev;
struct obd_ioobj *ioobj;
- struct cl_page *clpage;
+ struct cl_page *clpage = NULL;
struct ost_body *body;
const char *obd_name = cli->cl_import->imp_obd->obd_name;
bool page_access_allowed = true;
RETURN(-EINVAL);
if (opc == OST_WRITE && compressed) {
+ struct obd_connect_data *ocd =
+ &cli->cl_import->imp_connect_data;
struct brw_page **cpga = NULL;
__u64 kms = -1;
clpage = oap2cl_page(oap);
+ /**
+ * if server now does not support certain compression algorithm
+ * which is supposed to be used in this file chunk, try
+ * FAST compression type.
+ */
+ if ((COMPRESS_TYPE_TO_BIT(clpage->cp_comp_type) &
+ ocd->ocd_compress_types) == 0) {
+ for (i = 0; i < page_count; i++) {
+ clpage = oap2cl_page(brw_page2oap(pga[i]));
+ clpage->cp_comp_type = LL_COMPR_TYPE_FAST;
+ }
+ }
+
/* if a write is beyond the current known minimum size, we
* know there is no data in the chunk, so no possibility of
* read-modify write. this means we can compress that chunk
if (ocd->ocd_connect_flags & OBD_CONNECT_FLAGS2) {
__swab64s(&ocd->ocd_connect_flags2);
if (ocd->ocd_connect_flags2 & OBD_CONNECT2_COMPRESS)
- __swab64s(&ocd->ocd_compr_type);
+ __swab64s(&ocd->ocd_compress_types);
}
BUILD_BUG_ON(offsetof(typeof(*ocd), padding4) == 0);
BUILD_BUG_ON(offsetof(typeof(*ocd), padding5) == 0);
(long long)(int)offsetof(struct obd_connect_data, ocd_connect_flags2));
LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_connect_flags2) == 8, "found %lld\n",
(long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_connect_flags2));
- LASSERTF((int)offsetof(struct obd_connect_data, ocd_compr_type) == 88, "found %lld\n",
- (long long)(int)offsetof(struct obd_connect_data, ocd_compr_type));
- LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_compr_type) == 8, "found %lld\n",
- (long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_compr_type));
+ LASSERTF((int)offsetof(struct obd_connect_data, ocd_compress_types) == 88, "found %lld\n",
+ (long long)(int)offsetof(struct obd_connect_data, ocd_compress_types));
+ LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_compress_types) == 8, "found %lld\n",
+ (long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_compress_types));
LASSERTF((int)offsetof(struct obd_connect_data, padding4) == 96, "found %lld\n",
(long long)(int)offsetof(struct obd_connect_data, padding4));
LASSERTF((int)sizeof(((struct obd_connect_data *)0)->padding4) == 8, "found %lld\n",
lut->lut_cksum_t10pi_enforce = 0;
lut->lut_cksum_types_supported =
obd_cksum_types_supported_server(obd->obd_name);
+ lut->lut_compress_types_supported = OBD_COMPR_ALL;
spin_lock_init(&lut->lut_slc_locks_guard);
INIT_LIST_HEAD(&lut->lut_slc_locks);
# Set file system with different layout
COMPR_EXTRA_LAYOUT=${COMPR_EXTRA_LAYOUT:-"-E EOF -c 1"}
$LFS setstripe $COMPR_EXTRA_LAYOUT $MOUNT
+ALWAYS_EXCEPT_SAVE=$ALWAYS_EXCEPT
+
+test_0a() {
+ local types_save=($(do_facet ost1 \
+ $LCTL get_param -n obdfilter.*.compress_types))
+
+ [[ -n "$types_save" ]] || skip "no OST support for compress_types"
+ stack_trap "do_facet ost1 \
+ $LCTL set_param obdfilter.*.compress_types='$types_save'"
+
+ echo " ** add gzip, delete lzo compression type on OST"
+ do_facet ost1 $LCTL set_param obdfilter.*.compress_types=+gzip-lzo
+
+ # remount client to get new compression types from OSS
+ umount_client $MOUNT
+ mount_client $MOUNT
+
+ local types=$($LCTL get_param -n osc.*.import | grep compress_types)
+ [[ -n "$types" ]] || {
+ do_facet ost1 $LCTL get_param obdfilter.*.compress_types
+ echo $types
+ error "cannot find any compress support on client"
+ }
+
+ [[ "$types" =~ "gzip" ]] || {
+ do_facet ost1 $LCTL get_param obdfilter.*.compress_types
+ echo $types
+ error "cannot find gzip compress support on client"
+ }
+
+ [[ "$types" =~ "lzo" ]] && {
+ do_facet ost1 $LCTL get_param obdfilter.*.compress_types
+ echo $types
+ error "should not have lzo compress support on client"
+ }
+
+ do_facet ost1 $LCTL set_param obdfilter.*.compress_types='$types_save'
+ # need to remount to allow client to use all compression types
+ umount_client $MOUNT
+ mount_client $MOUNT
+}
+run_test 0a "compression types negotiation between client and OST"
+
+test_0b() {
+ local types_save=($(do_facet mds1 \
+ $LCTL get_param -n mdt.*.compress_types))
+
+ skip "MDT support for compression connect flags is disabled for now"
+
+ [[ -n "$types_save" ]] || skip "no MDT support for compress_types"
+ stack_trap "do_facet mds1 \
+ $LCTL set_param mdt.*.compress_types='$types_save'"
+
+ echo " ** add gzip, delete lzo compression type on MDT"
+ do_facet mds1 $LCTL set_param mdt.*.compress_types=+gzip-lzo
+
+ # remount client to get new compression types from MDS
+ umount_client $MOUNT
+ mount_client $MOUNT
+
+ local types=$($LCTL get_param -n mdc.*.import | grep compress_types)
+ [[ -n "$types" ]] || {
+ do_facet mds1 $LCTL get_param obdfilter.*.compress_types
+ echo $types
+ error "cannot find any compress support on client"
+ }
+
+ [[ "$types" =~ "gzip" ]] || {
+ do_facet mds1 $LCTL get_param obdfilter.*.compress_types
+ echo $types
+ error "cannot find gzip compress support on client"
+ }
+
+ [[ "$types" =~ "lzo" ]] && {
+ do_facet mds1 $LCTL get_param obdfilter.*.compress_types
+ echo $types
+ error "should not have lzo compress support on client"
+ }
+
+ do_facet mds1 $LCTL set_param mdt.*.compress_types='$types_save'
+ # need to remount to allow client to use all compression types
+ umount_client $MOUNT
+ mount_client $MOUNT
+}
+run_test 0b "compression types negotiation between client and MDT"
test_sanity()
{
CHECK_MEMBER(obd_connect_data, padding0);
CHECK_MEMBER(obd_connect_data, padding1);
CHECK_MEMBER(obd_connect_data, ocd_connect_flags2);
- CHECK_MEMBER(obd_connect_data, ocd_compr_type);
+ CHECK_MEMBER(obd_connect_data, ocd_compress_types);
CHECK_MEMBER(obd_connect_data, padding4);
CHECK_MEMBER(obd_connect_data, padding5);
CHECK_MEMBER(obd_connect_data, padding6);
(long long)(int)offsetof(struct obd_connect_data, ocd_connect_flags2));
LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_connect_flags2) == 8, "found %lld\n",
(long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_connect_flags2));
- LASSERTF((int)offsetof(struct obd_connect_data, ocd_compr_type) == 88, "found %lld\n",
- (long long)(int)offsetof(struct obd_connect_data, ocd_compr_type));
- LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_compr_type) == 8, "found %lld\n",
- (long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_compr_type));
+ LASSERTF((int)offsetof(struct obd_connect_data, ocd_compress_types) == 88, "found %lld\n",
+ (long long)(int)offsetof(struct obd_connect_data, ocd_compress_types));
+ LASSERTF((int)sizeof(((struct obd_connect_data *)0)->ocd_compress_types) == 8, "found %lld\n",
+ (long long)(int)sizeof(((struct obd_connect_data *)0)->ocd_compress_types));
LASSERTF((int)offsetof(struct obd_connect_data, padding4) == 96, "found %lld\n",
(long long)(int)offsetof(struct obd_connect_data, padding4));
LASSERTF((int)sizeof(((struct obd_connect_data *)0)->padding4) == 8, "found %lld\n",