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

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