summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2014-09-17 17:41:51 +0200
committerBrian Behlendorf <[email protected]>2014-09-23 11:58:05 -0700
commit1f6f97f3049706aa7ca95636fd587ae5f3d531a9 (patch)
treea976ba4838b37a42e7b4f3407ce54fee07f7ad68 /lib
parentab2894e66f40785b7d56d54f71158d6bf5b31b9a (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
Diffstat (limited to 'lib')
-rw-r--r--lib/libzfs/libzfs_pool.c23
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,