diff options
| author | eschrock <none@none> | 2006-01-30 21:34:28 -0800 |
|---|---|---|
| committer | eschrock <none@none> | 2006-01-30 21:34:28 -0800 |
| commit | c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07 (patch) | |
| tree | c677def7879e53aed9cc2dd748194594ce86aaea /usr/src | |
| parent | 6a0b2badb8e0f78966c154a45bd14bf3069c1486 (diff) | |
| download | illumos-joyent-c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07.tar.gz | |
6362672 import gets confused about overlapping slices
6364582 need to fixup paths if they've changed
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/cmd/truss/codes.c | 4 | ||||
| -rw-r--r-- | usr/src/cmd/zpool/zpool_main.c | 48 | ||||
| -rw-r--r-- | usr/src/cmd/zpool/zpool_util.c | 32 | ||||
| -rw-r--r-- | usr/src/cmd/zpool/zpool_util.h | 4 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 5 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_import.c | 54 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_pool.c | 144 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/spec/libzfs.spec | 6 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/zfs/spa.c | 29 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/zfs/sys/spa.h | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ioctl.c | 22 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/fs/zfs.h | 1 |
12 files changed, 281 insertions, 71 deletions
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c index 26e05ff875..0dc383acea 100644 --- a/usr/src/cmd/truss/codes.c +++ b/usr/src/cmd/truss/codes.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -891,6 +891,8 @@ const struct ioc { "zfs_cmd_t" }, { (uint_t)ZFS_IOC_VDEV_DETACH, "ZFS_IOC_VDEV_DETACH", "zfs_cmd_t" }, + { (uint_t)ZFS_IOC_VDEV_SETPATH, "ZFS_IOC_VDEV_SETPATH", + "zfs_cmd_t" }, { (uint_t)ZFS_IOC_OBJSET_STATS, "ZFS_IOC_OBJSET_STATS", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_DATASET_LIST_NEXT, "ZFS_IOC_DATASET_LIST_NEXT", diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c index 0d6701d7b6..808334bafe 100644 --- a/usr/src/cmd/zpool/zpool_main.c +++ b/usr/src/cmd/zpool/zpool_main.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -261,7 +261,7 @@ state_to_name(int state) } void -print_vdev_tree(const char *name, nvlist_t *nv, int indent) +print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent) { nvlist_t **child; uint_t c, children; @@ -275,8 +275,8 @@ print_vdev_tree(const char *name, nvlist_t *nv, int indent) return; for (c = 0; c < children; c++) { - vname = vdev_get_name(child[c]); - print_vdev_tree(vname, child[c], indent + 2); + vname = zpool_vdev_name(zhp, child[c]); + print_vdev_tree(zhp, vname, child[c], indent + 2); free(vname); } } @@ -364,8 +364,8 @@ zpool_do_add(int argc, char **argv) (void) printf(gettext("would update '%s' to the following " "configuration:\n"), zpool_get_name(zhp)); - print_vdev_tree(poolname, poolnvroot, 0); - print_vdev_tree(NULL, nvroot, 0); + print_vdev_tree(zhp, poolname, poolnvroot, 0); + print_vdev_tree(zhp, NULL, nvroot, 0); ret = 0; } else { @@ -527,7 +527,7 @@ zpool_do_create(int argc, char **argv) (void) printf(gettext("would create '%s' with the " "following layout:\n\n"), poolname); - print_vdev_tree(poolname, nvroot, 0); + print_vdev_tree(NULL, poolname, nvroot, 0); ret = 0; } else { @@ -691,9 +691,9 @@ zpool_do_export(int argc, char **argv) * name column. */ static int -max_width(nvlist_t *nv, int depth, int max) +max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) { - char *name = vdev_get_name(nv); + char *name = zpool_vdev_name(zhp, nv); nvlist_t **child; uint_t c, children; int ret; @@ -708,7 +708,7 @@ max_width(nvlist_t *nv, int depth, int max) return (max); for (c = 0; c < children; c++) - if ((ret = max_width(child[c], depth + 2, max)) > max) + if ((ret = max_width(zhp, child[c], depth + 2, max)) > max) max = ret; return (max); @@ -766,7 +766,7 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) return; for (c = 0; c < children; c++) { - vname = vdev_get_name(child[c]); + vname = zpool_vdev_name(NULL, child[c]); print_import_config(vname, child[c], namewidth, depth + 2); free(vname); @@ -875,7 +875,7 @@ show_import(nvlist_t *config) (void) printf(gettext("config:\n\n")); - namewidth = max_width(nvroot, 0, 0); + namewidth = max_width(NULL, nvroot, 0, 0); if (namewidth < 10) namewidth = 10; print_import_config(name, nvroot, namewidth, 0); @@ -1192,8 +1192,8 @@ print_one_stat(uint64_t value) * is a verbose output, and we don't want to display the toplevel pool stats. */ void -print_vdev_stats(const char *name, nvlist_t *oldnv, nvlist_t *newnv, - iostat_cbdata_t *cb, int depth) +print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, + nvlist_t *newnv, iostat_cbdata_t *cb, int depth) { nvlist_t **oldchild, **newchild; uint_t c, children; @@ -1260,8 +1260,8 @@ print_vdev_stats(const char *name, nvlist_t *oldnv, nvlist_t *newnv, return; for (c = 0; c < children; c++) { - vname = vdev_get_name(newchild[c]); - print_vdev_stats(vname, oldnv ? oldchild[c] : NULL, + vname = zpool_vdev_name(zhp, newchild[c]); + print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, newchild[c], cb, depth + 2); free(vname); } @@ -1308,7 +1308,7 @@ print_iostat(zpool_handle_t *zhp, void *data) /* * Print out the statistics for the pool. */ - print_vdev_stats(zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); + print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); if (cb->cb_verbose) print_iostat_separator(cb); @@ -1328,7 +1328,7 @@ get_namewidth(zpool_handle_t *zhp, void *data) if (!cb->cb_verbose) cb->cb_namewidth = strlen(zpool_get_name(zhp)); else - cb->cb_namewidth = max_width(nvroot, 0, 0); + cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); } /* @@ -2158,7 +2158,8 @@ print_scrub_status(nvlist_t *nvroot) * Print out configuration state as requested by status_callback. */ void -print_status_config(const char *name, nvlist_t *nv, int namewidth, int depth) +print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, + int namewidth, int depth) { nvlist_t **child; uint_t c, children; @@ -2214,8 +2215,8 @@ print_status_config(const char *name, nvlist_t *nv, int namewidth, int depth) (void) printf("\n"); for (c = 0; c < children; c++) { - vname = vdev_get_name(child[c]); - print_status_config(vname, child[c], + vname = zpool_vdev_name(zhp, child[c]); + print_status_config(zhp, vname, child[c], namewidth, depth + 2); free(vname); } @@ -2352,14 +2353,15 @@ status_callback(zpool_handle_t *zhp, void *data) (void) printf(gettext(" scrub: ")); print_scrub_status(nvroot); - namewidth = max_width(nvroot, 0, 0); + namewidth = max_width(zhp, nvroot, 0, 0); if (namewidth < 10) namewidth = 10; (void) printf(gettext("config:\n\n")); (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, "NAME", "STATE", "READ", "WRITE", "CKSUM"); - print_status_config(zpool_get_name(zhp), nvroot, namewidth, 0); + print_status_config(zhp, zpool_get_name(zhp), nvroot, + namewidth, 0); } else { (void) printf(gettext("config: The configuration cannot be " "determined.\n")); diff --git a/usr/src/cmd/zpool/zpool_util.c b/usr/src/cmd/zpool/zpool_util.c index 6615c36f4c..f50b0d2913 100644 --- a/usr/src/cmd/zpool/zpool_util.c +++ b/usr/src/cmd/zpool/zpool_util.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -78,33 +78,3 @@ no_memory(void) gettext("internal error: out of memory\n")); exit(1); } - -/* - * Given a vdev, return the name to display in iostat. If the vdev has a path, - * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. - * We also check if this is a whole disk, in which case we strip off the - * trailing 's0' slice name. - */ -char * -vdev_get_name(nvlist_t *nv) -{ - char *path; - uint64_t wholedisk; - - if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { - - if (strncmp(path, "/dev/dsk/", 9) == 0) - path += 9; - - if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, - &wholedisk) == 0 && wholedisk) { - char *tmp = safe_strdup(path); - tmp[strlen(path) - 2] = '\0'; - return (tmp); - } - } else { - verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); - } - - return (safe_strdup(path)); -} diff --git a/usr/src/cmd/zpool/zpool_util.h b/usr/src/cmd/zpool/zpool_util.h index 1c082a65c3..b2243e8f08 100644 --- a/usr/src/cmd/zpool/zpool_util.h +++ b/usr/src/cmd/zpool/zpool_util.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,8 +43,6 @@ void *safe_malloc(size_t); char *safe_strdup(const char *); void no_memory(void); -char *vdev_get_name(nvlist_t *nv); - /* * Virtual device functions */ diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index 7da0a674e0..0af03f460d 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -144,6 +144,11 @@ extern int zpool_import(nvlist_t *, const char *, const char *); extern nvlist_t *zpool_find_import(int argc, char **argv); /* + * Miscellaneous pool functions + */ +extern char *zpool_vdev_name(zpool_handle_t *, nvlist_t *); + +/* * Basic handle manipulations. These functions do not create or destroy the * underlying datasets, only the references to them. */ diff --git a/usr/src/lib/libzfs/common/libzfs_import.c b/usr/src/lib/libzfs/common/libzfs_import.c index 6c56a1a2da..cc86292a50 100644 --- a/usr/src/lib/libzfs/common/libzfs_import.c +++ b/usr/src/lib/libzfs/common/libzfs_import.c @@ -108,6 +108,7 @@ get_devid(const char *path) devid_str_free(minor); devid_free(devid); } + (void) close(fd); return (ret); } @@ -123,8 +124,9 @@ fix_paths(nvlist_t *nv, name_entry_t *names) nvlist_t **child; uint_t c, children; uint64_t guid; - name_entry_t *ne; - char *devid; + name_entry_t *ne, *best; + char *path, *devid; + int matched; if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0) { @@ -137,19 +139,55 @@ fix_paths(nvlist_t *nv, name_entry_t *names) * This is a leaf (file or disk) vdev. In either case, go through * the name list and see if we find a matching guid. If so, replace * the path and see if we can calculate a new devid. + * + * There may be multiple names associated with a particular guid, in + * which case we have overlapping slices or multiple paths to the same + * disk. If this is the case, then we want to pick the path that is + * the most similar to the original, where "most similar" is the number + * of matching characters starting from the end of the path. This will + * preserve slice numbers even if the disks have been reorganized, and + * will also catch preferred disk names if multiple paths exist. */ verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0); + if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0) + path = NULL; + + matched = 0; + best = NULL; + for (ne = names; ne != NULL; ne = ne->ne_next) { + if (ne->ne_guid == guid) { + const char *src, *dst; + int count; + + if (path == NULL) { + best = ne; + break; + } - for (ne = names; ne != NULL; ne = ne->ne_next) - if (ne->ne_guid == guid) - break; + src = ne->ne_name + strlen(ne->ne_name) - 1; + dst = path + strlen(path) - 1; + for (count = 0; src >= ne->ne_name && dst >= path; + src--, dst--, count++) + if (*src != *dst) + break; + + /* + * At this point, 'count' is the number of characters + * matched from the end. + */ + if (count > matched || best == NULL) { + best = ne; + matched = count; + } + } + } - if (ne == NULL) + if (best == NULL) return; - verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, ne->ne_name) == 0); + verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, best->ne_name) == 0); - if ((devid = get_devid(ne->ne_name)) == NULL) { + if ((devid = get_devid(best->ne_name)) == NULL) { (void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID); } else { verify(nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) == 0); diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c index ac6bfcc13d..5f243acfc5 100644 --- a/usr/src/lib/libzfs/common/libzfs_pool.c +++ b/usr/src/lib/libzfs/common/libzfs_pool.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1150,3 +1150,145 @@ zpool_remove_zvol_links(zpool_handle_t *zhp) zfs_close(zfp); return (ret); } + +/* + * Convert from a devid string to a path. + */ +static char * +devid_to_path(char *devid_str) +{ + ddi_devid_t devid; + char *minor; + char *path; + devid_nmlist_t *list = NULL; + int ret; + + if (devid_str_decode(devid_str, &devid, &minor) != 0) + return (NULL); + + ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); + + devid_str_free(minor); + devid_free(devid); + + if (ret != 0) + return (NULL); + + path = zfs_strdup(list[0].devname); + devid_free_nmlist(list); + + return (path); +} + +/* + * Convert from a path to a devid string. + */ +static char * +path_to_devid(const char *path) +{ + int fd; + ddi_devid_t devid; + char *minor, *ret; + + if ((fd = open(path, O_RDONLY)) < 0) + return (NULL); + + minor = NULL; + ret = NULL; + if (devid_get(fd, &devid) == 0) { + if (devid_get_minor_name(fd, &minor) == 0) + ret = devid_str_encode(devid, minor); + if (minor != NULL) + devid_str_free(minor); + devid_free(devid); + } + (void) close(fd); + + return (ret); +} + +/* + * Issue the necessary ioctl() to update the stored path value for the vdev. We + * ignore any failure here, since a common case is for an unprivileged user to + * type 'zpool status', and we'll display the correct information anyway. + */ +static void +set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) +{ + zfs_cmd_t zc = { 0 }; + + (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + (void) strncpy(zc.zc_prop_value, path, sizeof (zc.zc_prop_value)); + verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, + &zc.zc_pool_guid) == 0); + + (void) ioctl(zfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); +} + +/* + * Given a vdev, return the name to display in iostat. If the vdev has a path, + * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. + * We also check if this is a whole disk, in which case we strip off the + * trailing 's0' slice name. + * + * This routine is also responsible for identifying when disks have been + * reconfigured in a new location. The kernel will have opened the device by + * devid, but the path will still refer to the old location. To catch this, we + * first do a path -> devid translation (which is fast for the common case). If + * the devid matches, we're done. If not, we do a reverse devid -> path + * translation and issue the appropriate ioctl() to update the path of the vdev. + * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any + * of these checks. + */ +char * +zpool_vdev_name(zpool_handle_t *zhp, nvlist_t *nv) +{ + char *path, *devid; + uint64_t wholedisk; + + if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { + + if (zhp != NULL && + nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { + /* + * Determine if the current path is correct. + */ + char *newdevid = path_to_devid(path); + + if (newdevid == NULL || + strcmp(devid, newdevid) != 0) { + char *newpath; + + if ((newpath = devid_to_path(devid)) != NULL) { + /* + * Update the path appropriately. + */ + set_path(zhp, nv, newpath); + verify(nvlist_add_string(nv, + ZPOOL_CONFIG_PATH, newpath) == 0); + free(newpath); + verify(nvlist_lookup_string(nv, + ZPOOL_CONFIG_PATH, &path) == 0); + } + + if (newdevid) + devid_str_free(newdevid); + } + + } + + if (strncmp(path, "/dev/dsk/", 9) == 0) + path += 9; + + if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, + &wholedisk) == 0 && wholedisk) { + char *tmp = zfs_strdup(path); + tmp[strlen(path) - 2] = '\0'; + return (tmp); + } + } else { + verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); + } + + return (zfs_strdup(path)); +} diff --git a/usr/src/lib/libzfs/spec/libzfs.spec b/usr/src/lib/libzfs/spec/libzfs.spec index 8598c9c240..f4d10cf41e 100644 --- a/usr/src/lib/libzfs/spec/libzfs.spec +++ b/usr/src/lib/libzfs/spec/libzfs.spec @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START @@ -335,3 +335,7 @@ end function zpool_vdev_detach version SUNWprivate_1.1 end + +function zpool_vdev_name +version SUNWprivate_1.1 +end diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index b46b3b33a7..9b9bcab217 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1202,6 +1202,33 @@ spa_vdev_replace_done(spa_t *spa) } /* + * Update the stored path for this vdev. Dirty the vdev configuration, relying + * on spa_vdev_enter/exit() to synchronize the labels and cache. + */ +int +spa_vdev_setpath(spa_t *spa, uint64_t guid, const char *newpath) +{ + vdev_t *rvd, *vd; + uint64_t txg; + + rvd = spa->spa_root_vdev; + + txg = spa_vdev_enter(spa); + + if ((vd = vdev_lookup_by_guid(rvd, guid)) == NULL) + return (spa_vdev_exit(spa, NULL, txg, ENOENT)); + + spa_strfree(vd->vdev_path); + vd->vdev_path = spa_strdup(newpath); + + spa_config_set(spa, spa_config_generate(spa, rvd, txg, 0)); + + vdev_config_dirty(vd->vdev_top); + + return (spa_vdev_exit(spa, NULL, txg, 0)); +} + +/* * ========================================================================== * SPA Scrubbing * ========================================================================== diff --git a/usr/src/uts/common/fs/zfs/sys/spa.h b/usr/src/uts/common/fs/zfs/sys/spa.h index bd9493ce52..fbe2822a13 100644 --- a/usr/src/uts/common/fs/zfs/sys/spa.h +++ b/usr/src/uts/common/fs/zfs/sys/spa.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -307,6 +307,7 @@ extern int spa_vdev_attach(spa_t *spa, const char *path, nvlist_t *nvroot, extern int spa_vdev_detach(spa_t *spa, const char *path, uint64_t guid, int replace_done); extern void spa_vdev_replace_done(spa_t *spa); +extern int spa_vdev_setpath(spa_t *spa, uint64_t guid, const char *newpath); /* scrubbing */ extern int spa_scrub(spa_t *spa, pool_scrub_type_t type, boolean_t force); diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index ecd0155ee4..8c401ac2cb 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -621,6 +621,25 @@ zfs_ioc_vdev_detach(zfs_cmd_t *zc) } static int +zfs_ioc_vdev_setpath(zfs_cmd_t *zc) +{ + spa_t *spa; + char *path = zc->zc_prop_value; + uint64_t guid = zc->zc_pool_guid; + int error; + + error = spa_open(zc->zc_name, &spa, FTAG); + if (error != 0) + return (error); + + error = spa_vdev_setpath(spa, guid, path); + + spa_close(spa, FTAG); + return (error); +} + + +static int zfs_get_stats(zfs_cmd_t *zc) { char *name = zc->zc_name; @@ -1075,6 +1094,7 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = { { zfs_ioc_vdev_offline, zfs_secpolicy_config, pool_name }, { zfs_ioc_vdev_attach, zfs_secpolicy_config, pool_name }, { zfs_ioc_vdev_detach, zfs_secpolicy_config, pool_name }, + { zfs_ioc_vdev_setpath, zfs_secpolicy_config, pool_name }, { zfs_ioc_objset_stats, zfs_secpolicy_read, dataset_name }, { zfs_ioc_dataset_list_next, zfs_secpolicy_read, dataset_name }, { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, dataset_name }, diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h index cce14d4237..cc9cc359bc 100644 --- a/usr/src/uts/common/sys/fs/zfs.h +++ b/usr/src/uts/common/sys/fs/zfs.h @@ -285,6 +285,7 @@ typedef enum zfs_ioc { ZFS_IOC_VDEV_OFFLINE, ZFS_IOC_VDEV_ATTACH, ZFS_IOC_VDEV_DETACH, + ZFS_IOC_VDEV_SETPATH, ZFS_IOC_OBJSET_STATS, ZFS_IOC_DATASET_LIST_NEXT, ZFS_IOC_SNAPSHOT_LIST_NEXT, |
