drbd: struct drbd_request: Introduce a new collision flag
authorAndreas Gruenbacher <agruen@linbit.com>
Thu, 27 Jan 2011 13:12:23 +0000 (14:12 +0100)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Wed, 28 Sep 2011 08:26:29 +0000 (10:26 +0200)
This flag is set when a processes puts itself to sleep to wait for a
conflicting request to complete.

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

index b4e1dab62dc161a114169cde9b989467d3e0cf67..d9f3f7fd9bb21436f78853f3fc0c70fe4395b863 100644 (file)
@@ -1815,6 +1815,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
                first = 1;
                for (;;) {
                        struct drbd_interval *i;
+                       struct drbd_request *req2;
                        int have_unacked = 0;
                        int have_conflict = 0;
                        prepare_to_wait(&mdev->misc_wait, &wait,
@@ -1822,8 +1823,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
 
                        i = drbd_find_overlap(&mdev->write_requests, sector, size);
                        if (i) {
-                               struct drbd_request *req2 =
-                                       container_of(i, struct drbd_request, i);
+                               req2 = container_of(i, struct drbd_request, i);
 
                                /* only ALERT on first iteration,
                                 * we may be woken up early... */
@@ -1869,6 +1869,9 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
                                goto out_interrupted;
                        }
 
+                       /* Indicate to wake up mdev->misc_wait upon completion.  */
+                       req2->rq_state |= RQ_COLLISION;
+
                        spin_unlock_irq(&mdev->tconn->req_lock);
                        if (first) {
                                first = 0;
index 25fa87c95a10ea8d99938b0493fa01c03efb22d3..8b4ba94538bdb026af8d8c84410ab7b6ea3f2f92 100644 (file)
@@ -176,45 +176,9 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev,
            req->epoch == mdev->tconn->newest_tle->br_number)
                queue_barrier(mdev);
 
-       /* we need to do the conflict detection stuff,
-        * if the epoch_entries tree is non-empty and
-        * this request has completed on the network */
-       if ((s & RQ_NET_DONE) && !RB_EMPTY_ROOT(&mdev->epoch_entries)) {
-               const sector_t sector = req->i.sector;
-               const int size = req->i.size;
-               struct drbd_interval *i;
-
-               /* ASSERT:
-                * there must be no conflicting requests, since
-                * they must have been failed on the spot */
-
-               i = drbd_find_overlap(&mdev->write_requests, sector, size);
-               if (i) {
-                       struct drbd_request *req2 =
-                               container_of(i, struct drbd_request, i);
-
-                       dev_alert(DEV, "LOGIC BUG: completed: %p %llus +%u; "
-                             "other: %p %llus +%u\n",
-                             req, (unsigned long long)sector, size,
-                             i, (unsigned long long)req2->i.sector, req2->i.size);
-               }
-
-               /* maybe "wake" those conflicting epoch entries
-                * that wait for this request to finish.
-                *
-                * currently, there can be only _one_ such ee
-                * (well, or some more, which would be pending
-                * P_DISCARD_ACK not yet sent by the asender...),
-                * since we block the receiver thread upon the
-                * first conflict detection, which will wait on
-                * misc_wait.  maybe we want to assert that?
-                *
-                * anyways, if we found one,
-                * we just have to do a wake_up.  */
-               i = drbd_find_overlap(&mdev->epoch_entries, sector, size);
-               if (i)
-                       wake_up(&mdev->misc_wait);
-       }
+       /* Wake up any processes waiting for this request to complete.  */
+       if ((s & RQ_NET_DONE) && (s & RQ_COLLISION))
+               wake_up(&mdev->misc_wait);
 }
 
 void complete_master_bio(struct drbd_conf *mdev,
index 431e3f962c3a88faccde36f0d0247fa3ce285218..7a7464a2b3a63d5b6e153db0d2f89f126fe76004 100644 (file)
@@ -194,6 +194,12 @@ enum drbd_req_state_bits {
 
        /* Should call drbd_al_complete_io() for this request... */
        __RQ_IN_ACT_LOG,
+
+       /*
+        * Set when a processes puts itself to sleep to wait for this request
+        * to complete.
+        */
+       __RQ_COLLISION,
 };
 
 #define RQ_LOCAL_PENDING   (1UL << __RQ_LOCAL_PENDING)
@@ -214,6 +220,7 @@ enum drbd_req_state_bits {
 
 #define RQ_WRITE           (1UL << __RQ_WRITE)
 #define RQ_IN_ACT_LOG      (1UL << __RQ_IN_ACT_LOG)
+#define RQ_COLLISION      (1UL << __RQ_COLLISION)
 
 /* For waking up the frozen transfer log mod_req() has to return if the request
    should be counted in the epoch object*/