diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2014-02-11 09:30:49 +0100 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2014-07-10 18:34:55 +0200 |
commit | e334f55095b908f12c8bad991433f5d609e919d1 (patch) | |
tree | 00b88836a6eda4beeaea106f50fd423fc02d4043 /drivers/block/drbd/drbd_actlog.c | |
parent | ba3c6fb87d2df008eed8faaf01bb198e512fa72f (diff) | |
download | linux-e334f55095b908f12c8bad991433f5d609e919d1.tar.gz linux-e334f55095b908f12c8bad991433f5d609e919d1.tar.xz |
drbd: make sure disk cleanup happens in worker context
The recent fix to put_ldev() (correct ordering of access to local_cnt
and state.disk; memory barrier in __drbd_set_state) guarantees
that the cleanup happens exactly once.
However it does not yet guarantee that the cleanup happens from worker
context, the last put_ldev() may still happen from atomic context,
which must not happen: blkdev_put() may sleep.
Fix this by scheduling the cleanup to the worker instead,
using a couple more bits in device->flags and a new helper,
drbd_device_post_work().
Generalized the "resync progress" work to cover these new work bits.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_actlog.c')
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 9 |
1 files changed, 1 insertions, 8 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 14b2f27291aa..5add2016216c 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -797,20 +797,13 @@ static bool lazy_bitmap_update_due(struct drbd_device *device) static void maybe_schedule_on_disk_bitmap_update(struct drbd_device *device, bool rs_done) { - struct drbd_connection *connection; if (rs_done) set_bit(RS_DONE, &device->flags); /* and also set RS_PROGRESS below */ else if (!lazy_bitmap_update_due(device)) return; - /* compare with test_and_clear_bit() calls in and above - * try_update_all_on_disk_bitmaps() from the drbd_worker(). */ - if (test_and_set_bit(RS_PROGRESS, &device->flags)) - return; - connection = first_peer_device(device)->connection; - if (!test_and_set_bit(CONN_RS_PROGRESS, &connection->flags)) - wake_up(&connection->sender_work.q_wait); + drbd_device_post_work(device, RS_PROGRESS); } static int update_sync_bits(struct drbd_device *device, |