Whamcloud - gitweb
LU-13048 mdd: allow release after a non-blocking migrate
[fs/lustre-release.git] / lustre / utils / libmount_utils_zfs.c
index 920682c..cb0a539 100644 (file)
@@ -20,7 +20,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2012, 2016, Intel Corporation.
+ * Copyright (c) 2012, 2017, Intel Corporation.
  * Use is subject to license terms.
  */
 /*
@@ -31,8 +31,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <libzfs.h>
-
-#define HOSTID_PATH "/etc/hostid"
+#include <sys/systeminfo.h>
 
 /* Persistent mount data is stored in these user attributes */
 #define LDD_PREFIX             "lustre:"
@@ -58,16 +57,26 @@ struct zfs_ldd_prop_bridge {
        int   zlpb_ldd_offset;
        /* Function pointer responsible for reading in the @prop
         * property from @zhp and storing it in @ldd_field */
+#ifdef HAVE_ZFS_NVLIST_CONST_INTERFACES
+       int (*zlpb_get_prop_fn)(zfs_handle_t *zhp, const char *prop,
+            void *ldd_field);
+#else
        int (*zlpb_get_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field);
+#endif
        /* Function pointer responsible for writing the value of @ldd_field
         * into the @prop dataset property in @zhp */
        int (*zlpb_set_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field);
 };
 
 /* Forward declarations needed to initialize the ldd prop bridge list */
+#ifdef HAVE_ZFS_NVLIST_CONST_INTERFACES
+static int zfs_get_prop_int(zfs_handle_t *, const char *, void *);
+static int zfs_get_prop_str(zfs_handle_t *, const char *, void *);
+#else
 static int zfs_get_prop_int(zfs_handle_t *, char *, void *);
-static int zfs_set_prop_int(zfs_handle_t *, char *, void *);
 static int zfs_get_prop_str(zfs_handle_t *, char *, void *);
+#endif
+static int zfs_set_prop_int(zfs_handle_t *, char *, void *);
 static int zfs_set_prop_str(zfs_handle_t *, char *, void *);
 
 /* Helper for initializing the entries in the special_ldd_prop_params list.
@@ -169,24 +178,65 @@ static int zfs_erase_prop(zfs_handle_t *zhp, char *param)
        return zfs_remove_prop(zhp, nvl, propname);
 }
 
+#ifdef HAVE_ZFS_NVLIST_CONST_INTERFACES
+static int zfs_is_special_ldd_prop_param(const char *name)
+#else
+static int zfs_is_special_ldd_prop_param(char *name)
+#endif
+{
+       int i;
+
+       for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++)
+               if (!strcmp(name, special_ldd_prop_params[i].zlpb_prop_name))
+                       return 1;
+
+       return 0;
+}
+
 static int zfs_erase_allprops(zfs_handle_t *zhp)
 {
-       nvlist_t *nvl;
-       nvpair_t *curr = NULL;
+       nvlist_t *props;
+       nvpair_t *nvp;
+       size_t str_size = 1024 * 1024;
+       char *strs, *cur;
+       int rc = 0;
 
-       nvl = zfs_get_user_props(zhp);
-       if (!nvl)
+       strs = malloc(str_size);
+       if (!strs)
+               return ENOMEM;
+       cur = strs;
+
+       props = zfs_get_user_props(zhp);
+       if (props == NULL) {
+               free(strs);
                return ENOENT;
+       }
+       nvp = NULL;
+       while (nvp = nvlist_next_nvpair(props, nvp), nvp) {
+               if (strncmp(nvpair_name(nvp), LDD_PREFIX, strlen(LDD_PREFIX)))
+                       continue;
 
-       curr = nvlist_next_nvpair(nvl, curr);
-       while (curr) {
-               nvpair_t *next = nvlist_next_nvpair(nvl, curr);
+               if (zfs_is_special_ldd_prop_param(nvpair_name(nvp)))
+                       continue;
 
-               zfs_remove_prop(zhp, nvl, nvpair_name(curr));
-               curr = next;
+               rc = snprintf(cur, str_size - (cur - strs), "%s",
+                             nvpair_name(nvp));
+               if (rc != strlen(nvpair_name(nvp))) {
+                       fprintf(stderr, "%s: zfs has too many properties to erase, please repeat\n",
+                               progname);
+                       rc = EINVAL;
+                       break;
+               }
+               cur += strlen(cur) + 1;
+       }
+       cur = strs;
+       while ( cur < (strs + str_size) && strlen(cur) > 0) {
+               zfs_prop_inherit(zhp, cur, false);
+               cur += strlen(cur) + 1;
        }
 
-       return 0;
+       free(strs);
+       return rc;
 }
 
 /*
@@ -237,45 +287,12 @@ static int zfs_set_prop_params(zfs_handle_t *zhp, char *params)
 
 static int zfs_check_hostid(struct mkfs_opts *mop)
 {
-       FILE *f;
        unsigned long hostid;
-       int rc;
 
        if (strstr(mop->mo_ldd.ldd_params, PARAM_FAILNODE) == NULL)
                return 0;
 
-       f = fopen("/sys/module/spl/parameters/spl_hostid", "r");
-       if (f == NULL) {
-               fatal();
-               fprintf(stderr, "Failed to open spl_hostid: %s\n",
-                       strerror(errno));
-               return errno;
-       }
-       rc = fscanf(f, "%li", &hostid);
-       fclose(f);
-       if (rc != 1) {
-               fatal();
-               fprintf(stderr, "Failed to read spl_hostid: %d\n", rc);
-               return rc;
-       }
-
-       if (hostid != 0)
-               return 0;
-
-       f = fopen(HOSTID_PATH, "r");
-       if (f == NULL)
-               goto out;
-
-       rc = fread(&hostid, sizeof(uint32_t), 1, f);
-       fclose(f);
-
-       if (rc != 1) {
-               fprintf(stderr, "Failed to read "HOSTID_PATH": %d\n",
-                      rc);
-               hostid = 0;
-       }
-
-out:
+       hostid = get_system_hostid();
        if (hostid == 0) {
                if (mop->mo_flags & MO_NOHOSTID_CHECK) {
                        fprintf(stderr, "WARNING: spl_hostid not set. ZFS has "
@@ -326,8 +343,13 @@ int zfs_write_ldd(struct mkfs_opts *mop)
 
        vprint("Writing %s properties\n", ds);
 
-       if (mop->mo_flags & MO_ERASE_ALL)
+       if (mop->mo_flags & MO_ERASE_ALL) {
                ret = zfs_erase_allprops(zhp);
+               if (ret < 0) {
+                       fprintf(stderr, "zfs_erase_allprops Failed: %d\n", ret);
+                       goto out_close;
+               }
+       }
        ret = zfs_set_prop_params(zhp, ldd->ldd_params);
 
        for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) {
@@ -358,10 +380,16 @@ int zfs_erase_ldd(struct mkfs_opts *mop, char *param)
        return add_param(mop->mo_ldd.ldd_params, key, "");
 }
 
+#ifdef HAVE_ZFS_NVLIST_CONST_INTERFACES
+static int zfs_get_prop_int(zfs_handle_t *zhp, const char *prop, void *val)
+{
+       const char *propstr;
+#else
 static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, void *val)
 {
-       nvlist_t *propval;
        char *propstr;
+#endif
+       nvlist_t *propval;
        int ret;
 
        ret = nvlist_lookup_nvlist(zfs_get_user_props(zhp), prop, &propval);
@@ -380,10 +408,16 @@ static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, void *val)
        return ret;
 }
 
+#ifdef HAVE_ZFS_NVLIST_CONST_INTERFACES
+static int zfs_get_prop_str(zfs_handle_t *zhp, const char *prop, void *val)
+{
+       const char *propstr;
+#else
 static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, void *val)
 {
-       nvlist_t *propval;
        char *propstr;
+#endif
+       nvlist_t *propval;
        int ret;
 
        ret = nvlist_lookup_nvlist(zfs_get_user_props(zhp), prop, &propval);
@@ -399,17 +433,6 @@ static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, void *val)
        return ret;
 }
 
-static int zfs_is_special_ldd_prop_param(char *name)
-{
-       int i;
-
-       for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++)
-               if (!strcmp(name, special_ldd_prop_params[i].zlpb_prop_name))
-                       return 1;
-
-       return 0;
-}
-
 static int zfs_get_prop_params(zfs_handle_t *zhp, char *param)
 {
        nvlist_t *props;
@@ -477,8 +500,20 @@ int zfs_read_ldd(char *ds,  struct lustre_disk_data *ldd)
 
        ldd->ldd_mount_type = LDD_MT_ZFS;
        ret = 0;
+
+       if (strstr(ldd->ldd_params, PARAM_FAILNODE) != NULL) {
+               zpool_handle_t *pool = zfs_get_pool_handle(zhp);
+               uint64_t mh = zpool_get_prop_int(pool, ZPOOL_PROP_MULTIHOST,
+                                                NULL);
+               if (!mh)
+                       fprintf(stderr, "%s: %s is configured for failover "
+                               "but zpool does not have multihost enabled\n",
+                               progname, ds);
+       }
+
 out_close:
        zfs_close(zhp);
+
 out:
        return ret;
 }
@@ -543,6 +578,9 @@ static char *zfs_mkfs_opts(struct mkfs_opts *mop, char *str, int len)
 
        if (strlen(mop->mo_mkfsopts) != 0)
                snprintf(str, len, " -o %s", mop->mo_mkfsopts);
+       if (mop->mo_device_kb)
+               snprintf(str, len, " -o quota=%llu",
+                        (unsigned long long)mop->mo_device_kb * 1024);
 
        return str;
 }
@@ -667,6 +705,7 @@ int zfs_make_lustre(struct mkfs_opts *mop)
        php = zpool_open(g_zfs, pool);
        if (php) {
                pool_exists = 1;
+               zpool_set_prop(php, "canmount", "off");
                zpool_close(php);
        }
 
@@ -701,27 +740,24 @@ int zfs_make_lustre(struct mkfs_opts *mop)
        /*
         * Set Options on ZPOOL
         *
-        * ALL   - canmount=off
+        * ALL   - canmount=off (set above)
         * 0.7.0 - multihost=on
+        * 0.7.0 - feature@userobj_accounting=enabled
         */
        php = zpool_open(g_zfs, pool);
        if (php) {
-               if (pool_exists)
-                       zpool_set_prop(php, "canmount", "off");
-
                zpool_set_prop(php, "multihost", "on");
-
+               zpool_set_prop(php, "feature@userobj_accounting", "enabled");
                zpool_close(php);
        }
 
        /*
         * Create the ZFS filesystem with any required mkfs options:
         * - canmount=off is set to prevent zfs automounting
-        * - xattr=sa is set to use system attribute based xattrs
         */
        memset(mkfs_cmd, 0, PATH_MAX);
        snprintf(mkfs_cmd, PATH_MAX,
-                "zfs create -o canmount=off -o xattr=sa%s %s",
+                "zfs create -o canmount=off %s %s",
                 zfs_mkfs_opts(mop, mkfs_tmp, PATH_MAX), ds);
 
        vprint("mkfs_cmd = %s\n", mkfs_cmd);
@@ -733,6 +769,42 @@ int zfs_make_lustre(struct mkfs_opts *mop)
                goto out;
        }
 
+       /*
+        * Attempt to set dataset properties to reasonable defaults
+        * to optimize performance, unless the values were specified
+        * at the mkfs command line. Some ZFS pools or ZFS versions
+        * do not support these properties. We can safely ignore the
+        * errors and continue in those cases.
+        *
+        * zfs 0.6.1 - system attribute based xattrs
+        * zfs 0.6.5 - large block support
+        * zfs 0.7.0 - large dnode support
+        *
+        * Check if zhp is NULL as a defensive measure. Any dataset
+        * validation errors that would cause zfs_open() to fail
+        * should have been caught earlier.
+        */
+       zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM);
+       if (zhp) {
+               /* zfs 0.6.1 - system attribute based xattrs */
+               if (!strstr(mop->mo_mkfsopts, "xattr="))
+                       zfs_set_prop_str(zhp, "xattr", "sa");
+
+               /* zfs 0.7.0 - large dnode support */
+               if (!strstr(mop->mo_mkfsopts, "dnodesize=") &&
+                   !strstr(mop->mo_mkfsopts, "dnsize="))
+                       zfs_set_prop_str(zhp, "dnodesize", "auto");
+
+               if (IS_OST(&mop->mo_ldd)) {
+                       /* zfs 0.6.5 - large block support */
+                       if (!strstr(mop->mo_mkfsopts, "recordsize=") &&
+                           !strstr(mop->mo_mkfsopts, "recsize="))
+                               zfs_set_prop_str(zhp, "recordsize", "1M");
+               }
+
+               zfs_close(zhp);
+       }
+
 out:
        if (pool != NULL)
                free(pool);