.I key
to value
.IR value .
-This option can be repeated as desired. Typical options might include:
+This option can be repeated as desired. Typical options might include:
.RS
.I \--param sys.timeout=40
.RS
Set user comment about this disk, ignored by Lustre.
.TP
.BI \--dryrun
-Only print what would be done; does not affect the disk
+Only print what would be done; does not affect the disk.
+.TP
+.BI \--erase-param " param"
+Remove all previously stored instances of the parameter \fIparam\fR. Attempts
+to remove a non-existing parameter appear as successful ones.
.TP
.BI \--erase-params
-Remove all previous parameter info
+Remove all previously stored parameter info.
.TP
.BI \--failnode= nid,...
Set the NID(s) of a failover partner. This option can be repeated as desired.
service nodes. Cannot be used with --failnode.
.TP
.BI \--fsname= filesystem_name
-The Lustre filesystem this service will be part of. Default is 'lustre'
+The Lustre filesystem this service will be part of. Default is 'lustre'.
.TP
.BI \--index= index
-Force a particular OST or MDT index
+Force a particular OST or MDT index.
.TP
.BI \--mountfsoptions= opts
Set the persistent mount options that will be used when Lustre fs.
Network(s) to restrict this ost/mdt to. This option can be repeated as desired.
.TP
.BI \--mgs
-Add a configuration management service to this target
+Add a configuration management service to this target.
.TP
.BI \--mgsnode= nid,...
Set the NID(s) of the MGS node, required for all targets other than the MGS.
.TP
.BI \--nomgs
-Remove a configuration management service to this target
+Remove a configuration management service to this target.
+.TP
+.BI \--param " key=value"
+Set permanent parameter
+.I key
+to value
+.IR value .
+This option can be repeated as desired. All previously stored instances of
+.IR key
+are removed, and new instances specified in the command line are added.
+Typical options might include:
+.RS
+.I \--param sys.timeout=40
+.RS
+System obd timeout
+.RE
+.I \--param lov.stripesize=2M
+.RS
+Default stripe size
+.RE
+.I \--param lov.stripecount=2
+.RS
+Default stripe count
+.RE
+.I \--param failover.mode=failout
+.RS
+Return errors instead of waiting for recovery
+.RE
+.RE
.TP
.BI \--force-nohostid
Ignore unset hostid for ZFS import protection. To set hostid either set
.br
Correct order of operations is:
.br
-* Unmount all clients of this filesystem
+* Unmount all clients of this filesystem.
.br
-* Unmount MDT and all OSTs of this filesystem
+* Unmount MDT and all OSTs of this filesystem.
.br
-* Run \fBtunefs.lustre --writeconf <device>\fR on every server
+* Run \fBtunefs.lustre --writeconf <device>\fR on every server.
.br
-* Mount MDT and OSTs
+* Mount MDT and OSTs.
.br
* Mount clients
.TP
.SH EXAMPLES
.TP
-.B tunefs.lustre --erase-param --mgsnode=<new_nid> --writeconf /dev/sda
+.B tunefs.lustre --erase-params --mgsnode=<new_nid> --writeconf /dev/sda
Change the MGS NID address. (This should be done on every target disk,
since they should all be contacting the same MGS.)
.TP
-.B tunefs.lustre --param="failover.node=192.168.0.13@tcp0" /dev/sda
-Add a failover NID location for this target
+.B tunefs.lustre --param "failover.node=192.168.0.13@tcp0" /dev/sda
++Remove all previous failover NID locations for this target, and add a new
++failover NID location for this target.
++.TP
++.B tunefs.lustre --erase-param failover.node /dev/sda
++Remove all failover NID locations for this target.
.TP
.B tunefs.lustre --mgs --mdt --fsname=testfs /dev/sda
Upgrade an old 1.4.X Lustre MDT to 1.6. The new filesystem name is "testfs".
}
run_test 88 "check the default mount options can be overridden"
+test_89() { # LU-7131
+ [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.9.54) ]] ||
+ { skip "Need MDT version at least 2.9.54" && return 0; }
+
+ local key=failover.node
+ local val1=192.0.2.254@tcp0 # Reserved IPs, see RFC 5735
+ local val2=192.0.2.255@tcp0
+ local mdsdev=$(mdsdevname 1)
+ local params
+
+ stopall
+
+ [ $(facet_fstype mds1) == zfs ] && import_zpool mds1
+ # Check that parameters are added correctly
+ echo "tunefs --param $key=$val1"
+ do_facet mds "$TUNEFS --param $key=$val1 $mdsdev >/dev/null" ||
+ error "tunefs --param $key=$val1 failed"
+ params=$(do_facet mds $TUNEFS --dryrun $mdsdev) ||
+ error "tunefs --dryrun failed"
+ params=${params##*Parameters:}
+ params=${params%%exiting*}
+ [ $(echo $params | tr ' ' '\n' | grep -c $key=$val1) = "1" ] ||
+ error "on-disk parameter not added correctly via tunefs"
+
+ # Check that parameters replace existing instances when added
+ echo "tunefs --param $key=$val2"
+ do_facet mds "$TUNEFS --param $key=$val2 $mdsdev >/dev/null" ||
+ error "tunefs --param $key=$val2 failed"
+ params=$(do_facet mds $TUNEFS --dryrun $mdsdev) ||
+ error "tunefs --dryrun failed"
+ params=${params##*Parameters:}
+ params=${params%%exiting*}
+ [ $(echo $params | tr ' ' '\n' | grep -c $key=) = "1" ] ||
+ error "on-disk parameter not replaced via tunefs"
+ [ $(echo $params | tr ' ' '\n' | grep -c $key=$val2) = "1" ] ||
+ error "on-disk parameter not replaced correctly via tunefs"
+
+ # Check that a parameter is erased properly
+ echo "tunefs --erase-param $key"
+ do_facet mds "$TUNEFS --erase-param $key $mdsdev >/dev/null" ||
+ error "tunefs --erase-param $key failed"
+ params=$(do_facet mds $TUNEFS --dryrun $mdsdev) ||
+ error "tunefs --dryrun failed"
+ params=${params##*Parameters:}
+ params=${params%%exiting*}
+ [ $(echo $params | tr ' ' '\n' | grep -c $key=) = "0" ] ||
+ error "on-disk parameter not erased correctly via tunefs"
+
+ # Check that all the parameters are erased
+ echo "tunefs --erase-params"
+ do_facet mds "$TUNEFS --erase-params $mdsdev >/dev/null" ||
+ error "tunefs --erase-params failed"
+ params=$(do_facet mds $TUNEFS --dryrun $mdsdev) ||
+ error "tunefs --dryrun failed"
+ params=${params##*Parameters:}
+ params=${params%%exiting*}
+ [ -z $params ] ||
+ error "all on-disk parameters not erased correctly via tunefs"
+
+ # Check the order of options --erase-params and --param
+ echo "tunefs --param $key=$val1 --erase-params"
+ do_facet mds \
+ "$TUNEFS --param $key=$val1 --erase-params $mdsdev >/dev/null"||
+ error "tunefs --param $key=$val1 --erase-params failed"
+ params=$(do_facet mds $TUNEFS --dryrun $mdsdev) ||
+ error "tunefs --dryrun failed"
+ params=${params##*Parameters:}
+ params=${params%%exiting*}
+ [ $(echo $params | tr ' ' '\n') == "$key=$val1" ] ||
+ error "on-disk param not added correctly with --erase-params"
+
+ reformat
+}
+run_test 89 "check tunefs --param and --erase-param{s} options"
+
# $1 test directory
# $2 (optional) value of max_mod_rpcs_in_flight to set
check_max_mod_rpcs_in_flight() {
"\t\t--replace: replace an old target with the same index\n"
"\t\t--stripe-count-hint=#N: for optimizing MDT inode size\n"
#else
+ "\t\t--erase-param <key>: erase all instances of a parameter\n"
"\t\t--erase-params: erase all old parameter settings\n"
"\t\t--writeconf: erase all config logs for this fs.\n"
"\t\t--quota: enable space accounting on old 2.x device.\n"
/* ==================== Lustre config functions =============*/
-void print_ldd(char *str, struct lustre_disk_data *ldd)
+void print_ldd(char *str, struct mkfs_opts *mop)
{
+ struct lustre_disk_data *ldd = &mop->mo_ldd;
+
printf("\n %s:\n", str);
printf("Target: %s\n", ldd->ldd_svname);
if (ldd->ldd_svindex == INDEX_UNASSIGNED)
ldd->ldd_flags & LDD_F_NO_PRIMNODE? "no_primnode ":"",
ldd->ldd_flags & LDD_F_UPGRADE14 ? "upgrade1.4 ":"");
printf("Persistent mount opts: %s\n", ldd->ldd_mount_opts);
- printf("Parameters:%s\n", ldd->ldd_params);
+ osd_print_ldd_params(mop);
if (ldd->ldd_userdata[0])
printf("Comment: %s\n", ldd->ldd_userdata);
printf("\n");
usage(stderr);
}
+#ifdef TUNEFS
+/**
+ * Removes all existing instances of the parameter passed in \a param,
+ * which are in the form of "key=<value>", from the buffer at \a buf.
+ *
+ * The parameter can be either in the form of "key" when passed by option
+ * "--erase-param", or in the form of "key=<value>" when passed by option
+ * "--param".
+ *
+ * \param buf the buffer holding on-disk server parameters.
+ * \param param the parameter whose instances are to be removed from \a buf.
+ * \param withval true means the parameter is in the form of "key=<value>"
+ * false means the parameter is in the form of "key"
+ *
+ * \retval 0 success, parameter was erased,
+ * \retval 1 success, parameter was not found, don't need to do erase_ldd,
+ * \retval EINVAL failure, invalid input parameter.
+ */
+static int erase_param(const char *const buf, const char *const param,
+ bool withval)
+{
+ char search[PARAM_MAX + 1] = "";
+ char *buffer = (char *)buf;
+ bool found = false;
+
+ if (strlen(param) > PARAM_MAX) {
+ fprintf(stderr, "%s: param to erase is too long-\n%s\n",
+ progname, param);
+ return EINVAL;
+ }
+
+ /* add_param() writes a space as the first character in ldd_params */
+ search[0] = ' ';
+
+ /* "key" or "key=<value>" */
+ if (withval) {
+ char *keyend;
+
+ keyend = strchr(param, '=');
+ if (!keyend)
+ return EINVAL;
+ strncpy(&search[1], param, keyend - param + 1);
+ } else {
+ strncpy(&search[1], param, strlen(param));
+ strncat(search, "=", 1);
+ }
+
+ while (1) {
+ char *space;
+
+ buffer = strstr(buffer, search);
+ if (!buffer)
+ return found == true ? 0 : 1;
+ found = true;
+ space = strchr(buffer + 1, ' ');
+ if (space) {
+ memmove(buffer, space, strlen(space) + 1);
+ } else {
+ *buffer = '\0';
+ return 0;
+ }
+ }
+}
+#endif
+
/* from mount_lustre */
/* Get rid of symbolic hostnames for tcp, since kernel can't do lookups */
#define MAXNIDSTR 1024
{ "reformat", no_argument, NULL, 'r' },
{ "replace", no_argument, NULL, 'R' },
#else
+ { "erase-param", required_argument, NULL, 'E' },
{ "erase-params", no_argument, NULL, 'e' },
{ "quota", no_argument, NULL, 'Q' },
{ "rename", optional_argument, NULL, 'R' },
#ifndef TUNEFS
"b:c:d:k:MOrR";
#else
- "eQR::w";
+ "E:eQR::w";
#endif
struct lustre_disk_data *ldd = &mop->mo_ldd;
char new_fsname[16] = { 0 };
int replace = 0;
bool index_option = false;
+#ifdef TUNEFS
+ /* For the right semantics, if '-e'/'--erase-params' is specified,
+ * it must be picked out and all old parameters should be erased
+ * before any other changes are done. */
+ while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) !=
+ EOF) {
+ switch (opt) {
+ case 'e':
+ ldd->ldd_params[0] = '\0';
+ mop->mo_flags |= MO_ERASE_ALL;
+ ldd->ldd_flags |= LDD_F_UPDATE;
+ break;
+ default:
+ break;
+ }
+ if (mop->mo_flags & MO_ERASE_ALL)
+ break;
+ }
+ optind = 0;
+#endif
while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) !=
EOF) {
switch (opt) {
*mountopts = optarg;
break;
case 'p':
+#ifdef TUNEFS
+ /* Removes all existing instances of the parameter
+ * before adding new values.
+ */
+ rc = erase_param(ldd->ldd_params, optarg, true);
+ if (rc > 1)
+ return rc;
+#endif
rc = add_param(ldd->ldd_params, NULL, optarg);
if (rc != 0)
return rc;
-
/* Must update the mgs logs */
ldd->ldd_flags |= LDD_F_UPDATE;
break;
case 'R':
replace = 1;
break;
-#else /* !TUNEFS */
- case 'e':
- ldd->ldd_params[0] = '\0';
+#else /* TUNEFS */
+ case 'E':
+ rc = erase_param(ldd->ldd_params, optarg, false);
+ /* (rc == 1) means not found, so don't need to
+ * call osd_erase_ldd(). */
+ if (rc > 1)
+ return rc;
+ if (!rc) {
+ rc = osd_erase_ldd(mop, optarg);
+ if (rc)
+ return rc;
+ }
/* Must update the mgs logs */
ldd->ldd_flags |= LDD_F_UPDATE;
break;
+ case 'e':
+ /* Already done in the beginning */
+ break;
case 'Q':
mop->mo_flags |= MO_QUOTA;
break;
mop.mo_mgs_failnodes++;
if (verbose > 0)
- print_ldd("Read previous values", ldd);
+ print_ldd("Read previous values", &mop);
#endif /* TUNEFS */
ret = parse_opts(argc, argv, &mop, &mountopts, old_fsname);
ldd->ldd_flags &= ~LDD_F_NEED_INDEX;
ldd->ldd_svindex = 0;
}
+#ifndef TUNEFS
if (!IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) {
+#else
+ /* Don't check --mgs or --mgsnode if print_only is set or
+ * --erase-params is set. */
+ if (!IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0) && !print_only &&
+ !(mop.mo_flags & MO_ERASE_ALL)) {
+#endif
fatal();
if (IS_MDT(ldd))
fprintf(stderr, "Must specify --mgs or --mgsnode\n");
}
if (verbose >= 0)
- print_ldd("Permanent disk data", ldd);
+ print_ldd("Permanent disk data", &mop);
if (print_only) {
printf("exiting before disk write.\n");
fprintf(stderr, "failed to write local files\n");
goto out;
}
-
out:
osd_fini();
ret2 = loop_cleanup(&mop);
DLSYM(name, ops, fini);
DLSYM(name, ops, read_ldd);
DLSYM(name, ops, write_ldd);
+ DLSYM(name, ops, erase_ldd);
+ DLSYM(name, ops, print_ldd_params);
DLSYM(name, ops, is_lustre);
DLSYM(name, ops, make_lustre);
DLSYM(name, ops, prepare_lustre);
return ret;
}
+/* Erase param from the server config files */
+int osd_erase_ldd(struct mkfs_opts *mop, char *param)
+{
+ struct lustre_disk_data *ldd = &mop->mo_ldd;
+ int ret;
+
+ if (backfs_mount_type_okay(ldd->ldd_mount_type))
+ ret = backfs_ops[ldd->ldd_mount_type]->erase_ldd(mop, param);
+ else
+ ret = EINVAL;
+
+ return ret;
+}
+
+/* Print ldd_params */
+void osd_print_ldd_params(struct mkfs_opts *mop)
+{
+ struct lustre_disk_data *ldd = &mop->mo_ldd;
+
+ if (backfs_mount_type_okay(ldd->ldd_mount_type))
+ backfs_ops[ldd->ldd_mount_type]->print_ldd_params(mop);
+}
+
/* Was this device formatted for Lustre */
int osd_is_lustre(char *dev, unsigned *mount_type)
{
#define MO_QUOTA 0x10
#define MO_NOHOSTID_CHECK 0x20
#define MO_RENAME 0x40
+#define MO_ERASE_ALL 0x80
#define MAX_LOOP_DEVICES 16
#define INDEX_UNASSIGNED 0xFFFF
+/* Maximum length of on-disk parameters in the form key=<value> */
+#define PARAM_MAX 4096
+
/* used to describe the options to format the lustre disk, not persistent */
struct mkfs_opts {
struct lustre_disk_data mo_ldd; /* to be written in MOUNT_DATA_FILE */
/* generic target support */
int osd_write_ldd(struct mkfs_opts *mop);
int osd_read_ldd(char *dev, struct lustre_disk_data *ldd);
+int osd_erase_ldd(struct mkfs_opts *mop, char *param);
+void osd_print_ldd_params(struct mkfs_opts *mop);
int osd_is_lustre(char *dev, unsigned *mount_type);
int osd_make_lustre(struct mkfs_opts *mop);
int osd_prepare_lustre(struct mkfs_opts *mop,
void (*fini)(void);
int (*read_ldd)(char *ds, struct lustre_disk_data *ldd);
int (*write_ldd)(struct mkfs_opts *mop);
+ int (*erase_ldd)(struct mkfs_opts *mop, char *param);
+ void (*print_ldd_params)(struct mkfs_opts *mop);
int (*is_lustre)(char *dev, enum ldd_mount_type *mount_type);
int (*make_lustre)(struct mkfs_opts *mop);
int (*prepare_lustre)(struct mkfs_opts *mop,
return ret;
}
+int ldiskfs_erase_ldd(struct mkfs_opts *mop, char *param)
+{
+ return 0;
+}
+
+void ldiskfs_print_ldd_params(struct mkfs_opts *mop)
+{
+ printf("Parameters:%s\n", mop->mo_ldd.ldd_params);
+}
/* Display the need for the latest e2fsprogs to be installed. make_backfs
* indicates if the caller is make_lustre_backfs() or not. */
}
/*
+ * Remove a property from zfs property dataset
+ */
+static int zfs_remove_prop(zfs_handle_t *zhp, nvlist_t *nvl, char *propname)
+{
+ nvlist_remove_all(nvl, propname);
+ /* XXX: please replace zfs_prop_inherit() if there is a better function
+ * to call zfs_ioctl() to update data on-disk.
+ */
+ return zfs_prop_inherit(zhp, propname, false);
+}
+
+static int zfs_erase_prop(zfs_handle_t *zhp, char *param)
+{
+ nvlist_t *nvl;
+ char propname[ZFS_MAXPROPLEN];
+ int len = strlen(param) + strlen(LDD_PREFIX);
+
+ if (len > ZFS_MAXPROPLEN) {
+ fprintf(stderr, "%s: zfs prop to erase is too long-\n%s\n",
+ progname, param);
+ return EINVAL;
+ }
+
+ nvl = zfs_get_user_props(zhp);
+ if (!nvl)
+ return ENOENT;
+
+ snprintf(propname, len + 1, "%s%s", LDD_PREFIX, param);
+ return zfs_remove_prop(zhp, nvl, propname);
+}
+
+static int zfs_erase_allprops(zfs_handle_t *zhp)
+{
+ nvlist_t *nvl;
+ nvpair_t *curr = NULL;
+
+ nvl = zfs_get_user_props(zhp);
+ if (!nvl)
+ return ENOENT;
+
+ curr = nvlist_next_nvpair(nvl, curr);
+ while (curr) {
+ nvpair_t *next = nvlist_next_nvpair(nvl, curr);
+
+ zfs_remove_prop(zhp, nvl, nvpair_name(curr));
+ curr = next;
+ }
+
+ return 0;
+}
+
+/*
* Map '<key>=<value> ...' pairs in the passed string to dataset properties
- * of the form 'lustre:<key>=<value>'. Malformed <key>=<value> pairs will
- * be skipped.
+ * of the form 'lustre:<key>=<value>'. "<key>=" means to remove this key
+ * from the dataset.
*/
static int zfs_set_prop_params(zfs_handle_t *zhp, char *params)
{
char *params_dup, *token, *key, *value;
char *save_token = NULL;
- char prop_name[ZFS_MAXPROPLEN];
+ char propname[ZFS_MAXPROPLEN];
int ret = 0;
params_dup = strdup(params);
continue;
value = strtok(NULL, "=");
- if (value == NULL)
- continue;
-
- sprintf(prop_name, "%s%s", LDD_PREFIX, key);
- vprint(" %s=%s\n", prop_name, value);
+ if (!value) {
+ /* remove this prop when its value is null */
+ ret = zfs_erase_prop(zhp, key);
+ if (ret)
+ break;
+ } else {
+ snprintf(propname, strlen(LDD_PREFIX) + strlen(key) + 1,
+ "%s%s", LDD_PREFIX, key);
+ vprint(" %s=%s\n", propname, value);
- ret = zfs_prop_set(zhp, prop_name, value);
- if (ret)
- break;
+ ret = zfs_prop_set(zhp, propname, value);
+ if (ret)
+ break;
+ }
token = strtok_r(NULL, " ", &save_token);
}
ret = zfs_check_hostid(mop);
if (ret != 0)
- goto out;
+ goto out_close;
vprint("Writing %s properties\n", ds);
+ if (mop->mo_flags & MO_ERASE_ALL)
+ ret = zfs_erase_allprops(zhp);
+ ret = zfs_set_prop_params(zhp, ldd->ldd_params);
+
for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) {
bridge = &special_ldd_prop_params[i];
ret = bridge->zlpb_set_prop_fn(zhp, bridge->zlpb_prop_name,
goto out_close;
}
- ret = zfs_set_prop_params(zhp, ldd->ldd_params);
-
out_close:
zfs_close(zhp);
out:
return ret;
}
+/* Mark a property to be removed by the form of "key=" */
+int zfs_erase_ldd(struct mkfs_opts *mop, char *param)
+{
+ char key[ZFS_MAXPROPLEN] = "";
+
+ if (strlen(LDD_PREFIX) + strlen(param) > ZFS_MAXPROPLEN) {
+ fprintf(stderr, "%s: zfs prop to erase is too long-\n%s\n",
+ progname, param);
+ return EINVAL;
+ }
+ snprintf(key, strlen(param) + 2, "%s=", param);
+ return add_param(mop->mo_ldd.ldd_params, key, "");
+}
+
static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, void *val)
{
nvlist_t *propval;
return 0;
}
-static int zfs_get_prop_params(zfs_handle_t *zhp, char *param, int len)
+static int zfs_get_prop_params(zfs_handle_t *zhp, char *param)
{
nvlist_t *props;
nvpair_t *nvp;
- char key[ZFS_MAXPROPLEN];
- char *value;
+ char key[ZFS_MAXPROPLEN] = "";
+ char value[PARAM_MAX] = "";
int ret = 0;
props = zfs_get_user_props(zhp);
if (props == NULL)
return ENOENT;
- value = malloc(len);
- if (value == NULL)
- return ENOMEM;
-
nvp = NULL;
while (nvp = nvlist_next_nvpair(props, nvp), nvp) {
ret = zfs_get_prop_str(zhp, nvpair_name(nvp), value);
continue;
sprintf(key, "%s=", nvpair_name(nvp) + strlen(LDD_PREFIX));
-
ret = add_param(param, key, value);
if (ret)
break;
}
- free(value);
-
return ret;
}
goto out_close;
}
- ret = zfs_get_prop_params(zhp, ldd->ldd_params, 4096);
+ ret = zfs_get_prop_params(zhp, ldd->ldd_params);
if (ret && (ret != ENOENT))
goto out_close;
return ret;
}
+/* Print ldd params */
+void zfs_print_ldd_params(struct mkfs_opts *mop)
+{
+ char *from = mop->mo_ldd.ldd_params;
+ char *to;
+ int len;
+
+ vprint("Parameters:");
+ while (from) {
+ /* skip those keys to be removed in the form of "key=" */
+ to = strstr(from, "= ");
+ if (!to)
+ /* "key=" may be in the end */
+ if (*(from + strlen(from) - 1) == '=')
+ to = from + strlen(from) - 1;
+
+ /* find " " inward */
+ len = strlen(from);
+ if (to) {
+ len = strlen(from) - strlen(to);
+ while ((*(from + len) != ' ') && len)
+ len--;
+ }
+ if (len)
+ /* no space in the end */
+ vprint("%*.*s", len, len, from);
+
+ /* If there is no "key=" or "key=" is in the end, stop. */
+ if (!to || strlen(to) == 1)
+ break;
+
+ /* skip "=" */
+ from = to + 1;
+ }
+}
+
int zfs_is_lustre(char *ds, unsigned *mount_type)
{
struct lustre_disk_data tmp_ldd;