@@ -234,6 +234,7 @@ struct entry {
unsigned hit_count;
unsigned generation;
unsigned tick;
+ unsigned long dirty_writeback_after;
};
/*
@@ -393,6 +394,9 @@ struct mq_policy {
unsigned read_promote_adjustment;
unsigned write_promote_adjustment;
+ /* How long to wait before issuing a writeback */
+ unsigned writeback_delay;
+
/*
* The hash table allows us to quickly find an entry by origin
* block. Both pre_cache and cache entries are in here.
@@ -406,6 +410,7 @@ struct mq_policy {
#define DEFAULT_READ_PROMOTE_ADJUSTMENT 4
#define DEFAULT_WRITE_PROMOTE_ADJUSTMENT 8
#define DISCOURAGE_DEMOTING_DIRTY_THRESHOLD 128
+#define DEFAULT_WRITEBACK_DELAY 10
/*----------------------------------------------------------------*/
@@ -969,6 +974,9 @@ static void __mq_set_clear_dirty(struct mq_policy *mq, dm_oblock_t oblock, bool
del(mq, e);
e->dirty = set;
+ if(set)
+ e->dirty_writeback_after = jiffies + (mq->writeback_delay * HZ);
+
push(mq, e);
}
@@ -1090,9 +1098,12 @@ static int mq_remove_cblock(struct dm_cache_policy *p, dm_cblock_t cblock)
static int __mq_writeback_work(struct mq_policy *mq, dm_oblock_t *oblock,
dm_cblock_t *cblock)
{
- struct entry *e = pop(mq, &mq->cache_dirty);
+ struct entry *e = peek(&mq->cache_dirty);
+ if (!e || time_before(jiffies, e->dirty_writeback_after))
+ return -ENODATA;
- if (!e)
+ e = pop(mq, &mq->cache_dirty);
+ if (unlikely(!e))
return -ENODATA;
*oblock = e->oblock;
@@ -1125,6 +1136,7 @@ static void __force_mapping(struct mq_policy *mq,
del(mq, e);
e->oblock = new_oblock;
e->dirty = true;
+ e->dirty_writeback_after = jiffies + (mq->writeback_delay * HZ);
push(mq, e);
}
}
@@ -1185,6 +1197,9 @@ static int mq_set_config_value(struct dm_cache_policy *p,
else if (!strcasecmp(key, "write_promote_adjustment"))
mq->write_promote_adjustment = tmp;
+ else if (!strcasecmp(key, "writeback_delay"))
+ mq->writeback_delay = tmp;
+
else
return -EINVAL;
@@ -1196,16 +1211,18 @@ static int mq_emit_config_values(struct dm_cache_policy *p, char *result, unsign
ssize_t sz = 0;
struct mq_policy *mq = to_mq_policy(p);
- DMEMIT("10 random_threshold %u "
+ DMEMIT("12 random_threshold %u "
"sequential_threshold %u "
"discard_promote_adjustment %u "
"read_promote_adjustment %u "
- "write_promote_adjustment %u",
+ "write_promote_adjustment %u "
+ "writeback_delay %u",
mq->tracker.thresholds[PATTERN_RANDOM],
mq->tracker.thresholds[PATTERN_SEQUENTIAL],
mq->discard_promote_adjustment,
mq->read_promote_adjustment,
- mq->write_promote_adjustment);
+ mq->write_promote_adjustment,
+ mq->writeback_delay);
return 0;
}
@@ -1260,6 +1277,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
mq->discard_promote_adjustment = DEFAULT_DISCARD_PROMOTE_ADJUSTMENT;
mq->read_promote_adjustment = DEFAULT_READ_PROMOTE_ADJUSTMENT;
mq->write_promote_adjustment = DEFAULT_WRITE_PROMOTE_ADJUSTMENT;
+ mq->writeback_delay = DEFAULT_WRITEBACK_DELAY;
mutex_init(&mq->lock);
spin_lock_init(&mq->tick_lock);