I have been writing a block driver. If I use request queue in my block
driver, it's working fine. But, I'm having problems when I try to use
buffer_head directly on my own implemented "make_request_fn". I have
trying to fix the problem for a long long time, still not successful.
I'm using kernel 2.4.27. I provided part of my source code below.
Can anyone please give me some hint about if I handled buffer_head
correctly? Thanks!
/*
* Finally, the module stuff
*/
int npswap_init(void) {
/*
* Get the queue set up, and register our (nonexistent) partitions.
*/
blk_init_queue(BLK_DEFAULT_QUEUE(major), npswap_request);
// direct operate on buffer_head without using queue
if (noqueue)
{
blk_queue_make_request(BLK_DEFAULT_QUEUE(major),
npswap_make_request);
}
}
/*
* Transfer a buffer directly, without going through the request queue.
*/
int npswap_make_request(request_queue_t *queue, int rw, struct buffer_head *bh) {
u8 *ptr;
// Figure out what we are doing
Sbull_Dev *device = npswap_devices + MINOR(bh->b_rdev);
ptr = device->data + bh->b_rsector * npswap_hardsect;
// Paranoid check, this apparently can really happen
if (ptr + bh->b_size > device->data + npswap_blksize*npswap_size) {
static int count = 0;
if (count++ < 5)
printk(KERN_WARNING "npswap: request past end of device\n");
bh->b_end_io(bh, 0);
return 0;
}
spin_lock(&io_request_lock);
// This could be a high memory buffer, shift it down
#if CONFIG_HIGHMEM
bh = create_bounce(rw, bh);
//bh = blk_queue_bounce(queue, rw, bh);
PDEBUG("Defined: CONFIG_HIGHMEM\n");
#endif
//PDEBUG("bh->b_rsector: %ld, bh->b_size: %hd, nr_sectors: %d\n",
// bh->b_rsector, bh->b_size, (bh->b_size/npswap_hardsect));
// Do the transfer
switch(rw) {
case READ:
case READA: // Readahead
memcpy(bh->b_data, ptr, bh->b_size); // from npswap to buffer
bh->b_end_io(bh, 1);
break;
case WRITE:
refile_buffer(bh);
memcpy(ptr, bh->b_data, bh->b_size); // from buffer to npswap
mark_buffer_uptodate(bh, 1);
bh->b_end_io(bh, 1);
break;
default:
// can't happen
bh->b_end_io(bh, 0);
break;
}
spin_unlock(&io_request_lock);
// Nonzero return means we're done
return 0;
}