Esempio n. 1
0
static void
g_uzip_start(struct bio *bp)
{
	struct g_provider *pp;
	struct g_geom *gp;
	struct g_uzip_softc *sc;

	pp = bp->bio_to;
	gp = pp->geom;

	DPRINTF(GUZ_DBG_IO, ("%s/%s: %p: cmd=%d, offset=%jd, length=%jd, "
	    "buffer=%p\n", __func__, gp->name, bp, bp->bio_cmd,
	    (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length, bp->bio_data));

	sc = gp->softc;
	sc->req_total++;

	if (bp->bio_cmd != BIO_READ) {
		g_io_deliver(bp, EOPNOTSUPP);
		return;
	}

	bp->bio_resid = bp->bio_length;
	bp->bio_completed = 0;

	g_uzip_request(gp, bp);
}
Esempio n. 2
0
static void
g_uzip_do(struct g_uzip_softc *sc, struct bio *bp)
{
	struct bio *bp2;
	struct g_provider *pp;
	struct g_consumer *cp;
	struct g_geom *gp;
	char *data, *data2;
	off_t ofs;
	size_t blk, blkofs, len, ulen, firstblk;
	int err;

	bp2 = bp->bio_parent;
	gp = bp2->bio_to->geom;

	cp = LIST_FIRST(&gp->consumer);
	pp = cp->provider;

	bp2->bio_error = bp->bio_error;
	if (bp2->bio_error != 0)
		goto done;

	/* Make sure there's forward progress. */
	if (bp->bio_completed == 0) {
		bp2->bio_error = ECANCELED;
		goto done;
	}

	ofs = bp2->bio_offset + bp2->bio_completed;
	firstblk = blk = ofs / sc->blksz;
	blkofs = ofs % sc->blksz;
	data = bp->bio_data + sc->toc[blk].offset % pp->sectorsize;
	data2 = bp2->bio_data + bp2->bio_completed;
	while (bp->bio_completed && bp2->bio_resid) {
		if (blk > firstblk && !BLK_IS_CONT(sc, blk)) {
			DPRINTF_BLK(GUZ_DBG_IO, blk, ("%s/%s: %p: backref'ed "
			    "cluster #%u requested, looping around\n",
			    __func__, gp->name, bp2, (u_int)blk));
			goto done;
		}
		ulen = MIN(sc->blksz - blkofs, bp2->bio_resid);
		len = sc->toc[blk].blen;
		DPRINTF(GUZ_DBG_IO, ("%s/%s: %p/%ju: data2=%p, ulen=%u, "
		    "data=%p, len=%u\n", __func__, gp->name, gp,
		    bp->bio_completed, data2, (u_int)ulen, data, (u_int)len));
		if (len == 0) {
			/* All zero block: no cache update */
			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->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));
				goto done;
			}
			sc->last_blk = blk;
			memcpy(data2, sc->last_buf + blkofs, ulen);
			mtx_unlock(&sc->last_mtx);
			err = sc->dcp->rewind(sc->dcp, gp->name);
			if (err != 0) {
				bp2->bio_error = EILSEQ;
				DPRINTF(GUZ_DBG_ERR, ("%s/%s: rewind(%p) "
				    "failed\n", __func__, gp->name, sc->dcp));
				goto done;
			}
			data += len;
		} else
			break;

		data2 += ulen;
		bp2->bio_completed += ulen;
		bp2->bio_resid -= ulen;
		bp->bio_completed -= len;
		blkofs = 0;
		blk++;
	}

done:
	/* Finish processing the request. */
	free(bp->bio_data, M_GEOM_UZIP);
	g_destroy_bio(bp);
	if (bp2->bio_error != 0 || bp2->bio_resid == 0)
		g_io_deliver(bp2, bp2->bio_error);
	else
		g_uzip_request(gp, bp2);
}
Esempio n. 3
0
static void
g_uzip_done(struct bio *bp)
{
	z_stream zs;
	struct bio *bp2;
	struct g_provider *pp;
	struct g_consumer *cp;
	struct g_geom *gp;
	struct g_uzip_softc *sc;
	char *data, *data2;
	off_t ofs;
	size_t blk, blkofs, len, ulen;

	bp2 = bp->bio_parent;
	gp = bp2->bio_to->geom;
	sc = gp->softc;

	cp = LIST_FIRST(&gp->consumer);
	pp = cp->provider;

	bp2->bio_error = bp->bio_error;
	if (bp2->bio_error != 0)
		goto done;

	/* Make sure there's forward progress. */
	if (bp->bio_completed == 0) {
		bp2->bio_error = ECANCELED;
		goto done;
	}

	zs.zalloc = z_alloc;
	zs.zfree = z_free;
	if (inflateInit(&zs) != Z_OK) {
		bp2->bio_error = EILSEQ;
		goto done;
	}

	ofs = bp2->bio_offset + bp2->bio_completed;
	blk = ofs / sc->blksz;
	blkofs = ofs % sc->blksz;
	data = bp->bio_data + sc->offsets[blk] % pp->sectorsize;
	data2 = bp2->bio_data + bp2->bio_completed;
	while (bp->bio_completed && bp2->bio_resid) {
		ulen = MIN(sc->blksz - blkofs, bp2->bio_resid);
		len = sc->offsets[blk + 1] - sc->offsets[blk];
		DPRINTF(("%s/%s: %p/%ju: data2=%p, ulen=%u, data=%p, len=%u\n",
		    __func__, gp->name, gp, bp->bio_completed,
		    data2, (u_int)ulen, data, (u_int)len));
		if (len == 0) {
			/* All zero block: no cache update */
			bzero(data2, ulen);
		} else if (len <= bp->bio_completed) {
			zs.next_in = data;
			zs.avail_in = len;
			zs.next_out = sc->last_buf;
			zs.avail_out = sc->blksz;
			mtx_lock(&sc->last_mtx);
			if (inflate(&zs, Z_FINISH) != Z_STREAM_END) {
				sc->last_blk = -1;
				mtx_unlock(&sc->last_mtx);
				inflateEnd(&zs);
				bp2->bio_error = EILSEQ;
				goto done;
			}
			sc->last_blk = blk;
			memcpy(data2, sc->last_buf + blkofs, ulen);
			mtx_unlock(&sc->last_mtx);
			if (inflateReset(&zs) != Z_OK) {
				inflateEnd(&zs);
				bp2->bio_error = EILSEQ;
				goto done;
			}
			data += len;
		} else
			break;

		data2 += ulen;
		bp2->bio_completed += ulen;
		bp2->bio_resid -= ulen;
		bp->bio_completed -= len;
		blkofs = 0;
		blk++;
	}

	if (inflateEnd(&zs) != Z_OK)
		bp2->bio_error = EILSEQ;

done:
	/* Finish processing the request. */
	free(bp->bio_data, M_GEOM_UZIP);
	g_destroy_bio(bp);
	if (bp2->bio_error != 0 || bp2->bio_resid == 0)
		g_io_deliver(bp2, bp2->bio_error);
	else
		g_uzip_request(gp, bp2);
}