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;