root/drivers/block/rd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rd_request
  2. rd_ioctl
  3. rd_open
  4. rd_init
  5. identify_ramdisk_image
  6. rd_load
  7. malloc
  8. free
  9. gzip_mark
  10. gzip_release
  11. fill_inbuf
  12. flush_window
  13. error
  14. crd_load

   1 /*
   2  * ramdisk.c - Multiple ramdisk driver - gzip-loading version - v. 0.8 beta.
   3  * 
   4  * (C) Chad Page, Theodore Ts'o, et. al, 1995. 
   5  *
   6  * This ramdisk is designed to have filesystems created on it and mounted
   7  * just like a regular floppy disk.  
   8  *  
   9  * It also does something suggested by Linus: use the buffer cache as the
  10  * ramdisk data.  This makes it possible to dynamically allocate the ramdisk
  11  * buffer - with some consequences I have to deal with as I write this. 
  12  * 
  13  * This code is based on the original ramdisk.c, written mostly by
  14  * Theodore Ts'o (TYT) in 1991.  The code was largely rewritten by
  15  * Chad Page to use the buffer cache to store the ramdisk data in
  16  * 1995; Theodore then took over the driver again, and cleaned it up
  17  * for inclusion in the mainline kernel.
  18  *
  19  * The original CRAMDISK code was written by Richard Lyons, and
  20  * adapted by Chad Page to use the new ramdisk interface.  Theodore
  21  * Ts'o rewrote it so that both the compressed ramdisk loader and the
  22  * kernel decompressor uses the same inflate.c codebase.  The ramdisk
  23  * loader now also loads into a dynamic (buffer cache based) ramdisk,
  24  * not the old static ramdisk.  Support for the old static ramdisk has
  25  * been completely removed.
  26  */
  27 
  28 #include <linux/sched.h>
  29 #include <linux/minix_fs.h>
  30 #include <linux/ext2_fs.h>
  31 #include <linux/fs.h>
  32 #include <linux/kernel.h>
  33 #include <linux/string.h>
  34 #include <linux/mm.h>
  35 #include <linux/mman.h>
  36 #include <linux/malloc.h>
  37 #include <linux/ioctl.h>
  38 
  39 #include <asm/system.h>
  40 #include <asm/segment.h>
  41 
  42 extern void wait_for_keypress(void);
  43 
  44 /*
  45  * 35 has been officially registered as the RAMDISK major number, but
  46  * so is the original MAJOR number of 1.  We're using 1 in
  47  * include/linux/major.h for now
  48  */
  49 #define MAJOR_NR RAMDISK_MAJOR
  50 #include <linux/blk.h>
  51 
  52 #define BUILD_CRAMDISK
  53 #define NUM_RAMDISKS 8
  54 
  55 void rd_load(void);
  56 static int crd_load(struct file *fp, struct file *outfp);
  57 
  58 /* Various static variables go here... mostly used within the ramdisk code only. */
  59 
  60 static int rd_length[NUM_RAMDISKS];
  61 static int rd_blocksizes[NUM_RAMDISKS];
  62 
  63 /*
  64  * Parameters for the boot-loading of the ramdisk.  These are set by
  65  * init/main.c (from arguments to the kernel command line) or from the
  66  * architecture-specific setup routine (from the stored bootsector
  67  * information). 
  68  */
  69 int rd_doload = 0;              /* 1 = load ramdisk, 0 = don't load */
  70 int rd_prompt = 1;              /* 1 = prompt for ramdisk, 0 = don't prompt */
  71 int rd_image_start = 0;         /* starting block # of image */
  72 
  73 int rd_loading = 0;
  74 
  75 /*
  76  *  Basically, my strategy here is to set up a buffer-head which can't be
  77  *  deleted, and make that my Ramdisk.  If the request is outside of the
  78  *  allocated size, we must get rid of it...
  79  *
  80  */
  81 static void rd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         unsigned int minor;
  84         int offset, len;
  85 
  86 repeat:
  87         INIT_REQUEST;
  88         
  89         minor = MINOR(CURRENT->rq_dev);
  90 
  91         if (minor >= NUM_RAMDISKS) {
  92                 end_request(0);
  93                 goto repeat;
  94         }
  95         
  96         offset = CURRENT->sector << 9;
  97         len = CURRENT->current_nr_sectors << 9;
  98 
  99         if ((offset + len) > rd_length[minor]) {
 100                 end_request(0);
 101                 goto repeat;
 102         }
 103 
 104         if (CURRENT->cmd == READ) {     
 105                 memset(CURRENT->buffer, 0, len); 
 106         }
 107         set_bit(BH_Protected, &CURRENT->bh->b_state);
 108 
 109         end_request(1);
 110         goto repeat;
 111 } 
 112 
 113 static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         int err;
 116         
 117         if (!inode || !inode->i_rdev)   
 118                 return -EINVAL;
 119 
 120         switch (cmd) {
 121                 case BLKFLSBUF:
 122                         if (!suser()) return -EACCES;
 123                         invalidate_buffers(inode->i_rdev);
 124                         break;
 125                 case BLKGETSIZE:   /* Return device size */
 126                         if (!arg)  return -EINVAL;
 127                         err = verify_area(VERIFY_WRITE, (long *) arg,
 128                                           sizeof(long));
 129                         if (err)
 130                                 return err;
 131                         put_user(rd_length[MINOR(inode->i_rdev)] / 512, 
 132                                  (long *) arg);
 133                         return 0;
 134                         
 135                 default:
 136                         break;
 137         };
 138 
 139         return 0;
 140 }
 141 
 142 static int rd_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144 
 145         if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
 146                 return -ENODEV;
 147 
 148         return 0;
 149 }
 150 
 151 static struct file_operations fd_fops = {
 152         NULL,           /* lseek - default */
 153         block_read,     /* read - block dev write */
 154         block_write,    /* write - block dev write */
 155         NULL,           /* readdir - not here! */
 156         NULL,           /* select */
 157         rd_ioctl,       /* ioctl */
 158         NULL,           /* mmap */
 159         rd_open,        /* open */
 160         NULL,           /* no special release code... */
 161         block_fsync             /* fsync */ 
 162 };
 163 
 164 /* This is the registration and initialization section of the ramdisk driver */
 165 int rd_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 166 {
 167         int             i;
 168 
 169         if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
 170                 printk("RAMDISK2 : Could not get major %d", MAJOR_NR);
 171                 return -EIO;
 172         }
 173 
 174         blk_dev[MAJOR_NR].request_fn = &rd_request;
 175 
 176         for (i = 0; i < NUM_RAMDISKS; i++) {
 177                 rd_length[i] = (16384 * 1024);
 178                 rd_blocksizes[i] = 1024;
 179         }
 180 
 181         blksize_size[MAJOR_NR] = rd_blocksizes;
 182 
 183         return 0;
 184 }
 185 
 186 /*
 187  * This routine tries to a ramdisk image to load, and returns the
 188  * number of blocks to read for a non-compressed image, 0 if the image
 189  * is a compressed image, and -1 if an image with the right magic
 190  * numbers could not be found.
 191  *
 192  * We currently check for the following magic numbers:
 193  *      minix
 194  *      ext2
 195  *      gzip
 196  */
 197 int
 198 identify_ramdisk_image(int device, struct file *fp, int start_block)
     /* [previous][next][first][last][top][bottom][index][help] */
 199 {
 200         const int size = 512;
 201         struct minix_super_block *minixsb;
 202         struct ext2_super_block *ext2sb;
 203         int nblocks = -1;
 204         int max_blocks;
 205         unsigned char *buf;
 206 
 207         buf = kmalloc(size, GFP_KERNEL);
 208         if (buf == 0)
 209                 return -1;
 210 
 211         minixsb = (struct minix_super_block *) buf;
 212         ext2sb = (struct ext2_super_block *) buf;
 213         memset(buf, 0xe5, size);
 214 
 215         /*
 216          * Read block 0 to test for gzipped kernel
 217          */
 218         if (fp->f_op->lseek)
 219                 fp->f_op->lseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
 220         fp->f_pos = start_block * BLOCK_SIZE;
 221         
 222         fp->f_op->read(fp->f_inode, fp, buf, size);
 223 
 224         /*
 225          * If it matches the gzip magic numbers, return -1
 226          */
 227         if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
 228                 printk(KERN_NOTICE
 229                        "RAMDISK: Compressed image found at block %d\n",
 230                        start_block);
 231                 nblocks = 0;
 232                 goto done;
 233         }
 234 
 235         /*
 236          * Read block 1 to test for minix and ext2 superblock
 237          */
 238         if (fp->f_op->lseek)
 239                 fp->f_op->lseek(fp->f_inode, fp,
 240                                 (start_block+1) * BLOCK_SIZE, 0);
 241         fp->f_pos = (start_block+1) * BLOCK_SIZE;
 242 
 243         fp->f_op->read(fp->f_inode, fp, buf, size);
 244                 
 245         /* Try minix */
 246         if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
 247             minixsb->s_magic == MINIX_SUPER_MAGIC2) {
 248                 printk(KERN_NOTICE
 249                        "RAMDISK: Minix filesystem found at block %d\n",
 250                        start_block);
 251                 nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
 252                 goto done;
 253         }
 254 
 255         /* Try ext2 */
 256         printk("ext2 magic = %d\n", ext2sb->s_magic);
 257         if (ext2sb->s_magic == EXT2_SUPER_MAGIC) {
 258                 printk(KERN_NOTICE
 259                        "RAMDISK: Ext2 filesystem found at block %d\n",
 260                        start_block);
 261                 nblocks = ext2sb->s_blocks_count;
 262                 goto done;
 263         }
 264         printk(KERN_NOTICE
 265                "RAMDISK: Couldn't find valid ramdisk image starting at %d.\n",
 266                start_block);
 267         
 268 done:
 269         if (fp->f_op->lseek)
 270                 fp->f_op->lseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
 271         fp->f_pos = start_block * BLOCK_SIZE;   
 272 
 273         if ((nblocks > 0) && blk_size[MAJOR(device)]) {
 274                 max_blocks = blk_size[MAJOR(device)][MINOR(device)];
 275                 max_blocks -= start_block;
 276                 if (nblocks > max_blocks) {
 277                         printk(KERN_NOTICE
 278                                "RAMDISK: Restricting filesystem size "
 279                                "from %d to %d blocks.\n",
 280                                nblocks, max_blocks);
 281                         nblocks = max_blocks;
 282                 }
 283         }
 284         kfree(buf);
 285         return nblocks;
 286 }
 287 
 288 /*
 289  * This routine loads in the ramdisk image.
 290  */
 291 void rd_load()
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293         struct inode inode, out_inode;
 294         struct file infile, outfile;
 295         unsigned short fs;
 296         int device, ram_device;
 297         int nblocks, i;
 298         char *buf;
 299 
 300         if (rd_doload == 0)
 301                 return;
 302         
 303         device = ROOT_DEV;
 304         ram_device = (MAJOR_NR << 8);
 305 
 306         if (MAJOR(device) != FLOPPY_MAJOR) return;
 307 
 308         if (rd_prompt) {
 309                 printk(KERN_NOTICE
 310                        "VFS: Insert ramdisk floppy and press ENTER\n");
 311                 wait_for_keypress();
 312         }
 313 
 314         memset(&infile, 0, sizeof(infile));
 315         memset(&inode, 0, sizeof(inode));
 316         inode.i_rdev = device;
 317         infile.f_mode = 1; /* read only */
 318         infile.f_inode = &inode;
 319 
 320         memset(&outfile, 0, sizeof(outfile));
 321         memset(&out_inode, 0, sizeof(out_inode));
 322         out_inode.i_rdev = ram_device;
 323         outfile.f_mode = 3; /* read/write */
 324         outfile.f_inode = &out_inode;
 325 
 326         if (blkdev_open(&inode, &infile) != 0) return;
 327         if (blkdev_open(&out_inode, &outfile) != 0) return;
 328 
 329         fs = get_fs();
 330         set_fs(KERNEL_DS);
 331         rd_loading = 1;
 332         
 333         nblocks = identify_ramdisk_image(device, &infile, rd_image_start);
 334         if (nblocks < 0)
 335                 goto done;
 336 
 337         if (nblocks == 0) {
 338 #ifdef BUILD_CRAMDISK
 339                 if (crd_load(&infile, &outfile) == 0)
 340                         goto successful_load;
 341 #else
 342                 printk(KERN_NOTICE
 343                        "RAMDISK: Kernel does not support compressed "
 344                        "ramdisk images\n");
 345 #endif
 346                 goto done;
 347         }
 348 
 349         if (nblocks > (rd_length[0] >> BLOCK_SIZE_BITS)) {
 350                 printk("RAMDISK: image too big! (%d/%d blocks)\n",
 351                        nblocks, rd_length[0] >> BLOCK_SIZE_BITS);
 352                 goto done;
 353         }
 354                 
 355         /*
 356          * OK, time to copy in the data
 357          */
 358         buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
 359         if (buf == 0) {
 360                 printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
 361                 goto done;
 362         }
 363         for (i=0; i < nblocks; i++) {
 364                 infile.f_op->read(infile.f_inode, &infile, buf,
 365                                   BLOCK_SIZE);
 366                 outfile.f_op->write(outfile.f_inode, &outfile, buf,
 367                                     BLOCK_SIZE);
 368         }
 369         kfree(buf);
 370 
 371 successful_load:
 372         invalidate_buffers(ROOT_DEV);
 373         ROOT_DEV = (MAJOR_NR << 8);
 374 
 375 done:
 376         if (infile.f_op->release)
 377                 infile.f_op->release(&inode, &infile);
 378         set_fs(fs);
 379         rd_loading = 0;
 380 }
 381 
 382 #ifdef BUILD_CRAMDISK
 383 
 384 #include <string.h>
 385 
 386 /*
 387  * gzip declarations
 388  */
 389 
 390 #define OF(args)  args
 391 
 392 #define memzero(s, n)     memset ((s), 0, (n))
 393 
 394 
 395 typedef unsigned char  uch;
 396 typedef unsigned short ush;
 397 typedef unsigned long  ulg;
 398 
 399 #define INBUFSIZ 4096
 400 #define WSIZE 0x8000    /* window size--must be a power of two, and */
 401                         /*  at least 32K for zip's deflate method */
 402 
 403 static uch *inbuf;
 404 static uch *window;
 405 
 406 static unsigned insize = 0;  /* valid bytes in inbuf */
 407 static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
 408 static unsigned outcnt = 0;  /* bytes in output buffer */
 409 static exit_code = 0;
 410 static long bytes_out = 0;
 411 static struct file *crd_infp, *crd_outfp;
 412 
 413 #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
 414                 
 415 /* Diagnostic functions (stubbed out) */
 416 #define Assert(cond,msg)
 417 #define Trace(x)
 418 #define Tracev(x)
 419 #define Tracevv(x)
 420 #define Tracec(c,x)
 421 #define Tracecv(c,x)
 422 
 423 #define STATIC static
 424 
 425 static int  fill_inbuf(void);
 426 static void flush_window(void);
 427 static void *malloc(int size);
 428 static void free(void *where);
 429 static void error(char *m);
 430 static void gzip_mark(void **);
 431 static void gzip_release(void **);
 432 
 433 #include "../../lib/inflate.c"
 434 
 435 static void *malloc(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437         return kmalloc(size, GFP_KERNEL);
 438 }
 439 
 440 static void free(void *where)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442         kfree(where);
 443 }
 444 
 445 static void gzip_mark(void **ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447 }
 448 
 449 static void gzip_release(void **ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451 }
 452 
 453 
 454 /* ===========================================================================
 455  * Fill the input buffer. This is called only when the buffer is empty
 456  * and at least one byte is really needed.
 457  */
 458 static int fill_inbuf()
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460         if (exit_code) return -1;
 461         
 462         insize = crd_infp->f_op->read(crd_infp->f_inode, crd_infp,
 463                                       inbuf, INBUFSIZ);
 464         if (insize == 0) return -1;
 465 
 466         inptr = 1;
 467 
 468         return inbuf[0];
 469 }
 470 
 471 /* ===========================================================================
 472  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 473  * (Used for the decompressed data only.)
 474  */
 475 static void flush_window()
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477     ulg c = crc;         /* temporary variable */
 478     unsigned n;
 479     uch *in, ch;
 480     
 481     crd_outfp->f_op->write(crd_outfp->f_inode, crd_outfp, window,
 482                            outcnt);
 483     in = window;
 484     for (n = 0; n < outcnt; n++) {
 485             ch = *in++;
 486             c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
 487     }
 488     crc = c;
 489     bytes_out += (ulg)outcnt;
 490     outcnt = 0;
 491 }
 492 
 493 static void error(char *x)
     /* [previous][next][first][last][top][bottom][index][help] */
 494 {
 495         printk(KERN_ERR "%s", x);
 496         exit_code = 1;
 497 }
 498 
 499 static int
 500 crd_load(struct file * fp, struct file *outfp)
     /* [previous][next][first][last][top][bottom][index][help] */
 501 {
 502         int result;
 503         
 504         crd_infp = fp;
 505         crd_outfp = outfp;
 506         inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
 507         if (inbuf == 0) {
 508                 printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
 509                 return -1;
 510         }
 511         window = kmalloc(WSIZE, GFP_KERNEL);
 512         if (window == 0) {
 513                 printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
 514                 kfree(inbuf);
 515                 return -1;
 516         }
 517         makecrc();
 518         result = gunzip();
 519         kfree(inbuf);
 520         kfree(window);
 521         return result;
 522 }
 523 
 524 #endif
 525 
 526 
 527 

/* [previous][next][first][last][top][bottom][index][help] */