[PATCH] md: add a ->congested_fn function for raid5/6
[powerpc.git] / drivers / md / raid5.c
index 837ec4e..37e4ff6 100644 (file)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/*
+ * BITMAP UNPLUGGING:
+ *
+ * The sequencing for updating the bitmap reliably is a little
+ * subtle (and I got it wrong the first time) so it deserves some
+ * explanation.
+ *
+ * We group bitmap updates into batches.  Each batch has a number.
+ * We may write out several batches at once, but that isn't very important.
+ * conf->bm_write is the number of the last batch successfully written.
+ * conf->bm_flush is the number of the last batch that was closed to
+ *    new additions.
+ * When we discover that we will need to write to any block in a stripe
+ * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq
+ * the number of the batch it will be in. This is bm_flush+1.
+ * When we are ready to do a write, if that batch hasn't been written yet,
+ *   we plug the array and queue the stripe for later.
+ * When an unplug happens, we increment bm_flush, thus closing the current
+ *   batch.
+ * When we notice that bm_flush > bm_write, we write out all pending updates
+ * to the bitmap, and advance bm_write to where bm_flush was.
+ * This may occasionally write a bit out twice, but is sure never to
+ * miss any bits.
+ */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
@@ -89,12 +112,14 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
                BUG_ON(!list_empty(&sh->lru));
                BUG_ON(atomic_read(&conf->active_stripes)==0);
                if (test_bit(STRIPE_HANDLE, &sh->state)) {
-                       if (test_bit(STRIPE_DELAYED, &sh->state))
+                       if (test_bit(STRIPE_DELAYED, &sh->state)) {
                                list_add_tail(&sh->lru, &conf->delayed_list);
-                       else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
-                                conf->seq_write == sh->bm_seq)
+                               blk_plug_device(conf->mddev->queue);
+                       } else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+                                  sh->bm_seq - conf->seq_write > 0) {
                                list_add_tail(&sh->lru, &conf->bitmap_list);
-                       else {
+                               blk_plug_device(conf->mddev->queue);
+                       } else {
                                clear_bit(STRIPE_BIT_DELAY, &sh->state);
                                list_add_tail(&sh->lru, &conf->handle_list);
                        }
@@ -271,7 +296,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
                                                     < (conf->max_nr_stripes *3/4)
                                                     || !conf->inactive_blocked),
                                                    conf->device_lock,
-                                                   unplug_slaves(conf->mddev)
+                                                   raid5_unplug_device(conf->mddev->queue)
                                        );
                                conf->inactive_blocked = 0;
                        } else
@@ -282,7 +307,8 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
                        } else {
                                if (!test_bit(STRIPE_HANDLE, &sh->state))
                                        atomic_inc(&conf->active_stripes);
-                               if (list_empty(&sh->lru))
+                               if (list_empty(&sh->lru) &&
+                                   !test_bit(STRIPE_EXPANDING, &sh->state))
                                        BUG();
                                list_del_init(&sh->lru);
                        }
@@ -497,6 +523,8 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
        raid5_conf_t *conf = sh->raid_conf;
        int disks = sh->disks, i;
        int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+       char b[BDEVNAME_SIZE];
+       mdk_rdev_t *rdev;
 
        if (bi->bi_size)
                return 1;
@@ -544,25 +572,39 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
                set_bit(R5_UPTODATE, &sh->dev[i].flags);
 #endif
                if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-                       printk(KERN_INFO "raid5: read error corrected!!\n");
+                       rdev = conf->disks[i].rdev;
+                       printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
+                              mdname(conf->mddev), STRIPE_SECTORS,
+                              (unsigned long long)sh->sector + rdev->data_offset,
+                              bdevname(rdev->bdev, b));
                        clear_bit(R5_ReadError, &sh->dev[i].flags);
                        clear_bit(R5_ReWrite, &sh->dev[i].flags);
                }
                if (atomic_read(&conf->disks[i].rdev->read_errors))
                        atomic_set(&conf->disks[i].rdev->read_errors, 0);
        } else {
+               const char *bdn = bdevname(conf->disks[i].rdev->bdev, b);
                int retry = 0;
+               rdev = conf->disks[i].rdev;
+
                clear_bit(R5_UPTODATE, &sh->dev[i].flags);
-               atomic_inc(&conf->disks[i].rdev->read_errors);
+               atomic_inc(&rdev->read_errors);
                if (conf->mddev->degraded)
-                       printk(KERN_WARNING "raid5: read error not correctable.\n");
+                       printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n",
+                              mdname(conf->mddev),
+                              (unsigned long long)sh->sector + rdev->data_offset,
+                              bdn);
                else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
                        /* Oh, no!!! */
-                       printk(KERN_WARNING "raid5: read error NOT corrected!!\n");
-               else if (atomic_read(&conf->disks[i].rdev->read_errors)
+                       printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n",
+                              mdname(conf->mddev),
+                              (unsigned long long)sh->sector + rdev->data_offset,
+                              bdn);
+               else if (atomic_read(&rdev->read_errors)
                         > conf->max_nr_stripes)
                        printk(KERN_WARNING
-                              "raid5: Too many read errors, failing device.\n");
+                              "raid5:%s: Too many read errors, failing device %s.\n",
+                              mdname(conf->mddev), bdn);
                else
                        retry = 1;
                if (retry)
@@ -570,7 +612,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
                else {
                        clear_bit(R5_ReadError, &sh->dev[i].flags);
                        clear_bit(R5_ReWrite, &sh->dev[i].flags);
-                       md_error(conf->mddev, conf->disks[i].rdev);
+                       md_error(conf->mddev, rdev);
                }
        }
        rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
@@ -594,7 +636,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
        struct stripe_head *sh = bi->bi_private;
        raid5_conf_t *conf = sh->raid_conf;
        int disks = sh->disks, i;
-       unsigned long flags;
        int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 
        if (bi->bi_size)
@@ -612,7 +653,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
                return 0;
        }
 
-       spin_lock_irqsave(&conf->device_lock, flags);
        if (!uptodate)
                md_error(conf->mddev, conf->disks[i].rdev);
 
@@ -620,8 +660,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
        
        clear_bit(R5_LOCKED, &sh->dev[i].flags);
        set_bit(STRIPE_HANDLE, &sh->state);
-       __release_stripe(conf, sh);
-       spin_unlock_irqrestore(&conf->device_lock, flags);
+       release_stripe(sh);
        return 0;
 }
 
@@ -654,12 +693,12 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
        PRINTK("raid5: error called\n");
 
        if (!test_bit(Faulty, &rdev->flags)) {
-               mddev->sb_dirty = 1;
-               if (test_bit(In_sync, &rdev->flags)) {
-                       conf->working_disks--;
+               set_bit(MD_CHANGE_DEVS, &mddev->flags);
+               if (test_and_clear_bit(In_sync, &rdev->flags)) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        mddev->degraded++;
-                       conf->failed_disks++;
-                       clear_bit(In_sync, &rdev->flags);
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
                        /*
                         * if recovery was running, make sure it aborts.
                         */
@@ -669,7 +708,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
                printk (KERN_ALERT
                        "raid5: Disk failure on %s, disabling device."
                        " Operation continuing on %d devices\n",
-                       bdevname(rdev->bdev,b), conf->working_disks);
+                       bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
        }
 }
 
@@ -1271,9 +1310,9 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                (unsigned long long)sh->sector, dd_idx);
 
        if (conf->mddev->bitmap && firstwrite) {
-               sh->bm_seq = conf->seq_write;
                bitmap_startwrite(conf->mddev->bitmap, sh->sector,
                                  STRIPE_SECTORS, 0);
+               sh->bm_seq = conf->seq_flush+1;
                set_bit(STRIPE_BIT_DELAY, &sh->state);
        }
 
@@ -1311,10 +1350,9 @@ static int page_is_zero(struct page *p)
 static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
 {
        int sectors_per_chunk = conf->chunk_size >> 9;
-       sector_t x = stripe;
        int pd_idx, dd_idx;
-       int chunk_offset = sector_div(x, sectors_per_chunk);
-       stripe = x;
+       int chunk_offset = sector_div(stripe, sectors_per_chunk);
+
        raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk
                             + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf);
        return pd_idx;
@@ -2555,11 +2593,22 @@ static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk,
        return ret;
 }
 
-static inline void raid5_plug_device(raid5_conf_t *conf)
+static int raid5_congested(void *data, int bits)
 {
-       spin_lock_irq(&conf->device_lock);
-       blk_plug_device(conf->mddev->queue);
-       spin_unlock_irq(&conf->device_lock);
+       mddev_t *mddev = data;
+       raid5_conf_t *conf = mddev_to_conf(mddev);
+
+       /* No difference between reads and writes.  Just check
+        * how busy the stripe_cache is
+        */
+       if (conf->inactive_blocked)
+               return 1;
+       if (conf->quiesce)
+               return 1;
+       if (list_empty_careful(&conf->inactive_list))
+               return 1;
+
+       return 0;
 }
 
 static int make_request(request_queue_t *q, struct bio * bi)
@@ -2671,7 +2720,6 @@ static int make_request(request_queue_t *q, struct bio * bi)
                                goto retry;
                        }
                        finish_wait(&conf->wait_for_overlap, &w);
-                       raid5_plug_device(conf);
                        handle_stripe(sh, NULL);
                        release_stripe(sh);
                } else {
@@ -2747,9 +2795,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
                wait_event(conf->wait_for_overlap,
                           atomic_read(&conf->reshape_stripes)==0);
                mddev->reshape_position = conf->expand_progress;
-               mddev->sb_dirty = 1;
+               set_bit(MD_CHANGE_DEVS, &mddev->flags);
                md_wakeup_thread(mddev->thread);
-               wait_event(mddev->sb_wait, mddev->sb_dirty == 0 ||
+               wait_event(mddev->sb_wait, mddev->flags == 0 ||
                           kthread_should_stop());
                spin_lock_irq(&conf->device_lock);
                conf->expand_lo = mddev->reshape_position;
@@ -2924,7 +2972,7 @@ static void raid5d (mddev_t *mddev)
        while (1) {
                struct list_head *first;
 
-               if (conf->seq_flush - conf->seq_write > 0) {
+               if (conf->seq_flush != conf->seq_write) {
                        int seq = conf->seq_flush;
                        spin_unlock_irq(&conf->device_lock);
                        bitmap_unplug(mddev->bitmap);
@@ -3040,6 +3088,7 @@ static int run(mddev_t *mddev)
        mdk_rdev_t *rdev;
        struct disk_info *disk;
        struct list_head *tmp;
+       int working_disks = 0;
 
        if (mddev->level != 5 && mddev->level != 4 && mddev->level != 6) {
                printk(KERN_ERR "raid5: %s: raid level not set to 4/5/6 (%d)\n",
@@ -3142,14 +3191,14 @@ static int run(mddev_t *mddev)
                        printk(KERN_INFO "raid5: device %s operational as raid"
                                " disk %d\n", bdevname(rdev->bdev,b),
                                raid_disk);
-                       conf->working_disks++;
+                       working_disks++;
                }
        }
 
        /*
         * 0 for a fully functional array, 1 or 2 for a degraded array.
         */
-       mddev->degraded = conf->failed_disks = conf->raid_disks - conf->working_disks;
+       mddev->degraded = conf->raid_disks - working_disks;
        conf->mddev = mddev;
        conf->chunk_size = mddev->chunk_size;
        conf->level = mddev->level;
@@ -3184,7 +3233,7 @@ static int run(mddev_t *mddev)
        if (mddev->degraded > conf->max_degraded) {
                printk(KERN_ERR "raid5: not enough operational devices for %s"
                        " (%d/%d failed)\n",
-                       mdname(mddev), conf->failed_disks, conf->raid_disks);
+                       mdname(mddev), mddev->degraded, conf->raid_disks);
                goto abort;
        }
 
@@ -3247,9 +3296,6 @@ static int run(mddev_t *mddev)
                set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
                mddev->sync_thread = md_register_thread(md_do_sync, mddev,
                                                        "%s_reshape");
-               /* FIXME if md_register_thread fails?? */
-               md_wakeup_thread(mddev->sync_thread);
-
        }
 
        /* read-ahead size must cover two whole stripes, which is
@@ -3268,6 +3314,9 @@ static int run(mddev_t *mddev)
 
        mddev->queue->unplug_fn = raid5_unplug_device;
        mddev->queue->issue_flush_fn = raid5_issue_flush;
+       mddev->queue->backing_dev_info.congested_fn = raid5_congested;
+       mddev->queue->backing_dev_info.congested_data = mddev;
+
        mddev->array_size =  mddev->size * (conf->previous_raid_disks -
                                            conf->max_degraded);
 
@@ -3344,7 +3393,7 @@ static void status (struct seq_file *seq, mddev_t *mddev)
        int i;
 
        seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout);
-       seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks);
+       seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->raid_disks - mddev->degraded);
        for (i = 0; i < conf->raid_disks; i++)
                seq_printf (seq, "%s",
                               conf->disks[i].rdev &&
@@ -3366,8 +3415,8 @@ static void print_raid5_conf (raid5_conf_t *conf)
                printk("(conf==NULL)\n");
                return;
        }
-       printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks,
-                conf->working_disks, conf->failed_disks);
+       printk(" --- rd:%d wd:%d\n", conf->raid_disks,
+                conf->raid_disks - conf->mddev->degraded);
 
        for (i = 0; i < conf->raid_disks; i++) {
                char b[BDEVNAME_SIZE];
@@ -3389,11 +3438,11 @@ static int raid5_spare_active(mddev_t *mddev)
                tmp = conf->disks + i;
                if (tmp->rdev
                    && !test_bit(Faulty, &tmp->rdev->flags)
-                   && !test_bit(In_sync, &tmp->rdev->flags)) {
+                   && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        mddev->degraded--;
-                       conf->failed_disks--;
-                       conf->working_disks++;
-                       set_bit(In_sync, &tmp->rdev->flags);
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
                }
        }
        print_raid5_conf(conf);
@@ -3529,6 +3578,7 @@ static int raid5_start_reshape(mddev_t *mddev)
        struct list_head *rtmp;
        int spares = 0;
        int added_devices = 0;
+       unsigned long flags;
 
        if (mddev->degraded ||
            test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3562,7 +3612,6 @@ static int raid5_start_reshape(mddev_t *mddev)
                        if (raid5_add_disk(mddev, rdev)) {
                                char nm[20];
                                set_bit(In_sync, &rdev->flags);
-                               conf->working_disks++;
                                added_devices++;
                                rdev->recovery_offset = 0;
                                sprintf(nm, "rd%d", rdev->raid_disk);
@@ -3571,10 +3620,12 @@ static int raid5_start_reshape(mddev_t *mddev)
                                break;
                }
 
+       spin_lock_irqsave(&conf->device_lock, flags);
        mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
+       spin_unlock_irqrestore(&conf->device_lock, flags);
        mddev->raid_disks = conf->raid_disks;
        mddev->reshape_position = 0;
-       mddev->sb_dirty = 1;
+       set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
        clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
        clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);