diff options
-rw-r--r-- | drivers/md/md-cluster.c | 111 | ||||
-rw-r--r-- | drivers/md/md-cluster.h | 1 | ||||
-rw-r--r-- | drivers/md/md.c | 8 |
3 files changed, 120 insertions, 0 deletions
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 75c6602f4c75..b59c3a0ebd08 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c | |||
@@ -27,6 +27,18 @@ struct dlm_lock_resource { | |||
27 | struct mddev *mddev; /* pointing back to mddev. */ | 27 | struct mddev *mddev; /* pointing back to mddev. */ |
28 | }; | 28 | }; |
29 | 29 | ||
30 | struct suspend_info { | ||
31 | int slot; | ||
32 | sector_t lo; | ||
33 | sector_t hi; | ||
34 | struct list_head list; | ||
35 | }; | ||
36 | |||
37 | struct resync_info { | ||
38 | __le64 lo; | ||
39 | __le64 hi; | ||
40 | }; | ||
41 | |||
30 | struct md_cluster_info { | 42 | struct md_cluster_info { |
31 | /* dlm lock space and resources for clustered raid. */ | 43 | /* dlm lock space and resources for clustered raid. */ |
32 | dlm_lockspace_t *lockspace; | 44 | dlm_lockspace_t *lockspace; |
@@ -35,6 +47,8 @@ struct md_cluster_info { | |||
35 | struct dlm_lock_resource *sb_lock; | 47 | struct dlm_lock_resource *sb_lock; |
36 | struct mutex sb_mutex; | 48 | struct mutex sb_mutex; |
37 | struct dlm_lock_resource *bitmap_lockres; | 49 | struct dlm_lock_resource *bitmap_lockres; |
50 | struct list_head suspend_list; | ||
51 | spinlock_t suspend_lock; | ||
38 | }; | 52 | }; |
39 | 53 | ||
40 | static void sync_ast(void *arg) | 54 | static void sync_ast(void *arg) |
@@ -139,6 +153,37 @@ static char *pretty_uuid(char *dest, char *src) | |||
139 | return dest; | 153 | return dest; |
140 | } | 154 | } |
141 | 155 | ||
156 | static void add_resync_info(struct mddev *mddev, struct dlm_lock_resource *lockres, | ||
157 | sector_t lo, sector_t hi) | ||
158 | { | ||
159 | struct resync_info *ri; | ||
160 | |||
161 | ri = (struct resync_info *)lockres->lksb.sb_lvbptr; | ||
162 | ri->lo = cpu_to_le64(lo); | ||
163 | ri->hi = cpu_to_le64(hi); | ||
164 | } | ||
165 | |||
166 | static struct suspend_info *read_resync_info(struct mddev *mddev, struct dlm_lock_resource *lockres) | ||
167 | { | ||
168 | struct resync_info ri; | ||
169 | struct suspend_info *s = NULL; | ||
170 | sector_t hi = 0; | ||
171 | |||
172 | dlm_lock_sync(lockres, DLM_LOCK_CR); | ||
173 | memcpy(&ri, lockres->lksb.sb_lvbptr, sizeof(struct resync_info)); | ||
174 | hi = le64_to_cpu(ri.hi); | ||
175 | if (ri.hi > 0) { | ||
176 | s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL); | ||
177 | if (!s) | ||
178 | goto out; | ||
179 | s->hi = hi; | ||
180 | s->lo = le64_to_cpu(ri.lo); | ||
181 | } | ||
182 | dlm_unlock_sync(lockres); | ||
183 | out: | ||
184 | return s; | ||
185 | } | ||
186 | |||
142 | static void recover_prep(void *arg) | 187 | static void recover_prep(void *arg) |
143 | { | 188 | { |
144 | } | 189 | } |
@@ -171,6 +216,53 @@ static const struct dlm_lockspace_ops md_ls_ops = { | |||
171 | .recover_done = recover_done, | 216 | .recover_done = recover_done, |
172 | }; | 217 | }; |
173 | 218 | ||
219 | static int gather_all_resync_info(struct mddev *mddev, int total_slots) | ||
220 | { | ||
221 | struct md_cluster_info *cinfo = mddev->cluster_info; | ||
222 | int i, ret = 0; | ||
223 | struct dlm_lock_resource *bm_lockres; | ||
224 | struct suspend_info *s; | ||
225 | char str[64]; | ||
226 | |||
227 | |||
228 | for (i = 0; i < total_slots; i++) { | ||
229 | memset(str, '\0', 64); | ||
230 | snprintf(str, 64, "bitmap%04d", i); | ||
231 | bm_lockres = lockres_init(mddev, str, NULL, 1); | ||
232 | if (!bm_lockres) | ||
233 | return -ENOMEM; | ||
234 | if (i == (cinfo->slot_number - 1)) | ||
235 | continue; | ||
236 | |||
237 | bm_lockres->flags |= DLM_LKF_NOQUEUE; | ||
238 | ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); | ||
239 | if (ret == -EAGAIN) { | ||
240 | memset(bm_lockres->lksb.sb_lvbptr, '\0', LVB_SIZE); | ||
241 | s = read_resync_info(mddev, bm_lockres); | ||
242 | if (s) { | ||
243 | pr_info("%s:%d Resync[%llu..%llu] in progress on %d\n", | ||
244 | __func__, __LINE__, | ||
245 | (unsigned long long) s->lo, | ||
246 | (unsigned long long) s->hi, i); | ||
247 | spin_lock_irq(&cinfo->suspend_lock); | ||
248 | s->slot = i; | ||
249 | list_add(&s->list, &cinfo->suspend_list); | ||
250 | spin_unlock_irq(&cinfo->suspend_lock); | ||
251 | } | ||
252 | ret = 0; | ||
253 | lockres_free(bm_lockres); | ||
254 | continue; | ||
255 | } | ||
256 | if (ret) | ||
257 | goto out; | ||
258 | /* TODO: Read the disk bitmap sb and check if it needs recovery */ | ||
259 | dlm_unlock_sync(bm_lockres); | ||
260 | lockres_free(bm_lockres); | ||
261 | } | ||
262 | out: | ||
263 | return ret; | ||
264 | } | ||
265 | |||
174 | static int join(struct mddev *mddev, int nodes) | 266 | static int join(struct mddev *mddev, int nodes) |
175 | { | 267 | { |
176 | struct md_cluster_info *cinfo; | 268 | struct md_cluster_info *cinfo; |
@@ -221,8 +313,17 @@ static int join(struct mddev *mddev, int nodes) | |||
221 | goto err; | 313 | goto err; |
222 | } | 314 | } |
223 | 315 | ||
316 | INIT_LIST_HEAD(&cinfo->suspend_list); | ||
317 | spin_lock_init(&cinfo->suspend_lock); | ||
318 | |||
319 | ret = gather_all_resync_info(mddev, nodes); | ||
320 | if (ret) | ||
321 | goto err; | ||
322 | |||
224 | return 0; | 323 | return 0; |
225 | err: | 324 | err: |
325 | lockres_free(cinfo->bitmap_lockres); | ||
326 | lockres_free(cinfo->sb_lock); | ||
226 | if (cinfo->lockspace) | 327 | if (cinfo->lockspace) |
227 | dlm_release_lockspace(cinfo->lockspace, 2); | 328 | dlm_release_lockspace(cinfo->lockspace, 2); |
228 | mddev->cluster_info = NULL; | 329 | mddev->cluster_info = NULL; |
@@ -254,10 +355,20 @@ static int slot_number(struct mddev *mddev) | |||
254 | return cinfo->slot_number - 1; | 355 | return cinfo->slot_number - 1; |
255 | } | 356 | } |
256 | 357 | ||
358 | static void resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi) | ||
359 | { | ||
360 | struct md_cluster_info *cinfo = mddev->cluster_info; | ||
361 | |||
362 | add_resync_info(mddev, cinfo->bitmap_lockres, lo, hi); | ||
363 | /* Re-acquire the lock to refresh LVB */ | ||
364 | dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW); | ||
365 | } | ||
366 | |||
257 | static struct md_cluster_operations cluster_ops = { | 367 | static struct md_cluster_operations cluster_ops = { |
258 | .join = join, | 368 | .join = join, |
259 | .leave = leave, | 369 | .leave = leave, |
260 | .slot_number = slot_number, | 370 | .slot_number = slot_number, |
371 | .resync_info_update = resync_info_update, | ||
261 | }; | 372 | }; |
262 | 373 | ||
263 | static int __init cluster_init(void) | 374 | static int __init cluster_init(void) |
diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h index 52a21e0d6dbc..51a24df15b64 100644 --- a/drivers/md/md-cluster.h +++ b/drivers/md/md-cluster.h | |||
@@ -11,6 +11,7 @@ struct md_cluster_operations { | |||
11 | int (*join)(struct mddev *mddev, int nodes); | 11 | int (*join)(struct mddev *mddev, int nodes); |
12 | int (*leave)(struct mddev *mddev); | 12 | int (*leave)(struct mddev *mddev); |
13 | int (*slot_number)(struct mddev *mddev); | 13 | int (*slot_number)(struct mddev *mddev); |
14 | void (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi); | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | #endif /* _MD_CLUSTER_H */ | 17 | #endif /* _MD_CLUSTER_H */ |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 8f310d98f082..71f655015385 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -7626,6 +7626,9 @@ void md_do_sync(struct md_thread *thread) | |||
7626 | md_new_event(mddev); | 7626 | md_new_event(mddev); |
7627 | update_time = jiffies; | 7627 | update_time = jiffies; |
7628 | 7628 | ||
7629 | if (mddev_is_clustered(mddev)) | ||
7630 | md_cluster_ops->resync_info_update(mddev, j, max_sectors); | ||
7631 | |||
7629 | blk_start_plug(&plug); | 7632 | blk_start_plug(&plug); |
7630 | while (j < max_sectors) { | 7633 | while (j < max_sectors) { |
7631 | sector_t sectors; | 7634 | sector_t sectors; |
@@ -7686,6 +7689,8 @@ void md_do_sync(struct md_thread *thread) | |||
7686 | j += sectors; | 7689 | j += sectors; |
7687 | if (j > 2) | 7690 | if (j > 2) |
7688 | mddev->curr_resync = j; | 7691 | mddev->curr_resync = j; |
7692 | if (mddev_is_clustered(mddev)) | ||
7693 | md_cluster_ops->resync_info_update(mddev, j, max_sectors); | ||
7689 | mddev->curr_mark_cnt = io_sectors; | 7694 | mddev->curr_mark_cnt = io_sectors; |
7690 | if (last_check == 0) | 7695 | if (last_check == 0) |
7691 | /* this is the earliest that rebuild will be | 7696 | /* this is the earliest that rebuild will be |
@@ -7746,6 +7751,9 @@ void md_do_sync(struct md_thread *thread) | |||
7746 | /* tell personality that we are finished */ | 7751 | /* tell personality that we are finished */ |
7747 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); | 7752 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); |
7748 | 7753 | ||
7754 | if (mddev_is_clustered(mddev)) | ||
7755 | md_cluster_ops->resync_info_update(mddev, 0, 0); | ||
7756 | |||
7749 | if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && | 7757 | if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && |
7750 | mddev->curr_resync > 2) { | 7758 | mddev->curr_resync > 2) { |
7751 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { | 7759 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { |