diff -urN 2.4.0ac4/Documentation/Configure.help 2.4.0ac4-lvm/Documentation/Configure.help
--- 2.4.0ac4/Documentation/Configure.help	Tue Jan  9 01:25:32 2001
+++ 2.4.0ac4-lvm/Documentation/Configure.help	Tue Jan  9 01:26:16 2001
@@ -1447,15 +1447,6 @@
   want), say M here and read Documentation/modules.txt. The module
   will be called lvm-mod.o.
 
-Logical Volume Manager /proc file system information
-CONFIG_LVM_PROC_FS
-  If you say Y here, you are able to access overall Logical Volume
-  Manager, Volume Group, Logical and Physical Volume information in
-  /proc/lvm.
-
-  To use this option, you have to check, that the "/proc file system
-  support" (CONFIG_PROC_FS) is enabled too.
-
 Multiple devices driver support
 CONFIG_BLK_DEV_MD
   This driver lets you combine several hard disk partitions into one
diff -urN 2.4.0ac4/drivers/md/Config.in 2.4.0ac4-lvm/drivers/md/Config.in
--- 2.4.0ac4/drivers/md/Config.in	Tue Jan  9 01:25:37 2001
+++ 2.4.0ac4-lvm/drivers/md/Config.in	Tue Jan  9 01:26:16 2001
@@ -17,6 +17,5 @@
 fi
 
 dep_tristate '  Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD
-dep_mbool '    LVM information in proc filesystem' CONFIG_LVM_PROC_FS $CONFIG_BLK_DEV_LVM
 
 endmenu
diff -urN 2.4.0ac4/drivers/md/lvm-snap.c 2.4.0ac4-lvm/drivers/md/lvm-snap.c
--- 2.4.0ac4/drivers/md/lvm-snap.c	Tue Jan  2 17:41:16 2001
+++ 2.4.0ac4-lvm/drivers/md/lvm-snap.c	Tue Jan  9 01:26:17 2001
@@ -214,10 +214,10 @@
 	memset(lv_COW_table, 0, blksize_snap);
 	for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {
 		/* store new COW_table entry */
-		lv_COW_table[id].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
-		lv_COW_table[id].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_org);
-		lv_COW_table[id].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
-		lv_COW_table[id].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_new);
+		lv_COW_table[id].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
+		lv_COW_table[id].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_org);
+		lv_COW_table[id].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
+		lv_COW_table[id].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_new);
 	}
 }
 
@@ -268,10 +268,10 @@
 	blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
 
 	/* store new COW_table entry */
-	lv_COW_table[idx_COW_table].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
-	lv_COW_table[idx_COW_table].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_org);
-	lv_COW_table[idx_COW_table].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, snap_phys_dev));
-	lv_COW_table[idx_COW_table].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_new);
+	lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
+	lv_COW_table[idx_COW_table].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_org);
+	lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, snap_phys_dev));
+	lv_COW_table[idx_COW_table].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_new);
 
 	length_tmp = iobuf->length;
 	iobuf->length = blksize_snap;
diff -urN 2.4.0ac4/drivers/md/lvm.c 2.4.0ac4-lvm/drivers/md/lvm.c
--- 2.4.0ac4/drivers/md/lvm.c	Tue Jan  9 01:25:37 2001
+++ 2.4.0ac4-lvm/drivers/md/lvm.c	Wed Jan 10 05:36:54 2001
@@ -139,6 +139,7 @@
  *                 lvm_proc_get_global_info()
  *    02/11/2000 - implemented /proc/lvm/ hierarchy
  *    07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
+ *    25/12/2000 - fix procfs #defines - Christoph Hellwig
  *
  */
 
@@ -224,7 +225,7 @@
 
 static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 int lvm_proc_read_vg_info(char *, char **, off_t, int, int *, void *);
 int lvm_proc_read_lv_info(char *, char **, off_t, int, int *, void *);
 int lvm_proc_read_pv_info(char *, char **, off_t, int, int *, void *);
@@ -347,7 +348,7 @@
 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *lvm_proc_dir = NULL;
 static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
 struct proc_dir_entry *pde = NULL;
@@ -433,7 +434,7 @@
 		&lvm_chr_fops, NULL);
 #endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_proc_dir = create_proc_entry (LVM_DIR, S_IFDIR, &proc_root);
 	if (lvm_proc_dir != NULL) {
 		lvm_proc_vg_subdir = create_proc_entry (LVM_VG_SUBDIR, S_IFDIR, lvm_proc_dir);
@@ -521,7 +522,7 @@
 	blksize_size[MAJOR_NR] = NULL;
 	hardsect_size[MAJOR_NR] = NULL;
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
 	remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
 	remove_proc_entry(LVM_DIR, &proc_root);
@@ -1263,7 +1264,7 @@
 }
 
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 /*
  * Support functions /proc-Filesystem
  */
@@ -1452,8 +1453,6 @@
 	else
 		return count;
 } /* lvm_proc_get_global_info() */
-#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
-
 
 /*
  * provide VG information
@@ -1530,7 +1529,7 @@
 
 	return sz;
 }
-
+#endif /* CONFIG_PROC_FS */
 
 /*
  * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c
@@ -1659,6 +1658,8 @@
 	if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) {
 		/* original logical volume */
 		if (lv->lv_access & LV_SNAPSHOT_ORG) {
+			/* Serializes the access to the lv_snapshot_next list */
+			down(&lv->lv_snapshot_sem);
 			if (rw == WRITE || rw == WRITEA)
 			{
 				lv_t *lv_ptr;
@@ -1669,7 +1670,8 @@
 				     lv_ptr = lv_ptr->lv_snapshot_next) {
 					/* Check for inactive snapshot */
 					if (!(lv_ptr->lv_status & LV_ACTIVE)) continue;
-					down(&lv->lv_snapshot_org->lv_snapshot_sem);
+					/* Serializes the COW with the accesses to the snapshot device */
+					down(&lv_ptr->lv_snapshot_sem);
 					/* do we still have exception storage for this snapshot free? */
 					if (lv_ptr->lv_block_exception != NULL) {
 						rdev_sav = rdev_tmp;
@@ -1690,9 +1692,10 @@
 						rdev_tmp = rdev_sav;
 						rsector_tmp = rsector_sav;
 					}
-					up(&lv->lv_snapshot_org->lv_snapshot_sem);
+					up(&lv_ptr->lv_snapshot_sem);
 				}
 			}
+			up(&lv->lv_snapshot_sem);
 		} else {
 			/* remap snapshot logical volume */
 			down(&lv->lv_snapshot_sem);
@@ -1989,7 +1992,7 @@
 		&lvm_chr_fops, NULL);
 #endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_create_proc_entry_of_vg ( vg_ptr);
 #endif
 
@@ -2021,21 +2024,11 @@
 		for (p = 0; p < vg_ptr->pv_max; p++) {
 			if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) {
 				ret = lvm_do_pv_create(arg, vg_ptr, p);
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
-				lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
-#endif
 				if ( ret != 0) return ret;
-	
-				/* We don't need the PE list
-				   in kernel space like LVs pe_t list */
-				pv_ptr->pe = NULL;
-				vg_ptr->pv_cur++;
-				vg_ptr->pv_act++;
-				vg_ptr->pe_total +=
-				    pv_ptr->pe_total;
-#ifdef LVM_GET_INODE
-				/* insert a dummy inode for fs_may_mount */
-				pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
+				pv_ptr = vg_ptr->pv[p] ;
+				vg_ptr->pe_total += pv_ptr->pe_total;
+#ifdef CONFIG_PROC_FS
+				lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
 #endif
 				return 0;
 			}
@@ -2062,10 +2055,6 @@
 		    strcmp(pv_ptr->pv_name,
 			       pv_name) == 0) {
 			if (pv_ptr->lv_cur > 0) return -EPERM;
-			vg_ptr->pe_total -=
-			    pv_ptr->pe_total;
-			vg_ptr->pv_cur--;
-			vg_ptr->pv_act--;
 			lvm_do_pv_remove(vg_ptr, p);
 			/* Make PV pointer array contiguous */
 			for (; p < vg_ptr->pv_max - 1; p++)
@@ -2093,7 +2082,7 @@
 	if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)
 		return -EFAULT;
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_vg ( vg_ptr);
 #endif
 
@@ -2117,7 +2106,7 @@
 		strncpy(pv_ptr->vg_name, vg_name, NAME_LEN);
 	}
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_create_proc_entry_of_vg ( vg_ptr);
 #endif
 
@@ -2181,7 +2170,7 @@
 	devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);
 #endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_vg ( vg_ptr);
 #endif
 
@@ -2239,7 +2228,7 @@
 static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {
 	pv_t *pv_ptr = vg_ptr->pv[p];
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);
 #endif
 	vg_ptr->pe_total -=
@@ -2374,18 +2363,10 @@
 
 				lv_ptr->lv_snapshot_minor = 0;
 				lv_ptr->lv_snapshot_org = lv_ptr;
-				lv_ptr->lv_snapshot_prev = NULL;
-				/* walk thrugh the snapshot list */
-				while (lv_ptr->lv_snapshot_next != NULL)
-					lv_ptr = lv_ptr->lv_snapshot_next;
-				/* now lv_ptr points to the last existing snapshot in the chain */
-				vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr;
 				/* our new one now back points to the previous last in the chain
 				   which can be the original logical volume */
 				lv_ptr = vg_ptr->lv[l];
 				/* now lv_ptr points to our new last snapshot logical volume */
-				lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org;
-				lv_ptr->lv_snapshot_next = NULL;
 				lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe;
 				lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le;
 				lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le;
@@ -2444,22 +2425,27 @@
 	}
 #endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
 #endif
 
 	/* optionally add our new snapshot LV */
 	if (lv_ptr->lv_access & LV_SNAPSHOT) {
+		lv_t * org = lv_ptr->lv_snapshot_org, * last;
 		/* sync the original logical volume */
-		fsync_dev(lv_ptr->lv_snapshot_org->lv_dev);
+		fsync_dev(org->lv_dev);
 #ifdef	LVM_VFS_ENHANCEMENT
 		/* VFS function call to sync and lock the filesystem */
-		fsync_dev_lockfs(lv_ptr->lv_snapshot_org->lv_dev);
+		fsync_dev_lockfs(org->lv_dev);
 #endif
-		lv_ptr->lv_snapshot_org->lv_access |= LV_SNAPSHOT_ORG;
-		lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG;
-		/* put ourselve into the chain */
-		lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr;
+		down(&org->lv_snapshot_sem);
+		org->lv_access |= LV_SNAPSHOT_ORG;
+		lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
+		/* Link in the list of snapshot volumes */
+		for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next);
+		lv_ptr->lv_snapshot_prev = last;
+		last->lv_snapshot_next = lv_ptr;
+		up(&org->lv_snapshot_sem);
 	}
 
 	/* activate the logical volume */
@@ -2515,6 +2501,28 @@
 	    lv_ptr->lv_snapshot_next != NULL)
 		return -EPERM;
 
+	if (lv_ptr->lv_access & LV_SNAPSHOT) {
+		/*
+		 * Atomically make the the snapshot invisible
+		 * to the original lv before playing with it.
+		 */
+		lv_t * org = lv_ptr->lv_snapshot_org;
+		down(&org->lv_snapshot_sem);
+
+		/* remove this snapshot logical volume from the chain */
+		lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
+		if (lv_ptr->lv_snapshot_next != NULL) {
+			lv_ptr->lv_snapshot_next->lv_snapshot_prev =
+			    lv_ptr->lv_snapshot_prev;
+		}
+		up(&org->lv_snapshot_sem);
+
+		/* no more snapshots? */
+		if (!org->lv_snapshot_next)
+			org->lv_access &= ~LV_SNAPSHOT_ORG;
+		lvm_snapshot_release(lv_ptr);
+	}
+
 	lv_ptr->lv_status |= LV_SPINDOWN;
 
 	/* sync the buffers */
@@ -2548,25 +2556,13 @@
 			}
 		}
 		vfree(lv_ptr->lv_current_pe);
-	/* LV_SNAPSHOT */
-	} else {
-		/* remove this snapshot logical volume from the chain */
-		lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
-		if (lv_ptr->lv_snapshot_next != NULL) {
-			lv_ptr->lv_snapshot_next->lv_snapshot_prev =
-			    lv_ptr->lv_snapshot_prev;
-		}
-		/* no more snapshots? */
-		if (lv_ptr->lv_snapshot_org->lv_snapshot_next == NULL)
-			lv_ptr->lv_snapshot_org->lv_access &= ~LV_SNAPSHOT_ORG;
-		lvm_snapshot_release(lv_ptr);
 	}
 
 #ifdef	CONFIG_DEVFS_FS
 	devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]);
 #endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
 #endif
 
@@ -2916,13 +2912,13 @@
 		if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
 		if (lv_ptr->lv_dev == lv->lv_dev)
 		{
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 			lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
 #endif
 			strncpy(lv_ptr->lv_name,
 				lv_req->lv_name,
 				NAME_LEN);
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 			lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
 #endif
 			break;
@@ -3004,9 +3000,7 @@
 } /* lvm_do_pv_status() */
 
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
-
-
+#ifdef CONFIG_PROC_FS
 /*
  * create a /proc entry for a logical volume
  */
@@ -3135,8 +3129,7 @@
 		remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
 	}
 }
-#endif
-
+#endif /* CONFIG_PROC_FS */
 
 /*
  * support function initialize gendisk variables
diff -urN 2.4.0ac4/include/linux/lvm.h 2.4.0ac4-lvm/include/linux/lvm.h
--- 2.4.0ac4/include/linux/lvm.h	Mon Jan  8 06:33:52 2001
+++ 2.4.0ac4-lvm/include/linux/lvm.h	Tue Jan  9 01:26:17 2001
@@ -57,6 +57,8 @@
  *    26/06/2000 - implemented snapshot persistency and resizing support
  *    02/11/2000 - added hash table size member to lv structure
  *    12/11/2000 - removed unneeded timestamp definitions
+ *    24/12/2000 - removed LVM_TO_{CORE,DISK}*, use cpu_{from, to}_le*
+ *                 instead - Christoph Hellwig
  *
  */
 
@@ -68,7 +70,6 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
-#include <endian.h>
 
 /*
  * preprocessor definitions
@@ -324,51 +325,6 @@
 	COW_table_entries_per_PE = LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg, lv); \
 	COW_table_chunks_per_PE = ( COW_table_entries_per_PE * sizeof(lv_COW_table_disk_t) / SECTOR_SIZE + lv->lv_chunk_size - 1) / lv->lv_chunk_size; \
 	COW_table_entries_per_PE - COW_table_chunks_per_PE;})
-
-
-/* to disk and to core data conversion macros */
-#if __BYTE_ORDER == __BIG_ENDIAN
-
-#define LVM_TO_CORE16(x) ( \
-        ((uint16_t)((((uint16_t)(x) & 0x00FFU) << 8) | \
-                    (((uint16_t)(x) & 0xFF00U) >> 8))))
-
-#define LVM_TO_DISK16(x) LVM_TO_CORE16(x)
-
-#define LVM_TO_CORE32(x) ( \
-        ((uint32_t)((((uint32_t)(x) & 0x000000FFU) << 24) | \
-                    (((uint32_t)(x) & 0x0000FF00U) << 8))) \
-                    (((uint32_t)(x) & 0x00FF0000U) >> 8))) \
-                    (((uint32_t)(x) & 0xFF000000U) >> 24))))
-
-#define LVM_TO_DISK32(x) LVM_TO_CORE32(x)
-
-#define LVM_TO_CORE64(x) \
-        ((uint64_t)((((uint64_t)(x) & 0x00000000000000FFULL) << 56) | \
-                    (((uint64_t)(x) & 0x000000000000FF00ULL) << 40) | \
-                    (((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) | \
-                    (((uint64_t)(x) & 0x00000000FF000000ULL) <<  8) | \
-                    (((uint64_t)(x) & 0x000000FF00000000ULL) >>  8) | \
-                    (((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) | \
-                    (((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) | \
-                    (((uint64_t)(x) & 0xFF00000000000000ULL) >> 56))) 
-
-#define LVM_TO_DISK64(x) LVM_TO_CORE64(x)
-
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define LVM_TO_CORE16(x) x
-#define LVM_TO_DISK16(x) x
-#define LVM_TO_CORE32(x) x
-#define LVM_TO_DISK32(x) x
-#define LVM_TO_CORE64(x) x
-#define LVM_TO_DISK64(x) x
-
-#else
-
-#error "__BYTE_ORDER must be defined as __LITTLE_ENDIAN or __BIG_ENDIAN"
-
-#endif /* #if __BYTE_ORDER == __BIG_ENDIAN */
 
 
 /*