X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Flibmount_utils_zfs.c;h=71966fc41aa1eea3dd3039a4cef937d1c7c0040e;hb=6b8e97b76c472068e7d6bc792e4f202b2f70ca67;hp=920682c30dd912b1964cf28b84444bb6632d6e58;hpb=d6f57eda898cc80a1cff49ad3875021749563dbf;p=fs%2Flustre-release.git diff --git a/lustre/utils/libmount_utils_zfs.c b/lustre/utils/libmount_utils_zfs.c index 920682c..71966fc 100644 --- a/lustre/utils/libmount_utils_zfs.c +++ b/lustre/utils/libmount_utils_zfs.c @@ -20,19 +20,23 @@ * GPL HEADER END */ /* - * Copyright (c) 2012, 2016, Intel Corporation. + * Copyright (c) 2012, 2017, Intel Corporation. * Use is subject to license terms. */ /* * Author: Brian Behlendorf */ +#ifndef HAVE_ZFS_MULTIHOST +#include +#define list_move_tail(a, b) spl_list_move_tail(a, b) +#include +#endif #include "mount_utils.h" #include #include #include #include - -#define HOSTID_PATH "/etc/hostid" +#include /* Persistent mount data is stored in these user attributes */ #define LDD_PREFIX "lustre:" @@ -169,26 +173,171 @@ static int zfs_erase_prop(zfs_handle_t *zhp, char *param) return zfs_remove_prop(zhp, nvl, propname); } +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_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; } + free(strs); + return rc; +} +/* + * ZFS on linux 0.7.0-rc5 commit 379ca9cf2beba802f096273e89e30914a2d6bafc + * Multi-modifier protection (MMP) + * + * Introduced spa_get_hostid() along with a few constants like + * ZPOOL_CONFIG_MMP_HOSTID that can be checked to imply availablity of + * spa_get_hostid. Supply a fallback when spa_get_hostid is not + * available. + * + * This can be removed when zfs 0.6.x support is dropped. + */ +#if !defined(ZPOOL_CONFIG_MMP_HOSTID) && !defined(HAVE_ZFS_MULTIHOST) +unsigned long _hostid_from_proc(void) +{ + FILE *f; + unsigned long hostid; + int rc; + + f = fopen("/proc/sys/kernel/spl/hostid", "r"); + if (f == NULL) + goto out; + + rc = fscanf(f, "%lx", &hostid); + fclose(f); + if (rc == 1) + return hostid; +out: return 0; } +unsigned long _hostid_from_module_param(void) +{ + FILE *f; + unsigned long hostid; + int rc; + + f = fopen("/sys/module/spl/parameters/spl_hostid", "r"); + if (f == NULL) + goto out; + + rc = fscanf(f, "%li", &hostid); + fclose(f); + if (rc == 1) + return hostid; +out: + return 0; +} + +unsigned long _from_module_param_indirect(void) +{ + FILE *f; + unsigned long hostid = 0; + uint32_t hwid; + int rc; + char *spl_hostid_path = NULL; + + /* read the module parameter for HW_HOSTID_PATH */ + f = fopen("/sys/module/spl/parameters/spl_hostid_path", "r"); + if (f == NULL) { + fatal(); + fprintf(stderr, "Failed to open spl_hostid_path param: %s\n", + strerror(errno)); + goto out; + } + + rc = fscanf(f, "%ms%*[\n]", &spl_hostid_path); + fclose(f); + if (rc == 0 || !spl_hostid_path) + goto out; + + /* read the hostid from the file */ + f = fopen(spl_hostid_path, "r"); + if (f == NULL) { + fatal(); + fprintf(stderr, "Failed to open %s param: %s\n", + spl_hostid_path, strerror(errno)); + goto out; + } + + /* hostid is the first 4 bytes in native endian order */ + rc = fread(&hwid, sizeof(uint32_t), 1, f); + fclose(f); + if (rc == 1) + hostid = (unsigned long)hwid; + +out: + if (spl_hostid_path) + free(spl_hostid_path); + + return hostid; +} + +unsigned long spa_get_hostid(void) +{ + unsigned long hostid; + + hostid = _hostid_from_proc(); + if (hostid) + return hostid; + + /* if /proc isn't available, try /sys */ + hostid = _hostid_from_module_param(); + if (hostid) + return hostid; + + return _from_module_param_indirect(); +} +#endif + /* * Map '= ...' pairs in the passed string to dataset properties * of the form 'lustre:='. "=" means to remove this key @@ -237,45 +386,16 @@ 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: +#ifdef HAVE_ZFS_MULTIHOST + hostid = get_system_hostid(); +#else + hostid = spa_get_hostid(); +#endif if (hostid == 0) { if (mop->mo_flags & MO_NOHOSTID_CHECK) { fprintf(stderr, "WARNING: spl_hostid not set. ZFS has " @@ -399,17 +519,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 +586,22 @@ int zfs_read_ldd(char *ds, struct lustre_disk_data *ldd) ldd->ldd_mount_type = LDD_MT_ZFS; ret = 0; + +#ifdef HAVE_ZFS_MULTIHOST + 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); + } +#endif + out_close: zfs_close(zhp); + out: return ret; } @@ -543,6 +666,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 +793,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 +828,30 @@ 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 */ +#if defined(HAVE_ZFS_MULTIHOST) || defined(HAVE_DMU_USEROBJ_ACCOUNTING) php = zpool_open(g_zfs, pool); if (php) { - if (pool_exists) - zpool_set_prop(php, "canmount", "off"); - +#ifdef HAVE_ZFS_MULTIHOST zpool_set_prop(php, "multihost", "on"); - +#endif +#ifdef HAVE_DMU_USEROBJ_ACCOUNTING + zpool_set_prop(php, "feature@userobj_accounting", "enabled"); +#endif zpool_close(php); } +#endif /* * 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 +863,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);