Read GEOM_UNCOMPRESS metadata using several requests that fit into
MAXPHYS. For large compressed images the metadata size can be bigger than MAXPHYS and this triggers KASSERT in g_read_data(). Also use g_free() to free memory allocated by g_read_data(). PR: 199476 MFC after: 2 weeks
This commit is contained in:
parent
68691fe0ce
commit
153c57b5b4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=283104
@ -464,7 +464,8 @@ 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, type;
|
||||
uint64_t *offsets;
|
||||
uint32_t i, r, total, total_offsets, type;
|
||||
uint8_t *buf;
|
||||
int error;
|
||||
|
||||
@ -499,8 +500,8 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags)
|
||||
*/
|
||||
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);
|
||||
total = roundup(sizeof(struct cloop_header), pp->sectorsize);
|
||||
buf = g_read_data(cp, 0, total, NULL);
|
||||
if (buf == NULL)
|
||||
goto err;
|
||||
header = (struct cloop_header *) buf;
|
||||
@ -557,20 +558,29 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags)
|
||||
gp->name, sc->nblocks);
|
||||
goto err;
|
||||
}
|
||||
free(buf, M_GEOM);
|
||||
g_free(buf);
|
||||
|
||||
i = roundup((sizeof(struct cloop_header) +
|
||||
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]);
|
||||
M_GEOM_UNCOMPRESS, M_WAITOK | M_ZERO);
|
||||
total = roundup((sizeof(struct cloop_header) +
|
||||
total_offsets * sizeof(uint64_t)), pp->sectorsize);
|
||||
#define RSZ ((total - r) > MAXPHYS ? MAXPHYS: (total - r))
|
||||
for (r = 0, i = 0; r < total; r += MAXPHYS) {
|
||||
buf = g_read_data(cp, r, RSZ, &error);
|
||||
if (buf == NULL) {
|
||||
free(sc->offsets, M_GEOM_UNCOMPRESS);
|
||||
goto err;
|
||||
}
|
||||
offsets = (uint64_t *)buf;
|
||||
if (r == 0)
|
||||
offsets +=
|
||||
sizeof(struct cloop_header) / sizeof(uint64_t);
|
||||
for (; i < total_offsets && offsets < (uint64_t *)(buf + RSZ);
|
||||
i++, offsets++)
|
||||
sc->offsets[i] = be64toh(*offsets);
|
||||
g_free(buf);
|
||||
}
|
||||
free(buf, M_GEOM);
|
||||
#undef RSZ
|
||||
buf = NULL;
|
||||
DPRINTF(("%s: done reading offsets\n", gp->name));
|
||||
mtx_init(&sc->last_mtx, "geom_uncompress cache", NULL, MTX_DEF);
|
||||
@ -619,7 +629,7 @@ g_uncompress_taste(struct g_class *mp, struct g_provider *pp, int flags)
|
||||
g_topology_lock();
|
||||
g_access(cp, -1, 0, 0);
|
||||
if (buf != NULL)
|
||||
free(buf, M_GEOM);
|
||||
g_free(buf);
|
||||
if (gp->softc != NULL) {
|
||||
g_uncompress_softc_free(gp->softc, NULL);
|
||||
gp->softc = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user