diff options
Diffstat (limited to 'usr/src/lib/libzfs/common')
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 23 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_dataset.c | 7 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_pool.c | 181 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_status.c | 46 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_util.c | 5 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/mapfile-vers | 4 |
6 files changed, 206 insertions, 60 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index 4550e4a320..b23cfd239a 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -158,14 +158,20 @@ extern int zpool_add(zpool_handle_t *, nvlist_t *); * Functions to manipulate pool and vdev state */ extern int zpool_scrub(zpool_handle_t *, pool_scrub_type_t); +extern int zpool_clear(zpool_handle_t *, const char *); -extern int zpool_vdev_online(zpool_handle_t *, const char *); -extern int zpool_vdev_offline(zpool_handle_t *, const char *, int); -extern int zpool_vdev_attach(zpool_handle_t *, const char *, const char *, - nvlist_t *, int); +extern int zpool_vdev_online(zpool_handle_t *, const char *, int, + vdev_state_t *); +extern int zpool_vdev_offline(zpool_handle_t *, const char *, boolean_t); +extern int zpool_vdev_attach(zpool_handle_t *, const char *, + const char *, nvlist_t *, int); extern int zpool_vdev_detach(zpool_handle_t *, const char *); extern int zpool_vdev_remove(zpool_handle_t *, const char *); -extern int zpool_clear(zpool_handle_t *, const char *); + +extern int zpool_vdev_fault(zpool_handle_t *, uint64_t); +extern int zpool_vdev_degrade(zpool_handle_t *, uint64_t); +extern int zpool_vdev_clear(zpool_handle_t *, uint64_t); + extern nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *); extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *); @@ -173,8 +179,9 @@ extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *); * Functions to manage pool properties */ extern int zpool_set_prop(zpool_handle_t *, const char *, const char *); -extern int zpool_get_prop(zpool_handle_t *, zfs_prop_t, char *, +extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *, size_t proplen, zfs_source_t *); +extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t); extern const char *zpool_prop_to_name(zpool_prop_t); extern const char *zpool_prop_values(zpool_prop_t); @@ -197,6 +204,8 @@ typedef enum { ZPOOL_STATUS_FAILING_DEV, /* device experiencing errors */ ZPOOL_STATUS_VERSION_NEWER, /* newer on-disk version */ ZPOOL_STATUS_HOSTID_MISMATCH, /* last accessed by another system */ + ZPOOL_STATUS_FAULTED_DEV_R, /* faulted device with replicas */ + ZPOOL_STATUS_FAULTED_DEV_NR, /* faulted device with no replicas */ /* * The following are not faults per se, but still an error possibly @@ -372,7 +381,7 @@ extern int zfs_share(zfs_handle_t *); extern int zfs_unshare(zfs_handle_t *); /* - * Protocol-specifc share support functions. + * Protocol-specific share support functions. */ extern boolean_t zfs_is_shared_nfs(zfs_handle_t *, char **); extern int zfs_share_nfs(zfs_handle_t *); diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index de438079c6..3f8a377eff 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -1020,7 +1020,7 @@ zfs_validate_properties(libzfs_handle_t *hdl, zfs_type_t type, char *pool_name, break; - case ZFS_PROP_BOOTFS: + case ZPOOL_PROP_BOOTFS: /* * bootfs property value has to be a dataset name and * the dataset has to be in the same pool as it sets to. @@ -3568,7 +3568,7 @@ zfs_get_user_props(zfs_handle_t *zhp) } /* - * Given a comma-separated list of properties, contruct a property list + * Given a comma-separated list of properties, construct a property list * containing both user-defined and native properties. This function will * return a NULL list if 'all' is specified, which can later be expanded on a * per-dataset basis by zfs_expand_proplist(). @@ -3631,7 +3631,8 @@ zfs_get_proplist_common(libzfs_handle_t *hdl, char *fields, */ c = s[len]; s[len] = '\0'; - prop = zfs_name_to_prop_common(s, type); + prop = type == ZFS_TYPE_POOL ? zpool_name_to_prop(s) : + zfs_name_to_prop(s); if (prop != ZFS_PROP_INVAL && !zfs_prop_valid_for_type(prop, type)) diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c index a5e469c007..fa6cb1a8d6 100644 --- a/usr/src/lib/libzfs/common/libzfs_pool.c +++ b/usr/src/lib/libzfs/common/libzfs_pool.c @@ -862,10 +862,12 @@ is_spare(zpool_handle_t *zhp, uint64_t guid) } /* - * Bring the specified vdev online + * Bring the specified vdev online. The 'flags' parameter is a set of the + * ZFS_ONLINE_* flags. */ int -zpool_vdev_online(zpool_handle_t *zhp, const char *path) +zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, + vdev_state_t *newstate) { zfs_cmd_t zc = { 0 }; char msg[1024]; @@ -885,17 +887,22 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path) if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) return (zfs_error(hdl, EZFS_ISSPARE, msg)); - if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0) - return (0); + zc.zc_cookie = VDEV_STATE_ONLINE; + zc.zc_obj = flags; - return (zpool_standard_error(hdl, errno, msg)); + + if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) + return (zpool_standard_error(hdl, errno, msg)); + + *newstate = zc.zc_cookie; + return (0); } /* * Take the specified vdev offline */ int -zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) +zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) { zfs_cmd_t zc = { 0 }; char msg[1024]; @@ -915,9 +922,43 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) return (zfs_error(hdl, EZFS_ISSPARE, msg)); - zc.zc_cookie = istmp; + zc.zc_cookie = VDEV_STATE_OFFLINE; + zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; + + if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) + return (0); + + switch (errno) { + case EBUSY: + + /* + * There are no other replicas of this device. + */ + return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); + + default: + return (zpool_standard_error(hdl, errno, msg)); + } +} + +/* + * Mark the given vdev faulted. + */ +int +zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid) +{ + zfs_cmd_t zc = { 0 }; + char msg[1024]; + libzfs_handle_t *hdl = zhp->zpool_hdl; + + (void) snprintf(msg, sizeof (msg), + dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); - if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0) + (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + zc.zc_guid = guid; + zc.zc_cookie = VDEV_STATE_FAULTED; + + if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) return (0); switch (errno) { @@ -931,6 +972,30 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp) default: return (zpool_standard_error(hdl, errno, msg)); } + +} + +/* + * Mark the given vdev degraded. + */ +int +zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid) +{ + zfs_cmd_t zc = { 0 }; + char msg[1024]; + libzfs_handle_t *hdl = zhp->zpool_hdl; + + (void) snprintf(msg, sizeof (msg), + dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); + + (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + zc.zc_guid = guid; + zc.zc_cookie = VDEV_STATE_DEGRADED; + + if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) + return (0); + + return (zpool_standard_error(hdl, errno, msg)); } /* @@ -1232,6 +1297,29 @@ zpool_clear(zpool_handle_t *zhp, const char *path) } /* + * Similar to zpool_clear(), but takes a GUID (used by fmd). + */ +int +zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) +{ + zfs_cmd_t zc = { 0 }; + char msg[1024]; + libzfs_handle_t *hdl = zhp->zpool_hdl; + + (void) snprintf(msg, sizeof (msg), + dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), + guid); + + (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + zc.zc_guid = guid; + + if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) + return (0); + + return (zpool_standard_error(hdl, errno, msg)); +} + +/* * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> * hierarchy. */ @@ -1492,6 +1580,8 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) char *path, *devid; uint64_t value; char buf[64]; + vdev_stat_t *vs; + uint_t vsc; if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0) { @@ -1502,7 +1592,16 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) path = buf; } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { - if (zhp != NULL && + /* + * If the device is dead (faulted, offline, etc) then don't + * bother opening it. Otherwise we may be forcing the user to + * open a misbehaving device, which can have undesirable + * effects. + */ + if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, + (uint64_t **)&vs, &vsc) != 0 || + vs->vs_state >= VDEV_STATE_DEGRADED) && + zhp != NULL && nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { /* * Determine if the current path is correct. @@ -1684,7 +1783,7 @@ zpool_upgrade(zpool_handle_t *zhp) * * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE * otherwise ('zfs'). 'pool_create' is B_TRUE if we are logging the creation - * of the pool; B_FALSE otherwise. 'path' is the pathanme containing the + * of the pool; B_FALSE otherwise. 'path' is the pathname containing the * poolname. 'argc' and 'argv' are used to construct the command string. */ void @@ -2121,6 +2220,37 @@ zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) return (ret); } +uint64_t +zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop) +{ + uint64_t value; + nvlist_t *nvp; + + if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) + return (0); + + if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) + return (zpool_prop_default_numeric(prop)); + + switch (prop) { + case ZPOOL_PROP_AUTOREPLACE: + if (nvlist_lookup_nvlist(zhp->zpool_props, + zpool_prop_to_name(prop), &nvp) != 0) { + value = zpool_prop_default_numeric(prop); + } else { + VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE, + &value) == 0); + } + return (value); + break; + + default: + assert(0); + } + + return (0); +} + int zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, size_t proplen, zfs_source_t *srctype) @@ -2140,22 +2270,16 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg)); } - if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) + if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && + prop != ZPOOL_PROP_NAME) return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg)); - /* - * the "name" property is special cased - */ - if (!zfs_prop_valid_for_type(prop, ZFS_TYPE_POOL) && - prop != ZFS_PROP_NAME) - return (-1); - switch (prop) { - case ZFS_PROP_NAME: + case ZPOOL_PROP_NAME: (void) strlcpy(propbuf, zhp->zpool_name, proplen); break; - case ZFS_PROP_BOOTFS: + case ZPOOL_PROP_BOOTFS: if (nvlist_lookup_nvlist(zhp->zpool_props, zpool_prop_to_name(prop), &nvp) != 0) { strvalue = (char *)zfs_prop_default_string(prop); @@ -2171,7 +2295,22 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, if (strlen(strvalue) >= proplen) return (-1); } - (void) strcpy(propbuf, strvalue); + (void) strlcpy(propbuf, strvalue, proplen); + break; + + case ZPOOL_PROP_AUTOREPLACE: + if (nvlist_lookup_nvlist(zhp->zpool_props, + zpool_prop_to_name(prop), &nvp) != 0) { + value = zpool_prop_default_numeric(prop); + src = ZFS_SRC_DEFAULT; + } else { + VERIFY(nvlist_lookup_uint64(nvp, + ZFS_PROP_SOURCE, &value) == 0); + src = value; + VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE, + &value) == 0); + } + (void) strlcpy(propbuf, value ? "on" : "off", proplen); break; default: diff --git a/usr/src/lib/libzfs/common/libzfs_status.c b/usr/src/lib/libzfs/common/libzfs_status.c index 3eba97a431..97a81c35bb 100644 --- a/usr/src/lib/libzfs/common/libzfs_status.c +++ b/usr/src/lib/libzfs/common/libzfs_status.c @@ -30,7 +30,7 @@ * include both the status of an active pool, as well as the status exported * pools. Returns one of the ZPOOL_STATUS_* defines describing the status of * the pool. This status is independent (to a certain degree) from the state of - * the pool. A pool's state descsribes only whether or not it is capable of + * the pool. A pool's state describes only whether or not it is capable of * providing the necessary fault tolerance for data. The status describes the * overall status of devices. A pool that is online can still have a device * that is experiencing errors. @@ -47,7 +47,7 @@ #include "libzfs_impl.h" /* - * Message ID table. This must be kep in sync with the ZPOOL_STATUS_* defines + * Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines * in libzfs.h. Note that there are some status results which go past the end * of this table, and hence have no associated message ID. */ @@ -65,25 +65,6 @@ static char *zfs_msgid_table[] = { "ZFS-8000-EY" }; -/* - * If the pool is active, a certain class of static errors is overridden by the - * faults as analayzed by FMA. These faults have separate knowledge articles, - * and the article referred to by 'zpool status' must match that indicated by - * the syslog error message. We override missing data as well as corrupt pool. - */ -static char *zfs_msgid_table_active[] = { - "ZFS-8000-14", - "ZFS-8000-D3", /* overridden */ - "ZFS-8000-D3", /* overridden */ - "ZFS-8000-4J", - "ZFS-8000-5E", - "ZFS-8000-6X", - "ZFS-8000-CS", /* overridden */ - "ZFS-8000-8A", - "ZFS-8000-9P", - "ZFS-8000-CS", /* overridden */ -}; - #define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0])) /* ARGSUSED */ @@ -96,9 +77,16 @@ vdev_missing(uint64_t state, uint64_t aux, uint64_t errs) /* ARGSUSED */ static int +vdev_faulted(uint64_t state, uint64_t aux, uint64_t errs) +{ + return (state == VDEV_STATE_FAULTED); +} + +/* ARGSUSED */ +static int vdev_errors(uint64_t state, uint64_t aux, uint64_t errs) { - return (errs != 0); + return (state == VDEV_STATE_DEGRADED || errs != 0); } /* ARGSUSED */ @@ -163,9 +151,9 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t)) * following: * * - Check for a complete and valid configuration - * - Look for any missing devices in a non-replicated config + * - Look for any faulted or missing devices in a non-replicated config * - Check for any data errors - * - Check for any missing devices in a replicated config + * - Check for any faulted or missing devices in a replicated config * - Look for any devices showing errors * - Check for any resilvering devices * @@ -215,9 +203,13 @@ check_status(nvlist_t *config, boolean_t isimport) return (ZPOOL_STATUS_BAD_GUID_SUM); /* - * Missing devices in non-replicated config. + * Bad devices in non-replicated config. */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && + find_vdev_problem(nvroot, vdev_faulted)) + return (ZPOOL_STATUS_FAULTED_DEV_NR); + + if (vs->vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem(nvroot, vdev_missing)) return (ZPOOL_STATUS_MISSING_DEV_NR); @@ -244,6 +236,8 @@ check_status(nvlist_t *config, boolean_t isimport) /* * Missing devices in a replicated config. */ + if (find_vdev_problem(nvroot, vdev_faulted)) + return (ZPOOL_STATUS_FAULTED_DEV_R); if (find_vdev_problem(nvroot, vdev_missing)) return (ZPOOL_STATUS_MISSING_DEV_R); if (find_vdev_problem(nvroot, vdev_broken)) @@ -284,7 +278,7 @@ zpool_get_status(zpool_handle_t *zhp, char **msgid) if (ret >= NMSGID) *msgid = NULL; else - *msgid = zfs_msgid_table_active[ret]; + *msgid = zfs_msgid_table[ret]; return (ret); } diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c index 6b5a6de945..2ae3e2e6ce 100644 --- a/usr/src/lib/libzfs/common/libzfs_util.c +++ b/usr/src/lib/libzfs/common/libzfs_util.c @@ -490,9 +490,8 @@ zfs_nicenum(uint64_t num, char *buf, size_t buflen) */ int i; for (i = 2; i >= 0; i--) { - (void) snprintf(buf, buflen, "%.*f%c", i, - (double)num / (1ULL << 10 * index), u); - if (strlen(buf) <= 5) + if (snprintf(buf, buflen, "%.*f%c", i, + (double)num / (1ULL << 10 * index), u) <= 5) break; } } diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers index bd4d915a36..e182f14eed 100644 --- a/usr/src/lib/libzfs/common/mapfile-vers +++ b/usr/src/lib/libzfs/common/mapfile-vers @@ -116,6 +116,7 @@ SUNWprivate_1.1 { zpool_get_history; zpool_get_name; zpool_get_prop; + zpool_get_prop_int; zpool_get_proplist; zpool_get_root; zpool_get_space_total; @@ -144,7 +145,10 @@ SUNWprivate_1.1 { zpool_unmount_datasets; zpool_upgrade; zpool_vdev_attach; + zpool_vdev_clear; + zpool_vdev_degrade; zpool_vdev_detach; + zpool_vdev_fault; zpool_vdev_name; zpool_vdev_offline; zpool_vdev_online; |