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

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