Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Apr 2014 18:08:34 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r264769 - head/sys/geom/uncompress
Message-ID:  <201404221808.s3MI8Y8G057526@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: loos
Date: Tue Apr 22 18:08:34 2014
New Revision: 264769
URL: http://svnweb.freebsd.org/changeset/base/264769

Log:
  Keep geom_uncompress(4) in line with geom_uzip(4), bring in the r264504 fix.
  
  Make sure not to start I/O bigger than MAXPHYS bytes.
  
  Quoting r264504:
  
  When we detect the condition, we'll reduce the block count and perform
  a "short" read.  In g_uncompress_done() we need to consider the original
  I/O length and stop early if we're about to deflate a block that we didn't
  read.  By using bio_completed in the cloned BIO and not bio_length to
  check for this, we automatically and gracefully handle short reads that
  our providers may be doing on top of the short reads we may initiate
  ourselves.
  
  Reviewed by:	marcel

Modified:
  head/sys/geom/uncompress/g_uncompress.c

Modified: head/sys/geom/uncompress/g_uncompress.c
==============================================================================
--- head/sys/geom/uncompress/g_uncompress.c	Tue Apr 22 16:13:56 2014	(r264768)
+++ head/sys/geom/uncompress/g_uncompress.c	Tue Apr 22 18:08:34 2014	(r264769)
@@ -169,7 +169,7 @@ g_uncompress_done(struct bio *bp)
 	struct g_geom *gp;
 	struct bio *bp2;
 	uint32_t start_blk, i;
-	off_t pos, upos;
+	off_t iolen, pos, upos;
 	size_t bsize;
 	int err;
 
@@ -210,6 +210,7 @@ g_uncompress_done(struct bio *bp)
 	 */
 	start_blk = bp2->bio_offset / sc->blksz;
 	bsize = pp2->sectorsize;
+	iolen = bp->bio_completed;
 	pos = sc->offsets[start_blk] % bsize;
 	upos = 0;
 
@@ -239,6 +240,13 @@ g_uncompress_done(struct bio *bp)
 			continue;
 		}
 
+		if (len > iolen) {
+			DPRINTF(("%s: done: early termination: len (%jd) > "
+			    "iolen (%jd)\n",
+			    gp->name, (intmax_t)len, (intmax_t)iolen));
+			break;
+		}
+
 		mtx_lock(&sc->last_mtx);
 
 #ifdef GEOM_UNCOMPRESS_DEBUG
@@ -292,6 +300,7 @@ g_uncompress_done(struct bio *bp)
 		mtx_unlock(&sc->last_mtx);
 
 		pos += len;
+		iolen -= len;
 		upos += ulen;
 		bp2->bio_completed += ulen;
 	}
@@ -380,10 +389,18 @@ g_uncompress_start(struct bio *bp)
 	bsize = pp2->sectorsize;
 
 	bp2->bio_done = g_uncompress_done;
-	bp2->bio_offset = rounddown(sc->offsets[start_blk],bsize);
-	bp2->bio_length = roundup(sc->offsets[end_blk],bsize) -
-	    bp2->bio_offset;
-	bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UNCOMPRESS, M_NOWAIT);
+	bp2->bio_offset = rounddown(sc->offsets[start_blk], bsize);
+	while (1) {
+		bp2->bio_length = roundup(sc->offsets[end_blk], bsize) -
+		    bp2->bio_offset;
+		if (bp2->bio_length < MAXPHYS)
+			break;
+
+		end_blk--;
+		DPRINTF((
+		    "%s: bio_length (%jd) > MAXPHYS: lowering end_blk to %u\n",
+		    gp->name, (intmax_t)bp2->bio_length, end_blk));
+	}
 
 	DPRINTF(("%s: start %jd + %jd -> %ju + %ju -> %jd + %jd\n",
 	    gp->name,
@@ -392,6 +409,7 @@ g_uncompress_start(struct bio *bp)
 	    (uintmax_t)sc->offsets[end_blk] - sc->offsets[start_blk],
 	    (intmax_t)bp2->bio_offset, (intmax_t)bp2->bio_length));
 
+	bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UNCOMPRESS, M_NOWAIT);
 	if (bp2->bio_data == NULL) {
 		g_destroy_bio(bp2);
 		g_io_deliver(bp, ENOMEM);



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