svn commit: r264769 - head/sys/geom/uncompress
Luiz Otavio O Souza
loos at FreeBSD.org
Tue Apr 22 18:08:35 UTC 2014
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);
More information about the svn-src-all
mailing list