Date: Thu, 6 Aug 2020 14:07:49 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r363952 - in stable/12/cddl/contrib/opensolaris: cmd/zpool lib/libzfs/common Message-ID: <202008061407.076E7nHJ066933@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Thu Aug 6 14:07:49 2020 New Revision: 363952 URL: https://svnweb.freebsd.org/changeset/base/363952 Log: MFC r363447: MFOpenZFS: Fix zpool history unbounded memory usage PR: 247557 Modified: stable/12/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c Directory Properties: stable/12/ (props changed) Modified: stable/12/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c ============================================================================== --- stable/12/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c Thu Aug 6 13:41:42 2020 (r363951) +++ stable/12/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c Thu Aug 6 14:07:49 2020 (r363952) @@ -6226,25 +6226,13 @@ 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; + int i; - 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); - verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, &records, &numrecords) == 0); for (i = 0; i < numrecords; i++) { @@ -6344,8 +6332,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); } Modified: stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h ============================================================================== --- stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h Thu Aug 6 13:41:42 2020 (r363951) +++ stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h Thu Aug 6 14:07:49 2020 (r363952) @@ -440,7 +440,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_history_unpack(char *, uint64_t, uint64_t *, nvlist_t ***, uint_t *); extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *, Modified: stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c ============================================================================== --- stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c Thu Aug 6 13:41:42 2020 (r363951) +++ stable/12/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c Thu Aug 6 14:07:49 2020 (r363952) @@ -4124,33 +4124,37 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, u * 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; uint64_t buflen = HIS_BUF_LEN_DEF; - 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 at 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 == 0) + if (bytes_read == 0) { + *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 @@ -4165,9 +4169,7 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhi break; } } - - /* CONSTCOND */ - } while (1); + } free(buf);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202008061407.076E7nHJ066933>