X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Fmount_utils_zfs.c;h=9db2f8c9d3adcc95767a05e51c0d6a1a865f8020;hb=62a9ad817017d677b1914f0838d4a66ce64d2270;hp=96f67fc86b0e8928dbb728837daee74989a279c6;hpb=08aa217ce49aba1ded52e0f7adb8a607035123fd;p=fs%2Flustre-release.git diff --git a/lustre/utils/mount_utils_zfs.c b/lustre/utils/mount_utils_zfs.c index 96f67fc..9db2f8c 100644 --- a/lustre/utils/mount_utils_zfs.c +++ b/lustre/utils/mount_utils_zfs.c @@ -20,7 +20,7 @@ * GPL HEADER END */ /* - * Copyright (c) 2012, Intel Corporation. + * Copyright (c) 2012, 2013, Intel Corporation. * Use is subject to license terms. * */ @@ -31,102 +31,86 @@ #include #include #include -#include - -/* Persistent mount data is stored in these user attributes */ -#define LDD_VERSION_PROP "lustre:version" -#define LDD_FLAGS_PROP "lustre:flags" -#define LDD_INDEX_PROP "lustre:index" -#define LDD_FSNAME_PROP "lustre:fsname" -#define LDD_SVNAME_PROP "lustre:svname" -#define LDD_UUID_PROP "lustre:uuid" -#define LDD_USERDATA_PROP "lustre:userdata" -#define LDD_MOUNTOPTS_PROP "lustre:mountopts" -#define LDD_PARAMS_PROP "lustre:params" -/* indicate if the ZFS OSD has been successfully setup */ -static int osd_zfs_setup = 0; +/* Persistent mount data is stored in these user attributes */ +#define LDD_PREFIX "lustre:" +#define LDD_VERSION_PROP LDD_PREFIX "version" +#define LDD_FLAGS_PROP LDD_PREFIX "flags" +#define LDD_INDEX_PROP LDD_PREFIX "index" +#define LDD_FSNAME_PROP LDD_PREFIX "fsname" +#define LDD_SVNAME_PROP LDD_PREFIX "svname" +#define LDD_UUID_PROP LDD_PREFIX "uuid" +#define LDD_USERDATA_PROP LDD_PREFIX "userdata" +#define LDD_MOUNTOPTS_PROP LDD_PREFIX "mountopts" + +/* This structure is used to help bridge the gap between the ZFS + * properties Lustre uses and their corresponding internal LDD fields. + * It is meant to be used internally by the mount utility only. */ +struct zfs_ldd_prop_bridge { + /* Contains the publicly visible name for the property + * (i.e. what is shown when running "zfs get") */ + char *zlpb_prop_name; + /* Contains the offset into the lustre_disk_data structure where + * the value of this property is or will be stored. (i.e. the + * property is read from and written to this offset within ldd) */ + int zlpb_ldd_offset; + /* Function pointer responsible for reading in the @prop + * property from @zhp and storing it in @ldd_field */ + int (*zlpb_get_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field); + /* 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); +}; -static libzfs_handle_t *g_zfs; +/* Forward declarations needed to initialize the ldd prop bridge list */ +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 *); +static int zfs_set_prop_str(zfs_handle_t *, char *, void *); + +/* Helper for initializing the entries in the special_ldd_prop_params list. + * - @name: stored directly in the zlpb_prop_name field + * (e.g. lustre:fsname, lustre:version, etc.) + * - @field: the field in the lustre_disk_data which directly maps to + * the @name property. (e.g. ldd_fsname, ldd_config_ver, etc.) + * - @type: The type of @field. Only "int" and "str" are supported. + */ +#define ZLB_INIT(name, field, type) \ +{ \ + name, offsetof(struct lustre_disk_data, field), \ + zfs_get_prop_ ## type, zfs_set_prop_ ## type \ +} -/* dynamic linking handles for libzfs & libnvpair */ -static void *handle_libzfs; -static void *handle_nvpair; - -/* symbol table looked up with dlsym */ -struct zfs_symbols { - libzfs_handle_t *(*libzfs_init)(void); - void (*libzfs_fini)(libzfs_handle_t *); - int (*libzfs_load_module)(char *); - zfs_handle_t* (*zfs_open)(libzfs_handle_t *, const char *, int); - int (*zfs_destroy)(zfs_handle_t *, boolean_t); - void (*zfs_close)(zfs_handle_t *); - int (*zfs_prop_set)(zfs_handle_t*, const char*, const char*); - nvlist_t* (*zfs_get_user_props) (zfs_handle_t *); - int (*zfs_name_valid)(const char *, zfs_type_t); - zpool_handle_t* (*zpool_open)(libzfs_handle_t *, const char *); - void (*zpool_close)(zpool_handle_t *zhp); - int (*nvlist_lookup_string)(nvlist_t*, const char*, char**); - int (*nvlist_lookup_nvlist)(nvlist_t *, const char *, nvlist_t **); +/* These ldd properties are special because they all have their own + * individual fields in the lustre_disk_data structure, as opposed to + * being globbed into the ldd_params field. As such, these need special + * handling when reading/writing the ldd structure to/from persistent + * storage. */ +struct zfs_ldd_prop_bridge special_ldd_prop_params[] = { + ZLB_INIT(LDD_VERSION_PROP, ldd_config_ver, int), + ZLB_INIT(LDD_FLAGS_PROP, ldd_flags, int), + ZLB_INIT(LDD_INDEX_PROP, ldd_svindex, int), + ZLB_INIT(LDD_FSNAME_PROP, ldd_fsname, str), + ZLB_INIT(LDD_SVNAME_PROP, ldd_svname, str), + ZLB_INIT(LDD_UUID_PROP, ldd_uuid, str), + ZLB_INIT(LDD_USERDATA_PROP, ldd_userdata, str), + ZLB_INIT(LDD_MOUNTOPTS_PROP, ldd_mount_opts, str), + { NULL } }; -static struct zfs_symbols sym; -void zfs_fini(void); +/* indicate if the ZFS OSD has been successfully setup */ +static int osd_zfs_setup = 0; -#define DLSYM(handle, func) \ - do { \ - sym.func = (typeof(sym.func))dlsym(handle, #func); \ - } while(0) +static libzfs_handle_t *g_zfs; -/* populate the symbol table after a successful call to dlopen() */ -static int zfs_populate_symbols(void) -{ - char *error; - - dlerror(); /* Clear any existing error */ - - DLSYM(handle_libzfs, libzfs_init); -#define libzfs_init (*sym.libzfs_init) - DLSYM(handle_libzfs, libzfs_fini); -#define libzfs_fini (*sym.libzfs_fini) - DLSYM(handle_libzfs, libzfs_load_module); -#define libzfs_load_module (*sym.libzfs_load_module) - DLSYM(handle_libzfs, zfs_open); -#define zfs_open (*sym.zfs_open) - DLSYM(handle_libzfs, zfs_destroy); -#define zfs_destroy (*sym.zfs_destroy) - DLSYM(handle_libzfs, zfs_close); -#define zfs_close (*sym.zfs_close) - DLSYM(handle_libzfs, zfs_prop_set); -#define zfs_prop_set (*sym.zfs_prop_set) - DLSYM(handle_libzfs, zfs_get_user_props); -#define zfs_get_user_props (*sym.zfs_get_user_props) - DLSYM(handle_libzfs, zfs_name_valid); -#define zfs_name_valid (*sym.zfs_name_valid) - DLSYM(handle_libzfs, zpool_open); -#define zpool_open (*sym.zpool_open) - DLSYM(handle_libzfs, zpool_close); -#define zpool_close (*sym.zpool_close) - DLSYM(handle_nvpair, nvlist_lookup_string); -#define nvlist_lookup_string (*sym.nvlist_lookup_string) - DLSYM(handle_nvpair, nvlist_lookup_nvlist); -#define nvlist_lookup_nvlist (*sym.nvlist_lookup_nvlist) - - error = dlerror(); - if (error != NULL) { - fatal(); - fprintf(stderr, "%s\n", error); - return EINVAL; - } - return 0; -} +void zfs_fini(void); -static int zfs_set_prop_int(zfs_handle_t *zhp, char *prop, __u32 val) +static int zfs_set_prop_int(zfs_handle_t *zhp, char *prop, void *val) { char str[64]; int ret; - (void) snprintf(str, sizeof (str), "%lu", (unsigned long)val); + (void) snprintf(str, sizeof (str), "%i", *(int *)val); vprint(" %s=%s\n", prop, str); ret = zfs_prop_set(zhp, prop, str); @@ -137,15 +121,56 @@ static int zfs_set_prop_int(zfs_handle_t *zhp, char *prop, __u32 val) * Write the zfs property string, note that properties with a NULL or * zero-length value will not be written and 0 returned. */ -static int zfs_set_prop_str(zfs_handle_t *zhp, char *prop, char *val) +static int zfs_set_prop_str(zfs_handle_t *zhp, char *prop, void *val) { int ret = 0; if (val && strlen(val) > 0) { - vprint(" %s=%s\n", prop, val); - ret = zfs_prop_set(zhp, prop, val); + vprint(" %s=%s\n", prop, (char *)val); + ret = zfs_prop_set(zhp, prop, (char *)val); + } + + return ret; +} + +/* + * Map '= ...' pairs in the passed string to dataset properties + * of the form 'lustre:='. Malformed = pairs will + * be skipped. + */ +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_MAXNAMELEN]; + int ret = 0; + + params_dup = strdup(params); + if (params_dup == NULL) + return ENOMEM; + + token = strtok_r(params_dup, " ", &save_token); + while (token) { + key = strtok(token, "="); + if (key == NULL) + continue; + + value = strtok(NULL, "="); + if (value == NULL) + continue; + + sprintf(prop_name, "%s%s", LDD_PREFIX, key); + vprint(" %s=%s\n", prop_name, value); + + ret = zfs_prop_set(zhp, prop_name, value); + if (ret) + break; + + token = strtok_r(NULL, " ", &save_token); } + free(params_dup); + return ret; } @@ -166,7 +191,8 @@ int zfs_write_ldd(struct mkfs_opts *mop) struct lustre_disk_data *ldd = &mop->mo_ldd; char *ds = mop->mo_device; zfs_handle_t *zhp; - int ret = EINVAL; + struct zfs_ldd_prop_bridge *bridge; + int i, ret = EINVAL; if (osd_check_zfs_setup() == 0) return EINVAL; @@ -179,43 +205,15 @@ int zfs_write_ldd(struct mkfs_opts *mop) vprint("Writing %s properties\n", ds); - ret = zfs_set_prop_int(zhp, LDD_VERSION_PROP, ldd->ldd_config_ver); - if (ret) - goto out_close; - - ret = zfs_set_prop_int(zhp, LDD_FLAGS_PROP, ldd->ldd_flags); - if (ret) - goto out_close; - - ret = zfs_set_prop_int(zhp, LDD_INDEX_PROP, ldd->ldd_svindex); - if (ret) - goto out_close; - - ret = zfs_set_prop_str(zhp, LDD_FSNAME_PROP, ldd->ldd_fsname); - if (ret) - goto out_close; - - ret = zfs_set_prop_str(zhp, LDD_SVNAME_PROP, ldd->ldd_svname); - if (ret) - goto out_close; - - ret = zfs_set_prop_str(zhp, LDD_UUID_PROP, (char *)ldd->ldd_uuid); - if (ret) - goto out_close; - - ret = zfs_set_prop_str(zhp, LDD_USERDATA_PROP, ldd->ldd_userdata); - if (ret) - goto out_close; - - ret = zfs_set_prop_str(zhp, LDD_MOUNTOPTS_PROP, ldd->ldd_mount_opts); - if (ret) - goto out_close; - - if (strlen(ldd->ldd_params) > ZAP_MAXVALUELEN) { - ret = E2BIG; - goto out_close; + 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, + (void *)ldd + bridge->zlpb_ldd_offset); + if (ret) + goto out_close; } - ret = zfs_set_prop_str(zhp, LDD_PARAMS_PROP, ldd->ldd_params); + + ret = zfs_set_prop_params(zhp, ldd->ldd_params); out_close: zfs_close(zhp); @@ -223,7 +221,7 @@ out: return ret; } -static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, __u32 *val) +static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, void *val) { nvlist_t *propval; char *propstr; @@ -238,14 +236,14 @@ static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, __u32 *val) return ret; errno = 0; - *val = strtoul(propstr, NULL, 10); + *(__u32 *)val = strtoul(propstr, NULL, 10); if (errno) return errno; return ret; } -static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, char *val) +static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, void *val) { nvlist_t *propval; char *propstr; @@ -264,6 +262,57 @@ static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, char *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, int len) +{ + nvlist_t *props; + nvpair_t *nvp; + char key[ZFS_MAXNAMELEN]; + char *value; + 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); + if (ret) + break; + + if (strncmp(nvpair_name(nvp), LDD_PREFIX, strlen(LDD_PREFIX))) + continue; + + if (zfs_is_special_ldd_prop_param(nvpair_name(nvp))) + continue; + + sprintf(key, "%s=", nvpair_name(nvp) + strlen(LDD_PREFIX)); + + ret = add_param(param, key, value); + if (ret) + break; + } + + free(value); + + return ret; +} + /* * Read the server config as properties associated with the dataset. * Missing entries as not treated error and are simply skipped. @@ -271,7 +320,8 @@ static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, char *val) int zfs_read_ldd(char *ds, struct lustre_disk_data *ldd) { zfs_handle_t *zhp; - int ret = EINVAL; + struct zfs_ldd_prop_bridge *bridge; + int i, ret = EINVAL; if (osd_check_zfs_setup() == 0) return EINVAL; @@ -280,39 +330,15 @@ int zfs_read_ldd(char *ds, struct lustre_disk_data *ldd) if (zhp == NULL) goto out; - ret = zfs_get_prop_int(zhp, LDD_VERSION_PROP, &ldd->ldd_config_ver); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_int(zhp, LDD_FLAGS_PROP, &ldd->ldd_flags); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_int(zhp, LDD_INDEX_PROP, &ldd->ldd_svindex); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_str(zhp, LDD_FSNAME_PROP, ldd->ldd_fsname); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_str(zhp, LDD_SVNAME_PROP, ldd->ldd_svname); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_str(zhp, LDD_UUID_PROP, (char *)ldd->ldd_uuid); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_str(zhp, LDD_USERDATA_PROP, ldd->ldd_userdata); - if (ret && (ret != ENOENT)) - goto out_close; - - ret = zfs_get_prop_str(zhp, LDD_MOUNTOPTS_PROP, ldd->ldd_mount_opts); - if (ret && (ret != ENOENT)) - goto out_close; + for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) { + bridge = &special_ldd_prop_params[i]; + ret = bridge->zlpb_get_prop_fn(zhp, bridge->zlpb_prop_name, + (void *)ldd + bridge->zlpb_ldd_offset); + if (ret && (ret != ENOENT)) + goto out_close; + } - ret = zfs_get_prop_str(zhp, LDD_PARAMS_PROP, ldd->ldd_params); + ret = zfs_get_prop_params(zhp, ldd->ldd_params, 4096); if (ret && (ret != ENOENT)) goto out_close; @@ -368,7 +394,7 @@ static int zfs_create_vdev(struct mkfs_opts *mop, char *vdev) /* * Verify a file exists at the provided absolute path. If it doesn't - * and mo_device_sz is set attempt to create a file vdev to be used. + * and mo_device_kb is set attempt to create a file vdev to be used. * Relative paths will be passed directly to 'zpool create' which * will check multiple multiple locations under /dev/. */ @@ -385,14 +411,14 @@ static int zfs_create_vdev(struct mkfs_opts *mop, char *vdev) return ret; } - if (mop->mo_device_sz == 0) { + if (mop->mo_device_kb == 0) { fatal(); fprintf(stderr, "Unable to create vdev due to " "missing --device-size=#N(KB) parameter\n"); return EINVAL; } - ret = file_create(vdev, mop->mo_device_sz); + ret = file_create(vdev, mop->mo_device_kb); if (ret) { fatal(); fprintf(stderr, "Unable to create vdev %s (%d)\n", @@ -441,7 +467,7 @@ int zfs_make_lustre(struct mkfs_opts *mop) goto out; } - /* Due to zfs_name_valid() check the '/' must exist */ + /* Due to zfs_prepare_lustre() check the '/' must exist */ strchr(pool, '/')[0] = '\0'; /* If --reformat was given attempt to destroy the previous dataset */ @@ -502,13 +528,12 @@ int zfs_make_lustre(struct mkfs_opts *mop) /* * Create the ZFS filesystem with any required mkfs options: * - canmount=off is set to prevent zfs automounting - * - version=4 is set because SA are not yet handled by the osd + * - 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_mkfs_opts(mop, mkfs_tmp, PATH_MAX), - ds); + zfs_mkfs_opts(mop, mkfs_tmp, PATH_MAX), ds); vprint("mkfs_cmd = %s\n", mkfs_cmd); ret = run_command(mkfs_cmd, PATH_MAX); @@ -532,22 +557,32 @@ out: return ret; } +int zfs_enable_quota(struct mkfs_opts *mop) +{ + fprintf(stderr, "this option is not only valid for zfs\n"); + return ENOSYS; +} + int zfs_prepare_lustre(struct mkfs_opts *mop, char *default_mountopts, int default_len, char *always_mountopts, int always_len) { - int ret; - if (osd_check_zfs_setup() == 0) return EINVAL; - ret = zfs_name_valid(mop->mo_device, ZFS_TYPE_FILESYSTEM); - if (!ret) { + if (zfs_name_valid(mop->mo_device, ZFS_TYPE_FILESYSTEM) == 0) { fatal(); fprintf(stderr, "Invalid filesystem name %s\n", mop->mo_device); return EINVAL; } + if (strchr(mop->mo_device, '/') == NULL) { + fatal(); + fprintf(stderr, "Missing pool in filesystem name %s\n", + mop->mo_device); + return EINVAL; + } + return 0; } @@ -585,20 +620,6 @@ int zfs_init(void) * spamming ldiskfs users. An error message will still be printed if * someone tries to do some real work involving a ZFS backend */ - handle_libzfs = dlopen("libzfs.so", RTLD_LAZY); - if (handle_libzfs == NULL) - return EINVAL; - - handle_nvpair = dlopen("libnvpair.so", RTLD_LAZY); - if (handle_nvpair == NULL) { - ret = EINVAL; - goto out; - } - - ret = zfs_populate_symbols(); - if (ret) - goto out; - if (libzfs_load_module("zfs") != 0) { /* The ZFS modules are not installed */ ret = EINVAL; @@ -623,14 +644,5 @@ void zfs_fini(void) libzfs_fini(g_zfs); g_zfs = NULL; } - if (handle_nvpair) { - dlclose(handle_nvpair); - handle_nvpair = NULL; - } - if (handle_libzfs) { - dlclose(handle_libzfs); - handle_libzfs = NULL; - } - osd_zfs_setup = 0; }