Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Apr 2014 18:40:01 GMT
From:      dfilter@FreeBSD.ORG (dfilter service)
To:        freebsd-fs@FreeBSD.org
Subject:   Re: kern/186574: commit references a PR
Message-ID:  <201404141840.s3EIe1EA078385@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/186574; it has been noted by GNATS.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/186574: commit references a PR
Date: Mon, 14 Apr 2014 18:38:18 +0000 (UTC)

 Author: delphij
 Date: Mon Apr 14 18:38:14 2014
 New Revision: 264467
 URL: http://svnweb.freebsd.org/changeset/base/264467
 
 Log:
   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)
   MFC after:	2 weeks
 
 Modified:
   head/cddl/contrib/opensolaris/cmd/zdb/zdb.c
   head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
 
 Modified: head/cddl/contrib/opensolaris/cmd/zdb/zdb.c
 ==============================================================================
 --- head/cddl/contrib/opensolaris/cmd/zdb/zdb.c	Mon Apr 14 18:14:09 2014	(r264466)
 +++ head/cddl/contrib/opensolaris/cmd/zdb/zdb.c	Mon Apr 14 18:38:14 2014	(r264467)
 @@ -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: head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
 ==============================================================================
 --- head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c	Mon Apr 14 18:14:09 2014	(r264466)
 +++ head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c	Mon Apr 14 18:38:14 2014	(r264467)
 @@ -3744,7 +3744,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.
 @@ -3752,21 +3754,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,
 @@ -3774,8 +3779,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);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404141840.s3EIe1EA078385>