Print this page
NEX-5063 Passing invalid trim rate to zpool(1M) coredumps
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
5745 zfs set allows only one dataset property to be set at a time
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com>
Reviewed by: Richard PALO <richard@NetBSD.org>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Rich Lowe <richlowe@richlowe.net>
5692 expose the number of hole blocks in a file
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Boris Protopopov <bprotopopov@hotmail.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
NEX-4336 zpool vdev-get with an unsuported prop name core dumps
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3558 KRRP Integration
OS-103 handle CoS descriptor persistent references across vdev operations
OS-102 add man page info and tests for vdev/CoS properties and ZFS meta features
Moved closed ZFS files to open repo, changed Makefiles accordingly
Removed unneeded weak symbols
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (fix lint -courtesy of Yuri Pankov)
re #12584 rb4049 zfsxx latest code merge (fix lint - courtesy of Yuri Pankov)
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties

*** 20,29 **** --- 20,30 ---- */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> * Copyright (c) 2017 Datto Inc. */
*** 233,245 **** return (dgettext(TEXT_DOMAIN, "unable to generate diffs")); case EZFS_DIFFDATA: return (dgettext(TEXT_DOMAIN, "invalid diff data")); case EZFS_POOLREADONLY: return (dgettext(TEXT_DOMAIN, "pool is read-only")); ! case EZFS_NO_PENDING: ! return (dgettext(TEXT_DOMAIN, "operation is not " ! "in progress")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default: assert(hdl->libzfs_error == 0); return (dgettext(TEXT_DOMAIN, "no error")); --- 234,252 ---- return (dgettext(TEXT_DOMAIN, "unable to generate diffs")); case EZFS_DIFFDATA: return (dgettext(TEXT_DOMAIN, "invalid diff data")); case EZFS_POOLREADONLY: return (dgettext(TEXT_DOMAIN, "pool is read-only")); ! case EZFS_PROPNOTSUP: ! return (dgettext(TEXT_DOMAIN, "property is not supported")); ! case EZFS_COSNOTFOUND: ! return (dgettext(TEXT_DOMAIN, "CoS descriptor not found")); ! case EZFS_COSEXIST: ! return (dgettext(TEXT_DOMAIN, "CoS descriptor already exists")); ! case EZFS_COSREF: ! return (dgettext(TEXT_DOMAIN, ! "CoS descriptor is still referenced")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default: assert(hdl->libzfs_error == 0); return (dgettext(TEXT_DOMAIN, "no error"));
*** 387,396 **** --- 394,406 ---- zfs_verror(hdl, EZFS_BUSY, fmt, ap); break; case EROFS: zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); break; + case EINVAL: + zfs_verror(hdl, EZFS_INVALIDNAME, fmt, ap); + break; case ENAMETOOLONG: zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); break; case ENOTSUP: zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
*** 409,418 **** --- 419,472 ---- va_end(ap); return (-1); } int + zpool_vprop_standard_error(libzfs_handle_t *hdl, int error, const char *msg) + { + return (zpool_vprop_standard_error_fmt(hdl, error, "%s", msg)); + } + + /*PRINTFLIKE3*/ + int + zpool_vprop_standard_error_fmt(libzfs_handle_t *hdl, int error, + const char *fmt, ...) + { + va_list ap; + + va_start(ap, fmt); + + if (zfs_common_error(hdl, error, fmt, ap) != 0) { + va_end(ap); + return (-1); + } + + switch (error) { + case ENOENT: + zfs_verror(hdl, EZFS_COSNOTFOUND, fmt, ap); + break; + case ENOTSUP: + zfs_verror(hdl, EZFS_PROPNOTSUP, fmt, ap); + break; + + case EEXIST: + zfs_verror(hdl, EZFS_COSEXIST, fmt, ap); + break; + case EBUSY: + zfs_verror(hdl, EZFS_COSREF, fmt, ap); + break; + default: + zfs_error_aux(hdl, strerror(error)); + zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); + break; + } + + va_end(ap); + return (-1); + } + + int zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) { return (zpool_standard_error_fmt(hdl, error, "%s", msg)); }
*** 445,455 **** "pool already exists")); zfs_verror(hdl, EZFS_EXISTS, fmt, ap); break; case EBUSY: ! zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); zfs_verror(hdl, EZFS_BUSY, fmt, ap); break; case ENXIO: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, --- 499,510 ---- "pool already exists")); zfs_verror(hdl, EZFS_EXISTS, fmt, ap); break; case EBUSY: ! zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, ! "pool or device is busy")); zfs_verror(hdl, EZFS_BUSY, fmt, ap); break; case ENXIO: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
*** 481,494 **** break; case EROFS: zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); break; - /* There is no pending operation to cancel */ - case ENOTACTIVE: - zfs_verror(hdl, EZFS_NO_PENDING, fmt, ap); - break; default: zfs_error_aux(hdl, strerror(error)); zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); } --- 536,545 ----
*** 620,629 **** --- 671,682 ---- } zfs_prop_init(); zpool_prop_init(); zpool_feature_init(); + vdev_prop_init(); + cos_prop_init(); libzfs_mnttab_init(hdl); if (getenv("ZFS_PROP_DEBUG") != NULL) { hdl->libzfs_prop_debug = B_TRUE; }
*** 637,646 **** --- 690,701 ---- (void) close(hdl->libzfs_fd); if (hdl->libzfs_mnttab) (void) fclose(hdl->libzfs_mnttab); if (hdl->libzfs_sharetab) (void) fclose(hdl->libzfs_sharetab); + if (hdl->libzfs_log_str) + free(hdl->libzfs_log_str); zfs_uninit_libshare(hdl); zpool_free_handles(hdl); libzfs_fru_clear(hdl, B_TRUE); namespace_clear(hdl); libzfs_mnttab_fini(hdl);
*** 805,818 **** return (no_memory(hdl)); return (0); } int zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) { ! return (ioctl(hdl->libzfs_fd, request, zc)); } /* * ================================================================ * API shared by zfs and zpool property management --- 860,887 ---- return (no_memory(hdl)); return (0); } + #pragma weak libzfs_log_event = libzfs_log_event_stub + + /* ARGSUSED hdl zc */ + void + libzfs_log_event_stub(libzfs_handle_t *hdl, const char *zc) + { + } + int zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) { ! int error; ! ! error = ioctl(hdl->libzfs_fd, request, zc); ! if (error == 0) ! libzfs_log_event(hdl, zc->zc_name); ! ! return (error); } /* * ================================================================ * API shared by zfs and zpool property management
*** 1044,1053 **** --- 1113,1123 ---- for (i = 0; i < strlen(ends); i++) { if (toupper(buf[0]) == ends[i]) break; } if (i == strlen(ends)) { + if (hdl) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid numeric suffix '%s'"), buf); return (-1); }
*** 1057,1066 **** --- 1127,1137 ---- */ if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && toupper(buf[0]) != 'B')) return (10*i); + if (hdl) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid numeric suffix '%s'"), buf); return (-1); }
*** 1158,1171 **** zprop_type_t proptype; const char *propname; char *value; boolean_t isnone = B_FALSE; ! if (type == ZFS_TYPE_POOL) { proptype = zpool_prop_get_type(prop); propname = zpool_prop_to_name(prop); ! } else { proptype = zfs_prop_get_type(prop); propname = zfs_prop_to_name(prop); } /* --- 1229,1252 ---- zprop_type_t proptype; const char *propname; char *value; boolean_t isnone = B_FALSE; ! switch (type) { ! case ZFS_TYPE_POOL: proptype = zpool_prop_get_type(prop); propname = zpool_prop_to_name(prop); ! break; ! case ZFS_TYPE_VDEV: ! proptype = vdev_prop_get_type(prop); ! propname = vdev_prop_to_name(prop); ! break; ! case ZFS_TYPE_COS: ! proptype = cos_prop_get_type(prop); ! propname = cos_prop_to_name(prop); ! break; ! default: proptype = zfs_prop_get_type(prop); propname = zfs_prop_to_name(prop); } /*
*** 1489,1498 **** --- 1570,2011 ---- zfs_type_t type) { return (zprop_iter_common(func, cb, show_all, ordered, type)); } + int + vdev_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp) + { + *listp = NULL; + + /* + * If 'all' is specified, return a NULL list. + */ + if (strcmp(props, "all") == 0) { + vdev_prop_t prop; + for (prop = VDEV_PROP_PATH; prop < VDEV_NUM_PROPS; prop++) { + const char *propname = vdev_prop_to_name(prop); + if (addlist(hdl, (char *)propname, listp, + ZFS_TYPE_VDEV)) + return (-1); + listp = &(*listp)->pl_next; + } + + return (0); + } + + /* + * If no props were specified, return an error. + */ + if (props[0] == '\0') { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "no properties specified")); + return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, + "bad property list"))); + } + + /* + * It would be nice to use getsubopt() here, but the inclusion of column + * aliases makes this more effort than it's worth. + */ + while (*props != '\0') { + size_t len; + char *p; + char c; + + if ((p = strchr(props, ',')) == NULL) { + len = strlen(props); + p = props + len; + } else { + len = p - props; + } + + /* + * Check for empty options. + */ + if (len == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "empty property name")); + return (zfs_error(hdl, EZFS_BADPROP, + dgettext(TEXT_DOMAIN, "bad property list"))); + } + + /* + * Check all regular property names. + */ + c = props[len]; + props[len] = '\0'; + + /* + * Make sure we're looking at a valid prop. + */ + if (vdev_name_to_prop(props) == ZPROP_INVAL) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "invalid property '%s'"), props); + return (zfs_error(hdl, EZFS_BADPROP, + dgettext(TEXT_DOMAIN, "bad property list"))); + } + + if (addlist(hdl, props, listp, ZFS_TYPE_VDEV)) + return (-1); + listp = &(*listp)->pl_next; + + props = p; + if (c == ',') + props++; + } + + return (0); + } + + int + cos_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp) + { + *listp = NULL; + + /* + * If 'all' is specified, return a NULL list. + */ + if (strcmp(props, "all") == 0) { + cos_prop_t prop; + for (prop = COS_PROP_GUID; prop < COS_NUM_PROPS; prop++) { + const char *propname = cos_prop_to_name(prop); + if (addlist(hdl, (char *)propname, listp, + ZFS_TYPE_COS)) + return (-1); + listp = &(*listp)->pl_next; + } + + return (0); + } + + /* + * If no props were specified, return an error. + */ + if (props[0] == '\0') { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "no properties specified")); + return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, + "bad property list"))); + } + + /* + * It would be nice to use getsubopt() here, but the inclusion of column + * aliases makes this more effort than it's worth. + */ + while (*props != '\0') { + size_t len; + char *p; + char c; + + if ((p = strchr(props, ',')) == NULL) { + len = strlen(props); + p = props + len; + } else { + len = p - props; + } + + /* + * Check for empty options. + */ + if (len == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "empty property name")); + return (zfs_error(hdl, EZFS_BADPROP, + dgettext(TEXT_DOMAIN, "bad property list"))); + } + + /* + * Check all regular property names. + */ + c = props[len]; + props[len] = '\0'; + + if (addlist(hdl, props, listp, ZFS_TYPE_COS)) + return (-1); + listp = &(*listp)->pl_next; + + props = p; + if (c == ',') + props++; + } + + return (0); + } + + void + vdev_print_headers(zprop_get_cbdata_t *cbp) + { + zprop_list_t *pl = cbp->cb_proplist; + int i; + char *title; + size_t len; + + cbp->cb_first = B_FALSE; + if (cbp->cb_scripted) + return; + + /* + * Start with the length of the column headers. + */ + cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, + "POOLNAME")); + cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, + "c0t0d0s0")); + cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, + "PROPERTY")); + cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, + "VALUE")); + + for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { + /* + * 'PROPERTY' column + */ + const char *propname = vdev_prop_to_name(pl->pl_prop); + + len = strlen(propname); + if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) + cbp->cb_colwidths[GET_COL_PROPERTY] = len; + + /* + * 'VALUE' column. + */ + if (pl != cbp->cb_proplist && + pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) + cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; + + /* + * 'NAME' + */ + if (pl->pl_prop == 0 && + pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { + cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; + } + /* + * 'SOURCE' + */ + if (pl->pl_prop == 0 && + pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) { + cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width; + } + } + + /* + * Now go through and print the headers. + */ + for (i = 0; i < ZFS_GET_NCOLS-1; i++) { + switch (cbp->cb_columns[i]) { + case GET_COL_NAME: + title = dgettext(TEXT_DOMAIN, "POOLNAME"); + break; + case GET_COL_SOURCE: + title = dgettext(TEXT_DOMAIN, "VDEV"); + break; + case GET_COL_PROPERTY: + title = dgettext(TEXT_DOMAIN, "PROPERTY"); + break; + case GET_COL_VALUE: + title = dgettext(TEXT_DOMAIN, "VALUE"); + break; + default: + title = NULL; + } + + if (title != NULL) { + if (i == (ZFS_GET_NCOLS - 1) || + cbp->cb_columns[i + 1] == GET_COL_NONE) + (void) printf("%s", title); + else + (void) printf("%-*s ", + cbp->cb_colwidths[cbp->cb_columns[i]], + title); + } + } + (void) printf("\n"); + } + + void + cos_print_headers(zprop_get_cbdata_t *cbp) + { + zprop_list_t *pl = cbp->cb_proplist; + int i; + char *title; + size_t len; + + cbp->cb_first = B_FALSE; + if (cbp->cb_scripted) + return; + + /* + * Start with the length of the column headers. + */ + cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, + "POOLNAME")); + cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, + "c0t0d0s0")); + cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, + "PROPERTY")); + cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, + "VALUE")); + + for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { + /* + * 'PROPERTY' column + */ + const char *propname = cos_prop_to_name(pl->pl_prop); + + len = strlen(propname); + if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) + cbp->cb_colwidths[GET_COL_PROPERTY] = len; + + /* + * 'VALUE' column. + */ + if (pl != cbp->cb_proplist && + pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) + cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; + + /* + * 'NAME' + */ + if (pl->pl_prop == 0 && + pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { + cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; + } + /* + * 'SOURCE' + */ + if (pl->pl_prop == 0 && + pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) { + cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width; + } + } + + /* + * Now go through and print the headers. + */ + for (i = 0; i < ZFS_GET_NCOLS-1; i++) { + switch (cbp->cb_columns[i]) { + case GET_COL_NAME: + title = dgettext(TEXT_DOMAIN, "POOLNAME"); + break; + case GET_COL_SOURCE: + title = dgettext(TEXT_DOMAIN, "COS"); + break; + case GET_COL_PROPERTY: + title = dgettext(TEXT_DOMAIN, "PROPERTY"); + break; + case GET_COL_VALUE: + title = dgettext(TEXT_DOMAIN, "VALUE"); + break; + default: + title = NULL; + } + + if (title != NULL) { + if (i == (ZFS_GET_NCOLS - 1) || + cbp->cb_columns[i + 1] == GET_COL_NONE) + (void) printf("%s", title); + else + (void) printf("%-*s ", + cbp->cb_colwidths[cbp->cb_columns[i]], + title); + } + } + (void) printf("\n"); + } + + void + vdev_print_one_property(const char *poolname, const char *vdevname, + zprop_get_cbdata_t *cbp, const char *propname, const char *value) + { + int i; + const char *str; + + if (cbp->cb_first) + vdev_print_headers(cbp); + + for (i = 0; i < ZFS_GET_NCOLS; i++) { + switch (cbp->cb_columns[i]) { + case GET_COL_NAME: + str = poolname; + break; + + case GET_COL_SOURCE: + str = vdevname; + break; + + case GET_COL_PROPERTY: + str = propname; + break; + + case GET_COL_VALUE: + str = value; + break; + + default: + continue; + } + + if (cbp->cb_columns[i + 1] == GET_COL_NONE) + (void) printf("%s", str); + else if (cbp->cb_scripted) + (void) printf("%s\t", str); + else + (void) printf("%-*s ", + cbp->cb_colwidths[cbp->cb_columns[i]], + str); + } + + (void) printf("\n"); + } + + void + cos_print_one_property(const char *poolname, const char *cosname, + zprop_get_cbdata_t *cbp, const char *propname, const char *value) + { + int i; + const char *str; + + if (cbp->cb_first) + cos_print_headers(cbp); + + for (i = 0; i < ZFS_GET_NCOLS; i++) { + switch (cbp->cb_columns[i]) { + case GET_COL_NAME: + str = poolname; + break; + + case GET_COL_SOURCE: + str = cosname; + break; + + case GET_COL_PROPERTY: + str = propname; + break; + + case GET_COL_VALUE: + str = value; + break; + + default: + continue; + } + + if (cbp->cb_columns[i + 1] == GET_COL_NONE) + (void) printf("%s", str); + else if (cbp->cb_scripted) + (void) printf("%s\t", str); + else + (void) printf("%-*s ", + cbp->cb_colwidths[cbp->cb_columns[i]], + str); + } + + (void) printf("\n"); + } + /* * zfs_get_hole_count retrieves the number of holes (blocks which are * zero-filled) in the specified file using the _FIO_COUNT_FILLED ioctl. It * also optionally fetches the block size when bs is non-NULL. With hole count * and block size the full space consumed by the holes of a file can be