diff options
Diffstat (limited to 'usr/src/uts/common/fs/zfs')
-rw-r--r-- | usr/src/uts/common/fs/zfs/spa.c | 17 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/vdev_impl.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev.c | 31 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_disk.c | 64 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_file.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_mirror.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_missing.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_raidz.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_root.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ioctl.c | 22 |
10 files changed, 143 insertions, 32 deletions
diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index ed0d0cb36f..a4c61fc947 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ /* @@ -167,15 +167,17 @@ spa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval, static void spa_prop_get_config(spa_t *spa, nvlist_t **nvp) { + vdev_t *rvd = spa->spa_root_vdev; uint64_t size; uint64_t alloc; + uint64_t space; uint64_t cap, version; zprop_source_t src = ZPROP_SRC_NONE; spa_config_dirent_t *dp; ASSERT(MUTEX_HELD(&spa->spa_props_lock)); - if (spa->spa_root_vdev != NULL) { + if (rvd != NULL) { alloc = metaslab_class_get_alloc(spa_normal_class(spa)); size = metaslab_class_get_space(spa_normal_class(spa)); spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src); @@ -183,6 +185,15 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src); spa_prop_add_list(*nvp, ZPOOL_PROP_FREE, NULL, size - alloc, src); + + space = 0; + for (int c = 0; c < rvd->vdev_children; c++) { + vdev_t *tvd = rvd->vdev_child[c]; + space += tvd->vdev_max_asize - tvd->vdev_asize; + } + spa_prop_add_list(*nvp, ZPOOL_PROP_EXPANDSZ, NULL, space, + src); + spa_prop_add_list(*nvp, ZPOOL_PROP_READONLY, NULL, (spa_mode(spa) == FREAD), src); @@ -193,7 +204,7 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) ddt_get_pool_dedup_ratio(spa), src); spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL, - spa->spa_root_vdev->vdev_state, src); + rvd->vdev_state, src); version = spa_version(spa); if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION)) diff --git a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h index c297ae165c..3a2d7a04d8 100644 --- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_VDEV_IMPL_H @@ -55,7 +56,8 @@ typedef struct vdev_cache_entry vdev_cache_entry_t; /* * Virtual device operations */ -typedef int vdev_open_func_t(vdev_t *vd, uint64_t *size, uint64_t *ashift); +typedef int vdev_open_func_t(vdev_t *vd, uint64_t *size, uint64_t *max_size, + uint64_t *ashift); typedef void vdev_close_func_t(vdev_t *vd); typedef uint64_t vdev_asize_func_t(vdev_t *vd, uint64_t psize); typedef int vdev_io_start_func_t(zio_t *zio); @@ -119,6 +121,7 @@ struct vdev { uint64_t vdev_orig_guid; /* orig. guid prior to remove */ uint64_t vdev_asize; /* allocatable device capacity */ uint64_t vdev_min_asize; /* min acceptable asize */ + uint64_t vdev_max_asize; /* max acceptable asize */ uint64_t vdev_ashift; /* block alignment shift */ uint64_t vdev_state; /* see VDEV_STATE_* #defines */ uint64_t vdev_prevstate; /* used when reopening a vdev */ diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index 1af113e2e0..6606b1f486 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -108,7 +108,7 @@ vdev_get_min_asize(vdev_t *vd) vdev_t *pvd = vd->vdev_parent; /* - * The our parent is NULL (inactive spare or cache) or is the root, + * If our parent is NULL (inactive spare or cache) or is the root, * just return our own asize. */ if (pvd == NULL) @@ -737,6 +737,7 @@ vdev_add_parent(vdev_t *cvd, vdev_ops_t *ops) mvd->vdev_asize = cvd->vdev_asize; mvd->vdev_min_asize = cvd->vdev_min_asize; + mvd->vdev_max_asize = cvd->vdev_max_asize; mvd->vdev_ashift = cvd->vdev_ashift; mvd->vdev_state = cvd->vdev_state; mvd->vdev_crtxg = cvd->vdev_crtxg; @@ -1108,7 +1109,8 @@ vdev_open(vdev_t *vd) spa_t *spa = vd->vdev_spa; int error; uint64_t osize = 0; - uint64_t asize, psize; + uint64_t max_osize = 0; + uint64_t asize, max_asize, psize; uint64_t ashift = 0; ASSERT(vd->vdev_open_thread == curthread || @@ -1139,7 +1141,7 @@ vdev_open(vdev_t *vd) return (ENXIO); } - error = vd->vdev_ops->vdev_op_open(vd, &osize, &ashift); + error = vd->vdev_ops->vdev_op_open(vd, &osize, &max_osize, &ashift); /* * Reset the vdev_reopening flag so that we actually close @@ -1197,6 +1199,7 @@ vdev_open(vdev_t *vd) } osize = P2ALIGN(osize, (uint64_t)sizeof (vdev_label_t)); + max_osize = P2ALIGN(max_osize, (uint64_t)sizeof (vdev_label_t)); if (vd->vdev_children == 0) { if (osize < SPA_MINDEVSIZE) { @@ -1206,6 +1209,8 @@ vdev_open(vdev_t *vd) } psize = osize; asize = osize - (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE); + max_asize = max_osize - (VDEV_LABEL_START_SIZE + + VDEV_LABEL_END_SIZE); } else { if (vd->vdev_parent != NULL && osize < SPA_MINDEVSIZE - (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE)) { @@ -1215,6 +1220,7 @@ vdev_open(vdev_t *vd) } psize = 0; asize = osize; + max_asize = max_osize; } vd->vdev_psize = psize; @@ -1234,16 +1240,22 @@ vdev_open(vdev_t *vd) * For testing purposes, a higher ashift can be requested. */ vd->vdev_asize = asize; + vd->vdev_max_asize = max_asize; vd->vdev_ashift = MAX(ashift, vd->vdev_ashift); } else { /* - * Make sure the alignment requirement hasn't increased. + * Detect if the alignment requirement has increased. + * We don't want to make the pool unavailable, just + * issue a warning instead. */ - if (ashift > vd->vdev_top->vdev_ashift) { - vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN, - VDEV_AUX_BAD_LABEL); - return (EINVAL); + if (ashift > vd->vdev_top->vdev_ashift && + vd->vdev_ops->vdev_op_leaf) { + cmn_err(CE_WARN, + "Disk, '%s', has a block alignment that is " + "larger than the pool's alignment\n", + vd->vdev_path); } + vd->vdev_max_asize = max_asize; } /* @@ -2467,6 +2479,7 @@ vdev_get_stats(vdev_t *vd, vdev_stat_t *vs) vs->vs_rsize = vdev_get_min_asize(vd); if (vd->vdev_ops->vdev_op_leaf) vs->vs_rsize += VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE; + vs->vs_esize = vd->vdev_max_asize - vd->vdev_asize; mutex_exit(&vd->vdev_stat_lock); /* diff --git a/usr/src/uts/common/fs/zfs/vdev_disk.c b/usr/src/uts/common/fs/zfs/vdev_disk.c index f78580d0f1..49e425929f 100644 --- a/usr/src/uts/common/fs/zfs/vdev_disk.c +++ b/usr/src/uts/common/fs/zfs/vdev_disk.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -32,6 +33,7 @@ #include <sys/fs/zfs.h> #include <sys/zio.h> #include <sys/sunldi.h> +#include <sys/efi_partition.h> #include <sys/fm/fs/zfs.h> /* @@ -104,8 +106,39 @@ vdev_disk_rele(vdev_t *vd) } } +static uint64_t +vdev_disk_get_space(vdev_t *vd, uint64_t capacity, uint_t blksz) +{ + ASSERT(vd->vdev_wholedisk); + + vdev_disk_t *dvd = vd->vdev_tsd; + dk_efi_t dk_ioc; + efi_gpt_t *efi; + uint64_t avail_space = 0; + int efisize = EFI_LABEL_SIZE * 2; + + dk_ioc.dki_data = kmem_alloc(efisize, KM_SLEEP); + dk_ioc.dki_lba = 1; + dk_ioc.dki_length = efisize; + dk_ioc.dki_data_64 = (uint64_t)(uintptr_t)dk_ioc.dki_data; + efi = dk_ioc.dki_data; + + if (ldi_ioctl(dvd->vd_lh, DKIOCGETEFI, (intptr_t)&dk_ioc, + FKIOCTL, kcred, NULL) == 0) { + uint64_t efi_altern_lba = LE_64(efi->efi_gpt_AlternateLBA); + + zfs_dbgmsg("vdev %s, capacity %llu, altern lba %llu", + vd->vdev_path, capacity, efi_altern_lba); + if (capacity > efi_altern_lba) + avail_space = (capacity - efi_altern_lba) * blksz; + } + kmem_free(dk_ioc.dki_data, efisize); + return (avail_space); +} + static int -vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) +vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, + uint64_t *ashift) { spa_t *spa = vd->vdev_spa; vdev_disk_t *dvd; @@ -276,16 +309,6 @@ skip_open: } /* - * If we own the whole disk, try to enable disk write caching. - * We ignore errors because it's OK if we can't do it. - */ - if (vd->vdev_wholedisk == 1) { - int wce = 1; - (void) ldi_ioctl(dvd->vd_lh, DKIOCSETWCE, (intptr_t)&wce, - FKIOCTL, kcred, NULL); - } - - /* * Determine the device's minimum transfer size. * If the ioctl isn't supported, assume DEV_BSIZE. */ @@ -295,6 +318,25 @@ skip_open: *ashift = highbit(MAX(dkmext.dki_pbsize, SPA_MINBLOCKSIZE)) - 1; + if (vd->vdev_wholedisk == 1) { + uint64_t capacity = dkmext.dki_capacity - 1; + uint64_t blksz = dkmext.dki_lbsize; + int wce = 1; + + /* + * If we own the whole disk, try to enable disk write caching. + * We ignore errors because it's OK if we can't do it. + */ + (void) ldi_ioctl(dvd->vd_lh, DKIOCSETWCE, (intptr_t)&wce, + FKIOCTL, kcred, NULL); + + *max_psize = *psize + vdev_disk_get_space(vd, capacity, blksz); + zfs_dbgmsg("capacity change: vdev %s, psize %llu, " + "max_psize %llu", vd->vdev_path, *psize, *max_psize); + } else { + *max_psize = *psize; + } + /* * Clear the nowritecache bit, so that on a vdev_reopen() we will * try again. diff --git a/usr/src/uts/common/fs/zfs/vdev_file.c b/usr/src/uts/common/fs/zfs/vdev_file.c index 8c22aa5316..043fa51294 100644 --- a/usr/src/uts/common/fs/zfs/vdev_file.c +++ b/usr/src/uts/common/fs/zfs/vdev_file.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -47,7 +48,8 @@ vdev_file_rele(vdev_t *vd) } static int -vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) +vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, + uint64_t *ashift) { vdev_file_t *vf; vnode_t *vp; @@ -112,7 +114,7 @@ skip_open: return (error); } - *psize = vattr.va_size; + *max_psize = *psize = vattr.va_size; *ashift = SPA_MINBLOCKSHIFT; return (0); diff --git a/usr/src/uts/common/fs/zfs/vdev_mirror.c b/usr/src/uts/common/fs/zfs/vdev_mirror.c index 698c0275d3..a28ca3e396 100644 --- a/usr/src/uts/common/fs/zfs/vdev_mirror.c +++ b/usr/src/uts/common/fs/zfs/vdev_mirror.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + #include <sys/zfs_context.h> #include <sys/spa.h> #include <sys/vdev_impl.h> @@ -127,7 +131,8 @@ vdev_mirror_map_alloc(zio_t *zio) } static int -vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) +vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize, + uint64_t *ashift) { int numerrors = 0; int lasterror = 0; @@ -149,6 +154,7 @@ vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) } *asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1; + *max_asize = MIN(*max_asize - 1, cvd->vdev_max_asize - 1) + 1; *ashift = MAX(*ashift, cvd->vdev_ashift); } diff --git a/usr/src/uts/common/fs/zfs/vdev_missing.c b/usr/src/uts/common/fs/zfs/vdev_missing.c index 6a5588d592..3bd8c90e04 100644 --- a/usr/src/uts/common/fs/zfs/vdev_missing.c +++ b/usr/src/uts/common/fs/zfs/vdev_missing.c @@ -24,6 +24,10 @@ */ /* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + +/* * The 'missing' vdev is a special vdev type used only during import. It * signifies a placeholder in the root vdev for some vdev that we know is * missing. We pass it down to the kernel to allow the rest of the @@ -40,7 +44,8 @@ /* ARGSUSED */ static int -vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) +vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, + uint64_t *ashift) { /* * Really this should just fail. But then the root vdev will be in the @@ -49,6 +54,7 @@ vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) * will fail the GUID sum check before ever trying to open the pool. */ *psize = 0; + *max_psize = 0; *ashift = 0; return (0); } diff --git a/usr/src/uts/common/fs/zfs/vdev_raidz.c b/usr/src/uts/common/fs/zfs/vdev_raidz.c index 6094e01876..3ac3d3b167 100644 --- a/usr/src/uts/common/fs/zfs/vdev_raidz.c +++ b/usr/src/uts/common/fs/zfs/vdev_raidz.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Joyent, Inc. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -1445,7 +1446,8 @@ vdev_raidz_reconstruct(raidz_map_t *rm, int *t, int nt) } static int -vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) +vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize, + uint64_t *ashift) { vdev_t *cvd; uint64_t nparity = vd->vdev_nparity; @@ -1473,10 +1475,12 @@ vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) } *asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1; + *max_asize = MIN(*max_asize - 1, cvd->vdev_max_asize - 1) + 1; *ashift = MAX(*ashift, cvd->vdev_ashift); } *asize *= vd->vdev_children; + *max_asize *= vd->vdev_children; if (numerrors > nparity) { vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS; diff --git a/usr/src/uts/common/fs/zfs/vdev_root.c b/usr/src/uts/common/fs/zfs/vdev_root.c index 879f78f3a5..1abc79d330 100644 --- a/usr/src/uts/common/fs/zfs/vdev_root.c +++ b/usr/src/uts/common/fs/zfs/vdev_root.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + #include <sys/zfs_context.h> #include <sys/spa.h> #include <sys/vdev_impl.h> @@ -50,7 +54,8 @@ too_many_errors(vdev_t *vd, int numerrors) } static int -vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) +vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize, + uint64_t *ashift) { int lasterror = 0; int numerrors = 0; @@ -77,6 +82,7 @@ vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) } *asize = 0; + *max_asize = 0; *ashift = 0; return (0); diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index baffc223a3..f2bf4fc98f 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -22,7 +22,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Portions Copyright 2011 Martin Matuska * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ @@ -4066,6 +4066,22 @@ zfs_ioc_clear(zfs_cmd_t *zc) return (error); } +static int +zfs_ioc_pool_reopen(zfs_cmd_t *zc) +{ + spa_t *spa; + int error; + + error = spa_open(zc->zc_name, &spa, FTAG); + if (error) + return (error); + + spa_vdev_state_enter(spa, SCL_NONE); + vdev_reopen(spa->spa_root_vdev); + (void) spa_vdev_state_exit(spa, NULL, 0); + spa_close(spa, FTAG); + return (0); +} /* * inputs: * zc_name name of filesystem @@ -4910,7 +4926,9 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = { { zfs_ioc_destroy_snaps_nvl, zfs_secpolicy_destroy_recursive, DATASET_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_pool_reguid, zfs_secpolicy_config, POOL_NAME, B_TRUE, - POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY } + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_pool_reopen, zfs_secpolicy_config, POOL_NAME, B_TRUE, + POOL_CHECK_SUSPENDED }, }; int |