diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-04-21 05:36:49 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:49:03 -0500 |
commit | 302bdeae49842cbd2faec8203f49b1c4ef20294d (patch) | |
tree | d72c6310b848494153e257a3797254a1ac8d2c24 | |
parent | 91fd4dad64ce7ac48c4c30c7756c6d3c41e8ad0a (diff) |
drbd: Considering that the two_primaries config flag can change
Now since it is possible to change the two_primaries config
flag while the connection is up, make sure we treat a peer_req
in a consistent way if the config flag changes while the peer_req
is under IO.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 19 |
2 files changed, 18 insertions, 5 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 83e6cadbe7aa..3833d56b8de8 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -661,6 +661,9 @@ enum { | |||
661 | 661 | ||
662 | /* The peer wants a write ACK for this (wire proto C) */ | 662 | /* The peer wants a write ACK for this (wire proto C) */ |
663 | __EE_SEND_WRITE_ACK, | 663 | __EE_SEND_WRITE_ACK, |
664 | |||
665 | /* Is set when net_conf had two_primaries set while creating this peer_req */ | ||
666 | __EE_IN_INTERVAL_TREE, | ||
664 | }; | 667 | }; |
665 | #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO) | 668 | #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO) |
666 | #define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC) | 669 | #define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC) |
@@ -669,6 +672,7 @@ enum { | |||
669 | #define EE_HAS_DIGEST (1<<__EE_HAS_DIGEST) | 672 | #define EE_HAS_DIGEST (1<<__EE_HAS_DIGEST) |
670 | #define EE_RESTART_REQUESTS (1<<__EE_RESTART_REQUESTS) | 673 | #define EE_RESTART_REQUESTS (1<<__EE_RESTART_REQUESTS) |
671 | #define EE_SEND_WRITE_ACK (1<<__EE_SEND_WRITE_ACK) | 674 | #define EE_SEND_WRITE_ACK (1<<__EE_SEND_WRITE_ACK) |
675 | #define EE_IN_INTERVAL_TREE (1<<__EE_IN_INTERVAL_TREE) | ||
672 | 676 | ||
673 | /* flag bits per mdev */ | 677 | /* flag bits per mdev */ |
674 | enum { | 678 | enum { |
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 397f97701988..4665ad79b4ae 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -1752,7 +1752,7 @@ static int e_end_block(struct drbd_work *w, int cancel) | |||
1752 | } | 1752 | } |
1753 | /* we delete from the conflict detection hash _after_ we sent out the | 1753 | /* we delete from the conflict detection hash _after_ we sent out the |
1754 | * P_WRITE_ACK / P_NEG_ACK, to get the sequence number right. */ | 1754 | * P_WRITE_ACK / P_NEG_ACK, to get the sequence number right. */ |
1755 | if (mdev->tconn->net_conf->two_primaries) { | 1755 | if (peer_req->flags & EE_IN_INTERVAL_TREE) { |
1756 | spin_lock_irq(&mdev->tconn->req_lock); | 1756 | spin_lock_irq(&mdev->tconn->req_lock); |
1757 | D_ASSERT(!drbd_interval_empty(&peer_req->i)); | 1757 | D_ASSERT(!drbd_interval_empty(&peer_req->i)); |
1758 | drbd_remove_epoch_entry_interval(mdev, peer_req); | 1758 | drbd_remove_epoch_entry_interval(mdev, peer_req); |
@@ -1811,14 +1811,19 @@ static u32 seq_max(u32 a, u32 b) | |||
1811 | static bool need_peer_seq(struct drbd_conf *mdev) | 1811 | static bool need_peer_seq(struct drbd_conf *mdev) |
1812 | { | 1812 | { |
1813 | struct drbd_tconn *tconn = mdev->tconn; | 1813 | struct drbd_tconn *tconn = mdev->tconn; |
1814 | int tp; | ||
1814 | 1815 | ||
1815 | /* | 1816 | /* |
1816 | * We only need to keep track of the last packet_seq number of our peer | 1817 | * We only need to keep track of the last packet_seq number of our peer |
1817 | * if we are in dual-primary mode and we have the discard flag set; see | 1818 | * if we are in dual-primary mode and we have the discard flag set; see |
1818 | * handle_write_conflicts(). | 1819 | * handle_write_conflicts(). |
1819 | */ | 1820 | */ |
1820 | return tconn->net_conf->two_primaries && | 1821 | |
1821 | test_bit(DISCARD_CONCURRENT, &tconn->flags); | 1822 | rcu_read_lock(); |
1823 | tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries; | ||
1824 | rcu_read_unlock(); | ||
1825 | |||
1826 | return tp && test_bit(DISCARD_CONCURRENT, &tconn->flags); | ||
1822 | } | 1827 | } |
1823 | 1828 | ||
1824 | static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq) | 1829 | static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq) |
@@ -2049,7 +2054,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi) | |||
2049 | u32 peer_seq = be32_to_cpu(p->seq_num); | 2054 | u32 peer_seq = be32_to_cpu(p->seq_num); |
2050 | int rw = WRITE; | 2055 | int rw = WRITE; |
2051 | u32 dp_flags; | 2056 | u32 dp_flags; |
2052 | int err; | 2057 | int err, tp; |
2053 | 2058 | ||
2054 | mdev = vnr_to_mdev(tconn, pi->vnr); | 2059 | mdev = vnr_to_mdev(tconn, pi->vnr); |
2055 | if (!mdev) | 2060 | if (!mdev) |
@@ -2094,7 +2099,11 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi) | |||
2094 | atomic_inc(&peer_req->epoch->active); | 2099 | atomic_inc(&peer_req->epoch->active); |
2095 | spin_unlock(&mdev->epoch_lock); | 2100 | spin_unlock(&mdev->epoch_lock); |
2096 | 2101 | ||
2097 | if (mdev->tconn->net_conf->two_primaries) { | 2102 | rcu_read_lock(); |
2103 | tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries; | ||
2104 | rcu_read_unlock(); | ||
2105 | if (tp) { | ||
2106 | peer_req->flags |= EE_IN_INTERVAL_TREE; | ||
2098 | err = wait_for_and_update_peer_seq(mdev, peer_seq); | 2107 | err = wait_for_and_update_peer_seq(mdev, peer_seq); |
2099 | if (err) | 2108 | if (err) |
2100 | goto out_interrupted; | 2109 | goto out_interrupted; |