diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-11-10 18:45:36 +0100 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 16:58:06 +0100 |
commit | 6936fcb49ab369ad13267e292ec0e3490db91c4a (patch) | |
tree | f0748cdbf5cdb4e8cede5dc78315cca042b1fb08 /drivers/block/drbd/drbd_main.c | |
parent | 36baf6117b1deee37b9467224a0a14f1bb0863e2 (diff) |
drbd: Move the CREATE_BARRIER flag from connection to device
That is necessary since the whole transfer log is per connection(tconn)
and not per device(mdev).
This bug caused list corruption on the worker list. When a barrier is queued
for sending in the context of one device, another device did not see the
CREATE_BARRIER bit, and queued the same object again -> list corruption.
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_main.c')
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 11 |
1 files changed, 3 insertions, 8 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index e3186f2dad0..e1234065954 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -320,7 +320,7 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr, mdev = b->w.mdev; nob = b->next; - if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { + if (test_and_clear_bit(CREATE_BARRIER, &tconn->flags)) { _tl_add_barrier(tconn, b); if (nob) tconn->oldest_tle = nob; @@ -381,7 +381,7 @@ void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what) if (b->w.cb == NULL) { b->w.cb = w_send_barrier; inc_ap_pending(b->w.mdev); - set_bit(CREATE_BARRIER, &b->w.mdev->flags); + set_bit(CREATE_BARRIER, &tconn->flags); } drbd_queue_work(&tconn->data.work, &b->w); @@ -448,10 +448,8 @@ void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what) */ void tl_clear(struct drbd_tconn *tconn) { - struct drbd_conf *mdev; struct list_head *le, *tle; struct drbd_request *r; - int vnr; spin_lock_irq(&tconn->req_lock); @@ -470,10 +468,7 @@ void tl_clear(struct drbd_tconn *tconn) } /* ensure bit indicating barrier is required is clear */ - rcu_read_lock(); - idr_for_each_entry(&tconn->volumes, mdev, vnr) - clear_bit(CREATE_BARRIER, &mdev->flags); - rcu_read_unlock(); + clear_bit(CREATE_BARRIER, &tconn->flags); spin_unlock_irq(&tconn->req_lock); } |