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 <behlendorf1@llnl.gov>
Signed-off-by: Allan Jude <allan@klarasystems.com>
Closes #10631
This commit is contained in:
Allan Jude 2020-08-01 11:41:31 -04:00 committed by GitHub
parent 47ed79ff60
commit 8fb79fdddb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 2 deletions

View File

@ -98,6 +98,7 @@ zfs_errno = enum_with_offset(1024, [
'ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH', 'ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH',
'ZFS_ERR_RESILVER_IN_PROGRESS', 'ZFS_ERR_RESILVER_IN_PROGRESS',
'ZFS_ERR_REBUILD_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_VDEV_TOO_BIG = zfs_errno.ZFS_ERR_VDEV_TOO_BIG
ZFS_ERR_WRONG_PARENT = zfs_errno.ZFS_ERR_WRONG_PARENT ZFS_ERR_WRONG_PARENT = zfs_errno.ZFS_ERR_WRONG_PARENT
# vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4

View File

@ -59,6 +59,8 @@ def lzc_create_translate_error(ret, name, ds_type, props):
raise lzc_exc.ParentNotFound(name) raise lzc_exc.ParentNotFound(name)
if ret == ZFS_ERR_WRONG_PARENT: if ret == ZFS_ERR_WRONG_PARENT:
raise lzc_exc.WrongParent(_fs_name(name)) 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") raise _generic_exception(ret, name, "Failed to create filesystem")
@ -420,6 +422,8 @@ def lzc_receive_translate_errors(
def _map(ret, name): def _map(ret, name):
if ret == errno.EINVAL: if ret == errno.EINVAL:
return lzc_exc.PropertyInvalid(name) 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") return _generic_exception(ret, name, "Failed to set property")
_handle_err_list( _handle_err_list(
errno.EINVAL, properrs, [snapname], errno.EINVAL, properrs, [snapname],
@ -471,6 +475,8 @@ def lzc_receive_translate_errors(
raise lzc_exc.WrongParent(_fs_name(snapname)) raise lzc_exc.WrongParent(_fs_name(snapname))
if ret == zfs_errno.ZFS_ERR_STREAM_TRUNCATED: if ret == zfs_errno.ZFS_ERR_STREAM_TRUNCATED:
raise lzc_exc.StreamTruncated() raise lzc_exc.StreamTruncated()
if ret == zfs_errno.ZFS_ERR_BADPROP:
raise lzc_exc.PropertyInvalid(snapname)
raise lzc_exc.StreamIOError(ret) raise lzc_exc.StreamIOError(ret)

View File

@ -1366,6 +1366,7 @@ typedef enum {
ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH, ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH,
ZFS_ERR_RESILVER_IN_PROGRESS, ZFS_ERR_RESILVER_IN_PROGRESS,
ZFS_ERR_REBUILD_IN_PROGRESS, ZFS_ERR_REBUILD_IN_PROGRESS,
ZFS_ERR_BADPROP,
} zfs_errno_t; } zfs_errno_t;
/* /*

View File

@ -25,6 +25,10 @@
* Copyright (c) 2011, 2020 by Delphix. All rights reserved. * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright (c) 2017 Datto Inc. * 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: case ZFS_ERR_WRONG_PARENT:
zfs_verror(hdl, EZFS_WRONG_PARENT, fmt, ap); zfs_verror(hdl, EZFS_WRONG_PARENT, fmt, ap);
break; break;
case ZFS_ERR_BADPROP:
zfs_verror(hdl, EZFS_BADPROP, fmt, ap);
break;
default: default:
zfs_error_aux(hdl, strerror(error)); zfs_error_aux(hdl, strerror(error));
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 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; break;
case ZFS_ERR_BADPROP:
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
break;
case EACCES: case EACCES:
if (prop == ZFS_PROP_KEYLOCATION) { if (prop == ZFS_PROP_KEYLOCATION) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 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: case ZFS_ERR_REBUILD_IN_PROGRESS:
zfs_verror(hdl, EZFS_REBUILDING, fmt, ap); zfs_verror(hdl, EZFS_REBUILDING, fmt, ap);
break; break;
case ZFS_ERR_BADPROP:
zfs_verror(hdl, EZFS_BADPROP, fmt, ap);
break;
case ZFS_ERR_IOC_CMD_UNAVAIL: case ZFS_ERR_IOC_CMD_UNAVAIL:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs " zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs "
"module does not support this operation. A reboot may " "module does not support this operation. A reboot may "

View File

@ -2591,7 +2591,8 @@ retry:
case PROP_TYPE_INDEX: case PROP_TYPE_INDEX:
if (zfs_prop_index_to_string(prop, if (zfs_prop_index_to_string(prop,
intval, &unused) != 0) intval, &unused) != 0)
err = SET_ERROR(EINVAL); err =
SET_ERROR(ZFS_ERR_BADPROP);
break; break;
default: default:
cmn_err(CE_PANIC, cmn_err(CE_PANIC,