Re: new version of loop.c patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> Later I will try compiling it to see if it works, but that will take
> awhile -- all I have is a P166. I will probably get a reply from the
> list before this thing can finish the job. :)

I made a patch which *seems* to work. But I'm absolutely clueless if I did the Right Thing (tm)...
So use it on your own risk. Please don't blame me if it eats your disk.

Flo
--- loop.c	Thu Sep 27 16:39:10 2001
+++ loop.c	Fri Sep 28 11:37:11 2001
@@ -36,6 +36,9 @@
  * Al Viro too.
  * Jens Axboe <axboe@xxxxxxx>, Nov 2000
  *
+ * Fixed and made IV calculation customizable by lo_iv_mode
+ * Herbert Valerio Riedel <hvr@xxxxxxx>, 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;
@@ -493,8 +511,11 @@
 	/*
 	 * piggy old buffer on original, and submit for I/O
 	 */
-	bh = loop_get_buffer(lo, rbh);
 	IV = loop_get_iv(lo, rbh->b_rsector);
+	
+	bh = loop_get_buffer(lo, rbh);
+        bh->b_private = rbh;	
+        
 	if (rw == WRITE) {
 		set_bit(BH_Dirty, &bh->b_state);
 		if (lo_do_transfer(lo, WRITE, bh->b_data, rbh->b_data,
@@ -663,6 +684,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 +694,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;

[Index of Archives]     [Kernel]     [Linux Crypto]     [Gnu Crypto]     [Gnu Classpath]     [Netfilter]     [Bugtraq]
  Powered by Linux