summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-09-05 18:22:33 +0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 19:58:04 +0400
commit08b165ba11ebdb6b037a6071ae599f1d8c93807e (patch)
tree2c780dfb14e1324340fb1f771b414ab7f6cbe657 /drivers
parent935be260c1e92a1d9c251973d866b68bf2c20f12 (diff)
downloadlinux-08b165ba11ebdb6b037a6071ae599f1d8c93807e.tar.xz
drbd: Consider the discard-my-data flag for all volumes [bugz 359]
...not only for the first volume Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/drbd/drbd_int.h1
-rw-r--r--drivers/block/drbd/drbd_receiver.c24
2 files changed, 20 insertions, 5 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 9d0d6d0fb820..ccf28e986d4d 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 cd140bc0b56f..4004a682d0ec 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, ... */