diff -u -r linux/drivers/block/Config.in linux.lvm/drivers/block/Config.in
--- linux-2.3.99pre5/drivers/block/Config.in	Wed Apr 12 20:07:00 2000
+++ linux.lvm/drivers/block/Config.in	Wed Apr 12 19:54:12 2000
@@ -41,6 +41,11 @@
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
 dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
 
+tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N
+if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then
+   bool '   LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y
+fi
+
 bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
 dep_tristate '  Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD
 dep_tristate '  RAID-0 (striping) mode' CONFIG_MD_STRIPED $CONFIG_BLK_DEV_MD
diff -u -r linux/drivers/block/ll_rw_blk.c linux.lvm/drivers/block/ll_rw_blk.c
--- linux-2.3.99pre5/drivers/block/ll_rw_blk.c	Wed Apr 12 20:07:00 2000
+++ linux.lvm/drivers/block/ll_rw_blk.c	Wed Apr 12 18:57:37 2000
@@ -774,15 +774,6 @@
 	bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
 }
 
-static inline void buffer_IO_error(struct buffer_head * bh)
-{
-	mark_buffer_clean(bh);
-	/*
-	 * b_end_io has to clear the BH_Uptodate bitflag in the error case!
-	 */
-	bh->b_end_io(bh, 0);
-}
-
 int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
 {
 	unsigned long flags;
@@ -1071,6 +1062,9 @@
 #ifdef CONFIG_BLK_DEV_NBD
 	nbd_init();
 #endif
+#ifdef CONFIG_BLK_DEV_LVM
+       lvm_init();
+#endif 
 #ifdef CONFIG_MDISK
 	mdisk_init();
 #endif
diff -u -r linux/drivers/block/lvm-snap.c linux.lvm/drivers/block/lvm-snap.c
--- linux-2.3.99pre5/drivers/block/lvm-snap.c	Fri Feb 18 01:13:05 2000
+++ linux.lvm/drivers/block/lvm-snap.c	Wed Apr 12 18:36:25 2000
@@ -278,12 +278,12 @@
 	lvm_hash_link(lv_snap->lv_block_exception + idx,
 		      org_phys_dev, org_start, lv_snap);
 	lv_snap->lv_remap_ptr = idx + 1;
-	return 0;
+	return 1;
 
 	/* slow path */
  out:
 	lvm_drop_snapshot(lv_snap, reason);
-	return 1;
+	return -1;
 
  fail_out_of_space:
 	reason = "out of space";
diff -u -r linux/drivers/block/lvm.c linux.lvm/drivers/block/lvm.c
--- linux-2.3.99pre5/drivers/block/lvm.c	Wed Apr 12 20:07:00 2000
+++ linux.lvm/drivers/block/lvm.c	Wed Apr 12 18:44:07 2000
@@ -122,7 +122,7 @@
  *               - avoided "/dev/" in proc filesystem output
  *               - avoided inline strings functions lvm_strlen etc.
  *    14/02/2000 - support for 2.3.43
- *               - integrated Andrea Arcagnelli's snapshot code
+ *               - integrated Andrea Arcangeli's snapshot code
  *
  */
 
@@ -171,9 +171,9 @@
 #include <linux/errno.h>
 #include <linux/lvm.h>
 
-#define	LVM_CORRECT_READ_AHEAD( a) \
-   if      ( a < LVM_MIN_READ_AHEAD || \
-             a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;
+#define	LVM_CORRECT_READ_AHEAD(a)				\
+	(((a) < LVM_MIN_READ_AHEAD || (a) > LVM_MAX_READ_AHEAD)	\
+	 ? LVM_MAX_READ_AHEAD : (a))
 
 #ifndef WRITEA
 #  define WRITEA WRITE
@@ -193,13 +193,11 @@
 #define	DEVICE_REQUEST	lvm_dummy_device_request
 
 static int lvm_make_request_fn(request_queue_t *, int, struct buffer_head*);
+static void lvm_plug_device_noop(request_queue_t *, kdev_t);
 
 static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
 static int lvm_blk_open(struct inode *, struct file *);
 
-static ssize_t lvm_blk_read(struct file *, char *, size_t, loff_t *);
-static ssize_t lvm_blk_write(struct file *, const char *, size_t, loff_t *);
-
 static int lvm_chr_open(struct inode *, struct file *);
 
 static int lvm_chr_close(struct inode *, struct file *);
@@ -287,7 +285,7 @@
 static char pv_name[NAME_LEN];
 /* static char rootvg[NAME_LEN] = { 0, }; */
 static uint lv_open = 0;
-static const char *const lvm_name = LVM_NAME;
+const char *const lvm_name = LVM_NAME;
 static int lock = 0;
 static int loadtime = 0;
 static uint vg_count = 0;
@@ -298,7 +296,6 @@
 static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);
 
 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
 
 static struct file_operations lvm_chr_fops =
 {
@@ -307,18 +304,6 @@
 	ioctl:		lvm_chr_ioctl,
 };
 
-static struct file_operations lvm_blk_fops =
-{
-        open:           lvm_blk_open,
-        release:        blkdev_close,
-        read:           lvm_blk_read,
-        write:          lvm_blk_write,
-        ioctl:          lvm_blk_ioctl,
-        fsync:          block_fsync,
-};
-
-#define BLOCK_DEVICE_OPERATIONS
-/* block device operations structure needed for 2.3.38? and above */
 static struct block_device_operations lvm_blk_dops =
 {
 	open: 		lvm_blk_open,
@@ -370,11 +355,7 @@
 		printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
 		return -EIO;
 	}
-#ifdef BLOCK_DEVICE_OPERATIONS
 	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
-#else
-	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_fops) < 0)
-#endif
 	{
 		printk("%s -- register_blkdev failed\n", lvm_name);
 		if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
@@ -410,6 +391,7 @@
 
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
 	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
+	blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_plug_device_noop);
 	/* optional read root VGDA */
 /*
    if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
@@ -488,8 +470,6 @@
 
 	loadtime = CURRENT_TIME;
 
-	lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
-
 	pe_lock_req.lock = UNLOCK_PE;
 	pe_lock_req.data.lv_dev = \
 	    pe_lock_req.data.pv_dev = \
@@ -724,8 +704,19 @@
 				   sizeof(pv_flush_req)) != 0)
 			return -EFAULT;
 
-		fsync_dev(pv_flush_req.pv_dev);
-		invalidate_buffers(pv_flush_req.pv_dev);
+		for ( v = 0; v < ABS_MAX_VG; v++) {
+			unsigned int p;
+			if ( vg[v] == NULL) continue;
+			for ( p = 0; p < vg[v]->pv_max; p++) {
+				if ( vg[v]->pv[p] != NULL &&
+				     strcmp ( vg[v]->pv[p]->pv_name,
+					      pv_flush_req.pv_name) == 0) {
+					fsync_dev ( vg[v]->pv[p]->pv_dev);
+					invalidate_buffers ( vg[v]->pv[p]->pv_dev);
+					return 0;
+				}
+			}
+		}
 		return 0;
 
 	default:
@@ -813,10 +804,6 @@
 			if (!(lv_ptr->lv_access & LV_WRITE))  return -EACCES;
 		}
 
-#ifdef BLOCK_DEVICE_OPERATIONS
-		file->f_op = &lvm_blk_fops;
-#endif
-
                 /* be sure to increment VG counter */
 		if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;
 		lv_ptr->lv_open++;
@@ -837,34 +824,6 @@
 
 
 /*
- * block device read
- */
-static ssize_t lvm_blk_read(struct file *file, char *buffer,
-	      		    size_t size, loff_t * offset)
-{
-	int minor = MINOR(file->f_dentry->d_inode->i_rdev);
-
-	read_ahead[MAJOR(file->f_dentry->d_inode->i_rdev)] =
-           vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead;
-	return block_read(file, buffer, size, offset);
-}
-
-
-/*
- * block device write
- */
-static ssize_t lvm_blk_write(struct file *file, const char *buffer,
-	      		     size_t size, loff_t * offset)
-{
-	int minor = MINOR(file->f_dentry->d_inode->i_rdev);
-
-	read_ahead[MAJOR(file->f_dentry->d_inode->i_rdev)] =
-           vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead;
-	return block_write(file, buffer, size, offset);
-}
-
-
-/*
  * block device i/o-control routine
  */
 static int lvm_blk_ioctl(struct inode *inode, struct file *file,
@@ -906,6 +865,7 @@
 		       "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
 #endif
 		fsync_dev(inode->i_rdev);
+		invalidate_buffers(inode->i_rdev);
 		break;
 
 
@@ -921,7 +881,7 @@
 		if ((long) arg < LVM_MIN_READ_AHEAD ||
 		    (long) arg > LVM_MAX_READ_AHEAD)
 			return -EINVAL;
-		lv_ptr->lv_read_ahead = (long) arg;
+		read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = (long) arg;
 		break;
 
 
@@ -1293,7 +1253,6 @@
 static int lvm_map(struct buffer_head *bh, int rw)
 {
 	int minor = MINOR(bh->b_rdev);
-	int ret = 0;
 	ulong index;
 	ulong pe_start;
 	ulong size = bh->b_size >> 9;
@@ -1308,7 +1267,7 @@
 		printk(KERN_ALERT
 		       "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
 		       lvm_name, lv->lv_name);
-		return -1;
+		goto error;
 	}
 /*
    if ( lv->lv_access & LV_SNAPSHOT)
@@ -1323,7 +1282,7 @@
 	    (rw == WRITEA || rw == WRITE))
 	{
    printk ( "%s -- doing snapshot write for %02d:%02d[%02d:%02d]  b_blocknr: %lu  b_rsector: %lu\n", lvm_name, MAJOR ( bh->b_dev), MINOR ( bh->b_dev), MAJOR ( bh->b_rdev), MINOR ( bh->b_rdev), bh->b_blocknr, bh->b_rsector);
-		return 0;
+		goto error;
 	}
 
 	if ((rw == WRITE || rw == WRITEA) &&
@@ -1331,7 +1290,7 @@
 		printk(KERN_CRIT
 		    "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
 		       lvm_name, lv->lv_name);
-		return -1;
+		goto error;
 	}
 #ifdef DEBUG_MAP
 	printk(KERN_DEBUG
@@ -1347,7 +1306,7 @@
 		printk(KERN_ALERT
 		       "%s - lvm_map *rsector: %lu or size: %lu wrong for"
 		    " minor: %2d\n", lvm_name, rsector_tmp, size, minor);
-		return -1;
+		goto error;
 	}
 	rsector_sav = rsector_tmp;
 	rdev_sav = rdev_tmp;
@@ -1444,11 +1403,11 @@
 									      pe_start,
 									      lv_ptr)) {
 							/* create a new mapping */
-							ret = lvm_snapshot_COW(rdev_tmp,
-									       rsector_tmp,
-									       pe_start,
-									       rsector_sav,
-									       lv_ptr); 
+							lvm_snapshot_COW(rdev_tmp,
+									 rsector_tmp,
+									 pe_start,
+									 rsector_sav,
+									 lv_ptr); 
 						}
 						rdev_tmp = rdev_sav;
 						rsector_tmp = rsector_sav;
@@ -1467,7 +1426,11 @@
 	bh->b_rdev = rdev_tmp;
 	bh->b_rsector = rsector_tmp;
 
-	return ret;
+	return 1;
+
+ error:
+	buffer_IO_error(bh);
+	return -1;
 } /* lvm_map() */
 
 
@@ -1519,6 +1482,12 @@
 	return 1;
 }
 
+/*
+ * plug device function is a noop because plugging has to happen
+ * in the queue of the physical blockdevice to allow the
+ * elevator to do a better job.
+ */
+static void lvm_plug_device_noop(request_queue_t *q, kdev_t dev) { }
 
 /********************************************************************
  *
@@ -2090,7 +2059,7 @@
 	lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
 	vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = vg_ptr->vg_number;
 	vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = lv_ptr->lv_number;
-	LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
+	read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
 	vg_ptr->lv_cur++;
 	lv_ptr->lv_status = lv_status_save;
 
@@ -2328,7 +2297,7 @@
 	lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
 	/* vg_lv_map array doesn't have to be changed here */
 
-	LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
+	read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead = LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
 	lv_ptr->lv_status = lv_status_save;
 
 	return 0;
diff -u -r linux/drivers/block/md.c linux.lvm/drivers/block/md.c
--- linux-2.3.99pre5/drivers/block/md.c	Wed Apr 12 20:07:00 2000
+++ linux.lvm/drivers/block/md.c	Wed Apr 12 19:01:13 2000
@@ -185,8 +185,7 @@
 	if (mddev && mddev->pers)
 		return mddev->pers->make_request(q, mddev, rw, bh);
 	else {
-		mark_buffer_clean(bh);
-		bh->b_end_io(bh, 0);
+		buffer_IO_error(bh);
 		return -1;
 	}
 }
@@ -3456,7 +3455,7 @@
 {
 	int i;
 
-	for(i = 0; i < MAX_MD_BOOT_DEVS; i++) {
+	for(i = 0; i < MAX_MD_DEVS; i++) {
 		md_blocksizes[i] = 1024;
 		md_size[i] = 0;
 		md_maxreadahead[i] = MD_READAHEAD;
diff -u -r linux/include/linux/fs.h linux.lvm/include/linux/fs.h
--- linux-2.3.99pre5/include/linux/fs.h	Wed Apr 12 20:07:09 2000
+++ linux.lvm/include/linux/fs.h	Wed Apr 12 18:54:55 2000
@@ -940,6 +940,21 @@
 
 #define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state)
 
+/*
+ * If an error happens during the make_request, this function
+ * has to be recalled. It marks the buffer as clean and not
+ * uptodate, and it notifys the upper layer about the end
+ * of the I/O.
+ */
+static inline void buffer_IO_error(struct buffer_head * bh)
+{
+	mark_buffer_clean(bh);
+	/*
+	 * b_end_io has to clear the BH_Uptodate bitflag in the error case!
+	 */
+	bh->b_end_io(bh, 0);
+}
+
 extern void balance_dirty(kdev_t);
 extern int check_disk_change(kdev_t);
 extern int invalidate_inodes(struct super_block *);
diff -u -r linux/include/linux/lvm.h linux.lvm/include/linux/lvm.h
--- linux-2.3.99pre5/include/linux/lvm.h	Fri Feb 18 01:13:05 2000
+++ linux.lvm/include/linux/lvm.h	Wed Apr 12 19:30:57 2000
@@ -65,7 +65,7 @@
 #define	LVM_TOTAL_RESET
 
 #define LVM_GET_INODE
-#define	LVM_HD_NAME
+#undef	LVM_HD_NAME
 
 /* lots of debugging output (see driver source)
    #define DEBUG_LVM_GET_INFO
@@ -261,8 +261,8 @@
 #define	LVM_MAX_STRIPES		128	/* max # of stripes */
 #define	LVM_MAX_SIZE            ( 1024LU * 1024 * 1024 * 2)	/* 1TB[sectors] */
 #define	LVM_MAX_MIRRORS    	2	/* future use */
-#define	LVM_MIN_READ_AHEAD	2	/* minimum read ahead sectors */
-#define	LVM_MAX_READ_AHEAD	120	/* maximum read ahead sectors */
+#define	LVM_MIN_READ_AHEAD	0	/* minimum read ahead sectors */
+#define	LVM_MAX_READ_AHEAD	256	/* maximum read ahead sectors */
 #define	LVM_MAX_LV_IO_TIMEOUT	60	/* seconds I/O timeout (future use) */
 #define	LVM_PARTITION           0xfe	/* LVM partition id */
 #define	LVM_NEW_PARTITION       0x8e	/* new LVM partition id (10/09/1999) */
@@ -590,6 +590,7 @@
     struct lv_v2 *lv_snapshot_prev;
     struct lv_v2 *lv_snapshot_next;
     lv_block_exception_t *lv_block_exception;
+    uint8_t __unused;
     uint32_t lv_remap_ptr;
     uint32_t lv_remap_end;
     uint32_t lv_chunk_size;
@@ -786,7 +787,6 @@
 typedef struct
   {
     char pv_name[NAME_LEN];
-    kdev_t pv_dev;
   }
 pv_flush_req_t;
 
