162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci   drbd_worker.c
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci   This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci   Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
862306a36Sopenharmony_ci   Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
962306a36Sopenharmony_ci   Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci*/
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/drbd.h>
1662306a36Sopenharmony_ci#include <linux/sched/signal.h>
1762306a36Sopenharmony_ci#include <linux/wait.h>
1862306a36Sopenharmony_ci#include <linux/mm.h>
1962306a36Sopenharmony_ci#include <linux/memcontrol.h>
2062306a36Sopenharmony_ci#include <linux/mm_inline.h>
2162306a36Sopenharmony_ci#include <linux/slab.h>
2262306a36Sopenharmony_ci#include <linux/random.h>
2362306a36Sopenharmony_ci#include <linux/string.h>
2462306a36Sopenharmony_ci#include <linux/scatterlist.h>
2562306a36Sopenharmony_ci#include <linux/part_stat.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "drbd_int.h"
2862306a36Sopenharmony_ci#include "drbd_protocol.h"
2962306a36Sopenharmony_ci#include "drbd_req.h"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic int make_ov_request(struct drbd_peer_device *, int);
3262306a36Sopenharmony_cistatic int make_resync_request(struct drbd_peer_device *, int);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* endio handlers:
3562306a36Sopenharmony_ci *   drbd_md_endio (defined here)
3662306a36Sopenharmony_ci *   drbd_request_endio (defined here)
3762306a36Sopenharmony_ci *   drbd_peer_request_endio (defined here)
3862306a36Sopenharmony_ci *   drbd_bm_endio (defined in drbd_bitmap.c)
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci * For all these callbacks, note the following:
4162306a36Sopenharmony_ci * The callbacks will be called in irq context by the IDE drivers,
4262306a36Sopenharmony_ci * and in Softirqs/Tasklets/BH context by the SCSI drivers.
4362306a36Sopenharmony_ci * Try to get the locking right :)
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* used for synchronous meta data and bitmap IO
4862306a36Sopenharmony_ci * submitted by drbd_md_sync_page_io()
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_civoid drbd_md_endio(struct bio *bio)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	struct drbd_device *device;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	device = bio->bi_private;
5562306a36Sopenharmony_ci	device->md_io.error = blk_status_to_errno(bio->bi_status);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* special case: drbd_md_read() during drbd_adm_attach() */
5862306a36Sopenharmony_ci	if (device->ldev)
5962306a36Sopenharmony_ci		put_ldev(device);
6062306a36Sopenharmony_ci	bio_put(bio);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	/* We grabbed an extra reference in _drbd_md_sync_page_io() to be able
6362306a36Sopenharmony_ci	 * to timeout on the lower level device, and eventually detach from it.
6462306a36Sopenharmony_ci	 * If this io completion runs after that timeout expired, this
6562306a36Sopenharmony_ci	 * drbd_md_put_buffer() may allow us to finally try and re-attach.
6662306a36Sopenharmony_ci	 * During normal operation, this only puts that extra reference
6762306a36Sopenharmony_ci	 * down to 1 again.
6862306a36Sopenharmony_ci	 * Make sure we first drop the reference, and only then signal
6962306a36Sopenharmony_ci	 * completion, or we may (in drbd_al_read_log()) cycle so fast into the
7062306a36Sopenharmony_ci	 * next drbd_md_sync_page_io(), that we trigger the
7162306a36Sopenharmony_ci	 * ASSERT(atomic_read(&device->md_io_in_use) == 1) there.
7262306a36Sopenharmony_ci	 */
7362306a36Sopenharmony_ci	drbd_md_put_buffer(device);
7462306a36Sopenharmony_ci	device->md_io.done = 1;
7562306a36Sopenharmony_ci	wake_up(&device->misc_wait);
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/* reads on behalf of the partner,
7962306a36Sopenharmony_ci * "submitted" by the receiver
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_cistatic void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(local)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	unsigned long flags = 0;
8462306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
8562306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	spin_lock_irqsave(&device->resource->req_lock, flags);
8862306a36Sopenharmony_ci	device->read_cnt += peer_req->i.size >> 9;
8962306a36Sopenharmony_ci	list_del(&peer_req->w.list);
9062306a36Sopenharmony_ci	if (list_empty(&device->read_ee))
9162306a36Sopenharmony_ci		wake_up(&device->ee_wait);
9262306a36Sopenharmony_ci	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
9362306a36Sopenharmony_ci		__drbd_chk_io_error(device, DRBD_READ_ERROR);
9462306a36Sopenharmony_ci	spin_unlock_irqrestore(&device->resource->req_lock, flags);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	drbd_queue_work(&peer_device->connection->sender_work, &peer_req->w);
9762306a36Sopenharmony_ci	put_ldev(device);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/* writes on behalf of the partner, or resync writes,
10162306a36Sopenharmony_ci * "submitted" by the receiver, final stage.  */
10262306a36Sopenharmony_civoid drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(local)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	unsigned long flags = 0;
10562306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
10662306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
10762306a36Sopenharmony_ci	struct drbd_connection *connection = peer_device->connection;
10862306a36Sopenharmony_ci	struct drbd_interval i;
10962306a36Sopenharmony_ci	int do_wake;
11062306a36Sopenharmony_ci	u64 block_id;
11162306a36Sopenharmony_ci	int do_al_complete_io;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* after we moved peer_req to done_ee,
11462306a36Sopenharmony_ci	 * we may no longer access it,
11562306a36Sopenharmony_ci	 * it may be freed/reused already!
11662306a36Sopenharmony_ci	 * (as soon as we release the req_lock) */
11762306a36Sopenharmony_ci	i = peer_req->i;
11862306a36Sopenharmony_ci	do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
11962306a36Sopenharmony_ci	block_id = peer_req->block_id;
12062306a36Sopenharmony_ci	peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (peer_req->flags & EE_WAS_ERROR) {
12362306a36Sopenharmony_ci		/* In protocol != C, we usually do not send write acks.
12462306a36Sopenharmony_ci		 * In case of a write error, send the neg ack anyways. */
12562306a36Sopenharmony_ci		if (!__test_and_set_bit(__EE_SEND_WRITE_ACK, &peer_req->flags))
12662306a36Sopenharmony_ci			inc_unacked(device);
12762306a36Sopenharmony_ci		drbd_set_out_of_sync(peer_device, peer_req->i.sector, peer_req->i.size);
12862306a36Sopenharmony_ci	}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	spin_lock_irqsave(&device->resource->req_lock, flags);
13162306a36Sopenharmony_ci	device->writ_cnt += peer_req->i.size >> 9;
13262306a36Sopenharmony_ci	list_move_tail(&peer_req->w.list, &device->done_ee);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/*
13562306a36Sopenharmony_ci	 * Do not remove from the write_requests tree here: we did not send the
13662306a36Sopenharmony_ci	 * Ack yet and did not wake possibly waiting conflicting requests.
13762306a36Sopenharmony_ci	 * Removed from the tree from "drbd_process_done_ee" within the
13862306a36Sopenharmony_ci	 * appropriate dw.cb (e_end_block/e_end_resync_block) or from
13962306a36Sopenharmony_ci	 * _drbd_clear_done_ee.
14062306a36Sopenharmony_ci	 */
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	do_wake = list_empty(block_id == ID_SYNCER ? &device->sync_ee : &device->active_ee);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* FIXME do we want to detach for failed REQ_OP_DISCARD?
14562306a36Sopenharmony_ci	 * ((peer_req->flags & (EE_WAS_ERROR|EE_TRIM)) == EE_WAS_ERROR) */
14662306a36Sopenharmony_ci	if (peer_req->flags & EE_WAS_ERROR)
14762306a36Sopenharmony_ci		__drbd_chk_io_error(device, DRBD_WRITE_ERROR);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (connection->cstate >= C_WF_REPORT_PARAMS) {
15062306a36Sopenharmony_ci		kref_get(&device->kref); /* put is in drbd_send_acks_wf() */
15162306a36Sopenharmony_ci		if (!queue_work(connection->ack_sender, &peer_device->send_acks_work))
15262306a36Sopenharmony_ci			kref_put(&device->kref, drbd_destroy_device);
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci	spin_unlock_irqrestore(&device->resource->req_lock, flags);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	if (block_id == ID_SYNCER)
15762306a36Sopenharmony_ci		drbd_rs_complete_io(device, i.sector);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (do_wake)
16062306a36Sopenharmony_ci		wake_up(&device->ee_wait);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (do_al_complete_io)
16362306a36Sopenharmony_ci		drbd_al_complete_io(device, &i);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	put_ldev(device);
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/* writes on behalf of the partner, or resync writes,
16962306a36Sopenharmony_ci * "submitted" by the receiver.
17062306a36Sopenharmony_ci */
17162306a36Sopenharmony_civoid drbd_peer_request_endio(struct bio *bio)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = bio->bi_private;
17462306a36Sopenharmony_ci	struct drbd_device *device = peer_req->peer_device->device;
17562306a36Sopenharmony_ci	bool is_write = bio_data_dir(bio) == WRITE;
17662306a36Sopenharmony_ci	bool is_discard = bio_op(bio) == REQ_OP_WRITE_ZEROES ||
17762306a36Sopenharmony_ci			  bio_op(bio) == REQ_OP_DISCARD;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	if (bio->bi_status && drbd_ratelimit())
18062306a36Sopenharmony_ci		drbd_warn(device, "%s: error=%d s=%llus\n",
18162306a36Sopenharmony_ci				is_write ? (is_discard ? "discard" : "write")
18262306a36Sopenharmony_ci					: "read", bio->bi_status,
18362306a36Sopenharmony_ci				(unsigned long long)peer_req->i.sector);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if (bio->bi_status)
18662306a36Sopenharmony_ci		set_bit(__EE_WAS_ERROR, &peer_req->flags);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	bio_put(bio); /* no need for the bio anymore */
18962306a36Sopenharmony_ci	if (atomic_dec_and_test(&peer_req->pending_bios)) {
19062306a36Sopenharmony_ci		if (is_write)
19162306a36Sopenharmony_ci			drbd_endio_write_sec_final(peer_req);
19262306a36Sopenharmony_ci		else
19362306a36Sopenharmony_ci			drbd_endio_read_sec_final(peer_req);
19462306a36Sopenharmony_ci	}
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic void
19862306a36Sopenharmony_cidrbd_panic_after_delayed_completion_of_aborted_request(struct drbd_device *device)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	panic("drbd%u %s/%u potential random memory corruption caused by delayed completion of aborted local request\n",
20162306a36Sopenharmony_ci		device->minor, device->resource->name, device->vnr);
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/* read, readA or write requests on R_PRIMARY coming from drbd_make_request
20562306a36Sopenharmony_ci */
20662306a36Sopenharmony_civoid drbd_request_endio(struct bio *bio)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	unsigned long flags;
20962306a36Sopenharmony_ci	struct drbd_request *req = bio->bi_private;
21062306a36Sopenharmony_ci	struct drbd_device *device = req->device;
21162306a36Sopenharmony_ci	struct bio_and_error m;
21262306a36Sopenharmony_ci	enum drbd_req_event what;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	/* If this request was aborted locally before,
21562306a36Sopenharmony_ci	 * but now was completed "successfully",
21662306a36Sopenharmony_ci	 * chances are that this caused arbitrary data corruption.
21762306a36Sopenharmony_ci	 *
21862306a36Sopenharmony_ci	 * "aborting" requests, or force-detaching the disk, is intended for
21962306a36Sopenharmony_ci	 * completely blocked/hung local backing devices which do no longer
22062306a36Sopenharmony_ci	 * complete requests at all, not even do error completions.  In this
22162306a36Sopenharmony_ci	 * situation, usually a hard-reset and failover is the only way out.
22262306a36Sopenharmony_ci	 *
22362306a36Sopenharmony_ci	 * By "aborting", basically faking a local error-completion,
22462306a36Sopenharmony_ci	 * we allow for a more graceful swichover by cleanly migrating services.
22562306a36Sopenharmony_ci	 * Still the affected node has to be rebooted "soon".
22662306a36Sopenharmony_ci	 *
22762306a36Sopenharmony_ci	 * By completing these requests, we allow the upper layers to re-use
22862306a36Sopenharmony_ci	 * the associated data pages.
22962306a36Sopenharmony_ci	 *
23062306a36Sopenharmony_ci	 * If later the local backing device "recovers", and now DMAs some data
23162306a36Sopenharmony_ci	 * from disk into the original request pages, in the best case it will
23262306a36Sopenharmony_ci	 * just put random data into unused pages; but typically it will corrupt
23362306a36Sopenharmony_ci	 * meanwhile completely unrelated data, causing all sorts of damage.
23462306a36Sopenharmony_ci	 *
23562306a36Sopenharmony_ci	 * Which means delayed successful completion,
23662306a36Sopenharmony_ci	 * especially for READ requests,
23762306a36Sopenharmony_ci	 * is a reason to panic().
23862306a36Sopenharmony_ci	 *
23962306a36Sopenharmony_ci	 * We assume that a delayed *error* completion is OK,
24062306a36Sopenharmony_ci	 * though we still will complain noisily about it.
24162306a36Sopenharmony_ci	 */
24262306a36Sopenharmony_ci	if (unlikely(req->rq_state & RQ_LOCAL_ABORTED)) {
24362306a36Sopenharmony_ci		if (drbd_ratelimit())
24462306a36Sopenharmony_ci			drbd_emerg(device, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		if (!bio->bi_status)
24762306a36Sopenharmony_ci			drbd_panic_after_delayed_completion_of_aborted_request(device);
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* to avoid recursion in __req_mod */
25162306a36Sopenharmony_ci	if (unlikely(bio->bi_status)) {
25262306a36Sopenharmony_ci		switch (bio_op(bio)) {
25362306a36Sopenharmony_ci		case REQ_OP_WRITE_ZEROES:
25462306a36Sopenharmony_ci		case REQ_OP_DISCARD:
25562306a36Sopenharmony_ci			if (bio->bi_status == BLK_STS_NOTSUPP)
25662306a36Sopenharmony_ci				what = DISCARD_COMPLETED_NOTSUPP;
25762306a36Sopenharmony_ci			else
25862306a36Sopenharmony_ci				what = DISCARD_COMPLETED_WITH_ERROR;
25962306a36Sopenharmony_ci			break;
26062306a36Sopenharmony_ci		case REQ_OP_READ:
26162306a36Sopenharmony_ci			if (bio->bi_opf & REQ_RAHEAD)
26262306a36Sopenharmony_ci				what = READ_AHEAD_COMPLETED_WITH_ERROR;
26362306a36Sopenharmony_ci			else
26462306a36Sopenharmony_ci				what = READ_COMPLETED_WITH_ERROR;
26562306a36Sopenharmony_ci			break;
26662306a36Sopenharmony_ci		default:
26762306a36Sopenharmony_ci			what = WRITE_COMPLETED_WITH_ERROR;
26862306a36Sopenharmony_ci			break;
26962306a36Sopenharmony_ci		}
27062306a36Sopenharmony_ci	} else {
27162306a36Sopenharmony_ci		what = COMPLETED_OK;
27262306a36Sopenharmony_ci	}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	req->private_bio = ERR_PTR(blk_status_to_errno(bio->bi_status));
27562306a36Sopenharmony_ci	bio_put(bio);
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	/* not req_mod(), we need irqsave here! */
27862306a36Sopenharmony_ci	spin_lock_irqsave(&device->resource->req_lock, flags);
27962306a36Sopenharmony_ci	__req_mod(req, what, NULL, &m);
28062306a36Sopenharmony_ci	spin_unlock_irqrestore(&device->resource->req_lock, flags);
28162306a36Sopenharmony_ci	put_ldev(device);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (m.bio)
28462306a36Sopenharmony_ci		complete_master_bio(device, &m);
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_civoid drbd_csum_ee(struct crypto_shash *tfm, struct drbd_peer_request *peer_req, void *digest)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	SHASH_DESC_ON_STACK(desc, tfm);
29062306a36Sopenharmony_ci	struct page *page = peer_req->pages;
29162306a36Sopenharmony_ci	struct page *tmp;
29262306a36Sopenharmony_ci	unsigned len;
29362306a36Sopenharmony_ci	void *src;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	desc->tfm = tfm;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	crypto_shash_init(desc);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	src = kmap_atomic(page);
30062306a36Sopenharmony_ci	while ((tmp = page_chain_next(page))) {
30162306a36Sopenharmony_ci		/* all but the last page will be fully used */
30262306a36Sopenharmony_ci		crypto_shash_update(desc, src, PAGE_SIZE);
30362306a36Sopenharmony_ci		kunmap_atomic(src);
30462306a36Sopenharmony_ci		page = tmp;
30562306a36Sopenharmony_ci		src = kmap_atomic(page);
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci	/* and now the last, possibly only partially used page */
30862306a36Sopenharmony_ci	len = peer_req->i.size & (PAGE_SIZE - 1);
30962306a36Sopenharmony_ci	crypto_shash_update(desc, src, len ?: PAGE_SIZE);
31062306a36Sopenharmony_ci	kunmap_atomic(src);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	crypto_shash_final(desc, digest);
31362306a36Sopenharmony_ci	shash_desc_zero(desc);
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_civoid drbd_csum_bio(struct crypto_shash *tfm, struct bio *bio, void *digest)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	SHASH_DESC_ON_STACK(desc, tfm);
31962306a36Sopenharmony_ci	struct bio_vec bvec;
32062306a36Sopenharmony_ci	struct bvec_iter iter;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	desc->tfm = tfm;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	crypto_shash_init(desc);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	bio_for_each_segment(bvec, bio, iter) {
32762306a36Sopenharmony_ci		u8 *src;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci		src = bvec_kmap_local(&bvec);
33062306a36Sopenharmony_ci		crypto_shash_update(desc, src, bvec.bv_len);
33162306a36Sopenharmony_ci		kunmap_local(src);
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci	crypto_shash_final(desc, digest);
33462306a36Sopenharmony_ci	shash_desc_zero(desc);
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci/* MAYBE merge common code with w_e_end_ov_req */
33862306a36Sopenharmony_cistatic int w_e_send_csum(struct drbd_work *w, int cancel)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
34162306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
34262306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
34362306a36Sopenharmony_ci	int digest_size;
34462306a36Sopenharmony_ci	void *digest;
34562306a36Sopenharmony_ci	int err = 0;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	if (unlikely(cancel))
34862306a36Sopenharmony_ci		goto out;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	if (unlikely((peer_req->flags & EE_WAS_ERROR) != 0))
35162306a36Sopenharmony_ci		goto out;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	digest_size = crypto_shash_digestsize(peer_device->connection->csums_tfm);
35462306a36Sopenharmony_ci	digest = kmalloc(digest_size, GFP_NOIO);
35562306a36Sopenharmony_ci	if (digest) {
35662306a36Sopenharmony_ci		sector_t sector = peer_req->i.sector;
35762306a36Sopenharmony_ci		unsigned int size = peer_req->i.size;
35862306a36Sopenharmony_ci		drbd_csum_ee(peer_device->connection->csums_tfm, peer_req, digest);
35962306a36Sopenharmony_ci		/* Free peer_req and pages before send.
36062306a36Sopenharmony_ci		 * In case we block on congestion, we could otherwise run into
36162306a36Sopenharmony_ci		 * some distributed deadlock, if the other side blocks on
36262306a36Sopenharmony_ci		 * congestion as well, because our receiver blocks in
36362306a36Sopenharmony_ci		 * drbd_alloc_pages due to pp_in_use > max_buffers. */
36462306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
36562306a36Sopenharmony_ci		peer_req = NULL;
36662306a36Sopenharmony_ci		inc_rs_pending(peer_device);
36762306a36Sopenharmony_ci		err = drbd_send_drequest_csum(peer_device, sector, size,
36862306a36Sopenharmony_ci					      digest, digest_size,
36962306a36Sopenharmony_ci					      P_CSUM_RS_REQUEST);
37062306a36Sopenharmony_ci		kfree(digest);
37162306a36Sopenharmony_ci	} else {
37262306a36Sopenharmony_ci		drbd_err(device, "kmalloc() of digest failed.\n");
37362306a36Sopenharmony_ci		err = -ENOMEM;
37462306a36Sopenharmony_ci	}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ciout:
37762306a36Sopenharmony_ci	if (peer_req)
37862306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	if (unlikely(err))
38162306a36Sopenharmony_ci		drbd_err(device, "drbd_send_drequest(..., csum) failed\n");
38262306a36Sopenharmony_ci	return err;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci#define GFP_TRY	(__GFP_HIGHMEM | __GFP_NOWARN)
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector, int size)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
39062306a36Sopenharmony_ci	struct drbd_peer_request *peer_req;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	if (!get_ldev(device))
39362306a36Sopenharmony_ci		return -EIO;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	/* GFP_TRY, because if there is no memory available right now, this may
39662306a36Sopenharmony_ci	 * be rescheduled for later. It is "only" background resync, after all. */
39762306a36Sopenharmony_ci	peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER /* unused */, sector,
39862306a36Sopenharmony_ci				       size, size, GFP_TRY);
39962306a36Sopenharmony_ci	if (!peer_req)
40062306a36Sopenharmony_ci		goto defer;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	peer_req->w.cb = w_e_send_csum;
40362306a36Sopenharmony_ci	peer_req->opf = REQ_OP_READ;
40462306a36Sopenharmony_ci	spin_lock_irq(&device->resource->req_lock);
40562306a36Sopenharmony_ci	list_add_tail(&peer_req->w.list, &device->read_ee);
40662306a36Sopenharmony_ci	spin_unlock_irq(&device->resource->req_lock);
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	atomic_add(size >> 9, &device->rs_sect_ev);
40962306a36Sopenharmony_ci	if (drbd_submit_peer_request(peer_req) == 0)
41062306a36Sopenharmony_ci		return 0;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	/* If it failed because of ENOMEM, retry should help.  If it failed
41362306a36Sopenharmony_ci	 * because bio_add_page failed (probably broken lower level driver),
41462306a36Sopenharmony_ci	 * retry may or may not help.
41562306a36Sopenharmony_ci	 * If it does not, you may need to force disconnect. */
41662306a36Sopenharmony_ci	spin_lock_irq(&device->resource->req_lock);
41762306a36Sopenharmony_ci	list_del(&peer_req->w.list);
41862306a36Sopenharmony_ci	spin_unlock_irq(&device->resource->req_lock);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	drbd_free_peer_req(device, peer_req);
42162306a36Sopenharmony_cidefer:
42262306a36Sopenharmony_ci	put_ldev(device);
42362306a36Sopenharmony_ci	return -EAGAIN;
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ciint w_resync_timer(struct drbd_work *w, int cancel)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	struct drbd_device *device =
42962306a36Sopenharmony_ci		container_of(w, struct drbd_device, resync_work);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	switch (device->state.conn) {
43262306a36Sopenharmony_ci	case C_VERIFY_S:
43362306a36Sopenharmony_ci		make_ov_request(first_peer_device(device), cancel);
43462306a36Sopenharmony_ci		break;
43562306a36Sopenharmony_ci	case C_SYNC_TARGET:
43662306a36Sopenharmony_ci		make_resync_request(first_peer_device(device), cancel);
43762306a36Sopenharmony_ci		break;
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	return 0;
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_civoid resync_timer_fn(struct timer_list *t)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	struct drbd_device *device = from_timer(device, t, resync_timer);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	drbd_queue_work_if_unqueued(
44862306a36Sopenharmony_ci		&first_peer_device(device)->connection->sender_work,
44962306a36Sopenharmony_ci		&device->resync_work);
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cistatic void fifo_set(struct fifo_buffer *fb, int value)
45362306a36Sopenharmony_ci{
45462306a36Sopenharmony_ci	int i;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	for (i = 0; i < fb->size; i++)
45762306a36Sopenharmony_ci		fb->values[i] = value;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic int fifo_push(struct fifo_buffer *fb, int value)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	int ov;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	ov = fb->values[fb->head_index];
46562306a36Sopenharmony_ci	fb->values[fb->head_index++] = value;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	if (fb->head_index >= fb->size)
46862306a36Sopenharmony_ci		fb->head_index = 0;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	return ov;
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic void fifo_add_val(struct fifo_buffer *fb, int value)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	int i;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	for (i = 0; i < fb->size; i++)
47862306a36Sopenharmony_ci		fb->values[i] += value;
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistruct fifo_buffer *fifo_alloc(unsigned int fifo_size)
48262306a36Sopenharmony_ci{
48362306a36Sopenharmony_ci	struct fifo_buffer *fb;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	fb = kzalloc(struct_size(fb, values, fifo_size), GFP_NOIO);
48662306a36Sopenharmony_ci	if (!fb)
48762306a36Sopenharmony_ci		return NULL;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	fb->head_index = 0;
49062306a36Sopenharmony_ci	fb->size = fifo_size;
49162306a36Sopenharmony_ci	fb->total = 0;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	return fb;
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_cistatic int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int sect_in)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
49962306a36Sopenharmony_ci	struct disk_conf *dc;
50062306a36Sopenharmony_ci	unsigned int want;     /* The number of sectors we want in-flight */
50162306a36Sopenharmony_ci	int req_sect; /* Number of sectors to request in this turn */
50262306a36Sopenharmony_ci	int correction; /* Number of sectors more we need in-flight */
50362306a36Sopenharmony_ci	int cps; /* correction per invocation of drbd_rs_controller() */
50462306a36Sopenharmony_ci	int steps; /* Number of time steps to plan ahead */
50562306a36Sopenharmony_ci	int curr_corr;
50662306a36Sopenharmony_ci	int max_sect;
50762306a36Sopenharmony_ci	struct fifo_buffer *plan;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	dc = rcu_dereference(device->ldev->disk_conf);
51062306a36Sopenharmony_ci	plan = rcu_dereference(device->rs_plan_s);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	steps = plan->size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	if (device->rs_in_flight + sect_in == 0) { /* At start of resync */
51562306a36Sopenharmony_ci		want = ((dc->resync_rate * 2 * SLEEP_TIME) / HZ) * steps;
51662306a36Sopenharmony_ci	} else { /* normal path */
51762306a36Sopenharmony_ci		want = dc->c_fill_target ? dc->c_fill_target :
51862306a36Sopenharmony_ci			sect_in * dc->c_delay_target * HZ / (SLEEP_TIME * 10);
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	correction = want - device->rs_in_flight - plan->total;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	/* Plan ahead */
52462306a36Sopenharmony_ci	cps = correction / steps;
52562306a36Sopenharmony_ci	fifo_add_val(plan, cps);
52662306a36Sopenharmony_ci	plan->total += cps * steps;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	/* What we do in this step */
52962306a36Sopenharmony_ci	curr_corr = fifo_push(plan, 0);
53062306a36Sopenharmony_ci	plan->total -= curr_corr;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	req_sect = sect_in + curr_corr;
53362306a36Sopenharmony_ci	if (req_sect < 0)
53462306a36Sopenharmony_ci		req_sect = 0;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	max_sect = (dc->c_max_rate * 2 * SLEEP_TIME) / HZ;
53762306a36Sopenharmony_ci	if (req_sect > max_sect)
53862306a36Sopenharmony_ci		req_sect = max_sect;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	/*
54162306a36Sopenharmony_ci	drbd_warn(device, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
54262306a36Sopenharmony_ci		 sect_in, device->rs_in_flight, want, correction,
54362306a36Sopenharmony_ci		 steps, cps, device->rs_planed, curr_corr, req_sect);
54462306a36Sopenharmony_ci	*/
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	return req_sect;
54762306a36Sopenharmony_ci}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_cistatic int drbd_rs_number_requests(struct drbd_peer_device *peer_device)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
55262306a36Sopenharmony_ci	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
55362306a36Sopenharmony_ci	int number, mxb;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	sect_in = atomic_xchg(&device->rs_sect_in, 0);
55662306a36Sopenharmony_ci	device->rs_in_flight -= sect_in;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	rcu_read_lock();
55962306a36Sopenharmony_ci	mxb = drbd_get_max_buffers(device) / 2;
56062306a36Sopenharmony_ci	if (rcu_dereference(device->rs_plan_s)->size) {
56162306a36Sopenharmony_ci		number = drbd_rs_controller(peer_device, sect_in) >> (BM_BLOCK_SHIFT - 9);
56262306a36Sopenharmony_ci		device->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
56362306a36Sopenharmony_ci	} else {
56462306a36Sopenharmony_ci		device->c_sync_rate = rcu_dereference(device->ldev->disk_conf)->resync_rate;
56562306a36Sopenharmony_ci		number = SLEEP_TIME * device->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
56662306a36Sopenharmony_ci	}
56762306a36Sopenharmony_ci	rcu_read_unlock();
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	/* Don't have more than "max-buffers"/2 in-flight.
57062306a36Sopenharmony_ci	 * Otherwise we may cause the remote site to stall on drbd_alloc_pages(),
57162306a36Sopenharmony_ci	 * potentially causing a distributed deadlock on congestion during
57262306a36Sopenharmony_ci	 * online-verify or (checksum-based) resync, if max-buffers,
57362306a36Sopenharmony_ci	 * socket buffer sizes and resync rate settings are mis-configured. */
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	/* note that "number" is in units of "BM_BLOCK_SIZE" (which is 4k),
57662306a36Sopenharmony_ci	 * mxb (as used here, and in drbd_alloc_pages on the peer) is
57762306a36Sopenharmony_ci	 * "number of pages" (typically also 4k),
57862306a36Sopenharmony_ci	 * but "rs_in_flight" is in "sectors" (512 Byte). */
57962306a36Sopenharmony_ci	if (mxb - device->rs_in_flight/8 < number)
58062306a36Sopenharmony_ci		number = mxb - device->rs_in_flight/8;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	return number;
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_cistatic int make_resync_request(struct drbd_peer_device *const peer_device, int cancel)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	struct drbd_device *const device = peer_device->device;
58862306a36Sopenharmony_ci	struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
58962306a36Sopenharmony_ci	unsigned long bit;
59062306a36Sopenharmony_ci	sector_t sector;
59162306a36Sopenharmony_ci	const sector_t capacity = get_capacity(device->vdisk);
59262306a36Sopenharmony_ci	int max_bio_size;
59362306a36Sopenharmony_ci	int number, rollback_i, size;
59462306a36Sopenharmony_ci	int align, requeue = 0;
59562306a36Sopenharmony_ci	int i = 0;
59662306a36Sopenharmony_ci	int discard_granularity = 0;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	if (unlikely(cancel))
59962306a36Sopenharmony_ci		return 0;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	if (device->rs_total == 0) {
60262306a36Sopenharmony_ci		/* empty resync? */
60362306a36Sopenharmony_ci		drbd_resync_finished(peer_device);
60462306a36Sopenharmony_ci		return 0;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	if (!get_ldev(device)) {
60862306a36Sopenharmony_ci		/* Since we only need to access device->rsync a
60962306a36Sopenharmony_ci		   get_ldev_if_state(device,D_FAILED) would be sufficient, but
61062306a36Sopenharmony_ci		   to continue resync with a broken disk makes no sense at
61162306a36Sopenharmony_ci		   all */
61262306a36Sopenharmony_ci		drbd_err(device, "Disk broke down during resync!\n");
61362306a36Sopenharmony_ci		return 0;
61462306a36Sopenharmony_ci	}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	if (connection->agreed_features & DRBD_FF_THIN_RESYNC) {
61762306a36Sopenharmony_ci		rcu_read_lock();
61862306a36Sopenharmony_ci		discard_granularity = rcu_dereference(device->ldev->disk_conf)->rs_discard_granularity;
61962306a36Sopenharmony_ci		rcu_read_unlock();
62062306a36Sopenharmony_ci	}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	max_bio_size = queue_max_hw_sectors(device->rq_queue) << 9;
62362306a36Sopenharmony_ci	number = drbd_rs_number_requests(peer_device);
62462306a36Sopenharmony_ci	if (number <= 0)
62562306a36Sopenharmony_ci		goto requeue;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	for (i = 0; i < number; i++) {
62862306a36Sopenharmony_ci		/* Stop generating RS requests when half of the send buffer is filled,
62962306a36Sopenharmony_ci		 * but notify TCP that we'd like to have more space. */
63062306a36Sopenharmony_ci		mutex_lock(&connection->data.mutex);
63162306a36Sopenharmony_ci		if (connection->data.socket) {
63262306a36Sopenharmony_ci			struct sock *sk = connection->data.socket->sk;
63362306a36Sopenharmony_ci			int queued = sk->sk_wmem_queued;
63462306a36Sopenharmony_ci			int sndbuf = sk->sk_sndbuf;
63562306a36Sopenharmony_ci			if (queued > sndbuf / 2) {
63662306a36Sopenharmony_ci				requeue = 1;
63762306a36Sopenharmony_ci				if (sk->sk_socket)
63862306a36Sopenharmony_ci					set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
63962306a36Sopenharmony_ci			}
64062306a36Sopenharmony_ci		} else
64162306a36Sopenharmony_ci			requeue = 1;
64262306a36Sopenharmony_ci		mutex_unlock(&connection->data.mutex);
64362306a36Sopenharmony_ci		if (requeue)
64462306a36Sopenharmony_ci			goto requeue;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_cinext_sector:
64762306a36Sopenharmony_ci		size = BM_BLOCK_SIZE;
64862306a36Sopenharmony_ci		bit  = drbd_bm_find_next(device, device->bm_resync_fo);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci		if (bit == DRBD_END_OF_BITMAP) {
65162306a36Sopenharmony_ci			device->bm_resync_fo = drbd_bm_bits(device);
65262306a36Sopenharmony_ci			put_ldev(device);
65362306a36Sopenharmony_ci			return 0;
65462306a36Sopenharmony_ci		}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci		sector = BM_BIT_TO_SECT(bit);
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci		if (drbd_try_rs_begin_io(peer_device, sector)) {
65962306a36Sopenharmony_ci			device->bm_resync_fo = bit;
66062306a36Sopenharmony_ci			goto requeue;
66162306a36Sopenharmony_ci		}
66262306a36Sopenharmony_ci		device->bm_resync_fo = bit + 1;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci		if (unlikely(drbd_bm_test_bit(device, bit) == 0)) {
66562306a36Sopenharmony_ci			drbd_rs_complete_io(device, sector);
66662306a36Sopenharmony_ci			goto next_sector;
66762306a36Sopenharmony_ci		}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci#if DRBD_MAX_BIO_SIZE > BM_BLOCK_SIZE
67062306a36Sopenharmony_ci		/* try to find some adjacent bits.
67162306a36Sopenharmony_ci		 * we stop if we have already the maximum req size.
67262306a36Sopenharmony_ci		 *
67362306a36Sopenharmony_ci		 * Additionally always align bigger requests, in order to
67462306a36Sopenharmony_ci		 * be prepared for all stripe sizes of software RAIDs.
67562306a36Sopenharmony_ci		 */
67662306a36Sopenharmony_ci		align = 1;
67762306a36Sopenharmony_ci		rollback_i = i;
67862306a36Sopenharmony_ci		while (i < number) {
67962306a36Sopenharmony_ci			if (size + BM_BLOCK_SIZE > max_bio_size)
68062306a36Sopenharmony_ci				break;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci			/* Be always aligned */
68362306a36Sopenharmony_ci			if (sector & ((1<<(align+3))-1))
68462306a36Sopenharmony_ci				break;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci			if (discard_granularity && size == discard_granularity)
68762306a36Sopenharmony_ci				break;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci			/* do not cross extent boundaries */
69062306a36Sopenharmony_ci			if (((bit+1) & BM_BLOCKS_PER_BM_EXT_MASK) == 0)
69162306a36Sopenharmony_ci				break;
69262306a36Sopenharmony_ci			/* now, is it actually dirty, after all?
69362306a36Sopenharmony_ci			 * caution, drbd_bm_test_bit is tri-state for some
69462306a36Sopenharmony_ci			 * obscure reason; ( b == 0 ) would get the out-of-band
69562306a36Sopenharmony_ci			 * only accidentally right because of the "oddly sized"
69662306a36Sopenharmony_ci			 * adjustment below */
69762306a36Sopenharmony_ci			if (drbd_bm_test_bit(device, bit+1) != 1)
69862306a36Sopenharmony_ci				break;
69962306a36Sopenharmony_ci			bit++;
70062306a36Sopenharmony_ci			size += BM_BLOCK_SIZE;
70162306a36Sopenharmony_ci			if ((BM_BLOCK_SIZE << align) <= size)
70262306a36Sopenharmony_ci				align++;
70362306a36Sopenharmony_ci			i++;
70462306a36Sopenharmony_ci		}
70562306a36Sopenharmony_ci		/* if we merged some,
70662306a36Sopenharmony_ci		 * reset the offset to start the next drbd_bm_find_next from */
70762306a36Sopenharmony_ci		if (size > BM_BLOCK_SIZE)
70862306a36Sopenharmony_ci			device->bm_resync_fo = bit + 1;
70962306a36Sopenharmony_ci#endif
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci		/* adjust very last sectors, in case we are oddly sized */
71262306a36Sopenharmony_ci		if (sector + (size>>9) > capacity)
71362306a36Sopenharmony_ci			size = (capacity-sector)<<9;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci		if (device->use_csums) {
71662306a36Sopenharmony_ci			switch (read_for_csum(peer_device, sector, size)) {
71762306a36Sopenharmony_ci			case -EIO: /* Disk failure */
71862306a36Sopenharmony_ci				put_ldev(device);
71962306a36Sopenharmony_ci				return -EIO;
72062306a36Sopenharmony_ci			case -EAGAIN: /* allocation failed, or ldev busy */
72162306a36Sopenharmony_ci				drbd_rs_complete_io(device, sector);
72262306a36Sopenharmony_ci				device->bm_resync_fo = BM_SECT_TO_BIT(sector);
72362306a36Sopenharmony_ci				i = rollback_i;
72462306a36Sopenharmony_ci				goto requeue;
72562306a36Sopenharmony_ci			case 0:
72662306a36Sopenharmony_ci				/* everything ok */
72762306a36Sopenharmony_ci				break;
72862306a36Sopenharmony_ci			default:
72962306a36Sopenharmony_ci				BUG();
73062306a36Sopenharmony_ci			}
73162306a36Sopenharmony_ci		} else {
73262306a36Sopenharmony_ci			int err;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci			inc_rs_pending(peer_device);
73562306a36Sopenharmony_ci			err = drbd_send_drequest(peer_device,
73662306a36Sopenharmony_ci						 size == discard_granularity ? P_RS_THIN_REQ : P_RS_DATA_REQUEST,
73762306a36Sopenharmony_ci						 sector, size, ID_SYNCER);
73862306a36Sopenharmony_ci			if (err) {
73962306a36Sopenharmony_ci				drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
74062306a36Sopenharmony_ci				dec_rs_pending(peer_device);
74162306a36Sopenharmony_ci				put_ldev(device);
74262306a36Sopenharmony_ci				return err;
74362306a36Sopenharmony_ci			}
74462306a36Sopenharmony_ci		}
74562306a36Sopenharmony_ci	}
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	if (device->bm_resync_fo >= drbd_bm_bits(device)) {
74862306a36Sopenharmony_ci		/* last syncer _request_ was sent,
74962306a36Sopenharmony_ci		 * but the P_RS_DATA_REPLY not yet received.  sync will end (and
75062306a36Sopenharmony_ci		 * next sync group will resume), as soon as we receive the last
75162306a36Sopenharmony_ci		 * resync data block, and the last bit is cleared.
75262306a36Sopenharmony_ci		 * until then resync "work" is "inactive" ...
75362306a36Sopenharmony_ci		 */
75462306a36Sopenharmony_ci		put_ldev(device);
75562306a36Sopenharmony_ci		return 0;
75662306a36Sopenharmony_ci	}
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci requeue:
75962306a36Sopenharmony_ci	device->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
76062306a36Sopenharmony_ci	mod_timer(&device->resync_timer, jiffies + SLEEP_TIME);
76162306a36Sopenharmony_ci	put_ldev(device);
76262306a36Sopenharmony_ci	return 0;
76362306a36Sopenharmony_ci}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_cistatic int make_ov_request(struct drbd_peer_device *peer_device, int cancel)
76662306a36Sopenharmony_ci{
76762306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
76862306a36Sopenharmony_ci	int number, i, size;
76962306a36Sopenharmony_ci	sector_t sector;
77062306a36Sopenharmony_ci	const sector_t capacity = get_capacity(device->vdisk);
77162306a36Sopenharmony_ci	bool stop_sector_reached = false;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	if (unlikely(cancel))
77462306a36Sopenharmony_ci		return 1;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	number = drbd_rs_number_requests(peer_device);
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	sector = device->ov_position;
77962306a36Sopenharmony_ci	for (i = 0; i < number; i++) {
78062306a36Sopenharmony_ci		if (sector >= capacity)
78162306a36Sopenharmony_ci			return 1;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci		/* We check for "finished" only in the reply path:
78462306a36Sopenharmony_ci		 * w_e_end_ov_reply().
78562306a36Sopenharmony_ci		 * We need to send at least one request out. */
78662306a36Sopenharmony_ci		stop_sector_reached = i > 0
78762306a36Sopenharmony_ci			&& verify_can_do_stop_sector(device)
78862306a36Sopenharmony_ci			&& sector >= device->ov_stop_sector;
78962306a36Sopenharmony_ci		if (stop_sector_reached)
79062306a36Sopenharmony_ci			break;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci		size = BM_BLOCK_SIZE;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci		if (drbd_try_rs_begin_io(peer_device, sector)) {
79562306a36Sopenharmony_ci			device->ov_position = sector;
79662306a36Sopenharmony_ci			goto requeue;
79762306a36Sopenharmony_ci		}
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci		if (sector + (size>>9) > capacity)
80062306a36Sopenharmony_ci			size = (capacity-sector)<<9;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci		inc_rs_pending(peer_device);
80362306a36Sopenharmony_ci		if (drbd_send_ov_request(first_peer_device(device), sector, size)) {
80462306a36Sopenharmony_ci			dec_rs_pending(peer_device);
80562306a36Sopenharmony_ci			return 0;
80662306a36Sopenharmony_ci		}
80762306a36Sopenharmony_ci		sector += BM_SECT_PER_BIT;
80862306a36Sopenharmony_ci	}
80962306a36Sopenharmony_ci	device->ov_position = sector;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci requeue:
81262306a36Sopenharmony_ci	device->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
81362306a36Sopenharmony_ci	if (i == 0 || !stop_sector_reached)
81462306a36Sopenharmony_ci		mod_timer(&device->resync_timer, jiffies + SLEEP_TIME);
81562306a36Sopenharmony_ci	return 1;
81662306a36Sopenharmony_ci}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ciint w_ov_finished(struct drbd_work *w, int cancel)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	struct drbd_device_work *dw =
82162306a36Sopenharmony_ci		container_of(w, struct drbd_device_work, w);
82262306a36Sopenharmony_ci	struct drbd_device *device = dw->device;
82362306a36Sopenharmony_ci	kfree(dw);
82462306a36Sopenharmony_ci	ov_out_of_sync_print(first_peer_device(device));
82562306a36Sopenharmony_ci	drbd_resync_finished(first_peer_device(device));
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	return 0;
82862306a36Sopenharmony_ci}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_cistatic int w_resync_finished(struct drbd_work *w, int cancel)
83162306a36Sopenharmony_ci{
83262306a36Sopenharmony_ci	struct drbd_device_work *dw =
83362306a36Sopenharmony_ci		container_of(w, struct drbd_device_work, w);
83462306a36Sopenharmony_ci	struct drbd_device *device = dw->device;
83562306a36Sopenharmony_ci	kfree(dw);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	drbd_resync_finished(first_peer_device(device));
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	return 0;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic void ping_peer(struct drbd_device *device)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	struct drbd_connection *connection = first_peer_device(device)->connection;
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	clear_bit(GOT_PING_ACK, &connection->flags);
84762306a36Sopenharmony_ci	request_ping(connection);
84862306a36Sopenharmony_ci	wait_event(connection->ping_wait,
84962306a36Sopenharmony_ci		   test_bit(GOT_PING_ACK, &connection->flags) || device->state.conn < C_CONNECTED);
85062306a36Sopenharmony_ci}
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ciint drbd_resync_finished(struct drbd_peer_device *peer_device)
85362306a36Sopenharmony_ci{
85462306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
85562306a36Sopenharmony_ci	struct drbd_connection *connection = peer_device->connection;
85662306a36Sopenharmony_ci	unsigned long db, dt, dbdt;
85762306a36Sopenharmony_ci	unsigned long n_oos;
85862306a36Sopenharmony_ci	union drbd_state os, ns;
85962306a36Sopenharmony_ci	struct drbd_device_work *dw;
86062306a36Sopenharmony_ci	char *khelper_cmd = NULL;
86162306a36Sopenharmony_ci	int verify_done = 0;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	/* Remove all elements from the resync LRU. Since future actions
86462306a36Sopenharmony_ci	 * might set bits in the (main) bitmap, then the entries in the
86562306a36Sopenharmony_ci	 * resync LRU would be wrong. */
86662306a36Sopenharmony_ci	if (drbd_rs_del_all(device)) {
86762306a36Sopenharmony_ci		/* In case this is not possible now, most probably because
86862306a36Sopenharmony_ci		 * there are P_RS_DATA_REPLY Packets lingering on the worker's
86962306a36Sopenharmony_ci		 * queue (or even the read operations for those packets
87062306a36Sopenharmony_ci		 * is not finished by now).   Retry in 100ms. */
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci		schedule_timeout_interruptible(HZ / 10);
87362306a36Sopenharmony_ci		dw = kmalloc(sizeof(struct drbd_device_work), GFP_ATOMIC);
87462306a36Sopenharmony_ci		if (dw) {
87562306a36Sopenharmony_ci			dw->w.cb = w_resync_finished;
87662306a36Sopenharmony_ci			dw->device = device;
87762306a36Sopenharmony_ci			drbd_queue_work(&connection->sender_work, &dw->w);
87862306a36Sopenharmony_ci			return 1;
87962306a36Sopenharmony_ci		}
88062306a36Sopenharmony_ci		drbd_err(device, "Warn failed to drbd_rs_del_all() and to kmalloc(dw).\n");
88162306a36Sopenharmony_ci	}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
88462306a36Sopenharmony_ci	if (dt <= 0)
88562306a36Sopenharmony_ci		dt = 1;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	db = device->rs_total;
88862306a36Sopenharmony_ci	/* adjust for verify start and stop sectors, respective reached position */
88962306a36Sopenharmony_ci	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
89062306a36Sopenharmony_ci		db -= device->ov_left;
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	dbdt = Bit2KB(db/dt);
89362306a36Sopenharmony_ci	device->rs_paused /= HZ;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	if (!get_ldev(device))
89662306a36Sopenharmony_ci		goto out;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	ping_peer(device);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	spin_lock_irq(&device->resource->req_lock);
90162306a36Sopenharmony_ci	os = drbd_read_state(device);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	/* This protects us against multiple calls (that can happen in the presence
90662306a36Sopenharmony_ci	   of application IO), and against connectivity loss just before we arrive here. */
90762306a36Sopenharmony_ci	if (os.conn <= C_CONNECTED)
90862306a36Sopenharmony_ci		goto out_unlock;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	ns = os;
91162306a36Sopenharmony_ci	ns.conn = C_CONNECTED;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	drbd_info(device, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
91462306a36Sopenharmony_ci	     verify_done ? "Online verify" : "Resync",
91562306a36Sopenharmony_ci	     dt + device->rs_paused, device->rs_paused, dbdt);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	n_oos = drbd_bm_total_weight(device);
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	if (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) {
92062306a36Sopenharmony_ci		if (n_oos) {
92162306a36Sopenharmony_ci			drbd_alert(device, "Online verify found %lu %dk block out of sync!\n",
92262306a36Sopenharmony_ci			      n_oos, Bit2KB(1));
92362306a36Sopenharmony_ci			khelper_cmd = "out-of-sync";
92462306a36Sopenharmony_ci		}
92562306a36Sopenharmony_ci	} else {
92662306a36Sopenharmony_ci		D_ASSERT(device, (n_oos - device->rs_failed) == 0);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T)
92962306a36Sopenharmony_ci			khelper_cmd = "after-resync-target";
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		if (device->use_csums && device->rs_total) {
93262306a36Sopenharmony_ci			const unsigned long s = device->rs_same_csum;
93362306a36Sopenharmony_ci			const unsigned long t = device->rs_total;
93462306a36Sopenharmony_ci			const int ratio =
93562306a36Sopenharmony_ci				(t == 0)     ? 0 :
93662306a36Sopenharmony_ci			(t < 100000) ? ((s*100)/t) : (s/(t/100));
93762306a36Sopenharmony_ci			drbd_info(device, "%u %% had equal checksums, eliminated: %luK; "
93862306a36Sopenharmony_ci			     "transferred %luK total %luK\n",
93962306a36Sopenharmony_ci			     ratio,
94062306a36Sopenharmony_ci			     Bit2KB(device->rs_same_csum),
94162306a36Sopenharmony_ci			     Bit2KB(device->rs_total - device->rs_same_csum),
94262306a36Sopenharmony_ci			     Bit2KB(device->rs_total));
94362306a36Sopenharmony_ci		}
94462306a36Sopenharmony_ci	}
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	if (device->rs_failed) {
94762306a36Sopenharmony_ci		drbd_info(device, "            %lu failed blocks\n", device->rs_failed);
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T) {
95062306a36Sopenharmony_ci			ns.disk = D_INCONSISTENT;
95162306a36Sopenharmony_ci			ns.pdsk = D_UP_TO_DATE;
95262306a36Sopenharmony_ci		} else {
95362306a36Sopenharmony_ci			ns.disk = D_UP_TO_DATE;
95462306a36Sopenharmony_ci			ns.pdsk = D_INCONSISTENT;
95562306a36Sopenharmony_ci		}
95662306a36Sopenharmony_ci	} else {
95762306a36Sopenharmony_ci		ns.disk = D_UP_TO_DATE;
95862306a36Sopenharmony_ci		ns.pdsk = D_UP_TO_DATE;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T) {
96162306a36Sopenharmony_ci			if (device->p_uuid) {
96262306a36Sopenharmony_ci				int i;
96362306a36Sopenharmony_ci				for (i = UI_BITMAP ; i <= UI_HISTORY_END ; i++)
96462306a36Sopenharmony_ci					_drbd_uuid_set(device, i, device->p_uuid[i]);
96562306a36Sopenharmony_ci				drbd_uuid_set(device, UI_BITMAP, device->ldev->md.uuid[UI_CURRENT]);
96662306a36Sopenharmony_ci				_drbd_uuid_set(device, UI_CURRENT, device->p_uuid[UI_CURRENT]);
96762306a36Sopenharmony_ci			} else {
96862306a36Sopenharmony_ci				drbd_err(device, "device->p_uuid is NULL! BUG\n");
96962306a36Sopenharmony_ci			}
97062306a36Sopenharmony_ci		}
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci		if (!(os.conn == C_VERIFY_S || os.conn == C_VERIFY_T)) {
97362306a36Sopenharmony_ci			/* for verify runs, we don't update uuids here,
97462306a36Sopenharmony_ci			 * so there would be nothing to report. */
97562306a36Sopenharmony_ci			drbd_uuid_set_bm(device, 0UL);
97662306a36Sopenharmony_ci			drbd_print_uuids(device, "updated UUIDs");
97762306a36Sopenharmony_ci			if (device->p_uuid) {
97862306a36Sopenharmony_ci				/* Now the two UUID sets are equal, update what we
97962306a36Sopenharmony_ci				 * know of the peer. */
98062306a36Sopenharmony_ci				int i;
98162306a36Sopenharmony_ci				for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
98262306a36Sopenharmony_ci					device->p_uuid[i] = device->ldev->md.uuid[i];
98362306a36Sopenharmony_ci			}
98462306a36Sopenharmony_ci		}
98562306a36Sopenharmony_ci	}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	_drbd_set_state(device, ns, CS_VERBOSE, NULL);
98862306a36Sopenharmony_ciout_unlock:
98962306a36Sopenharmony_ci	spin_unlock_irq(&device->resource->req_lock);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	/* If we have been sync source, and have an effective fencing-policy,
99262306a36Sopenharmony_ci	 * once *all* volumes are back in sync, call "unfence". */
99362306a36Sopenharmony_ci	if (os.conn == C_SYNC_SOURCE) {
99462306a36Sopenharmony_ci		enum drbd_disk_state disk_state = D_MASK;
99562306a36Sopenharmony_ci		enum drbd_disk_state pdsk_state = D_MASK;
99662306a36Sopenharmony_ci		enum drbd_fencing_p fp = FP_DONT_CARE;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci		rcu_read_lock();
99962306a36Sopenharmony_ci		fp = rcu_dereference(device->ldev->disk_conf)->fencing;
100062306a36Sopenharmony_ci		if (fp != FP_DONT_CARE) {
100162306a36Sopenharmony_ci			struct drbd_peer_device *peer_device;
100262306a36Sopenharmony_ci			int vnr;
100362306a36Sopenharmony_ci			idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
100462306a36Sopenharmony_ci				struct drbd_device *device = peer_device->device;
100562306a36Sopenharmony_ci				disk_state = min_t(enum drbd_disk_state, disk_state, device->state.disk);
100662306a36Sopenharmony_ci				pdsk_state = min_t(enum drbd_disk_state, pdsk_state, device->state.pdsk);
100762306a36Sopenharmony_ci			}
100862306a36Sopenharmony_ci		}
100962306a36Sopenharmony_ci		rcu_read_unlock();
101062306a36Sopenharmony_ci		if (disk_state == D_UP_TO_DATE && pdsk_state == D_UP_TO_DATE)
101162306a36Sopenharmony_ci			conn_khelper(connection, "unfence-peer");
101262306a36Sopenharmony_ci	}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	put_ldev(device);
101562306a36Sopenharmony_ciout:
101662306a36Sopenharmony_ci	device->rs_total  = 0;
101762306a36Sopenharmony_ci	device->rs_failed = 0;
101862306a36Sopenharmony_ci	device->rs_paused = 0;
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	/* reset start sector, if we reached end of device */
102162306a36Sopenharmony_ci	if (verify_done && device->ov_left == 0)
102262306a36Sopenharmony_ci		device->ov_start_sector = 0;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	drbd_md_sync(device);
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	if (khelper_cmd)
102762306a36Sopenharmony_ci		drbd_khelper(device, khelper_cmd);
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	return 1;
103062306a36Sopenharmony_ci}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci/* helper */
103362306a36Sopenharmony_cistatic void move_to_net_ee_or_free(struct drbd_device *device, struct drbd_peer_request *peer_req)
103462306a36Sopenharmony_ci{
103562306a36Sopenharmony_ci	if (drbd_peer_req_has_active_page(peer_req)) {
103662306a36Sopenharmony_ci		/* This might happen if sendpage() has not finished */
103762306a36Sopenharmony_ci		int i = PFN_UP(peer_req->i.size);
103862306a36Sopenharmony_ci		atomic_add(i, &device->pp_in_use_by_net);
103962306a36Sopenharmony_ci		atomic_sub(i, &device->pp_in_use);
104062306a36Sopenharmony_ci		spin_lock_irq(&device->resource->req_lock);
104162306a36Sopenharmony_ci		list_add_tail(&peer_req->w.list, &device->net_ee);
104262306a36Sopenharmony_ci		spin_unlock_irq(&device->resource->req_lock);
104362306a36Sopenharmony_ci		wake_up(&drbd_pp_wait);
104462306a36Sopenharmony_ci	} else
104562306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci/**
104962306a36Sopenharmony_ci * w_e_end_data_req() - Worker callback, to send a P_DATA_REPLY packet in response to a P_DATA_REQUEST
105062306a36Sopenharmony_ci * @w:		work object.
105162306a36Sopenharmony_ci * @cancel:	The connection will be closed anyways
105262306a36Sopenharmony_ci */
105362306a36Sopenharmony_ciint w_e_end_data_req(struct drbd_work *w, int cancel)
105462306a36Sopenharmony_ci{
105562306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
105662306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
105762306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
105862306a36Sopenharmony_ci	int err;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	if (unlikely(cancel)) {
106162306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
106262306a36Sopenharmony_ci		dec_unacked(device);
106362306a36Sopenharmony_ci		return 0;
106462306a36Sopenharmony_ci	}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
106762306a36Sopenharmony_ci		err = drbd_send_block(peer_device, P_DATA_REPLY, peer_req);
106862306a36Sopenharmony_ci	} else {
106962306a36Sopenharmony_ci		if (drbd_ratelimit())
107062306a36Sopenharmony_ci			drbd_err(device, "Sending NegDReply. sector=%llus.\n",
107162306a36Sopenharmony_ci			    (unsigned long long)peer_req->i.sector);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci		err = drbd_send_ack(peer_device, P_NEG_DREPLY, peer_req);
107462306a36Sopenharmony_ci	}
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	dec_unacked(device);
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	move_to_net_ee_or_free(device, peer_req);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	if (unlikely(err))
108162306a36Sopenharmony_ci		drbd_err(device, "drbd_send_block() failed\n");
108262306a36Sopenharmony_ci	return err;
108362306a36Sopenharmony_ci}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_cistatic bool all_zero(struct drbd_peer_request *peer_req)
108662306a36Sopenharmony_ci{
108762306a36Sopenharmony_ci	struct page *page = peer_req->pages;
108862306a36Sopenharmony_ci	unsigned int len = peer_req->i.size;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	page_chain_for_each(page) {
109162306a36Sopenharmony_ci		unsigned int l = min_t(unsigned int, len, PAGE_SIZE);
109262306a36Sopenharmony_ci		unsigned int i, words = l / sizeof(long);
109362306a36Sopenharmony_ci		unsigned long *d;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci		d = kmap_atomic(page);
109662306a36Sopenharmony_ci		for (i = 0; i < words; i++) {
109762306a36Sopenharmony_ci			if (d[i]) {
109862306a36Sopenharmony_ci				kunmap_atomic(d);
109962306a36Sopenharmony_ci				return false;
110062306a36Sopenharmony_ci			}
110162306a36Sopenharmony_ci		}
110262306a36Sopenharmony_ci		kunmap_atomic(d);
110362306a36Sopenharmony_ci		len -= l;
110462306a36Sopenharmony_ci	}
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	return true;
110762306a36Sopenharmony_ci}
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci/**
111062306a36Sopenharmony_ci * w_e_end_rsdata_req() - Worker callback to send a P_RS_DATA_REPLY packet in response to a P_RS_DATA_REQUEST
111162306a36Sopenharmony_ci * @w:		work object.
111262306a36Sopenharmony_ci * @cancel:	The connection will be closed anyways
111362306a36Sopenharmony_ci */
111462306a36Sopenharmony_ciint w_e_end_rsdata_req(struct drbd_work *w, int cancel)
111562306a36Sopenharmony_ci{
111662306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
111762306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
111862306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
111962306a36Sopenharmony_ci	int err;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	if (unlikely(cancel)) {
112262306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
112362306a36Sopenharmony_ci		dec_unacked(device);
112462306a36Sopenharmony_ci		return 0;
112562306a36Sopenharmony_ci	}
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	if (get_ldev_if_state(device, D_FAILED)) {
112862306a36Sopenharmony_ci		drbd_rs_complete_io(device, peer_req->i.sector);
112962306a36Sopenharmony_ci		put_ldev(device);
113062306a36Sopenharmony_ci	}
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	if (device->state.conn == C_AHEAD) {
113362306a36Sopenharmony_ci		err = drbd_send_ack(peer_device, P_RS_CANCEL, peer_req);
113462306a36Sopenharmony_ci	} else if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
113562306a36Sopenharmony_ci		if (likely(device->state.pdsk >= D_INCONSISTENT)) {
113662306a36Sopenharmony_ci			inc_rs_pending(peer_device);
113762306a36Sopenharmony_ci			if (peer_req->flags & EE_RS_THIN_REQ && all_zero(peer_req))
113862306a36Sopenharmony_ci				err = drbd_send_rs_deallocated(peer_device, peer_req);
113962306a36Sopenharmony_ci			else
114062306a36Sopenharmony_ci				err = drbd_send_block(peer_device, P_RS_DATA_REPLY, peer_req);
114162306a36Sopenharmony_ci		} else {
114262306a36Sopenharmony_ci			if (drbd_ratelimit())
114362306a36Sopenharmony_ci				drbd_err(device, "Not sending RSDataReply, "
114462306a36Sopenharmony_ci				    "partner DISKLESS!\n");
114562306a36Sopenharmony_ci			err = 0;
114662306a36Sopenharmony_ci		}
114762306a36Sopenharmony_ci	} else {
114862306a36Sopenharmony_ci		if (drbd_ratelimit())
114962306a36Sopenharmony_ci			drbd_err(device, "Sending NegRSDReply. sector %llus.\n",
115062306a36Sopenharmony_ci			    (unsigned long long)peer_req->i.sector);
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci		err = drbd_send_ack(peer_device, P_NEG_RS_DREPLY, peer_req);
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci		/* update resync data with failure */
115562306a36Sopenharmony_ci		drbd_rs_failed_io(peer_device, peer_req->i.sector, peer_req->i.size);
115662306a36Sopenharmony_ci	}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	dec_unacked(device);
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	move_to_net_ee_or_free(device, peer_req);
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	if (unlikely(err))
116362306a36Sopenharmony_ci		drbd_err(device, "drbd_send_block() failed\n");
116462306a36Sopenharmony_ci	return err;
116562306a36Sopenharmony_ci}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ciint w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
116862306a36Sopenharmony_ci{
116962306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
117062306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
117162306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
117262306a36Sopenharmony_ci	struct digest_info *di;
117362306a36Sopenharmony_ci	int digest_size;
117462306a36Sopenharmony_ci	void *digest = NULL;
117562306a36Sopenharmony_ci	int err, eq = 0;
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	if (unlikely(cancel)) {
117862306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
117962306a36Sopenharmony_ci		dec_unacked(device);
118062306a36Sopenharmony_ci		return 0;
118162306a36Sopenharmony_ci	}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	if (get_ldev(device)) {
118462306a36Sopenharmony_ci		drbd_rs_complete_io(device, peer_req->i.sector);
118562306a36Sopenharmony_ci		put_ldev(device);
118662306a36Sopenharmony_ci	}
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	di = peer_req->digest;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
119162306a36Sopenharmony_ci		/* quick hack to try to avoid a race against reconfiguration.
119262306a36Sopenharmony_ci		 * a real fix would be much more involved,
119362306a36Sopenharmony_ci		 * introducing more locking mechanisms */
119462306a36Sopenharmony_ci		if (peer_device->connection->csums_tfm) {
119562306a36Sopenharmony_ci			digest_size = crypto_shash_digestsize(peer_device->connection->csums_tfm);
119662306a36Sopenharmony_ci			D_ASSERT(device, digest_size == di->digest_size);
119762306a36Sopenharmony_ci			digest = kmalloc(digest_size, GFP_NOIO);
119862306a36Sopenharmony_ci		}
119962306a36Sopenharmony_ci		if (digest) {
120062306a36Sopenharmony_ci			drbd_csum_ee(peer_device->connection->csums_tfm, peer_req, digest);
120162306a36Sopenharmony_ci			eq = !memcmp(digest, di->digest, digest_size);
120262306a36Sopenharmony_ci			kfree(digest);
120362306a36Sopenharmony_ci		}
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci		if (eq) {
120662306a36Sopenharmony_ci			drbd_set_in_sync(peer_device, peer_req->i.sector, peer_req->i.size);
120762306a36Sopenharmony_ci			/* rs_same_csums unit is BM_BLOCK_SIZE */
120862306a36Sopenharmony_ci			device->rs_same_csum += peer_req->i.size >> BM_BLOCK_SHIFT;
120962306a36Sopenharmony_ci			err = drbd_send_ack(peer_device, P_RS_IS_IN_SYNC, peer_req);
121062306a36Sopenharmony_ci		} else {
121162306a36Sopenharmony_ci			inc_rs_pending(peer_device);
121262306a36Sopenharmony_ci			peer_req->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
121362306a36Sopenharmony_ci			peer_req->flags &= ~EE_HAS_DIGEST; /* This peer request no longer has a digest pointer */
121462306a36Sopenharmony_ci			kfree(di);
121562306a36Sopenharmony_ci			err = drbd_send_block(peer_device, P_RS_DATA_REPLY, peer_req);
121662306a36Sopenharmony_ci		}
121762306a36Sopenharmony_ci	} else {
121862306a36Sopenharmony_ci		err = drbd_send_ack(peer_device, P_NEG_RS_DREPLY, peer_req);
121962306a36Sopenharmony_ci		if (drbd_ratelimit())
122062306a36Sopenharmony_ci			drbd_err(device, "Sending NegDReply. I guess it gets messy.\n");
122162306a36Sopenharmony_ci	}
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	dec_unacked(device);
122462306a36Sopenharmony_ci	move_to_net_ee_or_free(device, peer_req);
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	if (unlikely(err))
122762306a36Sopenharmony_ci		drbd_err(device, "drbd_send_block/ack() failed\n");
122862306a36Sopenharmony_ci	return err;
122962306a36Sopenharmony_ci}
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ciint w_e_end_ov_req(struct drbd_work *w, int cancel)
123262306a36Sopenharmony_ci{
123362306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
123462306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
123562306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
123662306a36Sopenharmony_ci	sector_t sector = peer_req->i.sector;
123762306a36Sopenharmony_ci	unsigned int size = peer_req->i.size;
123862306a36Sopenharmony_ci	int digest_size;
123962306a36Sopenharmony_ci	void *digest;
124062306a36Sopenharmony_ci	int err = 0;
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	if (unlikely(cancel))
124362306a36Sopenharmony_ci		goto out;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	digest_size = crypto_shash_digestsize(peer_device->connection->verify_tfm);
124662306a36Sopenharmony_ci	digest = kmalloc(digest_size, GFP_NOIO);
124762306a36Sopenharmony_ci	if (!digest) {
124862306a36Sopenharmony_ci		err = 1;	/* terminate the connection in case the allocation failed */
124962306a36Sopenharmony_ci		goto out;
125062306a36Sopenharmony_ci	}
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	if (likely(!(peer_req->flags & EE_WAS_ERROR)))
125362306a36Sopenharmony_ci		drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest);
125462306a36Sopenharmony_ci	else
125562306a36Sopenharmony_ci		memset(digest, 0, digest_size);
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	/* Free e and pages before send.
125862306a36Sopenharmony_ci	 * In case we block on congestion, we could otherwise run into
125962306a36Sopenharmony_ci	 * some distributed deadlock, if the other side blocks on
126062306a36Sopenharmony_ci	 * congestion as well, because our receiver blocks in
126162306a36Sopenharmony_ci	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
126262306a36Sopenharmony_ci	drbd_free_peer_req(device, peer_req);
126362306a36Sopenharmony_ci	peer_req = NULL;
126462306a36Sopenharmony_ci	inc_rs_pending(peer_device);
126562306a36Sopenharmony_ci	err = drbd_send_drequest_csum(peer_device, sector, size, digest, digest_size, P_OV_REPLY);
126662306a36Sopenharmony_ci	if (err)
126762306a36Sopenharmony_ci		dec_rs_pending(peer_device);
126862306a36Sopenharmony_ci	kfree(digest);
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ciout:
127162306a36Sopenharmony_ci	if (peer_req)
127262306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
127362306a36Sopenharmony_ci	dec_unacked(device);
127462306a36Sopenharmony_ci	return err;
127562306a36Sopenharmony_ci}
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_civoid drbd_ov_out_of_sync_found(struct drbd_peer_device *peer_device, sector_t sector, int size)
127862306a36Sopenharmony_ci{
127962306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
128062306a36Sopenharmony_ci	if (device->ov_last_oos_start + device->ov_last_oos_size == sector) {
128162306a36Sopenharmony_ci		device->ov_last_oos_size += size>>9;
128262306a36Sopenharmony_ci	} else {
128362306a36Sopenharmony_ci		device->ov_last_oos_start = sector;
128462306a36Sopenharmony_ci		device->ov_last_oos_size = size>>9;
128562306a36Sopenharmony_ci	}
128662306a36Sopenharmony_ci	drbd_set_out_of_sync(peer_device, sector, size);
128762306a36Sopenharmony_ci}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ciint w_e_end_ov_reply(struct drbd_work *w, int cancel)
129062306a36Sopenharmony_ci{
129162306a36Sopenharmony_ci	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
129262306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = peer_req->peer_device;
129362306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
129462306a36Sopenharmony_ci	struct digest_info *di;
129562306a36Sopenharmony_ci	void *digest;
129662306a36Sopenharmony_ci	sector_t sector = peer_req->i.sector;
129762306a36Sopenharmony_ci	unsigned int size = peer_req->i.size;
129862306a36Sopenharmony_ci	int digest_size;
129962306a36Sopenharmony_ci	int err, eq = 0;
130062306a36Sopenharmony_ci	bool stop_sector_reached = false;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	if (unlikely(cancel)) {
130362306a36Sopenharmony_ci		drbd_free_peer_req(device, peer_req);
130462306a36Sopenharmony_ci		dec_unacked(device);
130562306a36Sopenharmony_ci		return 0;
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
130962306a36Sopenharmony_ci	 * the resync lru has been cleaned up already */
131062306a36Sopenharmony_ci	if (get_ldev(device)) {
131162306a36Sopenharmony_ci		drbd_rs_complete_io(device, peer_req->i.sector);
131262306a36Sopenharmony_ci		put_ldev(device);
131362306a36Sopenharmony_ci	}
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	di = peer_req->digest;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
131862306a36Sopenharmony_ci		digest_size = crypto_shash_digestsize(peer_device->connection->verify_tfm);
131962306a36Sopenharmony_ci		digest = kmalloc(digest_size, GFP_NOIO);
132062306a36Sopenharmony_ci		if (digest) {
132162306a36Sopenharmony_ci			drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest);
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci			D_ASSERT(device, digest_size == di->digest_size);
132462306a36Sopenharmony_ci			eq = !memcmp(digest, di->digest, digest_size);
132562306a36Sopenharmony_ci			kfree(digest);
132662306a36Sopenharmony_ci		}
132762306a36Sopenharmony_ci	}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	/* Free peer_req and pages before send.
133062306a36Sopenharmony_ci	 * In case we block on congestion, we could otherwise run into
133162306a36Sopenharmony_ci	 * some distributed deadlock, if the other side blocks on
133262306a36Sopenharmony_ci	 * congestion as well, because our receiver blocks in
133362306a36Sopenharmony_ci	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
133462306a36Sopenharmony_ci	drbd_free_peer_req(device, peer_req);
133562306a36Sopenharmony_ci	if (!eq)
133662306a36Sopenharmony_ci		drbd_ov_out_of_sync_found(peer_device, sector, size);
133762306a36Sopenharmony_ci	else
133862306a36Sopenharmony_ci		ov_out_of_sync_print(peer_device);
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	err = drbd_send_ack_ex(peer_device, P_OV_RESULT, sector, size,
134162306a36Sopenharmony_ci			       eq ? ID_IN_SYNC : ID_OUT_OF_SYNC);
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	dec_unacked(device);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	--device->ov_left;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	/* let's advance progress step marks only for every other megabyte */
134862306a36Sopenharmony_ci	if ((device->ov_left & 0x200) == 0x200)
134962306a36Sopenharmony_ci		drbd_advance_rs_marks(peer_device, device->ov_left);
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	stop_sector_reached = verify_can_do_stop_sector(device) &&
135262306a36Sopenharmony_ci		(sector + (size>>9)) >= device->ov_stop_sector;
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	if (device->ov_left == 0 || stop_sector_reached) {
135562306a36Sopenharmony_ci		ov_out_of_sync_print(peer_device);
135662306a36Sopenharmony_ci		drbd_resync_finished(peer_device);
135762306a36Sopenharmony_ci	}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	return err;
136062306a36Sopenharmony_ci}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci/* FIXME
136362306a36Sopenharmony_ci * We need to track the number of pending barrier acks,
136462306a36Sopenharmony_ci * and to be able to wait for them.
136562306a36Sopenharmony_ci * See also comment in drbd_adm_attach before drbd_suspend_io.
136662306a36Sopenharmony_ci */
136762306a36Sopenharmony_cistatic int drbd_send_barrier(struct drbd_connection *connection)
136862306a36Sopenharmony_ci{
136962306a36Sopenharmony_ci	struct p_barrier *p;
137062306a36Sopenharmony_ci	struct drbd_socket *sock;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	sock = &connection->data;
137362306a36Sopenharmony_ci	p = conn_prepare_command(connection, sock);
137462306a36Sopenharmony_ci	if (!p)
137562306a36Sopenharmony_ci		return -EIO;
137662306a36Sopenharmony_ci	p->barrier = connection->send.current_epoch_nr;
137762306a36Sopenharmony_ci	p->pad = 0;
137862306a36Sopenharmony_ci	connection->send.current_epoch_writes = 0;
137962306a36Sopenharmony_ci	connection->send.last_sent_barrier_jif = jiffies;
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	return conn_send_command(connection, sock, P_BARRIER, sizeof(*p), NULL, 0);
138262306a36Sopenharmony_ci}
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_cistatic int pd_send_unplug_remote(struct drbd_peer_device *pd)
138562306a36Sopenharmony_ci{
138662306a36Sopenharmony_ci	struct drbd_socket *sock = &pd->connection->data;
138762306a36Sopenharmony_ci	if (!drbd_prepare_command(pd, sock))
138862306a36Sopenharmony_ci		return -EIO;
138962306a36Sopenharmony_ci	return drbd_send_command(pd, sock, P_UNPLUG_REMOTE, 0, NULL, 0);
139062306a36Sopenharmony_ci}
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ciint w_send_write_hint(struct drbd_work *w, int cancel)
139362306a36Sopenharmony_ci{
139462306a36Sopenharmony_ci	struct drbd_device *device =
139562306a36Sopenharmony_ci		container_of(w, struct drbd_device, unplug_work);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	if (cancel)
139862306a36Sopenharmony_ci		return 0;
139962306a36Sopenharmony_ci	return pd_send_unplug_remote(first_peer_device(device));
140062306a36Sopenharmony_ci}
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_cistatic void re_init_if_first_write(struct drbd_connection *connection, unsigned int epoch)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	if (!connection->send.seen_any_write_yet) {
140562306a36Sopenharmony_ci		connection->send.seen_any_write_yet = true;
140662306a36Sopenharmony_ci		connection->send.current_epoch_nr = epoch;
140762306a36Sopenharmony_ci		connection->send.current_epoch_writes = 0;
140862306a36Sopenharmony_ci		connection->send.last_sent_barrier_jif = jiffies;
140962306a36Sopenharmony_ci	}
141062306a36Sopenharmony_ci}
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_cistatic void maybe_send_barrier(struct drbd_connection *connection, unsigned int epoch)
141362306a36Sopenharmony_ci{
141462306a36Sopenharmony_ci	/* re-init if first write on this connection */
141562306a36Sopenharmony_ci	if (!connection->send.seen_any_write_yet)
141662306a36Sopenharmony_ci		return;
141762306a36Sopenharmony_ci	if (connection->send.current_epoch_nr != epoch) {
141862306a36Sopenharmony_ci		if (connection->send.current_epoch_writes)
141962306a36Sopenharmony_ci			drbd_send_barrier(connection);
142062306a36Sopenharmony_ci		connection->send.current_epoch_nr = epoch;
142162306a36Sopenharmony_ci	}
142262306a36Sopenharmony_ci}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ciint w_send_out_of_sync(struct drbd_work *w, int cancel)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	struct drbd_request *req = container_of(w, struct drbd_request, w);
142762306a36Sopenharmony_ci	struct drbd_device *device = req->device;
142862306a36Sopenharmony_ci	struct drbd_peer_device *const peer_device = first_peer_device(device);
142962306a36Sopenharmony_ci	struct drbd_connection *const connection = peer_device->connection;
143062306a36Sopenharmony_ci	int err;
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	if (unlikely(cancel)) {
143362306a36Sopenharmony_ci		req_mod(req, SEND_CANCELED, peer_device);
143462306a36Sopenharmony_ci		return 0;
143562306a36Sopenharmony_ci	}
143662306a36Sopenharmony_ci	req->pre_send_jif = jiffies;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	/* this time, no connection->send.current_epoch_writes++;
143962306a36Sopenharmony_ci	 * If it was sent, it was the closing barrier for the last
144062306a36Sopenharmony_ci	 * replicated epoch, before we went into AHEAD mode.
144162306a36Sopenharmony_ci	 * No more barriers will be sent, until we leave AHEAD mode again. */
144262306a36Sopenharmony_ci	maybe_send_barrier(connection, req->epoch);
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	err = drbd_send_out_of_sync(peer_device, req);
144562306a36Sopenharmony_ci	req_mod(req, OOS_HANDED_TO_NETWORK, peer_device);
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	return err;
144862306a36Sopenharmony_ci}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci/**
145162306a36Sopenharmony_ci * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request
145262306a36Sopenharmony_ci * @w:		work object.
145362306a36Sopenharmony_ci * @cancel:	The connection will be closed anyways
145462306a36Sopenharmony_ci */
145562306a36Sopenharmony_ciint w_send_dblock(struct drbd_work *w, int cancel)
145662306a36Sopenharmony_ci{
145762306a36Sopenharmony_ci	struct drbd_request *req = container_of(w, struct drbd_request, w);
145862306a36Sopenharmony_ci	struct drbd_device *device = req->device;
145962306a36Sopenharmony_ci	struct drbd_peer_device *const peer_device = first_peer_device(device);
146062306a36Sopenharmony_ci	struct drbd_connection *connection = peer_device->connection;
146162306a36Sopenharmony_ci	bool do_send_unplug = req->rq_state & RQ_UNPLUG;
146262306a36Sopenharmony_ci	int err;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	if (unlikely(cancel)) {
146562306a36Sopenharmony_ci		req_mod(req, SEND_CANCELED, peer_device);
146662306a36Sopenharmony_ci		return 0;
146762306a36Sopenharmony_ci	}
146862306a36Sopenharmony_ci	req->pre_send_jif = jiffies;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	re_init_if_first_write(connection, req->epoch);
147162306a36Sopenharmony_ci	maybe_send_barrier(connection, req->epoch);
147262306a36Sopenharmony_ci	connection->send.current_epoch_writes++;
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	err = drbd_send_dblock(peer_device, req);
147562306a36Sopenharmony_ci	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK, peer_device);
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	if (do_send_unplug && !err)
147862306a36Sopenharmony_ci		pd_send_unplug_remote(peer_device);
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ci	return err;
148162306a36Sopenharmony_ci}
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci/**
148462306a36Sopenharmony_ci * w_send_read_req() - Worker callback to send a read request (P_DATA_REQUEST) packet
148562306a36Sopenharmony_ci * @w:		work object.
148662306a36Sopenharmony_ci * @cancel:	The connection will be closed anyways
148762306a36Sopenharmony_ci */
148862306a36Sopenharmony_ciint w_send_read_req(struct drbd_work *w, int cancel)
148962306a36Sopenharmony_ci{
149062306a36Sopenharmony_ci	struct drbd_request *req = container_of(w, struct drbd_request, w);
149162306a36Sopenharmony_ci	struct drbd_device *device = req->device;
149262306a36Sopenharmony_ci	struct drbd_peer_device *const peer_device = first_peer_device(device);
149362306a36Sopenharmony_ci	struct drbd_connection *connection = peer_device->connection;
149462306a36Sopenharmony_ci	bool do_send_unplug = req->rq_state & RQ_UNPLUG;
149562306a36Sopenharmony_ci	int err;
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	if (unlikely(cancel)) {
149862306a36Sopenharmony_ci		req_mod(req, SEND_CANCELED, peer_device);
149962306a36Sopenharmony_ci		return 0;
150062306a36Sopenharmony_ci	}
150162306a36Sopenharmony_ci	req->pre_send_jif = jiffies;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	/* Even read requests may close a write epoch,
150462306a36Sopenharmony_ci	 * if there was any yet. */
150562306a36Sopenharmony_ci	maybe_send_barrier(connection, req->epoch);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	err = drbd_send_drequest(peer_device, P_DATA_REQUEST, req->i.sector, req->i.size,
150862306a36Sopenharmony_ci				 (unsigned long)req);
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK, peer_device);
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	if (do_send_unplug && !err)
151362306a36Sopenharmony_ci		pd_send_unplug_remote(peer_device);
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	return err;
151662306a36Sopenharmony_ci}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ciint w_restart_disk_io(struct drbd_work *w, int cancel)
151962306a36Sopenharmony_ci{
152062306a36Sopenharmony_ci	struct drbd_request *req = container_of(w, struct drbd_request, w);
152162306a36Sopenharmony_ci	struct drbd_device *device = req->device;
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
152462306a36Sopenharmony_ci		drbd_al_begin_io(device, &req->i);
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	req->private_bio = bio_alloc_clone(device->ldev->backing_bdev,
152762306a36Sopenharmony_ci					   req->master_bio, GFP_NOIO,
152862306a36Sopenharmony_ci					  &drbd_io_bio_set);
152962306a36Sopenharmony_ci	req->private_bio->bi_private = req;
153062306a36Sopenharmony_ci	req->private_bio->bi_end_io = drbd_request_endio;
153162306a36Sopenharmony_ci	submit_bio_noacct(req->private_bio);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	return 0;
153462306a36Sopenharmony_ci}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_cistatic int _drbd_may_sync_now(struct drbd_device *device)
153762306a36Sopenharmony_ci{
153862306a36Sopenharmony_ci	struct drbd_device *odev = device;
153962306a36Sopenharmony_ci	int resync_after;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	while (1) {
154262306a36Sopenharmony_ci		if (!odev->ldev || odev->state.disk == D_DISKLESS)
154362306a36Sopenharmony_ci			return 1;
154462306a36Sopenharmony_ci		rcu_read_lock();
154562306a36Sopenharmony_ci		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
154662306a36Sopenharmony_ci		rcu_read_unlock();
154762306a36Sopenharmony_ci		if (resync_after == -1)
154862306a36Sopenharmony_ci			return 1;
154962306a36Sopenharmony_ci		odev = minor_to_device(resync_after);
155062306a36Sopenharmony_ci		if (!odev)
155162306a36Sopenharmony_ci			return 1;
155262306a36Sopenharmony_ci		if ((odev->state.conn >= C_SYNC_SOURCE &&
155362306a36Sopenharmony_ci		     odev->state.conn <= C_PAUSED_SYNC_T) ||
155462306a36Sopenharmony_ci		    odev->state.aftr_isp || odev->state.peer_isp ||
155562306a36Sopenharmony_ci		    odev->state.user_isp)
155662306a36Sopenharmony_ci			return 0;
155762306a36Sopenharmony_ci	}
155862306a36Sopenharmony_ci}
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci/**
156162306a36Sopenharmony_ci * drbd_pause_after() - Pause resync on all devices that may not resync now
156262306a36Sopenharmony_ci * @device:	DRBD device.
156362306a36Sopenharmony_ci *
156462306a36Sopenharmony_ci * Called from process context only (admin command and after_state_ch).
156562306a36Sopenharmony_ci */
156662306a36Sopenharmony_cistatic bool drbd_pause_after(struct drbd_device *device)
156762306a36Sopenharmony_ci{
156862306a36Sopenharmony_ci	bool changed = false;
156962306a36Sopenharmony_ci	struct drbd_device *odev;
157062306a36Sopenharmony_ci	int i;
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	rcu_read_lock();
157362306a36Sopenharmony_ci	idr_for_each_entry(&drbd_devices, odev, i) {
157462306a36Sopenharmony_ci		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
157562306a36Sopenharmony_ci			continue;
157662306a36Sopenharmony_ci		if (!_drbd_may_sync_now(odev) &&
157762306a36Sopenharmony_ci		    _drbd_set_state(_NS(odev, aftr_isp, 1),
157862306a36Sopenharmony_ci				    CS_HARD, NULL) != SS_NOTHING_TO_DO)
157962306a36Sopenharmony_ci			changed = true;
158062306a36Sopenharmony_ci	}
158162306a36Sopenharmony_ci	rcu_read_unlock();
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci	return changed;
158462306a36Sopenharmony_ci}
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci/**
158762306a36Sopenharmony_ci * drbd_resume_next() - Resume resync on all devices that may resync now
158862306a36Sopenharmony_ci * @device:	DRBD device.
158962306a36Sopenharmony_ci *
159062306a36Sopenharmony_ci * Called from process context only (admin command and worker).
159162306a36Sopenharmony_ci */
159262306a36Sopenharmony_cistatic bool drbd_resume_next(struct drbd_device *device)
159362306a36Sopenharmony_ci{
159462306a36Sopenharmony_ci	bool changed = false;
159562306a36Sopenharmony_ci	struct drbd_device *odev;
159662306a36Sopenharmony_ci	int i;
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	rcu_read_lock();
159962306a36Sopenharmony_ci	idr_for_each_entry(&drbd_devices, odev, i) {
160062306a36Sopenharmony_ci		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
160162306a36Sopenharmony_ci			continue;
160262306a36Sopenharmony_ci		if (odev->state.aftr_isp) {
160362306a36Sopenharmony_ci			if (_drbd_may_sync_now(odev) &&
160462306a36Sopenharmony_ci			    _drbd_set_state(_NS(odev, aftr_isp, 0),
160562306a36Sopenharmony_ci					    CS_HARD, NULL) != SS_NOTHING_TO_DO)
160662306a36Sopenharmony_ci				changed = true;
160762306a36Sopenharmony_ci		}
160862306a36Sopenharmony_ci	}
160962306a36Sopenharmony_ci	rcu_read_unlock();
161062306a36Sopenharmony_ci	return changed;
161162306a36Sopenharmony_ci}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_civoid resume_next_sg(struct drbd_device *device)
161462306a36Sopenharmony_ci{
161562306a36Sopenharmony_ci	lock_all_resources();
161662306a36Sopenharmony_ci	drbd_resume_next(device);
161762306a36Sopenharmony_ci	unlock_all_resources();
161862306a36Sopenharmony_ci}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_civoid suspend_other_sg(struct drbd_device *device)
162162306a36Sopenharmony_ci{
162262306a36Sopenharmony_ci	lock_all_resources();
162362306a36Sopenharmony_ci	drbd_pause_after(device);
162462306a36Sopenharmony_ci	unlock_all_resources();
162562306a36Sopenharmony_ci}
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci/* caller must lock_all_resources() */
162862306a36Sopenharmony_cienum drbd_ret_code drbd_resync_after_valid(struct drbd_device *device, int o_minor)
162962306a36Sopenharmony_ci{
163062306a36Sopenharmony_ci	struct drbd_device *odev;
163162306a36Sopenharmony_ci	int resync_after;
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	if (o_minor == -1)
163462306a36Sopenharmony_ci		return NO_ERROR;
163562306a36Sopenharmony_ci	if (o_minor < -1 || o_minor > MINORMASK)
163662306a36Sopenharmony_ci		return ERR_RESYNC_AFTER;
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	/* check for loops */
163962306a36Sopenharmony_ci	odev = minor_to_device(o_minor);
164062306a36Sopenharmony_ci	while (1) {
164162306a36Sopenharmony_ci		if (odev == device)
164262306a36Sopenharmony_ci			return ERR_RESYNC_AFTER_CYCLE;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci		/* You are free to depend on diskless, non-existing,
164562306a36Sopenharmony_ci		 * or not yet/no longer existing minors.
164662306a36Sopenharmony_ci		 * We only reject dependency loops.
164762306a36Sopenharmony_ci		 * We cannot follow the dependency chain beyond a detached or
164862306a36Sopenharmony_ci		 * missing minor.
164962306a36Sopenharmony_ci		 */
165062306a36Sopenharmony_ci		if (!odev || !odev->ldev || odev->state.disk == D_DISKLESS)
165162306a36Sopenharmony_ci			return NO_ERROR;
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci		rcu_read_lock();
165462306a36Sopenharmony_ci		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
165562306a36Sopenharmony_ci		rcu_read_unlock();
165662306a36Sopenharmony_ci		/* dependency chain ends here, no cycles. */
165762306a36Sopenharmony_ci		if (resync_after == -1)
165862306a36Sopenharmony_ci			return NO_ERROR;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci		/* follow the dependency chain */
166162306a36Sopenharmony_ci		odev = minor_to_device(resync_after);
166262306a36Sopenharmony_ci	}
166362306a36Sopenharmony_ci}
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci/* caller must lock_all_resources() */
166662306a36Sopenharmony_civoid drbd_resync_after_changed(struct drbd_device *device)
166762306a36Sopenharmony_ci{
166862306a36Sopenharmony_ci	int changed;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	do {
167162306a36Sopenharmony_ci		changed  = drbd_pause_after(device);
167262306a36Sopenharmony_ci		changed |= drbd_resume_next(device);
167362306a36Sopenharmony_ci	} while (changed);
167462306a36Sopenharmony_ci}
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_civoid drbd_rs_controller_reset(struct drbd_peer_device *peer_device)
167762306a36Sopenharmony_ci{
167862306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
167962306a36Sopenharmony_ci	struct gendisk *disk = device->ldev->backing_bdev->bd_disk;
168062306a36Sopenharmony_ci	struct fifo_buffer *plan;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	atomic_set(&device->rs_sect_in, 0);
168362306a36Sopenharmony_ci	atomic_set(&device->rs_sect_ev, 0);
168462306a36Sopenharmony_ci	device->rs_in_flight = 0;
168562306a36Sopenharmony_ci	device->rs_last_events =
168662306a36Sopenharmony_ci		(int)part_stat_read_accum(disk->part0, sectors);
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	/* Updating the RCU protected object in place is necessary since
168962306a36Sopenharmony_ci	   this function gets called from atomic context.
169062306a36Sopenharmony_ci	   It is valid since all other updates also lead to an completely
169162306a36Sopenharmony_ci	   empty fifo */
169262306a36Sopenharmony_ci	rcu_read_lock();
169362306a36Sopenharmony_ci	plan = rcu_dereference(device->rs_plan_s);
169462306a36Sopenharmony_ci	plan->total = 0;
169562306a36Sopenharmony_ci	fifo_set(plan, 0);
169662306a36Sopenharmony_ci	rcu_read_unlock();
169762306a36Sopenharmony_ci}
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_civoid start_resync_timer_fn(struct timer_list *t)
170062306a36Sopenharmony_ci{
170162306a36Sopenharmony_ci	struct drbd_device *device = from_timer(device, t, start_resync_timer);
170262306a36Sopenharmony_ci	drbd_device_post_work(device, RS_START);
170362306a36Sopenharmony_ci}
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_cistatic void do_start_resync(struct drbd_device *device)
170662306a36Sopenharmony_ci{
170762306a36Sopenharmony_ci	if (atomic_read(&device->unacked_cnt) || atomic_read(&device->rs_pending_cnt)) {
170862306a36Sopenharmony_ci		drbd_warn(device, "postponing start_resync ...\n");
170962306a36Sopenharmony_ci		device->start_resync_timer.expires = jiffies + HZ/10;
171062306a36Sopenharmony_ci		add_timer(&device->start_resync_timer);
171162306a36Sopenharmony_ci		return;
171262306a36Sopenharmony_ci	}
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	drbd_start_resync(device, C_SYNC_SOURCE);
171562306a36Sopenharmony_ci	clear_bit(AHEAD_TO_SYNC_SOURCE, &device->flags);
171662306a36Sopenharmony_ci}
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_cistatic bool use_checksum_based_resync(struct drbd_connection *connection, struct drbd_device *device)
171962306a36Sopenharmony_ci{
172062306a36Sopenharmony_ci	bool csums_after_crash_only;
172162306a36Sopenharmony_ci	rcu_read_lock();
172262306a36Sopenharmony_ci	csums_after_crash_only = rcu_dereference(connection->net_conf)->csums_after_crash_only;
172362306a36Sopenharmony_ci	rcu_read_unlock();
172462306a36Sopenharmony_ci	return connection->agreed_pro_version >= 89 &&		/* supported? */
172562306a36Sopenharmony_ci		connection->csums_tfm &&			/* configured? */
172662306a36Sopenharmony_ci		(csums_after_crash_only == false		/* use for each resync? */
172762306a36Sopenharmony_ci		 || test_bit(CRASHED_PRIMARY, &device->flags));	/* or only after Primary crash? */
172862306a36Sopenharmony_ci}
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci/**
173162306a36Sopenharmony_ci * drbd_start_resync() - Start the resync process
173262306a36Sopenharmony_ci * @device:	DRBD device.
173362306a36Sopenharmony_ci * @side:	Either C_SYNC_SOURCE or C_SYNC_TARGET
173462306a36Sopenharmony_ci *
173562306a36Sopenharmony_ci * This function might bring you directly into one of the
173662306a36Sopenharmony_ci * C_PAUSED_SYNC_* states.
173762306a36Sopenharmony_ci */
173862306a36Sopenharmony_civoid drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
173962306a36Sopenharmony_ci{
174062306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = first_peer_device(device);
174162306a36Sopenharmony_ci	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
174262306a36Sopenharmony_ci	union drbd_state ns;
174362306a36Sopenharmony_ci	int r;
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	if (device->state.conn >= C_SYNC_SOURCE && device->state.conn < C_AHEAD) {
174662306a36Sopenharmony_ci		drbd_err(device, "Resync already running!\n");
174762306a36Sopenharmony_ci		return;
174862306a36Sopenharmony_ci	}
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	if (!connection) {
175162306a36Sopenharmony_ci		drbd_err(device, "No connection to peer, aborting!\n");
175262306a36Sopenharmony_ci		return;
175362306a36Sopenharmony_ci	}
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	if (!test_bit(B_RS_H_DONE, &device->flags)) {
175662306a36Sopenharmony_ci		if (side == C_SYNC_TARGET) {
175762306a36Sopenharmony_ci			/* Since application IO was locked out during C_WF_BITMAP_T and
175862306a36Sopenharmony_ci			   C_WF_SYNC_UUID we are still unmodified. Before going to C_SYNC_TARGET
175962306a36Sopenharmony_ci			   we check that we might make the data inconsistent. */
176062306a36Sopenharmony_ci			r = drbd_khelper(device, "before-resync-target");
176162306a36Sopenharmony_ci			r = (r >> 8) & 0xff;
176262306a36Sopenharmony_ci			if (r > 0) {
176362306a36Sopenharmony_ci				drbd_info(device, "before-resync-target handler returned %d, "
176462306a36Sopenharmony_ci					 "dropping connection.\n", r);
176562306a36Sopenharmony_ci				conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
176662306a36Sopenharmony_ci				return;
176762306a36Sopenharmony_ci			}
176862306a36Sopenharmony_ci		} else /* C_SYNC_SOURCE */ {
176962306a36Sopenharmony_ci			r = drbd_khelper(device, "before-resync-source");
177062306a36Sopenharmony_ci			r = (r >> 8) & 0xff;
177162306a36Sopenharmony_ci			if (r > 0) {
177262306a36Sopenharmony_ci				if (r == 3) {
177362306a36Sopenharmony_ci					drbd_info(device, "before-resync-source handler returned %d, "
177462306a36Sopenharmony_ci						 "ignoring. Old userland tools?", r);
177562306a36Sopenharmony_ci				} else {
177662306a36Sopenharmony_ci					drbd_info(device, "before-resync-source handler returned %d, "
177762306a36Sopenharmony_ci						 "dropping connection.\n", r);
177862306a36Sopenharmony_ci					conn_request_state(connection,
177962306a36Sopenharmony_ci							   NS(conn, C_DISCONNECTING), CS_HARD);
178062306a36Sopenharmony_ci					return;
178162306a36Sopenharmony_ci				}
178262306a36Sopenharmony_ci			}
178362306a36Sopenharmony_ci		}
178462306a36Sopenharmony_ci	}
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci	if (current == connection->worker.task) {
178762306a36Sopenharmony_ci		/* The worker should not sleep waiting for state_mutex,
178862306a36Sopenharmony_ci		   that can take long */
178962306a36Sopenharmony_ci		if (!mutex_trylock(device->state_mutex)) {
179062306a36Sopenharmony_ci			set_bit(B_RS_H_DONE, &device->flags);
179162306a36Sopenharmony_ci			device->start_resync_timer.expires = jiffies + HZ/5;
179262306a36Sopenharmony_ci			add_timer(&device->start_resync_timer);
179362306a36Sopenharmony_ci			return;
179462306a36Sopenharmony_ci		}
179562306a36Sopenharmony_ci	} else {
179662306a36Sopenharmony_ci		mutex_lock(device->state_mutex);
179762306a36Sopenharmony_ci	}
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	lock_all_resources();
180062306a36Sopenharmony_ci	clear_bit(B_RS_H_DONE, &device->flags);
180162306a36Sopenharmony_ci	/* Did some connection breakage or IO error race with us? */
180262306a36Sopenharmony_ci	if (device->state.conn < C_CONNECTED
180362306a36Sopenharmony_ci	|| !get_ldev_if_state(device, D_NEGOTIATING)) {
180462306a36Sopenharmony_ci		unlock_all_resources();
180562306a36Sopenharmony_ci		goto out;
180662306a36Sopenharmony_ci	}
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	ns = drbd_read_state(device);
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	ns.aftr_isp = !_drbd_may_sync_now(device);
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	ns.conn = side;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	if (side == C_SYNC_TARGET)
181562306a36Sopenharmony_ci		ns.disk = D_INCONSISTENT;
181662306a36Sopenharmony_ci	else /* side == C_SYNC_SOURCE */
181762306a36Sopenharmony_ci		ns.pdsk = D_INCONSISTENT;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	r = _drbd_set_state(device, ns, CS_VERBOSE, NULL);
182062306a36Sopenharmony_ci	ns = drbd_read_state(device);
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	if (ns.conn < C_CONNECTED)
182362306a36Sopenharmony_ci		r = SS_UNKNOWN_ERROR;
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ci	if (r == SS_SUCCESS) {
182662306a36Sopenharmony_ci		unsigned long tw = drbd_bm_total_weight(device);
182762306a36Sopenharmony_ci		unsigned long now = jiffies;
182862306a36Sopenharmony_ci		int i;
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci		device->rs_failed    = 0;
183162306a36Sopenharmony_ci		device->rs_paused    = 0;
183262306a36Sopenharmony_ci		device->rs_same_csum = 0;
183362306a36Sopenharmony_ci		device->rs_last_sect_ev = 0;
183462306a36Sopenharmony_ci		device->rs_total     = tw;
183562306a36Sopenharmony_ci		device->rs_start     = now;
183662306a36Sopenharmony_ci		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
183762306a36Sopenharmony_ci			device->rs_mark_left[i] = tw;
183862306a36Sopenharmony_ci			device->rs_mark_time[i] = now;
183962306a36Sopenharmony_ci		}
184062306a36Sopenharmony_ci		drbd_pause_after(device);
184162306a36Sopenharmony_ci		/* Forget potentially stale cached per resync extent bit-counts.
184262306a36Sopenharmony_ci		 * Open coded drbd_rs_cancel_all(device), we already have IRQs
184362306a36Sopenharmony_ci		 * disabled, and know the disk state is ok. */
184462306a36Sopenharmony_ci		spin_lock(&device->al_lock);
184562306a36Sopenharmony_ci		lc_reset(device->resync);
184662306a36Sopenharmony_ci		device->resync_locked = 0;
184762306a36Sopenharmony_ci		device->resync_wenr = LC_FREE;
184862306a36Sopenharmony_ci		spin_unlock(&device->al_lock);
184962306a36Sopenharmony_ci	}
185062306a36Sopenharmony_ci	unlock_all_resources();
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	if (r == SS_SUCCESS) {
185362306a36Sopenharmony_ci		wake_up(&device->al_wait); /* for lc_reset() above */
185462306a36Sopenharmony_ci		/* reset rs_last_bcast when a resync or verify is started,
185562306a36Sopenharmony_ci		 * to deal with potential jiffies wrap. */
185662306a36Sopenharmony_ci		device->rs_last_bcast = jiffies - HZ;
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci		drbd_info(device, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
185962306a36Sopenharmony_ci		     drbd_conn_str(ns.conn),
186062306a36Sopenharmony_ci		     (unsigned long) device->rs_total << (BM_BLOCK_SHIFT-10),
186162306a36Sopenharmony_ci		     (unsigned long) device->rs_total);
186262306a36Sopenharmony_ci		if (side == C_SYNC_TARGET) {
186362306a36Sopenharmony_ci			device->bm_resync_fo = 0;
186462306a36Sopenharmony_ci			device->use_csums = use_checksum_based_resync(connection, device);
186562306a36Sopenharmony_ci		} else {
186662306a36Sopenharmony_ci			device->use_csums = false;
186762306a36Sopenharmony_ci		}
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_ci		/* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
187062306a36Sopenharmony_ci		 * with w_send_oos, or the sync target will get confused as to
187162306a36Sopenharmony_ci		 * how much bits to resync.  We cannot do that always, because for an
187262306a36Sopenharmony_ci		 * empty resync and protocol < 95, we need to do it here, as we call
187362306a36Sopenharmony_ci		 * drbd_resync_finished from here in that case.
187462306a36Sopenharmony_ci		 * We drbd_gen_and_send_sync_uuid here for protocol < 96,
187562306a36Sopenharmony_ci		 * and from after_state_ch otherwise. */
187662306a36Sopenharmony_ci		if (side == C_SYNC_SOURCE && connection->agreed_pro_version < 96)
187762306a36Sopenharmony_ci			drbd_gen_and_send_sync_uuid(peer_device);
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci		if (connection->agreed_pro_version < 95 && device->rs_total == 0) {
188062306a36Sopenharmony_ci			/* This still has a race (about when exactly the peers
188162306a36Sopenharmony_ci			 * detect connection loss) that can lead to a full sync
188262306a36Sopenharmony_ci			 * on next handshake. In 8.3.9 we fixed this with explicit
188362306a36Sopenharmony_ci			 * resync-finished notifications, but the fix
188462306a36Sopenharmony_ci			 * introduces a protocol change.  Sleeping for some
188562306a36Sopenharmony_ci			 * time longer than the ping interval + timeout on the
188662306a36Sopenharmony_ci			 * SyncSource, to give the SyncTarget the chance to
188762306a36Sopenharmony_ci			 * detect connection loss, then waiting for a ping
188862306a36Sopenharmony_ci			 * response (implicit in drbd_resync_finished) reduces
188962306a36Sopenharmony_ci			 * the race considerably, but does not solve it. */
189062306a36Sopenharmony_ci			if (side == C_SYNC_SOURCE) {
189162306a36Sopenharmony_ci				struct net_conf *nc;
189262306a36Sopenharmony_ci				int timeo;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci				rcu_read_lock();
189562306a36Sopenharmony_ci				nc = rcu_dereference(connection->net_conf);
189662306a36Sopenharmony_ci				timeo = nc->ping_int * HZ + nc->ping_timeo * HZ / 9;
189762306a36Sopenharmony_ci				rcu_read_unlock();
189862306a36Sopenharmony_ci				schedule_timeout_interruptible(timeo);
189962306a36Sopenharmony_ci			}
190062306a36Sopenharmony_ci			drbd_resync_finished(peer_device);
190162306a36Sopenharmony_ci		}
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci		drbd_rs_controller_reset(peer_device);
190462306a36Sopenharmony_ci		/* ns.conn may already be != device->state.conn,
190562306a36Sopenharmony_ci		 * we may have been paused in between, or become paused until
190662306a36Sopenharmony_ci		 * the timer triggers.
190762306a36Sopenharmony_ci		 * No matter, that is handled in resync_timer_fn() */
190862306a36Sopenharmony_ci		if (ns.conn == C_SYNC_TARGET)
190962306a36Sopenharmony_ci			mod_timer(&device->resync_timer, jiffies);
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci		drbd_md_sync(device);
191262306a36Sopenharmony_ci	}
191362306a36Sopenharmony_ci	put_ldev(device);
191462306a36Sopenharmony_ciout:
191562306a36Sopenharmony_ci	mutex_unlock(device->state_mutex);
191662306a36Sopenharmony_ci}
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_cistatic void update_on_disk_bitmap(struct drbd_peer_device *peer_device, bool resync_done)
191962306a36Sopenharmony_ci{
192062306a36Sopenharmony_ci	struct drbd_device *device = peer_device->device;
192162306a36Sopenharmony_ci	struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
192262306a36Sopenharmony_ci	device->rs_last_bcast = jiffies;
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	if (!get_ldev(device))
192562306a36Sopenharmony_ci		return;
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci	drbd_bm_write_lazy(device, 0);
192862306a36Sopenharmony_ci	if (resync_done && is_sync_state(device->state.conn))
192962306a36Sopenharmony_ci		drbd_resync_finished(peer_device);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	drbd_bcast_event(device, &sib);
193262306a36Sopenharmony_ci	/* update timestamp, in case it took a while to write out stuff */
193362306a36Sopenharmony_ci	device->rs_last_bcast = jiffies;
193462306a36Sopenharmony_ci	put_ldev(device);
193562306a36Sopenharmony_ci}
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_cistatic void drbd_ldev_destroy(struct drbd_device *device)
193862306a36Sopenharmony_ci{
193962306a36Sopenharmony_ci	lc_destroy(device->resync);
194062306a36Sopenharmony_ci	device->resync = NULL;
194162306a36Sopenharmony_ci	lc_destroy(device->act_log);
194262306a36Sopenharmony_ci	device->act_log = NULL;
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci	__acquire(local);
194562306a36Sopenharmony_ci	drbd_backing_dev_free(device, device->ldev);
194662306a36Sopenharmony_ci	device->ldev = NULL;
194762306a36Sopenharmony_ci	__release(local);
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci	clear_bit(GOING_DISKLESS, &device->flags);
195062306a36Sopenharmony_ci	wake_up(&device->misc_wait);
195162306a36Sopenharmony_ci}
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_cistatic void go_diskless(struct drbd_device *device)
195462306a36Sopenharmony_ci{
195562306a36Sopenharmony_ci	struct drbd_peer_device *peer_device = first_peer_device(device);
195662306a36Sopenharmony_ci	D_ASSERT(device, device->state.disk == D_FAILED);
195762306a36Sopenharmony_ci	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
195862306a36Sopenharmony_ci	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
195962306a36Sopenharmony_ci	 * the protected members anymore, though, so once put_ldev reaches zero
196062306a36Sopenharmony_ci	 * again, it will be safe to free them. */
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	/* Try to write changed bitmap pages, read errors may have just
196362306a36Sopenharmony_ci	 * set some bits outside the area covered by the activity log.
196462306a36Sopenharmony_ci	 *
196562306a36Sopenharmony_ci	 * If we have an IO error during the bitmap writeout,
196662306a36Sopenharmony_ci	 * we will want a full sync next time, just in case.
196762306a36Sopenharmony_ci	 * (Do we want a specific meta data flag for this?)
196862306a36Sopenharmony_ci	 *
196962306a36Sopenharmony_ci	 * If that does not make it to stable storage either,
197062306a36Sopenharmony_ci	 * we cannot do anything about that anymore.
197162306a36Sopenharmony_ci	 *
197262306a36Sopenharmony_ci	 * We still need to check if both bitmap and ldev are present, we may
197362306a36Sopenharmony_ci	 * end up here after a failed attach, before ldev was even assigned.
197462306a36Sopenharmony_ci	 */
197562306a36Sopenharmony_ci	if (device->bitmap && device->ldev) {
197662306a36Sopenharmony_ci		/* An interrupted resync or similar is allowed to recounts bits
197762306a36Sopenharmony_ci		 * while we detach.
197862306a36Sopenharmony_ci		 * Any modifications would not be expected anymore, though.
197962306a36Sopenharmony_ci		 */
198062306a36Sopenharmony_ci		if (drbd_bitmap_io_from_worker(device, drbd_bm_write,
198162306a36Sopenharmony_ci					"detach", BM_LOCKED_TEST_ALLOWED, peer_device)) {
198262306a36Sopenharmony_ci			if (test_bit(WAS_READ_ERROR, &device->flags)) {
198362306a36Sopenharmony_ci				drbd_md_set_flag(device, MDF_FULL_SYNC);
198462306a36Sopenharmony_ci				drbd_md_sync(device);
198562306a36Sopenharmony_ci			}
198662306a36Sopenharmony_ci		}
198762306a36Sopenharmony_ci	}
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	drbd_force_state(device, NS(disk, D_DISKLESS));
199062306a36Sopenharmony_ci}
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_cistatic int do_md_sync(struct drbd_device *device)
199362306a36Sopenharmony_ci{
199462306a36Sopenharmony_ci	drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
199562306a36Sopenharmony_ci	drbd_md_sync(device);
199662306a36Sopenharmony_ci	return 0;
199762306a36Sopenharmony_ci}
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci/* only called from drbd_worker thread, no locking */
200062306a36Sopenharmony_civoid __update_timing_details(
200162306a36Sopenharmony_ci		struct drbd_thread_timing_details *tdp,
200262306a36Sopenharmony_ci		unsigned int *cb_nr,
200362306a36Sopenharmony_ci		void *cb,
200462306a36Sopenharmony_ci		const char *fn, const unsigned int line)
200562306a36Sopenharmony_ci{
200662306a36Sopenharmony_ci	unsigned int i = *cb_nr % DRBD_THREAD_DETAILS_HIST;
200762306a36Sopenharmony_ci	struct drbd_thread_timing_details *td = tdp + i;
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	td->start_jif = jiffies;
201062306a36Sopenharmony_ci	td->cb_addr = cb;
201162306a36Sopenharmony_ci	td->caller_fn = fn;
201262306a36Sopenharmony_ci	td->line = line;
201362306a36Sopenharmony_ci	td->cb_nr = *cb_nr;
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	i = (i+1) % DRBD_THREAD_DETAILS_HIST;
201662306a36Sopenharmony_ci	td = tdp + i;
201762306a36Sopenharmony_ci	memset(td, 0, sizeof(*td));
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci	++(*cb_nr);
202062306a36Sopenharmony_ci}
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_cistatic void do_device_work(struct drbd_device *device, const unsigned long todo)
202362306a36Sopenharmony_ci{
202462306a36Sopenharmony_ci	if (test_bit(MD_SYNC, &todo))
202562306a36Sopenharmony_ci		do_md_sync(device);
202662306a36Sopenharmony_ci	if (test_bit(RS_DONE, &todo) ||
202762306a36Sopenharmony_ci	    test_bit(RS_PROGRESS, &todo))
202862306a36Sopenharmony_ci		update_on_disk_bitmap(first_peer_device(device), test_bit(RS_DONE, &todo));
202962306a36Sopenharmony_ci	if (test_bit(GO_DISKLESS, &todo))
203062306a36Sopenharmony_ci		go_diskless(device);
203162306a36Sopenharmony_ci	if (test_bit(DESTROY_DISK, &todo))
203262306a36Sopenharmony_ci		drbd_ldev_destroy(device);
203362306a36Sopenharmony_ci	if (test_bit(RS_START, &todo))
203462306a36Sopenharmony_ci		do_start_resync(device);
203562306a36Sopenharmony_ci}
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci#define DRBD_DEVICE_WORK_MASK	\
203862306a36Sopenharmony_ci	((1UL << GO_DISKLESS)	\
203962306a36Sopenharmony_ci	|(1UL << DESTROY_DISK)	\
204062306a36Sopenharmony_ci	|(1UL << MD_SYNC)	\
204162306a36Sopenharmony_ci	|(1UL << RS_START)	\
204262306a36Sopenharmony_ci	|(1UL << RS_PROGRESS)	\
204362306a36Sopenharmony_ci	|(1UL << RS_DONE)	\
204462306a36Sopenharmony_ci	)
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_cistatic unsigned long get_work_bits(unsigned long *flags)
204762306a36Sopenharmony_ci{
204862306a36Sopenharmony_ci	unsigned long old, new;
204962306a36Sopenharmony_ci	do {
205062306a36Sopenharmony_ci		old = *flags;
205162306a36Sopenharmony_ci		new = old & ~DRBD_DEVICE_WORK_MASK;
205262306a36Sopenharmony_ci	} while (cmpxchg(flags, old, new) != old);
205362306a36Sopenharmony_ci	return old & DRBD_DEVICE_WORK_MASK;
205462306a36Sopenharmony_ci}
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_cistatic void do_unqueued_work(struct drbd_connection *connection)
205762306a36Sopenharmony_ci{
205862306a36Sopenharmony_ci	struct drbd_peer_device *peer_device;
205962306a36Sopenharmony_ci	int vnr;
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci	rcu_read_lock();
206262306a36Sopenharmony_ci	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
206362306a36Sopenharmony_ci		struct drbd_device *device = peer_device->device;
206462306a36Sopenharmony_ci		unsigned long todo = get_work_bits(&device->flags);
206562306a36Sopenharmony_ci		if (!todo)
206662306a36Sopenharmony_ci			continue;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci		kref_get(&device->kref);
206962306a36Sopenharmony_ci		rcu_read_unlock();
207062306a36Sopenharmony_ci		do_device_work(device, todo);
207162306a36Sopenharmony_ci		kref_put(&device->kref, drbd_destroy_device);
207262306a36Sopenharmony_ci		rcu_read_lock();
207362306a36Sopenharmony_ci	}
207462306a36Sopenharmony_ci	rcu_read_unlock();
207562306a36Sopenharmony_ci}
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_cistatic bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
207862306a36Sopenharmony_ci{
207962306a36Sopenharmony_ci	spin_lock_irq(&queue->q_lock);
208062306a36Sopenharmony_ci	list_splice_tail_init(&queue->q, work_list);
208162306a36Sopenharmony_ci	spin_unlock_irq(&queue->q_lock);
208262306a36Sopenharmony_ci	return !list_empty(work_list);
208362306a36Sopenharmony_ci}
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_cistatic void wait_for_work(struct drbd_connection *connection, struct list_head *work_list)
208662306a36Sopenharmony_ci{
208762306a36Sopenharmony_ci	DEFINE_WAIT(wait);
208862306a36Sopenharmony_ci	struct net_conf *nc;
208962306a36Sopenharmony_ci	int uncork, cork;
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	dequeue_work_batch(&connection->sender_work, work_list);
209262306a36Sopenharmony_ci	if (!list_empty(work_list))
209362306a36Sopenharmony_ci		return;
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci	/* Still nothing to do?
209662306a36Sopenharmony_ci	 * Maybe we still need to close the current epoch,
209762306a36Sopenharmony_ci	 * even if no new requests are queued yet.
209862306a36Sopenharmony_ci	 *
209962306a36Sopenharmony_ci	 * Also, poke TCP, just in case.
210062306a36Sopenharmony_ci	 * Then wait for new work (or signal). */
210162306a36Sopenharmony_ci	rcu_read_lock();
210262306a36Sopenharmony_ci	nc = rcu_dereference(connection->net_conf);
210362306a36Sopenharmony_ci	uncork = nc ? nc->tcp_cork : 0;
210462306a36Sopenharmony_ci	rcu_read_unlock();
210562306a36Sopenharmony_ci	if (uncork) {
210662306a36Sopenharmony_ci		mutex_lock(&connection->data.mutex);
210762306a36Sopenharmony_ci		if (connection->data.socket)
210862306a36Sopenharmony_ci			tcp_sock_set_cork(connection->data.socket->sk, false);
210962306a36Sopenharmony_ci		mutex_unlock(&connection->data.mutex);
211062306a36Sopenharmony_ci	}
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci	for (;;) {
211362306a36Sopenharmony_ci		int send_barrier;
211462306a36Sopenharmony_ci		prepare_to_wait(&connection->sender_work.q_wait, &wait, TASK_INTERRUPTIBLE);
211562306a36Sopenharmony_ci		spin_lock_irq(&connection->resource->req_lock);
211662306a36Sopenharmony_ci		spin_lock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
211762306a36Sopenharmony_ci		if (!list_empty(&connection->sender_work.q))
211862306a36Sopenharmony_ci			list_splice_tail_init(&connection->sender_work.q, work_list);
211962306a36Sopenharmony_ci		spin_unlock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
212062306a36Sopenharmony_ci		if (!list_empty(work_list) || signal_pending(current)) {
212162306a36Sopenharmony_ci			spin_unlock_irq(&connection->resource->req_lock);
212262306a36Sopenharmony_ci			break;
212362306a36Sopenharmony_ci		}
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci		/* We found nothing new to do, no to-be-communicated request,
212662306a36Sopenharmony_ci		 * no other work item.  We may still need to close the last
212762306a36Sopenharmony_ci		 * epoch.  Next incoming request epoch will be connection ->
212862306a36Sopenharmony_ci		 * current transfer log epoch number.  If that is different
212962306a36Sopenharmony_ci		 * from the epoch of the last request we communicated, it is
213062306a36Sopenharmony_ci		 * safe to send the epoch separating barrier now.
213162306a36Sopenharmony_ci		 */
213262306a36Sopenharmony_ci		send_barrier =
213362306a36Sopenharmony_ci			atomic_read(&connection->current_tle_nr) !=
213462306a36Sopenharmony_ci			connection->send.current_epoch_nr;
213562306a36Sopenharmony_ci		spin_unlock_irq(&connection->resource->req_lock);
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci		if (send_barrier)
213862306a36Sopenharmony_ci			maybe_send_barrier(connection,
213962306a36Sopenharmony_ci					connection->send.current_epoch_nr + 1);
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci		if (test_bit(DEVICE_WORK_PENDING, &connection->flags))
214262306a36Sopenharmony_ci			break;
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci		/* drbd_send() may have called flush_signals() */
214562306a36Sopenharmony_ci		if (get_t_state(&connection->worker) != RUNNING)
214662306a36Sopenharmony_ci			break;
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci		schedule();
214962306a36Sopenharmony_ci		/* may be woken up for other things but new work, too,
215062306a36Sopenharmony_ci		 * e.g. if the current epoch got closed.
215162306a36Sopenharmony_ci		 * In which case we send the barrier above. */
215262306a36Sopenharmony_ci	}
215362306a36Sopenharmony_ci	finish_wait(&connection->sender_work.q_wait, &wait);
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	/* someone may have changed the config while we have been waiting above. */
215662306a36Sopenharmony_ci	rcu_read_lock();
215762306a36Sopenharmony_ci	nc = rcu_dereference(connection->net_conf);
215862306a36Sopenharmony_ci	cork = nc ? nc->tcp_cork : 0;
215962306a36Sopenharmony_ci	rcu_read_unlock();
216062306a36Sopenharmony_ci	mutex_lock(&connection->data.mutex);
216162306a36Sopenharmony_ci	if (connection->data.socket) {
216262306a36Sopenharmony_ci		if (cork)
216362306a36Sopenharmony_ci			tcp_sock_set_cork(connection->data.socket->sk, true);
216462306a36Sopenharmony_ci		else if (!uncork)
216562306a36Sopenharmony_ci			tcp_sock_set_cork(connection->data.socket->sk, false);
216662306a36Sopenharmony_ci	}
216762306a36Sopenharmony_ci	mutex_unlock(&connection->data.mutex);
216862306a36Sopenharmony_ci}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ciint drbd_worker(struct drbd_thread *thi)
217162306a36Sopenharmony_ci{
217262306a36Sopenharmony_ci	struct drbd_connection *connection = thi->connection;
217362306a36Sopenharmony_ci	struct drbd_work *w = NULL;
217462306a36Sopenharmony_ci	struct drbd_peer_device *peer_device;
217562306a36Sopenharmony_ci	LIST_HEAD(work_list);
217662306a36Sopenharmony_ci	int vnr;
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	while (get_t_state(thi) == RUNNING) {
217962306a36Sopenharmony_ci		drbd_thread_current_set_cpu(thi);
218062306a36Sopenharmony_ci
218162306a36Sopenharmony_ci		if (list_empty(&work_list)) {
218262306a36Sopenharmony_ci			update_worker_timing_details(connection, wait_for_work);
218362306a36Sopenharmony_ci			wait_for_work(connection, &work_list);
218462306a36Sopenharmony_ci		}
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci		if (test_and_clear_bit(DEVICE_WORK_PENDING, &connection->flags)) {
218762306a36Sopenharmony_ci			update_worker_timing_details(connection, do_unqueued_work);
218862306a36Sopenharmony_ci			do_unqueued_work(connection);
218962306a36Sopenharmony_ci		}
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci		if (signal_pending(current)) {
219262306a36Sopenharmony_ci			flush_signals(current);
219362306a36Sopenharmony_ci			if (get_t_state(thi) == RUNNING) {
219462306a36Sopenharmony_ci				drbd_warn(connection, "Worker got an unexpected signal\n");
219562306a36Sopenharmony_ci				continue;
219662306a36Sopenharmony_ci			}
219762306a36Sopenharmony_ci			break;
219862306a36Sopenharmony_ci		}
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci		if (get_t_state(thi) != RUNNING)
220162306a36Sopenharmony_ci			break;
220262306a36Sopenharmony_ci
220362306a36Sopenharmony_ci		if (!list_empty(&work_list)) {
220462306a36Sopenharmony_ci			w = list_first_entry(&work_list, struct drbd_work, list);
220562306a36Sopenharmony_ci			list_del_init(&w->list);
220662306a36Sopenharmony_ci			update_worker_timing_details(connection, w->cb);
220762306a36Sopenharmony_ci			if (w->cb(w, connection->cstate < C_WF_REPORT_PARAMS) == 0)
220862306a36Sopenharmony_ci				continue;
220962306a36Sopenharmony_ci			if (connection->cstate >= C_WF_REPORT_PARAMS)
221062306a36Sopenharmony_ci				conn_request_state(connection, NS(conn, C_NETWORK_FAILURE), CS_HARD);
221162306a36Sopenharmony_ci		}
221262306a36Sopenharmony_ci	}
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	do {
221562306a36Sopenharmony_ci		if (test_and_clear_bit(DEVICE_WORK_PENDING, &connection->flags)) {
221662306a36Sopenharmony_ci			update_worker_timing_details(connection, do_unqueued_work);
221762306a36Sopenharmony_ci			do_unqueued_work(connection);
221862306a36Sopenharmony_ci		}
221962306a36Sopenharmony_ci		if (!list_empty(&work_list)) {
222062306a36Sopenharmony_ci			w = list_first_entry(&work_list, struct drbd_work, list);
222162306a36Sopenharmony_ci			list_del_init(&w->list);
222262306a36Sopenharmony_ci			update_worker_timing_details(connection, w->cb);
222362306a36Sopenharmony_ci			w->cb(w, 1);
222462306a36Sopenharmony_ci		} else
222562306a36Sopenharmony_ci			dequeue_work_batch(&connection->sender_work, &work_list);
222662306a36Sopenharmony_ci	} while (!list_empty(&work_list) || test_bit(DEVICE_WORK_PENDING, &connection->flags));
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	rcu_read_lock();
222962306a36Sopenharmony_ci	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
223062306a36Sopenharmony_ci		struct drbd_device *device = peer_device->device;
223162306a36Sopenharmony_ci		D_ASSERT(device, device->state.disk == D_DISKLESS && device->state.conn == C_STANDALONE);
223262306a36Sopenharmony_ci		kref_get(&device->kref);
223362306a36Sopenharmony_ci		rcu_read_unlock();
223462306a36Sopenharmony_ci		drbd_device_cleanup(device);
223562306a36Sopenharmony_ci		kref_put(&device->kref, drbd_destroy_device);
223662306a36Sopenharmony_ci		rcu_read_lock();
223762306a36Sopenharmony_ci	}
223862306a36Sopenharmony_ci	rcu_read_unlock();
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci	return 0;
224162306a36Sopenharmony_ci}
2242