[fixes] Re: Locking bugs in 2.4 md.c

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

 



On 2003-09-19T12:08:29,
   Neil Brown <neilb@cse.unsw.edu.au> said:

Hi Neil,

your patch needs the following two addendums.

Andi Kleen: Locking in md_seq_next is wrong, should happen in
md_seq_start

Andrea & I: Refcounting for the raidautostart feature is wrong.
This is actually a long-standing bug which is catched by your diffs,
which notice the wrong counter and BUG().

What would happen: user-space open()s /dev/md0, issues
ioctl(RAID_AUTOSTART) - which creates all md devices and sets active ==
0 ultimately -, and then close()s /dev/md0, which decrements active to
-1. Oops next time md_make_request gets called.

Patch fixes this and adds safeguard to md_release() already.


Sincerely,
    Lars Marowsky-Brée <lmb@suse.de>

-- 
High Availability & Clustering		ever tried. ever failed. no matter.
SuSE Labs				try again. fail again. fail better.
Research & Development, SUSE LINUX AG		-- Samuel Beckett

--- linux/drivers/md/md.c-o	2003-09-24 09:45:39.000000000 +0000
+++ linux/drivers/md/md.c	2003-09-24 09:47:23.000000000 +0000
@@ -3287,6 +3287,7 @@
 
 	if (l > 0x10000)
 		return NULL;
+	down_read(&all_mddevs_sem);
 	if (!l--)
 		/* header */
 		return (void*)1;
@@ -3304,7 +3305,6 @@
 	struct list_head *tmp;
 	mddev_t *next_mddev, *mddev = v;
 
-	down_read(&all_mddevs_sem);
 	++*pos;
 	if (v == (void*)2)
 		return NULL;
--- linux-2.4.21/drivers/md/md.c	2003-09-24 10:54:35.000000000 +0200
+++ linux-2.4.21.new/drivers/md/md.c	2003-09-24 10:53:34.000000000 +0200
@@ -60,7 +60,7 @@
 #endif
 
 #ifndef MODULE
-static void autostart_arrays (void);
+static void autostart_arrays (kdev_t);
 #endif
 
 static mdk_personality_t *pers[MAX_PERSONALITY];
@@ -2753,7 +2753,7 @@
 #ifndef MODULE
 		case RAID_AUTORUN:
 			err = 0;
-			autostart_arrays();
+			autostart_arrays(dev);
 			goto done;
 #endif
 
@@ -3017,8 +3017,11 @@
 {
 	mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
 	if (mddev) {
-		atomic_dec(&mddev->active);
-		atomic_dec(&mddev->active);
+		if (atomic_dec_and_test(&mddev->active))
+			/* Refcount should _never_ drop to zero here! */
+			BUG();
+		else
+			atomic_dec(&mddev->active);
 	}
 	return 0;
 }
@@ -3923,7 +3926,7 @@
 }
 
 
-static void autostart_arrays(void)
+static void autostart_arrays(kdev_t countdev)
 {
 	mdk_rdev_t *rdev;
 	int i;
@@ -3954,7 +3957,7 @@
 	}
 	dev_cnt = 0;
 
-	autorun_devices(-1);
+	autorun_devices(countdev);
 }
 
 static struct {
@@ -4183,7 +4186,7 @@
 	if (raid_setup_args.noautodetect)
 		printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n");
 	else
-		autostart_arrays();
+		autostart_arrays(-1);
 	md_setup_drive();
 	return 0;
 }

Attachment: pgp00054.pgp
Description: PGP signature


[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux