diff options
author | gw25295 <none@none> | 2008-07-07 10:11:14 -0700 |
---|---|---|
committer | gw25295 <none@none> | 2008-07-07 10:11:14 -0700 |
commit | 15e6edf145a9c2bb0e0272cf8debe823bb97529b (patch) | |
tree | a53f47c7441c48d1296ddc5dbf37e0f189969e90 /usr/src/lib/libzfs/common/libzfs_pool.c | |
parent | 0430f8daa551890e0788d3fd28aef3be44cf8730 (diff) | |
download | illumos-joyent-15e6edf145a9c2bb0e0272cf8debe823bb97529b.tar.gz |
6721094 Setting certain properties on root pools should not be allowed
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_pool.c')
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_pool.c | 99 |
1 files changed, 81 insertions, 18 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c index 00df5ca616..ec2102a05b 100644 --- a/usr/src/lib/libzfs/common/libzfs_pool.c +++ b/usr/src/lib/libzfs/common/libzfs_pool.c @@ -48,6 +48,7 @@ #include "zfs_prop.h" #include "libzfs_impl.h" +static int read_efi_label(nvlist_t *config, diskaddr_t *sb); /* * ==================================================================== @@ -284,6 +285,27 @@ bootfs_name_valid(const char *pool, char *bootfs) } /* + * Inspect the configuration to determine if any of the devices contain + * an EFI label. + */ +static boolean_t +pool_uses_efi(nvlist_t *config) +{ + nvlist_t **child; + uint_t c, children; + + if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, + &child, &children) != 0) + return (read_efi_label(config, NULL) >= 0); + + for (c = 0; c < children; c++) { + if (pool_uses_efi(child[c])) + return (B_TRUE); + } + return (B_FALSE); +} + +/* * Given an nvlist of zpool properties to be set, validate that they are * correct, and parse any numeric properties (index, boolean, etc) if they are * specified as strings. @@ -299,6 +321,8 @@ zpool_validate_properties(libzfs_handle_t *hdl, const char *poolname, uint64_t intval; char *slash; struct stat64 statbuf; + zpool_handle_t *zhp; + nvlist_t *nvroot; if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { (void) no_memory(hdl); @@ -372,6 +396,29 @@ zpool_validate_properties(libzfs_handle_t *hdl, const char *poolname, (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); goto error; } + + if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "could not open pool '%s'"), poolname); + (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); + goto error; + } + verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), + ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); + + /* + * bootfs property cannot be set on a disk which has + * been EFI labeled. + */ + if (pool_uses_efi(nvroot)) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "property '%s' not supported on " + "EFI labeled devices"), propname); + (void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf); + zpool_close(zhp); + goto error; + } + zpool_close(zhp); break; case ZPOOL_PROP_ALTROOT: @@ -2502,6 +2549,38 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, #define NEW_START_BLOCK 256 /* + * Read the EFI label from the config, if a label does not exist then + * pass back the error to the caller. If the caller has passed a non-NULL + * diskaddr argument then we set it to the starting address of the EFI + * partition. + */ +static int +read_efi_label(nvlist_t *config, diskaddr_t *sb) +{ + char *path; + int fd; + char diskname[MAXPATHLEN]; + int err = -1; + + if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0) + return (err); + + (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT, + strrchr(path, '/')); + if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { + struct dk_gpt *vtoc; + + if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) { + if (sb != NULL) + *sb = vtoc->efi_parts[0].p_start; + efi_free(vtoc); + } + (void) close(fd); + } + return (err); +} + +/* * determine where a partition starts on a disk in the current * configuration */ @@ -2510,10 +2589,7 @@ find_start_block(nvlist_t *config) { nvlist_t **child; uint_t c, children; - char *path; diskaddr_t sb = MAXOFFSET_T; - int fd; - char diskname[MAXPATHLEN]; uint64_t wholedisk; if (nvlist_lookup_nvlist_array(config, @@ -2523,21 +2599,8 @@ find_start_block(nvlist_t *config) &wholedisk) != 0 || !wholedisk) { return (MAXOFFSET_T); } - if (nvlist_lookup_string(config, - ZPOOL_CONFIG_PATH, &path) != 0) { - return (MAXOFFSET_T); - } - - (void) snprintf(diskname, sizeof (diskname), "%s%s", - RDISK_ROOT, strrchr(path, '/')); - if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { - struct dk_gpt *vtoc; - if (efi_alloc_and_read(fd, &vtoc) >= 0) { - sb = vtoc->efi_parts[0].p_start; - efi_free(vtoc); - } - (void) close(fd); - } + if (read_efi_label(config, &sb) < 0) + sb = MAXOFFSET_T; return (sb); } |