diff options
author | Matthew Ahrens <[email protected]> | 2014-09-17 17:41:51 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2014-09-23 11:58:05 -0700 |
commit | 1f6f97f3049706aa7ca95636fd587ae5f3d531a9 (patch) | |
tree | a976ba4838b37a42e7b4f3407ce54fee07f7ad68 | |
parent | ab2894e66f40785b7d56d54f71158d6bf5b31b9a (diff) |
Illumos 5116 - zpool history -i goes into infinite loop
5116 zpool history -i goes into infinite loop
Reviewed by: Christopher Siden <[email protected]>
Reviewed by: Dan Kimmel <[email protected]>
Reviewed by: George Wilson <[email protected]>
Reviewed by: Richard Elling <[email protected]>
Reviewed by: Boris Protopopov <[email protected]>
Approved by: Dan McDonald <[email protected]>
References:
https://www.illumos.org/issues/5116
https://github.com/illumos/illumos-gate/commit/3339867
Ported by: Turbo Fredriksson <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #2715
-rw-r--r-- | lib/libzfs/libzfs_pool.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 00ed1a3e3..b94974b83 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -3760,22 +3760,24 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, return (0); } -#define HIS_BUF_LEN (128*1024) - /* * Retrieve the command history of a pool. */ int zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) { - char buf[HIS_BUF_LEN]; + char *buf; + int buflen = 128 * 1024; uint64_t off = 0; nvlist_t **records = NULL; uint_t numrecords = 0; int err, i; + buf = malloc(buflen); + if (buf == NULL) + return (ENOMEM); do { - uint64_t bytes_read = sizeof (buf); + uint64_t bytes_read = buflen; uint64_t leftover; if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) @@ -3789,10 +3791,23 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) &leftover, &records, &numrecords)) != 0) break; off -= leftover; + if (leftover == bytes_read) { + /* + * no progress made, because buffer is not big enough + * to hold this record; resize and retry. + */ + buflen *= 2; + free(buf); + buf = malloc(buflen); + if (buf == NULL) + return (ENOMEM); + } /* CONSTCOND */ } while (1); + free(buf); + if (!err) { verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, |