summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c')
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
index e691df1..8dd24a7 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
@@ -3744,7 +3744,9 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
return (0);
}
-#define HIS_BUF_LEN (128*1024)
+/* from spa_history.c: spa_history_create_obj() */
+#define HIS_BUF_LEN_DEF (128 << 10)
+#define HIS_BUF_LEN_MAX (1 << 30)
/*
* Retrieve the command history of a pool.
@@ -3752,21 +3754,24 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
int
zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
{
- char buf[HIS_BUF_LEN];
+ char *buf = NULL;
+ uint64_t bufsize = HIS_BUF_LEN_DEF;
uint64_t off = 0;
nvlist_t **records = NULL;
uint_t numrecords = 0;
int err, i;
+ if ((buf = malloc(bufsize)) == NULL)
+ return (ENOMEM);
do {
- uint64_t bytes_read = sizeof (buf);
+ uint64_t bytes_read = bufsize;
uint64_t leftover;
if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
break;
/* if nothing else was read in, we're at EOF, just return */
- if (!bytes_read)
+ if (bytes_read == 0)
break;
if ((err = zpool_history_unpack(buf, bytes_read,
@@ -3774,8 +3779,25 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
break;
off -= leftover;
+ /*
+ * If the history block is too big, double the buffer
+ * size and try again.
+ */
+ if (leftover == bytes_read) {
+ free(buf);
+ buf = NULL;
+
+ bufsize <<= 1;
+ if ((bufsize >= HIS_BUF_LEN_MAX) ||
+ ((buf = malloc(bufsize)) == NULL)) {
+ err = ENOMEM;
+ break;
+ }
+ }
+
/* CONSTCOND */
} while (1);
+ free(buf);
if (!err) {
verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
OpenPOWER on IntegriCloud