aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c73
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;
1256repeat: 1258repeat:
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
3181void 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 */
3203int 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
3196void md_write_end(mddev_t *mddev) 3225void 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 */