--- linux/drivers/block/ll_rw_blk.c Mon Apr 9 09:09:52 2001 +++ linux-lvm/drivers/block/ll_rw_blk.c Mon Apr 9 15:48:12 2001 @@ -582,12 +582,6 @@ count = bh->b_size >> 9; sector = bh->b_rsector; - /* Uhhuh.. Nasty dead-lock possible here.. */ - if (buffer_locked(bh)) - return; - /* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */ - lock_buffer(bh); - if (blk_size[major]) { unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; @@ -606,7 +600,7 @@ kdevname(bh->b_dev), blksize_size[major][MINOR(bh->b_dev)], bh->b_blocknr, bh->b_rsector, bh->b_size, bh->b_count); - + goto end_io; } } @@ -662,7 +656,7 @@ req = *get_queue(bh->b_rdev); if (!req) { /* MD and loop can't handle plugging without deadlocking */ - if (major != MD_MAJOR && major != LOOP_MAJOR && + if (major != MD_MAJOR && major != LOOP_MAJOR && major != DDV_MAJOR && major != NBD_MAJOR) plug_device(blk_dev + major); /* is atomic */ } else switch (major) { @@ -794,7 +788,7 @@ { unsigned int major; int correct_size; - struct blk_dev_struct * dev; + struct blk_dev_struct *dev; int i; /* Make sure that the first block contains something reasonable */ @@ -830,19 +824,6 @@ correct_size, bh[i]->b_size); goto sorry; } - - /* Md remaps blocks now */ - bh[i]->b_rdev = bh[i]->b_dev; - bh[i]->b_rsector=bh[i]->b_blocknr*(bh[i]->b_size >> 9); -#ifdef CONFIG_BLK_DEV_MD - if (major==MD_MAJOR && - md_map (MINOR(bh[i]->b_dev), &bh[i]->b_rdev, - &bh[i]->b_rsector, bh[i]->b_size >> 9)) { - printk (KERN_ERR - "Bad md_map in ll_rw_block\n"); - goto sorry; - } -#endif } if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) { @@ -852,16 +833,18 @@ } for (i = 0; i < nr; i++) { - if (bh[i]) { - set_bit(BH_Req, &bh[i]->b_state); -#ifdef CONFIG_BLK_DEV_MD - if (MAJOR(bh[i]->b_dev) == MD_MAJOR) { - md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]); - continue; - } -#endif - make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]); - } + if (!bh[i]) + continue; + + set_bit(BH_Req, &bh[i]->b_state); + bh[i]->b_rdev = bh[i]->b_dev; + bh[i]->b_rsector = bh[i]->b_blocknr * (bh[i]->b_size >> 9); + + if (buffer_locked(bh[i])) + continue; + + lock_buffer(bh[i]); + generic_make_request(rw, bh[i]); } return; @@ -876,6 +859,28 @@ return; } +int generic_make_request(int rw, struct buffer_head *bh) { + int r = 1; + struct blk_dev_struct *dev = blk_dev + MAJOR(bh->b_rdev); + + while(dev->make_req_fn) { + if((r = dev->make_req_fn(bh, rw)) < 0) { + printk(KERN_NOTICE "Custom request function failed\n"); + bh->b_end_io(bh, 0); + return -1; + } + + dev = blk_dev + MAJOR(bh->b_rdev); + if(!r) break; + } + + if(r > 0) + make_request(MAJOR(bh->b_rdev), rw, bh); + + return 0; +} + + #ifdef CONFIG_STRAM_SWAP extern int stram_device_init( void ); #endif @@ -887,8 +892,8 @@ * 1 means we are done */ -int -end_that_request_first( struct request *req, int uptodate, char *name ) +int +end_that_request_first( struct request *req, int uptodate, char *name ) { struct buffer_head * bh; int nsect; @@ -924,7 +929,7 @@ } void -end_that_request_last( struct request *req ) +end_that_request_last( struct request *req ) { if (req->sem != NULL) up(req->sem); @@ -940,6 +945,7 @@ for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) { dev->request_fn = NULL; + dev->make_req_fn = NULL; dev->queue = NULL; dev->current_request = NULL; dev->plug.rq_status = RQ_INACTIVE; @@ -1045,6 +1051,9 @@ #ifdef CONFIG_SJCD sjcd_init(); #endif CONFIG_SJCD +#ifdef CONFIG_BLK_DEV_LVM + lvm_init(); +#endif #ifdef CONFIG_BLK_DEV_MD md_init(); #endif CONFIG_BLK_DEV_MD diff -urN -X /home/joe/packages/dontdiff linux-2.2.18-raw/drivers/block/md.c linux-2.2.18-raw-lvm0.9/drivers/block/md.c --- linux-2.2.18-raw/drivers/block/md.c Mon Sep 4 18:39:16 2000 +++ linux-2.2.18-raw-lvm0.9/drivers/block/md.c Wed Dec 13 11:20:11 2000 @@ -775,8 +775,16 @@ return (md_dev[minor].pers->map(md_dev+minor, rdev, rsector, size)); } -int md_make_request (int minor, int rw, struct buffer_head * bh) +int md_make_request(struct buffer_head *bh, int rw) { + int minor = MINOR(bh->b_rdev), r; + + r = md_map(minor, &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); + if(r) { + printk(KERN_ERR "Bad md_map in md_make_request\n"); + return r; + } + if (md_dev [minor].pers->make_request) { if (buffer_locked(bh)) return 0; @@ -793,11 +801,12 @@ return 0; } } - return (md_dev[minor].pers->make_request(md_dev+minor, rw, bh)); - } else { - make_request (MAJOR(bh->b_rdev), rw, bh); - return 0; + + /* I presume this returns <0 error, 0 success */ + return md_dev[minor].pers->make_request(md_dev+minor, rw, bh); } + + return 1; } static void do_md_request (void) @@ -1320,6 +1329,7 @@ } blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST; + blk_dev[MD_MAJOR].make_req_fn = md_make_request; blk_dev[MD_MAJOR].current_request=NULL; read_ahead[MD_MAJOR]=INT_MAX; memset(md_dev, 0, MAX_MD_DEV * sizeof (struct md_dev)); diff -urN -X /home/joe/packages/dontdiff linux-2.2.18-raw/include/linux/blkdev.h linux-2.2.18-raw-lvm0.9/include/linux/blkdev.h --- linux-2.2.18-raw/include/linux/blkdev.h Wed Dec 13 15:08:31 2000 +++ linux-2.2.18-raw-lvm0.9/include/linux/blkdev.h Wed Dec 13 15:34:20 2000 @@ -64,8 +64,20 @@ #define BLKELVGET _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t)) #define BLKELVSET _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t)) +/* + * should return: + * < 0 - error + * 0 - I've handled this request, you can stop now + * > 0 - carry on processing + */ +typedef int (bd_make_req_fn)(struct buffer_head *bh, int rw); + struct blk_dev_struct { request_fn_proc *request_fn; + + /* hook for remapping devices, used by md and lvm */ + bd_make_req_fn *make_req_fn; + /* * queue_proc has to be atomic */ @@ -92,7 +104,7 @@ /* md needs this function to remap requests */ extern int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size); -extern int md_make_request (int minor, int rw, struct buffer_head * bh); +extern int md_make_request (struct buffer_head * bh, int rw); extern int md_error (kdev_t mddev, kdev_t rdev); extern int * blk_size[MAX_BLKDEV]; --- linux/include/linux/fs.h Fri Jan 12 00:02:01 2001 +++ linux-generic-map/include/linux/fs.h Thu Apr 5 14:24:57 2001 @@ -880,6 +880,7 @@ extern struct buffer_head * get_hash_table(kdev_t, int, int); extern struct buffer_head * getblk(kdev_t, int, int); extern struct buffer_head * find_buffer(kdev_t dev, int block, int size); +extern int generic_make_request(int rw, struct buffer_head *bh); extern void ll_rw_block(int, int, struct buffer_head * bh[]); extern int is_read_only(kdev_t); extern void __brelse(struct buffer_head *); --- linux-generic-map/kernel/ksyms.c~ Thu Apr 5 14:05:43 2001 +++ linux-generic-map/kernel/ksyms.c Thu Apr 5 15:48:07 2001 @@ -180,6 +180,7 @@ EXPORT_SYMBOL(breada); EXPORT_SYMBOL(__brelse); EXPORT_SYMBOL(__bforget); +EXPORT_SYMBOL(generic_make_request); EXPORT_SYMBOL(ll_rw_block); EXPORT_SYMBOL(__wait_on_buffer); EXPORT_SYMBOL(mark_buffer_uptodate);