Import illumos changeset 13570:3411fd5f1589

1948 zpool list should show more detailed pool information

Display per-vdev information with "zpool list -v".
The added expandsize property has currently no value on FreeBSD.
This changeset allows adding expansion support to individual vdevs
in the future.

References:
https://www.illumos.org/issues/1948

Obtained from:	illumos (issue #1948)
MFC after:	2 weeks
This commit is contained in:
mm 2012-05-27 16:00:00 +00:00
parent a672aabea9
commit 38ef930079
17 changed files with 388 additions and 71 deletions

View File

@ -537,6 +537,8 @@ value of 1.76 indicates that 1.76 units of data were stored but only 1 unit of d
for a description of the deduplication feature.
.It Sy free
Number of blocks within the pool that are not allocated.
.It Sy expandsize
This property has currently no value on FreeBSD.
.It Sy guid
A unique identifier for the pool.
.It Sy health
@ -1275,7 +1277,7 @@ Treat exported or foreign devices as inactive.
.It Xo
.Nm
.Cm list
.Op Fl H
.Op Fl Hv
.Op Fl o Ar property Ns Op , Ns Ar ...
.Op Fl T Cm d Ns | Ns Cm u
.Op Ar pool

View File

@ -22,9 +22,9 @@
/*
* 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.
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
* Copyright (c) 2011 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
#include <solaris.h>
@ -46,6 +46,7 @@
#include <pwd.h>
#include <zone.h>
#include <sys/time.h>
#include <zfs_prop.h>
#include <sys/fs/zfs.h>
#include <sys/stat.h>
@ -70,6 +71,7 @@ static int zpool_do_status(int, char **);
static int zpool_do_online(int, char **);
static int zpool_do_offline(int, char **);
static int zpool_do_clear(int, char **);
static int zpool_do_reopen(int, char **);
static int zpool_do_reguid(int, char **);
@ -132,7 +134,8 @@ typedef enum {
HELP_GET,
HELP_SET,
HELP_SPLIT,
HELP_REGUID
HELP_REGUID,
HELP_REOPEN
} zpool_help_t;
@ -167,6 +170,7 @@ static zpool_command_t command_table[] = {
{ "online", zpool_do_online, HELP_ONLINE },
{ "offline", zpool_do_offline, HELP_OFFLINE },
{ "clear", zpool_do_clear, HELP_CLEAR },
{ "reopen", zpool_do_reopen, HELP_REOPEN },
{ NULL },
{ "attach", zpool_do_attach, HELP_ATTACH },
{ "detach", zpool_do_detach, HELP_DETACH },
@ -241,6 +245,8 @@ get_usage(zpool_help_t idx) {
"[new-device]\n"));
case HELP_REMOVE:
return (gettext("\tremove <pool> <device> ...\n"));
case HELP_REOPEN:
return (""); /* Undocumented command */
case HELP_SCRUB:
return (gettext("\tscrub [-s] <pool> ...\n"));
case HELP_STATUS:
@ -2109,10 +2115,10 @@ zpool_do_import(int argc, char **argv)
}
typedef struct iostat_cbdata {
zpool_list_t *cb_list;
int cb_verbose;
int cb_iteration;
boolean_t cb_verbose;
int cb_namewidth;
int cb_iteration;
zpool_list_t *cb_list;
} iostat_cbdata_t;
static void
@ -2582,8 +2588,9 @@ zpool_do_iostat(int argc, char **argv)
}
typedef struct list_cbdata {
boolean_t cb_verbose;
int cb_namewidth;
boolean_t cb_scripted;
boolean_t cb_first;
zprop_list_t *cb_proplist;
} list_cbdata_t;
@ -2591,16 +2598,27 @@ typedef struct list_cbdata {
* Given a list of columns to display, output appropriate headers for each one.
*/
static void
print_header(zprop_list_t *pl)
print_header(list_cbdata_t *cb)
{
zprop_list_t *pl = cb->cb_proplist;
const char *header;
boolean_t first = B_TRUE;
boolean_t right_justify;
size_t width = 0;
for (; pl != NULL; pl = pl->pl_next) {
if (pl->pl_prop == ZPROP_INVAL)
continue;
width = pl->pl_width;
if (first && cb->cb_verbose) {
/*
* Reset the width to accommodate the verbose listing
* of devices.
*/
width = cb->cb_namewidth;
}
if (!first)
(void) printf(" ");
else
@ -2612,9 +2630,10 @@ print_header(zprop_list_t *pl)
if (pl->pl_next == NULL && !right_justify)
(void) printf("%s", header);
else if (right_justify)
(void) printf("%*s", pl->pl_width, header);
(void) printf("%*s", width, header);
else
(void) printf("%-*s", pl->pl_width, header);
(void) printf("%-*s", width, header);
}
(void) printf("\n");
@ -2625,17 +2644,28 @@ print_header(zprop_list_t *pl)
* to the described layout.
*/
static void
print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
{
zprop_list_t *pl = cb->cb_proplist;
boolean_t first = B_TRUE;
char property[ZPOOL_MAXPROPLEN];
char *propstr;
boolean_t right_justify;
int width;
size_t width;
for (; pl != NULL; pl = pl->pl_next) {
width = pl->pl_width;
if (first && cb->cb_verbose) {
/*
* Reset the width to accommodate the verbose listing
* of devices.
*/
width = cb->cb_namewidth;
}
if (!first) {
if (scripted)
if (cb->cb_scripted)
(void) printf("\t");
else
(void) printf(" ");
@ -2645,7 +2675,10 @@ print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
right_justify = B_FALSE;
if (pl->pl_prop != ZPROP_INVAL) {
if (zpool_get_prop(zhp, pl->pl_prop, property,
if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ &&
zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0)
propstr = "-";
else if (zpool_get_prop(zhp, pl->pl_prop, property,
sizeof (property), NULL) != 0)
propstr = "-";
else
@ -2656,14 +2689,13 @@ print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
propstr = "-";
}
width = pl->pl_width;
/*
* If this is being called in scripted mode, or if this is the
* last column and it is left-justified, don't include a width
* format specifier.
*/
if (scripted || (pl->pl_next == NULL && !right_justify))
if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
(void) printf("%s", propstr);
else if (right_justify)
(void) printf("%*s", width, propstr);
@ -2674,6 +2706,101 @@ print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
(void) printf("\n");
}
static void
print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted)
{
char propval[64];
boolean_t fixed;
size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
zfs_nicenum(value, propval, sizeof (propval));
if (prop == ZPOOL_PROP_EXPANDSZ && value == 0)
(void) strlcpy(propval, "-", sizeof (propval));
if (scripted)
(void) printf("\t%s", propval);
else
(void) printf(" %*s", width, propval);
}
void
print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
list_cbdata_t *cb, int depth)
{
nvlist_t **child;
vdev_stat_t *vs;
uint_t c, children;
char *vname;
boolean_t scripted = cb->cb_scripted;
verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
if (name != NULL) {
if (scripted)
(void) printf("\t%s", name);
else if (strlen(name) + depth > cb->cb_namewidth)
(void) printf("%*s%s", depth, "", name);
else
(void) printf("%*s%s%*s", depth, "", name,
(int)(cb->cb_namewidth - strlen(name) - depth), "");
/* only toplevel vdevs have capacity stats */
if (vs->vs_space == 0) {
if (scripted)
(void) printf("\t-\t-\t-");
else
(void) printf(" - - -");
} else {
print_one_column(ZPOOL_PROP_SIZE, vs->vs_space,
scripted);
print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc,
scripted);
print_one_column(ZPOOL_PROP_FREE,
vs->vs_space - vs->vs_alloc, scripted);
}
print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize,
scripted);
(void) printf("\n");
}
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
&child, &children) != 0)
return;
for (c = 0; c < children; c++) {
uint64_t ishole = B_FALSE;
if (nvlist_lookup_uint64(child[c],
ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
continue;
vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
/*
* Include level 2 ARC devices in iostat output
*/
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) != 0)
return;
if (children > 0) {
(void) printf("%-*s - - - - - "
"-\n", cb->cb_namewidth, "cache");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, child[c],
B_FALSE);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
}
}
/*
* Generic callback function to list a pool.
*/
@ -2681,14 +2808,18 @@ int
list_callback(zpool_handle_t *zhp, void *data)
{
list_cbdata_t *cbp = data;
nvlist_t *config;
nvlist_t *nvroot;
if (cbp->cb_first) {
if (!cbp->cb_scripted)
print_header(cbp->cb_proplist);
cbp->cb_first = B_FALSE;
}
config = zpool_get_config(zhp, NULL);
print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
print_pool(zhp, cbp);
if (!cbp->cb_verbose)
return (0);
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0);
print_list_stats(zhp, NULL, nvroot, cbp, 0);
return (0);
}
@ -2712,12 +2843,15 @@ zpool_do_list(int argc, char **argv)
int ret;
list_cbdata_t cb = { 0 };
static char default_props[] =
"name,size,allocated,free,capacity,dedupratio,health,altroot";
"name,size,allocated,free,capacity,dedupratio,"
"health,altroot";
char *props = default_props;
unsigned long interval = 0, count = 0;
zpool_list_t *list;
boolean_t first = B_TRUE;
/* check options */
while ((c = getopt(argc, argv, ":Ho:T:")) != -1) {
while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
switch (c) {
case 'H':
cb.cb_scripted = B_TRUE;
@ -2728,6 +2862,9 @@ zpool_do_list(int argc, char **argv)
case 'T':
get_timestamp_arg(*optarg);
break;
case 'v':
cb.cb_verbose = B_TRUE;
break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@ -2748,21 +2885,32 @@ zpool_do_list(int argc, char **argv)
if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
usage(B_FALSE);
cb.cb_first = B_TRUE;
if ((list = pool_list_get(argc, argv, &cb.cb_proplist, &ret)) == NULL)
return (1);
if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
(void) printf(gettext("no pools available\n"));
zprop_free_list(cb.cb_proplist);
return (0);
}
for (;;) {
pool_list_update(list);
if (pool_list_count(list) == 0)
break;
cb.cb_namewidth = 0;
(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
if (timestamp_fmt != NODATE)
print_timestamp(timestamp_fmt);
ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
list_callback, &cb);
if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
(void) printf(gettext("no pools available\n"));
zprop_free_list(cb.cb_proplist);
return (0);
if (!cb.cb_scripted && (first || cb.cb_verbose)) {
print_header(&cb);
first = B_FALSE;
}
ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
if (interval == 0)
break;
@ -3382,6 +3530,36 @@ zpool_do_reguid(int argc, char **argv)
}
/*
* zpool reopen <pool>
*
* Reopen the pool so that the kernel can update the sizes of all vdevs.
*
* NOTE: This command is currently undocumented. If the command is ever
* exposed then the appropriate usage() messages will need to be made.
*/
int
zpool_do_reopen(int argc, char **argv)
{
int ret = 0;
zpool_handle_t *zhp;
char *pool;
argc--;
argv++;
if (argc != 1)
return (2);
pool = argv[0];
if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
return (1);
ret = zpool_reopen(zhp);
zpool_close(zhp);
return (ret);
}
typedef struct scrub_cbdata {
int cb_type;
int cb_argc;

View File

@ -24,7 +24,7 @@
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* 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.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
@ -237,6 +237,7 @@ typedef struct splitflags {
extern int zpool_scan(zpool_handle_t *, pool_scan_func_t);
extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
extern int zpool_reguid(zpool_handle_t *);
extern int zpool_reopen(zpool_handle_t *);
extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
vdev_state_t *);

View File

@ -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/types.h>
@ -301,6 +301,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case ZPOOL_PROP_SIZE:
case ZPOOL_PROP_ALLOCATED:
case ZPOOL_PROP_FREE:
case ZPOOL_PROP_EXPANDSZ:
(void) zfs_nicenum(intval, buf, len);
break;
@ -390,8 +391,8 @@ pool_uses_efi(nvlist_t *config)
return (B_FALSE);
}
static boolean_t
pool_is_bootable(zpool_handle_t *zhp)
boolean_t
zpool_is_bootable(zpool_handle_t *zhp)
{
char bootfs[ZPOOL_MAXNAMELEN];
@ -1126,7 +1127,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
return (zfs_error(hdl, EZFS_BADVERSION, msg));
}
if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
uint64_t s;
@ -2412,7 +2413,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
uint_t children;
nvlist_t *config_root;
libzfs_handle_t *hdl = zhp->zpool_hdl;
boolean_t rootpool = pool_is_bootable(zhp);
boolean_t rootpool = zpool_is_bootable(zhp);
if (replacing)
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@ -3053,6 +3054,26 @@ zpool_reguid(zpool_handle_t *zhp)
return (zpool_standard_error(hdl, errno, msg));
}
/*
* Reopen the pool.
*/
int
zpool_reopen(zpool_handle_t *zhp)
{
zfs_cmd_t zc = { 0 };
char msg[1024];
libzfs_handle_t *hdl = zhp->zpool_hdl;
(void) snprintf(msg, sizeof (msg),
dgettext(TEXT_DOMAIN, "cannot reopen '%s'"),
zhp->zpool_name);
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0)
return (0);
return (zpool_standard_error(hdl, errno, msg));
}
/*
* Convert from a devid string to a path.
*/
@ -3703,7 +3724,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
if (zhp) {
nvlist_t *nvroot;
if (pool_is_bootable(zhp)) {
if (zpool_is_bootable(zhp)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"EFI labeled devices are not supported on root "
"pools."));

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 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/zio.h>
@ -81,6 +81,8 @@ zpool_prop_init(void)
ZFS_TYPE_POOL, "<size>", "FREE");
zprop_register_number(ZPOOL_PROP_ALLOCATED, "allocated", 0,
PROP_READONLY, ZFS_TYPE_POOL, "<size>", "ALLOC");
zprop_register_number(ZPOOL_PROP_EXPANDSZ, "expandsize", 0,
PROP_READONLY, ZFS_TYPE_POOL, "<size>", "EXPANDSZ");
zprop_register_number(ZPOOL_PROP_CAPACITY, "capacity", 0, PROP_READONLY,
ZFS_TYPE_POOL, "<size>", "CAP");
zprop_register_number(ZPOOL_PROP_GUID, "guid", 0, PROP_READONLY,

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@ -175,15 +175,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);
@ -191,6 +193,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);
@ -201,7 +212,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))

View File

@ -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);
@ -118,6 +120,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 */

View File

@ -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>
@ -119,7 +119,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)
@ -748,6 +748,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;
@ -1119,7 +1120,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 ||
@ -1150,7 +1152,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
@ -1208,6 +1210,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) {
@ -1217,6 +1220,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)) {
@ -1226,6 +1231,7 @@ vdev_open(vdev_t *vd)
}
psize = 0;
asize = osize;
max_asize = max_osize;
}
vd->vdev_psize = psize;
@ -1245,6 +1251,7 @@ 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 {
/*
@ -1255,6 +1262,7 @@ vdev_open(vdev_t *vd)
VDEV_AUX_BAD_LABEL);
return (EINVAL);
}
vd->vdev_max_asize = max_asize;
}
/*
@ -2478,6 +2486,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);
/*

View File

@ -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>
@ -30,6 +31,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>
/*
@ -102,8 +104,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;
@ -273,16 +306,6 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
return (EINVAL);
}
/*
* 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.
@ -293,6 +316,25 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
*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.

View File

@ -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;
@ -125,7 +127,7 @@ vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
return (error);
}
*psize = vattr.va_size;
*max_psize = *psize = vattr.va_size;
*ashift = SPA_MINBLOCKSHIFT;
return (0);

View File

@ -21,6 +21,8 @@
/*
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Portions Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>
*/
#include <sys/zfs_context.h>
@ -405,7 +407,8 @@ vdev_geom_open_by_path(vdev_t *vd, int check_guid)
}
static int
vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
uint64_t *ashift)
{
struct g_provider *pp;
struct g_consumer *cp;
@ -488,7 +491,7 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
/*
* Determine the actual size of the device.
*/
*psize = pp->mediasize;
*max_psize = *psize = pp->mediasize;
/*
* Determine the device's minimum transfer size.

View File

@ -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);
}

View File

@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
/*
* 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
@ -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);
}

View File

@ -21,6 +21,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>
@ -1441,7 +1442,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;
@ -1469,10 +1471,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;

View File

@ -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);

View File

@ -24,7 +24,7 @@
* All rights reserved.
* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
* 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.
*/
@ -4125,6 +4125,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
@ -4994,7 +5010,9 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = {
{ zfs_ioc_space_snaps, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
B_TRUE },
{ zfs_ioc_send_progress, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
B_FALSE }
B_FALSE },
{ zfs_ioc_pool_reopen, zfs_secpolicy_config, POOL_NAME, B_TRUE,
B_TRUE },
};
int

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>. All rights reserved.
@ -171,6 +171,7 @@ typedef enum {
ZPOOL_PROP_ALLOCATED,
ZPOOL_PROP_READONLY,
ZPOOL_PROP_COMMENT,
ZPOOL_PROP_EXPANDSZ,
ZPOOL_NUM_PROPS
} zpool_prop_t;
@ -675,6 +676,7 @@ typedef struct vdev_stat {
uint64_t vs_space; /* total capacity */
uint64_t vs_dspace; /* deflated capacity */
uint64_t vs_rsize; /* replaceable dev size */
uint64_t vs_esize; /* expandable dev size */
uint64_t vs_ops[ZIO_TYPES]; /* operation count */
uint64_t vs_bytes[ZIO_TYPES]; /* bytes read/written */
uint64_t vs_read_errors; /* read errors */
@ -797,6 +799,7 @@ typedef unsigned long zfs_ioc_t;
#define ZFS_IOC_SPACE_WRITTEN _IOWR('Z', 61, struct zfs_cmd)
#define ZFS_IOC_SPACE_SNAPS _IOWR('Z', 62, struct zfs_cmd)
#define ZFS_IOC_SEND_PROGRESS _IOWR('Z', 63, struct zfs_cmd)
#define ZFS_IOC_POOL_REOPEN _IOWR('Z', 64, struct zfs_cmd)
/*
* Internal SPA load state. Used by FMA diagnosis engine.