Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Jan 2010 14:52:45 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org
Subject:   svn commit: r201501 - stable/6/sys/opencrypto
Message-ID:  <201001041452.o04Eqjr0090010@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Mon Jan  4 14:52:45 2010
New Revision: 201501
URL: http://svn.freebsd.org/changeset/base/201501

Log:
  MFC r199895:
  
    Change memory managment from a fixed size array to a list.
    This is needed to avoid running into out of buffer situations
    where we cannot alloc a new buffer because we hit the array size
    limit (ZBUF).
    Use a combined allocation for the struct and the actual data buffer
    to not increase the number of malloc calls. [1]
  
    Defer initialization of zbuf until we actually need it.
  
    Make sure the output buffer will be large enough in all cases.
  
    Details discussed with:     kib [1]
    Reviewed by:                kib [1]

Modified:
  stable/6/sys/opencrypto/deflate.c
  stable/6/sys/opencrypto/deflate.h
Directory Properties:
  stable/6/sys/   (props changed)
  stable/6/sys/contrib/pf/   (props changed)
  stable/6/sys/dev/cxgb/   (props changed)

Modified: stable/6/sys/opencrypto/deflate.c
==============================================================================
--- stable/6/sys/opencrypto/deflate.c	Mon Jan  4 14:45:31 2010	(r201500)
+++ stable/6/sys/opencrypto/deflate.c	Mon Jan  4 14:52:45 2010	(r201501)
@@ -65,53 +65,52 @@ deflate_global(data, size, decomp, out)
 	z_stream zbuf;
 	u_int8_t *output;
 	u_int32_t count, result;
-	int error, i = 0, j;
-	struct deflate_buf buf[ZBUF];
-
-	bzero(&zbuf, sizeof(z_stream));
-	for (j = 0; j < ZBUF; j++)
-		buf[j].flag = 0;
-
-	zbuf.next_in = data;	/* data that is going to be processed */
-	zbuf.zalloc = z_alloc;
-	zbuf.zfree = z_free;
-	zbuf.opaque = Z_NULL;
-	zbuf.avail_in = size;	/* Total length of data to be processed */
+	int error, i;
+	struct deflate_buf *bufh, *bufp;
 
+	bufh = bufp = NULL;
 	if (!decomp) {
-		buf[i].out = malloc((u_long) size, M_CRYPTO_DATA, 
-		    M_NOWAIT);
-		if (buf[i].out == NULL)
-			goto bad;
-		buf[i].size = size;
-		buf[i].flag = 1;
-		i++;
+		i = 1;
 	} else {
 		/*
 	 	 * Choose a buffer with 4x the size of the input buffer
 	 	 * for the size of the output buffer in the case of
 	 	 * decompression. If it's not sufficient, it will need to be
-	 	 * updated while the decompression is going on
+	 	 * updated while the decompression is going on.
 	 	 */
-
-		buf[i].out = malloc((u_long) (size * 4), 
-		    M_CRYPTO_DATA, M_NOWAIT);
-		if (buf[i].out == NULL)
-			goto bad;
-		buf[i].size = size * 4;
-		buf[i].flag = 1;
+		i = 4;
+	}
+	/*
+	 * Make sure we do have enough output space.  Repeated calls to
+	 * deflate need at least 6 bytes of output buffer space to avoid
+	 * repeated markers.  We will always provide at least 16 bytes.
+	 */
+	while ((size * i) < 16)
 		i++;
+
+	bufh = bufp = malloc(sizeof(*bufp) + (size_t)(size * i),
+	    M_CRYPTO_DATA, M_NOWAIT);
+	if (bufp == NULL) {
+		goto bad2;
 	}
+	bufp->next = NULL;
+	bufp->size = size * i;
 
-	zbuf.next_out = buf[0].out;
-	zbuf.avail_out = buf[0].size;
+	bzero(&zbuf, sizeof(z_stream));
+	zbuf.zalloc = z_alloc;
+	zbuf.zfree = z_free;
+	zbuf.opaque = Z_NULL;
+	zbuf.next_in = data;	/* Data that is going to be processed. */
+	zbuf.avail_in = size;	/* Total length of data to be processed. */
+	zbuf.next_out = bufp->data;
+	zbuf.avail_out = bufp->size;
 
 	error = decomp ? inflateInit2(&zbuf, window_inflate) :
 	    deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
 		    window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
-
 	if (error != Z_OK)
 		goto bad;
+
 	for (;;) {
 		error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) :
 				 deflate(&zbuf, Z_FINISH);
@@ -124,16 +123,20 @@ deflate_global(data, size, decomp, out)
 			/* Done. */
 			break;
 		} else if (zbuf.avail_out == 0) {
-			/* we need more output space, allocate size */
-			buf[i].out = malloc((u_long) size,
+			struct deflate_buf *p;
+
+			/* We need more output space for another iteration. */
+			p = malloc(sizeof(*p) + (size_t)(size * i),
 			    M_CRYPTO_DATA, M_NOWAIT);
-			if (buf[i].out == NULL)
+			if (p == NULL) {
 				goto bad;
-			zbuf.next_out = buf[i].out;
-			buf[i].size = size;
-			buf[i].flag = 1;
-			zbuf.avail_out = buf[i].size;
-			i++;
+			}
+			p->next = NULL;
+			p->size = size * i;
+			bufp->next = p;
+			bufp = p;
+			zbuf.next_out = bufp->data;
+			zbuf.avail_out = bufp->size;
 		} else {
 			/* Unexpect result. */
 			goto bad;
@@ -142,25 +145,31 @@ deflate_global(data, size, decomp, out)
 
 	result = count = zbuf.total_out;
 
-	*out = malloc((u_long) result, M_CRYPTO_DATA, M_NOWAIT);
-	if (*out == NULL)
+	*out = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
+	if (*out == NULL) {
 		goto bad;
+	}
 	if (decomp)
 		inflateEnd(&zbuf);
 	else
 		deflateEnd(&zbuf);
 	output = *out;
-	for (j = 0; buf[j].flag != 0; j++) {
-		if (count > buf[j].size) {
-			bcopy(buf[j].out, *out, buf[j].size);
-			*out += buf[j].size;
-			free(buf[j].out, M_CRYPTO_DATA);
-			count -= buf[j].size;
+	for (bufp = bufh; bufp != NULL; ) {
+		if (count > bufp->size) {
+			struct deflate_buf *p;
+
+			bcopy(bufp->data, *out, bufp->size);
+			*out += bufp->size;
+			count -= bufp->size;
+			p = bufp;
+			bufp = bufp->next;
+			free(p, M_CRYPTO_DATA);
 		} else {
-			/* it should be the last buffer */
-			bcopy(buf[j].out, *out, count);
+			/* It should be the last buffer. */
+			bcopy(bufp->data, *out, count);
 			*out += count;
-			free(buf[j].out, M_CRYPTO_DATA);
+			free(bufp, M_CRYPTO_DATA);
+			bufp = NULL;
 			count = 0;
 		}
 	}
@@ -168,13 +177,19 @@ deflate_global(data, size, decomp, out)
 	return result;
 
 bad:
-	*out = NULL;
-	for (j = 0; buf[j].flag != 0; j++)
-		free(buf[j].out, M_CRYPTO_DATA);
 	if (decomp)
 		inflateEnd(&zbuf);
 	else
 		deflateEnd(&zbuf);
+	for (bufp = bufh; bufp != NULL; ) {
+		struct deflate_buf *p;
+
+		p = bufp;
+		bufp = bufp->next;
+		free(p, M_CRYPTO_DATA);
+	}
+bad2:
+	*out = NULL;
 	return 0;
 }
 

Modified: stable/6/sys/opencrypto/deflate.h
==============================================================================
--- stable/6/sys/opencrypto/deflate.h	Mon Jan  4 14:45:31 2010	(r201500)
+++ stable/6/sys/opencrypto/deflate.h	Mon Jan  4 14:52:45 2010	(r201501)
@@ -47,10 +47,14 @@ u_int32_t deflate_global(u_int8_t *, u_i
 void *z_alloc(void *, u_int, u_int);
 void z_free(void *, void *);
 
+/*
+ * We are going to use a combined allocation to hold the metadata
+ * from the struct immediately followed by the real application data.
+ */
 struct deflate_buf {
-	u_int8_t *out;
-	u_int32_t size;
-	int flag;
+	struct deflate_buf *next;
+	uint32_t size;
+	uint8_t data[];
 };
 
 #endif /* _CRYPTO_DEFLATE_H_ */



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