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;