raidstart fails if the first disk of an array is unusable

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

 



  Hi. I couldn't find out who currently maintains raidtools, hopefully
this patch will find it's way to him/her via this list.

  Following a Debian bug report about raidtools' strange behaviour,
Pontus Fuchs found and fixed the cause for a problem that you possibly
have experienced: raidstart won't start an array if it can't read the
superblock from the disk that is marked first in raidtab. As you know,
starting (for example) a two disk RAID-1 array shouldn't fail if the
first disk is can't be used but the second can.

  The fix is to simply try out all the devices mentioned in raidtab when
starting an array. A patch (mostly by Fuchs) against raidtools-20010914
is attached.

  (Please CC me, I'm not on the list)
--- raidlib.c.old	Wed Aug 21 18:56:54 2002
+++ raidlib.c	Wed Aug 21 18:56:58 2002
@@ -149,21 +149,10 @@
     return 0;
 }
 static int do_mdstart (int fd, char *dev, dev_t rdev) {
-    int rc;
 
-    if ((rc = ioctl (fd, START_ARRAY, (unsigned long)rdev))) {
-	    save_errno=errno;
-	    switch (save_errno) {
-	      case EBUSY:
-		fprintf(stderr,"%s: already running\n",dev);
-		break;
-		/* fall through */
-	      default:
-		perror (dev);
-	    }
-	    errno=save_errno;
+    if (ioctl (fd, START_ARRAY, (unsigned long)rdev))
 	    return 1;
-    }
+
     return 0;
 }
 
@@ -396,10 +385,47 @@
       {
 	struct stat s;
 
-	stat (cfg->device_name[0], &s);
+	int level = cfg->array.param.level;
+	int i, lasterr = 0;
 
 	fd = open_or_die(cfg->md_name);
-	if (do_mdstart (fd, cfg->md_name, s.st_rdev)) rc++;
+
+	/* If the array is level 1,4 or 5 and the first disk
+	* is disconnected we should try the next possible disk
+	* in the array until we find one which the kernel-code
+	* can read the superblock from.
+	*/
+
+	rc = 1;
+	if(level == 1 || level == 4 || level == 5) {
+		for(i = 0; rc && i < MD_SB_DISKS; i++) {
+			if(!cfg->device_name[i])
+				continue;
+	
+			stat (cfg->device_name[i], &s);
+			if (do_mdstart (fd, cfg->md_name, s.st_rdev))
+				lasterr = errno;
+			else
+				rc = 0;
+		}
+	} else {
+			stat (cfg->device_name[0], &s);
+			if (do_mdstart (fd, cfg->md_name, s.st_rdev))
+				lasterr = errno;
+			else
+				rc = 0;
+	}
+
+	if(rc) {
+		switch (lasterr) {
+		case EBUSY:
+			fprintf(stderr,"%s: already running\n",cfg->md_name);
+			break;
+		default:
+			perror (cfg->md_name);
+		}
+	}
+
 	break;
       }
 

[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