Commit 9e5c3535 authored by Slava Pestov's avatar Slava Pestov Committed by Kent Overstreet

bcache: fix uninterruptible sleep in writeback thread

There were two issues here:

- writeback thread did not start until the device first became dirty
- writeback thread used uninterruptible sleep once running

Without this patch I see kernel warnings printed and a load average of
1.52 after booting my test VM. With this patch the warnings are gone and
the load average is near 0.00 as expected.
Signed-off-by: default avatarKent Overstreet <kmo@daterainc.com>
parent c5aa4a31
...@@ -1042,6 +1042,9 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c) ...@@ -1042,6 +1042,9 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
*/ */
atomic_set(&dc->count, 1); atomic_set(&dc->count, 1);
if (bch_cached_dev_writeback_start(dc))
return -ENOMEM;
if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) { if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
bch_sectors_dirty_init(dc); bch_sectors_dirty_init(dc);
atomic_set(&dc->has_dirty, 1); atomic_set(&dc->has_dirty, 1);
......
...@@ -239,7 +239,7 @@ static void read_dirty(struct cached_dev *dc) ...@@ -239,7 +239,7 @@ static void read_dirty(struct cached_dev *dc)
if (KEY_START(&w->key) != dc->last_read || if (KEY_START(&w->key) != dc->last_read ||
jiffies_to_msecs(delay) > 50) jiffies_to_msecs(delay) > 50)
while (!kthread_should_stop() && delay) while (!kthread_should_stop() && delay)
delay = schedule_timeout_uninterruptible(delay); delay = schedule_timeout_interruptible(delay);
dc->last_read = KEY_OFFSET(&w->key); dc->last_read = KEY_OFFSET(&w->key);
...@@ -436,7 +436,7 @@ static int bch_writeback_thread(void *arg) ...@@ -436,7 +436,7 @@ static int bch_writeback_thread(void *arg)
while (delay && while (delay &&
!kthread_should_stop() && !kthread_should_stop() &&
!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
delay = schedule_timeout_uninterruptible(delay); delay = schedule_timeout_interruptible(delay);
} }
} }
...@@ -478,7 +478,7 @@ void bch_sectors_dirty_init(struct cached_dev *dc) ...@@ -478,7 +478,7 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk); dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
} }
int bch_cached_dev_writeback_init(struct cached_dev *dc) void bch_cached_dev_writeback_init(struct cached_dev *dc)
{ {
sema_init(&dc->in_flight, 64); sema_init(&dc->in_flight, 64);
init_rwsem(&dc->writeback_lock); init_rwsem(&dc->writeback_lock);
...@@ -494,14 +494,20 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc) ...@@ -494,14 +494,20 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc)
dc->writeback_rate_d_term = 30; dc->writeback_rate_d_term = 30;
dc->writeback_rate_p_term_inverse = 6000; dc->writeback_rate_p_term_inverse = 6000;
INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
}
int bch_cached_dev_writeback_start(struct cached_dev *dc)
{
dc->writeback_thread = kthread_create(bch_writeback_thread, dc, dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
"bcache_writeback"); "bcache_writeback");
if (IS_ERR(dc->writeback_thread)) if (IS_ERR(dc->writeback_thread))
return PTR_ERR(dc->writeback_thread); return PTR_ERR(dc->writeback_thread);
INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
schedule_delayed_work(&dc->writeback_rate_update, schedule_delayed_work(&dc->writeback_rate_update,
dc->writeback_rate_update_seconds * HZ); dc->writeback_rate_update_seconds * HZ);
bch_writeback_queue(dc);
return 0; return 0;
} }
...@@ -85,6 +85,7 @@ static inline void bch_writeback_add(struct cached_dev *dc) ...@@ -85,6 +85,7 @@ static inline void bch_writeback_add(struct cached_dev *dc)
void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int); void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
void bch_sectors_dirty_init(struct cached_dev *dc); void bch_sectors_dirty_init(struct cached_dev *dc);
int bch_cached_dev_writeback_init(struct cached_dev *); void bch_cached_dev_writeback_init(struct cached_dev *);
int bch_cached_dev_writeback_start(struct cached_dev *);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment