diff -urN linux-2.4.10/drivers/block/loop.c linux-2.4.10-iv/drivers/block/loop.c --- linux-2.4.10/drivers/block/loop.c Mon Sep 17 22:16:30 2001 +++ linux-2.4.10-iv/drivers/block/loop.c Sat Sep 29 10:50:18 2001 @@ -36,6 +36,9 @@ * Al Viro too. * Jens Axboe , Nov 2000 * + * Fixed and made IV calculation customizable by lo_iv_mode + * Herbert Valerio Riedel , Apr 2001 + * * Still To Fix: * - Advisory locking is ignored here. * - Should use an own CAP_* category instead of CAP_SYS_ADMIN @@ -168,6 +171,43 @@ lo->lo_device); } +static inline int loop_get_bs(struct loop_device *lo) +{ + int bs = 0; + + if (blksize_size[MAJOR(lo->lo_device)]) + bs = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)]; + if (!bs) + bs = BLOCK_SIZE; + + return bs; +} + +static inline unsigned long loop_get_iv(struct loop_device *lo, + unsigned long sector) +{ + unsigned long offset, IV; + int bs; + + switch (lo->lo_iv_mode) { + case LO_IV_MODE_SECTOR: + IV = sector + (lo->lo_offset >> LO_IV_SECTOR_BITS); + break; + + default: + printk (KERN_WARNING "loop: unexpected lo_iv_mode\n"); + case LO_IV_MODE_DEFAULT: + bs = loop_get_bs(lo); + IV = sector / (bs >> 9) + lo->lo_offset / bs; + offset = ((sector % (bs >> 9)) << 9) + lo->lo_offset % bs; + if (offset >= bs) + IV++; + break; + } + + return IV; +} + static int lo_send(struct loop_device *lo, struct buffer_head *bh, int bsize, loff_t pos) { @@ -185,7 +225,8 @@ len = bh->b_size; data = bh->b_data; while (len > 0) { - int IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize; + unsigned long IV = loop_get_iv(lo, (pos - lo->lo_offset) >> LO_IV_SECTOR_BITS); + size = PAGE_CACHE_SIZE - offset; if (size > len) size = len; @@ -236,7 +277,10 @@ unsigned long count = desc->count; struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct loop_device *lo = p->lo; - int IV = page->index * (PAGE_CACHE_SIZE/p->bsize) + offset/p->bsize; + unsigned long IV = loop_get_iv(lo, + ((page->index << (PAGE_CACHE_SHIFT - LO_IV_SECTOR_BITS)) + + (offset >> LO_IV_SECTOR_BITS) + - (lo->lo_offset >> LO_IV_SECTOR_BITS))); if (size > count) size = count; @@ -276,32 +320,6 @@ return desc.error; } -static inline int loop_get_bs(struct loop_device *lo) -{ - int bs = 0; - - if (blksize_size[MAJOR(lo->lo_device)]) - bs = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)]; - if (!bs) - bs = BLOCK_SIZE; - - return bs; -} - -static inline unsigned long loop_get_iv(struct loop_device *lo, - unsigned long sector) -{ - int bs = loop_get_bs(lo); - unsigned long offset, IV; - - IV = sector / (bs >> 9) + lo->lo_offset / bs; - offset = ((sector % (bs >> 9)) << 9) + lo->lo_offset % bs; - if (offset >= bs) - IV++; - - return IV; -} - static int do_bh_filebacked(struct loop_device *lo, struct buffer_head *bh, int rw) { loff_t pos; @@ -663,6 +681,7 @@ lo->lo_backing_file = file; lo->transfer = NULL; lo->ioctl = NULL; + lo->lo_iv_mode = LO_IV_MODE_DEFAULT; figure_loop_size(lo); lo->old_gfp_mask = inode->i_mapping->gfp_mask; inode->i_mapping->gfp_mask = GFP_NOIO; @@ -672,7 +691,7 @@ bs = blksize_size[MAJOR(lo_device)][MINOR(lo_device)]; if (!bs) bs = BLOCK_SIZE; - + set_blocksize(dev, bs); lo->lo_bh = lo->lo_bhtail = NULL; diff -urN linux-2.4.10/include/linux/loop.h linux-2.4.10-iv/include/linux/loop.h --- linux-2.4.10/include/linux/loop.h Mon Sep 17 22:16:30 2001 +++ linux-2.4.10-iv/include/linux/loop.h Sat Sep 29 10:50:18 2001 @@ -24,6 +24,13 @@ Lo_rundown, }; +/* IV calculation related constants */ +#define LO_IV_MODE_DEFAULT 0 /* old logical block size based mode */ +#define LO_IV_MODE_SECTOR 1 /* calculate IV based on relative + 512 byte sectors */ +#define LO_IV_SECTOR_BITS 9 +#define LO_IV_SECTOR_SIZE (1 << LO_IV_SECTOR_BITS) + struct loop_device { int lo_number; int lo_refcnt; @@ -56,6 +63,8 @@ struct semaphore lo_ctl_mutex; struct semaphore lo_bh_mutex; atomic_t lo_pending; + + int lo_iv_mode; }; typedef int (* transfer_proc_t)(struct loop_device *, int cmd, @@ -122,6 +131,7 @@ #define LO_CRYPT_IDEA 6 #define LO_CRYPT_DUMMY 9 #define LO_CRYPT_SKIPJACK 10 +#define LO_CRYPT_CRYPTOAPI 18 /* international crypto patch */ #define MAX_LO_CRYPT 20 #ifdef __KERNEL__