4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License version 2 for more details. A copy is
14 * included in the COPYING file that accompanied this code.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Copyright (c) 2012, 2017, Intel Corporation.
24 * Use is subject to license terms.
27 * Author: Brian Behlendorf <behlendorf1@llnl.gov>
29 #ifndef HAVE_ZFS_MULTIHOST
31 #define list_move_tail(a, b) spl_list_move_tail(a, b)
34 #include "mount_utils.h"
39 #include <sys/systeminfo.h>
41 /* Persistent mount data is stored in these user attributes */
42 #define LDD_PREFIX "lustre:"
43 #define LDD_VERSION_PROP LDD_PREFIX "version"
44 #define LDD_FLAGS_PROP LDD_PREFIX "flags"
45 #define LDD_INDEX_PROP LDD_PREFIX "index"
46 #define LDD_FSNAME_PROP LDD_PREFIX "fsname"
47 #define LDD_SVNAME_PROP LDD_PREFIX "svname"
48 #define LDD_UUID_PROP LDD_PREFIX "uuid"
49 #define LDD_USERDATA_PROP LDD_PREFIX "userdata"
50 #define LDD_MOUNTOPTS_PROP LDD_PREFIX "mountopts"
52 /* This structure is used to help bridge the gap between the ZFS
53 * properties Lustre uses and their corresponding internal LDD fields.
54 * It is meant to be used internally by the mount utility only. */
55 struct zfs_ldd_prop_bridge {
56 /* Contains the publicly visible name for the property
57 * (i.e. what is shown when running "zfs get") */
59 /* Contains the offset into the lustre_disk_data structure where
60 * the value of this property is or will be stored. (i.e. the
61 * property is read from and written to this offset within ldd) */
63 /* Function pointer responsible for reading in the @prop
64 * property from @zhp and storing it in @ldd_field */
65 int (*zlpb_get_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field);
66 /* Function pointer responsible for writing the value of @ldd_field
67 * into the @prop dataset property in @zhp */
68 int (*zlpb_set_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field);
71 /* Forward declarations needed to initialize the ldd prop bridge list */
72 static int zfs_get_prop_int(zfs_handle_t *, char *, void *);
73 static int zfs_set_prop_int(zfs_handle_t *, char *, void *);
74 static int zfs_get_prop_str(zfs_handle_t *, char *, void *);
75 static int zfs_set_prop_str(zfs_handle_t *, char *, void *);
77 /* Helper for initializing the entries in the special_ldd_prop_params list.
78 * - @name: stored directly in the zlpb_prop_name field
79 * (e.g. lustre:fsname, lustre:version, etc.)
80 * - @field: the field in the lustre_disk_data which directly maps to
81 * the @name property. (e.g. ldd_fsname, ldd_config_ver, etc.)
82 * - @type: The type of @field. Only "int" and "str" are supported.
84 #define ZLB_INIT(name, field, type) \
86 .zlpb_prop_name = name, \
87 .zlpb_ldd_offset = offsetof(struct lustre_disk_data, field), \
88 .zlpb_get_prop_fn = zfs_get_prop_ ## type, \
89 .zlpb_set_prop_fn = zfs_set_prop_ ## type \
92 /* These ldd properties are special because they all have their own
93 * individual fields in the lustre_disk_data structure, as opposed to
94 * being globbed into the ldd_params field. As such, these need special
95 * handling when reading/writing the ldd structure to/from persistent
97 struct zfs_ldd_prop_bridge special_ldd_prop_params[] = {
98 ZLB_INIT(LDD_VERSION_PROP, ldd_config_ver, int),
99 ZLB_INIT(LDD_FLAGS_PROP, ldd_flags, int),
100 ZLB_INIT(LDD_INDEX_PROP, ldd_svindex, int),
101 ZLB_INIT(LDD_FSNAME_PROP, ldd_fsname, str),
102 ZLB_INIT(LDD_SVNAME_PROP, ldd_svname, str),
103 ZLB_INIT(LDD_UUID_PROP, ldd_uuid, str),
104 ZLB_INIT(LDD_USERDATA_PROP, ldd_userdata, str),
105 ZLB_INIT(LDD_MOUNTOPTS_PROP, ldd_mount_opts, str),
109 /* indicate if the ZFS OSD has been successfully setup */
110 static int osd_zfs_setup = 0;
112 static libzfs_handle_t *g_zfs;
116 static int zfs_set_prop_int(zfs_handle_t *zhp, char *prop, void *val)
121 (void) snprintf(str, sizeof (str), "%i", *(int *)val);
122 vprint(" %s=%s\n", prop, str);
123 ret = zfs_prop_set(zhp, prop, str);
129 * Write the zfs property string, note that properties with a NULL or
130 * zero-length value will not be written and 0 returned.
132 static int zfs_set_prop_str(zfs_handle_t *zhp, char *prop, void *val)
136 if (val && strlen(val) > 0) {
137 vprint(" %s=%s\n", prop, (char *)val);
138 ret = zfs_prop_set(zhp, prop, (char *)val);
145 * Remove a property from zfs property dataset
147 static int zfs_remove_prop(zfs_handle_t *zhp, nvlist_t *nvl, char *propname)
149 nvlist_remove_all(nvl, propname);
150 /* XXX: please replace zfs_prop_inherit() if there is a better function
151 * to call zfs_ioctl() to update data on-disk.
153 return zfs_prop_inherit(zhp, propname, false);
156 static int zfs_erase_prop(zfs_handle_t *zhp, char *param)
159 char propname[ZFS_MAXPROPLEN];
160 int len = strlen(param) + strlen(LDD_PREFIX);
162 if (len > ZFS_MAXPROPLEN) {
163 fprintf(stderr, "%s: zfs prop to erase is too long-\n%s\n",
168 nvl = zfs_get_user_props(zhp);
172 snprintf(propname, len + 1, "%s%s", LDD_PREFIX, param);
173 return zfs_remove_prop(zhp, nvl, propname);
176 static int zfs_is_special_ldd_prop_param(char *name)
180 for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++)
181 if (!strcmp(name, special_ldd_prop_params[i].zlpb_prop_name))
187 static int zfs_erase_allprops(zfs_handle_t *zhp)
191 size_t str_size = 1024 * 1024;
195 strs = malloc(str_size);
200 props = zfs_get_user_props(zhp);
206 while (nvp = nvlist_next_nvpair(props, nvp), nvp) {
207 if (strncmp(nvpair_name(nvp), LDD_PREFIX, strlen(LDD_PREFIX)))
210 if (zfs_is_special_ldd_prop_param(nvpair_name(nvp)))
213 rc = snprintf(cur, str_size - (cur - strs), "%s",
215 if (rc != strlen(nvpair_name(nvp))) {
216 fprintf(stderr, "%s: zfs has too many properties to erase, please repeat\n",
221 cur += strlen(cur) + 1;
224 while ( cur < (strs + str_size) && strlen(cur) > 0) {
225 zfs_prop_inherit(zhp, cur, false);
226 cur += strlen(cur) + 1;
233 * ZFS on linux 0.7.0-rc5 commit 379ca9cf2beba802f096273e89e30914a2d6bafc
234 * Multi-modifier protection (MMP)
236 * Introduced spa_get_hostid() along with a few constants like
237 * ZPOOL_CONFIG_MMP_HOSTID that can be checked to imply availablity of
238 * spa_get_hostid. Supply a fallback when spa_get_hostid is not
241 * This can be removed when zfs 0.6.x support is dropped.
243 #if !defined(ZPOOL_CONFIG_MMP_HOSTID) && !defined(HAVE_ZFS_MULTIHOST)
244 unsigned long _hostid_from_proc(void)
247 unsigned long hostid;
250 f = fopen("/proc/sys/kernel/spl/hostid", "r");
254 rc = fscanf(f, "%lx", &hostid);
262 unsigned long _hostid_from_module_param(void)
265 unsigned long hostid;
268 f = fopen("/sys/module/spl/parameters/spl_hostid", "r");
272 rc = fscanf(f, "%li", &hostid);
280 unsigned long _from_module_param_indirect(void)
283 unsigned long hostid = 0;
286 char *spl_hostid_path = NULL;
288 /* read the module parameter for HW_HOSTID_PATH */
289 f = fopen("/sys/module/spl/parameters/spl_hostid_path", "r");
292 fprintf(stderr, "Failed to open spl_hostid_path param: %s\n",
297 rc = fscanf(f, "%ms%*[\n]", &spl_hostid_path);
299 if (rc == 0 || !spl_hostid_path)
302 /* read the hostid from the file */
303 f = fopen(spl_hostid_path, "r");
306 fprintf(stderr, "Failed to open %s param: %s\n",
307 spl_hostid_path, strerror(errno));
311 /* hostid is the first 4 bytes in native endian order */
312 rc = fread(&hwid, sizeof(uint32_t), 1, f);
315 hostid = (unsigned long)hwid;
319 free(spl_hostid_path);
324 unsigned long spa_get_hostid(void)
326 unsigned long hostid;
328 hostid = _hostid_from_proc();
332 /* if /proc isn't available, try /sys */
333 hostid = _hostid_from_module_param();
337 return _from_module_param_indirect();
342 * Map '<key>=<value> ...' pairs in the passed string to dataset properties
343 * of the form 'lustre:<key>=<value>'. "<key>=" means to remove this key
346 static int zfs_set_prop_params(zfs_handle_t *zhp, char *params)
348 char *params_dup, *token, *key, *value;
349 char *save_token = NULL;
350 char propname[ZFS_MAXPROPLEN];
353 params_dup = strdup(params);
354 if (params_dup == NULL)
357 token = strtok_r(params_dup, " ", &save_token);
359 key = strtok(token, "=");
363 value = strtok(NULL, "=");
365 /* remove this prop when its value is null */
366 ret = zfs_erase_prop(zhp, key);
370 snprintf(propname, strlen(LDD_PREFIX) + strlen(key) + 1,
371 "%s%s", LDD_PREFIX, key);
372 vprint(" %s=%s\n", propname, value);
374 ret = zfs_prop_set(zhp, propname, value);
379 token = strtok_r(NULL, " ", &save_token);
387 static int zfs_check_hostid(struct mkfs_opts *mop)
389 unsigned long hostid;
391 if (strstr(mop->mo_ldd.ldd_params, PARAM_FAILNODE) == NULL)
394 #ifdef HAVE_ZFS_MULTIHOST
395 hostid = get_system_hostid();
397 hostid = spa_get_hostid();
400 if (mop->mo_flags & MO_NOHOSTID_CHECK) {
401 fprintf(stderr, "WARNING: spl_hostid not set. ZFS has "
402 "no zpool import protection\n");
405 fprintf(stderr, "spl_hostid not set. See %s(8)",
414 static int osd_check_zfs_setup(void)
416 if (osd_zfs_setup == 0) {
419 fprintf(stderr, "Failed to initialize ZFS library. Are the ZFS "
420 "packages and modules correctly installed?\n");
422 return osd_zfs_setup == 1;
425 /* Write the server config as properties associated with the dataset */
426 int zfs_write_ldd(struct mkfs_opts *mop)
428 struct lustre_disk_data *ldd = &mop->mo_ldd;
429 char *ds = mop->mo_device;
431 struct zfs_ldd_prop_bridge *bridge;
434 if (osd_check_zfs_setup() == 0)
437 zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM);
439 fprintf(stderr, "Failed to open zfs dataset %s\n", ds);
443 ret = zfs_check_hostid(mop);
447 vprint("Writing %s properties\n", ds);
449 if (mop->mo_flags & MO_ERASE_ALL)
450 ret = zfs_erase_allprops(zhp);
451 ret = zfs_set_prop_params(zhp, ldd->ldd_params);
453 for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) {
454 bridge = &special_ldd_prop_params[i];
455 ret = bridge->zlpb_set_prop_fn(zhp, bridge->zlpb_prop_name,
456 (void *)ldd + bridge->zlpb_ldd_offset);
467 /* Mark a property to be removed by the form of "key=" */
468 int zfs_erase_ldd(struct mkfs_opts *mop, char *param)
470 char key[ZFS_MAXPROPLEN] = "";
472 if (strlen(LDD_PREFIX) + strlen(param) > ZFS_MAXPROPLEN) {
473 fprintf(stderr, "%s: zfs prop to erase is too long-\n%s\n",
477 snprintf(key, strlen(param) + 2, "%s=", param);
478 return add_param(mop->mo_ldd.ldd_params, key, "");
481 static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, void *val)
487 ret = nvlist_lookup_nvlist(zfs_get_user_props(zhp), prop, &propval);
491 ret = nvlist_lookup_string(propval, ZPROP_VALUE, &propstr);
496 *(__u32 *)val = strtoul(propstr, NULL, 10);
503 static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, void *val)
509 ret = nvlist_lookup_nvlist(zfs_get_user_props(zhp), prop, &propval);
513 ret = nvlist_lookup_string(propval, ZPROP_VALUE, &propstr);
517 (void) strcpy(val, propstr);
522 static int zfs_get_prop_params(zfs_handle_t *zhp, char *param)
526 char key[ZFS_MAXPROPLEN] = "";
527 char value[PARAM_MAX] = "";
530 props = zfs_get_user_props(zhp);
535 while (nvp = nvlist_next_nvpair(props, nvp), nvp) {
536 ret = zfs_get_prop_str(zhp, nvpair_name(nvp), value);
540 if (strncmp(nvpair_name(nvp), LDD_PREFIX, strlen(LDD_PREFIX)))
543 if (zfs_is_special_ldd_prop_param(nvpair_name(nvp)))
546 sprintf(key, "%s=", nvpair_name(nvp) + strlen(LDD_PREFIX));
547 ret = add_param(param, key, value);
556 * Read the server config as properties associated with the dataset.
557 * Missing entries as not treated error and are simply skipped.
559 int zfs_read_ldd(char *ds, struct lustre_disk_data *ldd)
562 struct zfs_ldd_prop_bridge *bridge;
565 if (osd_check_zfs_setup() == 0)
568 zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM);
570 zhp = zfs_open(g_zfs, ds, ZFS_TYPE_SNAPSHOT);
575 for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) {
576 bridge = &special_ldd_prop_params[i];
577 ret = bridge->zlpb_get_prop_fn(zhp, bridge->zlpb_prop_name,
578 (void *)ldd + bridge->zlpb_ldd_offset);
579 if (ret && (ret != ENOENT))
583 ret = zfs_get_prop_params(zhp, ldd->ldd_params);
584 if (ret && (ret != ENOENT))
587 ldd->ldd_mount_type = LDD_MT_ZFS;
590 #ifdef HAVE_ZFS_MULTIHOST
591 if (strstr(ldd->ldd_params, PARAM_FAILNODE) != NULL) {
592 zpool_handle_t *pool = zfs_get_pool_handle(zhp);
593 uint64_t mh = zpool_get_prop_int(pool, ZPOOL_PROP_MULTIHOST,
596 fprintf(stderr, "%s: %s is configured for failover "
597 "but zpool does not have multihost enabled\n",
609 /* Print ldd params */
610 void zfs_print_ldd_params(struct mkfs_opts *mop)
612 char *from = mop->mo_ldd.ldd_params;
616 vprint("Parameters:");
618 /* skip those keys to be removed in the form of "key=" */
619 to = strstr(from, "= ");
621 /* "key=" may be in the end */
622 if (*(from + strlen(from) - 1) == '=')
623 to = from + strlen(from) - 1;
625 /* find " " inward */
628 len = strlen(from) - strlen(to);
629 while ((*(from + len) != ' ') && len)
633 /* no space in the end */
634 vprint("%*.*s", len, len, from);
636 /* If there is no "key=" or "key=" is in the end, stop. */
637 if (!to || strlen(to) == 1)
645 int zfs_is_lustre(char *ds, unsigned *mount_type)
647 struct lustre_disk_data tmp_ldd;
650 if (osd_zfs_setup == 0)
653 ret = zfs_read_ldd(ds, &tmp_ldd);
654 if ((ret == 0) && (tmp_ldd.ldd_config_ver > 0) &&
655 (strlen(tmp_ldd.ldd_svname) > 0)) {
656 *mount_type = tmp_ldd.ldd_mount_type;
663 static char *zfs_mkfs_opts(struct mkfs_opts *mop, char *str, int len)
667 if (strlen(mop->mo_mkfsopts) != 0)
668 snprintf(str, len, " -o %s", mop->mo_mkfsopts);
669 if (mop->mo_device_kb)
670 snprintf(str, len, " -o quota=%llu",
671 (unsigned long long)mop->mo_device_kb * 1024);
676 static int zfs_create_vdev(struct mkfs_opts *mop, char *vdev)
680 /* Silently ignore reserved vdev names */
681 if ((strncmp(vdev, "disk", 4) == 0) ||
682 (strncmp(vdev, "file", 4) == 0) ||
683 (strncmp(vdev, "mirror", 6) == 0) ||
684 (strncmp(vdev, "raidz", 5) == 0) ||
685 (strncmp(vdev, "spare", 5) == 0) ||
686 (strncmp(vdev, "log", 3) == 0) ||
687 (strncmp(vdev, "cache", 5) == 0))
691 * Verify a file exists at the provided absolute path. If it doesn't
692 * and mo_device_kb is set attempt to create a file vdev to be used.
693 * Relative paths will be passed directly to 'zpool create' which
694 * will check multiple multiple locations under /dev/.
696 if (vdev[0] == '/') {
697 ret = access(vdev, F_OK);
704 fprintf(stderr, "Unable to access required vdev "
705 "for pool %s (%d)\n", vdev, ret);
709 if (mop->mo_device_kb == 0) {
711 fprintf(stderr, "Unable to create vdev due to "
712 "missing --device-size=#N(KB) parameter\n");
716 ret = file_create(vdev, mop->mo_device_kb);
719 fprintf(stderr, "Unable to create vdev %s (%d)\n",
728 int zfs_make_lustre(struct mkfs_opts *mop)
733 char *mkfs_cmd = NULL;
734 char *mkfs_tmp = NULL;
735 char *ds = mop->mo_device;
736 int pool_exists = 0, ret;
738 if (osd_check_zfs_setup() == 0)
741 /* no automatic index with zfs backend */
742 if (mop->mo_ldd.ldd_flags & LDD_F_NEED_INDEX) {
744 fprintf(stderr, "The target index must be specified with "
749 ret = zfs_check_hostid(mop);
757 mkfs_cmd = malloc(PATH_MAX);
758 if (mkfs_cmd == NULL) {
763 mkfs_tmp = malloc(PATH_MAX);
764 if (mkfs_tmp == NULL) {
769 /* Due to zfs_prepare_lustre() check the '/' must exist */
770 strchr(pool, '/')[0] = '\0';
772 /* If --reformat was given attempt to destroy the previous dataset */
773 if ((mop->mo_flags & MO_FORCEFORMAT) &&
774 ((zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM)) != NULL)) {
776 ret = zfs_destroy(zhp, 0);
779 fprintf(stderr, "Failed destroy zfs dataset %s (%d)\n",
788 * Create the zpool if the vdevs have been specified and the pool
789 * does not already exists. The pool creation itself will be done
790 * with the zpool command rather than the zpool_create() library call
791 * so the existing zpool error handling can be leveraged.
793 php = zpool_open(g_zfs, pool);
796 zpool_set_prop(php, "canmount", "off");
800 if ((mop->mo_pool_vdevs != NULL) && (pool_exists == 0)) {
802 memset(mkfs_cmd, 0, PATH_MAX);
803 snprintf(mkfs_cmd, PATH_MAX,
804 "zpool create -f -O canmount=off %s", pool);
806 /* Append the vdev config and create file vdevs as required */
807 while (*mop->mo_pool_vdevs != NULL) {
808 strscat(mkfs_cmd, " ", PATH_MAX);
809 strscat(mkfs_cmd, *mop->mo_pool_vdevs, PATH_MAX);
811 ret = zfs_create_vdev(mop, *mop->mo_pool_vdevs);
815 mop->mo_pool_vdevs++;
818 vprint("mkfs_cmd = %s\n", mkfs_cmd);
819 ret = run_command(mkfs_cmd, PATH_MAX);
822 fprintf(stderr, "Unable to create pool %s (%d)\n",
829 * Set Options on ZPOOL
831 * ALL - canmount=off (set above)
832 * 0.7.0 - multihost=on
833 * 0.7.0 - feature@userobj_accounting=enabled
835 #if defined(HAVE_ZFS_MULTIHOST) || defined(HAVE_DMU_USEROBJ_ACCOUNTING)
836 php = zpool_open(g_zfs, pool);
838 #ifdef HAVE_ZFS_MULTIHOST
839 zpool_set_prop(php, "multihost", "on");
841 #ifdef HAVE_DMU_USEROBJ_ACCOUNTING
842 zpool_set_prop(php, "feature@userobj_accounting", "enabled");
849 * Create the ZFS filesystem with any required mkfs options:
850 * - canmount=off is set to prevent zfs automounting
852 memset(mkfs_cmd, 0, PATH_MAX);
853 snprintf(mkfs_cmd, PATH_MAX,
854 "zfs create -o canmount=off %s %s",
855 zfs_mkfs_opts(mop, mkfs_tmp, PATH_MAX), ds);
857 vprint("mkfs_cmd = %s\n", mkfs_cmd);
858 ret = run_command(mkfs_cmd, PATH_MAX);
861 fprintf(stderr, "Unable to create filesystem %s (%d)\n",
867 * Attempt to set dataset properties to reasonable defaults
868 * to optimize performance, unless the values were specified
869 * at the mkfs command line. Some ZFS pools or ZFS versions
870 * do not support these properties. We can safely ignore the
871 * errors and continue in those cases.
873 * zfs 0.6.1 - system attribute based xattrs
874 * zfs 0.6.5 - large block support
875 * zfs 0.7.0 - large dnode support
877 * Check if zhp is NULL as a defensive measure. Any dataset
878 * validation errors that would cause zfs_open() to fail
879 * should have been caught earlier.
881 zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM);
883 /* zfs 0.6.1 - system attribute based xattrs */
884 if (!strstr(mop->mo_mkfsopts, "xattr="))
885 zfs_set_prop_str(zhp, "xattr", "sa");
887 /* zfs 0.7.0 - large dnode support */
888 if (!strstr(mop->mo_mkfsopts, "dnodesize=") &&
889 !strstr(mop->mo_mkfsopts, "dnsize="))
890 zfs_set_prop_str(zhp, "dnodesize", "auto");
892 if (IS_OST(&mop->mo_ldd)) {
893 /* zfs 0.6.5 - large block support */
894 if (!strstr(mop->mo_mkfsopts, "recordsize=") &&
895 !strstr(mop->mo_mkfsopts, "recsize="))
896 zfs_set_prop_str(zhp, "recordsize", "1M");
906 if (mkfs_cmd != NULL)
909 if (mkfs_tmp != NULL)
915 int zfs_enable_quota(struct mkfs_opts *mop)
917 fprintf(stderr, "this option is not only valid for zfs\n");
921 int zfs_prepare_lustre(struct mkfs_opts *mop,
922 char *wanted_mountopts, size_t len)
924 if (osd_check_zfs_setup() == 0)
927 if (zfs_name_valid(mop->mo_device, ZFS_TYPE_FILESYSTEM) == 0) {
929 fprintf(stderr, "Invalid filesystem name %s\n", mop->mo_device);
933 if (strchr(mop->mo_device, '/') == NULL) {
935 fprintf(stderr, "Missing pool in filesystem name %s\n",
943 int zfs_tune_lustre(char *dev, struct mount_opts *mop)
945 if (osd_check_zfs_setup() == 0)
951 int zfs_label_lustre(struct mount_opts *mop)
956 if (osd_check_zfs_setup() == 0)
959 zhp = zfs_open(g_zfs, mop->mo_source, ZFS_TYPE_FILESYSTEM);
963 ret = zfs_set_prop_str(zhp, LDD_SVNAME_PROP, mop->mo_ldd.ldd_svname);
969 int zfs_rename_fsname(struct mkfs_opts *mop, const char *oldname)
971 struct mount_opts opts;
972 char mntpt[] = "/tmp/mntXXXXXX";
976 /* Change the filesystem label. */
977 opts.mo_ldd = mop->mo_ldd;
978 opts.mo_source = mop->mo_device;
979 ret = zfs_label_lustre(&opts);
983 fprintf(stderr, "Can't change filesystem label: %s\n",
988 /* Mount this device temporarily in order to write these files */
989 if (mkdtemp(mntpt) == NULL) {
992 fprintf(stderr, "Can't create temp mount point %s: %s\n",
993 mntpt, strerror(ret));
997 cmd_buf = malloc(PATH_MAX);
1003 memset(cmd_buf, 0, PATH_MAX);
1004 snprintf(cmd_buf, PATH_MAX - 1, "zfs set mountpoint=%s %s && "
1005 "zfs set canmount=on %s && zfs mount %s",
1006 mntpt, mop->mo_device, mop->mo_device, mop->mo_device);
1007 ret = run_command(cmd_buf, PATH_MAX);
1011 fprintf(stderr, "Unable to mount %s (%s)\n",
1012 mop->mo_device, strerror(ret));
1014 fprintf(stderr, "Is the %s module available?\n",
1015 MT_STR(&mop->mo_ldd));
1019 ret = lustre_rename_fsname(mop, mntpt, oldname);
1020 memset(cmd_buf, 0, PATH_MAX);
1021 snprintf(cmd_buf, PATH_MAX - 1, "zfs umount %s && "
1022 "zfs set canmount=off %s && zfs set mountpoint=none %s",
1023 mop->mo_device, mop->mo_device, mop->mo_device);
1024 run_command(cmd_buf, PATH_MAX);
1037 g_zfs = libzfs_init();
1039 if (g_zfs == NULL) {
1040 /* Try to load zfs.ko and retry libzfs_init() */
1042 ret = system("/sbin/modprobe -q zfs");
1045 g_zfs = libzfs_init();
1054 fprintf(stderr, "Failed to initialize ZFS library: %d\n", ret);
1069 struct module_backfs_ops zfs_ops = {
1072 .read_ldd = zfs_read_ldd,
1073 .write_ldd = zfs_write_ldd,
1074 .erase_ldd = zfs_erase_ldd,
1075 .print_ldd_params = zfs_print_ldd_params,
1076 .is_lustre = zfs_is_lustre,
1077 .make_lustre = zfs_make_lustre,
1078 .prepare_lustre = zfs_prepare_lustre,
1079 .tune_lustre = zfs_tune_lustre,
1080 .label_lustre = zfs_label_lustre,
1081 .enable_quota = zfs_enable_quota,
1082 .rename_fsname = zfs_rename_fsname,
1084 #endif /* PLUGIN_DIR */