taking account of bio_resid when b_maxsize is greater than
bio_length
Naeem Afzal
naeem_jarral at yahoo.com
Tue Jul 21 19:30:56 UTC 2009
Hi,
I am writing a disk driver which can only read maximum of 0x1000 bytes at a time, so d_maxsize = 0x1000. If the application tries to read more than that say 0x3000 and current bio_offset pointer is set to say 0xe00, driver can write only 0x200 (to stay within 0x1000 window), that means it will set the bio_resid=0xe00 as the request from OS will be 0x1000 (d_maxsize). Now subsequent OS request shuold be at 0x1000, but it was returning 0x1e00 as it does not count for bio_resid and assumes that maximum write happened. Could someone explain if my assumption is correct that it needs to take care of bio_resid?
regards
naeem
(FreeBSD 7.1)
/usr/src/sys/geom/geom_disk.c
static void
g_disk_start(struct bio *bp)
{
struct bio *bp2, *bp3;
struct disk *dp;
int error;
off_t off;
....
/* fall-through */
case BIO_READ:
case BIO_WRITE:
off = 0;
bp3 = NULL;
bp2 = g_clone_bio(bp);
if (bp2 == NULL) {
error = ENOMEM;
break;
}
do {
bp2->bio_offset += off;
bp2->bio_length -= off;
bp2->bio_data += off;
if (bp2->bio_length > dp->d_maxsize) {
/*
* XXX: If we have a stripesize we should really
* use it here.
*/
bp2->bio_length = dp->d_maxsize;
off += dp->d_maxsize;
/*
* To avoid a race, we need to grab the next bio
* before we schedule this one. See "notes".
*/
bp3 = g_clone_bio(bp);
if (bp3 == NULL)
bp->bio_error = ENOMEM;
}
bp2->bio_done = g_disk_done;
bp2->bio_pblkno = bp2->bio_offset / dp->d_sectorsize;
bp2->bio_bcount = bp2->bio_length;
bp2->bio_disk = dp;
devstat_start_transaction_bio(dp->d_devstat, bp2);
g_disk_lock_giant(dp);
dp->d_strategy(bp2);
g_disk_unlock_giant(dp);
#if 1 // I belive this line is needed to account for bio_resid??
off -= bp2->bio_resid;
#endif
More information about the freebsd-geom
mailing list