Fix 'zpool history' sometimes fails without reporting any error

The corresponding function 'zpool_get_history' in libzfs would printing
an error messages only when the ioctl call failed.

Add missing error reporting, specifically memory allocation failures
and error from 'zpool_history_unpack'.

Also avoid possibly reading of uninitialized 'err' variable in case
the requested offset pasts EOF.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Damian Szuberski <szuberskidamian@gmail.com>
Signed-off-by: WHR <msl0000023508@gmail.com>
Issue #13322 
Closes #13320
This commit is contained in:
Low-power 2022-04-16 05:16:07 +08:00 committed by GitHub
parent 0dd34a1955
commit 4dced31b98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 11 additions and 9 deletions

View File

@ -4439,17 +4439,17 @@ int
zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off, zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
boolean_t *eof) boolean_t *eof)
{ {
libzfs_handle_t *hdl = zhp->zpool_hdl;
char *buf; char *buf;
int buflen = 128 * 1024; int buflen = 128 * 1024;
nvlist_t **records = NULL; nvlist_t **records = NULL;
uint_t numrecords = 0; uint_t numrecords = 0;
int err, i; int err = 0, i;
uint64_t start = *off; uint64_t start = *off;
buf = malloc(buflen); buf = zfs_alloc(hdl, buflen);
if (buf == NULL)
return (ENOMEM); /* process about 1MiB a time */
/* process about 1MB a time */
while (*off - start < 1024 * 1024) { while (*off - start < 1024 * 1024) {
uint64_t bytes_read = buflen; uint64_t bytes_read = buflen;
uint64_t leftover; uint64_t leftover;
@ -4464,8 +4464,12 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
} }
if ((err = zpool_history_unpack(buf, bytes_read, if ((err = zpool_history_unpack(buf, bytes_read,
&leftover, &records, &numrecords)) != 0) &leftover, &records, &numrecords)) != 0) {
zpool_standard_error_fmt(hdl, err,
dgettext(TEXT_DOMAIN,
"cannot get history for '%s'"), zhp->zpool_name);
break; break;
}
*off -= leftover; *off -= leftover;
if (leftover == bytes_read) { if (leftover == bytes_read) {
/* /*
@ -4474,9 +4478,7 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
*/ */
buflen *= 2; buflen *= 2;
free(buf); free(buf);
buf = malloc(buflen); buf = zfs_alloc(hdl, buflen);
if (buf == NULL)
return (ENOMEM);
} }
} }