Block device request merging - repeated requests.

David Woodhouse dwmw2 en infradead.org
Lun Ene 31 18:55:09 CST 2000


axboe en suse.de said:
>  No, CURRENT->sector is always the "current" sector. When you call
> end_request, end_that_request_first will adjust rq->sector for you. 

I only see a modification of req->sector in the !uptodate case.

I get 'correct' behaviour if I add the following line immediately before 
every occurrence of end_request(1) in my driver:
	CURRENT->sector += CURRENT->current_nr_sectors;

# dd if=nftl.c bs=512 of=/dev/nftla count=6
NFTL write request of 0x2 sectors @ 0 (CURRENT->nr_sectors == 6
NFTL write request completed OK
NFTL write request of 0x2 sectors @ 2 (CURRENT->nr_sectors == 6
NFTL write request completed OK
NFTL write request of 0x2 sectors @ 4 (CURRENT->nr_sectors == 6
NFTL write request completed OK


>From 2.3.41:

int 
end_that_request_first( struct request *req, int uptodate, char *name ) 
{
        struct buffer_head * bh;
        int nsect;

        req->errors = 0;
        if (!uptodate) {
                printk("end_request: I/O error, dev %s (%s), sector %lu\n",
                        kdevname(req->rq_dev), name, req->sector);
                if ((bh = req->bh) != NULL) {
                        nsect = bh->b_size >> 9;
                        req->nr_sectors--;
                        req->nr_sectors &= ~(nsect - 1);
                        req->sector += nsect;
                        req->sector &= ~(nsect - 1);
                }
        }

        if ((bh = req->bh) != NULL) {
                req->bh = bh->b_reqnext;
                bh->b_reqnext = NULL;
                bh->b_end_io(bh, uptodate);
                if ((bh = req->bh) != NULL) {
                        req->current_nr_sectors = bh->b_size >> 9;
                        if (req->nr_sectors < req->current_nr_sectors) {
                                req->nr_sectors = req->current_nr_sectors;
                                printk("end_request: buffer-list destroyed\n");
                        }
                        req->buffer = bh->b_data;
                        return 1;
                }
        }
        return 0;
}



> > What am I missing?

> Probably an end_request somewhere. 

> The logic goes something like this:
> - receive request
> - transfer CURRENT->current_nr_sectors 
> - end_request

That's what I'm doing, modulo any stupid mistakes on my part - which is 
unlikely since this code hasn't changed for a while, and it worked before.

> You never need to look at CURRENT->nr_sectors if you are not handling
> clustered requests yourself, end_request handles that for you.

OK. I've replaced that with CURRENT->current_nr_sectors.

> FWIW, I have verified request handling with a dummy driver I wrote. It
> even handles merged requests with "holes", i.e. non-consequitive
> buffer heads. 

I think it would be a very good idea to include that in the kernel tree, as 
with drivers/net/skeleton.c.

Please could I have a copy?


--
dwmw2



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo en vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



Más información sobre la lista de distribución Ayuda