diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index bb43a1677626..15152e2da0d2 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -346,14 +346,16 @@ static int cfq_queue_empty(request_queue_t *q) | |||
346 | /* | 346 | /* |
347 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. | 347 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. |
348 | * We choose the request that is closest to the head right now. Distance | 348 | * We choose the request that is closest to the head right now. Distance |
349 | * behind the head are penalized and only allowed to a certain extent. | 349 | * behind the head is penalized and only allowed to a certain extent. |
350 | */ | 350 | */ |
351 | static struct cfq_rq * | 351 | static struct cfq_rq * |
352 | cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | 352 | cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) |
353 | { | 353 | { |
354 | sector_t last, s1, s2, d1 = 0, d2 = 0; | 354 | sector_t last, s1, s2, d1 = 0, d2 = 0; |
355 | int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */ | ||
356 | unsigned long back_max; | 355 | unsigned long back_max; |
356 | #define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */ | ||
357 | #define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */ | ||
358 | unsigned wrap = 0; /* bit mask: requests behind the disk head? */ | ||
357 | 359 | ||
358 | if (crq1 == NULL || crq1 == crq2) | 360 | if (crq1 == NULL || crq1 == crq2) |
359 | return crq2; | 361 | return crq2; |
@@ -385,35 +387,47 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | |||
385 | else if (s1 + back_max >= last) | 387 | else if (s1 + back_max >= last) |
386 | d1 = (last - s1) * cfqd->cfq_back_penalty; | 388 | d1 = (last - s1) * cfqd->cfq_back_penalty; |
387 | else | 389 | else |
388 | r1_wrap = 1; | 390 | wrap |= CFQ_RQ1_WRAP; |
389 | 391 | ||
390 | if (s2 >= last) | 392 | if (s2 >= last) |
391 | d2 = s2 - last; | 393 | d2 = s2 - last; |
392 | else if (s2 + back_max >= last) | 394 | else if (s2 + back_max >= last) |
393 | d2 = (last - s2) * cfqd->cfq_back_penalty; | 395 | d2 = (last - s2) * cfqd->cfq_back_penalty; |
394 | else | 396 | else |
395 | r2_wrap = 1; | 397 | wrap |= CFQ_RQ2_WRAP; |
396 | 398 | ||
397 | /* Found required data */ | 399 | /* Found required data */ |
398 | if (!r1_wrap && r2_wrap) | 400 | |
399 | return crq1; | 401 | /* |
400 | else if (!r2_wrap && r1_wrap) | 402 | * By doing switch() on the bit mask "wrap" we avoid having to |
401 | return crq2; | 403 | * check two variables for all permutations: --> faster! |
402 | else if (r1_wrap && r2_wrap) { | 404 | */ |
403 | /* both behind the head */ | 405 | switch (wrap) { |
404 | if (s1 <= s2) | 406 | case 0: /* common case for CFQ: crq1 and crq2 not wrapped */ |
407 | if (d1 < d2) | ||
405 | return crq1; | 408 | return crq1; |
406 | else | 409 | else if (d2 < d1) |
407 | return crq2; | 410 | return crq2; |
408 | } | 411 | else { |
412 | if (s1 >= s2) | ||
413 | return crq1; | ||
414 | else | ||
415 | return crq2; | ||
416 | } | ||
409 | 417 | ||
410 | /* Both requests in front of the head */ | 418 | case CFQ_RQ2_WRAP: |
411 | if (d1 < d2) | ||
412 | return crq1; | 419 | return crq1; |
413 | else if (d2 < d1) | 420 | case CFQ_RQ1_WRAP: |
414 | return crq2; | 421 | return crq2; |
415 | else { | 422 | case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */ |
416 | if (s1 >= s2) | 423 | default: |
424 | /* | ||
425 | * Since both rqs are wrapped, | ||
426 | * start with the one that's further behind head | ||
427 | * (--> only *one* back seek required), | ||
428 | * since back seek takes more time than forward. | ||
429 | */ | ||
430 | if (s1 <= s2) | ||
417 | return crq1; | 431 | return crq1; |
418 | else | 432 | else |
419 | return crq2; | 433 | return crq2; |