Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150741535
D7013.id18019.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D7013.id18019.diff
View Options
Index: head/sys/geom/uzip/g_uzip.c
===================================================================
--- head/sys/geom/uzip/g_uzip.c
+++ head/sys/geom/uzip/g_uzip.c
@@ -60,6 +60,8 @@
struct g_uzip_blk {
uint64_t offset;
uint32_t blen;
+ unsigned char last:1;
+ unsigned char padded:1;
#define BLEN_UNDEF UINT32_MAX
};
@@ -84,6 +86,16 @@
#define GUZ_DBG_IO 3
#define GUZ_DBG_TOC 4
+#define GUZ_DEV_SUFX ".uzip"
+#define GUZ_DEV_NAME(p) (p GUZ_DEV_SUFX)
+
+static char g_uzip_attach_to[MAXPATHLEN] = {"*"};
+static char g_uzip_noattach_to[MAXPATHLEN] = {GUZ_DEV_NAME("*")};
+TUNABLE_STR("kern.geom.uzip.attach_to", g_uzip_attach_to,
+ sizeof(g_uzip_attach_to));
+TUNABLE_STR("kern.geom.uzip.noattach_to", g_uzip_noattach_to,
+ sizeof(g_uzip_noattach_to));
+
SYSCTL_DECL(_kern_geom);
SYSCTL_NODE(_kern_geom, OID_AUTO, uzip, CTLFLAG_RW, 0, "GEOM_UZIP stuff");
static u_int g_uzip_debug = GEOM_UZIP_DBG_DEFAULT;
@@ -258,8 +270,9 @@
}
DPRINTF_BRNG(GUZ_DBG_IO, start_blk, end_blk, ("%s/%s: %p: "
- "start=%u (%ju), end=%u (%ju)\n", __func__, gp->name, bp,
+ "start=%u (%ju[%jd]), end=%u (%ju)\n", __func__, gp->name, bp,
(u_int)start_blk, (uintmax_t)sc->toc[start_blk].offset,
+ (intmax_t)sc->toc[start_blk].blen,
(u_int)end_blk, (uintmax_t)BLK_ENDS(sc, end_blk - 1)));
bp2 = g_clone_bio(bp);
@@ -272,16 +285,18 @@
bp2->bio_offset = TOFF_2_BOFF(sc, pp, start_blk);
while (1) {
bp2->bio_length = TLEN_2_BLEN(sc, pp, bp2, end_blk - 1);
- if (bp2->bio_length <= MAXPHYS)
+ if (bp2->bio_length <= MAXPHYS) {
break;
+ }
if (end_blk == (start_blk + 1)) {
break;
}
end_blk--;
}
- DPRINTF(GUZ_DBG_IO, ("%s/%s: bp2->bio_length = %jd\n",
- __func__, gp->name, (intmax_t)bp2->bio_length));
+ DPRINTF(GUZ_DBG_IO, ("%s/%s: bp2->bio_length = %jd, "
+ "bp2->bio_offset = %jd\n", __func__, gp->name,
+ (intmax_t)bp2->bio_length, (intmax_t)bp2->bio_offset));
bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UZIP, M_NOWAIT);
if (bp2->bio_data == NULL) {
@@ -315,6 +330,15 @@
wakeup(sc);
}
+static int
+g_uzip_memvcmp(const void *memory, unsigned char val, size_t size)
+{
+ const u_char *mm;
+
+ mm = (const u_char *)memory;
+ return (*mm == val) && memcmp(mm, mm + 1, size - 1) == 0;
+}
+
static void
g_uzip_do(struct g_uzip_softc *sc, struct bio *bp)
{
@@ -362,18 +386,33 @@
bp->bio_completed, data2, (u_int)ulen, data, (u_int)len));
if (len == 0) {
/* All zero block: no cache update */
+zero_block:
bzero(data2, ulen);
} else if (len <= bp->bio_completed) {
mtx_lock(&sc->last_mtx);
err = sc->dcp->decompress(sc->dcp, gp->name, data,
len, sc->last_buf);
+ if (err != 0 && sc->toc[blk].last != 0) {
+ /*
+ * Last block decompression has failed, check
+ * if it's just zero padding.
+ */
+ if (g_uzip_memvcmp(data, '\0', len) == 0) {
+ sc->toc[blk].blen = 0;
+ sc->last_blk = -1;
+ mtx_unlock(&sc->last_mtx);
+ len = 0;
+ goto zero_block;
+ }
+ }
if (err != 0) {
sc->last_blk = -1;
mtx_unlock(&sc->last_mtx);
bp2->bio_error = EILSEQ;
DPRINTF(GUZ_DBG_ERR, ("%s/%s: decompress"
- "(%p) failed\n", __func__, gp->name,
- sc->dcp));
+ "(%p, %ju, %ju) failed\n", __func__,
+ gp->name, sc->dcp, (uintmax_t)blk,
+ (uintmax_t)len));
goto done;
}
sc->last_blk = blk;
@@ -471,6 +510,7 @@
{
struct g_geom *gp;
+ G_VALID_CONSUMER(cp);
gp = cp->geom;
g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, gp->name);
g_topology_assert();
@@ -486,10 +526,12 @@
{
uint32_t i, j, backref_to;
uint64_t max_offset, min_offset;
+ struct g_uzip_blk *last_blk;
min_offset = sizeof(struct cloop_header) +
(sc->nblocks + 1) * sizeof(uint64_t);
max_offset = sc->toc[0].offset - 1;
+ last_blk = &sc->toc[0];
for (i = 0; i < sc->nblocks; i++) {
/* First do some bounds checking */
if ((sc->toc[i].offset < min_offset) ||
@@ -497,7 +539,7 @@
goto error_offset;
}
DPRINTF_BLK(GUZ_DBG_IO, i, ("%s: cluster #%u "
- "sc->toc[i].offset=%ju max_offset=%ju\n", gp->name,
+ "offset=%ju max_offset=%ju\n", gp->name,
(u_int)i, (uintmax_t)sc->toc[i].offset,
(uintmax_t)max_offset));
backref_to = BLEN_UNDEF;
@@ -523,6 +565,7 @@
sc->toc[i].blen = sc->toc[j].blen;
backref_to = j;
} else {
+ last_blk = &sc->toc[i];
/*
* For the "normal blocks" seek forward until we hit
* block whose offset is larger than ours and assume
@@ -557,6 +600,25 @@
}
DPRINTF_BLK(GUZ_DBG_TOC, i, ("\n"));
}
+ last_blk->last = 1;
+ /* Do a second pass to validate block lengths */
+ for (i = 0; i < sc->nblocks; i++) {
+ if (sc->toc[i].blen > sc->dcp->max_blen) {
+ if (sc->toc[i].last == 0) {
+ DPRINTF(GUZ_DBG_ERR, ("%s: cluster #%u "
+ "length (%ju) exceeds "
+ "max_blen (%ju)\n", gp->name, i,
+ (uintmax_t)sc->toc[i].blen,
+ (uintmax_t)sc->dcp->max_blen));
+ return (-1);
+ }
+ DPRINTF(GUZ_DBG_INFO, ("%s: cluster #%u extra "
+ "padding is detected, trimmed to %ju\n",
+ gp->name, i, (uintmax_t)sc->dcp->max_blen));
+ sc->toc[i].blen = sc->dcp->max_blen;
+ sc->toc[i].padded = 1;
+ }
+ }
return (0);
error_offset:
@@ -589,12 +651,19 @@
if (pp->acw > 0)
return (NULL);
+ if ((fnmatch(g_uzip_attach_to, pp->name, 0) != 0) ||
+ (fnmatch(g_uzip_noattach_to, pp->name, 0) == 0)) {
+ DPRINTF(GUZ_DBG_INFO, ("%s(%s,%s), ignoring\n", __func__,
+ mp->name, pp->name));
+ return (NULL);
+ }
+
buf = NULL;
/*
* Create geom instance.
*/
- gp = g_new_geomf(mp, "%s.uzip", pp->name);
+ gp = g_new_geomf(mp, GUZ_DEV_NAME("%s"), pp->name);
cp = g_new_consumer(gp);
error = g_attach(cp, pp);
if (error == 0)
@@ -712,6 +781,16 @@
sc->nblocks < offsets_read ? "more" : "less"));
goto e5;
}
+
+ if (type == G_UZIP) {
+ sc->dcp = g_uzip_zlib_ctor(sc->blksz);
+ } else {
+ sc->dcp = g_uzip_lzma_ctor(sc->blksz);
+ }
+ if (sc->dcp == NULL) {
+ goto e5;
+ }
+
/*
* "Fake" last+1 block, to make it easier for the TOC parser to
* iterate without making the last element a special case.
@@ -720,7 +799,7 @@
/* Massage TOC (table of contents), make sure it is sound */
if (g_uzip_parse_toc(sc, pp, gp) != 0) {
DPRINTF(GUZ_DBG_ERR, ("%s: TOC error\n", gp->name));
- goto e5;
+ goto e6;
}
mtx_init(&sc->last_mtx, "geom_uzip cache", NULL, MTX_DEF);
mtx_init(&sc->queue_mtx, "geom_uzip wrkthread", NULL, MTX_DEF);
@@ -730,15 +809,6 @@
sc->req_total = 0;
sc->req_cached = 0;
- if (type == G_UZIP) {
- sc->dcp = g_uzip_zlib_ctor(sc->blksz);
- } else {
- sc->dcp = g_uzip_lzma_ctor(sc->blksz);
- }
- if (sc->dcp == NULL) {
- goto e6;
- }
-
sc->uzip_do = &g_uzip_do;
error = kproc_create(g_uzip_wrkthr, sc, &sc->procp, 0, 0, "%s",
@@ -764,11 +834,11 @@
return (gp);
e7:
- sc->dcp->free(sc->dcp);
-e6:
free(sc->last_buf, M_GEOM);
mtx_destroy(&sc->queue_mtx);
mtx_destroy(&sc->last_mtx);
+e6:
+ sc->dcp->free(sc->dcp);
e5:
free(sc->toc, M_GEOM);
e4:
Index: head/sys/geom/uzip/g_uzip_dapi.h
===================================================================
--- head/sys/geom/uzip/g_uzip_dapi.h
+++ head/sys/geom/uzip/g_uzip_dapi.h
@@ -38,4 +38,5 @@
g_uzip_dapi_free_t free;
g_uzip_dapi_rewind_t rewind;
void *pvt;
+ int max_blen;
};
Index: head/sys/geom/uzip/g_uzip_lzma.c
===================================================================
--- head/sys/geom/uzip/g_uzip_lzma.c
+++ head/sys/geom/uzip/g_uzip_lzma.c
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/malloc.h>
+#include <sys/systm.h>
#include <contrib/xz-embedded/linux/include/linux/xz.h>
@@ -41,6 +42,7 @@
struct g_uzip_lzma {
struct g_uzip_dapi pub;
+ uint32_t blksz;
/* XZ decoder structs */
struct xz_buf b;
struct xz_dec *s;
@@ -75,13 +77,26 @@
lzp->b.out = obp;
lzp->b.in_pos = lzp->b.out_pos = 0;
lzp->b.in_size = ilen;
- lzp->b.out_size = (size_t)-1;
+ lzp->b.out_size = lzp->blksz;
err = (xz_dec_run(lzp->s, &lzp->b) != XZ_STREAM_END) ? 1 : 0;
/* TODO decoder recovery, if needed */
+ if (err != 0) {
+ printf("%s: ibp=%p, obp=%p, in_pos=%jd, out_pos=%jd, "
+ "in_size=%jd, out_size=%jd\n", __func__, ibp, obp,
+ (intmax_t)lzp->b.in_pos, (intmax_t)lzp->b.out_pos,
+ (intmax_t)lzp->b.in_size, (intmax_t)lzp->b.out_size);
+ }
return (err);
}
+static int
+LZ4_compressBound(int isize)
+{
+
+ return (isize + (isize / 255) + 16);
+}
+
struct g_uzip_dapi *
g_uzip_lzma_ctor(uint32_t blksz)
{
@@ -93,6 +108,8 @@
if (lzp->s == NULL) {
goto e1;
}
+ lzp->blksz = blksz;
+ lzp->pub.max_blen = LZ4_compressBound(blksz);
lzp->pub.decompress = &g_uzip_lzma_decompress;
lzp->pub.free = &g_uzip_lzma_free;
lzp->pub.rewind = &g_uzip_lzma_nop;
Index: head/sys/geom/uzip/g_uzip_zlib.c
===================================================================
--- head/sys/geom/uzip/g_uzip_zlib.c
+++ head/sys/geom/uzip/g_uzip_zlib.c
@@ -97,6 +97,13 @@
return (err);
}
+static int
+z_compressBound(int len)
+{
+
+ return (len + (len >> 12) + (len >> 14) + 11);
+}
+
struct g_uzip_dapi *
g_uzip_zlib_ctor(uint32_t blksz)
{
@@ -109,6 +116,7 @@
goto e1;
}
zp->blksz = blksz;
+ zp->pub.max_blen = z_compressBound(blksz);
zp->pub.decompress = &g_uzip_zlib_decompress;
zp->pub.free = &g_uzip_zlib_free;
zp->pub.rewind = &g_uzip_zlib_rewind;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 4, 6:25 PM (18 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30834041
Default Alt Text
D7013.id18019.diff (9 KB)
Attached To
Mode
D7013: Fix some bugs in the geom_uzip, improve handling of the last-sector padding, add some tuning knobs.
Attached
Detach File
Event Timeline
Log In to Comment