diff options
author | NeilBrown <neilb@suse.de> | 2008-04-30 03:52:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:32 -0400 |
commit | 31a59e3425d32743738e043c1df1668e0f22bbab (patch) | |
tree | 0329549fd16aeedb767511e6a58df3ed84f463c7 | |
parent | d897dbf91490f26dccef3d7056ffd09eb83a15a5 (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.c | 30 |
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); |