From 0f9ce65ed03f69c50ca506c2ef68d739db722971 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 9 Apr 2010 09:18:53 +1000 Subject: Add -fail support to --incremental This can be used for hot-unplug. When a device has been remove, udev can call mdadm --incremental --fail sda and mdadm will find the array holding sda and remove sda from the array. Based on code from Doug Ledford Signed-off-by: NeilBrown --- Incremental.c | 39 +++++++++++++++++++++++++++++++++++++++ Manage.c | 4 ++-- ReadMe.c | 16 +++++++++++----- mdadm.8 | 24 +++++++++++++++++++++++- mdadm.c | 12 ++++++++++++ mdadm.h | 2 +- 6 files changed, 88 insertions(+), 9 deletions(-) diff --git a/Incremental.c b/Incremental.c index 7ad648a..ed29488 100644 --- a/Incremental.c +++ b/Incremental.c @@ -843,3 +843,42 @@ 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 + * + * Note: the device name must be a kernel name like "sda", so + * that we can find it in /proc/mdstat + */ +int IncrementalRemove(char *devname, int verbose) +{ + int mdfd; + struct mdstat_ent *ent; + struct mddev_dev_s devlist; + + if (strchr(devname, '/')) { + fprintf(stderr, Name ": incremental removal requires a " + "kernel device name, not a file: %s\n", devname); + return 1; + } + ent = mdstat_by_component(devname); + if (!ent) { + fprintf(stderr, Name ": %s does not appear to be a component " + "of any array\n", devname); + return 1; + } + mdfd = open_dev(ent->devnum); + if (mdfd < 0) { + fprintf(stderr, Name ": Cannot open array %s!!\n", ent->dev); + return 1; + } + memset(&devlist, 0, sizeof(devlist)); + devlist.devname = devname; + devlist.disposition = 'f'; + Manage_subdevs(ent->dev, mdfd, &devlist, verbose); + devlist.disposition = 'r'; + return Manage_subdevs(ent->dev, mdfd, &devlist, verbose); +} diff --git a/Manage.c b/Manage.c index ad85705..ba585d2 100644 --- a/Manage.c +++ b/Manage.c @@ -893,8 +893,8 @@ int Manage_subdevs(char *devname, int fd, if (lfd >= 0) close(lfd); if (verbose >= 0) - fprintf(stderr, Name ": hot removed %s\n", - dnprintable); + fprintf(stderr, Name ": hot removed %s from %s\n", + dnprintable, devname); break; case 'f': /* set faulty */ diff --git a/ReadMe.c b/ReadMe.c index 9d5a211..b43d1a0 100644 --- a/ReadMe.c +++ b/ReadMe.c @@ -213,7 +213,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" @@ -256,7 +256,7 @@ char OptionHelp[] = " --examine-bitmap -X: Display the detail of a bitmap file\n" " --monitor -F : monitor (follow) some arrays\n" " --grow -G : resize/ reshape and array\n" -" --incremental -I : add a single device to an array as appropriate\n" +" --incremental -I : add/remove a single device to/from an array as appropriate\n" " --query -Q : Display general information about how a\n" " device relates to the md driver\n" " --auto-detect : Start arrays auto-detected by the kernel\n" @@ -535,20 +535,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..f547fda 100644 --- a/mdadm.8 +++ b/mdadm.8 @@ -136,6 +136,10 @@ This provides a convenient interface to a system. As each device is detected, .I mdadm has a chance to include it in some array as appropriate. +Optionally, when the +.I \-\-fail +flag is passed in 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,15 @@ 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. +The device name given should be a kernel device name such as "sda", +not a name in +.IR /dev . + .SH For Monitor mode: .TP .BR \-m ", " \-\-mail @@ -2141,6 +2154,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 +2170,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 that 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..6690546 100644 --- a/mdadm.c +++ b/mdadm.c @@ -774,6 +774,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 +1520,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 +1541,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 6bd3aae..2b47ae7 100644 --- a/mdadm.h +++ b/mdadm.h @@ -820,7 +820,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, unsigned long write_behind, -- cgit