Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / md / md.c
index 115a6dd..01233d8 100644 (file)
@@ -391,6 +391,8 @@ void mddev_suspend(struct mddev *mddev)
        synchronize_rcu();
        wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
        mddev->pers->quiesce(mddev, 1);
+
+       del_timer_sync(&mddev->safemode_timer);
 }
 EXPORT_SYMBOL_GPL(mddev_suspend);
 
@@ -439,7 +441,7 @@ static void submit_flushes(struct work_struct *ws)
        INIT_WORK(&mddev->flush_work, md_submit_flush_data);
        atomic_set(&mddev->flush_pending, 1);
        rcu_read_lock();
-       list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
+       rdev_for_each_rcu(rdev, mddev)
                if (rdev->raid_disk >= 0 &&
                    !test_bit(Faulty, &rdev->flags)) {
                        /* Take two references, one is dropped
@@ -749,7 +751,7 @@ static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr)
 {
        struct md_rdev *rdev;
 
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       rdev_for_each(rdev, mddev)
                if (rdev->desc_nr == nr)
                        return rdev;
 
@@ -760,7 +762,7 @@ static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev)
 {
        struct md_rdev *rdev;
 
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       rdev_for_each(rdev, mddev)
                if (rdev->bdev->bd_dev == dev)
                        return rdev;
 
@@ -1342,7 +1344,7 @@ static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev)
                sb->state |= (1<<MD_SB_BITMAP_PRESENT);
 
        sb->disks[0].state = (1<<MD_DISK_REMOVED);
-       list_for_each_entry(rdev2, &mddev->disks, same_set) {
+       rdev_for_each(rdev2, mddev) {
                mdp_disk_t *d;
                int desc_nr;
                int is_active = test_bit(In_sync, &rdev2->flags);
@@ -1805,18 +1807,18 @@ retry:
                                                | BB_LEN(internal_bb));
                                *bbp++ = cpu_to_le64(store_bb);
                        }
+                       bb->changed = 0;
                        if (read_seqretry(&bb->lock, seq))
                                goto retry;
 
                        bb->sector = (rdev->sb_start +
                                      (int)le32_to_cpu(sb->bblog_offset));
                        bb->size = le16_to_cpu(sb->bblog_size);
-                       bb->changed = 0;
                }
        }
 
        max_dev = 0;
-       list_for_each_entry(rdev2, &mddev->disks, same_set)
+       rdev_for_each(rdev2, mddev)
                if (rdev2->desc_nr+1 > max_dev)
                        max_dev = rdev2->desc_nr+1;
 
@@ -1833,7 +1835,7 @@ retry:
        for (i=0; i<max_dev;i++)
                sb->dev_roles[i] = cpu_to_le16(0xfffe);
        
-       list_for_each_entry(rdev2, &mddev->disks, same_set) {
+       rdev_for_each(rdev2, mddev) {
                i = rdev2->desc_nr;
                if (test_bit(Faulty, &rdev2->flags))
                        sb->dev_roles[i] = cpu_to_le16(0xfffe);
@@ -1948,7 +1950,7 @@ int md_integrity_register(struct mddev *mddev)
                return 0; /* nothing to do */
        if (!mddev->gendisk || blk_get_integrity(mddev->gendisk))
                return 0; /* shouldn't register, or already is */
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                /* skip spares and non-functional disks */
                if (test_bit(Faulty, &rdev->flags))
                        continue;
@@ -2175,7 +2177,7 @@ static void export_array(struct mddev *mddev)
 {
        struct md_rdev *rdev, *tmp;
 
-       rdev_for_each(rdev, tmp, mddev) {
+       rdev_for_each_safe(rdev, tmp, mddev) {
                if (!rdev->mddev) {
                        MD_BUG();
                        continue;
@@ -2307,11 +2309,11 @@ static void md_print_devices(void)
                        bitmap_print_sb(mddev->bitmap);
                else
                        printk("%s: ", mdname(mddev));
-               list_for_each_entry(rdev, &mddev->disks, same_set)
+               rdev_for_each(rdev, mddev)
                        printk("<%s>", bdevname(rdev->bdev,b));
                printk("\n");
 
-               list_for_each_entry(rdev, &mddev->disks, same_set)
+               rdev_for_each(rdev, mddev)
                        print_rdev(rdev, mddev->major_version);
        }
        printk("md:     **********************************\n");
@@ -2328,7 +2330,7 @@ static void sync_sbs(struct mddev * mddev, int nospares)
         * with the rest of the array)
         */
        struct md_rdev *rdev;
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (rdev->sb_events == mddev->events ||
                    (nospares &&
                     rdev->raid_disk < 0 &&
@@ -2351,7 +2353,7 @@ static void md_update_sb(struct mddev * mddev, int force_change)
 
 repeat:
        /* First make sure individual recovery_offsets are correct */
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (rdev->raid_disk >= 0 &&
                    mddev->delta_disks >= 0 &&
                    !test_bit(In_sync, &rdev->flags) &&
@@ -2364,8 +2366,9 @@ repeat:
                clear_bit(MD_CHANGE_DEVS, &mddev->flags);
                if (!mddev->external) {
                        clear_bit(MD_CHANGE_PENDING, &mddev->flags);
-                       list_for_each_entry(rdev, &mddev->disks, same_set) {
+                       rdev_for_each(rdev, mddev) {
                                if (rdev->badblocks.changed) {
+                                       rdev->badblocks.changed = 0;
                                        md_ack_all_badblocks(&rdev->badblocks);
                                        md_error(mddev, rdev);
                                }
@@ -2430,7 +2433,7 @@ repeat:
                mddev->events --;
        }
 
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (rdev->badblocks.changed)
                        any_badblocks_changed++;
                if (test_bit(Faulty, &rdev->flags))
@@ -2444,7 +2447,7 @@ repeat:
                 mdname(mddev), mddev->in_sync);
 
        bitmap_update_sb(mddev->bitmap);
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                char b[BDEVNAME_SIZE];
 
                if (rdev->sb_loaded != 1)
@@ -2493,7 +2496,7 @@ repeat:
        if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (test_and_clear_bit(FaultRecorded, &rdev->flags))
                        clear_bit(Blocked, &rdev->flags);
 
@@ -2896,7 +2899,7 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
                        struct md_rdev *rdev2;
 
                        mddev_lock(mddev);
-                       list_for_each_entry(rdev2, &mddev->disks, same_set)
+                       rdev_for_each(rdev2, mddev)
                                if (rdev->bdev == rdev2->bdev &&
                                    rdev != rdev2 &&
                                    overlaps(rdev->data_offset, rdev->sectors,
@@ -3193,7 +3196,7 @@ static void analyze_sbs(struct mddev * mddev)
        char b[BDEVNAME_SIZE];
 
        freshest = NULL;
-       rdev_for_each(rdev, tmp, mddev)
+       rdev_for_each_safe(rdev, tmp, mddev)
                switch (super_types[mddev->major_version].
                        load_super(rdev, freshest, mddev->minor_version)) {
                case 1:
@@ -3214,7 +3217,7 @@ static void analyze_sbs(struct mddev * mddev)
                validate_super(mddev, freshest);
 
        i = 0;
-       rdev_for_each(rdev, tmp, mddev) {
+       rdev_for_each_safe(rdev, tmp, mddev) {
                if (mddev->max_disks &&
                    (rdev->desc_nr >= mddev->max_disks ||
                     i > mddev->max_disks)) {
@@ -3403,7 +3406,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
                return -EINVAL;
        }
 
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       rdev_for_each(rdev, mddev)
                rdev->new_raid_disk = rdev->raid_disk;
 
        /* ->takeover must set new_* and/or delta_disks
@@ -3456,7 +3459,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
                mddev->safemode = 0;
        }
 
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (rdev->raid_disk < 0)
                        continue;
                if (rdev->new_raid_disk >= mddev->raid_disks)
@@ -3465,7 +3468,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
                        continue;
                sysfs_unlink_rdev(mddev, rdev);
        }
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (rdev->raid_disk < 0)
                        continue;
                if (rdev->new_raid_disk == rdev->raid_disk)
@@ -4796,7 +4799,7 @@ int md_run(struct mddev *mddev)
         * the only valid external interface is through the md
         * device.
         */
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (test_bit(Faulty, &rdev->flags))
                        continue;
                sync_blockdev(rdev->bdev);
@@ -4867,8 +4870,8 @@ int md_run(struct mddev *mddev)
                struct md_rdev *rdev2;
                int warned = 0;
 
-               list_for_each_entry(rdev, &mddev->disks, same_set)
-                       list_for_each_entry(rdev2, &mddev->disks, same_set) {
+               rdev_for_each(rdev, mddev)
+                       rdev_for_each(rdev2, mddev) {
                                if (rdev < rdev2 &&
                                    rdev->bdev->bd_contains ==
                                    rdev2->bdev->bd_contains) {
@@ -4945,7 +4948,7 @@ int md_run(struct mddev *mddev)
        mddev->in_sync = 1;
        smp_wmb();
        mddev->ready = 1;
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       rdev_for_each(rdev, mddev)
                if (rdev->raid_disk >= 0)
                        if (sysfs_link_rdev(mddev, rdev))
                                /* failure here is OK */;
@@ -5073,6 +5076,7 @@ static void md_clean(struct mddev *mddev)
        mddev->changed = 0;
        mddev->degraded = 0;
        mddev->safemode = 0;
+       mddev->merge_check_needed = 0;
        mddev->bitmap_info.offset = 0;
        mddev->bitmap_info.default_offset = 0;
        mddev->bitmap_info.chunksize = 0;
@@ -5175,7 +5179,7 @@ static int do_md_stop(struct mddev * mddev, int mode, int is_open)
                /* tell userspace to handle 'inactive' */
                sysfs_notify_dirent_safe(mddev->sysfs_state);
 
-               list_for_each_entry(rdev, &mddev->disks, same_set)
+               rdev_for_each(rdev, mddev)
                        if (rdev->raid_disk >= 0)
                                sysfs_unlink_rdev(mddev, rdev);
 
@@ -5226,7 +5230,7 @@ static void autorun_array(struct mddev *mddev)
 
        printk(KERN_INFO "md: running: ");
 
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                char b[BDEVNAME_SIZE];
                printk("<%s>", bdevname(rdev->bdev,b));
        }
@@ -5356,7 +5360,7 @@ static int get_array_info(struct mddev * mddev, void __user * arg)
        struct md_rdev *rdev;
 
        nr=working=insync=failed=spare=0;
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                nr++;
                if (test_bit(Faulty, &rdev->flags))
                        failed++;
@@ -5923,7 +5927,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
                 * grow, and re-add.
                 */
                return -EBUSY;
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                sector_t avail = rdev->sectors;
 
                if (fit && (num_sectors == 0 || num_sectors > avail))
@@ -6724,7 +6728,6 @@ static int md_seq_show(struct seq_file *seq, void *v)
        struct mddev *mddev = v;
        sector_t sectors;
        struct md_rdev *rdev;
-       struct bitmap *bitmap;
 
        if (v == (void*)1) {
                struct md_personality *pers;
@@ -6758,7 +6761,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
                }
 
                sectors = 0;
-               list_for_each_entry(rdev, &mddev->disks, same_set) {
+               rdev_for_each(rdev, mddev) {
                        char b[BDEVNAME_SIZE];
                        seq_printf(seq, " %s[%d]",
                                bdevname(rdev->bdev,b), rdev->desc_nr);
@@ -6812,27 +6815,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
                } else
                        seq_printf(seq, "\n       ");
 
-               if ((bitmap = mddev->bitmap)) {
-                       unsigned long chunk_kb;
-                       unsigned long flags;
-                       spin_lock_irqsave(&bitmap->lock, flags);
-                       chunk_kb = mddev->bitmap_info.chunksize >> 10;
-                       seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
-                               "%lu%s chunk",
-                               bitmap->pages - bitmap->missing_pages,
-                               bitmap->pages,
-                               (bitmap->pages - bitmap->missing_pages)
-                                       << (PAGE_SHIFT - 10),
-                               chunk_kb ? chunk_kb : mddev->bitmap_info.chunksize,
-                               chunk_kb ? "KB" : "B");
-                       if (bitmap->file) {
-                               seq_printf(seq, ", file: ");
-                               seq_path(seq, &bitmap->file->f_path, " \t\n");
-                       }
-
-                       seq_printf(seq, "\n");
-                       spin_unlock_irqrestore(&bitmap->lock, flags);
-               }
+               bitmap_status(seq, mddev->bitmap);
 
                seq_printf(seq, "\n");
        }
@@ -7170,7 +7153,7 @@ void md_do_sync(struct mddev *mddev)
                max_sectors = mddev->dev_sectors;
                j = MaxSector;
                rcu_read_lock();
-               list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
+               rdev_for_each_rcu(rdev, mddev)
                        if (rdev->raid_disk >= 0 &&
                            !test_bit(Faulty, &rdev->flags) &&
                            !test_bit(In_sync, &rdev->flags) &&
@@ -7342,7 +7325,7 @@ void md_do_sync(struct mddev *mddev)
                        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
                                mddev->curr_resync = MaxSector;
                        rcu_read_lock();
-                       list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
+                       rdev_for_each_rcu(rdev, mddev)
                                if (rdev->raid_disk >= 0 &&
                                    mddev->delta_disks >= 0 &&
                                    !test_bit(Faulty, &rdev->flags) &&
@@ -7388,7 +7371,7 @@ static int remove_and_add_spares(struct mddev *mddev)
 
        mddev->curr_resync_completed = 0;
 
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       rdev_for_each(rdev, mddev)
                if (rdev->raid_disk >= 0 &&
                    !test_bit(Blocked, &rdev->flags) &&
                    (test_bit(Faulty, &rdev->flags) ||
@@ -7406,7 +7389,7 @@ static int remove_and_add_spares(struct mddev *mddev)
                             "degraded");
 
 
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
+       rdev_for_each(rdev, mddev) {
                if (rdev->raid_disk >= 0 &&
                    !test_bit(In_sync, &rdev->flags) &&
                    !test_bit(Faulty, &rdev->flags))
@@ -7451,7 +7434,7 @@ static void reap_sync_thread(struct mddev *mddev)
         * do the superblock for an incrementally recovered device
         * written out.
         */
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       rdev_for_each(rdev, mddev)
                if (!mddev->degraded ||
                    test_bit(In_sync, &rdev->flags))
                        rdev->saved_raid_disk = -1;
@@ -7529,7 +7512,7 @@ void md_check_recovery(struct mddev *mddev)
                         * failed devices.
                         */
                        struct md_rdev *rdev;
-                       list_for_each_entry(rdev, &mddev->disks, same_set)
+                       rdev_for_each(rdev, mddev)
                                if (rdev->raid_disk >= 0 &&
                                    !test_bit(Blocked, &rdev->flags) &&
                                    test_bit(Faulty, &rdev->flags) &&
@@ -7579,14 +7562,14 @@ void md_check_recovery(struct mddev *mddev)
                 * any transients in the value of "sync_action".
                 */
                set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
-               clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                /* Clear some bits that don't mean anything, but
                 * might be left set
                 */
                clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
                clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
 
-               if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+               if (!test_and_clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+                   test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
                        goto unlock;
                /* no recovery is running.
                 * remove any failed drives, then
@@ -8040,7 +8023,7 @@ void md_ack_all_badblocks(struct badblocks *bb)
                return;
        write_seqlock_irq(&bb->lock);
 
-       if (bb->changed == 0) {
+       if (bb->changed == 0 && bb->unacked_exist) {
                u64 *p = bb->page;
                int i;
                for (i = 0; i < bb->count ; i++) {
@@ -8159,7 +8142,8 @@ static int md_notify_reboot(struct notifier_block *this,
 
        for_each_mddev(mddev, tmp) {
                if (mddev_trylock(mddev)) {
-                       __md_stop_writes(mddev);
+                       if (mddev->pers)
+                               __md_stop_writes(mddev);
                        mddev->safemode = 2;
                        mddev_unlock(mddev);
                }