Hi,

I made a small kernel and raidtools patch to mark a specific device as dirty
(failure).

Suppose you have as a /etc/raidtab
    raiddev /dev/md4
    chunk-size                128
    raid-level                1
    nr-raid-disks             2
    nr-spare-disks            1
    device                    /dev/loop1
    raid-disk                 0
    device                    /dev/loop2
    raid-disk                 1
    device                    /dev/loop3
    spare-disk                0

So you have a mirror with 2 devices and one spare disk. Now you create the raid
device. Set up a file system, etc. 

Suddenly you want to backup the mirror with no downtime, so you do a 

raidmarkdirty /dev/md4 /dev/loop2
raidhotremove /dev/md4 /dev/loop2

Now you can mount /dev/loop2 and backup it, while /dev/loop3 is updated.

After /dev/loop3 is in sync, we can play the same game:

raidhotadd    /dev/md4 /dev/loop2
raidmarkdirty /dev/md4 /dev/loop3
raidhotremove /dev/md4 /dev/loop3

Now you can mount /dev/loop3 and backup it, while /dev/loop2 is updated.

Got the thing ??

OK ..... if you like it, test and improve it :) Please answer me directly, as
I am not on the raid mailing list.

So long,
        Harald

 --
» Harald Hoyer ««»» mailto:[EMAIL PROTECTED] ««»» http://hot.spotline.de ««
···············································································
COMPASS [for the CDC-6000 series] is the sort of assembler one expects from
a corporation whose president codes in octal.
                -- J.N. Gray
diff -u -r raidtools-0.90/Makefile.in raidtools-0.90.dirty/Makefile.in
--- raidtools-0.90/Makefile.in	Thu Jan 28 12:28:08 1999
+++ raidtools-0.90.dirty/Makefile.in	Mon Mar 29 10:11:07 1999
@@ -40,7 +40,7 @@
 CC = @CC@
 CFLAGS = @CFLAGS@ -O2 -Wall -DMD_VERSION=\""raidtools-@VERS@"\" -g
 LDFLAGS = @LDFLAGS@
-RAIDLINKS = raidstop raidhotadd raidhotremove
+RAIDLINKS = raidstop raidhotadd raidhotremove raidmarkdirty
 
 all: $(BINARIES)
 
diff -u -r raidtools-0.90/md-int.h raidtools-0.90.dirty/md-int.h
--- raidtools-0.90/md-int.h	Thu Jan 28 12:28:08 1999
+++ raidtools-0.90.dirty/md-int.h	Mon Mar 29 10:11:59 1999
@@ -65,6 +65,7 @@
 #define UNPROTECT_ARRAY         _IO (MD_MAJOR, 0x26)
 #define PROTECT_ARRAY           _IO (MD_MAJOR, 0x27)
 #define HOT_ADD_DISK            _IO (MD_MAJOR, 0x28)
+#define MARK_DISK_DIRTY         _IO (MD_MAJOR, 0x29)
 
 /* usage */
 #define RUN_ARRAY               _IOW (MD_MAJOR, 0x30, struct md_param)
diff -u -r raidtools-0.90/raidlib.c raidtools-0.90.dirty/raidlib.c
--- raidtools-0.90/raidlib.c	Thu Jan 28 12:28:08 1999
+++ raidtools-0.90.dirty/raidlib.c	Mon Mar 29 10:10:00 1999
@@ -31,7 +31,7 @@
 
 #define OLD_MDTOOLS ((md_ver.major == 0) && (md_ver.minor < 0.50))
 
-static save_errno = 0;
+static int save_errno = 0;
 
 md_cfg_entry_t *cfg_head = NULL, *cfg = NULL;
 int do_quiet_flag = 0;
@@ -309,6 +309,53 @@
     return 0;
 }
 
+int do_raidmarkdirty (int md_fd, char * disk_name, char * md_name)
+{
+    int rc;
+    struct stat s;
+
+    if (OLD_MDTOOLS) {
+	fprintf(stderr,"kernel does not support hot-add!\n");
+        exit(EXIT_FAILURE);
+    }
+	
+    fstat (md_fd, &s);
+    if (major (s.st_rdev) != MD_MAJOR) {
+	fprintf(stderr,"%s: not an MD device!\n",md_name);
+        exit(EXIT_FAILURE);
+    }
+
+    stat (disk_name, &s);
+
+    rc = ioctl (md_fd, MARK_DISK_DIRTY, (unsigned long)s.st_rdev);
+    if (rc) {
+	    save_errno = errno;
+  	    fprintf(stderr,"%s: can not mark disk dirty: ", md_name);
+	    switch (save_errno) {
+	      case ENXIO:
+		fprintf(stderr,"disk does not exist!\n");
+		break;
+	      case EBUSY:
+		fprintf(stderr,"disk busy!\n");
+		break;
+	      case ENOSPC:
+		fprintf(stderr,"too small disk!\n");
+		break;
+	      case ENODEV:
+		fprintf(stderr,"array not running!\n");
+		break;
+	      case EINVAL:
+		fprintf(stderr,"invalid argument.\n");
+		break;
+	      default:
+		perror (md_name);
+	    }
+	    errno = save_errno;
+	    return 1;
+    }
+    return 0;
+}
+
 int do_raidhotremove (int md_fd, char * disk_name, char * md_name)
 {
     int rc;
@@ -413,6 +460,9 @@
 	return 1;
 
       case raidhotadd:
+	return 1;
+
+      case raidmarkdirty:
 	return 1;
     }
     close (fd);
diff -u -r raidtools-0.90/raidlib.h raidtools-0.90.dirty/raidlib.h
--- raidtools-0.90/raidlib.h	Thu Jan 28 12:28:08 1999
+++ raidtools-0.90.dirty/raidlib.h	Mon Mar 29 10:08:42 1999
@@ -19,7 +19,9 @@
 
 extern struct md_version md_ver;
 enum raidaddFunc {raidadd, raidstart, raidrun, raidstop,
-			raidstop_ro, raidhotremove, raidhotadd };
+		  raidstop_ro, raidhotremove, raidhotadd, 
+		  raidmarkdirty };
+
 extern md_cfg_entry_t *cfg_head, *cfg;
 extern int do_quiet_flag;
 
@@ -31,6 +33,6 @@
 int do_raidstart_rw (int fd, char *dev);
 int do_raidhotremove (int md_fd, char * disk_name, char *md_name);
 int do_raidhotadd (int md_fd, char * disk_name, char *md_name);
-
+int do_raidmarkdirty (int md_fd, char * disk_name, char *md_name);
 
 #endif
diff -u -r raidtools-0.90/raidstart.c raidtools-0.90.dirty/raidstart.c
--- raidtools-0.90/raidstart.c	Thu Jan 28 12:28:08 1999
+++ raidtools-0.90.dirty/raidstart.c	Mon Mar 29 10:27:44 1999
@@ -69,6 +69,8 @@
 	func = raidstop;
     else if (!strcmp (namestart, "raidhotadd"))
 	func = raidhotadd;
+    else if (!strcmp (namestart, "raidmarkdirty"))
+	func = raidmarkdirty;
     else if (!strcmp (namestart, "raidhotremove"))
 	func = raidhotremove;
     else {
@@ -156,7 +158,8 @@
     /*
      * we want to fast-handle hot-remove and hot-add too.
      */
-    if ((func == raidhotremove) || (func == raidhotadd)) {
+    if ((func == raidhotremove) || (func == raidhotadd) 
+	|| (func == raidmarkdirty)) {
         int md_fd;
 	char * md_name;
 
@@ -180,8 +183,11 @@
 	if (func == raidhotremove) {
 	        if (do_raidhotremove (md_fd, *args, md_name))
 		    exit(EXIT_FAILURE);
-	} else {
+	} else if (func == raidhotadd) {
 	        if (do_raidhotadd (md_fd, *args, md_name))
+		    exit(EXIT_FAILURE);
+	} else if (func == raidmarkdirty) {
+	        if (do_raidmarkdirty (md_fd, *args, md_name))
 		    exit(EXIT_FAILURE);
 	}
         exit(0);
Index: 2.2.3.2/drivers/block/raid5.c
--- 2.2.3.2/drivers/block/raid5.c Tue, 09 Mar 1999 11:46:33 +0100 root (linux/P/38_raid5.c 1.2 644)
+++ 2.2.4.1(w)/drivers/block/raid5.c Mon, 29 Mar 1999 11:38:14 +0200 root (linux/P/38_raid5.c 1.1 644)
@@ -1983,6 +1983,10 @@
 		 * non-operational disk slot in the 'low' area of
 		 * the disk array.
 		 */
+		mark_disk_sync(sb->disks+fdisk->number);
+		mark_disk_active(sb->disks+fdisk->number);
+		sb->active_disks++;
+		sb->spare_disks--;
 		conf->failed_disks--;
 		conf->working_disks++;
 		conf->spare = NULL;
Index: 2.2.3.2/drivers/block/raid1.c
--- 2.2.3.2/drivers/block/raid1.c Tue, 09 Mar 1999 11:46:33 +0100 root (linux/P/39_raid1.c 1.2 644)
+++ 2.2.4.1(w)/drivers/block/raid1.c Mon, 29 Mar 1999 13:31:14 +0200 root (linux/P/39_raid1.c 1.1 644)
@@ -580,6 +580,7 @@
 	unsigned long flags;
 	mdp_super_t *sb = mddev->sb;
 	mdp_disk_t *failed_desc, *spare_desc, *added_desc;
+	mdk_rdev_t * rdev;
 
 	save_flags(flags);
 	cli();
@@ -770,6 +772,19 @@
 		 * non-operational disk slot in the 'low' area of
 		 * the disk array.
 		 */
+
+		mark_disk_sync(sb->disks+fdisk->number);
+		mark_disk_active(sb->disks+fdisk->number);
+		rdev = find_rdev(mddev, sdisk->dev);
+
+		if (rdev) {
+		   rdev->desc_nr = sdisk->number;
+		   mddev->sb_dirty = 1;
+		   md_update_sb(mddev);
+		}
+
+		sb->active_disks++;
+		sb->spare_disks--;
 
 		conf->working_disks++;
 
Index: 2.2.3.2/drivers/block/md.c
--- 2.2.3.2/drivers/block/md.c Tue, 09 Mar 1999 11:46:33 +0100 root (linux/Q/17_md.c 1.2 644)
+++ 2.2.4.1(w)/drivers/block/md.c Mon, 29 Mar 1999 13:29:09 +0200 root (linux/Q/17_md.c 1.1 644)
@@ -2430,6 +2436,8 @@
 	return -EINVAL;
 }
 
+static int md_remove_disk(mddev_t *mddev, kdev_t rdev);
+
 static int md_ioctl (struct inode *inode, struct file *file,
                      unsigned int cmd, unsigned long arg)
 {
@@ -2632,6 +2640,10 @@
 			err = add_new_disk(mddev, (void *)arg);
 			goto done_unlock;
       
+		case MARK_DISK_DIRTY:
+			err = md_remove_disk(mddev, (kdev_t)arg);
+			goto done_unlock;
+
 		case HOT_REMOVE_DISK:
 			err = hot_remove_disk(mddev, (kdev_t)arg);
 			goto done_unlock;
@@ -2995,6 +3007,14 @@
 }
 
 
+int md_remove_disk(mddev_t *mddev, kdev_t dev)
+{
+   int ret;
+   fsync_dev (mddev_to_kdev(mddev));
+   ret = md_error (mddev_to_kdev(mddev), dev);
+   return ret;
+}
+
 int md_error (kdev_t dev, kdev_t rdev)
 {
 	mddev_t *mddev = kdev_to_mddev(dev);
@@ -3672,10 +3692,12 @@
 			 * pointer too
 			 */
 			mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_ACTIVE);
+/* BETTER DO THIS IN THE CORRESPONDING MODULES
 			mark_disk_sync(spare);
 			mark_disk_active(spare);
 			sb->active_disks++;
-			sb->spare_disks--;
+			sb->spare_disks--
+*/
 		}
 		restore_flags(flags);
 		mddev->sb_dirty = 1;

Reply via email to