From 9d26a69f727aff6b4ff3ade3711b67862adbf48d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 12 Jan 2012 13:39:08 +0100 Subject: [PATCH] Make sure to retry in case a remove fails due to an array being busy Signed-off-by: Jes Sorensen --- ...sure-we-retry-soon-when-remove-fails.patch | 92 +++++++++++++++ ...turn-from-read_and_act-more-symbolic.patch | 109 ++++++++++++++++++ mdadm.spec | 9 +- 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 mdadm-3.2.3-monitor-ensure-we-retry-soon-when-remove-fails.patch create mode 100644 mdadm-3.2.3-monitor-make-return-from-read_and_act-more-symbolic.patch diff --git a/mdadm-3.2.3-monitor-ensure-we-retry-soon-when-remove-fails.patch b/mdadm-3.2.3-monitor-ensure-we-retry-soon-when-remove-fails.patch new file mode 100644 index 0000000..a89bb5d --- /dev/null +++ b/mdadm-3.2.3-monitor-ensure-we-retry-soon-when-remove-fails.patch @@ -0,0 +1,92 @@ +From 68226a80812cd9fce63dbd14d2225ffdf16a781b Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 3 Jan 2012 00:36:23 +1100 +Subject: [PATCH 2/2] monitor: ensure we retry soon when 'remove' fails. + +If a 'remove' fails there is no certainty that another event will +happen soon, so make sure we retry soon anyway. + +Reported-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + mdadm.h | 1 + + monitor.c | 16 ++++++++++------ + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/mdadm.h b/mdadm.h +index 3bcd052..381ef86 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -867,6 +867,7 @@ struct supertype { + * external:/md0/12 + */ + int devcnt; ++ int retry_soon; + + struct mdinfo *devs; + +diff --git a/monitor.c b/monitor.c +index cfe4178..c987d10 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -212,6 +212,7 @@ static void signal_manager(void) + */ + + #define ARRAY_DIRTY 1 ++#define ARRAY_BUSY 2 + static int read_and_act(struct active_array *a) + { + unsigned long long sync_completed; +@@ -419,9 +420,9 @@ static int read_and_act(struct active_array *a) + if ((mdi->next_state & DS_REMOVE) && mdi->state_fd >= 0) { + int remove_result; + +- /* the kernel may not be able to immediately remove the +- * disk, we can simply wait until the next event to try +- * again. ++ /* The kernel may not be able to immediately remove the ++ * disk. In that case we wait a little while and ++ * try again. + */ + remove_result = write_attr("remove", mdi->state_fd); + if (remove_result > 0) { +@@ -429,7 +430,8 @@ static int read_and_act(struct active_array *a) + close(mdi->state_fd); + close(mdi->recovery_fd); + mdi->state_fd = -1; +- } ++ } else ++ ret |= ARRAY_BUSY; + } + if (mdi->next_state & DS_INSYNC) { + write_attr("+in_sync", mdi->state_fd); +@@ -597,7 +599,7 @@ static int wait_and_act(struct supertype *container, int nowait) + struct timespec ts; + ts.tv_sec = 24*3600; + ts.tv_nsec = 0; +- if (*aap == NULL) { ++ if (*aap == NULL || container->retry_soon) { + /* just waiting to get O_EXCL access */ + ts.tv_sec = 0; + ts.tv_nsec = 20000000ULL; +@@ -612,7 +614,7 @@ static int wait_and_act(struct supertype *container, int nowait) + #ifdef DEBUG + dprint_wake_reasons(&rfds); + #endif +- ++ container->retry_soon = 0; + } + + if (update_queue) { +@@ -653,6 +655,8 @@ static int wait_and_act(struct supertype *container, int nowait) + */ + if (sigterm && !(ret & ARRAY_DIRTY)) + a->container = NULL; /* stop touching this array */ ++ if (ret & ARRAY_BUSY) ++ container->retry_soon = 1; + } + } + +-- +1.7.8.2 + diff --git a/mdadm-3.2.3-monitor-make-return-from-read_and_act-more-symbolic.patch b/mdadm-3.2.3-monitor-make-return-from-read_and_act-more-symbolic.patch new file mode 100644 index 0000000..edb85cb --- /dev/null +++ b/mdadm-3.2.3-monitor-make-return-from-read_and_act-more-symbolic.patch @@ -0,0 +1,109 @@ +From 77b3ac8c6521d836dd3c6ef247c252293920fd52 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 3 Jan 2012 11:18:59 +1100 +Subject: [PATCH 1/2] monitor: make return from read_and_act more symbolic. + +Rather than just a number, use a named flag. + +This makes the code easier to understand and allows room for returning +more flags later. + +Signed-off-by: NeilBrown +--- + monitor.c | 20 ++++++++++---------- + 1 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/monitor.c b/monitor.c +index 29bde18..cfe4178 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -211,6 +211,7 @@ static void signal_manager(void) + * + */ + ++#define ARRAY_DIRTY 1 + static int read_and_act(struct active_array *a) + { + unsigned long long sync_completed; +@@ -218,7 +219,7 @@ static int read_and_act(struct active_array *a) + int check_reshape = 0; + int deactivate = 0; + struct mdinfo *mdi; +- int dirty = 0; ++ int ret = 0; + int count = 0; + + a->next_state = bad_word; +@@ -254,14 +255,14 @@ static int read_and_act(struct active_array *a) + if (a->curr_state == write_pending) { + a->container->ss->set_array_state(a, 0); + a->next_state = active; +- dirty = 1; ++ ret |= ARRAY_DIRTY; + } + if (a->curr_state == active_idle) { + /* Set array to 'clean' FIRST, then mark clean + * in the metadata + */ + a->next_state = clean; +- dirty = 1; ++ ret |= ARRAY_DIRTY; + } + if (a->curr_state == clean) { + a->container->ss->set_array_state(a, 1); +@@ -269,7 +270,7 @@ static int read_and_act(struct active_array *a) + if (a->curr_state == active || + a->curr_state == suspended || + a->curr_state == bad_word) +- dirty = 1; ++ ret |= ARRAY_DIRTY; + if (a->curr_state == readonly) { + /* Well, I'm ready to handle things. If readonly + * wasn't requested, transition to read-auto. +@@ -284,7 +285,7 @@ static int read_and_act(struct active_array *a) + a->next_state = read_auto; /* array is clean */ + else { + a->next_state = active; /* Now active for recovery etc */ +- dirty = 1; ++ ret |= ARRAY_DIRTY; + } + } + } +@@ -459,7 +460,7 @@ static int read_and_act(struct active_array *a) + if (deactivate) + a->container = NULL; + +- return dirty; ++ return ret; + } + + static struct mdinfo * +@@ -629,7 +630,6 @@ static int wait_and_act(struct supertype *container, int nowait) + rv = 0; + dirty_arrays = 0; + for (a = *aap; a ; a = a->next) { +- int is_dirty; + + if (a->replaces && !discard_this) { + struct active_array **ap; +@@ -644,14 +644,14 @@ static int wait_and_act(struct supertype *container, int nowait) + signal_manager(); + } + if (a->container && !a->to_remove) { +- is_dirty = read_and_act(a); ++ int ret = read_and_act(a); + rv |= 1; +- dirty_arrays += is_dirty; ++ dirty_arrays += !!(ret & ARRAY_DIRTY); + /* when terminating stop manipulating the array after it + * is clean, but make sure read_and_act() is given a + * chance to handle 'active_idle' + */ +- if (sigterm && !is_dirty) ++ if (sigterm && !(ret & ARRAY_DIRTY)) + a->container = NULL; /* stop touching this array */ + } + } +-- +1.7.8.2 + diff --git a/mdadm.spec b/mdadm.spec index 2d160af..b04c119 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,7 +1,7 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm Version: 3.2.3 -Release: 2%{?dist} +Release: 3%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.bz2 Source1: mdmonitor.init Source2: raid-check @@ -12,6 +12,8 @@ Source6: mdmonitor.service Source7: mdmonitor-takeover.service Source8: mdadm.conf Patch1: mdadm-3.2.3-Work-around-gcc-4.7-s-strict-aliasing-checks.patch +Patch2: mdadm-3.2.3-monitor-make-return-from-read_and_act-more-symbolic.patch +Patch3: mdadm-3.2.3-monitor-ensure-we-retry-soon-when-remove-fails.patch Patch19: mdadm-3.2.3-udev.patch Patch20: mdadm-2.5.2-static.patch URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ @@ -121,6 +123,11 @@ fi %{_initrddir}/* %changelog +* Thu Jan 12 2012 Jes Sorensen - 3.2.3-3 +- Fix case where we have to retry in case a remove fails due to an array + being busy +- Resolves: bz773337 (rawhide) bz773340 (f16) bz773341 (f15) + * Thu Jan 5 2012 Jes Sorensen - 3.2.3-2 - Workaround for gcc-4.7 strict aliasing breaking the build