--- 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);
