diff -urN ref/drivers/block/ll_rw_blk.c lvm/drivers/block/ll_rw_blk.c --- ref/drivers/block/ll_rw_blk.c Wed Feb 23 01:23:11 2000 +++ lvm/drivers/block/ll_rw_blk.c Wed Feb 23 01:27:15 2000 @@ -177,9 +177,9 @@ q->plug_device_fn = plug; } -void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) +void blk_logical_volume(struct blk_dev_struct * bdev, logical_volume_fn * mfn) { - q->make_request_fn = mfn; + bdev->logical_volume_fn = mfn; } static inline int ll_new_segment(request_queue_t *q, struct request *req, int max_segments) @@ -256,7 +256,6 @@ q->back_merge_fn = ll_back_merge_fn; q->front_merge_fn = ll_front_merge_fn; q->merge_requests_fn = ll_merge_requests_fn; - q->make_request_fn = NULL; q->plug_tq.sync = 0; q->plug_tq.routine = &generic_unplug_device; q->plug_tq.data = q; @@ -953,13 +952,10 @@ bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); } -void generic_make_request(int rw, struct buffer_head * bh) +static void generic_make_request(request_queue_t * q, int rw, struct buffer_head * bh) { - request_queue_t * q; unsigned long flags; - q = blk_get_queue(bh->b_rdev); - __make_request(q, rw, bh); spin_lock_irqsave(&io_request_lock,flags); @@ -968,6 +964,11 @@ spin_unlock_irqrestore(&io_request_lock,flags); } +static inline void buffer_IO_error(struct buffer_head * bh) +{ + mark_buffer_clean(bh); /* remeber to refile it */ + bh->b_end_io(bh, 0); /* b_end_io has to clear the BH_Uptodate bitflag */ +} /* This function can be used to request a number of buffers from a block device. Currently the only restriction is that all buffers must belong to @@ -975,12 +976,12 @@ static void __ll_rw_block(int rw, int nr, struct buffer_head * bh[],int haslock) { - unsigned int major; + unsigned int major, logical_major; int correct_size; request_queue_t *q; int i; - major = MAJOR(bh[0]->b_dev); + logical_major = major = MAJOR(bh[0]->b_dev); q = blk_get_queue(bh[0]->b_dev); if (!q) { printk(KERN_ERR @@ -1025,23 +1026,36 @@ } set_bit(BH_Req, &bh[i]->b_state); - if (q->make_request_fn) - q->make_request_fn(rw, bh[i]); - else { - bh[i]->b_rdev = bh[i]->b_dev; - bh[i]->b_rsector = bh[i]->b_blocknr*(bh[i]->b_size>>9); + bh[i]->b_rdev = bh[i]->b_dev; + bh[i]->b_rsector = bh[i]->b_blocknr*(bh[i]->b_size>>9); + + major = logical_major; + if (blk_dev[major].logical_volume_fn) { + /* + * Loop thru all functions until we don't + * hit a volume driver any longer. + */ + do { + if (blk_dev[major].logical_volume_fn(rw, bh[i])) + goto IO_error; + major = MAJOR(bh[i]->b_rdev); + } while (blk_dev[major].logical_volume_fn); - generic_make_request(rw, bh[i]); + q = blk_get_queue(bh[i]->b_rdev); } + + generic_make_request(q, rw, bh[i]); + continue; + + IO_error: + buffer_IO_error(bh[i]); } return; sorry: for (i = 0; i < nr; i++) { - mark_buffer_clean(bh[i]); /* remeber to refile it */ - clear_bit(BH_Uptodate, &bh[i]->b_state); - bh[i]->b_end_io(bh[i], 0); + buffer_IO_error(bh[i]); } return; } @@ -1120,6 +1134,7 @@ for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) { dev->queue = NULL; blk_init_queue(&dev->request_queue, NULL); + dev->logical_volume_fn = NULL; } req = all_requests + NR_REQUEST; @@ -1237,5 +1252,5 @@ EXPORT_SYMBOL(blk_cleanup_queue); EXPORT_SYMBOL(blk_queue_headactive); EXPORT_SYMBOL(blk_queue_pluggable); -EXPORT_SYMBOL(blk_queue_make_request); +EXPORT_SYMBOL(blk_logical_volume); EXPORT_SYMBOL(generic_make_request); diff -urN ref/include/linux/blkdev.h lvm/include/linux/blkdev.h --- ref/include/linux/blkdev.h Mon Feb 21 15:17:34 2000 +++ lvm/include/linux/blkdev.h Wed Feb 23 01:31:31 2000 @@ -53,7 +53,7 @@ int); typedef void (request_fn_proc) (request_queue_t *q); typedef request_queue_t * (queue_proc) (kdev_t dev); -typedef void (make_request_fn) (int rw, struct buffer_head *bh); +typedef int (logical_volume_fn) (int rw, struct buffer_head *bh); typedef void (plug_device_fn) (request_queue_t *q, kdev_t device); typedef void (unplug_device_fn) (void *q); @@ -77,7 +77,6 @@ merge_request_fn * back_merge_fn; merge_request_fn * front_merge_fn; merge_requests_fn * merge_requests_fn; - make_request_fn * make_request_fn; plug_device_fn * plug_device_fn; /* * The queue owner gets to use this for whatever they like. @@ -108,6 +107,7 @@ request_queue_t request_queue; queue_proc *queue; void *data; + logical_volume_fn * logical_volume_fn; }; struct sec_size { @@ -129,7 +129,6 @@ extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); extern void generic_unplug_device(void * data); -extern void generic_make_request(int rw, struct buffer_head * bh); extern request_queue_t * blk_get_queue(kdev_t dev); /* @@ -139,7 +138,7 @@ extern void blk_cleanup_queue(request_queue_t *); extern void blk_queue_headactive(request_queue_t *, int); extern void blk_queue_pluggable(request_queue_t *, plug_device_fn *); -extern void blk_queue_make_request(request_queue_t *, make_request_fn *); +extern void blk_logical_volume(struct blk_dev_struct *, logical_volume_fn *); extern int * blk_size[MAX_BLKDEV];