diff options
author | NeilBrown <neilb@suse.de> | 2005-11-09 00:39:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:37 -0500 |
commit | 24dd469d728dae07f40c5d79ea6dedd38cdf1a30 (patch) | |
tree | 3975aaeaa6c1cd77a2d4b06184ad3bd0175a44a5 | |
parent | 3f294f4fb6f2ba887b717674da26c21f3d57f3fc (diff) |
[PATCH] md: allow a manual resync with md
You can trigger a 'check' with
echo check > /sys/block/mdX/md/scan_mode
or a check-and-repair errors with
echo repair > /sys/block/mdX/md/scan_mode
and read the current state from the same file.
Note: personalities need to know the different between 'check' and 'repair',
but don't yet. Until they do, 'check' will be the same as 'repair' and will
just do a normal resync pass.
Signed-off-by: Neil Brown <neilb@suse.de>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/md/md.c | 77 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 4 |
2 files changed, 72 insertions, 9 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 74520b50c307..37400873b879 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1714,9 +1714,60 @@ static struct md_sysfs_entry md_raid_disks = { | |||
1714 | .show = md_show_rdisks, | 1714 | .show = md_show_rdisks, |
1715 | }; | 1715 | }; |
1716 | 1716 | ||
1717 | static ssize_t | ||
1718 | md_show_scan(mddev_t *mddev, char *page) | ||
1719 | { | ||
1720 | char *type = "none"; | ||
1721 | if (mddev->recovery & | ||
1722 | ((1<<MD_RECOVERY_RUNNING) || (1<<MD_RECOVERY_NEEDED))) { | ||
1723 | if (mddev->recovery & (1<<MD_RECOVERY_SYNC)) { | ||
1724 | if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) | ||
1725 | type = "resync"; | ||
1726 | else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) | ||
1727 | type = "check"; | ||
1728 | else | ||
1729 | type = "repair"; | ||
1730 | } else | ||
1731 | type = "recover"; | ||
1732 | } | ||
1733 | return sprintf(page, "%s\n", type); | ||
1734 | } | ||
1735 | |||
1736 | static ssize_t | ||
1737 | md_store_scan(mddev_t *mddev, const char *page, size_t len) | ||
1738 | { | ||
1739 | int canscan=0; | ||
1740 | if (mddev->recovery & | ||
1741 | ((1<<MD_RECOVERY_RUNNING) || (1<<MD_RECOVERY_NEEDED))) | ||
1742 | return -EBUSY; | ||
1743 | down(&mddev->reconfig_sem); | ||
1744 | if (mddev->pers && mddev->pers->sync_request) | ||
1745 | canscan=1; | ||
1746 | up(&mddev->reconfig_sem); | ||
1747 | if (!canscan) | ||
1748 | return -EINVAL; | ||
1749 | |||
1750 | if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0) | ||
1751 | set_bit(MD_RECOVERY_CHECK, &mddev->recovery); | ||
1752 | else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0) | ||
1753 | return -EINVAL; | ||
1754 | set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); | ||
1755 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
1756 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
1757 | md_wakeup_thread(mddev->thread); | ||
1758 | return len; | ||
1759 | } | ||
1760 | |||
1761 | static struct md_sysfs_entry md_scan_mode = { | ||
1762 | .attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR }, | ||
1763 | .show = md_show_scan, | ||
1764 | .store = md_store_scan, | ||
1765 | }; | ||
1766 | |||
1717 | static struct attribute *md_default_attrs[] = { | 1767 | static struct attribute *md_default_attrs[] = { |
1718 | &md_level.attr, | 1768 | &md_level.attr, |
1719 | &md_raid_disks.attr, | 1769 | &md_raid_disks.attr, |
1770 | &md_scan_mode.attr, | ||
1720 | NULL, | 1771 | NULL, |
1721 | }; | 1772 | }; |
1722 | 1773 | ||
@@ -3855,7 +3906,8 @@ static void md_do_sync(mddev_t *mddev) | |||
3855 | 3906 | ||
3856 | is_mddev_idle(mddev); /* this also initializes IO event counters */ | 3907 | is_mddev_idle(mddev); /* this also initializes IO event counters */ |
3857 | /* we don't use the checkpoint if there's a bitmap */ | 3908 | /* we don't use the checkpoint if there's a bitmap */ |
3858 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap) | 3909 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap |
3910 | && ! test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) | ||
3859 | j = mddev->recovery_cp; | 3911 | j = mddev->recovery_cp; |
3860 | else | 3912 | else |
3861 | j = 0; | 3913 | j = 0; |
@@ -4093,9 +4145,13 @@ void md_check_recovery(mddev_t *mddev) | |||
4093 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 4145 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
4094 | goto unlock; | 4146 | goto unlock; |
4095 | } | 4147 | } |
4096 | if (mddev->recovery) | 4148 | /* Clear some bits that don't mean anything, but |
4097 | /* probably just the RECOVERY_NEEDED flag */ | 4149 | * might be left set |
4098 | mddev->recovery = 0; | 4150 | */ |
4151 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
4152 | clear_bit(MD_RECOVERY_ERR, &mddev->recovery); | ||
4153 | clear_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
4154 | clear_bit(MD_RECOVERY_DONE, &mddev->recovery); | ||
4099 | 4155 | ||
4100 | /* no recovery is running. | 4156 | /* no recovery is running. |
4101 | * remove any failed drives, then | 4157 | * remove any failed drives, then |
@@ -4129,14 +4185,17 @@ void md_check_recovery(mddev_t *mddev) | |||
4129 | } | 4185 | } |
4130 | } | 4186 | } |
4131 | 4187 | ||
4132 | if (!spares && (mddev->recovery_cp == MaxSector )) { | 4188 | if (spares) { |
4133 | /* nothing we can do ... */ | 4189 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
4190 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | ||
4191 | } else if (mddev->recovery_cp < MaxSector) { | ||
4192 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
4193 | } else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) | ||
4194 | /* nothing to be done ... */ | ||
4134 | goto unlock; | 4195 | goto unlock; |
4135 | } | 4196 | |
4136 | if (mddev->pers->sync_request) { | 4197 | if (mddev->pers->sync_request) { |
4137 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | 4198 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); |
4138 | if (!spares) | ||
4139 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
4140 | if (spares && mddev->bitmap && ! mddev->bitmap->file) { | 4199 | if (spares && mddev->bitmap && ! mddev->bitmap->file) { |
4141 | /* We are adding a device or devices to an array | 4200 | /* We are adding a device or devices to an array |
4142 | * which has the bitmap stored on all devices. | 4201 | * which has the bitmap stored on all devices. |
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index d1dad32ebe07..efd04dca0abd 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
@@ -182,6 +182,8 @@ struct mddev_s | |||
182 | * ERR: and IO error was detected - abort the resync/recovery | 182 | * ERR: and IO error was detected - abort the resync/recovery |
183 | * INTR: someone requested a (clean) early abort. | 183 | * INTR: someone requested a (clean) early abort. |
184 | * DONE: thread is done and is waiting to be reaped | 184 | * DONE: thread is done and is waiting to be reaped |
185 | * REQUEST: user-space has requested a sync (used with SYNC) | ||
186 | * CHECK: user-space request for for check-only, no repair | ||
185 | */ | 187 | */ |
186 | #define MD_RECOVERY_RUNNING 0 | 188 | #define MD_RECOVERY_RUNNING 0 |
187 | #define MD_RECOVERY_SYNC 1 | 189 | #define MD_RECOVERY_SYNC 1 |
@@ -189,6 +191,8 @@ struct mddev_s | |||
189 | #define MD_RECOVERY_INTR 3 | 191 | #define MD_RECOVERY_INTR 3 |
190 | #define MD_RECOVERY_DONE 4 | 192 | #define MD_RECOVERY_DONE 4 |
191 | #define MD_RECOVERY_NEEDED 5 | 193 | #define MD_RECOVERY_NEEDED 5 |
194 | #define MD_RECOVERY_REQUESTED 6 | ||
195 | #define MD_RECOVERY_CHECK 7 | ||
192 | unsigned long recovery; | 196 | unsigned long recovery; |
193 | 197 | ||
194 | int in_sync; /* know to not need resync */ | 198 | int in_sync; /* know to not need resync */ |