diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2012-02-18 19:27:53 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-05-09 09:16:38 -0400 |
commit | b6a370ba0786b5eb09c479bffeffe7baba484ab0 (patch) | |
tree | f9c77b675c02ade44902532d9f62ea4e484de5cb /drivers/block | |
parent | fc28845bc005995b41ae8c83c7922d088f0ad228 (diff) |
drbd: Fix a potential write ordering issue on SyncTarget nodes
If a SyncTarget node gets a P_RS_DATA_REPLY before a P_DATA packet
for the same sector, it simply submits these two IO requests.
This is be possible because on the SyncSource node, the data of the
P_RS_DATA_REPLY packet was read from disk. Immediately after that a
write request from upper layers came in.
The disk scheduler or even the "hardware" queues on the disk drive might
reorder these writes.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 6b0505a3c4fc..d601501c336a 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -1585,6 +1585,24 @@ static int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int u | |||
1585 | return ok; | 1585 | return ok; |
1586 | } | 1586 | } |
1587 | 1587 | ||
1588 | static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_epoch_entry *data_e) | ||
1589 | { | ||
1590 | |||
1591 | struct drbd_epoch_entry *rs_e; | ||
1592 | bool rv = 0; | ||
1593 | |||
1594 | spin_lock_irq(&mdev->req_lock); | ||
1595 | list_for_each_entry(rs_e, &mdev->sync_ee, w.list) { | ||
1596 | if (overlaps(data_e->sector, data_e->size, rs_e->sector, rs_e->size)) { | ||
1597 | rv = 1; | ||
1598 | break; | ||
1599 | } | ||
1600 | } | ||
1601 | spin_unlock_irq(&mdev->req_lock); | ||
1602 | |||
1603 | return rv; | ||
1604 | } | ||
1605 | |||
1588 | /* Called from receive_Data. | 1606 | /* Called from receive_Data. |
1589 | * Synchronize packets on sock with packets on msock. | 1607 | * Synchronize packets on sock with packets on msock. |
1590 | * | 1608 | * |
@@ -1828,6 +1846,9 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned | |||
1828 | list_add(&e->w.list, &mdev->active_ee); | 1846 | list_add(&e->w.list, &mdev->active_ee); |
1829 | spin_unlock_irq(&mdev->req_lock); | 1847 | spin_unlock_irq(&mdev->req_lock); |
1830 | 1848 | ||
1849 | if (mdev->state.conn == C_SYNC_TARGET) | ||
1850 | wait_event(mdev->ee_wait, !overlapping_resync_write(mdev, e)); | ||
1851 | |||
1831 | switch (mdev->net_conf->wire_protocol) { | 1852 | switch (mdev->net_conf->wire_protocol) { |
1832 | case DRBD_PROT_C: | 1853 | case DRBD_PROT_C: |
1833 | inc_unacked(mdev); | 1854 | inc_unacked(mdev); |