Commit 905e51b39a5558706a6ed883fe104de3d417050b

Authored by Joe Thornber
Committed by Alasdair G Kergon
1 parent 31998ef193

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>

Showing 1 changed file with 26 additions and 2 deletions Side-by-side Diff

drivers/md/dm-thin.c
... ... @@ -23,6 +23,7 @@
23 23 #define DEFERRED_SET_SIZE 64
24 24 #define MAPPING_POOL_SIZE 1024
25 25 #define PRISON_CELLS 1024
  26 +#define COMMIT_PERIOD HZ
26 27  
27 28 /*
28 29 * The block size of the device holding pool data must be
29 30  
... ... @@ -520,8 +521,10 @@
520 521  
521 522 struct workqueue_struct *wq;
522 523 struct work_struct worker;
  524 + struct delayed_work waker;
523 525  
524 526 unsigned ref_count;
  527 + unsigned long last_commit_jiffies;
525 528  
526 529 spinlock_t lock;
527 530 struct bio_list deferred_bios;
... ... @@ -1271,6 +1274,12 @@
1271 1274 }
1272 1275 }
1273 1276  
  1277 +static int need_commit_due_to_time(struct pool *pool)
  1278 +{
  1279 + return jiffies < pool->last_commit_jiffies ||
  1280 + jiffies > pool->last_commit_jiffies + COMMIT_PERIOD;
  1281 +}
  1282 +
1274 1283 static void process_deferred_bios(struct pool *pool)
1275 1284 {
1276 1285 unsigned long flags;
... ... @@ -1312,7 +1321,7 @@
1312 1321 bio_list_init(&pool->deferred_flush_bios);
1313 1322 spin_unlock_irqrestore(&pool->lock, flags);
1314 1323  
1315   - if (bio_list_empty(&bios))
  1324 + if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
1316 1325 return;
1317 1326  
1318 1327 r = dm_pool_commit_metadata(pool->pmd);
... ... @@ -1323,6 +1332,7 @@
1323 1332 bio_io_error(bio);
1324 1333 return;
1325 1334 }
  1335 + pool->last_commit_jiffies = jiffies;
1326 1336  
1327 1337 while ((bio = bio_list_pop(&bios)))
1328 1338 generic_make_request(bio);
... ... @@ -1336,6 +1346,17 @@
1336 1346 process_deferred_bios(pool);
1337 1347 }
1338 1348  
  1349 +/*
  1350 + * We want to commit periodically so that not too much
  1351 + * unwritten data builds up.
  1352 + */
  1353 +static void do_waker(struct work_struct *ws)
  1354 +{
  1355 + struct pool *pool = container_of(to_delayed_work(ws), struct pool, waker);
  1356 + wake_worker(pool);
  1357 + queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
  1358 +}
  1359 +
1339 1360 /*----------------------------------------------------------------*/
1340 1361  
1341 1362 /*
... ... @@ -1545,6 +1566,7 @@
1545 1566 }
1546 1567  
1547 1568 INIT_WORK(&pool->worker, do_worker);
  1569 + INIT_DELAYED_WORK(&pool->waker, do_waker);
1548 1570 spin_lock_init(&pool->lock);
1549 1571 bio_list_init(&pool->deferred_bios);
1550 1572 bio_list_init(&pool->deferred_flush_bios);
... ... @@ -1571,6 +1593,7 @@
1571 1593 goto bad_endio_hook_pool;
1572 1594 }
1573 1595 pool->ref_count = 1;
  1596 + pool->last_commit_jiffies = jiffies;
1574 1597 pool->pool_md = pool_md;
1575 1598 pool->md_dev = metadata_dev;
1576 1599 __pool_table_insert(pool);
... ... @@ -1900,7 +1923,7 @@
1900 1923 __requeue_bios(pool);
1901 1924 spin_unlock_irqrestore(&pool->lock, flags);
1902 1925  
1903   - wake_worker(pool);
  1926 + do_waker(&pool->waker.work);
1904 1927 }
1905 1928  
1906 1929 static void pool_postsuspend(struct dm_target *ti)
... ... @@ -1909,6 +1932,7 @@
1909 1932 struct pool_c *pt = ti->private;
1910 1933 struct pool *pool = pt->pool;
1911 1934  
  1935 + cancel_delayed_work(&pool->waker);
1912 1936 flush_workqueue(pool->wq);
1913 1937  
1914 1938 r = dm_pool_commit_metadata(pool->pmd);