diff options
| -rw-r--r-- | drivers/md/md.c | 36 | ||||
| -rw-r--r-- | drivers/md/md.h | 8 |
2 files changed, 25 insertions, 19 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 709755fb6d7b..17e7fd776034 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -397,12 +397,12 @@ static void md_submit_flush_data(struct work_struct *ws) | |||
| 397 | 397 | ||
| 398 | void md_flush_request(struct mddev *mddev, struct bio *bio) | 398 | void md_flush_request(struct mddev *mddev, struct bio *bio) |
| 399 | { | 399 | { |
| 400 | spin_lock_irq(&mddev->write_lock); | 400 | spin_lock_irq(&mddev->lock); |
| 401 | wait_event_lock_irq(mddev->sb_wait, | 401 | wait_event_lock_irq(mddev->sb_wait, |
| 402 | !mddev->flush_bio, | 402 | !mddev->flush_bio, |
| 403 | mddev->write_lock); | 403 | mddev->lock); |
| 404 | mddev->flush_bio = bio; | 404 | mddev->flush_bio = bio; |
| 405 | spin_unlock_irq(&mddev->write_lock); | 405 | spin_unlock_irq(&mddev->lock); |
| 406 | 406 | ||
| 407 | INIT_WORK(&mddev->flush_work, submit_flushes); | 407 | INIT_WORK(&mddev->flush_work, submit_flushes); |
| 408 | queue_work(md_wq, &mddev->flush_work); | 408 | queue_work(md_wq, &mddev->flush_work); |
| @@ -465,7 +465,7 @@ void mddev_init(struct mddev *mddev) | |||
| 465 | atomic_set(&mddev->active, 1); | 465 | atomic_set(&mddev->active, 1); |
| 466 | atomic_set(&mddev->openers, 0); | 466 | atomic_set(&mddev->openers, 0); |
| 467 | atomic_set(&mddev->active_io, 0); | 467 | atomic_set(&mddev->active_io, 0); |
| 468 | spin_lock_init(&mddev->write_lock); | 468 | spin_lock_init(&mddev->lock); |
| 469 | atomic_set(&mddev->flush_pending, 0); | 469 | atomic_set(&mddev->flush_pending, 0); |
| 470 | init_waitqueue_head(&mddev->sb_wait); | 470 | init_waitqueue_head(&mddev->sb_wait); |
| 471 | init_waitqueue_head(&mddev->recovery_wait); | 471 | init_waitqueue_head(&mddev->recovery_wait); |
| @@ -2230,7 +2230,7 @@ repeat: | |||
| 2230 | return; | 2230 | return; |
| 2231 | } | 2231 | } |
| 2232 | 2232 | ||
| 2233 | spin_lock_irq(&mddev->write_lock); | 2233 | spin_lock(&mddev->lock); |
| 2234 | 2234 | ||
| 2235 | mddev->utime = get_seconds(); | 2235 | mddev->utime = get_seconds(); |
| 2236 | 2236 | ||
| @@ -2287,7 +2287,7 @@ repeat: | |||
| 2287 | } | 2287 | } |
| 2288 | 2288 | ||
| 2289 | sync_sbs(mddev, nospares); | 2289 | sync_sbs(mddev, nospares); |
| 2290 | spin_unlock_irq(&mddev->write_lock); | 2290 | spin_unlock(&mddev->lock); |
| 2291 | 2291 | ||
| 2292 | pr_debug("md: updating %s RAID superblock on device (in sync %d)\n", | 2292 | pr_debug("md: updating %s RAID superblock on device (in sync %d)\n", |
| 2293 | mdname(mddev), mddev->in_sync); | 2293 | mdname(mddev), mddev->in_sync); |
| @@ -2326,15 +2326,15 @@ repeat: | |||
| 2326 | md_super_wait(mddev); | 2326 | md_super_wait(mddev); |
| 2327 | /* if there was a failure, MD_CHANGE_DEVS was set, and we re-write super */ | 2327 | /* if there was a failure, MD_CHANGE_DEVS was set, and we re-write super */ |
| 2328 | 2328 | ||
| 2329 | spin_lock_irq(&mddev->write_lock); | 2329 | spin_lock(&mddev->lock); |
| 2330 | if (mddev->in_sync != sync_req || | 2330 | if (mddev->in_sync != sync_req || |
| 2331 | test_bit(MD_CHANGE_DEVS, &mddev->flags)) { | 2331 | test_bit(MD_CHANGE_DEVS, &mddev->flags)) { |
| 2332 | /* have to write it out again */ | 2332 | /* have to write it out again */ |
| 2333 | spin_unlock_irq(&mddev->write_lock); | 2333 | spin_unlock(&mddev->lock); |
| 2334 | goto repeat; | 2334 | goto repeat; |
| 2335 | } | 2335 | } |
| 2336 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); | 2336 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); |
| 2337 | spin_unlock_irq(&mddev->write_lock); | 2337 | spin_unlock(&mddev->lock); |
| 2338 | wake_up(&mddev->sb_wait); | 2338 | wake_up(&mddev->sb_wait); |
| 2339 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | 2339 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) |
| 2340 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | 2340 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
| @@ -3722,7 +3722,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
| 3722 | case clean: | 3722 | case clean: |
| 3723 | if (mddev->pers) { | 3723 | if (mddev->pers) { |
| 3724 | restart_array(mddev); | 3724 | restart_array(mddev); |
| 3725 | spin_lock_irq(&mddev->write_lock); | 3725 | spin_lock(&mddev->lock); |
| 3726 | if (atomic_read(&mddev->writes_pending) == 0) { | 3726 | if (atomic_read(&mddev->writes_pending) == 0) { |
| 3727 | if (mddev->in_sync == 0) { | 3727 | if (mddev->in_sync == 0) { |
| 3728 | mddev->in_sync = 1; | 3728 | mddev->in_sync = 1; |
| @@ -3733,7 +3733,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
| 3733 | err = 0; | 3733 | err = 0; |
| 3734 | } else | 3734 | } else |
| 3735 | err = -EBUSY; | 3735 | err = -EBUSY; |
| 3736 | spin_unlock_irq(&mddev->write_lock); | 3736 | spin_unlock(&mddev->lock); |
| 3737 | } else | 3737 | } else |
| 3738 | err = -EINVAL; | 3738 | err = -EINVAL; |
| 3739 | break; | 3739 | break; |
| @@ -7102,7 +7102,7 @@ void md_write_start(struct mddev *mddev, struct bio *bi) | |||
| 7102 | if (mddev->safemode == 1) | 7102 | if (mddev->safemode == 1) |
| 7103 | mddev->safemode = 0; | 7103 | mddev->safemode = 0; |
| 7104 | if (mddev->in_sync) { | 7104 | if (mddev->in_sync) { |
| 7105 | spin_lock_irq(&mddev->write_lock); | 7105 | spin_lock(&mddev->lock); |
| 7106 | if (mddev->in_sync) { | 7106 | if (mddev->in_sync) { |
| 7107 | mddev->in_sync = 0; | 7107 | mddev->in_sync = 0; |
| 7108 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 7108 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
| @@ -7110,7 +7110,7 @@ void md_write_start(struct mddev *mddev, struct bio *bi) | |||
| 7110 | md_wakeup_thread(mddev->thread); | 7110 | md_wakeup_thread(mddev->thread); |
| 7111 | did_change = 1; | 7111 | did_change = 1; |
| 7112 | } | 7112 | } |
| 7113 | spin_unlock_irq(&mddev->write_lock); | 7113 | spin_unlock(&mddev->lock); |
| 7114 | } | 7114 | } |
| 7115 | if (did_change) | 7115 | if (did_change) |
| 7116 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 7116 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
| @@ -7148,7 +7148,7 @@ int md_allow_write(struct mddev *mddev) | |||
| 7148 | if (!mddev->pers->sync_request) | 7148 | if (!mddev->pers->sync_request) |
| 7149 | return 0; | 7149 | return 0; |
| 7150 | 7150 | ||
| 7151 | spin_lock_irq(&mddev->write_lock); | 7151 | spin_lock(&mddev->lock); |
| 7152 | if (mddev->in_sync) { | 7152 | if (mddev->in_sync) { |
| 7153 | mddev->in_sync = 0; | 7153 | mddev->in_sync = 0; |
| 7154 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 7154 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
| @@ -7156,11 +7156,11 @@ int md_allow_write(struct mddev *mddev) | |||
| 7156 | if (mddev->safemode_delay && | 7156 | if (mddev->safemode_delay && |
| 7157 | mddev->safemode == 0) | 7157 | mddev->safemode == 0) |
| 7158 | mddev->safemode = 1; | 7158 | mddev->safemode = 1; |
| 7159 | spin_unlock_irq(&mddev->write_lock); | 7159 | spin_unlock(&mddev->lock); |
| 7160 | md_update_sb(mddev, 0); | 7160 | md_update_sb(mddev, 0); |
| 7161 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 7161 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
| 7162 | } else | 7162 | } else |
| 7163 | spin_unlock_irq(&mddev->write_lock); | 7163 | spin_unlock(&mddev->lock); |
| 7164 | 7164 | ||
| 7165 | if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) | 7165 | if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) |
| 7166 | return -EAGAIN; | 7166 | return -EAGAIN; |
| @@ -7688,7 +7688,7 @@ void md_check_recovery(struct mddev *mddev) | |||
| 7688 | 7688 | ||
| 7689 | if (!mddev->external) { | 7689 | if (!mddev->external) { |
| 7690 | int did_change = 0; | 7690 | int did_change = 0; |
| 7691 | spin_lock_irq(&mddev->write_lock); | 7691 | spin_lock(&mddev->lock); |
| 7692 | if (mddev->safemode && | 7692 | if (mddev->safemode && |
| 7693 | !atomic_read(&mddev->writes_pending) && | 7693 | !atomic_read(&mddev->writes_pending) && |
| 7694 | !mddev->in_sync && | 7694 | !mddev->in_sync && |
| @@ -7699,7 +7699,7 @@ void md_check_recovery(struct mddev *mddev) | |||
| 7699 | } | 7699 | } |
| 7700 | if (mddev->safemode == 1) | 7700 | if (mddev->safemode == 1) |
| 7701 | mddev->safemode = 0; | 7701 | mddev->safemode = 0; |
| 7702 | spin_unlock_irq(&mddev->write_lock); | 7702 | spin_unlock(&mddev->lock); |
| 7703 | if (did_change) | 7703 | if (did_change) |
| 7704 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 7704 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
| 7705 | } | 7705 | } |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 03cec5bdcaae..f0d15bdd96d4 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -386,7 +386,13 @@ struct mddev { | |||
| 386 | 386 | ||
| 387 | struct work_struct del_work; /* used for delayed sysfs removal */ | 387 | struct work_struct del_work; /* used for delayed sysfs removal */ |
| 388 | 388 | ||
| 389 | spinlock_t write_lock; | 389 | /* "lock" protects: |
| 390 | * flush_bio transition from NULL to !NULL | ||
| 391 | * rdev superblocks, events | ||
| 392 | * clearing MD_CHANGE_* | ||
| 393 | * in_sync - and related safemode and MD_CHANGE changes | ||
| 394 | */ | ||
| 395 | spinlock_t lock; | ||
| 390 | wait_queue_head_t sb_wait; /* for waiting on superblock updates */ | 396 | wait_queue_head_t sb_wait; /* for waiting on superblock updates */ |
| 391 | atomic_t pending_writes; /* number of active superblock writes */ | 397 | atomic_t pending_writes; /* number of active superblock writes */ |
| 392 | 398 | ||
