drbd: Consider the discard-my-data flag for all volumes [bugz 359]
authorPhilipp Reisner <philipp.reisner@linbit.com>
Mon, 5 Sep 2011 14:22:33 +0000 (16:22 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 8 Nov 2012 15:58:04 +0000 (16:58 +0100)
...not only for the first volume

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_receiver.c

index 9d0d6d0fb8207eb753f67ee007de82af65e5aefd..ccf28e986d4d095d6fea64ec295ad6601e321cc7 100644 (file)
@@ -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 */
index cd140bc0b56fd3d9bd0a3c5751c0f730c7629bf5..4004a682d0ec22cfcc599a6011e70a0caf9b1b8d 100644 (file)
@@ -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, ... */