Commit a500c2ef authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Philipp Reisner
Browse files

drbd: struct drbd_request: Introduce a new collision flag



This flag is set when a processes puts itself to sleep to wait for a
conflicting request to complete.

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 9e204cdd
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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;
+3 −39
Original line number Diff line number Diff line
@@ -176,46 +176,10 @@ 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 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,
		struct bio_and_error *m)
+7 −0
Original line number Diff line number Diff line
@@ -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*/