]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/md/linear.c
md: linear.c: Make two local variables sector-based.
[linux-2.6.git] / drivers / md / linear.c
index 192741083196f25d7c75ab85bf2aaeb167a2e09d..13e928bde7cdee3c629c064636f71e1c37c7d004 100644 (file)
@@ -42,7 +42,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
        (void)sector_div(block, conf->hash_spacing);
        hash = conf->hash_table[block];
 
-       while ((sector>>1) >= (hash->size + hash->offset))
+       while (sector >= hash->num_sectors + hash->start_sector)
                hash++;
        return hash;
 }
@@ -50,20 +50,22 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 /**
  *     linear_mergeable_bvec -- tell bio layer if two requests can be merged
  *     @q: request queue
- *     @bio: the buffer head that's been built up so far
+ *     @bvm: properties of new bio
  *     @biovec: the request that could be merged to it.
  *
  *     Return amount of bytes we can take at this offset
  */
-static int linear_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec)
+static int linear_mergeable_bvec(struct request_queue *q,
+                                struct bvec_merge_data *bvm,
+                                struct bio_vec *biovec)
 {
        mddev_t *mddev = q->queuedata;
        dev_info_t *dev0;
-       unsigned long maxsectors, bio_sectors = bio->bi_size >> 9;
-       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
+       sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 
        dev0 = which_dev(mddev, sector);
-       maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1));
+       maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
 
        if (maxsectors < bio_sectors)
                maxsectors = 0;
@@ -79,38 +81,18 @@ static int linear_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio
        return maxsectors << 9;
 }
 
-static void linear_unplug(request_queue_t *q)
+static void linear_unplug(struct request_queue *q)
 {
        mddev_t *mddev = q->queuedata;
        linear_conf_t *conf = mddev_to_conf(mddev);
        int i;
 
        for (i=0; i < mddev->raid_disks; i++) {
-               request_queue_t *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
-               if (r_queue->unplug_fn)
-                       r_queue->unplug_fn(r_queue);
+               struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
+               blk_unplug(r_queue);
        }
 }
 
-static int linear_issue_flush(request_queue_t *q, struct gendisk *disk,
-                             sector_t *error_sector)
-{
-       mddev_t *mddev = q->queuedata;
-       linear_conf_t *conf = mddev_to_conf(mddev);
-       int i, ret = 0;
-
-       for (i=0; i < mddev->raid_disks && ret == 0; i++) {
-               struct block_device *bdev = conf->disks[i].rdev->bdev;
-               request_queue_t *r_queue = bdev_get_queue(bdev);
-
-               if (!r_queue->issue_flush_fn)
-                       ret = -EOPNOTSUPP;
-               else
-                       ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-       }
-       return ret;
-}
-
 static int linear_congested(void *data, int bits)
 {
        mddev_t *mddev = data;
@@ -118,7 +100,7 @@ static int linear_congested(void *data, int bits)
        int i, ret = 0;
 
        for (i = 0; i < mddev->raid_disks && !ret ; i++) {
-               request_queue_t *q = bdev_get_queue(conf->disks[i].rdev->bdev);
+               struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
                ret |= bdi_congested(&q->backing_dev_info, bits);
        }
        return ret;
@@ -130,8 +112,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
        dev_info_t **table;
        mdk_rdev_t *rdev;
        int i, nb_zone, cnt;
-       sector_t min_spacing;
-       sector_t curr_offset;
+       sector_t min_sectors;
+       sector_t curr_sector;
        struct list_head *tmp;
 
        conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
@@ -140,13 +122,13 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                return NULL;
 
        cnt = 0;
-       conf->array_size = 0;
+       conf->array_sectors = 0;
 
-       ITERATE_RDEV(mddev,rdev,tmp) {
+       rdev_for_each(rdev, tmp, mddev) {
                int j = rdev->raid_disk;
                dev_info_t *disk = conf->disks + j;
 
-               if (j < 0 || j > raid_disks || disk->rdev) {
+               if (j < 0 || j >= raid_disks || disk->rdev) {
                        printk("linear: disk numbering problem. Aborting!\n");
                        goto out;
                }
@@ -163,8 +145,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                    mddev->queue->max_sectors > (PAGE_SIZE>>9))
                        blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
-               disk->size = rdev->size;
-               conf->array_size += rdev->size;
+               disk->num_sectors = rdev->size * 2;
+               conf->array_sectors += rdev->size * 2;
 
                cnt++;
        }
@@ -173,23 +155,23 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                goto out;
        }
 
-       min_spacing = conf->array_size;
-       sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
+       min_sectors = conf->array_sectors;
+       sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
 
-       /* min_spacing is the minimum spacing that will fit the hash
+       /* min_sectors is the minimum spacing that will fit the hash
         * table in one PAGE.  This may be much smaller than needed.
         * We find the smallest non-terminal set of consecutive devices
-        * that is larger than min_spacing as use the size of that as
+        * that is larger than min_sectors and use the size of that as
         * the actual spacing
         */
-       conf->hash_spacing = conf->array_size;
+       conf->hash_spacing = conf->array_sectors / 2;
        for (i=0; i < cnt-1 ; i++) {
-               sector_t sz = 0;
+               sector_t tmp = 0;
                int j;
-               for (j = i; j < cnt - 1 && sz < min_spacing; j++)
-                       sz += conf->disks[j].size;
-               if (sz >= min_spacing && sz < conf->hash_spacing)
-                       conf->hash_spacing = sz;
+               for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
+                       tmp += conf->disks[j].num_sectors;
+               if (tmp >= min_sectors && tmp < conf->hash_spacing * 2)
+                       conf->hash_spacing = tmp / 2;
        }
 
        /* hash_spacing may be too large for sector_div to work with,
@@ -212,7 +194,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                unsigned round;
                unsigned long base;
 
-               sz = conf->array_size >> conf->preshift;
+               sz = conf->array_sectors >> (conf->preshift + 1);
                sz += 1; /* force round-up */
                base = conf->hash_spacing >> conf->preshift;
                round = sector_div(sz, base);
@@ -229,21 +211,20 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
         * Here we generate the linear hash table
         * First calculate the device offsets.
         */
-       conf->disks[0].offset = 0;
+       conf->disks[0].start_sector = 0;
        for (i = 1; i < raid_disks; i++)
-               conf->disks[i].offset =
-                       conf->disks[i-1].offset +
-                       conf->disks[i-1].size;
+               conf->disks[i].start_sector =
+                       conf->disks[i-1].start_sector +
+                       conf->disks[i-1].num_sectors;
 
        table = conf->hash_table;
-       curr_offset = 0;
        i = 0;
-       for (curr_offset = 0;
-            curr_offset < conf->array_size;
-            curr_offset += conf->hash_spacing) {
+       for (curr_sector = 0;
+            curr_sector < conf->array_sectors;
+            curr_sector += conf->hash_spacing * 2) {
 
                while (i < raid_disks-1 &&
-                      curr_offset >= conf->disks[i+1].offset)
+                      curr_sector >= conf->disks[i+1].start_sector)
                        i++;
 
                *table ++ = conf->disks + i;
@@ -270,16 +251,16 @@ static int linear_run (mddev_t *mddev)
 {
        linear_conf_t *conf;
 
+       mddev->queue->queue_lock = &mddev->queue->__queue_lock;
        conf = linear_conf(mddev, mddev->raid_disks);
 
        if (!conf)
                return 1;
        mddev->private = conf;
-       mddev->array_size = conf->array_size;
+       mddev->array_sectors = conf->array_sectors;
 
        blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
        mddev->queue->unplug_fn = linear_unplug;
-       mddev->queue->issue_flush_fn = linear_issue_flush;
        mddev->queue->backing_dev_info.congested_fn = linear_congested;
        mddev->queue->backing_dev_info.congested_data = mddev;
        return 0;
@@ -310,8 +291,8 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
        newconf->prev = mddev_to_conf(mddev);
        mddev->private = newconf;
        mddev->raid_disks++;
-       mddev->array_size = newconf->array_size;
-       set_capacity(mddev->gendisk, mddev->array_size << 1);
+       mddev->array_sectors = newconf->array_sectors;
+       set_capacity(mddev->gendisk, mddev->array_sectors);
        return 0;
 }
 
@@ -330,45 +311,52 @@ static int linear_stop (mddev_t *mddev)
        return 0;
 }
 
-static int linear_make_request (request_queue_t *q, struct bio *bio)
+static int linear_make_request (struct request_queue *q, struct bio *bio)
 {
        const int rw = bio_data_dir(bio);
        mddev_t *mddev = q->queuedata;
        dev_info_t *tmp_dev;
-       sector_t block;
+       int cpu;
 
        if (unlikely(bio_barrier(bio))) {
-               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               bio_endio(bio, -EOPNOTSUPP);
                return 0;
        }
 
-       disk_stat_inc(mddev->gendisk, ios[rw]);
-       disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+       cpu = part_stat_lock();
+       part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+       part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+                     bio_sectors(bio));
+       part_stat_unlock();
 
        tmp_dev = which_dev(mddev, bio->bi_sector);
-       block = bio->bi_sector >> 1;
     
-       if (unlikely(block >= (tmp_dev->size + tmp_dev->offset)
-                    || block < tmp_dev->offset)) {
+       if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
+                                       tmp_dev->start_sector)
+                    || (bio->bi_sector <
+                        tmp_dev->start_sector))) {
                char b[BDEVNAME_SIZE];
 
-               printk("linear_make_request: Block %llu out of bounds on "
-                       "dev %s size %llu offset %llu\n",
-                       (unsigned long long)block,
+               printk("linear_make_request: Sector %llu out of bounds on "
+                       "dev %s: %llu sectors, offset %llu\n",
+                       (unsigned long long)bio->bi_sector,
                        bdevname(tmp_dev->rdev->bdev, b),
-                       (unsigned long long)tmp_dev->size,
-                       (unsigned long long)tmp_dev->offset);
-               bio_io_error(bio, bio->bi_size);
+                       (unsigned long long)tmp_dev->num_sectors,
+                       (unsigned long long)tmp_dev->start_sector);
+               bio_io_error(bio);
                return 0;
        }
        if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
-                    (tmp_dev->offset + tmp_dev->size)<<1)) {
+                    tmp_dev->start_sector + tmp_dev->num_sectors)) {
                /* This bio crosses a device boundary, so we have to
                 * split it.
                 */
                struct bio_pair *bp;
-               bp = bio_split(bio, bio_split_pool,
-                              ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector);
+
+               bp = bio_split(bio,
+                              tmp_dev->start_sector + tmp_dev->num_sectors
+                              - bio->bi_sector);
+
                if (linear_make_request(q, &bp->bio1))
                        generic_make_request(&bp->bio1);
                if (linear_make_request(q, &bp->bio2))
@@ -378,7 +366,8 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
        }
                    
        bio->bi_bdev = tmp_dev->rdev->bdev;
-       bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset;
+       bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
+               + tmp_dev->rdev->data_offset;
 
        return 1;
 }
@@ -386,29 +375,6 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
 static void linear_status (struct seq_file *seq, mddev_t *mddev)
 {
 
-#undef MD_DEBUG
-#ifdef MD_DEBUG
-       int j;
-       linear_conf_t *conf = mddev_to_conf(mddev);
-       sector_t s = 0;
-  
-       seq_printf(seq, "      ");
-       for (j = 0; j < mddev->raid_disks; j++)
-       {
-               char b[BDEVNAME_SIZE];
-               s += conf->smallest_size;
-               seq_printf(seq, "[%s",
-                          bdevname(conf->hash_table[j][0].rdev->bdev,b));
-
-               while (s > conf->hash_table[j][0].offset +
-                          conf->hash_table[j][0].size)
-                       seq_printf(seq, "/%s] ",
-                                  bdevname(conf->hash_table[j][1].rdev->bdev,b));
-               else
-                       seq_printf(seq, "] ");
-       }
-       seq_printf(seq, "\n");
-#endif
        seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
 }