aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-04-21 05:36:49 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 10:49:03 -0500
commit302bdeae49842cbd2faec8203f49b1c4ef20294d (patch)
treed72c6310b848494153e257a3797254a1ac8d2c24
parent91fd4dad64ce7ac48c4c30c7756c6d3c41e8ad0a (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.h4
-rw-r--r--drivers/block/drbd/drbd_receiver.c19
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 */
674enum { 678enum {
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)
1811static bool need_peer_seq(struct drbd_conf *mdev) 1811static 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
1824static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq) 1829static 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;