root/drivers/block/loop.c

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

DEFINITIONS

This source file includes following definitions.
  1. transfer_none
  2. transfer_xor
  3. transfer_des
  4. figure_loop_size
  5. do_lo_request
  6. loop_set_fd
  7. loop_clr_fd
  8. loop_set_status
  9. loop_get_status
  10. lo_ioctl
  11. lo_open
  12. lo_release
  13. loop_init
  14. cleanup_module

   1 /*
   2  *  linux/drivers/block/loop.c
   3  *
   4  *  Written by Theodore Ts'o, 3/29/93
   5  * 
   6  * Copyright 1993 by Theodore Ts'o.  Redistribution of this file is
   7  * permitted under the GNU Public License.
   8  *
   9  * DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993
  10  *
  11  * Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994
  12  *
  13  * Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996
  14  */
  15 
  16 #include <linux/module.h>
  17 
  18 #include <linux/fs.h>
  19 #include <linux/stat.h>
  20 #include <linux/errno.h>
  21 #include <linux/major.h>
  22 
  23 #include <asm/segment.h>
  24 
  25 #ifdef DES_AVAILABLE
  26 #include "des.h"
  27 #endif
  28 #include <linux/loop.h>         /* must follow des.h */
  29 
  30 #define MAJOR_NR LOOP_MAJOR
  31 
  32 #define DEVICE_NAME "loop"
  33 #define DEVICE_REQUEST do_lo_request
  34 #define DEVICE_NR(device) (MINOR(device))
  35 #define DEVICE_ON(device)
  36 #define DEVICE_OFF(device)
  37 #define DEVICE_NO_RANDOM
  38 #define TIMEOUT_VALUE (6 * HZ)
  39 #include <linux/blk.h>
  40 
  41 #define MAX_LOOP 8
  42 static struct loop_device loop_dev[MAX_LOOP];
  43 static int loop_sizes[MAX_LOOP];
  44 
  45 /*
  46  * Transfer functions
  47  */
  48 static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf,
     /* [previous][next][first][last][top][bottom][index][help] */
  49                   char *loop_buf, int size)
  50 {
  51         if (cmd == READ)
  52                 memcpy(loop_buf, raw_buf, size);
  53         else
  54                 memcpy(raw_buf, loop_buf, size);
  55         return 0;
  56 }
  57 
  58 static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf,
     /* [previous][next][first][last][top][bottom][index][help] */
  59                  char *loop_buf, int size)
  60 {
  61         char    *in, *out, *key;
  62         int     i, keysize;
  63 
  64         if (cmd == READ) {
  65                 in = raw_buf;
  66                 out = loop_buf;
  67         } else {
  68                 in = loop_buf;
  69                 out = raw_buf;
  70         }
  71         key = lo->lo_encrypt_key;
  72         keysize = lo->lo_encrypt_key_size;
  73         for (i=0; i < size; i++)
  74                 *out++ = *in++ ^ key[(i & 511) % keysize];
  75         return 0;
  76 }
  77 
  78 #ifdef DES_AVAILABLE
  79 static int transfer_des(struct loop_device *lo, int cmd, char *raw_buf,
     /* [previous][next][first][last][top][bottom][index][help] */
  80                   char *loop_buf, int size)
  81 {
  82         unsigned long tmp[2];
  83         unsigned long x0,x1,p0,p1;
  84 
  85         if (size & 7)
  86                 return -EINVAL;
  87         x0 = lo->lo_des_init[0];
  88         x1 = lo->lo_des_init[1];
  89         while (size) {
  90                 if (cmd == READ) {
  91                         tmp[0] = (p0 = ((unsigned long *) raw_buf)[0])^x0;
  92                         tmp[1] = (p1 = ((unsigned long *) raw_buf)[1])^x1;
  93                         des_ecb_encrypt((des_cblock *) tmp,(des_cblock *)
  94                             loop_buf,lo->lo_des_key,DES_ENCRYPT);
  95                         x0 = p0^((unsigned long *) loop_buf)[0];
  96                         x1 = p1^((unsigned long *) loop_buf)[1];
  97                 }
  98                 else {
  99                         p0 = ((unsigned long *) loop_buf)[0];
 100                         p1 = ((unsigned long *) loop_buf)[1];
 101                         des_ecb_encrypt((des_cblock *) loop_buf,(des_cblock *)
 102                             raw_buf,lo->lo_des_key,DES_DECRYPT);
 103                         ((unsigned long *) raw_buf)[0] ^= x0;
 104                         ((unsigned long *) raw_buf)[1] ^= x1;
 105                         x0 = p0^((unsigned long *) raw_buf)[0];
 106                         x1 = p1^((unsigned long *) raw_buf)[1];
 107                 }
 108                 size -= 8;
 109                 raw_buf += 8;
 110                 loop_buf += 8;
 111         }
 112         return 0;
 113 }
 114 #endif
 115 
 116 static transfer_proc_t xfer_funcs[MAX_LOOP] = {
 117         transfer_none,          /* LO_CRYPT_NONE */
 118         transfer_xor,           /* LO_CRYPT_XOR */
 119 #ifdef DES_AVAILABLE
 120         transfer_des,           /* LO_CRYPT_DES */
 121 #else
 122         NULL,                   /* LO_CRYPT_DES */
 123 #endif
 124         0                       /* LO_CRYPT_IDEA */
 125 };
 126 
 127 
 128 #define MAX_DISK_SIZE 1024*1024*1024
 129 
 130 
 131 static void figure_loop_size(struct loop_device *lo)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133         int     size;
 134 
 135         if (S_ISREG(lo->lo_inode->i_mode))
 136                 size = (lo->lo_inode->i_size - lo->lo_offset) / BLOCK_SIZE;
 137         else {
 138                 kdev_t lodev = lo->lo_device;
 139                 if (blk_size[MAJOR(lodev)])
 140                         size = blk_size[MAJOR(lodev)][MINOR(lodev)] -
 141                                 lo->lo_offset / BLOCK_SIZE;
 142                 else
 143                         size = MAX_DISK_SIZE;
 144         }
 145         loop_sizes[lo->lo_number] = size;
 146 }
 147 
 148 static void do_lo_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150         int     real_block, block, offset, len, blksize, size;
 151         char    *dest_addr;
 152         struct loop_device *lo;
 153         struct buffer_head *bh;
 154 
 155 repeat:
 156         INIT_REQUEST;
 157         if (MINOR(CURRENT->rq_dev) >= MAX_LOOP)
 158                 goto error_out;
 159         lo = &loop_dev[MINOR(CURRENT->rq_dev)];
 160         if (!lo->lo_inode || !lo->transfer)
 161                 goto error_out;
 162 
 163         blksize = BLOCK_SIZE;
 164         if (blksize_size[MAJOR(lo->lo_device)]) {
 165             blksize = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)];
 166             if (!blksize)
 167               blksize = BLOCK_SIZE;
 168         }
 169 
 170         dest_addr = CURRENT->buffer;
 171         
 172         if (blksize < 512) {
 173                 block = CURRENT->sector * (512/blksize);
 174                 offset = 0;
 175         } else {
 176                 block = CURRENT->sector / (blksize >> 9);
 177                 offset = CURRENT->sector % (blksize >> 9);
 178         }
 179         block += lo->lo_offset / blksize;
 180         offset += lo->lo_offset % blksize;
 181         if (offset > blksize) {
 182                 block++;
 183                 offset -= blksize;
 184         }
 185         len = CURRENT->current_nr_sectors << 9;
 186         if (CURRENT->cmd == WRITE) {
 187                 if (lo->lo_flags & LO_FLAGS_READ_ONLY)
 188                         goto error_out;
 189         } else if (CURRENT->cmd != READ) {
 190                 printk("unknown loop device command (%d)?!?", CURRENT->cmd);
 191                 goto error_out;
 192         }
 193         while (len > 0) {
 194                 real_block = block;
 195                 if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
 196                         real_block = bmap(lo->lo_inode, block);
 197                         if (!real_block) {
 198                                 printk("loop: block %d not present\n", block);
 199                                 goto error_out;
 200                         }
 201                 }
 202                 bh = getblk(lo->lo_device, real_block, blksize);
 203                 if (!bh) {
 204                         printk("loop: device %s: getblk(-, %d, %d) returned NULL",
 205                                kdevname(lo->lo_device),
 206                                block, blksize);
 207                         goto error_out;
 208                 }
 209                 if (!buffer_uptodate(bh) && ((CURRENT->cmd == READ) ||
 210                                         (offset || (len < blksize)))) {
 211                         ll_rw_block(READ, 1, &bh);
 212                         wait_on_buffer(bh);
 213                         if (!buffer_uptodate(bh)) {
 214                                 brelse(bh);
 215                                 goto error_out;
 216                         }
 217                 }
 218                 size = blksize - offset;
 219                 if (size > len)
 220                         size = len;
 221                            
 222                 if ((lo->transfer)(lo, CURRENT->cmd, bh->b_data + offset,
 223                                    dest_addr, size)) {
 224                         printk("loop: transfer error block %d\n", block);
 225                         brelse(bh);
 226                         goto error_out;
 227                 }
 228                 if (CURRENT->cmd == WRITE)
 229                         mark_buffer_dirty(bh, 1);
 230                 brelse(bh);
 231                 dest_addr += size;
 232                 len -= size;
 233                 offset = 0;
 234                 block++;
 235         }
 236         end_request(1);
 237         goto repeat;
 238 error_out:
 239         end_request(0);
 240         goto repeat;
 241 }
 242 
 243 static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 244 {
 245         struct file     *file;
 246         struct inode    *inode;
 247 
 248         if (arg >= NR_OPEN || !(file = current->files->fd[arg]))
 249                 return -EBADF;
 250         if (lo->lo_inode)
 251                 return -EBUSY;
 252         inode = file->f_inode;
 253         if (!inode) {
 254                 printk("loop_set_fd: NULL inode?!?\n");
 255                 return -EINVAL;
 256         }
 257         if (S_ISBLK(inode->i_mode)) {
 258                 int error = blkdev_open(inode, file);
 259                 if (error)
 260                         return error;
 261                 lo->lo_device = inode->i_rdev;
 262                 lo->lo_flags = 0;
 263         } else if (S_ISREG(inode->i_mode)) {
 264                 lo->lo_device = inode->i_dev;
 265                 lo->lo_flags = LO_FLAGS_DO_BMAP;
 266         } else
 267                 return -EINVAL;
 268 
 269         if (IS_RDONLY (inode) || is_read_only(lo->lo_device)) {
 270                 lo->lo_flags |= LO_FLAGS_READ_ONLY;
 271                 set_device_ro(dev, 1);
 272         } else {
 273                 invalidate_inode_pages (inode);
 274                 set_device_ro(dev, 0);
 275         }
 276 
 277         lo->lo_inode = inode;
 278         lo->lo_inode->i_count++;
 279         lo->transfer = NULL;
 280         figure_loop_size(lo);
 281         MOD_INC_USE_COUNT;
 282         return 0;
 283 }
 284 
 285 static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287         if (!lo->lo_inode)
 288                 return -ENXIO;
 289         if (lo->lo_refcnt > 1)  /* we needed one fd for the ioctl */
 290                 return -EBUSY;
 291         if (S_ISBLK(lo->lo_inode->i_mode))
 292                 blkdev_release (lo->lo_inode);
 293         iput(lo->lo_inode);
 294         lo->lo_device = 0;
 295         lo->lo_inode = NULL;
 296         lo->lo_encrypt_type = 0;
 297         lo->lo_offset = 0;
 298         lo->lo_encrypt_key_size = 0;
 299         memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 300         memset(lo->lo_name, 0, LO_NAME_SIZE);
 301         loop_sizes[lo->lo_number] = 0;
 302         invalidate_buffers(dev);
 303         MOD_DEC_USE_COUNT;
 304         return 0;
 305 }
 306 
 307 static int loop_set_status(struct loop_device *lo, struct loop_info *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309         struct loop_info info;
 310         int err;
 311 
 312         if (!lo->lo_inode)
 313                 return -ENXIO;
 314         if (!arg)
 315                 return -EINVAL;
 316         err = verify_area(VERIFY_READ, arg, sizeof(info));
 317         if (err)
 318                 return err;
 319         memcpy_fromfs(&info, arg, sizeof(info));
 320         if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE)
 321                 return -EINVAL;
 322         switch (info.lo_encrypt_type) {
 323         case LO_CRYPT_NONE:
 324                 break;
 325         case LO_CRYPT_XOR:
 326                 if (info.lo_encrypt_key_size < 0)
 327                         return -EINVAL;
 328                 break;
 329 #ifdef DES_AVAILABLE
 330         case LO_CRYPT_DES:
 331                 if (info.lo_encrypt_key_size != 8)
 332                         return -EINVAL;
 333                 des_set_key((des_cblock *) lo->lo_encrypt_key,
 334                    lo->lo_des_key);
 335                 memcpy(lo->lo_des_init,info.lo_init,8);
 336                 break;
 337 #endif
 338         default:
 339                 return -EINVAL;
 340         }
 341         lo->lo_offset = info.lo_offset;
 342         strncpy(lo->lo_name, info.lo_name, LO_NAME_SIZE);
 343         lo->lo_encrypt_type = info.lo_encrypt_type;
 344         lo->transfer = xfer_funcs[lo->lo_encrypt_type];
 345         lo->lo_encrypt_key_size = info.lo_encrypt_key_size;
 346         if (info.lo_encrypt_key_size)
 347                 memcpy(lo->lo_encrypt_key, info.lo_encrypt_key,
 348                        info.lo_encrypt_key_size);
 349         figure_loop_size(lo);
 350         return 0;
 351 }
 352 
 353 static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 354 {
 355         struct loop_info        info;
 356         int err;
 357         
 358         if (!lo->lo_inode)
 359                 return -ENXIO;
 360         if (!arg)
 361                 return -EINVAL;
 362         err = verify_area(VERIFY_WRITE, arg, sizeof(info));
 363         if (err)
 364                 return err;
 365         memset(&info, 0, sizeof(info));
 366         info.lo_number = lo->lo_number;
 367         info.lo_device = kdev_t_to_nr(lo->lo_inode->i_dev);
 368         info.lo_inode = lo->lo_inode->i_ino;
 369         info.lo_rdevice = kdev_t_to_nr(lo->lo_device);
 370         info.lo_offset = lo->lo_offset;
 371         info.lo_flags = lo->lo_flags;
 372         strncpy(info.lo_name, lo->lo_name, LO_NAME_SIZE);
 373         info.lo_encrypt_type = lo->lo_encrypt_type;
 374         if (lo->lo_encrypt_key_size && suser()) {
 375                 info.lo_encrypt_key_size = lo->lo_encrypt_key_size;
 376                 memcpy(info.lo_encrypt_key, lo->lo_encrypt_key,
 377                        lo->lo_encrypt_key_size);
 378         }
 379         memcpy_tofs(arg, &info, sizeof(info));
 380         return 0;
 381 }
 382 
 383 static int lo_ioctl(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 384         unsigned int cmd, unsigned long arg)
 385 {
 386         struct loop_device *lo;
 387         int dev, err;
 388 
 389         if (!inode)
 390                 return -EINVAL;
 391         if (MAJOR(inode->i_rdev) != MAJOR_NR) {
 392                 printk("lo_ioctl: pseudo-major != %d\n", MAJOR_NR);
 393                 return -ENODEV;
 394         }
 395         dev = MINOR(inode->i_rdev);
 396         if (dev >= MAX_LOOP)
 397                 return -ENODEV;
 398         lo = &loop_dev[dev];
 399         switch (cmd) {
 400         case LOOP_SET_FD:
 401                 return loop_set_fd(lo, inode->i_rdev, arg);
 402         case LOOP_CLR_FD:
 403                 return loop_clr_fd(lo, inode->i_rdev);
 404         case LOOP_SET_STATUS:
 405                 return loop_set_status(lo, (struct loop_info *) arg);
 406         case LOOP_GET_STATUS:
 407                 return loop_get_status(lo, (struct loop_info *) arg);
 408         case BLKGETSIZE:   /* Return device size */
 409                 if (!lo->lo_inode)
 410                         return -ENXIO;
 411                 if (!arg)  return -EINVAL;
 412                 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 413                 if (err)
 414                         return err;
 415                 put_fs_long(loop_sizes[lo->lo_number] << 1, (long *) arg);
 416                 return 0;
 417                 default:
 418                         return -EINVAL;
 419         }
 420         return 0;
 421 }
 422 
 423 static int lo_open(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 424 {
 425         struct loop_device *lo;
 426         int     dev;
 427 
 428         if (!inode)
 429                 return -EINVAL;
 430         if (MAJOR(inode->i_rdev) != MAJOR_NR) {
 431                 printk("lo_open: pseudo-major != %d\n", MAJOR_NR);
 432                 return -ENODEV;
 433         }
 434         dev = MINOR(inode->i_rdev);
 435         if (dev >= MAX_LOOP)
 436                 return -ENODEV;
 437         lo = &loop_dev[dev];
 438         lo->lo_refcnt++;
 439         MOD_INC_USE_COUNT;
 440         return 0;
 441 }
 442 
 443 static void lo_release(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445         struct loop_device *lo;
 446         int     dev;
 447 
 448         if (!inode)
 449                 return;
 450         if (MAJOR(inode->i_rdev) != MAJOR_NR) {
 451                 printk("lo_release: pseudo-major != %d\n", MAJOR_NR);
 452                 return;
 453         }
 454         dev = MINOR(inode->i_rdev);
 455         if (dev >= MAX_LOOP)
 456                 return;
 457         fsync_dev(inode->i_rdev);
 458         lo = &loop_dev[dev];
 459         if (lo->lo_refcnt <= 0)
 460                 printk("lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
 461         else  {
 462                 lo->lo_refcnt--;
 463                 MOD_DEC_USE_COUNT;
 464         }
 465 }
 466 
 467 static struct file_operations lo_fops = {
 468         NULL,                   /* lseek - default */
 469         block_read,             /* read - general block-dev read */
 470         block_write,            /* write - general block-dev write */
 471         NULL,                   /* readdir - bad */
 472         NULL,                   /* select */
 473         lo_ioctl,               /* ioctl */
 474         NULL,                   /* mmap */
 475         lo_open,                /* open */
 476         lo_release              /* release */
 477 };
 478 
 479 /*
 480  * And now the modules code and kernel interface.
 481  */
 482 #ifdef MODULE
 483 #define loop_init init_module
 484 #endif
 485 
 486 int
 487 loop_init( void ) {
     /* [previous][next][first][last][top][bottom][index][help] */
 488         int     i;
 489 
 490         if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
 491                 printk("Unable to get major number %d for loop device\n",
 492                        MAJOR_NR);
 493                 return -EIO;
 494         }
 495 #ifndef MODULE
 496         printk("loop: registered device at major %d\n", MAJOR_NR);
 497 #endif
 498 
 499         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 500         for (i=0; i < MAX_LOOP; i++) {
 501                 memset(&loop_dev[i], 0, sizeof(struct loop_device));
 502                 loop_dev[i].lo_number = i;
 503         }
 504         memset(&loop_sizes, 0, sizeof(loop_sizes));
 505         blk_size[MAJOR_NR] = loop_sizes;
 506 
 507         return 0;
 508 }
 509 
 510 #ifdef MODULE
 511 void
 512 cleanup_module( void ) {
     /* [previous][next][first][last][top][bottom][index][help] */
 513   if (unregister_blkdev(MAJOR_NR, "loop") != 0)
 514     printk("loop: cleanup_module failed\n");
 515 }
 516 #endif

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