patch-2.1.88 linux/drivers/block/ll_rw_blk.c

Next file: linux/drivers/block/rz1000.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.87/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
@@ -22,6 +22,9 @@
 #include <asm/io.h>
 #include <linux/blk.h>
 
+#define ATOMIC_ON()	do { } while (0)
+#define ATOMIC_OFF()	do { } while (0)
+
 /*
  * The request-struct contains all necessary data
  * to load a nr of sectors into memory
@@ -37,7 +40,7 @@
 /*
  * Protect the request list against multiple users..
  */
-spinlock_t current_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * used to wait on when there are no free requests
@@ -340,6 +343,7 @@
 	unsigned int sector, count;
 	struct request * req;
 	int rw_ahead, max_req, max_sectors;
+	unsigned long flags;
 
 	count = bh->b_size >> 9;
 	sector = bh->b_rsector;
@@ -407,13 +411,20 @@
 	 * Try to coalesce the new request with old requests
 	 */
 	max_sectors = get_max_sectors(bh->b_rdev);
-	cli();
+
+	/*
+	 * Now we acquire the request spinlock, we have to be mega careful
+	 * not to schedule or do something nonatomic
+	 */
+	spin_lock_irqsave(&io_request_lock,flags);
+	ATOMIC_ON();
+
 	req = *get_queue(bh->b_rdev);
 	if (!req) {
 		/* MD and loop can't handle plugging without deadlocking */
 		if (major != MD_MAJOR && major != LOOP_MAJOR && 
 		    major != DDV_MAJOR)
-			plug_device(blk_dev + major);
+			plug_device(blk_dev + major); /* is atomic */
 	} else switch (major) {
 	     case IDE0_MAJOR:	/* same as HD_MAJOR */
 	     case IDE1_MAJOR:
@@ -467,14 +478,18 @@
 				continue;
 
 			mark_buffer_clean(bh);
-		    	sti();
+			ATOMIC_OFF();
+			spin_unlock_irqrestore(&io_request_lock,flags);
 		    	return;
+
 		} while ((req = req->next) != NULL);
 	}
 
 /* find an unused request. */
 	req = get_request(max_req, bh->b_rdev);
-	sti();
+
+	ATOMIC_OFF();
+	spin_unlock_irqrestore(&io_request_lock,flags);
 
 /* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
 	if (!req) {
@@ -646,9 +661,12 @@
 			if (j == 0) {
 				req[j] = get_request_wait(max_req, rdev);
 			} else {
-				cli();
+				unsigned long flags;
+				spin_lock_irqsave(&io_request_lock,flags);
+				ATOMIC_ON();
 				req[j] = get_request(max_req, rdev);
-				sti();
+				ATOMIC_OFF();
+				spin_unlock_irqrestore(&io_request_lock,flags);
 				if (req[j] == NULL)
 					break;
 			}

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