Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Jul 2009 12:04:14 -0700 (PDT)
From:      Naeem Afzal <naeem_jarral@yahoo.com>
To:        freebsd-geom@freebsd.org
Subject:   taking account of bio_resid when b_maxsize is greater than bio_length
Message-ID:  <937396.78922.qm@web81102.mail.mud.yahoo.com>

next in thread | raw e-mail | index | archive | help



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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?937396.78922.qm>