diff options
author | Joe Thornber <ejt@redhat.com> | 2014-10-22 09:30:58 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2014-11-10 15:25:29 -0500 |
commit | b155aa0e5a81ea1f05ff7aced0ec8e34c980c19e (patch) | |
tree | 56f73848b2e70f8a9eb4d97d51b742fc93c3ad0f /drivers/md | |
parent | 41abc4e1af369bb5438eaee398e3beee690cc8ca (diff) |
dm cache policy mq: tweak algorithm that decides when to promote a block
Rather than maintaining a separate promote_threshold variable that we
periodically update we now use the hit count of the oldest clean
block. Also add a fudge factor to discourage demoting dirty blocks.
With some tests this has a sizeable difference, because the old code
was too eager to demote blocks. For example, device-mapper-test-suite's
git_extract_cache_quick test goes from taking 190 seconds, to 142
(linear on spindle takes 250).
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-cache-policy-mq.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c index 0e385e40909e..334d098d720d 100644 --- a/drivers/md/dm-cache-policy-mq.c +++ b/drivers/md/dm-cache-policy-mq.c | |||
@@ -181,24 +181,30 @@ static void queue_shift_down(struct queue *q) | |||
181 | * Gives us the oldest entry of the lowest popoulated level. If the first | 181 | * Gives us the oldest entry of the lowest popoulated level. If the first |
182 | * level is emptied then we shift down one level. | 182 | * level is emptied then we shift down one level. |
183 | */ | 183 | */ |
184 | static struct list_head *queue_pop(struct queue *q) | 184 | static struct list_head *queue_peek(struct queue *q) |
185 | { | 185 | { |
186 | unsigned level; | 186 | unsigned level; |
187 | struct list_head *r; | ||
188 | 187 | ||
189 | for (level = 0; level < NR_QUEUE_LEVELS; level++) | 188 | for (level = 0; level < NR_QUEUE_LEVELS; level++) |
190 | if (!list_empty(q->qs + level)) { | 189 | if (!list_empty(q->qs + level)) |
191 | r = q->qs[level].next; | 190 | return q->qs[level].next; |
192 | list_del(r); | ||
193 | 191 | ||
194 | /* have we just emptied the bottom level? */ | 192 | return NULL; |
195 | if (level == 0 && list_empty(q->qs)) | 193 | } |
196 | queue_shift_down(q); | ||
197 | 194 | ||
198 | return r; | 195 | static struct list_head *queue_pop(struct queue *q) |
199 | } | 196 | { |
197 | struct list_head *r = queue_peek(q); | ||
200 | 198 | ||
201 | return NULL; | 199 | if (r) { |
200 | list_del(r); | ||
201 | |||
202 | /* have we just emptied the bottom level? */ | ||
203 | if (list_empty(q->qs)) | ||
204 | queue_shift_down(q); | ||
205 | } | ||
206 | |||
207 | return r; | ||
202 | } | 208 | } |
203 | 209 | ||
204 | static struct list_head *list_pop(struct list_head *lh) | 210 | static struct list_head *list_pop(struct list_head *lh) |
@@ -383,13 +389,6 @@ struct mq_policy { | |||
383 | unsigned generation; | 389 | unsigned generation; |
384 | unsigned generation_period; /* in lookups (will probably change) */ | 390 | unsigned generation_period; /* in lookups (will probably change) */ |
385 | 391 | ||
386 | /* | ||
387 | * Entries in the pre_cache whose hit count passes the promotion | ||
388 | * threshold move to the cache proper. Working out the correct | ||
389 | * value for the promotion_threshold is crucial to this policy. | ||
390 | */ | ||
391 | unsigned promote_threshold; | ||
392 | |||
393 | unsigned discard_promote_adjustment; | 392 | unsigned discard_promote_adjustment; |
394 | unsigned read_promote_adjustment; | 393 | unsigned read_promote_adjustment; |
395 | unsigned write_promote_adjustment; | 394 | unsigned write_promote_adjustment; |
@@ -406,6 +405,7 @@ struct mq_policy { | |||
406 | #define DEFAULT_DISCARD_PROMOTE_ADJUSTMENT 1 | 405 | #define DEFAULT_DISCARD_PROMOTE_ADJUSTMENT 1 |
407 | #define DEFAULT_READ_PROMOTE_ADJUSTMENT 4 | 406 | #define DEFAULT_READ_PROMOTE_ADJUSTMENT 4 |
408 | #define DEFAULT_WRITE_PROMOTE_ADJUSTMENT 8 | 407 | #define DEFAULT_WRITE_PROMOTE_ADJUSTMENT 8 |
408 | #define DISCOURAGE_DEMOTING_DIRTY_THRESHOLD 128 | ||
409 | 409 | ||
410 | /*----------------------------------------------------------------*/ | 410 | /*----------------------------------------------------------------*/ |
411 | 411 | ||
@@ -518,6 +518,12 @@ static struct entry *pop(struct mq_policy *mq, struct queue *q) | |||
518 | return e; | 518 | return e; |
519 | } | 519 | } |
520 | 520 | ||
521 | static struct entry *peek(struct queue *q) | ||
522 | { | ||
523 | struct list_head *h = queue_peek(q); | ||
524 | return h ? container_of(h, struct entry, list) : NULL; | ||
525 | } | ||
526 | |||
521 | /* | 527 | /* |
522 | * Has this entry already been updated? | 528 | * Has this entry already been updated? |
523 | */ | 529 | */ |
@@ -570,10 +576,6 @@ static void check_generation(struct mq_policy *mq) | |||
570 | break; | 576 | break; |
571 | } | 577 | } |
572 | } | 578 | } |
573 | |||
574 | mq->promote_threshold = nr ? total / nr : 1; | ||
575 | if (mq->promote_threshold * nr < total) | ||
576 | mq->promote_threshold++; | ||
577 | } | 579 | } |
578 | } | 580 | } |
579 | 581 | ||
@@ -641,6 +643,30 @@ static int demote_cblock(struct mq_policy *mq, dm_oblock_t *oblock) | |||
641 | } | 643 | } |
642 | 644 | ||
643 | /* | 645 | /* |
646 | * Entries in the pre_cache whose hit count passes the promotion | ||
647 | * threshold move to the cache proper. Working out the correct | ||
648 | * value for the promotion_threshold is crucial to this policy. | ||
649 | */ | ||
650 | static unsigned promote_threshold(struct mq_policy *mq) | ||
651 | { | ||
652 | struct entry *e; | ||
653 | |||
654 | if (any_free_cblocks(mq)) | ||
655 | return 0; | ||
656 | |||
657 | e = peek(&mq->cache_clean); | ||
658 | if (e) | ||
659 | return e->hit_count; | ||
660 | |||
661 | e = peek(&mq->cache_dirty); | ||
662 | if (e) | ||
663 | return e->hit_count + DISCOURAGE_DEMOTING_DIRTY_THRESHOLD; | ||
664 | |||
665 | /* This should never happen */ | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | /* | ||
644 | * We modify the basic promotion_threshold depending on the specific io. | 670 | * We modify the basic promotion_threshold depending on the specific io. |
645 | * | 671 | * |
646 | * If the origin block has been discarded then there's no cost to copy it | 672 | * If the origin block has been discarded then there's no cost to copy it |
@@ -653,7 +679,7 @@ static unsigned adjusted_promote_threshold(struct mq_policy *mq, | |||
653 | bool discarded_oblock, int data_dir) | 679 | bool discarded_oblock, int data_dir) |
654 | { | 680 | { |
655 | if (data_dir == READ) | 681 | if (data_dir == READ) |
656 | return mq->promote_threshold + mq->read_promote_adjustment; | 682 | return promote_threshold(mq) + mq->read_promote_adjustment; |
657 | 683 | ||
658 | if (discarded_oblock && (any_free_cblocks(mq) || any_clean_cblocks(mq))) { | 684 | if (discarded_oblock && (any_free_cblocks(mq) || any_clean_cblocks(mq))) { |
659 | /* | 685 | /* |
@@ -663,7 +689,7 @@ static unsigned adjusted_promote_threshold(struct mq_policy *mq, | |||
663 | return mq->discard_promote_adjustment; | 689 | return mq->discard_promote_adjustment; |
664 | } | 690 | } |
665 | 691 | ||
666 | return mq->promote_threshold + mq->write_promote_adjustment; | 692 | return promote_threshold(mq) + mq->write_promote_adjustment; |
667 | } | 693 | } |
668 | 694 | ||
669 | static bool should_promote(struct mq_policy *mq, struct entry *e, | 695 | static bool should_promote(struct mq_policy *mq, struct entry *e, |
@@ -1230,7 +1256,6 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, | |||
1230 | mq->tick = 0; | 1256 | mq->tick = 0; |
1231 | mq->hit_count = 0; | 1257 | mq->hit_count = 0; |
1232 | mq->generation = 0; | 1258 | mq->generation = 0; |
1233 | mq->promote_threshold = 0; | ||
1234 | mq->discard_promote_adjustment = DEFAULT_DISCARD_PROMOTE_ADJUSTMENT; | 1259 | mq->discard_promote_adjustment = DEFAULT_DISCARD_PROMOTE_ADJUSTMENT; |
1235 | mq->read_promote_adjustment = DEFAULT_READ_PROMOTE_ADJUSTMENT; | 1260 | mq->read_promote_adjustment = DEFAULT_READ_PROMOTE_ADJUSTMENT; |
1236 | mq->write_promote_adjustment = DEFAULT_WRITE_PROMOTE_ADJUSTMENT; | 1261 | mq->write_promote_adjustment = DEFAULT_WRITE_PROMOTE_ADJUSTMENT; |