diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 73 |
1 files changed, 59 insertions, 14 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index c842e34d850e..177d2a7d7cea 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -218,6 +218,8 @@ static mddev_t * mddev_find(dev_t unit) | |||
218 | INIT_LIST_HEAD(&new->all_mddevs); | 218 | INIT_LIST_HEAD(&new->all_mddevs); |
219 | init_timer(&new->safemode_timer); | 219 | init_timer(&new->safemode_timer); |
220 | atomic_set(&new->active, 1); | 220 | atomic_set(&new->active, 1); |
221 | bio_list_init(&new->write_list); | ||
222 | spin_lock_init(&new->write_lock); | ||
221 | 223 | ||
222 | new->queue = blk_alloc_queue(GFP_KERNEL); | 224 | new->queue = blk_alloc_queue(GFP_KERNEL); |
223 | if (!new->queue) { | 225 | if (!new->queue) { |
@@ -1251,9 +1253,11 @@ static void md_update_sb(mddev_t * mddev) | |||
1251 | int err, count = 100; | 1253 | int err, count = 100; |
1252 | struct list_head *tmp; | 1254 | struct list_head *tmp; |
1253 | mdk_rdev_t *rdev; | 1255 | mdk_rdev_t *rdev; |
1256 | int sync_req; | ||
1254 | 1257 | ||
1255 | mddev->sb_dirty = 0; | ||
1256 | repeat: | 1258 | repeat: |
1259 | spin_lock(&mddev->write_lock); | ||
1260 | sync_req = mddev->in_sync; | ||
1257 | mddev->utime = get_seconds(); | 1261 | mddev->utime = get_seconds(); |
1258 | mddev->events ++; | 1262 | mddev->events ++; |
1259 | 1263 | ||
@@ -1272,8 +1276,12 @@ repeat: | |||
1272 | * do not write anything to disk if using | 1276 | * do not write anything to disk if using |
1273 | * nonpersistent superblocks | 1277 | * nonpersistent superblocks |
1274 | */ | 1278 | */ |
1275 | if (!mddev->persistent) | 1279 | if (!mddev->persistent) { |
1280 | mddev->sb_dirty = 0; | ||
1281 | spin_unlock(&mddev->write_lock); | ||
1276 | return; | 1282 | return; |
1283 | } | ||
1284 | spin_unlock(&mddev->write_lock); | ||
1277 | 1285 | ||
1278 | dprintk(KERN_INFO | 1286 | dprintk(KERN_INFO |
1279 | "md: updating %s RAID superblock on device (in sync %d)\n", | 1287 | "md: updating %s RAID superblock on device (in sync %d)\n", |
@@ -1304,6 +1312,15 @@ repeat: | |||
1304 | printk(KERN_ERR \ | 1312 | printk(KERN_ERR \ |
1305 | "md: excessive errors occurred during superblock update, exiting\n"); | 1313 | "md: excessive errors occurred during superblock update, exiting\n"); |
1306 | } | 1314 | } |
1315 | spin_lock(&mddev->write_lock); | ||
1316 | if (mddev->in_sync != sync_req) { | ||
1317 | /* have to write it out again */ | ||
1318 | spin_unlock(&mddev->write_lock); | ||
1319 | goto repeat; | ||
1320 | } | ||
1321 | mddev->sb_dirty = 0; | ||
1322 | spin_unlock(&mddev->write_lock); | ||
1323 | |||
1307 | } | 1324 | } |
1308 | 1325 | ||
1309 | /* | 1326 | /* |
@@ -3178,19 +3195,31 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok) | |||
3178 | } | 3195 | } |
3179 | 3196 | ||
3180 | 3197 | ||
3181 | void md_write_start(mddev_t *mddev) | 3198 | /* md_write_start(mddev, bi) |
3199 | * If we need to update some array metadata (e.g. 'active' flag | ||
3200 | * in superblock) before writing, queue bi for later writing | ||
3201 | * and return 0, else return 1 and it will be written now | ||
3202 | */ | ||
3203 | int md_write_start(mddev_t *mddev, struct bio *bi) | ||
3182 | { | 3204 | { |
3183 | if (!atomic_read(&mddev->writes_pending)) { | 3205 | if (bio_data_dir(bi) != WRITE) |
3184 | mddev_lock_uninterruptible(mddev); | 3206 | return 1; |
3185 | if (mddev->in_sync) { | 3207 | |
3186 | mddev->in_sync = 0; | 3208 | atomic_inc(&mddev->writes_pending); |
3187 | del_timer(&mddev->safemode_timer); | 3209 | spin_lock(&mddev->write_lock); |
3188 | md_update_sb(mddev); | 3210 | if (mddev->in_sync == 0 && mddev->sb_dirty == 0) { |
3189 | } | 3211 | spin_unlock(&mddev->write_lock); |
3190 | atomic_inc(&mddev->writes_pending); | 3212 | return 1; |
3191 | mddev_unlock(mddev); | 3213 | } |
3192 | } else | 3214 | bio_list_add(&mddev->write_list, bi); |
3193 | atomic_inc(&mddev->writes_pending); | 3215 | |
3216 | if (mddev->in_sync) { | ||
3217 | mddev->in_sync = 0; | ||
3218 | mddev->sb_dirty = 1; | ||
3219 | } | ||
3220 | spin_unlock(&mddev->write_lock); | ||
3221 | md_wakeup_thread(mddev->thread); | ||
3222 | return 0; | ||
3194 | } | 3223 | } |
3195 | 3224 | ||
3196 | void md_write_end(mddev_t *mddev) | 3225 | void md_write_end(mddev_t *mddev) |
@@ -3472,6 +3501,7 @@ void md_check_recovery(mddev_t *mddev) | |||
3472 | mddev->sb_dirty || | 3501 | mddev->sb_dirty || |
3473 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || | 3502 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || |
3474 | test_bit(MD_RECOVERY_DONE, &mddev->recovery) || | 3503 | test_bit(MD_RECOVERY_DONE, &mddev->recovery) || |
3504 | mddev->write_list.head || | ||
3475 | (mddev->safemode == 1) || | 3505 | (mddev->safemode == 1) || |
3476 | (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending) | 3506 | (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending) |
3477 | && !mddev->in_sync && mddev->recovery_cp == MaxSector) | 3507 | && !mddev->in_sync && mddev->recovery_cp == MaxSector) |
@@ -3480,7 +3510,9 @@ void md_check_recovery(mddev_t *mddev) | |||
3480 | 3510 | ||
3481 | if (mddev_trylock(mddev)==0) { | 3511 | if (mddev_trylock(mddev)==0) { |
3482 | int spares =0; | 3512 | int spares =0; |
3513 | struct bio *blist; | ||
3483 | 3514 | ||
3515 | spin_lock(&mddev->write_lock); | ||
3484 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && | 3516 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && |
3485 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { | 3517 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { |
3486 | mddev->in_sync = 1; | 3518 | mddev->in_sync = 1; |
@@ -3488,9 +3520,22 @@ void md_check_recovery(mddev_t *mddev) | |||
3488 | } | 3520 | } |
3489 | if (mddev->safemode == 1) | 3521 | if (mddev->safemode == 1) |
3490 | mddev->safemode = 0; | 3522 | mddev->safemode = 0; |
3523 | blist = bio_list_get(&mddev->write_list); | ||
3524 | spin_unlock(&mddev->write_lock); | ||
3491 | 3525 | ||
3492 | if (mddev->sb_dirty) | 3526 | if (mddev->sb_dirty) |
3493 | md_update_sb(mddev); | 3527 | md_update_sb(mddev); |
3528 | |||
3529 | while (blist) { | ||
3530 | struct bio *b = blist; | ||
3531 | blist = blist->bi_next; | ||
3532 | b->bi_next = NULL; | ||
3533 | generic_make_request(b); | ||
3534 | /* we already counted this, so need to un-count */ | ||
3535 | md_write_end(mddev); | ||
3536 | } | ||
3537 | |||
3538 | |||
3494 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && | 3539 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && |
3495 | !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) { | 3540 | !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) { |
3496 | /* resync/recovery still happening */ | 3541 | /* resync/recovery still happening */ |