aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zpool/zpool_main.c44
-rw-r--r--include/libzfs.h3
-rw-r--r--lib/libzfs/libzfs_pool.c20
3 files changed, 41 insertions, 26 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index 7a95add94..6071babfd 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -8518,24 +8518,12 @@ typedef struct hist_cbdata {
boolean_t internal;
} hist_cbdata_t;
-/*
- * Print out the command history for a specific pool.
- */
-static int
-get_history_one(zpool_handle_t *zhp, void *data)
+static void
+print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
{
- nvlist_t *nvhis;
nvlist_t **records;
uint_t numrecords;
- int ret, i;
- hist_cbdata_t *cb = (hist_cbdata_t *)data;
-
- cb->first = B_FALSE;
-
- (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
-
- if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
- return (ret);
+ int i;
verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
&records, &numrecords) == 0);
@@ -8639,8 +8627,32 @@ get_history_one(zpool_handle_t *zhp, void *data)
(void) printf("]");
(void) printf("\n");
}
+}
+
+/*
+ * Print out the command history for a specific pool.
+ */
+static int
+get_history_one(zpool_handle_t *zhp, void *data)
+{
+ nvlist_t *nvhis;
+ int ret;
+ hist_cbdata_t *cb = (hist_cbdata_t *)data;
+ uint64_t off = 0;
+ boolean_t eof = B_FALSE;
+
+ cb->first = B_FALSE;
+
+ (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
+
+ while (!eof) {
+ if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
+ return (ret);
+
+ print_history_records(nvhis, cb);
+ nvlist_free(nvhis);
+ }
(void) printf("\n");
- nvlist_free(nvhis);
return (ret);
}
diff --git a/include/libzfs.h b/include/libzfs.h
index 7828a2759..8e9f6fb3f 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -432,7 +432,8 @@ typedef enum {
extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *,
int name_flags);
extern int zpool_upgrade(zpool_handle_t *, uint64_t);
-extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
+extern int zpool_get_history(zpool_handle_t *, nvlist_t **, uint64_t *,
+ boolean_t *);
extern int zpool_events_next(libzfs_handle_t *, nvlist_t **, int *, unsigned,
int);
extern int zpool_events_clear(libzfs_handle_t *, int *);
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index 75ce7c9ab..380229da5 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -4160,33 +4160,37 @@ get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
* Retrieve the command history of a pool.
*/
int
-zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
+zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
+ boolean_t *eof)
{
char *buf;
int buflen = 128 * 1024;
- uint64_t off = 0;
nvlist_t **records = NULL;
uint_t numrecords = 0;
int err, i;
+ uint64_t start = *off;
buf = malloc(buflen);
if (buf == NULL)
return (ENOMEM);
- do {
+ /* process about 1MB a time */
+ while (*off - start < 1024 * 1024) {
uint64_t bytes_read = buflen;
uint64_t leftover;
- if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
+ 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) {
+ *eof = B_TRUE;
break;
+ }
if ((err = zpool_history_unpack(buf, bytes_read,
&leftover, &records, &numrecords)) != 0)
break;
- off -= leftover;
+ *off -= leftover;
if (leftover == bytes_read) {
/*
* no progress made, because buffer is not big enough
@@ -4198,9 +4202,7 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
if (buf == NULL)
return (ENOMEM);
}
-
- /* CONSTCOND */
- } while (1);
+ }
free(buf);