From efe92bcae0067b85ba380a1d63a488f0328d16e0 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Tue, 6 Apr 2010 16:45:46 +0000 Subject: [PATCH] - Clean up directory mess once and for all - Add incremental remove support --- .cvsignore | 1 + mdadm-2.5.2-static.patch | 26 +- mdadm-3.1.1-endian.patch | 20 +- mdadm-3.1.1-imsm.patch | 13 - mdadm-3.1.1-warn.patch | 152 -------- mdadm-3.1.2-decremental-2.patch | 36 ++ mdadm-3.1.2-decremental.patch | 633 ++++++++++++++++++++++++++++++++ mdadm-3.1.2-directory.patch | 265 +++++++++++++ mdadm-3.1.2-mapfile.patch | 80 ++++ mdadm-3.1.2-mapname.patch | 58 +++ mdadm-3.1.2-rebuild.patch | 38 ++ mdadm.rules | 5 +- mdadm.spec | 44 ++- sources | 2 +- 14 files changed, 1180 insertions(+), 193 deletions(-) delete mode 100644 mdadm-3.1.1-imsm.patch delete mode 100644 mdadm-3.1.1-warn.patch create mode 100644 mdadm-3.1.2-decremental-2.patch create mode 100644 mdadm-3.1.2-decremental.patch create mode 100644 mdadm-3.1.2-directory.patch create mode 100644 mdadm-3.1.2-mapfile.patch create mode 100644 mdadm-3.1.2-mapname.patch create mode 100644 mdadm-3.1.2-rebuild.patch diff --git a/.cvsignore b/.cvsignore index 439a87b..1b8b081 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,2 +1,3 @@ mdadm-3.0.3.tar.bz2 mdadm-3.1.1-gcd9a8b5.tar.bz2 +mdadm-3.1.2.tar.bz2 diff --git a/mdadm-2.5.2-static.patch b/mdadm-2.5.2-static.patch index 62fcf4d..a0cd1c3 100644 --- a/mdadm-2.5.2-static.patch +++ b/mdadm-2.5.2-static.patch @@ -1,15 +1,19 @@ ---- mdadm-3.1.1/Makefile.static 2010-02-08 01:26:18.000000000 -0500 -+++ mdadm-3.1.1/Makefile 2010-02-17 13:52:42.928428188 -0500 -@@ -62,7 +62,7 @@ CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE) - # from early boot to late boot. +--- mdadm-3.1.2/Makefile.static 2010-04-06 11:55:03.098505021 -0400 ++++ mdadm-3.1.2/Makefile 2010-04-06 11:55:44.120254408 -0400 +@@ -62,9 +62,9 @@ CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE) + # pivotroot from early boot to late boot. # If you don't have /lib/init/rw you might want to use /dev/.something - # e.g. make ALT_RUN=/dev/.mdadm --ALT_RUN = /lib/init/rw -+ALT_RUN = /dev/md - ALTFLAGS = -DALT_RUN=\"$(ALT_RUN)\" - CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(ALTFLAGS) - -@@ -196,16 +196,16 @@ install : mdadm mdmon install-man instal + # e.g. make MAP_DIR=/dev/.mdadm +-MAP_DIR = /lib/init/rw/mdadm +-MAP_FILE = map +-MDMON_DIR = /lib/init/rw/mdmon ++MAP_DIR = /dev/md ++MAP_FILE = md-device-map ++MDMON_DIR = /dev/md + DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\" + DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\" + CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) +@@ -206,16 +206,16 @@ install : mdadm mdmon install-man instal $(INSTALL) -D $(STRIP) -m 755 mdmon $(DESTDIR)$(BINDIR)/mdmon install-static : mdadm.static install-man diff --git a/mdadm-3.1.1-endian.patch b/mdadm-3.1.1-endian.patch index 7342019..c45f175 100644 --- a/mdadm-3.1.1-endian.patch +++ b/mdadm-3.1.1-endian.patch @@ -1,6 +1,17 @@ ---- mdadm-3.1.1/util.c.endian 2010-02-21 19:13:56.253610477 -0500 -+++ mdadm-3.1.1/util.c 2010-02-21 19:16:26.338375501 -0500 -@@ -395,7 +395,12 @@ char *__fname_from_uuid(int id[4], int s +From 86983cce34645efb2b270a737d573e01eeee96e5 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 24 Mar 2010 09:07:02 +1100 +Subject: [PATCH 1/6] + +--- + util.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/util.c b/util.c +index d292a66..79d2b0f 100644 +--- a/util.c ++++ b/util.c +@@ -425,7 +425,12 @@ char *__fname_from_uuid(int id[4], int swap, char *buf, char sep) char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep) { @@ -14,3 +25,6 @@ } #ifndef MDASSEMBLE +-- +1.6.6.1 + diff --git a/mdadm-3.1.1-imsm.patch b/mdadm-3.1.1-imsm.patch deleted file mode 100644 index a5d74ed..0000000 --- a/mdadm-3.1.1-imsm.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Assemble.c b/Assemble.c -index e4d6181..23cc438 100644 ---- a/Assemble.c -+++ b/Assemble.c -@@ -434,7 +434,7 @@ int Assemble(struct supertype *st, char *mddev, - } - } - st = tst; tst = NULL; -- if (!auto_assem && tmpdev->next != NULL) { -+ if (!auto_assem && inargv && tmpdev->next != NULL) { - fprintf(stderr, Name ": %s is a container, but is not " - "only device given: confused and aborting\n", - devname); diff --git a/mdadm-3.1.1-warn.patch b/mdadm-3.1.1-warn.patch deleted file mode 100644 index 9f07bb9..0000000 --- a/mdadm-3.1.1-warn.patch +++ /dev/null @@ -1,152 +0,0 @@ ---- mdadm-3.1.1/Grow.c.warn 2010-02-08 01:26:18.000000000 -0500 -+++ mdadm-3.1.1/Grow.c 2010-02-17 14:58:43.615427833 -0500 -@@ -1096,7 +1096,7 @@ int Grow_reshape(char *devname, int fd, - /* set them all just in case some old 'new_*' value - * persists from some earlier problem - */ -- int err; -+ int err = 0; - if (sysfs_set_num(sra, NULL, "chunk_size", nchunk) < 0) - rv = 1, err = errno; - if (!rv && sysfs_set_num(sra, NULL, "layout", nlayout) < 0) -@@ -1269,6 +1269,7 @@ int grow_backup(struct mdinfo *sra, - int odata = disks; - int rv = 0; - int i; -+ int ret; - unsigned long long new_degraded; - //printf("offset %llu\n", offset); - if (level >= 4) -@@ -1334,10 +1335,10 @@ int grow_backup(struct mdinfo *sra, - ((char*)&bsb.sb_csum2)-((char*)&bsb)); - - lseek64(destfd[i], destoffsets[i] - 4096, 0); -- write(destfd[i], &bsb, 512); -+ ret = write(destfd[i], &bsb, 512); - if (destoffsets[i] > 4096) { - lseek64(destfd[i], destoffsets[i]+stripes*chunk*odata, 0); -- write(destfd[i], &bsb, 512); -+ ret = write(destfd[i], &bsb, 512); - } - fsync(destfd[i]); - } -@@ -1368,6 +1369,7 @@ int wait_backup(struct mdinfo *sra, - int fd = sysfs_get_fd(sra, NULL, "sync_completed"); - unsigned long long completed; - int i; -+ int ret; - - if (fd < 0) - return -1; -@@ -1406,7 +1408,7 @@ int wait_backup(struct mdinfo *sra, - bsb.sb_csum2 = bsb_csum((char*)&bsb, - ((char*)&bsb.sb_csum2)-((char*)&bsb)); - lseek64(destfd[i], destoffsets[i]-4096, 0); -- write(destfd[i], &bsb, 512); -+ ret = write(destfd[i], &bsb, 512); - fsync(destfd[i]); - } - return 0; -@@ -1414,8 +1416,9 @@ int wait_backup(struct mdinfo *sra, - - static void fail(char *msg) - { -- write(2, msg, strlen(msg)); -- write(2, "\n", 1); -+ int ret; -+ ret = write(2, msg, strlen(msg)); -+ ret = write(2, "\n", 1); - exit(1); - } - -@@ -1452,8 +1455,10 @@ static void validate(int afd, int bfd, u - free(abuf); - free(bbuf); - abuflen = len; -- posix_memalign((void**)&abuf, 4096, abuflen); -- posix_memalign((void**)&bbuf, 4096, abuflen); -+ if (posix_memalign((void**)&abuf, 4096, abuflen) != 0) -+ fail("unable to allocate aligned memory"); -+ if (posix_memalign((void**)&bbuf, 4096, abuflen) != 0) -+ fail("unable to allocate aligned memory"); - } - - lseek64(bfd, offset, 0); -@@ -1486,7 +1491,11 @@ static void validate(int afd, int bfd, u - free(bbuf); - abuflen = len; - abuf = malloc(abuflen); -+ if (abuf == NULL) -+ fail("unable to allocate memory"); - bbuf = malloc(abuflen); -+ if (bbuf == NULL) -+ fail("unable to allocate memory"); - } - - lseek64(bfd, offset+__le64_to_cpu(bsb2.devstart2)*512, 0); -@@ -1508,7 +1517,8 @@ static int child_grow(int afd, struct md - char *buf; - int degraded = 0; - -- posix_memalign((void**)&buf, 4096, disks * chunk); -+ if (posix_memalign((void**)&buf, 4096, disks * chunk) != 0) -+ fail("unable to allocate aligned memory"); - sysfs_set_num(sra, NULL, "suspend_hi", 0); - sysfs_set_num(sra, NULL, "suspend_lo", 0); - grow_backup(sra, 0, stripes, -@@ -1536,7 +1546,8 @@ static int child_shrink(int afd, struct - int rv; - int degraded = 0; - -- posix_memalign((void**)&buf, 4096, disks * chunk); -+ if (posix_memalign((void**)&buf, 4096, disks * chunk) != 0) -+ fail("unable to allocate alinged memory"); - start = sra->component_size - stripes * chunk/512; - sysfs_set_num(sra, NULL, "sync_max", start); - sysfs_set_str(sra, NULL, "sync_action", "reshape"); -@@ -1575,7 +1586,8 @@ static int child_same_size(int afd, stru - int degraded = 0; - - -- posix_memalign((void**)&buf, 4096, disks * chunk); -+ if (posix_memalign((void**)&buf, 4096, disks * chunk) != 0) -+ fail("unable to allocate alinged memory"); - - sysfs_set_num(sra, NULL, "suspend_lo", 0); - sysfs_set_num(sra, NULL, "suspend_hi", 0); ---- mdadm-3.1.1/restripe.c.warn 2010-02-08 01:26:18.000000000 -0500 -+++ mdadm-3.1.1/restripe.c 2010-02-17 14:58:43.615427833 -0500 -@@ -565,7 +565,10 @@ int restore_stripes(int *dest, unsigned - - int data_disks = raid_disks - (level == 0 ? 0 : level <= 5 ? 1 : 2); - -- posix_memalign((void**)&stripe_buf, 4096, raid_disks * chunk_size); -+ if (posix_memalign((void**)&stripe_buf, 4096, raid_disks * chunk_size) != 0) { -+ fprintf(stderr, "unable to allocate aligned memory\n"); -+ exit(1); -+ } - if (zero == NULL) { - zero = malloc(chunk_size); - if (zero) ---- mdadm-3.1.1/mdmon.c.warn 2010-02-08 01:26:18.000000000 -0500 -+++ mdadm-3.1.1/mdmon.c 2010-02-17 14:58:43.616427642 -0500 -@@ -176,7 +176,7 @@ static void try_kill_monitor(pid_t pid, - fl = fcntl(sock, F_GETFL, 0); - fl &= ~O_NONBLOCK; - fcntl(sock, F_SETFL, fl); -- read(sock, buf, 100); -+ n = read(sock, buf, 100); - } - - void remove_pidfile(char *devname) ---- mdadm-3.1.1/super-intel.c.warn 2010-02-17 14:59:16.757425375 -0500 -+++ mdadm-3.1.1/super-intel.c 2010-02-17 15:00:15.309803578 -0500 -@@ -698,7 +698,7 @@ static void print_imsm_dev(struct imsm_d - printf(" <-- %s", map_state_str[map->map_state]); - printf("\n Checkpoint : %u (%llu)", - __le32_to_cpu(dev->vol.curr_migr_unit), -- blocks_per_migr_unit(dev)); -+ (unsigned long long)blocks_per_migr_unit(dev)); - } - printf("\n"); - printf(" Dirty State : %s\n", dev->vol.dirty ? "dirty" : "clean"); diff --git a/mdadm-3.1.2-decremental-2.patch b/mdadm-3.1.2-decremental-2.patch new file mode 100644 index 0000000..2ab9f6b --- /dev/null +++ b/mdadm-3.1.2-decremental-2.patch @@ -0,0 +1,36 @@ +commit ddda49f6daf481471334f5675fbc1fa149d83ad6 +Author: Doug Ledford +Date: Tue Apr 6 12:17:25 2010 -0400 + + Minor bug fix to incremental remove support + + Signed-off-by: Doug Ledford + +diff --git a/Manage.c b/Manage.c +index 6539eda..b15586b 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -386,6 +386,7 @@ int Manage_subdevs(char *devname, int fd, + + next = dv->next; + jnext = 0; ++ tfd = -1; + + if (strcmp(dv->devname, "failed")==0 || + strcmp(dv->devname, "faulty")==0) { +@@ -406,6 +407,7 @@ int Manage_subdevs(char *devname, int fd, + stb.st_rdev = makedev(disc.major, disc.minor); + next = dv; + jnext = j+1; ++ tfd = 0; + sprintf(dvname,"%d:%d", disc.major, disc.minor); + dnprintable = dvname; + break; +@@ -440,6 +442,7 @@ int Manage_subdevs(char *devname, int fd, + stb.st_rdev = makedev(disc.major, disc.minor); + next = dv; + jnext = j+1; ++ tfd = 0; + dnprintable = dvname; + break; + } diff --git a/mdadm-3.1.2-decremental.patch b/mdadm-3.1.2-decremental.patch new file mode 100644 index 0000000..5e2515f --- /dev/null +++ b/mdadm-3.1.2-decremental.patch @@ -0,0 +1,633 @@ +From 8c43c776715301ff020639801a8b1b4716fdf745 Mon Sep 17 00:00:00 2001 +From: Doug Ledford +Date: Mon, 5 Apr 2010 12:32:08 -0400 +Subject: [PATCH 6/6] Initial implementation of incremental remove support + +Signed-off-by: Doug Ledford +--- + Incremental.c | 36 ++++++++++++++++++ + Manage.c | 105 +++++++++++++++++++++++++++++++++++++-------------- + ReadMe.c | 21 +++++++--- + mdadm.8 | 23 ++++++++++- + mdadm.c | 13 ++++++ + mdadm.h | 8 ++++ + mdstat.c | 90 +++++++++++++++++++++++++++++++++++++++++++- + sysfs.c | 13 ++++-- + udev-md-raid.rules | 16 +++++--- + 9 files changed, 274 insertions(+), 51 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index 7ad648a..d32a8e5 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -843,3 +843,39 @@ int Incremental_container(struct supertype *st, char *devname, int verbose, + map_unlock(&map); + return 0; + } ++ ++/* ++ * IncrementalRemove - Attempt to see if the passed in device belongs to any ++ * raid arrays, and if so first fail (if needed) and then remove the device. ++ * ++ * @devname - The device we want to remove ++ * ++ * Special note: We would like to just use Managedevs to fail/remove the ++ * device, but unfortunately, by the time we are called via udev, the device ++ * special file is already gone, and so we can't stat the device and se we ++ * don't have the right rdev value to use in the ioctls. So, we use the ++ * sysfs method of device removal instead, but since that's not gauranteed ++ * to work depending on the version of kernel we run on, try to use the ++ * ioctl method first and only fallback if we don't have a valid device ++ * special file. That way we can support operation manually on older kernels ++ * even if we won't be able to do this automatically via udev on older ++ * kernels. ++ */ ++int IncrementalRemove(char *devname, int verbose) ++{ ++ char mddev[100] = "/dev/"; ++ int mdfd; ++ struct mddev_dev_s devlist; ++ ++ strncpy(mddev + 5, devname, sizeof(mddev) - 5); ++ if (mdstat_check_active(mddev + 5)) ++ return 1; ++ if ((mdfd = open_mddev(mddev, 0)) < 0) ++ return 1; ++ memset(&devlist, 0, sizeof(devlist)); ++ devlist.devname = devname; ++ devlist.disposition = 'f'; ++ Manage_subdevs(mddev, mdfd, &devlist, verbose); ++ devlist.disposition = 'r'; ++ return Manage_subdevs(mddev, mdfd, &devlist, verbose); ++} +diff --git a/Manage.c b/Manage.c +index f848d8b..6539eda 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -346,6 +346,9 @@ int Manage_subdevs(char *devname, int fd, + mdu_disk_info_t disc; + unsigned long long array_size; + mddev_dev_t dv, next = NULL; ++ struct mdinfo *mdi = NULL; ++ struct mdinfo *dev = NULL; ++ char sys_name[20] = "dev-"; + struct stat stb; + int j, jnext = 0; + int tfd; +@@ -443,16 +446,43 @@ int Manage_subdevs(char *devname, int fd, + if (jnext == 0) + continue; + } else { ++ /* ++ * For fail/remove operations, allow the disk ++ * to be completely missing, use name matching ++ * to a device in our sysfs entries to ++ * suffice. For add we need a valid block device. ++ * Leave this loop one of three ways: ++ * 1) tfd < 0 and dev is set to our device ++ * 2) tfd >= 0 and dev is NULL ++ * 3) failed to find suitable device and return ++ */ + j = 0; + + tfd = dev_open(dv->devname, O_RDONLY); +- if (tfd < 0 && dv->disposition == 'r' && +- lstat(dv->devname, &stb) == 0) +- /* Be happy, the lstat worked, that is +- * enough for --remove +- */ +- ; +- else { ++ if (tfd < 0 && dv->disposition != 'a') { ++ strcpy(&sys_name[4], ++ strrchr(dv->devname, '/') + 1); ++ mdi = sysfs_read(fd, 0, ++ GET_DEVS | KEEP_GONE_DEVS); ++ if (!mdi) { ++ fprintf(stderr, Name ": can't open %s " ++ "and can't read sysfs info\n", ++ dv->devname); ++ return 1; ++ } ++ for (dev = mdi->devs; dev; dev = dev->next) { ++ if (strcmp(sys_name, dev->sys_name)) ++ continue; ++ break; ++ } ++ if (!dev) { ++ fprintf(stderr, Name ": can't open %s " ++ "and %s not listed in sysfs\n", ++ dv->devname, sys_name); ++ sysfs_free(mdi); ++ return 1; ++ } ++ } else { + if (tfd < 0 || fstat(tfd, &stb) != 0) { + fprintf(stderr, Name ": cannot find %s: %s\n", + dv->devname, strerror(errno)); +@@ -461,12 +491,12 @@ int Manage_subdevs(char *devname, int fd, + return 1; + } + close(tfd); +- } +- if ((stb.st_mode & S_IFMT) != S_IFBLK) { +- fprintf(stderr, Name ": %s is not a " +- "block device.\n", +- dv->devname); +- return 1; ++ if ((stb.st_mode & S_IFMT) != S_IFBLK) { ++ fprintf(stderr, Name ": %s is not a " ++ "block device.\n", ++ dv->devname); ++ return 1; ++ } + } + } + switch(dv->disposition){ +@@ -790,26 +820,36 @@ int Manage_subdevs(char *devname, int fd, + return 1; + } + } +- /* FIXME check that it is a current member */ +- err = ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev); +- if (err && errno == ENODEV) { ++ /* stb.st_rdev is only valid if we have a tfd that ++ * does not indicate an error on attempt to open ++ * the devname ++ */ ++ if (tfd >= 0) ++ err = ioctl(fd, HOT_REMOVE_DISK, ++ (unsigned long)stb.st_rdev); ++ if (tfd < 0 || (err && errno == ENODEV)) { + /* Old kernels rejected this if no personality + * registered */ +- struct mdinfo *sra = sysfs_read(fd, 0, GET_DEVS); +- struct mdinfo *dv = NULL; +- if (sra) +- dv = sra->devs; +- for ( ; dv ; dv=dv->next) +- if (dv->disk.major == major(stb.st_rdev) && +- dv->disk.minor == minor(stb.st_rdev)) ++ if (!mdi) { ++ strcpy(&sys_name[4], ++ strrchr(dv->devname, '/') + 1); ++ mdi = sysfs_read(fd, 0, GET_DEVS | ++ KEEP_GONE_DEVS); ++ if (mdi) ++ dev = mdi->devs; ++ for ( ; dev ; dev=dev->next) { ++ if (strcmp(sys_name, dev->sys_name)) ++ continue; + break; +- if (dv) +- err = sysfs_set_str(sra, dv, ++ } ++ } ++ if (dev) ++ err = sysfs_set_str(mdi, dev, + "state", "remove"); + else + err = -1; +- if (sra) +- sysfs_free(sra); ++ if (mdi) ++ sysfs_free(mdi); + } + if (err) { + fprintf(stderr, Name ": hot remove failed " +@@ -844,11 +884,18 @@ int Manage_subdevs(char *devname, int fd, + + case 'f': /* set faulty */ + /* FIXME check current member */ +- if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) { ++ if ((tfd >= 0 && ioctl(fd, SET_DISK_FAULTY, ++ (unsigned long) stb.st_rdev)) || ++ (tfd < 0 && sysfs_set_str(mdi, dev, "state", ++ "faulty"))) { + fprintf(stderr, Name ": set device faulty failed for %s: %s\n", + dnprintable, strerror(errno)); ++ if (mdi) ++ sysfs_free(mdi); + return 1; +- } ++ } ++ if (mdi) ++ sysfs_free(mdi); + if (verbose >= 0) + fprintf(stderr, Name ": set %s faulty in %s\n", + dnprintable, devname); +diff --git a/ReadMe.c b/ReadMe.c +index 9d5a211..fd216ec 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -86,11 +86,12 @@ char Version[] = Name " - v3.1.2 - 10th March 2010\n"; + * At the time if writing, there is only minimal support. + */ + +-char short_options[]="-ABCDEFGIQhVXWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; ++char short_options[]= ++ "-ABCDEFGIQhVXWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; + char short_bitmap_options[]= +- "-ABCDEFGIQhVXWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; ++ "-ABCDEFGIQhVXWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; + char short_bitmap_auto_options[]= +- "-ABCDEFGIQhVXWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:"; ++ "-ABCDEFGIQhVXWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:"; + + struct option long_options[] = { + {"manage", 0, 0, '@'}, +@@ -213,7 +214,7 @@ char Help[] = + " mdadm --grow options device\n" + " resize/reshape an active array\n" + " mdadm --incremental device\n" +-" add a device to an array as appropriate\n" ++" add/remove a device to/from an array as appropriate\n" + " mdadm --monitor options...\n" + " Monitor one or more array for significant changes.\n" + " mdadm device options...\n" +@@ -535,20 +536,26 @@ char Help_grow[] = + ; + + char Help_incr[] = +-"Usage: mdadm --incremental [-Rqrs] device\n" ++"Usage: mdadm --incremental [-Rqrsf] device\n" + "\n" + "This usage allows for incremental assembly of md arrays. Devices can be\n" + "added one at a time as they are discovered. Once an array has all expected\n" + "devices, it will be started.\n" + "\n" +-"Options that are valid with incremental assembly (-I --incremental) more are:\n" +-" --run -R : run arrays as soon as a minimal number of devices are\n" ++"Optionally, the process can be reversed by using the fail option.\n" ++"When fail mode is invoked, mdadm will see if the device belongs to an array\n" ++"and then both fail (if needed) and remove the device from that array.\n" ++"\n" ++"Options that are valid with incremental assembly (-I --incremental) are:\n" ++" --run -R : Run arrays as soon as a minimal number of devices are\n" + " : present rather than waiting for all expected.\n" + " --quiet -q : Don't print any information messages, just errors.\n" + " --rebuild -r : Rebuild the 'map' file that mdadm uses for tracking\n" + " : partial arrays.\n" + " --scan -s : Use with -R to start any arrays that have the minimal\n" + " : required number of devices, but are not yet started.\n" ++" --fail -f : First fail (if needed) and then remove device from\n" ++" : any array that it is a member of.\n" + ; + + char Help_config[] = +diff --git a/mdadm.8 b/mdadm.8 +index 4edfc41..eaf9155 100644 +--- a/mdadm.8 ++++ b/mdadm.8 +@@ -135,7 +135,11 @@ This provides a convenient interface to a + .I hot-plug + system. As each device is detected, + .I mdadm +-has a chance to include it in some array as appropriate. ++has a chance to include it in some array as appropriate. Optionally, ++with the ++.I \-\-fail ++flag is passed in then we will remove the device from any active array ++instead of adding it. + + If a + .B CONTAINER +@@ -189,7 +193,7 @@ Change the size or shape of an active array. + + .TP + .BR \-I ", " \-\-incremental +-Add a single device into an appropriate array, and possibly start the array. ++Add/remove a single device to/from an appropriate array, and possibly start the array. + + .TP + .B \-\-auto-detect +@@ -1235,6 +1239,12 @@ in + .B mdadm.conf + as requiring an external bitmap, that bitmap will be attached first. + ++.TP ++.BR \-\-fail ", " \-f ++This allows the hot-plug system to remove devices that have fully disappeared ++from the kernel. It will first fail and then remove the device from any ++array it belongs to. ++ + .SH For Monitor mode: + .TP + .BR \-m ", " \-\-mail +@@ -2141,6 +2151,10 @@ Usage: + .I component-device + .HP 12 + Usage: ++.B mdadm \-\-incremental \-\-fail ++.I component-device ++.HP 12 ++Usage: + .B mdadm \-\-incremental \-\-rebuild + .HP 12 + Usage: +@@ -2153,6 +2167,11 @@ passed to + .B "mdadm \-\-incremental" + to be conditionally added to an appropriate array. + ++Conversely, it can also be used with the ++.B \-\-fail ++flag to do just the opposite and find whatever array a particular device ++is part of and remove the device from the array. ++ + If the device passed is a + .B CONTAINER + device created by a previous call to +diff --git a/mdadm.c b/mdadm.c +index d5e34c0..cd6fd8f 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -124,6 +124,7 @@ int main(int argc, char *argv[]) + ident.name[0] = 0; + ident.container = NULL; + ident.member = NULL; ++ ident.member_index = -1; + + while ((option_index = -1) , + (opt=getopt_long(argc, argv, +@@ -774,6 +775,9 @@ int main(int argc, char *argv[]) + devmode = 'r'; + continue; + case O(MANAGE,'f'): /* set faulty */ ++ case O(INCREMENTAL,'f'): /* r for incremental is taken, use f ++ * even though we will both fail and ++ * remove the device */ + devmode = 'f'; + continue; + case O(INCREMENTAL,'R'): +@@ -1517,6 +1521,11 @@ int main(int argc, char *argv[]) + ": --incremental --scan meaningless without --run.\n"); + break; + } ++ if (devmode == 'f') { ++ fprintf(stderr, Name ++ ": --incremental --scan --fail not supported.\n"); ++ break; ++ } + rv = IncrementalScan(verbose); + } + if (!devlist) { +@@ -1533,6 +1542,10 @@ int main(int argc, char *argv[]) + rv = 1; + break; + } ++ if (devmode == 'f') { ++ rv = IncrementalRemove(devlist->devname, verbose-quiet); ++ break; ++ } + rv = Incremental(devlist->devname, verbose-quiet, runstop, + ss, homehost, require_homehost, autof); + break; +diff --git a/mdadm.h b/mdadm.h +index d8ab85f..c113d0f 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -315,6 +315,7 @@ typedef struct mddev_ident_s { + * of some other entry. + */ + char *member; /* subarray within a container */ ++ int member_index; /* subarray index within a container */ + + struct mddev_ident_s *next; + union { +@@ -355,6 +356,10 @@ struct mdstat_ent { + int raid_disks; + int chunk_size; + char * metadata_version; ++ struct dev_member { ++ char *name; ++ struct dev_member *next; ++ } *members; + struct mdstat_ent *next; + }; + +@@ -363,6 +368,7 @@ extern void free_mdstat(struct mdstat_ent *ms); + extern void mdstat_wait(int seconds); + extern void mdstat_wait_fd(int fd, const sigset_t *sigmask); + extern int mddev_busy(int devnum); ++extern int mdstat_check_active(char *devname); + + struct map_ent { + struct map_ent *next; +@@ -404,6 +410,7 @@ enum sysfs_read_flags { + GET_STATE = (1 << 13), + GET_ERROR = (1 << 14), + SKIP_GONE_DEVS = (1 << 15), ++ KEEP_GONE_DEVS = (1 << 16), + }; + + /* If fd >= 0, get the array it is open on, +@@ -817,6 +824,7 @@ extern int Incremental_container(struct supertype *st, char *devname, + int trustworthy); + extern void RebuildMap(void); + extern int IncrementalScan(int verbose); ++extern int IncrementalRemove(char *devname, int verbose); + + extern int CreateBitmap(char *filename, int force, char uuid[16], + unsigned long chunksize, unsigned long daemon_sleep, +diff --git a/mdstat.c b/mdstat.c +index 4a9f370..81d2212 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -83,6 +83,45 @@ + #include + #include + ++static void free_member_devnames(struct dev_member **m) ++{ ++ struct dev_member *t; ++ if (!*m) ++ return; ++ while(*m) { ++ t = *m; ++ *m = (*m)->next; ++ if (t->name) ++ free(t->name); ++ free(t); ++ } ++ *m = NULL; ++} ++ ++static struct dev_member *add_member_devname(struct dev_member **m, char *name) ++{ ++ struct dev_member *new; ++ char *t; ++ ++ if (!m || !name) ++ return NULL; ++ ++ new = malloc(sizeof(*new)); ++ if (!new) ++ return NULL; ++ if ((t = strchr(name, '[')) == NULL) ++ { ++ /* not a device */ ++ free(new); ++ return *m; ++ } ++ new->name = strndup(name, t - name); ++ new->next = *m; ++ *m = new; ++ ++ return new; ++} ++ + void free_mdstat(struct mdstat_ent *ms) + { + while (ms) { +@@ -91,6 +130,7 @@ void free_mdstat(struct mdstat_ent *ms) + if (ms->level) free(ms->level); + if (ms->pattern) free(ms->pattern); + if (ms->metadata_version) free(ms->metadata_version); ++ if (ms->members) free_member_devnames(&ms->members); + t = ms; + ms = ms->next; + free(t); +@@ -159,6 +199,7 @@ struct mdstat_ent *mdstat_read(int hold, int start) + ent->raid_disks = 0; + ent->chunk_size = 0; + ent->devcnt = 0; ++ ent->members = NULL; + + ent->dev = strdup(line); + ent->devnum = devnum; +@@ -170,15 +211,23 @@ struct mdstat_ent *mdstat_read(int hold, int start) + ent->active = 1; + else if (strcmp(w, "inactive")==0) + ent->active = 0; +- else if (ent->active >=0 && ++ else if (ent->active > 0 && + ent->level == NULL && + w[0] != '(' /*readonly*/) { + ent->level = strdup(w); + in_devs = 1; + } else if (in_devs && strcmp(w, "blocks")==0) + in_devs = 0; +- else if (in_devs) { ++ else if (in_devs || (ent->active == 0 && w[0] != '(' && ++ w[l - 1] == ')')) { ++ if (isdigit(w[0])) ++ continue; ++ in_devs = 1; + ent->devcnt++; ++ if (!add_member_devname(&ent->members, w)) { ++ free_mdstat(ent); ++ break; ++ } + if (strncmp(w, "md", 2)==0) { + /* This has an md device as a component. + * If that device is already in the +@@ -310,3 +359,40 @@ int mddev_busy(int devnum) + free_mdstat(mdstat); + return me != NULL; + } ++ ++/* ++ * Finds name of the active array holding this device ++ * @param[in] devname name of member device ++ * @param[out] devname name of array ++ * ++ * @return found (0), or ++ * not found, failure (1) ++ */ ++ ++int mdstat_check_active(char *devname) ++{ ++ struct mdstat_ent *mdstat = mdstat_read(0, 0); ++ struct mdstat_ent *ent; ++ char *name; ++ ++ if (!devname) ++ return 1; ++ name = strrchr(devname, '/'); ++ if (name++ == NULL) ++ return 1; ++ ++ for (ent = mdstat; ent; ent = ent->next) { ++ struct dev_member *m; ++ if (ent->active && (strstr(ent->metadata_version,"imsm") || ++ strstr(ent->metadata_version,"ddf"))) ++ /* only return container matches, not subarrays */ ++ continue; ++ for (m = ent->members; m; m = m->next) { ++ if (!strcmp(m->name, name)) { ++ strcpy(devname, ent->dev); ++ return 0; ++ } ++ } ++ } ++ return 1; ++} +diff --git a/sysfs.c b/sysfs.c +index ebf9d8a..65dd848 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -273,13 +273,16 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options) + + strcpy(dbase, "block/dev"); + if (load_sys(fname, buf)) { +- free(dev); +- if (options & SKIP_GONE_DEVS) ++ if (options & SKIP_GONE_DEVS) { ++ free(dev); + continue; +- else ++ } else if (options & KEEP_GONE_DEVS) { ++ dev->disk.major = dev->disk.minor = -1; ++ } else + goto abort; +- } +- sscanf(buf, "%d:%d", &dev->disk.major, &dev->disk.minor); ++ } else ++ sscanf(buf, "%d:%d", &dev->disk.major, ++ &dev->disk.minor); + + /* special case check for block devices that can go 'offline' */ + if (options & SKIP_GONE_DEVS) { +diff --git a/udev-md-raid.rules b/udev-md-raid.rules +index c9a4f0e..aff14fa 100644 +--- a/udev-md-raid.rules ++++ b/udev-md-raid.rules +@@ -1,17 +1,16 @@ + # do not edit this file, it will be overwritten on update + + SUBSYSTEM!="block", GOTO="md_end" +-ACTION!="add|change", GOTO="md_end" ++ACTION!="add|change|remove", GOTO="md_end" ++ACTION=="remove", GOTO="md_remove" + ACTION=="change", GOTO="md_no_incr" + +-# import data from a raid member and activate it +-#ENV{ID_FS_TYPE}=="linux_raid_member", IMPORT{program}="/sbin/mdadm --examine --export $tempnode", RUN+="/sbin/mdadm --incremental $env{DEVNAME}" +-# import data from a raid set ++# we are adding a raid member, activate it ++ENV{ID_FS_TYPE}=="linux_raid_member", RUN+="/sbin/mdadm -I $env{DEVNAME}" + LABEL="md_no_incr" + KERNEL!="md*", GOTO="md_end" + +-# partitions have no md/{array_state,metadata_version}, but should not +-# for that reason be ignored. ++# partitions have no md/{array_state,metadata_version} + ENV{DEVTYPE}=="partition", GOTO="md_ignore_state" + + # container devices have a metadata version of e.g. 'external:ddf' and +@@ -32,7 +31,12 @@ ENV{DEVTYPE}=="partition", ENV{MD_DEVNAME}=="*[0-9]", SYMLINK+="md/$env{MD_DEVNA + + IMPORT{program}="/sbin/blkid -o udev -p $tempnode" + OPTIONS+="link_priority=100" ++OPTIONS+="watch" + ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}" + ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}" ++GOTO="md_end" ++ ++LABEL="md_remove" ++ENV{ID_FS_TYPE}=="linux_raid_member", RUN+="/sbin/mdadm -If $env{DEVNAME}" + + LABEL="md_end" +-- +1.6.6.1 + diff --git a/mdadm-3.1.2-directory.patch b/mdadm-3.1.2-directory.patch new file mode 100644 index 0000000..61132a4 --- /dev/null +++ b/mdadm-3.1.2-directory.patch @@ -0,0 +1,265 @@ +From df3e08eaa7ee07528968bb7152dfaaeebd3c97cb Mon Sep 17 00:00:00 2001 +From: Doug Ledford +Date: Fri, 2 Apr 2010 10:53:47 -0400 +Subject: [PATCH 5/6] Fix all the confusion over directories once and for all. We now have + 3 directory definitions: mdmon directory for its pid and sock files, + mdmonitor directory which is for the mdadm monitor mode pid file and + can only be passed in via command line, and the directory for the + mdadm map file. Only the mdadm map file still hunts multiple locations, + and the number of locations has been reduced to /var/run and the + compile time specified location. I could see lowering that to just + 1 location, but I didn't do that with this patch. + +Signed-off-by: Doug Ledford +--- + Makefile | 18 +++++++++--------- + mapfile.c | 18 ++++++++---------- + mdadm.h | 41 +++++++++++++++++++++-------------------- + mdmon.c | 28 ++++++---------------------- + msg.c | 2 +- + util.c | 4 +--- + 6 files changed, 46 insertions(+), 65 deletions(-) + +diff --git a/Makefile b/Makefile +index 2aafad0..30e52a7 100644 +--- a/Makefile ++++ b/Makefile +@@ -58,16 +58,16 @@ CONFFILE = $(SYSCONFDIR)/mdadm.conf + CONFFILE2 = $(SYSCONFDIR)/mdadm/mdadm.conf + MAILCMD =/usr/sbin/sendmail -t + CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE)\" -DCONFFILE2=\"$(CONFFILE2)\" +-# ALT_RUN should be somewhere that persists across the pivotroot +-# from early boot to late boot. ++# Both MAP_DIR and MDMON_DIR should be somewhere that persists across the ++# pivotroot from early boot to late boot. + # If you don't have /lib/init/rw you might want to use /dev/.something +-# e.g. make ALT_RUN=/dev/.mdadm +-ALT_RUN = /lib/init/rw +-ALT_MAPFILE = map +-VAR_RUN = /var/run +-ALTFLAGS = -DALT_RUN=\"$(ALT_RUN)\" -DALT_MAPFILE=\"$(ALT_MAPFILE)\" +-VARFLAGS = -DVAR_RUN=\"$(VAR_RUN)\" +-CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(ALTFLAGS) $(VARFLAGS) ++# e.g. make MAP_DIR=/dev/.mdadm ++MAP_DIR = /lib/init/rw/mdadm ++MAP_FILE = map ++MDMON_DIR = /lib/init/rw/mdmon ++DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\" ++DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\" ++CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) + + # If you want a static binary, you might uncomment these + # LDFLAGS = -static +diff --git a/mapfile.c b/mapfile.c +index d47fde1..f4339db 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -52,28 +52,26 @@ + #include + + #define mapnames(base) { base, base ".new", base ".lock"} +-char *mapname[3][3] = { +- mapnames(VAR_RUN "/map"), +- mapnames("/var/run/mdadm.map"), +- mapnames(ALT_RUN "/" ALT_MAPFILE) ++char *mapname[2][3] = { ++ mapnames(MAP_DIR "/" MAP_FILE), ++ mapnames("/var/run/mdadm.map") + }; +-char *mapdir[3] = { VAR_RUN, NULL, ALT_RUN }; ++char *mapdir[2] = { MAP_DIR, NULL }; + +-int mapmode[3] = { O_RDONLY, O_RDWR|O_CREAT, O_RDWR|O_CREAT | O_TRUNC }; ++int mapmode[3] = { O_RDONLY, O_RDWR|O_CREAT, O_RDWR|O_CREAT|O_TRUNC }; + char *mapsmode[3] = { "r", "w", "w"}; + + FILE *open_map(int modenum, int *choice) + { + int i; + +- for (i = 0 ; i < 3 ; i++) { ++ for (i = 0 ; i < 2 ; i++) { + int fd; +- if ((mapmode[modenum] & O_CREAT) && +- mapdir[modenum]) ++ if ((mapmode[modenum] & O_CREAT) && mapdir[i]) + /* Attempt to create directory, don't worry about + * failure. + */ +- mkdir(mapdir[modenum], 0755); ++ mkdir(mapdir[i], 0755); + fd = open(mapname[i][modenum], mapmode[modenum], 0600); + if (fd >= 0) { + *choice = i; +diff --git a/mdadm.h b/mdadm.h +index 0386129..d8ab85f 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -68,28 +68,30 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); + #define DEFAULT_BITMAP_DELAY 5 + #define DEFAULT_MAX_WRITE_BEHIND 256 + +-/* VAR_RUN is where pid and socket files used for communicating +- * with mdmon normally live. It should be /var/run, but if +- * it is too hard to remount /var/run as read-only rather than +- * unmounting it at shutdown time, then it should be +- * redefined to some place that comfortably persists until +- * final shutdown, possibly in /dev if that is a tmpfs. +- * Note: VAR_RUN does not need to be writable at shutdown, +- * only during boot when "mdmon --takeover" is run. +- */ +-#ifndef VAR_RUN +-#define VAR_RUN "/var/run/mdadm" +-#endif /* VAR_RUN */ +-/* ALT_RUN should be somewhere that persists across the pivotroot ++/* MAP_DIR should be somewhere that persists across the pivotroot + * from early boot to late boot. + * If you don't have /lib/init/rw you might want to use /dev/.something + */ +-#ifndef ALT_RUN +-#define ALT_RUN "/lib/init/rw/mdadm" +-#endif /* ALT_RUN */ +-#ifndef ALT_MAPFILE +-#define ALT_MAPFILE "map" +-#endif /* ALT_MAPFILE */ ++#ifndef MAP_DIR ++#define MAP_DIR "/lib/init/rw/mdadm" ++#endif /* MAP_DIR */ ++/* MAP_FILE is what we name the map file we put in MAP_DIR, in case you ++ * want something other than the default of "map" ++ */ ++#ifndef MAP_FILE ++#define MAP_FILE "map" ++#endif /* MAP_FILE */ ++/* MDMON_DIR is where pid and socket files used for communicating ++ * with mdmon normally live. It *should* be /var/run, but when ++ * mdmon is needed at early boot then it needs to write there prior ++ * to /var/run being mounted read/write, and it also then needs to ++ * persist beyond when /var/run is mounter read-only. So, to be ++ * safe, the default is somewhere that is read/write early in the ++ * boot process and stays up as long as possible during shutdown. ++ */ ++#ifndef MDMON_DIR ++#define MDMON_DIR "/lib/init/rw/mdmon" ++#endif /* MDMON_DIR */ + + #include "md_u.h" + #include "md_p.h" +@@ -910,7 +912,6 @@ extern int create_mddev(char *dev, char *name, int autof, int trustworthy, + extern int open_mddev(char *dev, int report_errors); + extern int open_container(int fd); + +-extern char *pid_dir; + extern int mdmon_running(int devnum); + extern int mdmon_pid(int devnum); + extern int check_env(char *name); +diff --git a/mdmon.c b/mdmon.c +index 69c320e..cbb72cc 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -120,10 +120,10 @@ static int make_pidfile(char *devname) + int fd; + int n; + +- if (mkdir(pid_dir, 0700) < 0 && ++ if (mkdir(MDMON_DIR, 0755) < 0 && + errno != EEXIST) + return -errno; +- sprintf(path, "%s/%s.pid", pid_dir, devname); ++ sprintf(path, "%s/%s.pid", MDMON_DIR, devname); + + fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd < 0) +@@ -189,13 +189,10 @@ void remove_pidfile(char *devname) + { + char buf[100]; + +- sprintf(buf, "%s/%s.pid", pid_dir, devname); ++ sprintf(buf, "%s/%s.pid", MDMON_DIR, devname); + unlink(buf); +- sprintf(buf, "%s/%s.sock", pid_dir, devname); ++ sprintf(buf, "%s/%s.sock", MDMON_DIR, devname); + unlink(buf); +- if (strcmp(pid_dir, ALT_RUN) == 0) +- /* try to clean up when we are finished with this dir */ +- rmdir(pid_dir); + } + + static int make_control_sock(char *devname) +@@ -208,7 +205,7 @@ static int make_control_sock(char *devname) + if (sigterm) + return -1; + +- sprintf(path, "%s/%s.sock", pid_dir, devname); ++ sprintf(path, "%s/%s.sock", MDMON_DIR, devname); + unlink(path); + sfd = socket(PF_LOCAL, SOCK_STREAM, 0); + if (sfd < 0) +@@ -445,12 +442,7 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover) + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + +- pid_dir = VAR_RUN; + victim = mdmon_pid(container->devnum); +- if (victim < 0) { +- pid_dir = ALT_RUN; +- victim = mdmon_pid(container->devnum); +- } + if (victim >= 0) + victim_sock = connect_monitor(container->devname); + +@@ -474,16 +466,8 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover) + */ + if (victim > 0) + remove_pidfile(devname); +- pid_dir = VAR_RUN; + if (make_pidfile(devname) < 0) { +- /* Try the alternate */ +- pid_dir = ALT_RUN; +- if (make_pidfile(devname) < 0) { +- fprintf(stderr, "mdmon: Neither %s nor %s are writable\n" +- " cannot create .pid or .sock files. Aborting\n", +- VAR_RUN, ALT_RUN); +- exit(3); +- } ++ exit(3); + } + container->sock = make_control_sock(devname); + +diff --git a/msg.c b/msg.c +index d2d8445..aabfa8f 100644 +--- a/msg.c ++++ b/msg.c +@@ -147,7 +147,7 @@ int connect_monitor(char *devname) + int pos; + char *c; + +- pos = sprintf(path, "%s/", pid_dir); ++ pos = sprintf(path, "%s/", MDMON_DIR); + if (is_subarray(devname)) { + devname++; + c = strchr(devname, '/'); +diff --git a/util.c b/util.c +index 79d2b0f..bdb19f9 100644 +--- a/util.c ++++ b/util.c +@@ -1499,15 +1499,13 @@ int fd2devnum(int fd) + return NoMdDev; + } + +-char *pid_dir = VAR_RUN; +- + int mdmon_pid(int devnum) + { + char path[100]; + char pid[10]; + int fd; + int n; +- sprintf(path, "%s/%s.pid", pid_dir, devnum2devname(devnum)); ++ sprintf(path, "%s/%s.pid", MDMON_DIR, devnum2devname(devnum)); + fd = open(path, O_RDONLY | O_NOATIME, 0); + + if (fd < 0) +-- +1.6.6.1 + diff --git a/mdadm-3.1.2-mapfile.patch b/mdadm-3.1.2-mapfile.patch new file mode 100644 index 0000000..5523c0d --- /dev/null +++ b/mdadm-3.1.2-mapfile.patch @@ -0,0 +1,80 @@ +From 435b90e7d41a17f35a984112cace471c975906f4 Mon Sep 17 00:00:00 2001 +From: Doug Ledford +Date: Tue, 16 Mar 2010 23:00:11 -0400 +Subject: [PATCH 2/6] Create directory to contain mapfile (Assuming parent exists and + filesystem is writable). + This particularly keeps udev happy if VAR_RUN is set to /dev/md. + +Signed-off-by: Doug Ledford +Signed-off-by: NeilBrown +--- + mapfile.c | 17 +++++++++++++---- + mdmon.c | 2 +- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/mapfile.c b/mapfile.c +index 366ebe3..89187ac 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -29,7 +29,7 @@ + */ + + /* /var/run/mdadm.map is used to track arrays being created in --incremental +- * more. It particularly allows lookup from UUID to array device, but ++ * mode. It particularly allows lookup from UUID to array device, but + * also allows the array device name to be easily found. + * + * The map file is line based with space separated fields. The fields are: +@@ -42,8 +42,8 @@ + * However /var/run may not exist or be writable in early boot. And if + * no-one has created /var/run/mdadm, we still want to survive. + * So possible locations are: +- * /var/run/mdadm/map /var/run/mdadm.map /dev/.mdadm.map +- * the last, because udev requires a writable /dev very early. ++ * /var/run/mdadm/map /var/run/mdadm.map /lib/initrw/madam/map ++ * The last can easily be change at compile to e.g. somewhere in /dev. + * We read from the first one that exists and write to the first + * one that we can. + */ +@@ -57,6 +57,7 @@ char *mapname[3][3] = { + mapnames("/var/run/mdadm.map"), + mapnames(ALT_RUN "/map") + }; ++char *mapdir[3] = { VAR_RUN, NULL, ALT_RUN }; + + int mapmode[3] = { O_RDONLY, O_RDWR|O_CREAT, O_RDWR|O_CREAT | O_TRUNC }; + char *mapsmode[3] = { "r", "w", "w"}; +@@ -64,8 +65,16 @@ char *mapsmode[3] = { "r", "w", "w"}; + FILE *open_map(int modenum, int *choice) + { + int i; ++ + for (i = 0 ; i < 3 ; i++) { +- int fd = open(mapname[i][modenum], mapmode[modenum], 0600); ++ int fd; ++ if ((mapmode[modenum] & O_CREAT) && ++ mapdir[modenum]) ++ /* Attempt to create directory, don't worry about ++ * failure. ++ */ ++ mkdir(mapdir[modenum], 0755); ++ fd = open(mapname[i][modenum], mapmode[modenum], 0600); + if (fd >= 0) { + *choice = i; + return fdopen(fd, mapsmode[modenum]); +diff --git a/mdmon.c b/mdmon.c +index 961aa77..69c320e 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -120,7 +120,7 @@ static int make_pidfile(char *devname) + int fd; + int n; + +- if (mkdir(pid_dir, 0600) < 0 && ++ if (mkdir(pid_dir, 0700) < 0 && + errno != EEXIST) + return -errno; + sprintf(path, "%s/%s.pid", pid_dir, devname); +-- +1.6.6.1 + diff --git a/mdadm-3.1.2-mapname.patch b/mdadm-3.1.2-mapname.patch new file mode 100644 index 0000000..a8f88f5 --- /dev/null +++ b/mdadm-3.1.2-mapname.patch @@ -0,0 +1,58 @@ +From e259df4e63f553c1271fa7d7612c110d2518e572 Mon Sep 17 00:00:00 2001 +From: Doug Ledford +Date: Wed, 17 Mar 2010 10:52:22 -0400 +Subject: [PATCH 3/6] mapfile: if we putting the mapfile in a custom location via ALT_RUN, allow + a custom filename too. + +Signed-off-by: Doug Ledford +--- + Makefile | 3 ++- + mapfile.c | 2 +- + mdadm.h | 3 +++ + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index 1035ea8..2aafad0 100644 +--- a/Makefile ++++ b/Makefile +@@ -63,8 +63,9 @@ CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE)\" -DCONFFILE2=\"$(CONFFILE2)\" + # If you don't have /lib/init/rw you might want to use /dev/.something + # e.g. make ALT_RUN=/dev/.mdadm + ALT_RUN = /lib/init/rw ++ALT_MAPFILE = map + VAR_RUN = /var/run +-ALTFLAGS = -DALT_RUN=\"$(ALT_RUN)\" ++ALTFLAGS = -DALT_RUN=\"$(ALT_RUN)\" -DALT_MAPFILE=\"$(ALT_MAPFILE)\" + VARFLAGS = -DVAR_RUN=\"$(VAR_RUN)\" + CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(ALTFLAGS) $(VARFLAGS) + +diff --git a/mapfile.c b/mapfile.c +index 89187ac..74f7256 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -55,7 +55,7 @@ + char *mapname[3][3] = { + mapnames(VAR_RUN "/map"), + mapnames("/var/run/mdadm.map"), +- mapnames(ALT_RUN "/map") ++ mapnames(ALT_RUN "/" ALT_MAPFILE) + }; + char *mapdir[3] = { VAR_RUN, NULL, ALT_RUN }; + +diff --git a/mdadm.h b/mdadm.h +index 362b66b..0386129 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -87,6 +87,9 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); + #ifndef ALT_RUN + #define ALT_RUN "/lib/init/rw/mdadm" + #endif /* ALT_RUN */ ++#ifndef ALT_MAPFILE ++#define ALT_MAPFILE "map" ++#endif /* ALT_MAPFILE */ + + #include "md_u.h" + #include "md_p.h" +-- +1.6.6.1 + diff --git a/mdadm-3.1.2-rebuild.patch b/mdadm-3.1.2-rebuild.patch new file mode 100644 index 0000000..a9be5c3 --- /dev/null +++ b/mdadm-3.1.2-rebuild.patch @@ -0,0 +1,38 @@ +From 7bf59f5c16d928d3826fdf0c406d1aac5775e78b Mon Sep 17 00:00:00 2001 +From: Doug Ledford +Date: Wed, 17 Mar 2010 09:28:07 -0400 +Subject: [PATCH 4/6] Only signal a udev change event if we actually write a mapfile in RebuildMap + +Signed-off-by: Doug Ledford +--- + mapfile.c | 14 ++++++++------ + 1 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/mapfile.c b/mapfile.c +index 74f7256..d47fde1 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -471,12 +471,14 @@ void RebuildMap(void) + } + sysfs_free(sra); + } +- map_write(map); ++ /* Only trigger a change if we wrote a new map file */ ++ if (map_write(map)) ++ for (md = mdstat ; md ; md = md->next) { ++ struct mdinfo *sra = sysfs_read(-1, md->devnum, ++ GET_VERSION); ++ sysfs_uevent(sra, "change"); ++ sysfs_free(sra); ++ } + map_free(map); +- for (md = mdstat ; md ; md = md->next) { +- struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_VERSION); +- sysfs_uevent(sra, "change"); +- sysfs_free(sra); +- } + free_mdstat(mdstat); + } +-- +1.6.6.1 + diff --git a/mdadm.rules b/mdadm.rules index 39fd0cd..df3d906 100644 --- a/mdadm.rules +++ b/mdadm.rules @@ -3,6 +3,7 @@ # See udev(8) for syntax SUBSYSTEM=="block", ACTION=="add", ENV{ID_FS_TYPE}=="linux_raid_member", \ - IMPORT{program}="/sbin/mdadm --examine --export $tempnode", \ - RUN+="/bin/bash -c '[ ! -f /dev/.in_sysinit ] && mdadm -I $env{DEVNAME}'" + RUN+="/sbin/mdadm -I $env{DEVNAME}" +SUBSYSTEM=="block", ACTION=="remove", ENV{ID_FS_TYPE}=="linux_raid_member", \ + RUN+="/sbin/mdadm -If $env{DEVNAME}" diff --git a/mdadm.spec b/mdadm.spec index 82e265a..66f9412 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,16 +1,20 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm -Version: 3.1.1 -Release: 0.gcd9a8b5.6%{?dist} -Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}-gcd9a8b5.tar.bz2 +Version: 3.1.2 +Release: 3%{?dist} +Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.bz2 Source1: mdmonitor.init Source2: raid-check Source3: mdadm.rules Source4: mdadm-raid-check-sysconfig -Patch1: mdadm-2.5.2-static.patch -Patch2: mdadm-3.1.1-warn.patch -Patch3: mdadm-3.1.1-endian.patch -Patch4: mdadm-3.1.1-imsm.patch +Patch1: mdadm-3.1.2-mapname.patch +Patch2: mdadm-3.1.1-endian.patch +Patch3: mdadm-3.1.2-mapfile.patch +Patch4: mdadm-3.1.2-rebuild.patch +Patch5: mdadm-3.1.2-directory.patch +Patch6: mdadm-3.1.2-decremental.patch +Patch7: mdadm-3.1.2-decremental-2.patch +Patch9: mdadm-2.5.2-static.patch URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ License: GPLv2+ Group: System Environment/Base @@ -31,10 +35,14 @@ file can be used to help with some common tasks. %prep %setup -q -%patch1 -p1 -b .static -%patch2 -p1 -b .warn -%patch3 -p1 -b .endian -%patch4 -p1 -b .imsm +%patch3 -p1 -b .mapfile +%patch1 -p1 -b .mapname +%patch2 -p1 -b .endian +%patch4 -p1 -b .rebuild +%patch5 -p1 -b .directory +%patch6 -p1 -b .decremental +%patch7 -p1 -b .decremental-2 +%patch9 -p1 -b .static %build make %{?_smp_mflags} CXFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" SYSCONFDIR="%{_sysconfdir}" mdadm.static mdadm mdmon @@ -81,6 +89,20 @@ fi %attr(0700,root,root) %dir /var/run/mdadm %changelog +* Tue Apr 06 2010 Doug Ledford - 3.1.2-3 +- Clean up directory mess once and for all +- Add incremental remove support + +* Wed Mar 17 2010 Doug Ledford - 3.1.2-2 +- Add a little more paranoia checking to the RebuildMap code to avoid ever + having the same infinite loop as in bz569019 again even if we change file + locations to somewhere where we can't create a mapfile + +* Tue Mar 16 2010 Doug Ledford - 3.1.2-1 +- Grab latest upstream release instead of git repo snapshot (bz552344, bz572561) +- The lack of /dev/md is causing problems, so add code to mapfile.c to cause + us to create /dev/md if it doesn't exist (bz569019) + * Tue Feb 23 2010 Doug Ledford - 3.1.1-0.gcd9a8b5.6 - Newer version of imsm patch that leaves warning, but only when there actually are too many devices on the command line (bz554974) diff --git a/sources b/sources index 622391f..bab8ed6 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -fd4bcda48d6dc3d6113b5c25950c9671 mdadm-3.1.1-gcd9a8b5.tar.bz2 +c5a39f38c465229767a5af2a4eb81bef mdadm-3.1.2.tar.bz2