Illumos 5116 - zpool history -i goes into infinite loop

5116 zpool history -i goes into infinite loop
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Richard Elling <richard.elling@gmail.com>
Reviewed by: Boris Protopopov <boris.protopopov@me.com>
Approved by: Dan McDonald <danmcd@omniti.com>

References:
  https://www.illumos.org/issues/5116
  https://github.com/illumos/illumos-gate/commit/3339867

Ported by: Turbo Fredriksson <turbo@bayour.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #2715
This commit is contained in:
Matthew Ahrens 2014-09-17 17:41:51 +02:00 committed by Brian Behlendorf
parent ab2894e66f
commit 1f6f97f304
1 changed files with 19 additions and 4 deletions

View File

@ -3760,22 +3760,24 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
return (0); return (0);
} }
#define HIS_BUF_LEN (128*1024)
/* /*
* Retrieve the command history of a pool. * Retrieve the command history of a pool.
*/ */
int int
zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 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; uint64_t off = 0;
nvlist_t **records = NULL; nvlist_t **records = NULL;
uint_t numrecords = 0; uint_t numrecords = 0;
int err, i; int err, i;
buf = malloc(buflen);
if (buf == NULL)
return (ENOMEM);
do { do {
uint64_t bytes_read = sizeof (buf); uint64_t bytes_read = buflen;
uint64_t leftover; uint64_t leftover;
if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 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) &leftover, &records, &numrecords)) != 0)
break; break;
off -= leftover; 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 */ /* CONSTCOND */
} while (1); } while (1);
free(buf);
if (!err) { if (!err) {
verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,