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

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