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)) { |
