mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 17:01:14 +00:00
dm thin: commit outstanding data every second
Commit unwritten data every second to prevent too much building up. Released blocks don't become available until after the next commit (for crash resilience). Prior to this patch commits were only triggered by a message to the target or a REQ_{FLUSH,FUA} bio. This allowed far too big a position to build up. The interval is hard-coded to 1 second. This is a sensible setting. I'm not making this user configurable, since there isn't much to be gained by tweaking this - and a lot lost by setting it far too high. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
This commit is contained in:
parent
31998ef193
commit
905e51b39a
1 changed files with 26 additions and 2 deletions
|
@ -23,6 +23,7 @@
|
||||||
#define DEFERRED_SET_SIZE 64
|
#define DEFERRED_SET_SIZE 64
|
||||||
#define MAPPING_POOL_SIZE 1024
|
#define MAPPING_POOL_SIZE 1024
|
||||||
#define PRISON_CELLS 1024
|
#define PRISON_CELLS 1024
|
||||||
|
#define COMMIT_PERIOD HZ
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The block size of the device holding pool data must be
|
* The block size of the device holding pool data must be
|
||||||
|
@ -520,8 +521,10 @@ struct pool {
|
||||||
|
|
||||||
struct workqueue_struct *wq;
|
struct workqueue_struct *wq;
|
||||||
struct work_struct worker;
|
struct work_struct worker;
|
||||||
|
struct delayed_work waker;
|
||||||
|
|
||||||
unsigned ref_count;
|
unsigned ref_count;
|
||||||
|
unsigned long last_commit_jiffies;
|
||||||
|
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
struct bio_list deferred_bios;
|
struct bio_list deferred_bios;
|
||||||
|
@ -1271,6 +1274,12 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int need_commit_due_to_time(struct pool *pool)
|
||||||
|
{
|
||||||
|
return jiffies < pool->last_commit_jiffies ||
|
||||||
|
jiffies > pool->last_commit_jiffies + COMMIT_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
static void process_deferred_bios(struct pool *pool)
|
static void process_deferred_bios(struct pool *pool)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -1312,7 +1321,7 @@ static void process_deferred_bios(struct pool *pool)
|
||||||
bio_list_init(&pool->deferred_flush_bios);
|
bio_list_init(&pool->deferred_flush_bios);
|
||||||
spin_unlock_irqrestore(&pool->lock, flags);
|
spin_unlock_irqrestore(&pool->lock, flags);
|
||||||
|
|
||||||
if (bio_list_empty(&bios))
|
if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r = dm_pool_commit_metadata(pool->pmd);
|
r = dm_pool_commit_metadata(pool->pmd);
|
||||||
|
@ -1323,6 +1332,7 @@ static void process_deferred_bios(struct pool *pool)
|
||||||
bio_io_error(bio);
|
bio_io_error(bio);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pool->last_commit_jiffies = jiffies;
|
||||||
|
|
||||||
while ((bio = bio_list_pop(&bios)))
|
while ((bio = bio_list_pop(&bios)))
|
||||||
generic_make_request(bio);
|
generic_make_request(bio);
|
||||||
|
@ -1336,6 +1346,17 @@ static void do_worker(struct work_struct *ws)
|
||||||
process_deferred_bios(pool);
|
process_deferred_bios(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We want to commit periodically so that not too much
|
||||||
|
* unwritten data builds up.
|
||||||
|
*/
|
||||||
|
static void do_waker(struct work_struct *ws)
|
||||||
|
{
|
||||||
|
struct pool *pool = container_of(to_delayed_work(ws), struct pool, waker);
|
||||||
|
wake_worker(pool);
|
||||||
|
queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1545,6 +1566,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_WORK(&pool->worker, do_worker);
|
INIT_WORK(&pool->worker, do_worker);
|
||||||
|
INIT_DELAYED_WORK(&pool->waker, do_waker);
|
||||||
spin_lock_init(&pool->lock);
|
spin_lock_init(&pool->lock);
|
||||||
bio_list_init(&pool->deferred_bios);
|
bio_list_init(&pool->deferred_bios);
|
||||||
bio_list_init(&pool->deferred_flush_bios);
|
bio_list_init(&pool->deferred_flush_bios);
|
||||||
|
@ -1571,6 +1593,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
|
||||||
goto bad_endio_hook_pool;
|
goto bad_endio_hook_pool;
|
||||||
}
|
}
|
||||||
pool->ref_count = 1;
|
pool->ref_count = 1;
|
||||||
|
pool->last_commit_jiffies = jiffies;
|
||||||
pool->pool_md = pool_md;
|
pool->pool_md = pool_md;
|
||||||
pool->md_dev = metadata_dev;
|
pool->md_dev = metadata_dev;
|
||||||
__pool_table_insert(pool);
|
__pool_table_insert(pool);
|
||||||
|
@ -1900,7 +1923,7 @@ static void pool_resume(struct dm_target *ti)
|
||||||
__requeue_bios(pool);
|
__requeue_bios(pool);
|
||||||
spin_unlock_irqrestore(&pool->lock, flags);
|
spin_unlock_irqrestore(&pool->lock, flags);
|
||||||
|
|
||||||
wake_worker(pool);
|
do_waker(&pool->waker.work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pool_postsuspend(struct dm_target *ti)
|
static void pool_postsuspend(struct dm_target *ti)
|
||||||
|
@ -1909,6 +1932,7 @@ static void pool_postsuspend(struct dm_target *ti)
|
||||||
struct pool_c *pt = ti->private;
|
struct pool_c *pt = ti->private;
|
||||||
struct pool *pool = pt->pool;
|
struct pool *pool = pt->pool;
|
||||||
|
|
||||||
|
cancel_delayed_work(&pool->waker);
|
||||||
flush_workqueue(pool->wq);
|
flush_workqueue(pool->wq);
|
||||||
|
|
||||||
r = dm_pool_commit_metadata(pool->pmd);
|
r = dm_pool_commit_metadata(pool->pmd);
|
||||||
|
|
Loading…
Reference in a new issue