--- rd.c.0	Thu Dec 23 08:13:58 1999
+++ rd.c	Thu Dec 23 09:58:14 1999
@@ -58,6 +58,7 @@
 #include <linux/fd.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/vmalloc.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -93,6 +94,7 @@
 /* Various static variables go here.  Most are used only in the RAM disk code.
  */
 
+static char *rd_memory[NUM_RAMDISKS];		/* where the data is kept */
 static unsigned long rd_length[NUM_RAMDISKS];	/* Size of RAM disks in bytes   */
 static int rd_hardsec[NUM_RAMDISKS];		/* Size of real blocks in bytes */
 static int rd_blocksizes[NUM_RAMDISKS];		/* Size of 1024 byte blocks :)  */
@@ -210,17 +212,10 @@
 		goto repeat;
 	}
 
-	/*
-	 * If we're reading, fill the buffer with 0's.  This is okay since
-         * we're using protected buffers which should never get freed...
-	 *
-	 * If we're writing, we protect the buffer.
-  	 */
-
 	if (CURRENT->cmd == READ) 
-		memset(CURRENT->buffer, 0, len); 
+		memcpy(CURRENT->buffer, rd_memory[minor] + offset, len); 
 	else
-		set_bit(BH_Protected, &CURRENT->bh->b_state);
+		memcpy(rd_memory[minor] + offset, CURRENT->buffer, len); 
 
 	end_request(1);
 	goto repeat;
@@ -237,7 +232,8 @@
 
 	switch (cmd) {
 		case BLKFLSBUF:
-			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+			if (!capable(CAP_SYS_ADMIN))
+				return -EACCES;
 			invalidate_buffers(inode->i_rdev);
 			break;
 
@@ -304,8 +300,10 @@
 
 static int rd_open(struct inode * inode, struct file * filp)
 {
+	int minor = DEVICE_NR(inode->i_rdev);
+
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (DEVICE_NR(inode->i_rdev) == INITRD_MINOR) {
+	if (minor == INITRD_MINOR) {
 		if (!initrd_start) return -ENODEV;
 		initrd_users++;
 		filp->f_op = &initrd_fops;
@@ -313,11 +311,21 @@
 	}
 #endif
 
-	if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
+	if (minor >= NUM_RAMDISKS)
 		return -ENXIO;
 
-	MOD_INC_USE_COUNT;
+	if (rd_memory[minor] == NULL) {
+		rd_memory[minor] = vmalloc(rd_length[minor]);
+		if (!rd_memory[minor]) {
+			printk(KERN_ERR 
+			"RAMDISK: Can't vmalloc(%08lx) for minor=%d\n", 
+			rd_length[minor], minor);
+			return -ENOMEM;
+		}
+		memset(rd_memory[minor], '\0', rd_length[minor]);
+	}
 
+	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -346,9 +354,11 @@
 {
 	int i;
 
-	for (i = 0 ; i < NUM_RAMDISKS; i++)
+	for (i = 0; i < NUM_RAMDISKS; i++) {
+		if (rd_memory[i] != NULL)
+			vfree(rd_memory[i]);
 		invalidate_buffers(MKDEV(MAJOR_NR, i));
-
+	}
 	unregister_blkdev( MAJOR_NR, "ramdisk" );
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 }
@@ -356,16 +366,16 @@
 /* This is the registration and initialization section of the RAM disk driver */
 int __init rd_init (void)
 {
-	int		i;
+	int i;
 
 	if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
-	    (rd_blocksize & (rd_blocksize-1)))
-	{
+	    (rd_blocksize & (rd_blocksize-1))) {
 		printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
 		       rd_blocksize);
 		rd_blocksize = BLOCK_SIZE;
 	}
 
+
 	if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
 		printk("RAMDISK: Could not get major %d", MAJOR_NR);
 		return -EIO;
@@ -375,10 +385,11 @@
 
 	for (i = 0; i < NUM_RAMDISKS; i++) {
 		/* rd_size is given in kB */
-		rd_length[i] = rd_size << 10;
+		rd_length[i] = PAGE_ALIGN(rd_size << 10);
 		rd_hardsec[i] = rd_blocksize;
 		rd_blocksizes[i] = rd_blocksize;
 		rd_kbsize[i] = rd_size;
+		rd_memory[i] = NULL;
 	}
 
 	hardsect_size[MAJOR_NR] = rd_hardsec;		/* Size of the RAM disk blocks */
