From: Nick Piggin Here are some random cleanups. Main one is removing the histogram. It can go back in if we want to try out different types of stats, but for now it seems OK. Functional change _should_ only be slightly lower MAX_THINKTIME allowed, even though its now basically unlimited with the removal of the histogram. See comment for details. drivers/block/as-iosched.c | 62 +++++++++++++++++++++++++-------------------- 1 files changed, 35 insertions(+), 27 deletions(-) diff -puN drivers/block/as-iosched.c~as-misc-cleanups drivers/block/as-iosched.c --- 25/drivers/block/as-iosched.c~as-misc-cleanups 2003-03-19 22:34:32.000000000 -0800 +++ 25-akpm/drivers/block/as-iosched.c 2003-03-19 22:34:32.000000000 -0800 @@ -91,8 +91,14 @@ static unsigned long antic_expire = HZ / * to a single as_io_context may appear in multiple queues at once. */ -/* Keep track of up to 30ms thinktimes */ -#define MAX_THINKTIME (HZ/33UL) +/* + * Keep track of up to 20ms thinktimes. We can go as big as we like here, + * however huge values tend to interfere and not decay fast enough. A program + * might be in a non-io phase of operation. Waiting on user input for example, + * or doing a lengthy computation. A small penalty can be justified there, and + * will still catch out those processes that constantly have large thinktimes. + */ +#define MAX_THINKTIME (HZ/50UL) struct as_io_context { atomic_t refcount; @@ -104,8 +110,9 @@ struct as_io_context { /* IO History tracking */ /* Thinktime */ unsigned long last_end_request; - unsigned long thinktime[MAX_THINKTIME]; - unsigned long mean_thinktime; + unsigned long ttime_total; + unsigned long ttime_samples; + unsigned long ttime_mean; /* Read / write pattern */ int last_data_dir; unsigned long dir_after_read[2]; @@ -269,8 +276,12 @@ static struct as_io_context *get_as_io_c ret->state = 1 << AS_TASK_RUNNING; atomic_set(&ret->nr_queued, 0); atomic_set(&ret->nr_dispatched, 0); - memset(ret->thinktime, 0, sizeof(ret->thinktime)); - ret->mean_thinktime = 0; + ret->ttime_total = 0; + ret->ttime_samples = 0; + ret->ttime_mean = 0; + ret->dir_after_read[READ] = 0; + ret->dir_after_read[WRITE] = 0; + ret->mean_dir_after_read = READ; tsk->as_io_context = ret; } } @@ -760,7 +771,7 @@ static int as_can_break_anticipation(str return 1; } - if (aic && aic->mean_thinktime > max(HZ/200, 1)) { + if (aic && aic->ttime_mean > max(HZ/200, 1)) { ant_stats.big_thinktime++; return 1; } @@ -811,15 +822,12 @@ static int as_can_anticipate(struct as_d /* * as_update_iohist keeps a decaying histogram of IO thinktimes, and - * updates @aic->mean_thinktime based on that. It is called when a new + * updates @aic->ttime_mean based on that. It is called when a new * request is queued. */ static void as_update_iohist(struct as_io_context *aic, int data_dir) { - unsigned i; unsigned long thinktime; - unsigned long total = 0; - unsigned long num = 0; if (aic == NULL) return; @@ -830,32 +838,32 @@ static void as_update_iohist(struct as_i thinktime = jiffies - aic->last_end_request; thinktime = min(thinktime, MAX_THINKTIME-1); /* fixed point: 1.0 == 1<<8 */ - aic->thinktime[thinktime] += 256; - - for (i = 0; i < MAX_THINKTIME; i++) { - unsigned long tt = aic->thinktime[i]; - total += i*tt; - num += tt; - - aic->thinktime[i] = (tt>>1) + (tt>>2); - } - /* fixed point factor is cancelled here */ - if (num) - aic->mean_thinktime = (total+128) / num; + aic->ttime_samples += 256; + aic->ttime_total += 256*thinktime; + if (aic->ttime_samples) + /* fixed point factor is cancelled here */ + aic->ttime_mean = (aic->ttime_total + 128) + / aic->ttime_samples; + aic->ttime_samples = (aic->ttime_samples>>1) + + (aic->ttime_samples>>2); + aic->ttime_total = (aic->ttime_total>>1) + + (aic->ttime_total>>2); } /* Calculate read/write pattern */ if (aic->last_data_dir == READ) { + unsigned long rprob, wprob; aic->dir_after_read[data_dir] += 256; + rprob = aic->dir_after_read[READ]; + wprob = aic->dir_after_read[WRITE]; - if (aic->dir_after_read[READ]*4 >= - aic->dir_after_read[WRITE]*5) + if (rprob*4 >= wprob*5) aic->mean_dir_after_read = READ; else aic->mean_dir_after_read = WRITE; - aic->dir_after_read[READ] = (aic->dir_after_read[READ]>>1) + (aic->dir_after_read[READ]>>2); - aic->dir_after_read[WRITE] = (aic->dir_after_read[WRITE]>>1) + (aic->dir_after_read[WRITE]>>2);; + aic->dir_after_read[READ] = (rprob>>1) + (rprob>>2); + aic->dir_after_read[WRITE] = (wprob>>1) + (wprob>>2);; } } } _