[PATCH] md: improve the interface to sync_request
authorNeilBrown <neilb@cse.unsw.edu.au>
Wed, 22 Jun 2005 00:17:13 +0000 (17:17 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 22 Jun 2005 02:07:43 +0000 (19:07 -0700)
1/ change the return value (which is number-of-sectors synced)
 from 'int' to 'sector_t'.
 The number of sectors is usually easily small enough to fit
 in an int, but if resync needs to abort, it may want to return
 the total number of remaining sectors, which could be large.
 Also errors cannot be returned as negative numbers now, so use
 0 instead
2/ Add a 'skipped' return parameter to allow the array to report
 that it skipped the sectors.  This allows md to take this into account
 in the speed calculations.
 Currently there is no important skipping, but the bitmap-based-resync
 that is coming will use this.

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/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid6main.c
include/linux/raid/md_k.h

index 177d2a7d7cea21bf57cb1afdad76f8fa30ff3aa6..fa608a1a5c20a2d8043050f176ff3459eeb971c5 100644 (file)
@@ -3241,12 +3241,13 @@ static void md_do_sync(mddev_t *mddev)
        mddev_t *mddev2;
        unsigned int currspeed = 0,
                 window;
-       sector_t max_sectors,j;
+       sector_t max_sectors,j, io_sectors;
        unsigned long mark[SYNC_MARKS];
        sector_t mark_cnt[SYNC_MARKS];
        int last_mark,m;
        struct list_head *tmp;
        sector_t last_check;
+       int skipped = 0;
 
        /* just incase thread restarts... */
        if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
@@ -3312,7 +3313,7 @@ static void md_do_sync(mddev_t *mddev)
 
        if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
                /* resync follows the size requested by the personality,
-                * which default to physical size, but can be virtual size
+                * which defaults to physical size, but can be virtual size
                 */
                max_sectors = mddev->resync_max_sectors;
        else
@@ -3331,9 +3332,10 @@ static void md_do_sync(mddev_t *mddev)
                j = mddev->recovery_cp;
        else
                j = 0;
+       io_sectors = 0;
        for (m = 0; m < SYNC_MARKS; m++) {
                mark[m] = jiffies;
-               mark_cnt[m] = j;
+               mark_cnt[m] = io_sectors;
        }
        last_mark = 0;
        mddev->resync_mark = mark[last_mark];
@@ -3358,21 +3360,29 @@ static void md_do_sync(mddev_t *mddev)
        }
 
        while (j < max_sectors) {
-               int sectors;
+               sector_t sectors;
 
-               sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
-               if (sectors < 0) {
+               skipped = 0;
+               sectors = mddev->pers->sync_request(mddev, j, &skipped,
+                                           currspeed < sysctl_speed_limit_min);
+               if (sectors == 0) {
                        set_bit(MD_RECOVERY_ERR, &mddev->recovery);
                        goto out;
                }
-               atomic_add(sectors, &mddev->recovery_active);
+
+               if (!skipped) { /* actual IO requested */
+                       io_sectors += sectors;
+                       atomic_add(sectors, &mddev->recovery_active);
+               }
+
                j += sectors;
                if (j>1) mddev->curr_resync = j;
 
-               if (last_check + window > j || j == max_sectors)
+
+               if (last_check + window > io_sectors || j == max_sectors)
                        continue;
 
-               last_check = j;
+               last_check = io_sectors;
 
                if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
                    test_bit(MD_RECOVERY_ERR, &mddev->recovery))
@@ -3386,7 +3396,7 @@ static void md_do_sync(mddev_t *mddev)
                        mddev->resync_mark = mark[next];
                        mddev->resync_mark_cnt = mark_cnt[next];
                        mark[next] = jiffies;
-                       mark_cnt[next] = j - atomic_read(&mddev->recovery_active);
+                       mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active);
                        last_mark = next;
                }
 
@@ -3413,7 +3423,8 @@ static void md_do_sync(mddev_t *mddev)
                mddev->queue->unplug_fn(mddev->queue);
                cond_resched();
 
-               currspeed = ((unsigned long)(j-mddev->resync_mark_cnt))/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
+               currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
+                       /((jiffies-mddev->resync_mark)/HZ +1) +1;
 
                if (currspeed > sysctl_speed_limit_min) {
                        if ((currspeed > sysctl_speed_limit_max) ||
@@ -3433,7 +3444,7 @@ static void md_do_sync(mddev_t *mddev)
        wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
        /* tell personality that we are finished */
-       mddev->pers->sync_request(mddev, max_sectors, 1);
+       mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
 
        if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
            mddev->curr_resync > 2 &&
index 3f1280bbaf39e220cf674bd838dbc90e8f2f7403..3c5c916cb09ed9af10833bfde0854b5fe4951669 100644 (file)
@@ -1010,7 +1010,7 @@ static int init_resync(conf_t *conf)
  * that can be installed to exclude normal IO requests.
  */
 
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        conf_t *conf = mddev_to_conf(mddev);
        mirror_info_t *mirror;
@@ -1023,7 +1023,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
 
        if (!conf->r1buf_pool)
                if (init_resync(conf))
-                       return -ENOMEM;
+                       return 0;
 
        max_sector = mddev->size << 1;
        if (sector_nr >= max_sector) {
@@ -1107,8 +1107,8 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                /* There is nowhere to write, so all non-sync
                 * drives must be failed - so we are finished
                 */
-               int rv = max_sector - sector_nr;
-               md_done_sync(mddev, rv, 1);
+               sector_t rv = max_sector - sector_nr;
+               *skipped = 1;
                put_buf(r1_bio);
                rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
                return rv;
index bfc9f52f0ecf1fad6ab6f6718596de8ce9f83a17..8476515bfdc79e293ee079a6fea11e15884dcc39 100644 (file)
@@ -1321,7 +1321,7 @@ static int init_resync(conf_t *conf)
  *
  */
 
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        conf_t *conf = mddev_to_conf(mddev);
        r10bio_t *r10_bio;
@@ -1335,7 +1335,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
 
        if (!conf->r10buf_pool)
                if (init_resync(conf))
-                       return -ENOMEM;
+                       return 0;
 
  skipped:
        max_sector = mddev->size << 1;
@@ -1343,15 +1343,15 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                max_sector = mddev->resync_max_sectors;
        if (sector_nr >= max_sector) {
                close_sync(conf);
+               *skipped = 1;
                return sectors_skipped;
        }
        if (chunks_skipped >= conf->raid_disks) {
                /* if there has been nothing to do on any drive,
                 * then there is nothing to do at all..
                 */
-               sector_t sec = max_sector - sector_nr;
-               md_done_sync(mddev, sec, 1);
-               return sec + sectors_skipped;
+               *skipped = 1;
+               return (max_sector - sector_nr) + sectors_skipped;
        }
 
        /* make sure whole request will fit in a chunk - if chunks
@@ -1565,17 +1565,22 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                }
        }
 
+       if (sectors_skipped)
+               /* pretend they weren't skipped, it makes
+                * no important difference in this case
+                */
+               md_done_sync(mddev, sectors_skipped, 1);
+
        return sectors_skipped + nr_sectors;
  giveup:
        /* There is nowhere to write, so all non-sync
         * drives must be failed, so try the next chunk...
         */
        {
-       int sec = max_sector - sector_nr;
+       sector_t sec = max_sector - sector_nr;
        sectors_skipped += sec;
        chunks_skipped ++;
        sector_nr = max_sector;
-       md_done_sync(mddev, sec, 1);
        goto skipped;
        }
 }
index 677ce49078daf587123b5e04c2dca9013552f15e..1ce3f5aaa984b57f4b20f28fe809ec2e1b23bd75 100644 (file)
@@ -1477,7 +1477,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
 }
 
 /* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
        struct stripe_head *sh;
@@ -1500,8 +1500,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
         * nothing we can do.
         */
        if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-               int rv = (mddev->size << 1) - sector_nr;
-               md_done_sync(mddev, rv, 1);
+               sector_t rv = (mddev->size << 1) - sector_nr;
+               *skipped = 1;
                return rv;
        }
 
index fede16c4e8f36d287117f2c702f0494790561df3..d9c385496dc5f2fcf572f99fabdb834a3e9a44dd 100644 (file)
@@ -1636,7 +1636,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
 }
 
 /* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
        struct stripe_head *sh;
@@ -1659,8 +1659,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
         * nothing we can do.
         */
        if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-               int rv = (mddev->size << 1) - sector_nr;
-               md_done_sync(mddev, rv, 1);
+               sector_t rv = (mddev->size << 1) - sector_nr;
+               *skipped = 1;
                return rv;
        }
 
index d92db54255a356bcd610ce074ea2e4a5e5747fac..bce0032decff83bc64a120c1e599057c15da2c02 100644 (file)
@@ -298,7 +298,7 @@ struct mdk_personality_s
        int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
        int (*hot_remove_disk) (mddev_t *mddev, int number);
        int (*spare_active) (mddev_t *mddev);
-       int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
+       sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
        int (*resize) (mddev_t *mddev, sector_t sectors);
        int (*reshape) (mddev_t *mddev, int raid_disks);
        int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);