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

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