]> git.hungrycats.org Git - linux/commitdiff
[PATCH] md: assorted minor md/raid1 fixes
authorNeil Brown <neilb@cse.unsw.edu.au>
Tue, 24 Aug 2004 04:28:42 +0000 (21:28 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 24 Aug 2004 04:28:42 +0000 (21:28 -0700)
1/ rationalise read_balance and "map" in raid1.  Discard map and
   tidyup the interface to read_balance so it can be used instead.

2/ use offsetof rather than a caclulation to find the size of an
   structure with a var-length array at the end.

3/ remove some meaningless #defines

4/ use printk_ratelimit to limit reports of failed sectors being redirected.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/md/raid1.c

index 4ca50f8ba8b91843fe5fb8912c9de58c4d989055..179dd05ca0a87d6a53869fb8578c391b847a8295 100644 (file)
 
 #include <linux/raid/raid1.h>
 
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
@@ -44,13 +40,12 @@ static void * r1bio_pool_alloc(int gfp_flags, void *data)
 {
        struct pool_info *pi = data;
        r1bio_t *r1_bio;
+       int size = offsetof(r1bio_t, bios[pi->raid_disks]);
 
        /* allocate a r1bio with room for raid_disks entries in the bios array */
-       r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*pi->raid_disks,
-                        gfp_flags);
+       r1_bio = kmalloc(size, gfp_flags);
        if (r1_bio)
-               memset(r1_bio, 0, sizeof(*r1_bio) +
-                              sizeof(struct bio*) * pi->raid_disks);
+               memset(r1_bio, 0, size);
        else
                unplug_slaves(pi->mddev);
 
@@ -104,7 +99,7 @@ static void * r1buf_pool_alloc(int gfp_flags, void *data)
                bio->bi_io_vec[i].bv_page = page;
        }
 
-       r1_bio->master_bio = bio;
+       r1_bio->master_bio = NULL;
 
        return r1_bio;
 
@@ -189,32 +184,6 @@ static inline void put_buf(r1bio_t *r1_bio)
        spin_unlock_irqrestore(&conf->resync_lock, flags);
 }
 
-static int map(mddev_t *mddev, mdk_rdev_t **rdevp)
-{
-       conf_t *conf = mddev_to_conf(mddev);
-       int i, disks = conf->raid_disks;
-
-       /*
-        * Later we do read balancing on the read side
-        * now we use the first available disk.
-        */
-
-       spin_lock_irq(&conf->device_lock);
-       for (i = 0; i < disks; i++) {
-               mdk_rdev_t *rdev = conf->mirrors[i].rdev;
-               if (rdev && rdev->in_sync) {
-                       *rdevp = rdev;
-                       atomic_inc(&rdev->nr_pending);
-                       spin_unlock_irq(&conf->device_lock);
-                       return i;
-               }
-       }
-       spin_unlock_irq(&conf->device_lock);
-
-       printk(KERN_ERR "raid1_map(): huh, no more operational devices?\n");
-       return -1;
-}
-
 static void reschedule_retry(r1bio_t *r1_bio)
 {
        unsigned long flags;
@@ -292,8 +261,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
                 * oops, read error:
                 */
                char b[BDEVNAME_SIZE];
-               printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
-                      bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
+               if (printk_ratelimit())
+                       printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
+                              bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
                reschedule_retry(r1_bio);
        }
 
@@ -363,11 +333,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
  *
  * The rdev for the device selected will have nr_pending incremented.
  */
-static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
+static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 {
        const unsigned long this_sector = r1_bio->sector;
        int new_disk = conf->last_used, disk = new_disk;
-       const int sectors = bio->bi_size >> 9;
+       const int sectors = r1_bio->sectors;
        sector_t new_distance, current_distance;
 
        spin_lock_irq(&conf->device_lock);
@@ -378,14 +348,14 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
         */
        if (conf->mddev->recovery_cp < MaxSector &&
            (this_sector + sectors >= conf->next_resync)) {
-               /* make sure that disk is operational */
+               /* Choose the first operation device, for consistancy */
                new_disk = 0;
 
                while (!conf->mirrors[new_disk].rdev ||
                       !conf->mirrors[new_disk].rdev->in_sync) {
                        new_disk++;
                        if (new_disk == conf->raid_disks) {
-                               new_disk = 0;
+                               new_disk = -1;
                                break;
                        }
                }
@@ -400,7 +370,7 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
                        new_disk = conf->raid_disks;
                new_disk--;
                if (new_disk == disk) {
-                       new_disk = conf->last_used;
+                       new_disk = -1;
                        goto rb_out;
                }
        }
@@ -440,13 +410,13 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
        } while (disk != conf->last_used);
 
 rb_out:
-       r1_bio->read_disk = new_disk;
-       conf->next_seq_sect = this_sector + sectors;
 
-       conf->last_used = new_disk;
 
-       if (conf->mirrors[new_disk].rdev)
+       if (new_disk >= 0) {
+               conf->next_seq_sect = this_sector + sectors;
+               conf->last_used = new_disk;
                atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending);
+       }
        spin_unlock_irq(&conf->device_lock);
 
        return new_disk;
@@ -571,15 +541,26 @@ static int make_request(request_queue_t *q, struct bio * bio)
        r1_bio->mddev = mddev;
        r1_bio->sector = bio->bi_sector;
 
+       r1_bio->state = 0;
+
        if (bio_data_dir(bio) == READ) {
                /*
                 * read balancing logic:
                 */
-               mirror = conf->mirrors + read_balance(conf, bio, r1_bio);
+               int rdisk = read_balance(conf, r1_bio);
+
+               if (rdisk < 0) {
+                       /* couldn't find anywhere to read from */
+                       raid_end_bio_io(r1_bio);
+                       return 0;
+               }
+               mirror = conf->mirrors + rdisk;
+
+               r1_bio->read_disk = rdisk;
 
                read_bio = bio_clone(bio, GFP_NOIO);
 
-               r1_bio->bios[r1_bio->read_disk] = read_bio;
+               r1_bio->bios[rdisk] = read_bio;
 
                read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
                read_bio->bi_bdev = mirror->rdev->bdev;
@@ -951,7 +932,7 @@ static void raid1d(mddev_t *mddev)
                } else {
                        int disk;
                        bio = r1_bio->bios[r1_bio->read_disk];
-                       if ((disk=map(mddev, &rdev)) == -1) {
+                       if ((disk=read_balance(conf, r1_bio)) == -1) {
                                printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
                                       " read error for block %llu\n",
                                       bdevname(bio->bi_bdev,b),
@@ -961,10 +942,12 @@ static void raid1d(mddev_t *mddev)
                                r1_bio->bios[r1_bio->read_disk] = NULL;
                                r1_bio->read_disk = disk;
                                r1_bio->bios[r1_bio->read_disk] = bio;
-                               printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
-                                      " another mirror\n",
-                                      bdevname(rdev->bdev,b),
-                                      (unsigned long long)r1_bio->sector);
+                               rdev = conf->mirrors[disk].rdev;
+                               if (printk_ratelimit())
+                                       printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
+                                              " another mirror\n",
+                                              bdevname(rdev->bdev,b),
+                                              (unsigned long long)r1_bio->sector);
                                bio->bi_bdev = rdev->bdev;
                                bio->bi_sector = r1_bio->sector + rdev->data_offset;
                                bio->bi_rw = READ;