summaryrefslogtreecommitdiffstats
path: root/super-intel.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-09-28 21:12:06 +0200
committerDan Williams <dan.j.williams@intel.com>2008-10-15 23:15:51 +0200
commitf8f603f1337d58e73e0ce384322d6ee0668549ea (patch)
treefb1af75cf380de86c9e36d4c02371e1ce534f370 /super-intel.c
parentExtend --wait-clean to checkpoint resync (diff)
downloadmdadm-f8f603f1337d58e73e0ce384322d6ee0668549ea.tar.xz
mdadm-f8f603f1337d58e73e0ce384322d6ee0668549ea.zip
imsm: enable checkpointing of migration (resync/rebuild)
When the array is shutdown, or when mdadm --wait-clean is called, any active resync process will be idled allowing mdmon to record the current resync position. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'super-intel.c')
-rw-r--r--super-intel.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/super-intel.c b/super-intel.c
index 7e1f986b..80427e4a 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -77,7 +77,8 @@ struct imsm_map {
} __attribute__ ((packed));
struct imsm_vol {
- __u32 reserved[2];
+ __u32 curr_migr_unit;
+ __u32 reserved;
__u8 migr_state; /* Normal or Migrating */
__u8 migr_type; /* Initializing, Rebuilding, ... */
__u8 dirty;
@@ -751,9 +752,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
info->component_size = __le32_to_cpu(map->blocks_per_member);
memset(info->uuid, 0, sizeof(info->uuid));
- if (map->map_state == IMSM_T_STATE_UNINITIALIZED ||
- dev->vol.dirty || dev->vol.migr_state)
+ if (map->map_state == IMSM_T_STATE_UNINITIALIZED || dev->vol.dirty)
info->resync_start = 0;
+ else if (dev->vol.migr_state)
+ info->resync_start = __le32_to_cpu(dev->vol.curr_migr_unit);
else
info->resync_start = ~0ULL;
@@ -1127,11 +1129,21 @@ static void migrate(struct imsm_dev *dev, __u8 to_state, int rebuild_resync)
dev->vol.migr_state = 1;
dev->vol.migr_type = rebuild_resync;
+ dev->vol.curr_migr_unit = 0;
dest = get_imsm_map(dev, 1);
memcpy(dest, src, sizeof_imsm_map(src));
src->map_state = to_state;
}
+
+static void end_migration(struct imsm_dev *dev, __u8 map_state)
+{
+ struct imsm_map *map = get_imsm_map(dev, 0);
+
+ dev->vol.migr_state = 0;
+ dev->vol.curr_migr_unit = 0;
+ map->map_state = map_state;
+}
#endif
static int parse_raid_devices(struct intel_super *super)
@@ -1602,6 +1614,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
vol->migr_state = 0;
vol->migr_type = 0;
vol->dirty = 0;
+ vol->curr_migr_unit = 0;
for (i = 0; i < idx; i++) {
struct imsm_dev *prev = get_imsm_dev(super, i);
struct imsm_map *pmap = get_imsm_map(prev, 0);
@@ -2485,8 +2498,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
*/
if (is_resyncing(dev)) {
dprintf("imsm: mark resync done\n");
- dev->vol.migr_state = 0;
- map->map_state = map_state;
+ end_migration(dev, map_state);
super->updates_pending++;
}
} else if (!is_resyncing(dev) && !failed) {
@@ -2498,6 +2510,14 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
super->updates_pending++;
}
+ /* check if we can update the migration checkpoint */
+ if (dev->vol.migr_state &&
+ __le32_to_cpu(dev->vol.curr_migr_unit) != a->resync_start) {
+ dprintf("imsm: checkpoint migration (%llu)\n", a->resync_start);
+ dev->vol.curr_migr_unit = __cpu_to_le32(a->resync_start);
+ super->updates_pending++;
+ }
+
/* mark dirty / clean */
if (dev->vol.dirty != !consistent) {
dprintf("imsm: mark '%s' (%llu)\n",
@@ -2557,8 +2577,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
/* check if recovery complete, newly degraded, or failed */
if (map_state == IMSM_T_STATE_NORMAL && is_rebuilding(dev)) {
- map->map_state = map_state;
- dev->vol.migr_state = 0;
+ end_migration(dev, map_state);
super->updates_pending++;
} else if (map_state == IMSM_T_STATE_DEGRADED &&
map->map_state != map_state &&
@@ -2569,8 +2588,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
} else if (map_state == IMSM_T_STATE_FAILED &&
map->map_state != map_state) {
dprintf("imsm: mark failed\n");
- dev->vol.migr_state = 0;
- map->map_state = map_state;
+ end_migration(dev, map_state);
super->updates_pending++;
}
}