diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2013-10-23 04:59:16 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-11-08 11:10:28 -0500 |
commit | b874d231e115af9b2c4a7ed1a4c5ae2db8a21aaf (patch) | |
tree | d1af0ee989ce07385e59a8f4c9848ec3505a8517 | |
parent | 69babf05cbe909a9a520b39772655f88b407f257 (diff) |
drbd: Fix an connection drop issue after enabling allow-two-primaries
Since drbd-8.4.0 it is possible to change the allow-two-primaries
network option while the connection is established.
The sequence code used to partially order packets from the
data socket with packets from the meta-data socket, still assued
that the allow-two-primaries option is constant while the
connection is established.
I.e.
On a node that has the RESOLVE_CONFLICTS bits set, after enabling
allow-two-primaries, when receiving the next data packet it timed out
while waiting for the necessary packets on the data socket to arrive
(wait_for_and_update_peer_seq() function).
Fixed that by always tracking the sequence number, but only waiting
for it if allow-two-primaries is set.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 39 |
1 files changed, 16 insertions, 23 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index cc29cd3bf78b..12c59eb3b127 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -1890,29 +1890,11 @@ static u32 seq_max(u32 a, u32 b) | |||
1890 | return seq_greater(a, b) ? a : b; | 1890 | return seq_greater(a, b) ? a : b; |
1891 | } | 1891 | } |
1892 | 1892 | ||
1893 | static bool need_peer_seq(struct drbd_conf *mdev) | ||
1894 | { | ||
1895 | struct drbd_tconn *tconn = mdev->tconn; | ||
1896 | int tp; | ||
1897 | |||
1898 | /* | ||
1899 | * We only need to keep track of the last packet_seq number of our peer | ||
1900 | * if we are in dual-primary mode and we have the resolve-conflicts flag set; see | ||
1901 | * handle_write_conflicts(). | ||
1902 | */ | ||
1903 | |||
1904 | rcu_read_lock(); | ||
1905 | tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries; | ||
1906 | rcu_read_unlock(); | ||
1907 | |||
1908 | return tp && test_bit(RESOLVE_CONFLICTS, &tconn->flags); | ||
1909 | } | ||
1910 | |||
1911 | static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq) | 1893 | static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq) |
1912 | { | 1894 | { |
1913 | unsigned int newest_peer_seq; | 1895 | unsigned int newest_peer_seq; |
1914 | 1896 | ||
1915 | if (need_peer_seq(mdev)) { | 1897 | if (test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)) { |
1916 | spin_lock(&mdev->peer_seq_lock); | 1898 | spin_lock(&mdev->peer_seq_lock); |
1917 | newest_peer_seq = seq_max(mdev->peer_seq, peer_seq); | 1899 | newest_peer_seq = seq_max(mdev->peer_seq, peer_seq); |
1918 | mdev->peer_seq = newest_peer_seq; | 1900 | mdev->peer_seq = newest_peer_seq; |
@@ -1972,22 +1954,31 @@ static int wait_for_and_update_peer_seq(struct drbd_conf *mdev, const u32 peer_s | |||
1972 | { | 1954 | { |
1973 | DEFINE_WAIT(wait); | 1955 | DEFINE_WAIT(wait); |
1974 | long timeout; | 1956 | long timeout; |
1975 | int ret; | 1957 | int ret = 0, tp; |
1976 | 1958 | ||
1977 | if (!need_peer_seq(mdev)) | 1959 | if (!test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)) |
1978 | return 0; | 1960 | return 0; |
1979 | 1961 | ||
1980 | spin_lock(&mdev->peer_seq_lock); | 1962 | spin_lock(&mdev->peer_seq_lock); |
1981 | for (;;) { | 1963 | for (;;) { |
1982 | if (!seq_greater(peer_seq - 1, mdev->peer_seq)) { | 1964 | if (!seq_greater(peer_seq - 1, mdev->peer_seq)) { |
1983 | mdev->peer_seq = seq_max(mdev->peer_seq, peer_seq); | 1965 | mdev->peer_seq = seq_max(mdev->peer_seq, peer_seq); |
1984 | ret = 0; | ||
1985 | break; | 1966 | break; |
1986 | } | 1967 | } |
1968 | |||
1987 | if (signal_pending(current)) { | 1969 | if (signal_pending(current)) { |
1988 | ret = -ERESTARTSYS; | 1970 | ret = -ERESTARTSYS; |
1989 | break; | 1971 | break; |
1990 | } | 1972 | } |
1973 | |||
1974 | rcu_read_lock(); | ||
1975 | tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries; | ||
1976 | rcu_read_unlock(); | ||
1977 | |||
1978 | if (!tp) | ||
1979 | break; | ||
1980 | |||
1981 | /* Only need to wait if two_primaries is enabled */ | ||
1991 | prepare_to_wait(&mdev->seq_wait, &wait, TASK_INTERRUPTIBLE); | 1982 | prepare_to_wait(&mdev->seq_wait, &wait, TASK_INTERRUPTIBLE); |
1992 | spin_unlock(&mdev->peer_seq_lock); | 1983 | spin_unlock(&mdev->peer_seq_lock); |
1993 | rcu_read_lock(); | 1984 | rcu_read_lock(); |
@@ -2228,8 +2219,10 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi) | |||
2228 | } | 2219 | } |
2229 | goto out_interrupted; | 2220 | goto out_interrupted; |
2230 | } | 2221 | } |
2231 | } else | 2222 | } else { |
2223 | update_peer_seq(mdev, peer_seq); | ||
2232 | spin_lock_irq(&mdev->tconn->req_lock); | 2224 | spin_lock_irq(&mdev->tconn->req_lock); |
2225 | } | ||
2233 | list_add(&peer_req->w.list, &mdev->active_ee); | 2226 | list_add(&peer_req->w.list, &mdev->active_ee); |
2234 | spin_unlock_irq(&mdev->tconn->req_lock); | 2227 | spin_unlock_irq(&mdev->tconn->req_lock); |
2235 | 2228 | ||