Merge tag 'md/3.19' of git://neil.brown.name/md
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Dec 2014 20:13:05 +0000 (12:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Dec 2014 20:13:05 +0000 (12:13 -0800)
Pull md updates from Neil Brown:
 "Three fixes for md.

   I did have a largish set of locking changes queued, but late testing
  showed they weren't quite as stable as I thought and while I fixed
  what I found, I decided it safer to delay them a release ...
  particularly as I'll be AFK for a few weeks.  So expect a larger batch
  next time :-)"

* tag 'md/3.19' of git://neil.brown.name/md:
  md: Check MD_RECOVERY_RUNNING as well as ->sync_thread.
  md: fix semicolon.cocci warnings
  md/raid5: fetch_block must fetch all the blocks handle_stripe_dirtying wants.

1  2 
drivers/md/md.c

diff --combined drivers/md/md.c
@@@ -247,6 -247,7 +247,6 @@@ static void md_make_request(struct requ
  {
        const int rw = bio_data_dir(bio);
        struct mddev *mddev = q->queuedata;
 -      int cpu;
        unsigned int sectors;
  
        if (mddev == NULL || mddev->pers == NULL
        sectors = bio_sectors(bio);
        mddev->pers->make_request(mddev, bio);
  
 -      cpu = part_stat_lock();
 -      part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
 -      part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);
 -      part_stat_unlock();
 +      generic_start_io_acct(rw, sectors, &mddev->gendisk->part0);
  
        if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
                wake_up(&mddev->sb_wait);
@@@ -2691,7 -2695,8 +2691,8 @@@ static ssize_t new_offset_store(struct 
        if (kstrtoull(buf, 10, &new_offset) < 0)
                return -EINVAL;
  
-       if (mddev->sync_thread)
+       if (mddev->sync_thread ||
+           test_bit(MD_RECOVERY_RUNNING,&mddev->recovery))
                return -EBUSY;
        if (new_offset == rdev->data_offset)
                /* reset is always permitted */
@@@ -3268,6 -3273,7 +3269,7 @@@ level_store(struct mddev *mddev, const 
         */
  
        if (mddev->sync_thread ||
+           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
            mddev->reshape_position != MaxSector ||
            mddev->sysfs_active)
                return -EBUSY;
@@@ -4022,6 -4028,7 +4024,7 @@@ action_store(struct mddev *mddev, cons
                clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
  
        if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
+               flush_workqueue(md_misc_wq);
                if (mddev->sync_thread) {
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                        md_reap_sync_thread(mddev);
@@@ -5040,6 -5047,7 +5043,7 @@@ static void md_clean(struct mddev *mdde
  static void __md_stop_writes(struct mddev *mddev)
  {
        set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+       flush_workqueue(md_misc_wq);
        if (mddev->sync_thread) {
                set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                md_reap_sync_thread(mddev);
@@@ -5100,19 -5108,22 +5104,22 @@@ static int md_set_readonly(struct mdde
                set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
                md_wakeup_thread(mddev->thread);
        }
-       if (mddev->sync_thread) {
+       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+       if (mddev->sync_thread)
                /* Thread might be blocked waiting for metadata update
                 * which will now never happen */
                wake_up_process(mddev->sync_thread->tsk);
-       }
        mddev_unlock(mddev);
-       wait_event(resync_wait, mddev->sync_thread == NULL);
+       wait_event(resync_wait, !test_bit(MD_RECOVERY_RUNNING,
+                                         &mddev->recovery));
        mddev_lock_nointr(mddev);
  
        mutex_lock(&mddev->open_mutex);
        if ((mddev->pers && atomic_read(&mddev->openers) > !!bdev) ||
            mddev->sync_thread ||
+           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
            (bdev && !test_bit(MD_STILL_CLOSED, &mddev->flags))) {
                printk("md: %s still in use.\n",mdname(mddev));
                if (did_freeze) {
@@@ -5158,20 -5169,24 +5165,24 @@@ static int do_md_stop(struct mddev *mdd
                set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
                md_wakeup_thread(mddev->thread);
        }
-       if (mddev->sync_thread) {
+       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+       if (mddev->sync_thread)
                /* Thread might be blocked waiting for metadata update
                 * which will now never happen */
                wake_up_process(mddev->sync_thread->tsk);
-       }
        mddev_unlock(mddev);
-       wait_event(resync_wait, mddev->sync_thread == NULL);
+       wait_event(resync_wait, (mddev->sync_thread == NULL &&
+                                !test_bit(MD_RECOVERY_RUNNING,
+                                          &mddev->recovery)));
        mddev_lock_nointr(mddev);
  
        mutex_lock(&mddev->open_mutex);
        if ((mddev->pers && atomic_read(&mddev->openers) > !!bdev) ||
            mddev->sysfs_active ||
            mddev->sync_thread ||
+           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
            (bdev && !test_bit(MD_STILL_CLOSED, &mddev->flags))) {
                printk("md: %s still in use.\n",mdname(mddev));
                mutex_unlock(&mddev->open_mutex);
@@@ -5946,7 -5961,8 +5957,8 @@@ static int update_size(struct mddev *md
         * of each device.  If num_sectors is zero, we find the largest size
         * that fits.
         */
-       if (mddev->sync_thread)
+       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+           mddev->sync_thread)
                return -EBUSY;
        if (mddev->ro)
                return -EROFS;
@@@ -5977,7 -5993,9 +5989,9 @@@ static int update_raid_disks(struct mdd
        if (raid_disks <= 0 ||
            (mddev->max_disks && raid_disks >= mddev->max_disks))
                return -EINVAL;
-       if (mddev->sync_thread || mddev->reshape_position != MaxSector)
+       if (mddev->sync_thread ||
+           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+           mddev->reshape_position != MaxSector)
                return -EBUSY;
  
        rdev_for_each(rdev, mddev) {
@@@ -6965,7 -6983,7 +6979,7 @@@ static unsigned int mdstat_poll(struct 
        int mask;
  
        if (md_unloading)
-               return POLLIN|POLLRDNORM|POLLERR|POLLPRI;;
+               return POLLIN|POLLRDNORM|POLLERR|POLLPRI;
        poll_wait(filp, &md_event_waiters, wait);
  
        /* always allow read */
@@@ -7589,6 -7607,7 +7603,7 @@@ static void md_start_sync(struct work_s
                clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
                clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
                clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+               wake_up(&resync_wait);
                if (test_and_clear_bit(MD_RECOVERY_RECOVER,
                                       &mddev->recovery))
                        if (mddev->sysfs_action)
@@@ -7757,6 -7776,7 +7772,7 @@@ void md_check_recovery(struct mddev *md
        not_running:
                if (!mddev->sync_thread) {
                        clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+                       wake_up(&resync_wait);
                        if (test_and_clear_bit(MD_RECOVERY_RECOVER,
                                               &mddev->recovery))
                                if (mddev->sysfs_action)
@@@ -7775,7 -7795,6 +7791,6 @@@ void md_reap_sync_thread(struct mddev *
  
        /* resync has finished, collect result */
        md_unregister_thread(&mddev->sync_thread);
-       wake_up(&resync_wait);
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
            !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
                /* success...*/
        clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
        clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
        clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+       wake_up(&resync_wait);
        /* flag recovery needed just to double check */
        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
        sysfs_notify_dirent_safe(mddev->sysfs_action);