예제 #1
0
파일: atapi-cd.c 프로젝트: AhmadTux/freebsd
static void 
acd_geom_start(struct bio *bp)
{
    device_t dev = bp->bio_to->geom->softc;
    struct acd_softc *cdp = device_get_ivars(dev);

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

    if (bp->bio_cmd == BIO_READ && cdp->disk_size == -1) {
	g_io_deliver(bp, EIO);
	return;
    }

    /* GEOM classes must do their own request limiting */
    if (bp->bio_length <= cdp->iomax) {
	bp->bio_pblkno = bp->bio_offset / bp->bio_to->sectorsize;
	acd_strategy(bp);
    }
    else {
	u_int pos, size = cdp->iomax - cdp->iomax % bp->bio_to->sectorsize;
	struct bio *bp2, *bp3;

	if (!(bp2 = g_clone_bio(bp)))
	    g_io_deliver(bp, EIO);

	for (pos = 0; bp2; pos += size) {
	    bp3 = NULL;
	    bp2->bio_done = g_std_done;
	    bp2->bio_to = bp->bio_to;
	    bp2->bio_offset += pos;
	    bp2->bio_data += pos;
	    bp2->bio_length = bp->bio_length - pos;
	    if (bp2->bio_length > size) {
		bp2->bio_length = size;
		if (!(bp3 = g_clone_bio(bp)))
		    bp->bio_error = ENOMEM;
	    }
	    bp2->bio_pblkno = bp2->bio_offset / bp2->bio_to->sectorsize;
	    acd_strategy(bp2);
	    bp2 = bp3;
	}
    }
}
예제 #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, 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);
}
예제 #3
0
static void
g_aes_start(struct bio *bp)
{
	struct g_geom *gp;
	struct g_consumer *cp;
	struct g_aes_softc *sc;
	struct bio *bp2;
	u_char *p1, *p2, *b, *e;
	keyInstance ekey;
	off_t o;

	gp = bp->bio_to->geom;
	cp = LIST_FIRST(&gp->consumer);
	sc = gp->softc;
	switch (bp->bio_cmd) {
	case BIO_READ:
		bp2 = g_clone_bio(bp);
		if (bp2 == NULL) {
			g_io_deliver(bp, ENOMEM);
			return;
		}
		bp2->bio_done = g_aes_read_done;
		bp2->bio_offset += sc->sectorsize;
		g_io_request(bp2, cp);
		break;
	case BIO_WRITE:
		bp2 = g_clone_bio(bp);
		if (bp2 == NULL) {
			g_io_deliver(bp, ENOMEM);
			return;
		}
		bp2->bio_done = g_aes_write_done;
		bp2->bio_offset += sc->sectorsize;
		bp2->bio_data = g_malloc(bp->bio_length, M_WAITOK);
		b = bp->bio_data;
		e = bp->bio_data;
		e += bp->bio_length;
		p2 = bp2->bio_data;
		o = bp->bio_offset;
		for (p1 = b; p1 < e; p1 += sc->sectorsize) {
			g_aes_makekey(sc, o, &ekey, DIR_ENCRYPT);
			rijndael_blockEncrypt(&sc->ci, &ekey,
			    p1, sc->sectorsize * 8, p2);
			p2 += sc->sectorsize;
			o += sc->sectorsize;
		}
		bzero(&ekey, sizeof ekey);	/* destroy evidence */
		g_io_request(bp2, cp);
		break;
	case BIO_GETATTR:
		bp2 = g_clone_bio(bp);
		if (bp2 == NULL) {
			g_io_deliver(bp, ENOMEM);
			return;
		}
		bp2->bio_done = g_std_done;
		bp2->bio_offset += sc->sectorsize;
		g_io_request(bp2, cp);
		break;
	default:
		g_io_deliver(bp, EOPNOTSUPP);
		return;
	}
	return;
}
예제 #4
0
파일: g_uzip.c 프로젝트: coyizumi/cs111
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);
}
예제 #5
0
파일: g_uzip.c 프로젝트: AhmadTux/freebsd
static void
g_uzip_start(struct bio *bp)
{
	struct bio *bp2;
	struct g_provider *pp, *pp2;
	struct g_geom *gp;
	struct g_consumer *cp;
	struct g_uzip_softc *sc;
	uint32_t start_blk, end_blk;
	size_t bsize;

	pp = bp->bio_to;
	gp = pp->geom;
	DPRINTF(("%s: start (%d)\n", gp->name, bp->bio_cmd));

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

	cp = LIST_FIRST(&gp->consumer);
	pp2 = cp->provider;
	sc = gp->softc;

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

	sc->req_total++;
	if (start_blk + 1 == end_blk) {
		mtx_lock(&sc->last_mtx);
		if (start_blk == sc->last_blk) {
			off_t uoff;

			uoff = bp->bio_offset % sc->blksz;
			KASSERT(bp->bio_length <= sc->blksz - uoff,
			    ("cached data error"));
			memcpy(bp->bio_data, sc->last_buf + uoff,
			    bp->bio_length);
			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));
			bp->bio_completed = bp->bio_length;
			g_io_deliver(bp, 0);
			return;
		}
		mtx_unlock(&sc->last_mtx);
	}

	bp2 = g_clone_bio(bp);
	if (bp2 == NULL) {
		g_io_deliver(bp, ENOMEM);
		return;
	}
	bp2->bio_done = g_uzip_done;
	DPRINTF(("%s: start (%d..%d), %s: %d + %lld, %s: %d + %lld\n",
	    gp->name, start_blk, end_blk,
	    pp->name, pp->sectorsize, pp->mediasize,
	    pp2->name, pp2->sectorsize, 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",
	    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));
	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;
	}

	g_io_request(bp2, cp);
	DPRINTF(("%s: start ok\n", gp->name));
}