--- 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 */