Esempio n. 1
0
static int
g_uzip_request(struct g_geom *gp, struct bio *bp)
{
	struct g_uzip_softc *sc;
	struct bio *bp2;
	struct g_consumer *cp;
	struct g_provider *pp;
	off_t ofs, start_blk_ofs;
	size_t i, start_blk, end_blk, zsize;

	if (g_uzip_cached(gp, bp) != 0)
		return (1);

	sc = gp->softc;

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

	ofs = bp->bio_offset + bp->bio_completed;
	start_blk = ofs / sc->blksz;
	KASSERT(start_blk < sc->nblocks, ("start_blk out of range"));
	end_blk = howmany(ofs + bp->bio_resid, sc->blksz);
	KASSERT(end_blk <= sc->nblocks, ("end_blk out of range"));

	for (; BLK_IS_NIL(sc, start_blk) && start_blk < end_blk; start_blk++) {
		/* Fill in any leading Nil blocks */
		start_blk_ofs = ofs % sc->blksz;
		zsize = MIN(sc->blksz - start_blk_ofs, bp->bio_resid);
		DPRINTF_BLK(GUZ_DBG_IO, start_blk, ("%s/%s: %p/%ju: "
		    "filling %ju zero bytes\n", __func__, gp->name, gp,
		    (uintmax_t)bp->bio_completed, (uintmax_t)zsize));
		bzero(bp->bio_data + bp->bio_completed, zsize);
		bp->bio_completed += zsize;
		bp->bio_resid -= zsize;
		ofs += zsize;
	}

	if (start_blk == end_blk) {
		KASSERT(bp->bio_resid == 0, ("bp->bio_resid is invalid"));
		/*
		 * No non-Nil data is left, complete request immediately.
		 */
		DPRINTF(GUZ_DBG_IO, ("%s/%s: %p: all done returning %ju "
		    "bytes\n", __func__, gp->name, gp,
		    (uintmax_t)bp->bio_completed));
		g_io_deliver(bp, 0);
		return (1);
	}

	for (i = start_blk + 1; i < end_blk; i++) {
		/* Trim discontinuous areas if any */
		if (!BLK_IS_CONT(sc, i)) {
			end_blk = i;
			break;
		}
	}

	DPRINTF_BRNG(GUZ_DBG_IO, start_blk, end_blk, ("%s/%s: %p: "
	    "start=%u (%ju), end=%u (%ju)\n", __func__, gp->name, bp,
	    (u_int)start_blk, (uintmax_t)sc->toc[start_blk].offset,
	    (u_int)end_blk, (uintmax_t)BLK_ENDS(sc, end_blk - 1)));

	bp2 = g_clone_bio(bp);
	if (bp2 == NULL) {
		g_io_deliver(bp, ENOMEM);
		return (1);
	}
	bp2->bio_done = g_uzip_read_done;

	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)
			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));

	bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UZIP, M_NOWAIT);
	if (bp2->bio_data == NULL) {
		g_destroy_bio(bp2);
		g_io_deliver(bp, ENOMEM);
		return (1);
	}

	DPRINTF_BRNG(GUZ_DBG_IO, start_blk, end_blk, ("%s/%s: %p: "
	    "reading %jd bytes from offset %jd\n", __func__, gp->name, bp,
	    (intmax_t)bp2->bio_length, (intmax_t)bp2->bio_offset));

	g_io_request(bp2, cp);
	return (0);
}
Esempio n. 2
0
static int
g_uzip_request(struct g_geom *gp, struct bio *bp)
{
	struct g_uzip_softc *sc;
	struct bio *bp2;
	struct g_consumer *cp;
	struct g_provider *pp;
	off_t ofs;
	size_t start_blk, end_blk;

	if (g_uzip_cached(gp, bp) != 0)
		return (1);

	sc = gp->softc;

	bp2 = g_clone_bio(bp);
	if (bp2 == NULL) {
		g_io_deliver(bp, ENOMEM);
		return (1);
	}
	bp2->bio_done = g_uzip_done;

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

	ofs = bp->bio_offset + bp->bio_completed;
	start_blk = ofs / sc->blksz;
	KASSERT(start_blk < sc->nblocks, ("start_blk out of range"));
	end_blk = (ofs + bp->bio_resid + sc->blksz - 1) / sc->blksz;
	KASSERT(end_blk <= sc->nblocks, ("end_blk out of range"));

	DPRINTF(("%s/%s: %p: start=%u (%jd), end=%u (%jd)\n",
	    __func__, gp->name, bp,
	    (u_int)start_blk, (intmax_t)sc->offsets[start_blk],
	    (u_int)end_blk, (intmax_t)sc->offsets[end_blk]));

	bp2->bio_offset = sc->offsets[start_blk] - 
	    sc->offsets[start_blk] % pp->sectorsize;
	while (1) {
		bp2->bio_length = sc->offsets[end_blk] - bp2->bio_offset;
		bp2->bio_length = (bp2->bio_length + pp->sectorsize - 1) /
		    pp->sectorsize * pp->sectorsize;
		if (bp2->bio_length <= MAXPHYS)
			break;

		end_blk--;
	}

	bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UZIP, M_NOWAIT);
	if (bp2->bio_data == NULL) {
		g_destroy_bio(bp2);
		g_io_deliver(bp, ENOMEM);
		return (1);
	}

	DPRINTF(("%s/%s: %p: reading %jd bytes from offset %jd\n",
	    __func__, gp->name, bp,
	    (intmax_t)bp2->bio_length, (intmax_t)bp2->bio_offset));

	g_io_request(bp2, cp);
	return (0);
}