diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index f52cc6d93939..5bafdd32681d 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -153,6 +153,7 @@ MAN= aac.4 \ geom_fox.4 \ geom_linux_lvm.4 \ geom_map.4 \ + geom_uncompress.4 \ geom_uzip.4 \ gif.4 \ gpib.4 \ diff --git a/share/man/man4/geom_uncompress.4 b/share/man/man4/geom_uncompress.4 new file mode 100644 index 000000000000..6e848d430fac --- /dev/null +++ b/share/man/man4/geom_uncompress.4 @@ -0,0 +1,107 @@ +.\" Copyright (c) 2014, Luiz Otavio O Souza +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 9, 2014 +.Dt GEOM_UNCOMPRESS 4 +.Os +.Sh NAME +.Nm geom_uncompress +.Nd "GEOM based compressed disk images" +.Sh SYNOPSIS +To compile this driver into the kernel, place the following line in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "options GEOM_UNCOMPRESS" +.Ed +.Pp +Alternatively, to load the driver as a module at boot time, place the +following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +geom_uncompress_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +framework provides support for compressed read only disk images. +This allows significant storage savings at the expense of a little CPU +time on each read. +Data written in the GEOM label area allows +.Nm +to detect compressed images which have been created with +.Xr mkulzma 8 +or +.Xr mkuzip 8 +and presented to the kernel as a logical disk device via +.Xr md 4 . +.Nm +creates a unique +.Pa md#.uncompress +device for each image. +.Pp +The +.Nm +device is subsequently used by the +.Fx +kernel to access the disk images. +The +.Nm +driver does not allow write operations to the underlying disk image. +To check which +.Xr md 4 +devices match a given +.Nm +device: +.Bd -literal -offset indent +# geom uncompress list +Geom name: md0.uncompress +Providers: +1. Name: md0.uncompress + Mediasize: 52428800 (50M) + Sectorsize: 512 + Mode: r1w0e0 +Consumers: +1. Name: md0 + Mediasize: 20864000 (20M) + Sectorsize: 512 + Mode: r1w0e0 +.Ed +.Sh SEE ALSO +.Xr GEOM 4 , +.Xr md 4 , +.Xr geom 8 , +.Xr mkulzma 8 , +.Xr mkuzip 8 +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An "Maxim Sobolev" Aq sobomax@FreeBSD.org +and +.An "Aleksandr Rybalko" Aq ray@FreeBSD.org . +This manual page was written by +.An "Luiz Otavio O Souza" Aq loos@FreeBSD.org . diff --git a/sys/geom/uncompress/g_uncompress.c b/sys/geom/uncompress/g_uncompress.c index d2948ef0c28e..5bc8d30bc1de 100644 --- a/sys/geom/uncompress/g_uncompress.c +++ b/sys/geom/uncompress/g_uncompress.c @@ -116,7 +116,7 @@ g_uncompress_softc_free(struct g_uncompress_softc *sc, struct g_geom *gp) } if (sc->offsets != NULL) { free(sc->offsets, M_GEOM_UNCOMPRESS); - sc->offsets = 0; + sc->offsets = NULL; } switch (sc->type) { @@ -150,6 +150,7 @@ z_alloc(void *nil, u_int type, u_int size) void *ptr; ptr = malloc(type * size, M_GEOM_UNCOMPRESS, M_NOWAIT); + return (ptr); } @@ -169,7 +170,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,24 +211,27 @@ 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; - DPRINTF(("%s: done: bio_length %lld bio_completed %lld start_blk %d, " - "pos %lld, upos %lld (%lld, %d, %d)\n", - gp->name, bp->bio_length, bp->bio_completed, start_blk, pos, upos, - bp2->bio_offset, sc->blksz, bsize)); + DPRINTF(("%s: done: bio_length %jd bio_completed %jd start_blk %d, " + "pos %jd, upos %jd (%jd, %d, %zu)\n", + gp->name, (intmax_t)bp->bio_length, (intmax_t)bp->bio_completed, + start_blk, (intmax_t)pos, (intmax_t)upos, + (intmax_t)bp2->bio_offset, sc->blksz, bsize)); for (i = start_blk; upos < bp2->bio_length; i++) { - off_t len, dlen, ulen, uoff; + off_t len, ulen, uoff; uoff = i == start_blk ? bp2->bio_offset % sc->blksz : 0; ulen = MIN(sc->blksz - uoff, bp2->bio_length - upos); - dlen = len = sc->offsets[i + 1] - sc->offsets[i]; + len = sc->offsets[i + 1] - sc->offsets[i]; - DPRINTF(("%s: done: inflate block %d, start %lld, end %lld " - "len %lld\n", - gp->name, i, sc->offsets[i], sc->offsets[i + 1], len)); + DPRINTF(( + "%s: done: inflate block %d, start %ju, end %ju len %jd\n", + gp->name, i, (uintmax_t)sc->offsets[i], + (uintmax_t)sc->offsets[i + 1], (intmax_t)len)); if (len == 0) { /* All zero block: no cache update */ @@ -236,12 +240,17 @@ g_uncompress_done(struct bio *bp) bp2->bio_completed += ulen; 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 if (g_debugflags & 32) - hexdump(bp->bio_data + pos, dlen, 0, 0); + hexdump(bp->bio_data + pos, len, 0, 0); #endif switch (sc->type) { @@ -249,7 +258,7 @@ g_uncompress_done(struct bio *bp) sc->b->in = bp->bio_data + pos; sc->b->out = sc->last_buf; sc->b->in_pos = sc->b->out_pos = 0; - sc->b->in_size = dlen; + sc->b->in_size = len; sc->b->out_size = (size_t)-1; err = (xz_dec_run(sc->s, sc->b) != XZ_STREAM_END) ? @@ -258,13 +267,13 @@ g_uncompress_done(struct bio *bp) break; case GEOM_UZIP: sc->zs->next_in = bp->bio_data + pos; - sc->zs->avail_in = dlen; + sc->zs->avail_in = len; sc->zs->next_out = sc->last_buf; sc->zs->avail_out = sc->blksz; err = (inflate(sc->zs, Z_FINISH) != Z_STREAM_END) ? 1 : 0; - if ((err) && (inflateReset(sc->zs) != Z_OK)) + if ((err) || (inflateReset(sc->zs) != Z_OK)) printf("%s: UZIP decoder reset failed\n", gp->name); break; @@ -290,6 +299,7 @@ g_uncompress_done(struct bio *bp) mtx_unlock(&sc->last_mtx); pos += len; + iolen -= len; upos += ulen; bp2->bio_completed += ulen; } @@ -298,8 +308,9 @@ done: /* * Finish processing the request. */ - DPRINTF(("%s: done: (%d, %lld, %ld)\n", - gp->name, bp2->bio_error, bp2->bio_completed, bp2->bio_resid)); + DPRINTF(("%s: done: (%d, %jd, %ld)\n", + gp->name, bp2->bio_error, (intmax_t)bp2->bio_completed, + bp2->bio_resid)); free(bp->bio_data, M_GEOM_UNCOMPRESS); g_destroy_bio(bp); g_io_deliver(bp2, bp2->bio_error); @@ -316,12 +327,12 @@ g_uncompress_start(struct bio *bp) uint32_t start_blk, end_blk; size_t bsize; - pp = bp->bio_to; gp = pp->geom; - DPRINTF(("%s: start (%s) to %s off=%lld len=%lld\n", gp->name, - (bp->bio_cmd==BIO_READ) ? "BIO_READ" : "BIO_WRITE*", - pp->name, bp->bio_offset, bp->bio_length)); + DPRINTF(("%s: start (%d:%s) to %s off=%jd len=%jd\n", + gp->name, bp->bio_cmd, + (bp->bio_cmd == BIO_READ) ? "BIO_READ" : "NOTSUPPORTED", + pp->name, (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length)); if (bp->bio_cmd != BIO_READ) { g_io_deliver(bp, EOPNOTSUPP); @@ -334,10 +345,8 @@ g_uncompress_start(struct bio *bp) start_blk = bp->bio_offset / sc->blksz; end_blk = howmany(bp->bio_offset + bp->bio_length, sc->blksz); - KASSERT(start_blk < sc->nblocks, - ("start_blk out of range")); - KASSERT(end_blk <= sc->nblocks, - ("end_blk out of range")); + KASSERT(start_blk < sc->nblocks, ("start_blk out of range")); + KASSERT(end_blk <= sc->nblocks, ("end_blk out of range")); sc->req_total++; if (start_blk + 1 == end_blk) { @@ -353,9 +362,9 @@ g_uncompress_start(struct bio *bp) sc->req_cached++; mtx_unlock(&sc->last_mtx); - DPRINTF(("%s: start: cached 0 + %lld, " - "%lld + 0 + %lld\n", - gp->name, bp->bio_length, uoff, bp->bio_length)); + DPRINTF(("%s: start: cached 0 + %jd, %jd + 0 + %jd\n", + gp->name, (intmax_t)bp->bio_length, (intmax_t)uoff, + (intmax_t)bp->bio_length)); bp->bio_completed = bp->bio_length; g_io_deliver(bp, 0); return; @@ -368,26 +377,31 @@ g_uncompress_start(struct bio *bp) g_io_deliver(bp, ENOMEM); return; } - DPRINTF(("%s: start (%d..%d), %s: %d + %llu, %s: %d + %llu\n", + DPRINTF(("%s: start (%d..%d), %s: %d + %jd, %s: %d + %jd\n", gp->name, start_blk, end_blk, - pp->name, pp->sectorsize, pp->mediasize, - pp2->name, pp2->sectorsize, pp2->mediasize)); - + pp->name, pp->sectorsize, (intmax_t)pp->mediasize, + pp2->name, pp2->sectorsize, (intmax_t)pp2->mediasize)); 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; - DPRINTF(("%s: start %lld + %lld -> %lld + %lld -> %lld + %lld\n", + 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, - bp->bio_offset, bp->bio_length, - sc->offsets[start_blk], - sc->offsets[end_blk] - sc->offsets[start_blk], - bp2->bio_offset, bp2->bio_length)); - + (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length, + (uintmax_t)sc->offsets[start_blk], + (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); @@ -403,8 +417,7 @@ g_uncompress_orphan(struct g_consumer *cp) { struct g_geom *gp; - g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, - cp->provider->name); + g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, cp->provider->name); g_topology_assert(); gp = cp->geom; @@ -451,7 +464,7 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags) struct g_provider *pp2; struct g_consumer *cp; struct g_geom *gp; - uint32_t i, total_offsets, offsets_read, type; + uint32_t i, total_offsets, type; uint8_t *buf; int error; @@ -484,17 +497,15 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags) * Read cloop header, look for CLOOP magic, perform * other validity checks. */ - DPRINTF(("%s: media sectorsize %u, mediasize %lld\n", - gp->name, pp->sectorsize, pp->mediasize)); - + DPRINTF(("%s: media sectorsize %u, mediasize %jd\n", + gp->name, pp->sectorsize, (intmax_t)pp->mediasize)); i = roundup(sizeof(struct cloop_header), pp->sectorsize); buf = g_read_data(cp, 0, i, NULL); if (buf == NULL) goto err; - header = (struct cloop_header *) buf; if (strncmp(header->magic, CLOOP_MAGIC_START, - sizeof(CLOOP_MAGIC_START) - 1) != 0) { + sizeof(CLOOP_MAGIC_START) - 1) != 0) { DPRINTF(("%s: no CLOOP magic\n", gp->name)); goto err; } @@ -546,25 +557,20 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags) gp->name, sc->nblocks); goto err; } - sc->offsets = malloc( - total_offsets * sizeof(uint64_t), M_GEOM_UNCOMPRESS, M_WAITOK); - offsets_read = MIN(total_offsets, - (pp->sectorsize - sizeof(*header)) / sizeof(uint64_t)); - for (i = 0; i < offsets_read; i++) - sc->offsets[i] = be64toh(((uint64_t *) (header + 1))[i]); - DPRINTF(("%s: %u offsets in the first sector\n", - gp->name, offsets_read)); - free(buf, M_GEOM); + i = roundup((sizeof(struct cloop_header) + - total_offsets * sizeof(uint64_t)),pp->sectorsize); + total_offsets * sizeof(uint64_t)), pp->sectorsize); buf = g_read_data(cp, 0, i, NULL); if (buf == NULL) goto err; + sc->offsets = malloc(total_offsets * sizeof(uint64_t), + M_GEOM_UNCOMPRESS, M_WAITOK); for (i = 0; i <= total_offsets; i++) { sc->offsets[i] = be64toh(((uint64_t *) (buf+sizeof(struct cloop_header)))[i]); } + free(buf, M_GEOM); DPRINTF(("%s: done reading offsets\n", gp->name)); mtx_init(&sc->last_mtx, "geom_uncompress cache", NULL, MTX_DEF); sc->last_blk = -1; @@ -599,15 +605,13 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags) pp2->stripeoffset = pp->stripeoffset; } g_error_provider(pp2, 0); - free(buf, M_GEOM); g_access(cp, -1, 0, 0); - DPRINTF(("%s: taste ok (%d, %lld), (%d, %d), %x\n", + DPRINTF(("%s: taste ok (%d, %jd), (%d, %d), %x\n", gp->name, - pp2->sectorsize, pp2->mediasize, + pp2->sectorsize, (intmax_t)pp2->mediasize, pp2->stripeoffset, pp2->stripesize, pp2->flags)); - printf("%s: %u x %u blocks\n", - gp->name, sc->nblocks, sc->blksz); + printf("%s: %u x %u blocks\n", gp->name, sc->nblocks, sc->blksz); return (gp); err: @@ -622,6 +626,7 @@ err: g_detach(cp); g_destroy_consumer(cp); g_destroy_geom(gp); + return (NULL); } @@ -648,6 +653,7 @@ g_uncompress_destroy_geom(struct gctl_req *req, struct g_class *mp, g_uncompress_softc_free(gp->softc, gp); gp->softc = NULL; g_wither_geom(gp, ENXIO); + return (0); } @@ -664,4 +670,4 @@ static struct g_class g_uncompress_class = { }; DECLARE_GEOM_CLASS(g_uncompress_class, g_uncompress); - +MODULE_DEPEND(g_uncompress, zlib, 1, 1, 1); diff --git a/sys/geom/uzip/g_uzip.c b/sys/geom/uzip/g_uzip.c index 917789f2ed51..1dacfa0b4e9e 100644 --- a/sys/geom/uzip/g_uzip.c +++ b/sys/geom/uzip/g_uzip.c @@ -35,8 +35,8 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include +#include #include #include @@ -45,19 +45,19 @@ FEATURE(geom_uzip, "GEOM uzip read-only compressed disks support"); #undef GEOM_UZIP_DEBUG #ifdef GEOM_UZIP_DEBUG -#define DPRINTF(a) printf a +#define DPRINTF(a) printf a #else -#define DPRINTF(a) +#define DPRINTF(a) #endif static MALLOC_DEFINE(M_GEOM_UZIP, "geom_uzip", "GEOM UZIP data structures"); -#define UZIP_CLASS_NAME "UZIP" +#define UZIP_CLASS_NAME "UZIP" /* * Maximum allowed valid block size (to prevent foot-shooting) */ -#define MAX_BLKSZ (MAXPHYS - MAXPHYS / 1000 - 12) +#define MAX_BLKSZ (MAXPHYS - MAXPHYS / 1000 - 12) /* * Integer values (block size, number of blocks, offsets) @@ -65,7 +65,7 @@ static MALLOC_DEFINE(M_GEOM_UZIP, "geom_uzip", "GEOM UZIP data structures"); * and in native order in struct g_uzip_softc */ -#define CLOOP_MAGIC_LEN 128 +#define CLOOP_MAGIC_LEN 128 static char CLOOP_MAGIC_START[] = "#!/bin/sh\n"; struct cloop_header { @@ -89,12 +89,15 @@ struct g_uzip_softc { static void g_uzip_softc_free(struct g_uzip_softc *sc, struct g_geom *gp) { + if (gp != NULL) { printf("%s: %d requests, %d cached\n", gp->name, sc->req_total, sc->req_cached); } - if (sc->offsets != NULL) + if (sc->offsets != NULL) { free(sc->offsets, M_GEOM_UZIP); + sc->offsets = NULL; + } mtx_destroy(&sc->last_mtx); free(sc->last_buf, M_GEOM_UZIP); free(sc, M_GEOM_UZIP); @@ -106,12 +109,14 @@ z_alloc(void *nil, u_int type, u_int size) void *ptr; ptr = malloc(type * size, M_GEOM_UZIP, M_NOWAIT); - return ptr; + + return (ptr); } static void z_free(void *nil, void *ptr) { + free(ptr, M_GEOM_UZIP); } @@ -125,7 +130,7 @@ g_uzip_done(struct bio *bp) struct g_consumer *cp; struct g_geom *gp; struct g_uzip_softc *sc; - off_t pos, upos; + off_t iolen, pos, upos; uint32_t start_blk, i; size_t bsize; @@ -153,11 +158,13 @@ g_uzip_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; - DPRINTF(("%s: done: start_blk %d, pos %lld, upos %lld (%lld, %d, %d)\n", - gp->name, start_blk, pos, upos, - bp2->bio_offset, sc->blksz, bsize)); + DPRINTF(("%s: done: start_blk %d, pos %jd, upos %jd, iolen %jd " + "(%jd, %d, %zd)\n", + gp->name, start_blk, (intmax_t)pos, (intmax_t)upos, + (intmax_t)iolen, (intmax_t)bp2->bio_offset, sc->blksz, bsize)); for (i = start_blk; upos < bp2->bio_length; i++) { off_t len, ulen, uoff; @@ -172,6 +179,12 @@ g_uzip_done(struct bio *bp) bp2->bio_completed += ulen; continue; } + if (len > iolen) { + DPRINTF(("%s: done: early termination: len (%jd) > " + "iolen (%jd)\n", + gp->name, (intmax_t)len, (intmax_t)iolen)); + break; + } zs.next_in = bp->bio_data + pos; zs.avail_in = len; zs.next_out = sc->last_buf; @@ -181,21 +194,22 @@ g_uzip_done(struct bio *bp) if (err != Z_STREAM_END) { sc->last_blk = -1; mtx_unlock(&sc->last_mtx); - DPRINTF(("%s: done: inflate failed (%lld + %lld -> %lld + %lld + %lld)\n", - gp->name, pos, len, uoff, upos, ulen)); + DPRINTF(("%s: done: inflate failed (%jd + %jd -> %jd + %jd + %jd)\n", + gp->name, (intmax_t)pos, (intmax_t)len, + (intmax_t)uoff, (intmax_t)upos, (intmax_t)ulen)); inflateEnd(&zs); bp2->bio_error = EIO; goto done; } sc->last_blk = i; - DPRINTF(("%s: done: inflated %lld + %lld -> %lld + %lld + %lld\n", - gp->name, - pos, len, - uoff, upos, ulen)); + DPRINTF(("%s: done: inflated %jd + %jd -> %jd + %jd + %jd\n", + gp->name, (intmax_t)pos, (intmax_t)len, (intmax_t)uoff, + (intmax_t)upos, (intmax_t)ulen)); memcpy(bp2->bio_data + upos, sc->last_buf + uoff, ulen); mtx_unlock(&sc->last_mtx); pos += len; + iolen -= len; upos += ulen; bp2->bio_completed += ulen; err = inflateReset(&zs); @@ -215,8 +229,9 @@ done: /* * Finish processing the request. */ - DPRINTF(("%s: done: (%d, %lld, %ld)\n", - gp->name, bp2->bio_error, bp2->bio_completed, bp2->bio_resid)); + DPRINTF(("%s: done: (%d, %jd, %ld)\n", + gp->name, bp2->bio_error, (intmax_t)bp2->bio_completed, + bp2->bio_resid)); free(bp->bio_data, M_GEOM_UZIP); g_destroy_bio(bp); g_io_deliver(bp2, bp2->bio_error); @@ -248,10 +263,8 @@ g_uzip_start(struct bio *bp) start_blk = bp->bio_offset / sc->blksz; end_blk = (bp->bio_offset + bp->bio_length + sc->blksz - 1) / sc->blksz; - KASSERT(start_blk < sc->nblocks, - ("start_blk out of range")); - KASSERT(end_blk <= sc->nblocks, - ("end_blk out of range")); + KASSERT(start_blk < sc->nblocks, ("start_blk out of range")); + KASSERT(end_blk <= sc->nblocks, ("end_blk out of range")); sc->req_total++; if (start_blk + 1 == end_blk) { @@ -267,8 +280,9 @@ g_uzip_start(struct bio *bp) sc->req_cached++; mtx_unlock(&sc->last_mtx); - DPRINTF(("%s: start: cached 0 + %lld, %lld + 0 + %lld\n", - gp->name, bp->bio_length, uoff, bp->bio_length)); + DPRINTF(("%s: start: cached 0 + %jd, %jd + 0 + %jd\n", + gp->name, (intmax_t)bp->bio_length, (intmax_t)uoff, + (intmax_t)bp->bio_length)); bp->bio_completed = bp->bio_length; g_io_deliver(bp, 0); return; @@ -282,19 +296,28 @@ g_uzip_start(struct bio *bp) return; } bp2->bio_done = g_uzip_done; - DPRINTF(("%s: start (%d..%d), %s: %d + %lld, %s: %d + %lld\n", + DPRINTF(("%s: start (%d..%d), %s: %d + %jd, %s: %d + %jd\n", gp->name, start_blk, end_blk, - pp->name, pp->sectorsize, pp->mediasize, - pp2->name, pp2->sectorsize, pp2->mediasize)); + pp->name, pp->sectorsize, (intmax_t)pp->mediasize, + pp2->name, pp2->sectorsize, (intmax_t)pp2->mediasize)); bsize = pp2->sectorsize; bp2->bio_offset = sc->offsets[start_blk] - sc->offsets[start_blk] % bsize; - bp2->bio_length = sc->offsets[end_blk] - bp2->bio_offset; - bp2->bio_length = (bp2->bio_length + bsize - 1) / bsize * bsize; - DPRINTF(("%s: start %lld + %lld -> %lld + %lld -> %lld + %lld\n", + while (1) { + bp2->bio_length = sc->offsets[end_blk] - bp2->bio_offset; + bp2->bio_length = (bp2->bio_length + bsize - 1) / bsize * bsize; + 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, - bp->bio_offset, bp->bio_length, - sc->offsets[start_blk], sc->offsets[end_blk] - sc->offsets[start_blk], - bp2->bio_offset, bp2->bio_length)); + (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length, + (uintmax_t)sc->offsets[start_blk], + (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_UZIP, M_NOWAIT); if (bp2->bio_data == NULL) { g_destroy_bio(bp2); @@ -311,7 +334,7 @@ g_uzip_orphan(struct g_consumer *cp) { struct g_geom *gp; - g_trace(G_T_TOPOLOGY, "g_uzip_orphan(%p/%s)", cp, cp->provider->name); + g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, cp->provider->name); g_topology_assert(); gp = cp->geom; @@ -331,7 +354,7 @@ g_uzip_access(struct g_provider *pp, int dr, int dw, int de) KASSERT (cp != NULL, ("g_uzip_access but no consumer")); if (cp->acw + dw > 0) - return EROFS; + return (EROFS); return (g_access(cp, dr, dw, de)); } @@ -342,7 +365,7 @@ g_uzip_spoiled(struct g_consumer *cp) struct g_geom *gp; gp = cp->geom; - g_trace(G_T_TOPOLOGY, "g_uzip_spoiled(%p/%s)", cp, gp->name); + g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, gp->name); g_topology_assert(); g_uzip_softc_free(gp->softc, gp); @@ -362,7 +385,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) struct g_provider *pp2; struct g_uzip_softc *sc; - g_trace(G_T_TOPOLOGY, "g_uzip_taste(%s,%s)", mp->name, pp->name); + g_trace(G_T_TOPOLOGY, "%s(%s,%s)", __func__, mp->name, pp->name); g_topology_assert(); /* Skip providers that are already open for writing. */ @@ -391,14 +414,14 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) * Read cloop header, look for CLOOP magic, perform * other validity checks. */ - DPRINTF(("%s: media sectorsize %u, mediasize %lld\n", - gp->name, pp->sectorsize, pp->mediasize)); + DPRINTF(("%s: media sectorsize %u, mediasize %jd\n", + gp->name, pp->sectorsize, (intmax_t)pp->mediasize)); buf = g_read_data(cp, 0, pp->sectorsize, NULL); if (buf == NULL) goto err; header = (struct cloop_header *) buf; if (strncmp(header->magic, CLOOP_MAGIC_START, - sizeof(CLOOP_MAGIC_START) - 1) != 0) { + sizeof(CLOOP_MAGIC_START) - 1) != 0) { DPRINTF(("%s: no CLOOP magic\n", gp->name)); goto err; } @@ -427,7 +450,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) if (sizeof(struct cloop_header) + total_offsets * sizeof(uint64_t) > pp->mediasize) { printf("%s: media too small for %u blocks\n", - gp->name, sc->nblocks); + gp->name, sc->nblocks); goto err; } sc->offsets = malloc( @@ -456,6 +479,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) } offsets_read += nread; } + free(buf, M_GEOM); DPRINTF(("%s: done reading offsets\n", gp->name)); mtx_init(&sc->last_mtx, "geom_uzip cache", NULL, MTX_DEF); sc->last_blk = -1; @@ -467,17 +491,16 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) pp2 = g_new_providerf(gp, "%s", gp->name); pp2->sectorsize = 512; pp2->mediasize = (off_t)sc->nblocks * sc->blksz; - pp2->stripesize = pp->stripesize; - pp2->stripeoffset = pp->stripeoffset; + pp2->stripesize = pp->stripesize; + pp2->stripeoffset = pp->stripeoffset; g_error_provider(pp2, 0); g_access(cp, -1, 0, 0); - DPRINTF(("%s: taste ok (%d, %lld), (%d, %d), %x\n", + DPRINTF(("%s: taste ok (%d, %jd), (%d, %d), %x\n", gp->name, - pp2->sectorsize, pp2->mediasize, + pp2->sectorsize, (intmax_t)pp2->mediasize, pp2->stripeoffset, pp2->stripesize, pp2->flags)); - printf("%s: %u x %u blocks\n", - gp->name, sc->nblocks, sc->blksz); + printf("%s: %u x %u blocks\n", gp->name, sc->nblocks, sc->blksz); return (gp); err: @@ -492,6 +515,7 @@ err: g_detach(cp); g_destroy_consumer(cp); g_destroy_geom(gp); + return (NULL); } @@ -500,7 +524,7 @@ g_uzip_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp) { struct g_provider *pp; - g_trace(G_T_TOPOLOGY, "g_uzip_destroy_geom(%s, %s)", mp->name, gp->name); + g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, gp->name); g_topology_assert(); if (gp->softc == NULL) { @@ -517,6 +541,7 @@ g_uzip_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp) g_uzip_softc_free(gp->softc, gp); gp->softc = NULL; g_wither_geom(gp, ENXIO); + return (0); } diff --git a/sys/modules/geom/Makefile b/sys/modules/geom/Makefile index ca7d7e639558..74166400d740 100644 --- a/sys/modules/geom/Makefile +++ b/sys/modules/geom/Makefile @@ -24,6 +24,7 @@ SUBDIR= geom_bde \ geom_shsec \ geom_stripe \ geom_sunlabel \ + geom_uncompress \ geom_uzip \ geom_vinum \ geom_virstor \ diff --git a/sys/modules/geom/geom_uncompress/Makefile b/sys/modules/geom/geom_uncompress/Makefile index 3bec55a8389d..ab0912e4e1c1 100644 --- a/sys/modules/geom/geom_uncompress/Makefile +++ b/sys/modules/geom/geom_uncompress/Makefile @@ -7,11 +7,11 @@ ${.CURDIR}/../../../net KMOD= geom_uncompress -CFLAGS= -I${.CURDIR}/../../../geom/uncompress/ \ +CFLAGS+= -I${.CURDIR}/../../../geom/uncompress/ \ -I${.CURDIR}/../../../contrib/xz-embedded/freebsd \ -I${.CURDIR}/../../../contrib/xz-embedded/linux/lib/xz/ SRCS= g_uncompress.c xz_crc32.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c \ - xz_malloc.c zlib.c + xz_malloc.c SRCS+= xz.h xz_config.h xz_lzma2.h xz_malloc.h xz_private.h xz_stream.h zlib.h .include