patch-2.1.31 linux/drivers/block/loop.c

Next file: linux/drivers/block/md.c
Previous file: linux/drivers/block/ide.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.30/linux/drivers/block/loop.c linux/drivers/block/loop.c
@@ -12,6 +12,8 @@
  * Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994
  *
  * Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996
+ *
+ * Fixed do_loop_request() re-entrancy - <Vincent.Renardias@waw.com> Mar 20, 1997
  */
 
 #include <linux/module.h>
@@ -181,12 +183,15 @@
 	char	*dest_addr;
 	struct loop_device *lo;
 	struct buffer_head *bh;
+	struct request *current_request;
 
 repeat:
 	INIT_REQUEST;
-	if (MINOR(CURRENT->rq_dev) >= MAX_LOOP)
+	current_request=CURRENT;
+	CURRENT=current_request->next;
+	if (MINOR(current_request->rq_dev) >= MAX_LOOP)
 		goto error_out;
-	lo = &loop_dev[MINOR(CURRENT->rq_dev)];
+	lo = &loop_dev[MINOR(current_request->rq_dev)];
 	if (!lo->lo_inode || !lo->transfer)
 		goto error_out;
 
@@ -197,14 +202,14 @@
 	      blksize = BLOCK_SIZE;
 	}
 
-	dest_addr = CURRENT->buffer;
+	dest_addr = current_request->buffer;
 	
 	if (blksize < 512) {
-		block = CURRENT->sector * (512/blksize);
+		block = current_request->sector * (512/blksize);
 		offset = 0;
 	} else {
-		block = CURRENT->sector / (blksize >> 9);
-		offset = (CURRENT->sector % (blksize >> 9)) << 9;
+		block = current_request->sector / (blksize >> 9);
+		offset = (current_request->sector % (blksize >> 9)) << 9;
 	}
 	block += lo->lo_offset / blksize;
 	offset += lo->lo_offset % blksize;
@@ -212,13 +217,13 @@
 		block++;
 		offset -= blksize;
 	}
-	len = CURRENT->current_nr_sectors << 9;
+	len = current_request->current_nr_sectors << 9;
 
-	if (CURRENT->cmd == WRITE) {
+	if (current_request->cmd == WRITE) {
 		if (lo->lo_flags & LO_FLAGS_READ_ONLY)
 			goto error_out;
-	} else if (CURRENT->cmd != READ) {
-		printk("unknown loop device command (%d)?!?", CURRENT->cmd);
+	} else if (current_request->cmd != READ) {
+		printk("unknown loop device command (%d)?!?", current_request->cmd);
 		goto error_out;
 	}
 	while (len > 0) {
@@ -237,7 +242,7 @@
 			       block, blksize);
 			goto error_out;
 		}
-		if (!buffer_uptodate(bh) && ((CURRENT->cmd == READ) ||
+		if (!buffer_uptodate(bh) && ((current_request->cmd == READ) ||
 					(offset || (len < blksize)))) {
 			ll_rw_block(READ, 1, &bh);
 			wait_on_buffer(bh);
@@ -250,13 +255,13 @@
 		if (size > len)
 			size = len;
 			   
-		if ((lo->transfer)(lo, CURRENT->cmd, bh->b_data + offset,
+		if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
 				   dest_addr, size)) {
 			printk("loop: transfer error block %d\n", block);
 			brelse(bh);
 			goto error_out;
 		}
-		if (CURRENT->cmd == WRITE) {
+		if (current_request->cmd == WRITE) {
 			mark_buffer_uptodate(bh, 1);
 			mark_buffer_dirty(bh, 1);
 		}
@@ -266,9 +271,13 @@
 		offset = 0;
 		block++;
 	}
+	current_request->next=CURRENT;
+	CURRENT=current_request;
 	end_request(1);
 	goto repeat;
 error_out:
+    current_request->next=CURRENT;
+	CURRENT=current_request;
 	end_request(0);
 	goto repeat;
 }
@@ -484,20 +493,20 @@
 	return 0;
 }
 
-static void lo_release(struct inode *inode, struct file *file)
+static int lo_release(struct inode *inode, struct file *file)
 {
 	struct loop_device *lo;
 	int	dev;
 
 	if (!inode)
-		return;
+		return 0;
 	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
 		printk("lo_release: pseudo-major != %d\n", MAJOR_NR);
-		return;
+		return 0;
 	}
 	dev = MINOR(inode->i_rdev);
 	if (dev >= MAX_LOOP)
-		return;
+		return 0;
 	fsync_dev(inode->i_rdev);
 	lo = &loop_dev[dev];
 	if (lo->lo_refcnt <= 0)
@@ -506,6 +515,7 @@
 		lo->lo_refcnt--;
 		MOD_DEC_USE_COUNT;
 	}
+	return 0;
 }
 
 static struct file_operations lo_fops = {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov