Merge branch 'next-i2c' of git://aeryn.fluff.org.uk/bjdooks/linux
[safe/jmp/linux-2.6] / drivers / md / raid0.c
index 6e85e88..925507e 100644 (file)
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
 
-#include <linux/raid/raid0.h>
+#include <linux/blkdev.h>
+#include <linux/seq_file.h>
+#include "md.h"
+#include "raid0.h"
 
 static void raid0_unplug(struct request_queue *q)
 {
@@ -57,7 +60,6 @@ static int create_strip_zones (mddev_t *mddev)
        sector_t min_spacing;
        raid0_conf_t *conf = mddev_to_conf(mddev);
        mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev;
-       struct list_head *tmp1, *tmp2;
        struct strip_zone *zone;
        int cnt;
        char b[BDEVNAME_SIZE];
@@ -67,23 +69,22 @@ static int create_strip_zones (mddev_t *mddev)
         */
        conf->nr_strip_zones = 0;
  
-       rdev_for_each(rdev1, tmp1, mddev) {
+       list_for_each_entry(rdev1, &mddev->disks, same_set) {
                printk(KERN_INFO "raid0: looking at %s\n",
                        bdevname(rdev1->bdev,b));
                c = 0;
-               rdev_for_each(rdev2, tmp2, mddev) {
+               list_for_each_entry(rdev2, &mddev->disks, same_set) {
                        printk(KERN_INFO "raid0:   comparing %s(%llu)",
                               bdevname(rdev1->bdev,b),
-                              (unsigned long long)rdev1->size);
+                              (unsigned long long)rdev1->sectors);
                        printk(KERN_INFO " with %s(%llu)\n",
                               bdevname(rdev2->bdev,b),
-                              (unsigned long long)rdev2->size);
+                              (unsigned long long)rdev2->sectors);
                        if (rdev2 == rdev1) {
                                printk(KERN_INFO "raid0:   END\n");
                                break;
                        }
-                       if (rdev2->size == rdev1->size)
-                       {
+                       if (rdev2->sectors == rdev1->sectors) {
                                /*
                                 * Not unique, don't count it as a new
                                 * group
@@ -120,7 +121,7 @@ static int create_strip_zones (mddev_t *mddev)
        cnt = 0;
        smallest = NULL;
        zone->dev = conf->devlist;
-       rdev_for_each(rdev1, tmp1, mddev) {
+       list_for_each_entry(rdev1, &mddev->disks, same_set) {
                int j = rdev1->raid_disk;
 
                if (j < 0 || j >= mddev->raid_disks) {
@@ -143,10 +144,10 @@ static int create_strip_zones (mddev_t *mddev)
                 */
 
                if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
-                   mddev->queue->max_sectors > (PAGE_SIZE>>9))
+                   queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
                        blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
-               if (!smallest || (rdev1->size <smallest->size))
+               if (!smallest || (rdev1->sectors < smallest->sectors))
                        smallest = rdev1;
                cnt++;
        }
@@ -156,10 +157,10 @@ static int create_strip_zones (mddev_t *mddev)
                goto abort;
        }
        zone->nb_dev = cnt;
-       zone->sectors = smallest->size * cnt * 2;
+       zone->sectors = smallest->sectors * cnt;
        zone->zone_start = 0;
 
-       current_start = smallest->size * 2;
+       current_start = smallest->sectors;
        curr_zone_start = zone->sectors;
 
        /* now do the other zones */
@@ -178,29 +179,29 @@ static int create_strip_zones (mddev_t *mddev)
                        rdev = conf->strip_zone[0].dev[j];
                        printk(KERN_INFO "raid0: checking %s ...",
                                bdevname(rdev->bdev, b));
-                       if (rdev->size > current_start / 2) {
-                               printk(KERN_INFO " contained as device %d\n",
-                                       c);
-                               zone->dev[c] = rdev;
-                               c++;
-                               if (!smallest || (rdev->size <smallest->size)) {
-                                       smallest = rdev;
-                                       printk(KERN_INFO "  (%llu) is smallest!.\n",
-                                               (unsigned long long)rdev->size);
-                               }
-                       } else
+                       if (rdev->sectors <= current_start) {
                                printk(KERN_INFO " nope.\n");
+                               continue;
+                       }
+                       printk(KERN_INFO " contained as device %d\n", c);
+                       zone->dev[c] = rdev;
+                       c++;
+                       if (!smallest || rdev->sectors < smallest->sectors) {
+                               smallest = rdev;
+                               printk(KERN_INFO "  (%llu) is smallest!.\n",
+                                       (unsigned long long)rdev->sectors);
+                       }
                }
 
                zone->nb_dev = c;
-               zone->sectors = (smallest->size * 2 - current_start) * c;
+               zone->sectors = (smallest->sectors - current_start) * c;
                printk(KERN_INFO "raid0: zone->nb_dev: %d, sectors: %llu\n",
                        zone->nb_dev, (unsigned long long)zone->sectors);
 
                zone->zone_start = curr_zone_start;
                curr_zone_start += zone->sectors;
 
-               current_start = smallest->size * 2;
+               current_start = smallest->sectors;
                printk(KERN_INFO "raid0: current zone start: %llu\n",
                        (unsigned long long)current_start);
        }
@@ -213,16 +214,16 @@ static int create_strip_zones (mddev_t *mddev)
         * strip though as it's size has no bearing on the efficacy of the hash
         * table.
         */
-       conf->hash_spacing = curr_zone_start / 2;
-       min_spacing = curr_zone_start / 2;
+       conf->spacing = curr_zone_start;
+       min_spacing = curr_zone_start;
        sector_div(min_spacing, PAGE_SIZE/sizeof(struct strip_zone*));
        for (i=0; i < conf->nr_strip_zones-1; i++) {
-               sector_t sz = 0;
-               for (j=i; j<conf->nr_strip_zones-1 &&
-                            sz < min_spacing ; j++)
-                       sz += conf->strip_zone[j].sectors / 2;
-               if (sz >= min_spacing && sz < conf->hash_spacing)
-                       conf->hash_spacing = sz;
+               sector_t s = 0;
+               for (j = i; j < conf->nr_strip_zones - 1 &&
+                               s < min_spacing; j++)
+                       s += conf->strip_zone[j].sectors;
+               if (s >= min_spacing && s < conf->spacing)
+                       conf->spacing = s;
        }
 
        mddev->queue->unplug_fn = raid0_unplug;
@@ -262,13 +263,25 @@ static int raid0_mergeable_bvec(struct request_queue *q,
                return max;
 }
 
+static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+{
+       sector_t array_sectors = 0;
+       mdk_rdev_t *rdev;
+
+       WARN_ONCE(sectors || raid_disks,
+                 "%s does not support generic reshape\n", __func__);
+
+       list_for_each_entry(rdev, &mddev->disks, same_set)
+               array_sectors += rdev->sectors;
+
+       return array_sectors;
+}
+
 static int raid0_run (mddev_t *mddev)
 {
        unsigned  cur=0, i=0, nb_zone;
-       s64 size;
+       s64 sectors;
        raid0_conf_t *conf;
-       mdk_rdev_t *rdev;
-       struct list_head *tmp;
 
        if (mddev->chunk_size == 0) {
                printk(KERN_ERR "md/raid0: non-zero chunk size required.\n");
@@ -293,55 +306,53 @@ static int raid0_run (mddev_t *mddev)
                goto out_free_conf;
 
        /* calculate array device size */
-       mddev->array_sectors = 0;
-       rdev_for_each(rdev, tmp, mddev)
-               mddev->array_sectors += rdev->size * 2;
-
-       printk("raid0 : md_size is %llu blocks.\n", 
-               (unsigned long long)mddev->array_sectors / 2);
-       printk("raid0 : conf->hash_spacing is %llu blocks.\n",
-               (unsigned long long)conf->hash_spacing);
+       md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
+
+       printk(KERN_INFO "raid0 : md_size is %llu sectors.\n",
+               (unsigned long long)mddev->array_sectors);
+       printk(KERN_INFO "raid0 : conf->spacing is %llu sectors.\n",
+               (unsigned long long)conf->spacing);
        {
-               sector_t s = mddev->array_sectors / 2;
-               sector_t space = conf->hash_spacing;
+               sector_t s = raid0_size(mddev, 0, 0);
+               sector_t space = conf->spacing;
                int round;
-               conf->preshift = 0;
+               conf->sector_shift = 0;
                if (sizeof(sector_t) > sizeof(u32)) {
                        /*shift down space and s so that sector_div will work */
                        while (space > (sector_t) (~(u32)0)) {
                                s >>= 1;
                                space >>= 1;
                                s += 1; /* force round-up */
-                               conf->preshift++;
+                               conf->sector_shift++;
                        }
                }
                round = sector_div(s, (u32)space) ? 1 : 0;
                nb_zone = s + round;
        }
-       printk("raid0 : nb_zone is %d.\n", nb_zone);
+       printk(KERN_INFO "raid0 : nb_zone is %d.\n", nb_zone);
 
-       printk("raid0 : Allocating %Zd bytes for hash.\n",
+       printk(KERN_INFO "raid0 : Allocating %zu bytes for hash.\n",
                                nb_zone*sizeof(struct strip_zone*));
        conf->hash_table = kmalloc (sizeof (struct strip_zone *)*nb_zone, GFP_KERNEL);
        if (!conf->hash_table)
                goto out_free_conf;
-       size = conf->strip_zone[cur].sectors / 2;
+       sectors = conf->strip_zone[cur].sectors;
 
        conf->hash_table[0] = conf->strip_zone + cur;
        for (i=1; i< nb_zone; i++) {
-               while (size <= conf->hash_spacing) {
+               while (sectors <= conf->spacing) {
                        cur++;
-                       size += conf->strip_zone[cur].sectors / 2;
+                       sectors += conf->strip_zone[cur].sectors;
                }
-               size -= conf->hash_spacing;
+               sectors -= conf->spacing;
                conf->hash_table[i] = conf->strip_zone + cur;
        }
-       if (conf->preshift) {
-               conf->hash_spacing >>= conf->preshift;
-               /* round hash_spacing up so when we divide by it, we
+       if (conf->sector_shift) {
+               conf->spacing >>= conf->sector_shift;
+               /* round spacing up so when we divide by it, we
                 * err on the side of too-low, which is safest
                 */
-               conf->hash_spacing++;
+               conf->spacing++;
        }
 
        /* calculate the max read-ahead size.
@@ -435,8 +446,8 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
  
 
        {
-               sector_t x = sector >> (conf->preshift + 1);
-               sector_div(x, (u32)conf->hash_spacing);
+               sector_t x = sector >> conf->sector_shift;
+               sector_div(x, (u32)conf->spacing);
                zone = conf->hash_table[x];
        }
 
@@ -511,6 +522,7 @@ static struct mdk_personality raid0_personality=
        .run            = raid0_run,
        .stop           = raid0_stop,
        .status         = raid0_status,
+       .size           = raid0_size,
 };
 
 static int __init raid0_init (void)