diff -ruN -X linux-2.6.20.2/Documentation/dontdiff linux-2.6.20.2/drivers/md/raid5.c linux-2.6.20.2-raid/drivers/md/raid5.c --- linux-2.6.20.2/drivers/md/raid5.c 2007-03-09 20:58:04.000000000 +0200 +++ linux-2.6.20.2-raid/drivers/md/raid5.c 2007-03-30 12:37:55.000000000 +0300 @@ -65,6 +65,7 @@ #define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) #define HASH_MASK (NR_HASH - 1) + #define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])) /* bio's attached to a stripe+device for I/O are linked together in bi_sector @@ -234,6 +235,8 @@ sh->sector = sector; sh->pd_idx = pd_idx; sh->state = 0; + sh->active_preread_jiffies = + msecs_to_jiffies( atomic_read(&conf->deadline_ms) )+ jiffies; sh->disks = disks; @@ -628,6 +631,7 @@ clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); + sh->active_preread_jiffies = jiffies; release_stripe(sh); return 0; } @@ -1255,8 +1259,11 @@ bip = &sh->dev[dd_idx].towrite; if (*bip == NULL && sh->dev[dd_idx].written == NULL) firstwrite = 1; - } else + } else{ bip = &sh->dev[dd_idx].toread; + sh->active_preread_jiffies = jiffies; + } + while (*bip && (*bip)->bi_sector < bi->bi_sector) { if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector) goto overlap; @@ -2437,13 +2444,27 @@ -static void raid5_activate_delayed(raid5_conf_t *conf) +static struct stripe_head* raid5_activate_delayed(raid5_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { struct list_head *l = conf->delayed_list.next; struct stripe_head *sh; sh = list_entry(l, struct stripe_head, lru); + + if( time_before(jiffies,sh->active_preread_jiffies) ){ + PRINTK("deadline : no expire sec=%lld %8u %8u\n", + (unsigned long long) sh->sector, + jiffies_to_msecs(sh->active_preread_jiffies), + jiffies_to_msecs(jiffies)); + return sh; + } + else{ + PRINTK("deadline: expire:sec=%lld %8u %8u\n", + (unsigned long long)sh->sector, + jiffies_to_msecs(sh->active_preread_jiffies), + jiffies_to_msecs(jiffies)); + } list_del_init(l); clear_bit(STRIPE_DELAYED, &sh->state); if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) @@ -2451,6 +2472,7 @@ list_add_tail(&sh->lru, &conf->handle_list); } } + return NULL; } static void activate_bit_delay(raid5_conf_t *conf) @@ -3191,7 +3213,7 @@ */ static void raid5d (mddev_t *mddev) { - struct stripe_head *sh; + struct stripe_head *sh,*delayed_sh=NULL; raid5_conf_t *conf = mddev_to_conf(mddev); int handled; @@ -3218,8 +3240,10 @@ atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD && !blk_queue_plugged(mddev->queue) && !list_empty(&conf->delayed_list)) - raid5_activate_delayed(conf); - + delayed_sh=raid5_activate_delayed(conf); + + if(delayed_sh) break; + while ((bio = remove_bio_from_retry(conf))) { int ok; spin_unlock_irq(&conf->device_lock); @@ -3254,9 +3278,51 @@ unplug_slaves(mddev); PRINTK("--- raid5d inactive\n"); + if (delayed_sh){ + long wakeup=delayed_sh->active_preread_jiffies-jiffies; + PRINTK("--- raid5d inactive sleep for %d\n", + jiffies_to_msecs(wakeup) ); + if (wakeup>0) + mddev->thread->timeout = wakeup; + } +} + +static ssize_t +raid5_show_stripe_deadline(mddev_t *mddev, char *page) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + if (conf) + return sprintf(page, "%d\n", atomic_read(&conf->deadline_ms)); + else + return 0; } static ssize_t +raid5_store_stripe_deadline(mddev_t *mddev, const char *page, size_t len) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + char *end; + int new; + if (len >= PAGE_SIZE) + return -EINVAL; + if (!conf) + return -ENODEV; + new = simple_strtoul(page, &end, 10); + if (!*page || (*end && *end != '\n') ) + return -EINVAL; + if (new < 0 || new > 10000) + return -EINVAL; + atomic_set(&conf->deadline_ms,new); + return len; +} + +static struct md_sysfs_entry +raid5_stripe_deadline = __ATTR(stripe_deadline, S_IRUGO | S_IWUSR, + raid5_show_stripe_deadline, + raid5_store_stripe_deadline); + + +static ssize_t raid5_show_stripe_cache_size(mddev_t *mddev, char *page) { raid5_conf_t *conf = mddev_to_conf(mddev); @@ -3297,6 +3363,9 @@ return len; } + + + static struct md_sysfs_entry raid5_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR, raid5_show_stripe_cache_size, @@ -3318,8 +3387,10 @@ static struct attribute *raid5_attrs[] = { &raid5_stripecache_size.attr, &raid5_stripecache_active.attr, + &raid5_stripe_deadline.attr, NULL, }; + static struct attribute_group raid5_attrs_group = { .name = NULL, .attrs = raid5_attrs, @@ -3567,6 +3638,8 @@ blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); + atomic_set(&conf->deadline_ms,0); + return 0; abort: if (conf) {