From 8fb79fdddb076036a006e19f4e1b93b3baf72498 Mon Sep 17 00:00:00 2001 From: Allan Jude Date: Sat, 1 Aug 2020 11:41:31 -0400 Subject: [PATCH] Change the error handling for invalid property values ZFS recv should return a useful error message when an invalid index property value is provided in the send stream properties nvlist With a compression= property outside of the understood range: Before: ``` receiving full stream of zof/zstd_send@send2 into testpool/recv@send2 internal error: Invalid argument Aborted (core dumped) ``` Note: the recv completes successfully, the abort() is likely just to make it easier to track the unexpected error code. After: ``` receiving full stream of zof/zstd_send@send2 into testpool/recv@send2 cannot receive compression property on testpool/recv: invalid property value received 28.9M stream in 1 seconds (28.9M/sec) ``` Reviewed-by: Brian Behlendorf Signed-off-by: Allan Jude Closes #10631 --- contrib/pyzfs/libzfs_core/_constants.py | 2 +- contrib/pyzfs/libzfs_core/_error_translation.py | 6 ++++++ include/sys/fs/zfs.h | 1 + lib/libzfs/libzfs_util.c | 14 ++++++++++++++ module/zfs/zfs_ioctl.c | 3 ++- 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/contrib/pyzfs/libzfs_core/_constants.py b/contrib/pyzfs/libzfs_core/_constants.py index 367ffb63a9..2dfed224c2 100644 --- a/contrib/pyzfs/libzfs_core/_constants.py +++ b/contrib/pyzfs/libzfs_core/_constants.py @@ -98,6 +98,7 @@ zfs_errno = enum_with_offset(1024, [ 'ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH', 'ZFS_ERR_RESILVER_IN_PROGRESS', 'ZFS_ERR_REBUILD_IN_PROGRESS', + 'ZFS_ERR_BADPROP', ], {} ) @@ -110,5 +111,4 @@ ZFS_ERR_DEVRM_IN_PROGRESS = zfs_errno.ZFS_ERR_DEVRM_IN_PROGRESS ZFS_ERR_VDEV_TOO_BIG = zfs_errno.ZFS_ERR_VDEV_TOO_BIG ZFS_ERR_WRONG_PARENT = zfs_errno.ZFS_ERR_WRONG_PARENT - # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4 diff --git a/contrib/pyzfs/libzfs_core/_error_translation.py b/contrib/pyzfs/libzfs_core/_error_translation.py index 5a063c714a..f494461f63 100644 --- a/contrib/pyzfs/libzfs_core/_error_translation.py +++ b/contrib/pyzfs/libzfs_core/_error_translation.py @@ -59,6 +59,8 @@ def lzc_create_translate_error(ret, name, ds_type, props): raise lzc_exc.ParentNotFound(name) if ret == ZFS_ERR_WRONG_PARENT: raise lzc_exc.WrongParent(_fs_name(name)) + if ret == zfs_errno.ZFS_ERR_BADPROP: + raise lzc_exc.PropertyInvalid(name) raise _generic_exception(ret, name, "Failed to create filesystem") @@ -420,6 +422,8 @@ def lzc_receive_translate_errors( def _map(ret, name): if ret == errno.EINVAL: return lzc_exc.PropertyInvalid(name) + if ret == zfs_errno.ZFS_ERR_BADPROP: + return lzc_exc.PropertyInvalid(name) return _generic_exception(ret, name, "Failed to set property") _handle_err_list( errno.EINVAL, properrs, [snapname], @@ -471,6 +475,8 @@ def lzc_receive_translate_errors( raise lzc_exc.WrongParent(_fs_name(snapname)) if ret == zfs_errno.ZFS_ERR_STREAM_TRUNCATED: raise lzc_exc.StreamTruncated() + if ret == zfs_errno.ZFS_ERR_BADPROP: + raise lzc_exc.PropertyInvalid(snapname) raise lzc_exc.StreamIOError(ret) diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index ef87c24a46..8126832bad 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -1366,6 +1366,7 @@ typedef enum { ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH, ZFS_ERR_RESILVER_IN_PROGRESS, ZFS_ERR_REBUILD_IN_PROGRESS, + ZFS_ERR_BADPROP, } zfs_errno_t; /* diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index a27c5cc273..c43c6bb1fe 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -25,6 +25,10 @@ * Copyright (c) 2011, 2020 by Delphix. All rights reserved. * Copyright 2016 Igor Kozhukhov * Copyright (c) 2017 Datto Inc. + * Copyright (c) 2020 The FreeBSD Foundation + * + * Portions of this software were developed by Allan Jude + * under sponsorship from the FreeBSD Foundation. */ /* @@ -475,6 +479,9 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ZFS_ERR_WRONG_PARENT: zfs_verror(hdl, EZFS_WRONG_PARENT, fmt, ap); break; + case ZFS_ERR_BADPROP: + zfs_verror(hdl, EZFS_BADPROP, fmt, ap); + break; default: zfs_error_aux(hdl, strerror(error)); zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); @@ -567,6 +574,10 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err, } break; + case ZFS_ERR_BADPROP: + (void) zfs_error(hdl, EZFS_BADPROP, errbuf); + break; + case EACCES: if (prop == ZFS_PROP_KEYLOCATION) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -703,6 +714,9 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ZFS_ERR_REBUILD_IN_PROGRESS: zfs_verror(hdl, EZFS_REBUILDING, fmt, ap); break; + case ZFS_ERR_BADPROP: + zfs_verror(hdl, EZFS_BADPROP, fmt, ap); + break; case ZFS_ERR_IOC_CMD_UNAVAIL: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs " "module does not support this operation. A reboot may " diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 672eec9ccf..d0d5207b4e 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -2591,7 +2591,8 @@ retry: case PROP_TYPE_INDEX: if (zfs_prop_index_to_string(prop, intval, &unused) != 0) - err = SET_ERROR(EINVAL); + err = + SET_ERROR(ZFS_ERR_BADPROP); break; default: cmn_err(CE_PANIC,