aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-cache-policy-mq.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2013-12-09 07:53:05 -0500
committerMike Snitzer <snitzer@redhat.com>2014-01-07 10:14:33 -0500
commit78e03d69733c48312ae81fe4ac0790dbea412b9d (patch)
tree47ffaceb2c4c977ab639810d6812a356f364def4 /drivers/md/dm-cache-policy-mq.c
parentb815805154cc62debbc423a6c27ae39290b300ae (diff)
dm cache policy mq: introduce three promotion threshold tunables
Internally the mq policy maintains a promotion threshold variable. If the hit count of a block not in the cache goes above this threshold it gets promoted to the cache. This patch introduces three new tunables that allow you to tweak the promotion threshold by adding a small value. These adjustments depend on the io type: read_promote_adjustment: READ io, default 4 write_promote_adjustment: WRITE io, default 8 discard_promote_adjustment: READ/WRITE io to a discarded block, default 1 If you're trying to quickly warm a new cache device you may wish to reduce these to encourage promotion. Remember to switch them back to their defaults after the cache fills though. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-cache-policy-mq.c')
-rw-r--r--drivers/md/dm-cache-policy-mq.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c
index 7f1aaa38a7e0..e63e36cefc89 100644
--- a/drivers/md/dm-cache-policy-mq.c
+++ b/drivers/md/dm-cache-policy-mq.c
@@ -390,6 +390,10 @@ struct mq_policy {
390 */ 390 */
391 unsigned promote_threshold; 391 unsigned promote_threshold;
392 392
393 unsigned discard_promote_adjustment;
394 unsigned read_promote_adjustment;
395 unsigned write_promote_adjustment;
396
393 /* 397 /*
394 * The hash table allows us to quickly find an entry by origin 398 * The hash table allows us to quickly find an entry by origin
395 * block. Both pre_cache and cache entries are in here. 399 * block. Both pre_cache and cache entries are in here.
@@ -399,6 +403,10 @@ struct mq_policy {
399 struct hlist_head *table; 403 struct hlist_head *table;
400}; 404};
401 405
406#define DEFAULT_DISCARD_PROMOTE_ADJUSTMENT 1
407#define DEFAULT_READ_PROMOTE_ADJUSTMENT 4
408#define DEFAULT_WRITE_PROMOTE_ADJUSTMENT 8
409
402/*----------------------------------------------------------------*/ 410/*----------------------------------------------------------------*/
403 411
404/* 412/*
@@ -641,25 +649,21 @@ static int demote_cblock(struct mq_policy *mq, dm_oblock_t *oblock)
641 * We bias towards reads, since they can be demoted at no cost if they 649 * We bias towards reads, since they can be demoted at no cost if they
642 * haven't been dirtied. 650 * haven't been dirtied.
643 */ 651 */
644#define DISCARDED_PROMOTE_THRESHOLD 1
645#define READ_PROMOTE_THRESHOLD 4
646#define WRITE_PROMOTE_THRESHOLD 8
647
648static unsigned adjusted_promote_threshold(struct mq_policy *mq, 652static unsigned adjusted_promote_threshold(struct mq_policy *mq,
649 bool discarded_oblock, int data_dir) 653 bool discarded_oblock, int data_dir)
650{ 654{
651 if (data_dir == READ) 655 if (data_dir == READ)
652 return mq->promote_threshold + READ_PROMOTE_THRESHOLD; 656 return mq->promote_threshold + mq->read_promote_adjustment;
653 657
654 if (discarded_oblock && (any_free_cblocks(mq) || any_clean_cblocks(mq))) { 658 if (discarded_oblock && (any_free_cblocks(mq) || any_clean_cblocks(mq))) {
655 /* 659 /*
656 * We don't need to do any copying at all, so give this a 660 * We don't need to do any copying at all, so give this a
657 * very low threshold. 661 * very low threshold.
658 */ 662 */
659 return DISCARDED_PROMOTE_THRESHOLD; 663 return mq->discard_promote_adjustment;
660 } 664 }
661 665
662 return mq->promote_threshold + WRITE_PROMOTE_THRESHOLD; 666 return mq->promote_threshold + mq->write_promote_adjustment;
663} 667}
664 668
665static bool should_promote(struct mq_policy *mq, struct entry *e, 669static bool should_promote(struct mq_policy *mq, struct entry *e,
@@ -808,7 +812,7 @@ static int no_entry_found(struct mq_policy *mq, dm_oblock_t oblock,
808 bool can_migrate, bool discarded_oblock, 812 bool can_migrate, bool discarded_oblock,
809 int data_dir, struct policy_result *result) 813 int data_dir, struct policy_result *result)
810{ 814{
811 if (adjusted_promote_threshold(mq, discarded_oblock, data_dir) == 1) { 815 if (adjusted_promote_threshold(mq, discarded_oblock, data_dir) <= 1) {
812 if (can_migrate) 816 if (can_migrate)
813 insert_in_cache(mq, oblock, result); 817 insert_in_cache(mq, oblock, result);
814 else 818 else
@@ -1134,20 +1138,28 @@ static int mq_set_config_value(struct dm_cache_policy *p,
1134 const char *key, const char *value) 1138 const char *key, const char *value)
1135{ 1139{
1136 struct mq_policy *mq = to_mq_policy(p); 1140 struct mq_policy *mq = to_mq_policy(p);
1137 enum io_pattern pattern;
1138 unsigned long tmp; 1141 unsigned long tmp;
1139 1142
1140 if (!strcasecmp(key, "random_threshold"))
1141 pattern = PATTERN_RANDOM;
1142 else if (!strcasecmp(key, "sequential_threshold"))
1143 pattern = PATTERN_SEQUENTIAL;
1144 else
1145 return -EINVAL;
1146
1147 if (kstrtoul(value, 10, &tmp)) 1143 if (kstrtoul(value, 10, &tmp))
1148 return -EINVAL; 1144 return -EINVAL;
1149 1145
1150 mq->tracker.thresholds[pattern] = tmp; 1146 if (!strcasecmp(key, "random_threshold")) {
1147 mq->tracker.thresholds[PATTERN_RANDOM] = tmp;
1148
1149 } else if (!strcasecmp(key, "sequential_threshold")) {
1150 mq->tracker.thresholds[PATTERN_SEQUENTIAL] = tmp;
1151
1152 } else if (!strcasecmp(key, "discard_promote_adjustment"))
1153 mq->discard_promote_adjustment = tmp;
1154
1155 else if (!strcasecmp(key, "read_promote_adjustment"))
1156 mq->read_promote_adjustment = tmp;
1157
1158 else if (!strcasecmp(key, "write_promote_adjustment"))
1159 mq->write_promote_adjustment = tmp;
1160
1161 else
1162 return -EINVAL;
1151 1163
1152 return 0; 1164 return 0;
1153} 1165}
@@ -1157,9 +1169,16 @@ static int mq_emit_config_values(struct dm_cache_policy *p, char *result, unsign
1157 ssize_t sz = 0; 1169 ssize_t sz = 0;
1158 struct mq_policy *mq = to_mq_policy(p); 1170 struct mq_policy *mq = to_mq_policy(p);
1159 1171
1160 DMEMIT("4 random_threshold %u sequential_threshold %u", 1172 DMEMIT("10 random_threshold %u "
1173 "sequential_threshold %u "
1174 "discard_promote_adjustment %u "
1175 "read_promote_adjustment %u "
1176 "write_promote_adjustment %u",
1161 mq->tracker.thresholds[PATTERN_RANDOM], 1177 mq->tracker.thresholds[PATTERN_RANDOM],
1162 mq->tracker.thresholds[PATTERN_SEQUENTIAL]); 1178 mq->tracker.thresholds[PATTERN_SEQUENTIAL],
1179 mq->discard_promote_adjustment,
1180 mq->read_promote_adjustment,
1181 mq->write_promote_adjustment);
1163 1182
1164 return 0; 1183 return 0;
1165} 1184}
@@ -1212,6 +1231,9 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
1212 mq->hit_count = 0; 1231 mq->hit_count = 0;
1213 mq->generation = 0; 1232 mq->generation = 0;
1214 mq->promote_threshold = 0; 1233 mq->promote_threshold = 0;
1234 mq->discard_promote_adjustment = DEFAULT_DISCARD_PROMOTE_ADJUSTMENT;
1235 mq->read_promote_adjustment = DEFAULT_READ_PROMOTE_ADJUSTMENT;
1236 mq->write_promote_adjustment = DEFAULT_WRITE_PROMOTE_ADJUSTMENT;
1215 mutex_init(&mq->lock); 1237 mutex_init(&mq->lock);
1216 spin_lock_init(&mq->tick_lock); 1238 spin_lock_init(&mq->tick_lock);
1217 1239
@@ -1243,7 +1265,7 @@ bad_pre_cache_init:
1243 1265
1244static struct dm_cache_policy_type mq_policy_type = { 1266static struct dm_cache_policy_type mq_policy_type = {
1245 .name = "mq", 1267 .name = "mq",
1246 .version = {1, 1, 0}, 1268 .version = {1, 2, 0},
1247 .hint_size = 4, 1269 .hint_size = 4,
1248 .owner = THIS_MODULE, 1270 .owner = THIS_MODULE,
1249 .create = mq_create 1271 .create = mq_create
@@ -1251,7 +1273,7 @@ static struct dm_cache_policy_type mq_policy_type = {
1251 1273
1252static struct dm_cache_policy_type default_policy_type = { 1274static struct dm_cache_policy_type default_policy_type = {
1253 .name = "default", 1275 .name = "default",
1254 .version = {1, 1, 0}, 1276 .version = {1, 2, 0},
1255 .hint_size = 4, 1277 .hint_size = 4,
1256 .owner = THIS_MODULE, 1278 .owner = THIS_MODULE,
1257 .create = mq_create 1279 .create = mq_create