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>