aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-04-30 03:52:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:32 -0400
commit31a59e3425d32743738e043c1df1668e0f22bbab (patch)
tree0329549fd16aeedb767511e6a58df3ed84f463c7
parentd897dbf91490f26dccef3d7056ffd09eb83a15a5 (diff)
md: fix 'safemode' handling for external metadata.
'safemode' relates to marking an array as 'clean' if there has been no write traffic for a while (a couple of seconds), to reduce the chance of the array being found dirty on reboot. ->safemode is set to '1' when there have been no write for a while, and it gets set to '0' when the superblock is updates with the 'clean' flag set. This requires a few fixes for 'external' metadata: - When an array is set to 'clean' via sysfs, 'safemode' must be cleared. - when we write to an array that has 'safemode' set (there must have been some delay in updating the metadata), we need to clear safemode. - Don't try to update external metadata in md_check_recovery for safemode transitions - it won't work. Also, don't try to support "immediate safe mode" (safemode==2) for external metadata, it cannot really work (the safemode timeout can be set very low if this is really needed). Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/md/md.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 7a44c81ae3cd..ff9fef389608 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2615,6 +2615,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
2615 if (atomic_read(&mddev->writes_pending) == 0) { 2615 if (atomic_read(&mddev->writes_pending) == 0) {
2616 if (mddev->in_sync == 0) { 2616 if (mddev->in_sync == 0) {
2617 mddev->in_sync = 1; 2617 mddev->in_sync = 1;
2618 if (mddev->safemode == 1)
2619 mddev->safemode = 0;
2618 if (mddev->persistent) 2620 if (mddev->persistent)
2619 set_bit(MD_CHANGE_CLEAN, 2621 set_bit(MD_CHANGE_CLEAN,
2620 &mddev->flags); 2622 &mddev->flags);
@@ -5392,6 +5394,8 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
5392 md_wakeup_thread(mddev->sync_thread); 5394 md_wakeup_thread(mddev->sync_thread);
5393 } 5395 }
5394 atomic_inc(&mddev->writes_pending); 5396 atomic_inc(&mddev->writes_pending);
5397 if (mddev->safemode == 1)
5398 mddev->safemode = 0;
5395 if (mddev->in_sync) { 5399 if (mddev->in_sync) {
5396 spin_lock_irq(&mddev->write_lock); 5400 spin_lock_irq(&mddev->write_lock);
5397 if (mddev->in_sync) { 5401 if (mddev->in_sync) {
@@ -5816,7 +5820,7 @@ void md_check_recovery(mddev_t *mddev)
5816 return; 5820 return;
5817 5821
5818 if (signal_pending(current)) { 5822 if (signal_pending(current)) {
5819 if (mddev->pers->sync_request) { 5823 if (mddev->pers->sync_request && !mddev->external) {
5820 printk(KERN_INFO "md: %s in immediate safe mode\n", 5824 printk(KERN_INFO "md: %s in immediate safe mode\n",
5821 mdname(mddev)); 5825 mdname(mddev));
5822 mddev->safemode = 2; 5826 mddev->safemode = 2;
@@ -5828,7 +5832,7 @@ void md_check_recovery(mddev_t *mddev)
5828 (mddev->flags && !mddev->external) || 5832 (mddev->flags && !mddev->external) ||
5829 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || 5833 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
5830 test_bit(MD_RECOVERY_DONE, &mddev->recovery) || 5834 test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
5831 (mddev->safemode == 1) || 5835 (mddev->external == 0 && mddev->safemode == 1) ||
5832 (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending) 5836 (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
5833 && !mddev->in_sync && mddev->recovery_cp == MaxSector) 5837 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
5834 )) 5838 ))
@@ -5837,16 +5841,20 @@ void md_check_recovery(mddev_t *mddev)
5837 if (mddev_trylock(mddev)) { 5841 if (mddev_trylock(mddev)) {
5838 int spares = 0; 5842 int spares = 0;
5839 5843
5840 spin_lock_irq(&mddev->write_lock); 5844 if (!mddev->external) {
5841 if (mddev->safemode && !atomic_read(&mddev->writes_pending) && 5845 spin_lock_irq(&mddev->write_lock);
5842 !mddev->in_sync && mddev->recovery_cp == MaxSector) { 5846 if (mddev->safemode &&
5843 mddev->in_sync = 1; 5847 !atomic_read(&mddev->writes_pending) &&
5844 if (mddev->persistent) 5848 !mddev->in_sync &&
5845 set_bit(MD_CHANGE_CLEAN, &mddev->flags); 5849 mddev->recovery_cp == MaxSector) {
5850 mddev->in_sync = 1;
5851 if (mddev->persistent)
5852 set_bit(MD_CHANGE_CLEAN, &mddev->flags);
5853 }
5854 if (mddev->safemode == 1)
5855 mddev->safemode = 0;
5856 spin_unlock_irq(&mddev->write_lock);
5846 } 5857 }
5847 if (mddev->safemode == 1)
5848 mddev->safemode = 0;
5849 spin_unlock_irq(&mddev->write_lock);
5850 5858
5851 if (mddev->flags) 5859 if (mddev->flags)
5852 md_update_sb(mddev, 0); 5860 md_update_sb(mddev, 0);