From 08b165ba11ebdb6b037a6071ae599f1d8c93807e Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 5 Sep 2011 16:22:33 +0200 Subject: [PATCH] drbd: Consider the discard-my-data flag for all volumes [bugz 359] ...not only for the first volume Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_receiver.c | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 9d0d6d0..ccf28e9 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -697,6 +697,7 @@ enum { AL_SUSPENDED, /* Activity logging is currently suspended. */ AHEAD_TO_SYNC_SOURCE, /* Ahead -> SyncSource queued */ B_RS_H_DONE, /* Before resync handler done (already executed) */ + DISCARD_MY_DATA, /* discard_my_data flag per volume */ }; struct drbd_bitmap; /* opaque for drbd_conf */ diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index cd140bc..4004a68 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -846,6 +846,7 @@ static int conn_connect(struct drbd_tconn *tconn) struct drbd_conf *mdev; struct net_conf *nc; int vnr, timeout, try, h, ok; + bool discard_my_data; if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS) return -2; @@ -960,6 +961,7 @@ retry: msock->sk->sk_rcvtimeo = nc->ping_int*HZ; timeout = nc->timeout * HZ / 10; + discard_my_data = nc->discard_my_data; rcu_read_unlock(); msock->sk->sk_sndtimeo = timeout; @@ -997,6 +999,12 @@ retry: idr_for_each_entry(&tconn->volumes, mdev, vnr) { kref_get(&mdev->kref); rcu_read_unlock(); + + if (discard_my_data) + set_bit(DISCARD_MY_DATA, &mdev->flags); + else + clear_bit(DISCARD_MY_DATA, &mdev->flags); + drbd_connected(mdev); kref_put(&mdev->kref, &drbd_minor_destroy); rcu_read_lock(); @@ -1008,6 +1016,14 @@ retry: drbd_thread_start(&tconn->asender); + mutex_lock(&tconn->conf_update); + /* The discard_my_data flag is a single-shot modifier to the next + * connection attempt, the handshake of which is now well underway. + * No need for rcu style copying of the whole struct + * just to clear a single value. */ + tconn->net_conf->discard_my_data = 0; + mutex_unlock(&tconn->conf_update); + return h; out_release_sockets: @@ -2906,9 +2922,9 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol } if (hg == -100) { - if (nc->discard_my_data && !(mdev->p_uuid[UI_FLAGS]&1)) + if (test_bit(DISCARD_MY_DATA, &mdev->flags) && !(mdev->p_uuid[UI_FLAGS]&1)) hg = -1; - if (!nc->discard_my_data && (mdev->p_uuid[UI_FLAGS]&1)) + if (!test_bit(DISCARD_MY_DATA, &mdev->flags) && (mdev->p_uuid[UI_FLAGS]&1)) hg = 1; if (abs(hg) < 100) @@ -3856,9 +3872,7 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi) } } - mutex_lock(&mdev->tconn->conf_update); - mdev->tconn->net_conf->discard_my_data = 0; /* without copy; single bit op is atomic */ - mutex_unlock(&mdev->tconn->conf_update); + clear_bit(DISCARD_MY_DATA, &mdev->flags); drbd_md_sync(mdev); /* update connected indicator, la_size, ... */ -- 2.7.4