svn commit: r265040 - in stable/9/cddl/contrib/opensolaris: cmd/zdb lib/libzfs/common
Xin LI
delphij at FreeBSD.org
Mon Apr 28 06:11:45 UTC 2014
Author: delphij
Date: Mon Apr 28 06:11:44 2014
New Revision: 265040
URL: http://svnweb.freebsd.org/changeset/base/265040
Log:
MFC r264467:
Take into account when zpool history block grows exceeding 128KB in zpool(8)
and zdb(8) by growing the buffer on demand with a cap of 1GB (specified in
spa_history_create_obj()).
PR: bin/186574
Submitted by: Andrew Childs <lorne cons org nz> (with changes)
Modified:
stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c
stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
Directory Properties:
stable/9/cddl/contrib/opensolaris/ (props changed)
stable/9/cddl/contrib/opensolaris/lib/libzfs/ (props changed)
Modified: stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c Mon Apr 28 06:11:03 2014 (r265039)
+++ stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c Mon Apr 28 06:11:44 2014 (r265040)
@@ -929,11 +929,16 @@ dump_dtl(vdev_t *vd, int indent)
dump_dtl(vd->vdev_child[c], indent + 4);
}
+/* from spa_history.c: spa_history_create_obj() */
+#define HIS_BUF_LEN_DEF (128 << 10)
+#define HIS_BUF_LEN_MAX (1 << 30)
+
static void
dump_history(spa_t *spa)
{
nvlist_t **events = NULL;
- char buf[SPA_MAXBLOCKSIZE];
+ char *buf = NULL;
+ uint64_t bufsize = HIS_BUF_LEN_DEF;
uint64_t resid, len, off = 0;
uint_t num = 0;
int error;
@@ -942,8 +947,11 @@ dump_history(spa_t *spa)
char tbuf[30];
char internalstr[MAXPATHLEN];
+ if ((buf = malloc(bufsize)) == NULL)
+ (void) fprintf(stderr, "Unable to read history: "
+ "out of memory\n");
do {
- len = sizeof (buf);
+ len = bufsize;
if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
(void) fprintf(stderr, "Unable to read history: "
@@ -953,9 +961,26 @@ dump_history(spa_t *spa)
if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
break;
-
off -= resid;
+
+ /*
+ * If the history block is too big, double the buffer
+ * size and try again.
+ */
+ if (resid == len) {
+ free(buf);
+ buf = NULL;
+
+ bufsize <<= 1;
+ if ((bufsize >= HIS_BUF_LEN_MAX) ||
+ ((buf = malloc(bufsize)) == NULL)) {
+ (void) fprintf(stderr, "Unable to read history: "
+ "out of memory\n");
+ return;
+ }
+ }
} while (len != 0);
+ free(buf);
(void) printf("\nHistory:\n");
for (int i = 0; i < num; i++) {
Modified: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c Mon Apr 28 06:11:03 2014 (r265039)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c Mon Apr 28 06:11:44 2014 (r265040)
@@ -3736,7 +3736,9 @@ zpool_history_unpack(char *buf, uint64_t
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.
@@ -3744,21 +3746,24 @@ zpool_history_unpack(char *buf, uint64_t
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,
@@ -3766,8 +3771,25 @@ zpool_get_history(zpool_handle_t *zhp, n
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);
More information about the svn-src-stable-9
mailing list