Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d407cfa authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge branch 'for-jens' of git://git.drbd.org/linux-drbd into for-linus

parents 98775171 0d5934e3
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -1475,9 +1475,16 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
		first_word = 0;
		spin_lock_irq(&b->bm_lock);
	}

	/* last page (respectively only page, for first page == last page) */
	last_word = MLPP(el >> LN2_BPL);

	/* consider bitmap->bm_bits = 32768, bitmap->bm_number_of_pages = 1. (or multiples).
	 * ==> e = 32767, el = 32768, last_page = 2,
	 * and now last_word = 0.
	 * We do not want to touch last_page in this case,
	 * as we did not allocate it, it is not present in bitmap->bm_pages.
	 */
	if (last_word)
		bm_set_full_words_within_one_page(mdev->bitmap, last_page, first_word, last_word);

	/* possibly trailing bits.
+42 −24
Original line number Diff line number Diff line
@@ -472,12 +472,17 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
		req->rq_state |= RQ_LOCAL_COMPLETED;
		req->rq_state &= ~RQ_LOCAL_PENDING;

		D_ASSERT(!(req->rq_state & RQ_NET_MASK));
		if (req->rq_state & RQ_LOCAL_ABORTED) {
			_req_may_be_done(req, m);
			break;
		}

		__drbd_chk_io_error(mdev, false);

	goto_queue_for_net_read:

		D_ASSERT(!(req->rq_state & RQ_NET_MASK));

		/* no point in retrying if there is no good remote data,
		 * or we have no connection. */
		if (mdev->state.pdsk != D_UP_TO_DATE) {
@@ -765,6 +770,40 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s
	return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr);
}

static void maybe_pull_ahead(struct drbd_conf *mdev)
{
	int congested = 0;

	/* If I don't even have good local storage, we can not reasonably try
	 * to pull ahead of the peer. We also need the local reference to make
	 * sure mdev->act_log is there.
	 * Note: caller has to make sure that net_conf is there.
	 */
	if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
		return;

	if (mdev->net_conf->cong_fill &&
	    atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) {
		dev_info(DEV, "Congestion-fill threshold reached\n");
		congested = 1;
	}

	if (mdev->act_log->used >= mdev->net_conf->cong_extents) {
		dev_info(DEV, "Congestion-extents threshold reached\n");
		congested = 1;
	}

	if (congested) {
		queue_barrier(mdev); /* last barrier, after mirrored writes */

		if (mdev->net_conf->on_congestion == OC_PULL_AHEAD)
			_drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL);
		else  /*mdev->net_conf->on_congestion == OC_DISCONNECT */
			_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
	}
	put_ldev(mdev);
}

static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
{
	const int rw = bio_rw(bio);
@@ -972,29 +1011,8 @@ allocate_barrier:
		_req_mod(req, queue_for_send_oos);

	if (remote &&
	    mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) {
		int congested = 0;

		if (mdev->net_conf->cong_fill &&
		    atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) {
			dev_info(DEV, "Congestion-fill threshold reached\n");
			congested = 1;
		}

		if (mdev->act_log->used >= mdev->net_conf->cong_extents) {
			dev_info(DEV, "Congestion-extents threshold reached\n");
			congested = 1;
		}

		if (congested) {
			queue_barrier(mdev); /* last barrier, after mirrored writes */

			if (mdev->net_conf->on_congestion == OC_PULL_AHEAD)
				_drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL);
			else  /*mdev->net_conf->on_congestion == OC_DISCONNECT */
				_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
		}
	}
	    mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96)
		maybe_pull_ahead(mdev);

	spin_unlock_irq(&mdev->req_lock);
	kfree(b); /* if someone else has beaten us to it... */