xref: /openbmc/linux/drivers/block/drbd/drbd_worker.c (revision 6db7e50a)
1b411b363SPhilipp Reisner /*
2b411b363SPhilipp Reisner    drbd_worker.c
3b411b363SPhilipp Reisner 
4b411b363SPhilipp Reisner    This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
5b411b363SPhilipp Reisner 
6b411b363SPhilipp Reisner    Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
7b411b363SPhilipp Reisner    Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
8b411b363SPhilipp Reisner    Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
9b411b363SPhilipp Reisner 
10b411b363SPhilipp Reisner    drbd is free software; you can redistribute it and/or modify
11b411b363SPhilipp Reisner    it under the terms of the GNU General Public License as published by
12b411b363SPhilipp Reisner    the Free Software Foundation; either version 2, or (at your option)
13b411b363SPhilipp Reisner    any later version.
14b411b363SPhilipp Reisner 
15b411b363SPhilipp Reisner    drbd is distributed in the hope that it will be useful,
16b411b363SPhilipp Reisner    but WITHOUT ANY WARRANTY; without even the implied warranty of
17b411b363SPhilipp Reisner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18b411b363SPhilipp Reisner    GNU General Public License for more details.
19b411b363SPhilipp Reisner 
20b411b363SPhilipp Reisner    You should have received a copy of the GNU General Public License
21b411b363SPhilipp Reisner    along with drbd; see the file COPYING.  If not, write to
22b411b363SPhilipp Reisner    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23b411b363SPhilipp Reisner 
24b411b363SPhilipp Reisner */
25b411b363SPhilipp Reisner 
26b411b363SPhilipp Reisner #include <linux/module.h>
27b411b363SPhilipp Reisner #include <linux/drbd.h>
28b411b363SPhilipp Reisner #include <linux/sched.h>
29b411b363SPhilipp Reisner #include <linux/wait.h>
30b411b363SPhilipp Reisner #include <linux/mm.h>
31b411b363SPhilipp Reisner #include <linux/memcontrol.h>
32b411b363SPhilipp Reisner #include <linux/mm_inline.h>
33b411b363SPhilipp Reisner #include <linux/slab.h>
34b411b363SPhilipp Reisner #include <linux/random.h>
35b411b363SPhilipp Reisner #include <linux/string.h>
36b411b363SPhilipp Reisner #include <linux/scatterlist.h>
37b411b363SPhilipp Reisner 
38b411b363SPhilipp Reisner #include "drbd_int.h"
39a3603a6eSAndreas Gruenbacher #include "drbd_protocol.h"
40b411b363SPhilipp Reisner #include "drbd_req.h"
41b411b363SPhilipp Reisner 
42d448a2e1SAndreas Gruenbacher static int make_ov_request(struct drbd_device *, int);
43d448a2e1SAndreas Gruenbacher static int make_resync_request(struct drbd_device *, int);
44b411b363SPhilipp Reisner 
45c5a91619SAndreas Gruenbacher /* endio handlers:
46c5a91619SAndreas Gruenbacher  *   drbd_md_io_complete (defined here)
47fcefa62eSAndreas Gruenbacher  *   drbd_request_endio (defined here)
48fcefa62eSAndreas Gruenbacher  *   drbd_peer_request_endio (defined here)
49c5a91619SAndreas Gruenbacher  *   bm_async_io_complete (defined in drbd_bitmap.c)
50c5a91619SAndreas Gruenbacher  *
51b411b363SPhilipp Reisner  * For all these callbacks, note the following:
52b411b363SPhilipp Reisner  * The callbacks will be called in irq context by the IDE drivers,
53b411b363SPhilipp Reisner  * and in Softirqs/Tasklets/BH context by the SCSI drivers.
54b411b363SPhilipp Reisner  * Try to get the locking right :)
55b411b363SPhilipp Reisner  *
56b411b363SPhilipp Reisner  */
57b411b363SPhilipp Reisner 
58b411b363SPhilipp Reisner 
59b411b363SPhilipp Reisner /* About the global_state_lock
60b411b363SPhilipp Reisner    Each state transition on an device holds a read lock. In case we have
6195f8efd0SAndreas Gruenbacher    to evaluate the resync after dependencies, we grab a write lock, because
62b411b363SPhilipp Reisner    we need stable states on all devices for that.  */
63b411b363SPhilipp Reisner rwlock_t global_state_lock;
64b411b363SPhilipp Reisner 
65b411b363SPhilipp Reisner /* used for synchronous meta data and bitmap IO
66b411b363SPhilipp Reisner  * submitted by drbd_md_sync_page_io()
67b411b363SPhilipp Reisner  */
68b411b363SPhilipp Reisner void drbd_md_io_complete(struct bio *bio, int error)
69b411b363SPhilipp Reisner {
70b411b363SPhilipp Reisner 	struct drbd_md_io *md_io;
71b30ab791SAndreas Gruenbacher 	struct drbd_device *device;
72b411b363SPhilipp Reisner 
73b411b363SPhilipp Reisner 	md_io = (struct drbd_md_io *)bio->bi_private;
74b30ab791SAndreas Gruenbacher 	device = container_of(md_io, struct drbd_device, md_io);
75cdfda633SPhilipp Reisner 
76b411b363SPhilipp Reisner 	md_io->error = error;
77b411b363SPhilipp Reisner 
780cfac5ddSPhilipp Reisner 	/* We grabbed an extra reference in _drbd_md_sync_page_io() to be able
790cfac5ddSPhilipp Reisner 	 * to timeout on the lower level device, and eventually detach from it.
800cfac5ddSPhilipp Reisner 	 * If this io completion runs after that timeout expired, this
810cfac5ddSPhilipp Reisner 	 * drbd_md_put_buffer() may allow us to finally try and re-attach.
820cfac5ddSPhilipp Reisner 	 * During normal operation, this only puts that extra reference
830cfac5ddSPhilipp Reisner 	 * down to 1 again.
840cfac5ddSPhilipp Reisner 	 * Make sure we first drop the reference, and only then signal
850cfac5ddSPhilipp Reisner 	 * completion, or we may (in drbd_al_read_log()) cycle so fast into the
860cfac5ddSPhilipp Reisner 	 * next drbd_md_sync_page_io(), that we trigger the
87b30ab791SAndreas Gruenbacher 	 * ASSERT(atomic_read(&device->md_io_in_use) == 1) there.
880cfac5ddSPhilipp Reisner 	 */
89b30ab791SAndreas Gruenbacher 	drbd_md_put_buffer(device);
90cdfda633SPhilipp Reisner 	md_io->done = 1;
91b30ab791SAndreas Gruenbacher 	wake_up(&device->misc_wait);
92cdfda633SPhilipp Reisner 	bio_put(bio);
93b30ab791SAndreas Gruenbacher 	if (device->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */
94b30ab791SAndreas Gruenbacher 		put_ldev(device);
95b411b363SPhilipp Reisner }
96b411b363SPhilipp Reisner 
97b411b363SPhilipp Reisner /* reads on behalf of the partner,
98b411b363SPhilipp Reisner  * "submitted" by the receiver
99b411b363SPhilipp Reisner  */
100a186e478SRashika Kheria static void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(local)
101b411b363SPhilipp Reisner {
102b411b363SPhilipp Reisner 	unsigned long flags = 0;
103a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
104b411b363SPhilipp Reisner 
1050500813fSAndreas Gruenbacher 	spin_lock_irqsave(&device->resource->req_lock, flags);
106b30ab791SAndreas Gruenbacher 	device->read_cnt += peer_req->i.size >> 9;
107a8cd15baSAndreas Gruenbacher 	list_del(&peer_req->w.list);
108b30ab791SAndreas Gruenbacher 	if (list_empty(&device->read_ee))
109b30ab791SAndreas Gruenbacher 		wake_up(&device->ee_wait);
110db830c46SAndreas Gruenbacher 	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
111b30ab791SAndreas Gruenbacher 		__drbd_chk_io_error(device, DRBD_READ_ERROR);
1120500813fSAndreas Gruenbacher 	spin_unlock_irqrestore(&device->resource->req_lock, flags);
113b411b363SPhilipp Reisner 
11484b8c06bSAndreas Gruenbacher 	drbd_queue_work(&first_peer_device(device)->connection->sender_work,
115a8cd15baSAndreas Gruenbacher 			&peer_req->w);
116b30ab791SAndreas Gruenbacher 	put_ldev(device);
117b411b363SPhilipp Reisner }
118b411b363SPhilipp Reisner 
119b411b363SPhilipp Reisner /* writes on behalf of the partner, or resync writes,
12045bb912bSLars Ellenberg  * "submitted" by the receiver, final stage.  */
121db830c46SAndreas Gruenbacher static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(local)
122b411b363SPhilipp Reisner {
123b411b363SPhilipp Reisner 	unsigned long flags = 0;
124a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
125181286adSLars Ellenberg 	struct drbd_interval i;
126b411b363SPhilipp Reisner 	int do_wake;
127579b57edSAndreas Gruenbacher 	u64 block_id;
128b411b363SPhilipp Reisner 	int do_al_complete_io;
129b411b363SPhilipp Reisner 
130db830c46SAndreas Gruenbacher 	/* after we moved peer_req to done_ee,
131b411b363SPhilipp Reisner 	 * we may no longer access it,
132b411b363SPhilipp Reisner 	 * it may be freed/reused already!
133b411b363SPhilipp Reisner 	 * (as soon as we release the req_lock) */
134181286adSLars Ellenberg 	i = peer_req->i;
135db830c46SAndreas Gruenbacher 	do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
136db830c46SAndreas Gruenbacher 	block_id = peer_req->block_id;
137b411b363SPhilipp Reisner 
1380500813fSAndreas Gruenbacher 	spin_lock_irqsave(&device->resource->req_lock, flags);
139b30ab791SAndreas Gruenbacher 	device->writ_cnt += peer_req->i.size >> 9;
140a8cd15baSAndreas Gruenbacher 	list_move_tail(&peer_req->w.list, &device->done_ee);
141b411b363SPhilipp Reisner 
142bb3bfe96SAndreas Gruenbacher 	/*
1435e472264SAndreas Gruenbacher 	 * Do not remove from the write_requests tree here: we did not send the
144bb3bfe96SAndreas Gruenbacher 	 * Ack yet and did not wake possibly waiting conflicting requests.
145bb3bfe96SAndreas Gruenbacher 	 * Removed from the tree from "drbd_process_done_ee" within the
14684b8c06bSAndreas Gruenbacher 	 * appropriate dw.cb (e_end_block/e_end_resync_block) or from
147bb3bfe96SAndreas Gruenbacher 	 * _drbd_clear_done_ee.
148bb3bfe96SAndreas Gruenbacher 	 */
149b411b363SPhilipp Reisner 
150b30ab791SAndreas Gruenbacher 	do_wake = list_empty(block_id == ID_SYNCER ? &device->sync_ee : &device->active_ee);
151b411b363SPhilipp Reisner 
152db830c46SAndreas Gruenbacher 	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
153b30ab791SAndreas Gruenbacher 		__drbd_chk_io_error(device, DRBD_WRITE_ERROR);
1540500813fSAndreas Gruenbacher 	spin_unlock_irqrestore(&device->resource->req_lock, flags);
155b411b363SPhilipp Reisner 
156579b57edSAndreas Gruenbacher 	if (block_id == ID_SYNCER)
157b30ab791SAndreas Gruenbacher 		drbd_rs_complete_io(device, i.sector);
158b411b363SPhilipp Reisner 
159b411b363SPhilipp Reisner 	if (do_wake)
160b30ab791SAndreas Gruenbacher 		wake_up(&device->ee_wait);
161b411b363SPhilipp Reisner 
162b411b363SPhilipp Reisner 	if (do_al_complete_io)
163b30ab791SAndreas Gruenbacher 		drbd_al_complete_io(device, &i);
164b411b363SPhilipp Reisner 
165a6b32bc3SAndreas Gruenbacher 	wake_asender(first_peer_device(device)->connection);
166b30ab791SAndreas Gruenbacher 	put_ldev(device);
16745bb912bSLars Ellenberg }
168b411b363SPhilipp Reisner 
16945bb912bSLars Ellenberg /* writes on behalf of the partner, or resync writes,
17045bb912bSLars Ellenberg  * "submitted" by the receiver.
17145bb912bSLars Ellenberg  */
172fcefa62eSAndreas Gruenbacher void drbd_peer_request_endio(struct bio *bio, int error)
17345bb912bSLars Ellenberg {
174db830c46SAndreas Gruenbacher 	struct drbd_peer_request *peer_req = bio->bi_private;
175a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
17645bb912bSLars Ellenberg 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
17745bb912bSLars Ellenberg 	int is_write = bio_data_dir(bio) == WRITE;
17845bb912bSLars Ellenberg 
17907194272SLars Ellenberg 	if (error && __ratelimit(&drbd_ratelimit_state))
180d0180171SAndreas Gruenbacher 		drbd_warn(device, "%s: error=%d s=%llus\n",
18145bb912bSLars Ellenberg 				is_write ? "write" : "read", error,
182db830c46SAndreas Gruenbacher 				(unsigned long long)peer_req->i.sector);
18345bb912bSLars Ellenberg 	if (!error && !uptodate) {
18407194272SLars Ellenberg 		if (__ratelimit(&drbd_ratelimit_state))
185d0180171SAndreas Gruenbacher 			drbd_warn(device, "%s: setting error to -EIO s=%llus\n",
18645bb912bSLars Ellenberg 					is_write ? "write" : "read",
187db830c46SAndreas Gruenbacher 					(unsigned long long)peer_req->i.sector);
18845bb912bSLars Ellenberg 		/* strange behavior of some lower level drivers...
18945bb912bSLars Ellenberg 		 * fail the request by clearing the uptodate flag,
19045bb912bSLars Ellenberg 		 * but do not return any error?! */
19145bb912bSLars Ellenberg 		error = -EIO;
19245bb912bSLars Ellenberg 	}
19345bb912bSLars Ellenberg 
19445bb912bSLars Ellenberg 	if (error)
195db830c46SAndreas Gruenbacher 		set_bit(__EE_WAS_ERROR, &peer_req->flags);
19645bb912bSLars Ellenberg 
19745bb912bSLars Ellenberg 	bio_put(bio); /* no need for the bio anymore */
198db830c46SAndreas Gruenbacher 	if (atomic_dec_and_test(&peer_req->pending_bios)) {
19945bb912bSLars Ellenberg 		if (is_write)
200db830c46SAndreas Gruenbacher 			drbd_endio_write_sec_final(peer_req);
20145bb912bSLars Ellenberg 		else
202db830c46SAndreas Gruenbacher 			drbd_endio_read_sec_final(peer_req);
20345bb912bSLars Ellenberg 	}
204b411b363SPhilipp Reisner }
205b411b363SPhilipp Reisner 
206b411b363SPhilipp Reisner /* read, readA or write requests on R_PRIMARY coming from drbd_make_request
207b411b363SPhilipp Reisner  */
208fcefa62eSAndreas Gruenbacher void drbd_request_endio(struct bio *bio, int error)
209b411b363SPhilipp Reisner {
210a115413dSLars Ellenberg 	unsigned long flags;
211b411b363SPhilipp Reisner 	struct drbd_request *req = bio->bi_private;
21284b8c06bSAndreas Gruenbacher 	struct drbd_device *device = req->device;
213a115413dSLars Ellenberg 	struct bio_and_error m;
214b411b363SPhilipp Reisner 	enum drbd_req_event what;
215b411b363SPhilipp Reisner 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
216b411b363SPhilipp Reisner 
217b411b363SPhilipp Reisner 	if (!error && !uptodate) {
218d0180171SAndreas Gruenbacher 		drbd_warn(device, "p %s: setting error to -EIO\n",
219b411b363SPhilipp Reisner 			 bio_data_dir(bio) == WRITE ? "write" : "read");
220b411b363SPhilipp Reisner 		/* strange behavior of some lower level drivers...
221b411b363SPhilipp Reisner 		 * fail the request by clearing the uptodate flag,
222b411b363SPhilipp Reisner 		 * but do not return any error?! */
223b411b363SPhilipp Reisner 		error = -EIO;
224b411b363SPhilipp Reisner 	}
225b411b363SPhilipp Reisner 
2261b6dd252SPhilipp Reisner 
2271b6dd252SPhilipp Reisner 	/* If this request was aborted locally before,
2281b6dd252SPhilipp Reisner 	 * but now was completed "successfully",
2291b6dd252SPhilipp Reisner 	 * chances are that this caused arbitrary data corruption.
2301b6dd252SPhilipp Reisner 	 *
2311b6dd252SPhilipp Reisner 	 * "aborting" requests, or force-detaching the disk, is intended for
2321b6dd252SPhilipp Reisner 	 * completely blocked/hung local backing devices which do no longer
2331b6dd252SPhilipp Reisner 	 * complete requests at all, not even do error completions.  In this
2341b6dd252SPhilipp Reisner 	 * situation, usually a hard-reset and failover is the only way out.
2351b6dd252SPhilipp Reisner 	 *
2361b6dd252SPhilipp Reisner 	 * By "aborting", basically faking a local error-completion,
2371b6dd252SPhilipp Reisner 	 * we allow for a more graceful swichover by cleanly migrating services.
2381b6dd252SPhilipp Reisner 	 * Still the affected node has to be rebooted "soon".
2391b6dd252SPhilipp Reisner 	 *
2401b6dd252SPhilipp Reisner 	 * By completing these requests, we allow the upper layers to re-use
2411b6dd252SPhilipp Reisner 	 * the associated data pages.
2421b6dd252SPhilipp Reisner 	 *
2431b6dd252SPhilipp Reisner 	 * If later the local backing device "recovers", and now DMAs some data
2441b6dd252SPhilipp Reisner 	 * from disk into the original request pages, in the best case it will
2451b6dd252SPhilipp Reisner 	 * just put random data into unused pages; but typically it will corrupt
2461b6dd252SPhilipp Reisner 	 * meanwhile completely unrelated data, causing all sorts of damage.
2471b6dd252SPhilipp Reisner 	 *
2481b6dd252SPhilipp Reisner 	 * Which means delayed successful completion,
2491b6dd252SPhilipp Reisner 	 * especially for READ requests,
2501b6dd252SPhilipp Reisner 	 * is a reason to panic().
2511b6dd252SPhilipp Reisner 	 *
2521b6dd252SPhilipp Reisner 	 * We assume that a delayed *error* completion is OK,
2531b6dd252SPhilipp Reisner 	 * though we still will complain noisily about it.
2541b6dd252SPhilipp Reisner 	 */
2551b6dd252SPhilipp Reisner 	if (unlikely(req->rq_state & RQ_LOCAL_ABORTED)) {
2561b6dd252SPhilipp Reisner 		if (__ratelimit(&drbd_ratelimit_state))
257d0180171SAndreas Gruenbacher 			drbd_emerg(device, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
2581b6dd252SPhilipp Reisner 
2591b6dd252SPhilipp Reisner 		if (!error)
2601b6dd252SPhilipp Reisner 			panic("possible random memory corruption caused by delayed completion of aborted local request\n");
2611b6dd252SPhilipp Reisner 	}
2621b6dd252SPhilipp Reisner 
263b411b363SPhilipp Reisner 	/* to avoid recursion in __req_mod */
264b411b363SPhilipp Reisner 	if (unlikely(error)) {
265b411b363SPhilipp Reisner 		what = (bio_data_dir(bio) == WRITE)
2668554df1cSAndreas Gruenbacher 			? WRITE_COMPLETED_WITH_ERROR
2675c3c7e64SLars Ellenberg 			: (bio_rw(bio) == READ)
2688554df1cSAndreas Gruenbacher 			  ? READ_COMPLETED_WITH_ERROR
2698554df1cSAndreas Gruenbacher 			  : READ_AHEAD_COMPLETED_WITH_ERROR;
270b411b363SPhilipp Reisner 	} else
2718554df1cSAndreas Gruenbacher 		what = COMPLETED_OK;
272b411b363SPhilipp Reisner 
273b411b363SPhilipp Reisner 	bio_put(req->private_bio);
274b411b363SPhilipp Reisner 	req->private_bio = ERR_PTR(error);
275b411b363SPhilipp Reisner 
276a115413dSLars Ellenberg 	/* not req_mod(), we need irqsave here! */
2770500813fSAndreas Gruenbacher 	spin_lock_irqsave(&device->resource->req_lock, flags);
278a115413dSLars Ellenberg 	__req_mod(req, what, &m);
2790500813fSAndreas Gruenbacher 	spin_unlock_irqrestore(&device->resource->req_lock, flags);
280b30ab791SAndreas Gruenbacher 	put_ldev(device);
281a115413dSLars Ellenberg 
282a115413dSLars Ellenberg 	if (m.bio)
283b30ab791SAndreas Gruenbacher 		complete_master_bio(device, &m);
284b411b363SPhilipp Reisner }
285b411b363SPhilipp Reisner 
28679a3c8d3SAndreas Gruenbacher void drbd_csum_ee(struct crypto_hash *tfm, struct drbd_peer_request *peer_req, void *digest)
28745bb912bSLars Ellenberg {
28845bb912bSLars Ellenberg 	struct hash_desc desc;
28945bb912bSLars Ellenberg 	struct scatterlist sg;
290db830c46SAndreas Gruenbacher 	struct page *page = peer_req->pages;
29145bb912bSLars Ellenberg 	struct page *tmp;
29245bb912bSLars Ellenberg 	unsigned len;
29345bb912bSLars Ellenberg 
29445bb912bSLars Ellenberg 	desc.tfm = tfm;
29545bb912bSLars Ellenberg 	desc.flags = 0;
29645bb912bSLars Ellenberg 
29745bb912bSLars Ellenberg 	sg_init_table(&sg, 1);
29845bb912bSLars Ellenberg 	crypto_hash_init(&desc);
29945bb912bSLars Ellenberg 
30045bb912bSLars Ellenberg 	while ((tmp = page_chain_next(page))) {
30145bb912bSLars Ellenberg 		/* all but the last page will be fully used */
30245bb912bSLars Ellenberg 		sg_set_page(&sg, page, PAGE_SIZE, 0);
30345bb912bSLars Ellenberg 		crypto_hash_update(&desc, &sg, sg.length);
30445bb912bSLars Ellenberg 		page = tmp;
30545bb912bSLars Ellenberg 	}
30645bb912bSLars Ellenberg 	/* and now the last, possibly only partially used page */
307db830c46SAndreas Gruenbacher 	len = peer_req->i.size & (PAGE_SIZE - 1);
30845bb912bSLars Ellenberg 	sg_set_page(&sg, page, len ?: PAGE_SIZE, 0);
30945bb912bSLars Ellenberg 	crypto_hash_update(&desc, &sg, sg.length);
31045bb912bSLars Ellenberg 	crypto_hash_final(&desc, digest);
31145bb912bSLars Ellenberg }
31245bb912bSLars Ellenberg 
31379a3c8d3SAndreas Gruenbacher void drbd_csum_bio(struct crypto_hash *tfm, struct bio *bio, void *digest)
314b411b363SPhilipp Reisner {
315b411b363SPhilipp Reisner 	struct hash_desc desc;
316b411b363SPhilipp Reisner 	struct scatterlist sg;
3177988613bSKent Overstreet 	struct bio_vec bvec;
3187988613bSKent Overstreet 	struct bvec_iter iter;
319b411b363SPhilipp Reisner 
320b411b363SPhilipp Reisner 	desc.tfm = tfm;
321b411b363SPhilipp Reisner 	desc.flags = 0;
322b411b363SPhilipp Reisner 
323b411b363SPhilipp Reisner 	sg_init_table(&sg, 1);
324b411b363SPhilipp Reisner 	crypto_hash_init(&desc);
325b411b363SPhilipp Reisner 
3267988613bSKent Overstreet 	bio_for_each_segment(bvec, bio, iter) {
3277988613bSKent Overstreet 		sg_set_page(&sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
328b411b363SPhilipp Reisner 		crypto_hash_update(&desc, &sg, sg.length);
329b411b363SPhilipp Reisner 	}
330b411b363SPhilipp Reisner 	crypto_hash_final(&desc, digest);
331b411b363SPhilipp Reisner }
332b411b363SPhilipp Reisner 
3339676c760SLars Ellenberg /* MAYBE merge common code with w_e_end_ov_req */
33499920dc5SAndreas Gruenbacher static int w_e_send_csum(struct drbd_work *w, int cancel)
335b411b363SPhilipp Reisner {
336a8cd15baSAndreas Gruenbacher 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
337a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
338b411b363SPhilipp Reisner 	int digest_size;
339b411b363SPhilipp Reisner 	void *digest;
34099920dc5SAndreas Gruenbacher 	int err = 0;
341b411b363SPhilipp Reisner 
34253ea4331SLars Ellenberg 	if (unlikely(cancel))
34353ea4331SLars Ellenberg 		goto out;
344b411b363SPhilipp Reisner 
3459676c760SLars Ellenberg 	if (unlikely((peer_req->flags & EE_WAS_ERROR) != 0))
34653ea4331SLars Ellenberg 		goto out;
34753ea4331SLars Ellenberg 
348a6b32bc3SAndreas Gruenbacher 	digest_size = crypto_hash_digestsize(first_peer_device(device)->connection->csums_tfm);
349b411b363SPhilipp Reisner 	digest = kmalloc(digest_size, GFP_NOIO);
350b411b363SPhilipp Reisner 	if (digest) {
351db830c46SAndreas Gruenbacher 		sector_t sector = peer_req->i.sector;
352db830c46SAndreas Gruenbacher 		unsigned int size = peer_req->i.size;
35379a3c8d3SAndreas Gruenbacher 		drbd_csum_ee(first_peer_device(device)->connection->csums_tfm, peer_req, digest);
3549676c760SLars Ellenberg 		/* Free peer_req and pages before send.
35553ea4331SLars Ellenberg 		 * In case we block on congestion, we could otherwise run into
35653ea4331SLars Ellenberg 		 * some distributed deadlock, if the other side blocks on
35753ea4331SLars Ellenberg 		 * congestion as well, because our receiver blocks in
358c37c8ecfSAndreas Gruenbacher 		 * drbd_alloc_pages due to pp_in_use > max_buffers. */
359b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
360db830c46SAndreas Gruenbacher 		peer_req = NULL;
361b30ab791SAndreas Gruenbacher 		inc_rs_pending(device);
36269a22773SAndreas Gruenbacher 		err = drbd_send_drequest_csum(first_peer_device(device), sector, size,
36353ea4331SLars Ellenberg 					      digest, digest_size,
364b411b363SPhilipp Reisner 					      P_CSUM_RS_REQUEST);
365b411b363SPhilipp Reisner 		kfree(digest);
366b411b363SPhilipp Reisner 	} else {
367d0180171SAndreas Gruenbacher 		drbd_err(device, "kmalloc() of digest failed.\n");
36899920dc5SAndreas Gruenbacher 		err = -ENOMEM;
369b411b363SPhilipp Reisner 	}
370b411b363SPhilipp Reisner 
37153ea4331SLars Ellenberg out:
372db830c46SAndreas Gruenbacher 	if (peer_req)
373b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
374b411b363SPhilipp Reisner 
37599920dc5SAndreas Gruenbacher 	if (unlikely(err))
376d0180171SAndreas Gruenbacher 		drbd_err(device, "drbd_send_drequest(..., csum) failed\n");
37799920dc5SAndreas Gruenbacher 	return err;
378b411b363SPhilipp Reisner }
379b411b363SPhilipp Reisner 
380b411b363SPhilipp Reisner #define GFP_TRY	(__GFP_HIGHMEM | __GFP_NOWARN)
381b411b363SPhilipp Reisner 
38269a22773SAndreas Gruenbacher static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector, int size)
383b411b363SPhilipp Reisner {
38469a22773SAndreas Gruenbacher 	struct drbd_device *device = peer_device->device;
385db830c46SAndreas Gruenbacher 	struct drbd_peer_request *peer_req;
386b411b363SPhilipp Reisner 
387b30ab791SAndreas Gruenbacher 	if (!get_ldev(device))
38880a40e43SLars Ellenberg 		return -EIO;
389b411b363SPhilipp Reisner 
390b30ab791SAndreas Gruenbacher 	if (drbd_rs_should_slow_down(device, sector))
3910f0601f4SLars Ellenberg 		goto defer;
3920f0601f4SLars Ellenberg 
393b411b363SPhilipp Reisner 	/* GFP_TRY, because if there is no memory available right now, this may
394b411b363SPhilipp Reisner 	 * be rescheduled for later. It is "only" background resync, after all. */
39569a22773SAndreas Gruenbacher 	peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER /* unused */, sector,
3960db55363SAndreas Gruenbacher 				       size, GFP_TRY);
397db830c46SAndreas Gruenbacher 	if (!peer_req)
39880a40e43SLars Ellenberg 		goto defer;
399b411b363SPhilipp Reisner 
400a8cd15baSAndreas Gruenbacher 	peer_req->w.cb = w_e_send_csum;
4010500813fSAndreas Gruenbacher 	spin_lock_irq(&device->resource->req_lock);
402a8cd15baSAndreas Gruenbacher 	list_add(&peer_req->w.list, &device->read_ee);
4030500813fSAndreas Gruenbacher 	spin_unlock_irq(&device->resource->req_lock);
404b411b363SPhilipp Reisner 
405b30ab791SAndreas Gruenbacher 	atomic_add(size >> 9, &device->rs_sect_ev);
406b30ab791SAndreas Gruenbacher 	if (drbd_submit_peer_request(device, peer_req, READ, DRBD_FAULT_RS_RD) == 0)
40780a40e43SLars Ellenberg 		return 0;
40845bb912bSLars Ellenberg 
40910f6d992SLars Ellenberg 	/* If it failed because of ENOMEM, retry should help.  If it failed
41010f6d992SLars Ellenberg 	 * because bio_add_page failed (probably broken lower level driver),
41110f6d992SLars Ellenberg 	 * retry may or may not help.
41210f6d992SLars Ellenberg 	 * If it does not, you may need to force disconnect. */
4130500813fSAndreas Gruenbacher 	spin_lock_irq(&device->resource->req_lock);
414a8cd15baSAndreas Gruenbacher 	list_del(&peer_req->w.list);
4150500813fSAndreas Gruenbacher 	spin_unlock_irq(&device->resource->req_lock);
41622cc37a9SLars Ellenberg 
417b30ab791SAndreas Gruenbacher 	drbd_free_peer_req(device, peer_req);
41880a40e43SLars Ellenberg defer:
419b30ab791SAndreas Gruenbacher 	put_ldev(device);
42080a40e43SLars Ellenberg 	return -EAGAIN;
421b411b363SPhilipp Reisner }
422b411b363SPhilipp Reisner 
42399920dc5SAndreas Gruenbacher int w_resync_timer(struct drbd_work *w, int cancel)
424794abb75SPhilipp Reisner {
42584b8c06bSAndreas Gruenbacher 	struct drbd_device *device =
42684b8c06bSAndreas Gruenbacher 		container_of(w, struct drbd_device, resync_work);
42784b8c06bSAndreas Gruenbacher 
428b30ab791SAndreas Gruenbacher 	switch (device->state.conn) {
429794abb75SPhilipp Reisner 	case C_VERIFY_S:
430d448a2e1SAndreas Gruenbacher 		make_ov_request(device, cancel);
431794abb75SPhilipp Reisner 		break;
432794abb75SPhilipp Reisner 	case C_SYNC_TARGET:
433d448a2e1SAndreas Gruenbacher 		make_resync_request(device, cancel);
434794abb75SPhilipp Reisner 		break;
435794abb75SPhilipp Reisner 	}
436794abb75SPhilipp Reisner 
43799920dc5SAndreas Gruenbacher 	return 0;
438794abb75SPhilipp Reisner }
439794abb75SPhilipp Reisner 
440b411b363SPhilipp Reisner void resync_timer_fn(unsigned long data)
441b411b363SPhilipp Reisner {
442b30ab791SAndreas Gruenbacher 	struct drbd_device *device = (struct drbd_device *) data;
443b411b363SPhilipp Reisner 
444b30ab791SAndreas Gruenbacher 	if (list_empty(&device->resync_work.list))
44584b8c06bSAndreas Gruenbacher 		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
44684b8c06bSAndreas Gruenbacher 				&device->resync_work);
447b411b363SPhilipp Reisner }
448b411b363SPhilipp Reisner 
449778f271dSPhilipp Reisner static void fifo_set(struct fifo_buffer *fb, int value)
450778f271dSPhilipp Reisner {
451778f271dSPhilipp Reisner 	int i;
452778f271dSPhilipp Reisner 
453778f271dSPhilipp Reisner 	for (i = 0; i < fb->size; i++)
454f10f2623SPhilipp Reisner 		fb->values[i] = value;
455778f271dSPhilipp Reisner }
456778f271dSPhilipp Reisner 
457778f271dSPhilipp Reisner static int fifo_push(struct fifo_buffer *fb, int value)
458778f271dSPhilipp Reisner {
459778f271dSPhilipp Reisner 	int ov;
460778f271dSPhilipp Reisner 
461778f271dSPhilipp Reisner 	ov = fb->values[fb->head_index];
462778f271dSPhilipp Reisner 	fb->values[fb->head_index++] = value;
463778f271dSPhilipp Reisner 
464778f271dSPhilipp Reisner 	if (fb->head_index >= fb->size)
465778f271dSPhilipp Reisner 		fb->head_index = 0;
466778f271dSPhilipp Reisner 
467778f271dSPhilipp Reisner 	return ov;
468778f271dSPhilipp Reisner }
469778f271dSPhilipp Reisner 
470778f271dSPhilipp Reisner static void fifo_add_val(struct fifo_buffer *fb, int value)
471778f271dSPhilipp Reisner {
472778f271dSPhilipp Reisner 	int i;
473778f271dSPhilipp Reisner 
474778f271dSPhilipp Reisner 	for (i = 0; i < fb->size; i++)
475778f271dSPhilipp Reisner 		fb->values[i] += value;
476778f271dSPhilipp Reisner }
477778f271dSPhilipp Reisner 
4789958c857SPhilipp Reisner struct fifo_buffer *fifo_alloc(int fifo_size)
4799958c857SPhilipp Reisner {
4809958c857SPhilipp Reisner 	struct fifo_buffer *fb;
4819958c857SPhilipp Reisner 
4828747d30aSLars Ellenberg 	fb = kzalloc(sizeof(struct fifo_buffer) + sizeof(int) * fifo_size, GFP_NOIO);
4839958c857SPhilipp Reisner 	if (!fb)
4849958c857SPhilipp Reisner 		return NULL;
4859958c857SPhilipp Reisner 
4869958c857SPhilipp Reisner 	fb->head_index = 0;
4879958c857SPhilipp Reisner 	fb->size = fifo_size;
4889958c857SPhilipp Reisner 	fb->total = 0;
4899958c857SPhilipp Reisner 
4909958c857SPhilipp Reisner 	return fb;
4919958c857SPhilipp Reisner }
4929958c857SPhilipp Reisner 
493b30ab791SAndreas Gruenbacher static int drbd_rs_controller(struct drbd_device *device)
494778f271dSPhilipp Reisner {
495daeda1ccSPhilipp Reisner 	struct disk_conf *dc;
496778f271dSPhilipp Reisner 	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
497778f271dSPhilipp Reisner 	unsigned int want;     /* The number of sectors we want in the proxy */
498778f271dSPhilipp Reisner 	int req_sect; /* Number of sectors to request in this turn */
499778f271dSPhilipp Reisner 	int correction; /* Number of sectors more we need in the proxy*/
500778f271dSPhilipp Reisner 	int cps; /* correction per invocation of drbd_rs_controller() */
501778f271dSPhilipp Reisner 	int steps; /* Number of time steps to plan ahead */
502778f271dSPhilipp Reisner 	int curr_corr;
503778f271dSPhilipp Reisner 	int max_sect;
504813472ceSPhilipp Reisner 	struct fifo_buffer *plan;
505778f271dSPhilipp Reisner 
506b30ab791SAndreas Gruenbacher 	sect_in = atomic_xchg(&device->rs_sect_in, 0); /* Number of sectors that came in */
507b30ab791SAndreas Gruenbacher 	device->rs_in_flight -= sect_in;
508778f271dSPhilipp Reisner 
509b30ab791SAndreas Gruenbacher 	dc = rcu_dereference(device->ldev->disk_conf);
510b30ab791SAndreas Gruenbacher 	plan = rcu_dereference(device->rs_plan_s);
511778f271dSPhilipp Reisner 
512813472ceSPhilipp Reisner 	steps = plan->size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
513778f271dSPhilipp Reisner 
514b30ab791SAndreas Gruenbacher 	if (device->rs_in_flight + sect_in == 0) { /* At start of resync */
515daeda1ccSPhilipp Reisner 		want = ((dc->resync_rate * 2 * SLEEP_TIME) / HZ) * steps;
516778f271dSPhilipp Reisner 	} else { /* normal path */
517daeda1ccSPhilipp Reisner 		want = dc->c_fill_target ? dc->c_fill_target :
518daeda1ccSPhilipp Reisner 			sect_in * dc->c_delay_target * HZ / (SLEEP_TIME * 10);
519778f271dSPhilipp Reisner 	}
520778f271dSPhilipp Reisner 
521b30ab791SAndreas Gruenbacher 	correction = want - device->rs_in_flight - plan->total;
522778f271dSPhilipp Reisner 
523778f271dSPhilipp Reisner 	/* Plan ahead */
524778f271dSPhilipp Reisner 	cps = correction / steps;
525813472ceSPhilipp Reisner 	fifo_add_val(plan, cps);
526813472ceSPhilipp Reisner 	plan->total += cps * steps;
527778f271dSPhilipp Reisner 
528778f271dSPhilipp Reisner 	/* What we do in this step */
529813472ceSPhilipp Reisner 	curr_corr = fifo_push(plan, 0);
530813472ceSPhilipp Reisner 	plan->total -= curr_corr;
531778f271dSPhilipp Reisner 
532778f271dSPhilipp Reisner 	req_sect = sect_in + curr_corr;
533778f271dSPhilipp Reisner 	if (req_sect < 0)
534778f271dSPhilipp Reisner 		req_sect = 0;
535778f271dSPhilipp Reisner 
536daeda1ccSPhilipp Reisner 	max_sect = (dc->c_max_rate * 2 * SLEEP_TIME) / HZ;
537778f271dSPhilipp Reisner 	if (req_sect > max_sect)
538778f271dSPhilipp Reisner 		req_sect = max_sect;
539778f271dSPhilipp Reisner 
540778f271dSPhilipp Reisner 	/*
541d0180171SAndreas Gruenbacher 	drbd_warn(device, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
542b30ab791SAndreas Gruenbacher 		 sect_in, device->rs_in_flight, want, correction,
543b30ab791SAndreas Gruenbacher 		 steps, cps, device->rs_planed, curr_corr, req_sect);
544778f271dSPhilipp Reisner 	*/
545778f271dSPhilipp Reisner 
546778f271dSPhilipp Reisner 	return req_sect;
547778f271dSPhilipp Reisner }
548778f271dSPhilipp Reisner 
549b30ab791SAndreas Gruenbacher static int drbd_rs_number_requests(struct drbd_device *device)
550e65f440dSLars Ellenberg {
551e65f440dSLars Ellenberg 	int number;
552813472ceSPhilipp Reisner 
553813472ceSPhilipp Reisner 	rcu_read_lock();
554b30ab791SAndreas Gruenbacher 	if (rcu_dereference(device->rs_plan_s)->size) {
555b30ab791SAndreas Gruenbacher 		number = drbd_rs_controller(device) >> (BM_BLOCK_SHIFT - 9);
556b30ab791SAndreas Gruenbacher 		device->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
557e65f440dSLars Ellenberg 	} else {
558b30ab791SAndreas Gruenbacher 		device->c_sync_rate = rcu_dereference(device->ldev->disk_conf)->resync_rate;
559b30ab791SAndreas Gruenbacher 		number = SLEEP_TIME * device->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
560e65f440dSLars Ellenberg 	}
561813472ceSPhilipp Reisner 	rcu_read_unlock();
562e65f440dSLars Ellenberg 
563e65f440dSLars Ellenberg 	/* ignore the amount of pending requests, the resync controller should
564e65f440dSLars Ellenberg 	 * throttle down to incoming reply rate soon enough anyways. */
565e65f440dSLars Ellenberg 	return number;
566e65f440dSLars Ellenberg }
567e65f440dSLars Ellenberg 
568d448a2e1SAndreas Gruenbacher static int make_resync_request(struct drbd_device *device, int cancel)
569b411b363SPhilipp Reisner {
570b411b363SPhilipp Reisner 	unsigned long bit;
571b411b363SPhilipp Reisner 	sector_t sector;
572b30ab791SAndreas Gruenbacher 	const sector_t capacity = drbd_get_capacity(device->this_bdev);
5731816a2b4SLars Ellenberg 	int max_bio_size;
574e65f440dSLars Ellenberg 	int number, rollback_i, size;
575b411b363SPhilipp Reisner 	int align, queued, sndbuf;
5760f0601f4SLars Ellenberg 	int i = 0;
577b411b363SPhilipp Reisner 
578b411b363SPhilipp Reisner 	if (unlikely(cancel))
57999920dc5SAndreas Gruenbacher 		return 0;
580b411b363SPhilipp Reisner 
581b30ab791SAndreas Gruenbacher 	if (device->rs_total == 0) {
582af85e8e8SLars Ellenberg 		/* empty resync? */
583b30ab791SAndreas Gruenbacher 		drbd_resync_finished(device);
58499920dc5SAndreas Gruenbacher 		return 0;
585af85e8e8SLars Ellenberg 	}
586af85e8e8SLars Ellenberg 
587b30ab791SAndreas Gruenbacher 	if (!get_ldev(device)) {
588b30ab791SAndreas Gruenbacher 		/* Since we only need to access device->rsync a
589b30ab791SAndreas Gruenbacher 		   get_ldev_if_state(device,D_FAILED) would be sufficient, but
590b411b363SPhilipp Reisner 		   to continue resync with a broken disk makes no sense at
591b411b363SPhilipp Reisner 		   all */
592d0180171SAndreas Gruenbacher 		drbd_err(device, "Disk broke down during resync!\n");
59399920dc5SAndreas Gruenbacher 		return 0;
594b411b363SPhilipp Reisner 	}
595b411b363SPhilipp Reisner 
596b30ab791SAndreas Gruenbacher 	max_bio_size = queue_max_hw_sectors(device->rq_queue) << 9;
597b30ab791SAndreas Gruenbacher 	number = drbd_rs_number_requests(device);
598e65f440dSLars Ellenberg 	if (number == 0)
5990f0601f4SLars Ellenberg 		goto requeue;
600b411b363SPhilipp Reisner 
601b411b363SPhilipp Reisner 	for (i = 0; i < number; i++) {
602b411b363SPhilipp Reisner 		/* Stop generating RS requests, when half of the send buffer is filled */
603a6b32bc3SAndreas Gruenbacher 		mutex_lock(&first_peer_device(device)->connection->data.mutex);
604a6b32bc3SAndreas Gruenbacher 		if (first_peer_device(device)->connection->data.socket) {
605a6b32bc3SAndreas Gruenbacher 			queued = first_peer_device(device)->connection->data.socket->sk->sk_wmem_queued;
606a6b32bc3SAndreas Gruenbacher 			sndbuf = first_peer_device(device)->connection->data.socket->sk->sk_sndbuf;
607b411b363SPhilipp Reisner 		} else {
608b411b363SPhilipp Reisner 			queued = 1;
609b411b363SPhilipp Reisner 			sndbuf = 0;
610b411b363SPhilipp Reisner 		}
611a6b32bc3SAndreas Gruenbacher 		mutex_unlock(&first_peer_device(device)->connection->data.mutex);
612b411b363SPhilipp Reisner 		if (queued > sndbuf / 2)
613b411b363SPhilipp Reisner 			goto requeue;
614b411b363SPhilipp Reisner 
615b411b363SPhilipp Reisner next_sector:
616b411b363SPhilipp Reisner 		size = BM_BLOCK_SIZE;
617b30ab791SAndreas Gruenbacher 		bit  = drbd_bm_find_next(device, device->bm_resync_fo);
618b411b363SPhilipp Reisner 
6194b0715f0SLars Ellenberg 		if (bit == DRBD_END_OF_BITMAP) {
620b30ab791SAndreas Gruenbacher 			device->bm_resync_fo = drbd_bm_bits(device);
621b30ab791SAndreas Gruenbacher 			put_ldev(device);
62299920dc5SAndreas Gruenbacher 			return 0;
623b411b363SPhilipp Reisner 		}
624b411b363SPhilipp Reisner 
625b411b363SPhilipp Reisner 		sector = BM_BIT_TO_SECT(bit);
626b411b363SPhilipp Reisner 
627b30ab791SAndreas Gruenbacher 		if (drbd_rs_should_slow_down(device, sector) ||
628b30ab791SAndreas Gruenbacher 		    drbd_try_rs_begin_io(device, sector)) {
629b30ab791SAndreas Gruenbacher 			device->bm_resync_fo = bit;
630b411b363SPhilipp Reisner 			goto requeue;
631b411b363SPhilipp Reisner 		}
632b30ab791SAndreas Gruenbacher 		device->bm_resync_fo = bit + 1;
633b411b363SPhilipp Reisner 
634b30ab791SAndreas Gruenbacher 		if (unlikely(drbd_bm_test_bit(device, bit) == 0)) {
635b30ab791SAndreas Gruenbacher 			drbd_rs_complete_io(device, sector);
636b411b363SPhilipp Reisner 			goto next_sector;
637b411b363SPhilipp Reisner 		}
638b411b363SPhilipp Reisner 
6391816a2b4SLars Ellenberg #if DRBD_MAX_BIO_SIZE > BM_BLOCK_SIZE
640b411b363SPhilipp Reisner 		/* try to find some adjacent bits.
641b411b363SPhilipp Reisner 		 * we stop if we have already the maximum req size.
642b411b363SPhilipp Reisner 		 *
643b411b363SPhilipp Reisner 		 * Additionally always align bigger requests, in order to
644b411b363SPhilipp Reisner 		 * be prepared for all stripe sizes of software RAIDs.
645b411b363SPhilipp Reisner 		 */
646b411b363SPhilipp Reisner 		align = 1;
647d207450cSPhilipp Reisner 		rollback_i = i;
648b411b363SPhilipp Reisner 		for (;;) {
6491816a2b4SLars Ellenberg 			if (size + BM_BLOCK_SIZE > max_bio_size)
650b411b363SPhilipp Reisner 				break;
651b411b363SPhilipp Reisner 
652b411b363SPhilipp Reisner 			/* Be always aligned */
653b411b363SPhilipp Reisner 			if (sector & ((1<<(align+3))-1))
654b411b363SPhilipp Reisner 				break;
655b411b363SPhilipp Reisner 
656b411b363SPhilipp Reisner 			/* do not cross extent boundaries */
657b411b363SPhilipp Reisner 			if (((bit+1) & BM_BLOCKS_PER_BM_EXT_MASK) == 0)
658b411b363SPhilipp Reisner 				break;
659b411b363SPhilipp Reisner 			/* now, is it actually dirty, after all?
660b411b363SPhilipp Reisner 			 * caution, drbd_bm_test_bit is tri-state for some
661b411b363SPhilipp Reisner 			 * obscure reason; ( b == 0 ) would get the out-of-band
662b411b363SPhilipp Reisner 			 * only accidentally right because of the "oddly sized"
663b411b363SPhilipp Reisner 			 * adjustment below */
664b30ab791SAndreas Gruenbacher 			if (drbd_bm_test_bit(device, bit+1) != 1)
665b411b363SPhilipp Reisner 				break;
666b411b363SPhilipp Reisner 			bit++;
667b411b363SPhilipp Reisner 			size += BM_BLOCK_SIZE;
668b411b363SPhilipp Reisner 			if ((BM_BLOCK_SIZE << align) <= size)
669b411b363SPhilipp Reisner 				align++;
670b411b363SPhilipp Reisner 			i++;
671b411b363SPhilipp Reisner 		}
672b411b363SPhilipp Reisner 		/* if we merged some,
673b411b363SPhilipp Reisner 		 * reset the offset to start the next drbd_bm_find_next from */
674b411b363SPhilipp Reisner 		if (size > BM_BLOCK_SIZE)
675b30ab791SAndreas Gruenbacher 			device->bm_resync_fo = bit + 1;
676b411b363SPhilipp Reisner #endif
677b411b363SPhilipp Reisner 
678b411b363SPhilipp Reisner 		/* adjust very last sectors, in case we are oddly sized */
679b411b363SPhilipp Reisner 		if (sector + (size>>9) > capacity)
680b411b363SPhilipp Reisner 			size = (capacity-sector)<<9;
681a6b32bc3SAndreas Gruenbacher 		if (first_peer_device(device)->connection->agreed_pro_version >= 89 &&
682a6b32bc3SAndreas Gruenbacher 		    first_peer_device(device)->connection->csums_tfm) {
68369a22773SAndreas Gruenbacher 			switch (read_for_csum(first_peer_device(device), sector, size)) {
68480a40e43SLars Ellenberg 			case -EIO: /* Disk failure */
685b30ab791SAndreas Gruenbacher 				put_ldev(device);
68699920dc5SAndreas Gruenbacher 				return -EIO;
68780a40e43SLars Ellenberg 			case -EAGAIN: /* allocation failed, or ldev busy */
688b30ab791SAndreas Gruenbacher 				drbd_rs_complete_io(device, sector);
689b30ab791SAndreas Gruenbacher 				device->bm_resync_fo = BM_SECT_TO_BIT(sector);
690d207450cSPhilipp Reisner 				i = rollback_i;
691b411b363SPhilipp Reisner 				goto requeue;
69280a40e43SLars Ellenberg 			case 0:
69380a40e43SLars Ellenberg 				/* everything ok */
69480a40e43SLars Ellenberg 				break;
69580a40e43SLars Ellenberg 			default:
69680a40e43SLars Ellenberg 				BUG();
697b411b363SPhilipp Reisner 			}
698b411b363SPhilipp Reisner 		} else {
69999920dc5SAndreas Gruenbacher 			int err;
70099920dc5SAndreas Gruenbacher 
701b30ab791SAndreas Gruenbacher 			inc_rs_pending(device);
70269a22773SAndreas Gruenbacher 			err = drbd_send_drequest(first_peer_device(device), P_RS_DATA_REQUEST,
70399920dc5SAndreas Gruenbacher 						 sector, size, ID_SYNCER);
70499920dc5SAndreas Gruenbacher 			if (err) {
705d0180171SAndreas Gruenbacher 				drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
706b30ab791SAndreas Gruenbacher 				dec_rs_pending(device);
707b30ab791SAndreas Gruenbacher 				put_ldev(device);
70899920dc5SAndreas Gruenbacher 				return err;
709b411b363SPhilipp Reisner 			}
710b411b363SPhilipp Reisner 		}
711b411b363SPhilipp Reisner 	}
712b411b363SPhilipp Reisner 
713b30ab791SAndreas Gruenbacher 	if (device->bm_resync_fo >= drbd_bm_bits(device)) {
714b411b363SPhilipp Reisner 		/* last syncer _request_ was sent,
715b411b363SPhilipp Reisner 		 * but the P_RS_DATA_REPLY not yet received.  sync will end (and
716b411b363SPhilipp Reisner 		 * next sync group will resume), as soon as we receive the last
717b411b363SPhilipp Reisner 		 * resync data block, and the last bit is cleared.
718b411b363SPhilipp Reisner 		 * until then resync "work" is "inactive" ...
719b411b363SPhilipp Reisner 		 */
720b30ab791SAndreas Gruenbacher 		put_ldev(device);
72199920dc5SAndreas Gruenbacher 		return 0;
722b411b363SPhilipp Reisner 	}
723b411b363SPhilipp Reisner 
724b411b363SPhilipp Reisner  requeue:
725b30ab791SAndreas Gruenbacher 	device->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
726b30ab791SAndreas Gruenbacher 	mod_timer(&device->resync_timer, jiffies + SLEEP_TIME);
727b30ab791SAndreas Gruenbacher 	put_ldev(device);
72899920dc5SAndreas Gruenbacher 	return 0;
729b411b363SPhilipp Reisner }
730b411b363SPhilipp Reisner 
731d448a2e1SAndreas Gruenbacher static int make_ov_request(struct drbd_device *device, int cancel)
732b411b363SPhilipp Reisner {
733b411b363SPhilipp Reisner 	int number, i, size;
734b411b363SPhilipp Reisner 	sector_t sector;
735b30ab791SAndreas Gruenbacher 	const sector_t capacity = drbd_get_capacity(device->this_bdev);
73658ffa580SLars Ellenberg 	bool stop_sector_reached = false;
737b411b363SPhilipp Reisner 
738b411b363SPhilipp Reisner 	if (unlikely(cancel))
739b411b363SPhilipp Reisner 		return 1;
740b411b363SPhilipp Reisner 
741b30ab791SAndreas Gruenbacher 	number = drbd_rs_number_requests(device);
742b411b363SPhilipp Reisner 
743b30ab791SAndreas Gruenbacher 	sector = device->ov_position;
744b411b363SPhilipp Reisner 	for (i = 0; i < number; i++) {
74558ffa580SLars Ellenberg 		if (sector >= capacity)
746b411b363SPhilipp Reisner 			return 1;
74758ffa580SLars Ellenberg 
74858ffa580SLars Ellenberg 		/* We check for "finished" only in the reply path:
74958ffa580SLars Ellenberg 		 * w_e_end_ov_reply().
75058ffa580SLars Ellenberg 		 * We need to send at least one request out. */
75158ffa580SLars Ellenberg 		stop_sector_reached = i > 0
752b30ab791SAndreas Gruenbacher 			&& verify_can_do_stop_sector(device)
753b30ab791SAndreas Gruenbacher 			&& sector >= device->ov_stop_sector;
75458ffa580SLars Ellenberg 		if (stop_sector_reached)
75558ffa580SLars Ellenberg 			break;
756b411b363SPhilipp Reisner 
757b411b363SPhilipp Reisner 		size = BM_BLOCK_SIZE;
758b411b363SPhilipp Reisner 
759b30ab791SAndreas Gruenbacher 		if (drbd_rs_should_slow_down(device, sector) ||
760b30ab791SAndreas Gruenbacher 		    drbd_try_rs_begin_io(device, sector)) {
761b30ab791SAndreas Gruenbacher 			device->ov_position = sector;
762b411b363SPhilipp Reisner 			goto requeue;
763b411b363SPhilipp Reisner 		}
764b411b363SPhilipp Reisner 
765b411b363SPhilipp Reisner 		if (sector + (size>>9) > capacity)
766b411b363SPhilipp Reisner 			size = (capacity-sector)<<9;
767b411b363SPhilipp Reisner 
768b30ab791SAndreas Gruenbacher 		inc_rs_pending(device);
76969a22773SAndreas Gruenbacher 		if (drbd_send_ov_request(first_peer_device(device), sector, size)) {
770b30ab791SAndreas Gruenbacher 			dec_rs_pending(device);
771b411b363SPhilipp Reisner 			return 0;
772b411b363SPhilipp Reisner 		}
773b411b363SPhilipp Reisner 		sector += BM_SECT_PER_BIT;
774b411b363SPhilipp Reisner 	}
775b30ab791SAndreas Gruenbacher 	device->ov_position = sector;
776b411b363SPhilipp Reisner 
777b411b363SPhilipp Reisner  requeue:
778b30ab791SAndreas Gruenbacher 	device->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
77958ffa580SLars Ellenberg 	if (i == 0 || !stop_sector_reached)
780b30ab791SAndreas Gruenbacher 		mod_timer(&device->resync_timer, jiffies + SLEEP_TIME);
781b411b363SPhilipp Reisner 	return 1;
782b411b363SPhilipp Reisner }
783b411b363SPhilipp Reisner 
78499920dc5SAndreas Gruenbacher int w_ov_finished(struct drbd_work *w, int cancel)
785b411b363SPhilipp Reisner {
78684b8c06bSAndreas Gruenbacher 	struct drbd_device_work *dw =
78784b8c06bSAndreas Gruenbacher 		container_of(w, struct drbd_device_work, w);
78884b8c06bSAndreas Gruenbacher 	struct drbd_device *device = dw->device;
78984b8c06bSAndreas Gruenbacher 	kfree(dw);
790b30ab791SAndreas Gruenbacher 	ov_out_of_sync_print(device);
791b30ab791SAndreas Gruenbacher 	drbd_resync_finished(device);
792b411b363SPhilipp Reisner 
79399920dc5SAndreas Gruenbacher 	return 0;
794b411b363SPhilipp Reisner }
795b411b363SPhilipp Reisner 
79699920dc5SAndreas Gruenbacher static int w_resync_finished(struct drbd_work *w, int cancel)
797b411b363SPhilipp Reisner {
79884b8c06bSAndreas Gruenbacher 	struct drbd_device_work *dw =
79984b8c06bSAndreas Gruenbacher 		container_of(w, struct drbd_device_work, w);
80084b8c06bSAndreas Gruenbacher 	struct drbd_device *device = dw->device;
80184b8c06bSAndreas Gruenbacher 	kfree(dw);
802b411b363SPhilipp Reisner 
803b30ab791SAndreas Gruenbacher 	drbd_resync_finished(device);
804b411b363SPhilipp Reisner 
80599920dc5SAndreas Gruenbacher 	return 0;
806b411b363SPhilipp Reisner }
807b411b363SPhilipp Reisner 
808b30ab791SAndreas Gruenbacher static void ping_peer(struct drbd_device *device)
809af85e8e8SLars Ellenberg {
810a6b32bc3SAndreas Gruenbacher 	struct drbd_connection *connection = first_peer_device(device)->connection;
8112a67d8b9SPhilipp Reisner 
812bde89a9eSAndreas Gruenbacher 	clear_bit(GOT_PING_ACK, &connection->flags);
813bde89a9eSAndreas Gruenbacher 	request_ping(connection);
814bde89a9eSAndreas Gruenbacher 	wait_event(connection->ping_wait,
815bde89a9eSAndreas Gruenbacher 		   test_bit(GOT_PING_ACK, &connection->flags) || device->state.conn < C_CONNECTED);
816af85e8e8SLars Ellenberg }
817af85e8e8SLars Ellenberg 
818b30ab791SAndreas Gruenbacher int drbd_resync_finished(struct drbd_device *device)
819b411b363SPhilipp Reisner {
820b411b363SPhilipp Reisner 	unsigned long db, dt, dbdt;
821b411b363SPhilipp Reisner 	unsigned long n_oos;
822b411b363SPhilipp Reisner 	union drbd_state os, ns;
82384b8c06bSAndreas Gruenbacher 	struct drbd_device_work *dw;
824b411b363SPhilipp Reisner 	char *khelper_cmd = NULL;
82526525618SLars Ellenberg 	int verify_done = 0;
826b411b363SPhilipp Reisner 
827b411b363SPhilipp Reisner 	/* Remove all elements from the resync LRU. Since future actions
828b411b363SPhilipp Reisner 	 * might set bits in the (main) bitmap, then the entries in the
829b411b363SPhilipp Reisner 	 * resync LRU would be wrong. */
830b30ab791SAndreas Gruenbacher 	if (drbd_rs_del_all(device)) {
831b411b363SPhilipp Reisner 		/* In case this is not possible now, most probably because
832b411b363SPhilipp Reisner 		 * there are P_RS_DATA_REPLY Packets lingering on the worker's
833b411b363SPhilipp Reisner 		 * queue (or even the read operations for those packets
834b411b363SPhilipp Reisner 		 * is not finished by now).   Retry in 100ms. */
835b411b363SPhilipp Reisner 
83620ee6390SPhilipp Reisner 		schedule_timeout_interruptible(HZ / 10);
83784b8c06bSAndreas Gruenbacher 		dw = kmalloc(sizeof(struct drbd_device_work), GFP_ATOMIC);
83884b8c06bSAndreas Gruenbacher 		if (dw) {
83984b8c06bSAndreas Gruenbacher 			dw->w.cb = w_resync_finished;
84084b8c06bSAndreas Gruenbacher 			dw->device = device;
84184b8c06bSAndreas Gruenbacher 			drbd_queue_work(&first_peer_device(device)->connection->sender_work,
84284b8c06bSAndreas Gruenbacher 					&dw->w);
843b411b363SPhilipp Reisner 			return 1;
844b411b363SPhilipp Reisner 		}
84584b8c06bSAndreas Gruenbacher 		drbd_err(device, "Warn failed to drbd_rs_del_all() and to kmalloc(dw).\n");
846b411b363SPhilipp Reisner 	}
847b411b363SPhilipp Reisner 
848b30ab791SAndreas Gruenbacher 	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
849b411b363SPhilipp Reisner 	if (dt <= 0)
850b411b363SPhilipp Reisner 		dt = 1;
85158ffa580SLars Ellenberg 
852b30ab791SAndreas Gruenbacher 	db = device->rs_total;
85358ffa580SLars Ellenberg 	/* adjust for verify start and stop sectors, respective reached position */
854b30ab791SAndreas Gruenbacher 	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
855b30ab791SAndreas Gruenbacher 		db -= device->ov_left;
85658ffa580SLars Ellenberg 
857b411b363SPhilipp Reisner 	dbdt = Bit2KB(db/dt);
858b30ab791SAndreas Gruenbacher 	device->rs_paused /= HZ;
859b411b363SPhilipp Reisner 
860b30ab791SAndreas Gruenbacher 	if (!get_ldev(device))
861b411b363SPhilipp Reisner 		goto out;
862b411b363SPhilipp Reisner 
863b30ab791SAndreas Gruenbacher 	ping_peer(device);
864af85e8e8SLars Ellenberg 
8650500813fSAndreas Gruenbacher 	spin_lock_irq(&device->resource->req_lock);
866b30ab791SAndreas Gruenbacher 	os = drbd_read_state(device);
867b411b363SPhilipp Reisner 
86826525618SLars Ellenberg 	verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T);
86926525618SLars Ellenberg 
870b411b363SPhilipp Reisner 	/* This protects us against multiple calls (that can happen in the presence
871b411b363SPhilipp Reisner 	   of application IO), and against connectivity loss just before we arrive here. */
872b411b363SPhilipp Reisner 	if (os.conn <= C_CONNECTED)
873b411b363SPhilipp Reisner 		goto out_unlock;
874b411b363SPhilipp Reisner 
875b411b363SPhilipp Reisner 	ns = os;
876b411b363SPhilipp Reisner 	ns.conn = C_CONNECTED;
877b411b363SPhilipp Reisner 
878d0180171SAndreas Gruenbacher 	drbd_info(device, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
87926525618SLars Ellenberg 	     verify_done ? "Online verify" : "Resync",
880b30ab791SAndreas Gruenbacher 	     dt + device->rs_paused, device->rs_paused, dbdt);
881b411b363SPhilipp Reisner 
882b30ab791SAndreas Gruenbacher 	n_oos = drbd_bm_total_weight(device);
883b411b363SPhilipp Reisner 
884b411b363SPhilipp Reisner 	if (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) {
885b411b363SPhilipp Reisner 		if (n_oos) {
886d0180171SAndreas Gruenbacher 			drbd_alert(device, "Online verify found %lu %dk block out of sync!\n",
887b411b363SPhilipp Reisner 			      n_oos, Bit2KB(1));
888b411b363SPhilipp Reisner 			khelper_cmd = "out-of-sync";
889b411b363SPhilipp Reisner 		}
890b411b363SPhilipp Reisner 	} else {
8910b0ba1efSAndreas Gruenbacher 		D_ASSERT(device, (n_oos - device->rs_failed) == 0);
892b411b363SPhilipp Reisner 
893b411b363SPhilipp Reisner 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T)
894b411b363SPhilipp Reisner 			khelper_cmd = "after-resync-target";
895b411b363SPhilipp Reisner 
896a6b32bc3SAndreas Gruenbacher 		if (first_peer_device(device)->connection->csums_tfm && device->rs_total) {
897b30ab791SAndreas Gruenbacher 			const unsigned long s = device->rs_same_csum;
898b30ab791SAndreas Gruenbacher 			const unsigned long t = device->rs_total;
899b411b363SPhilipp Reisner 			const int ratio =
900b411b363SPhilipp Reisner 				(t == 0)     ? 0 :
901b411b363SPhilipp Reisner 			(t < 100000) ? ((s*100)/t) : (s/(t/100));
902d0180171SAndreas Gruenbacher 			drbd_info(device, "%u %% had equal checksums, eliminated: %luK; "
903b411b363SPhilipp Reisner 			     "transferred %luK total %luK\n",
904b411b363SPhilipp Reisner 			     ratio,
905b30ab791SAndreas Gruenbacher 			     Bit2KB(device->rs_same_csum),
906b30ab791SAndreas Gruenbacher 			     Bit2KB(device->rs_total - device->rs_same_csum),
907b30ab791SAndreas Gruenbacher 			     Bit2KB(device->rs_total));
908b411b363SPhilipp Reisner 		}
909b411b363SPhilipp Reisner 	}
910b411b363SPhilipp Reisner 
911b30ab791SAndreas Gruenbacher 	if (device->rs_failed) {
912d0180171SAndreas Gruenbacher 		drbd_info(device, "            %lu failed blocks\n", device->rs_failed);
913b411b363SPhilipp Reisner 
914b411b363SPhilipp Reisner 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T) {
915b411b363SPhilipp Reisner 			ns.disk = D_INCONSISTENT;
916b411b363SPhilipp Reisner 			ns.pdsk = D_UP_TO_DATE;
917b411b363SPhilipp Reisner 		} else {
918b411b363SPhilipp Reisner 			ns.disk = D_UP_TO_DATE;
919b411b363SPhilipp Reisner 			ns.pdsk = D_INCONSISTENT;
920b411b363SPhilipp Reisner 		}
921b411b363SPhilipp Reisner 	} else {
922b411b363SPhilipp Reisner 		ns.disk = D_UP_TO_DATE;
923b411b363SPhilipp Reisner 		ns.pdsk = D_UP_TO_DATE;
924b411b363SPhilipp Reisner 
925b411b363SPhilipp Reisner 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T) {
926b30ab791SAndreas Gruenbacher 			if (device->p_uuid) {
927b411b363SPhilipp Reisner 				int i;
928b411b363SPhilipp Reisner 				for (i = UI_BITMAP ; i <= UI_HISTORY_END ; i++)
929b30ab791SAndreas Gruenbacher 					_drbd_uuid_set(device, i, device->p_uuid[i]);
930b30ab791SAndreas Gruenbacher 				drbd_uuid_set(device, UI_BITMAP, device->ldev->md.uuid[UI_CURRENT]);
931b30ab791SAndreas Gruenbacher 				_drbd_uuid_set(device, UI_CURRENT, device->p_uuid[UI_CURRENT]);
932b411b363SPhilipp Reisner 			} else {
933d0180171SAndreas Gruenbacher 				drbd_err(device, "device->p_uuid is NULL! BUG\n");
934b411b363SPhilipp Reisner 			}
935b411b363SPhilipp Reisner 		}
936b411b363SPhilipp Reisner 
93762b0da3aSLars Ellenberg 		if (!(os.conn == C_VERIFY_S || os.conn == C_VERIFY_T)) {
93862b0da3aSLars Ellenberg 			/* for verify runs, we don't update uuids here,
93962b0da3aSLars Ellenberg 			 * so there would be nothing to report. */
940b30ab791SAndreas Gruenbacher 			drbd_uuid_set_bm(device, 0UL);
941b30ab791SAndreas Gruenbacher 			drbd_print_uuids(device, "updated UUIDs");
942b30ab791SAndreas Gruenbacher 			if (device->p_uuid) {
943b411b363SPhilipp Reisner 				/* Now the two UUID sets are equal, update what we
944b411b363SPhilipp Reisner 				 * know of the peer. */
945b411b363SPhilipp Reisner 				int i;
946b411b363SPhilipp Reisner 				for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
947b30ab791SAndreas Gruenbacher 					device->p_uuid[i] = device->ldev->md.uuid[i];
948b411b363SPhilipp Reisner 			}
949b411b363SPhilipp Reisner 		}
95062b0da3aSLars Ellenberg 	}
951b411b363SPhilipp Reisner 
952b30ab791SAndreas Gruenbacher 	_drbd_set_state(device, ns, CS_VERBOSE, NULL);
953b411b363SPhilipp Reisner out_unlock:
9540500813fSAndreas Gruenbacher 	spin_unlock_irq(&device->resource->req_lock);
955b30ab791SAndreas Gruenbacher 	put_ldev(device);
956b411b363SPhilipp Reisner out:
957b30ab791SAndreas Gruenbacher 	device->rs_total  = 0;
958b30ab791SAndreas Gruenbacher 	device->rs_failed = 0;
959b30ab791SAndreas Gruenbacher 	device->rs_paused = 0;
96058ffa580SLars Ellenberg 
96158ffa580SLars Ellenberg 	/* reset start sector, if we reached end of device */
962b30ab791SAndreas Gruenbacher 	if (verify_done && device->ov_left == 0)
963b30ab791SAndreas Gruenbacher 		device->ov_start_sector = 0;
964b411b363SPhilipp Reisner 
965b30ab791SAndreas Gruenbacher 	drbd_md_sync(device);
96613d42685SLars Ellenberg 
967b411b363SPhilipp Reisner 	if (khelper_cmd)
968b30ab791SAndreas Gruenbacher 		drbd_khelper(device, khelper_cmd);
969b411b363SPhilipp Reisner 
970b411b363SPhilipp Reisner 	return 1;
971b411b363SPhilipp Reisner }
972b411b363SPhilipp Reisner 
973b411b363SPhilipp Reisner /* helper */
974b30ab791SAndreas Gruenbacher static void move_to_net_ee_or_free(struct drbd_device *device, struct drbd_peer_request *peer_req)
975b411b363SPhilipp Reisner {
976045417f7SAndreas Gruenbacher 	if (drbd_peer_req_has_active_page(peer_req)) {
977b411b363SPhilipp Reisner 		/* This might happen if sendpage() has not finished */
978db830c46SAndreas Gruenbacher 		int i = (peer_req->i.size + PAGE_SIZE -1) >> PAGE_SHIFT;
979b30ab791SAndreas Gruenbacher 		atomic_add(i, &device->pp_in_use_by_net);
980b30ab791SAndreas Gruenbacher 		atomic_sub(i, &device->pp_in_use);
9810500813fSAndreas Gruenbacher 		spin_lock_irq(&device->resource->req_lock);
982a8cd15baSAndreas Gruenbacher 		list_add_tail(&peer_req->w.list, &device->net_ee);
9830500813fSAndreas Gruenbacher 		spin_unlock_irq(&device->resource->req_lock);
984435f0740SLars Ellenberg 		wake_up(&drbd_pp_wait);
985b411b363SPhilipp Reisner 	} else
986b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
987b411b363SPhilipp Reisner }
988b411b363SPhilipp Reisner 
989b411b363SPhilipp Reisner /**
990b411b363SPhilipp Reisner  * w_e_end_data_req() - Worker callback, to send a P_DATA_REPLY packet in response to a P_DATA_REQUEST
991b30ab791SAndreas Gruenbacher  * @device:	DRBD device.
992b411b363SPhilipp Reisner  * @w:		work object.
993b411b363SPhilipp Reisner  * @cancel:	The connection will be closed anyways
994b411b363SPhilipp Reisner  */
99599920dc5SAndreas Gruenbacher int w_e_end_data_req(struct drbd_work *w, int cancel)
996b411b363SPhilipp Reisner {
997a8cd15baSAndreas Gruenbacher 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
998a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
99999920dc5SAndreas Gruenbacher 	int err;
1000b411b363SPhilipp Reisner 
1001b411b363SPhilipp Reisner 	if (unlikely(cancel)) {
1002b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
1003b30ab791SAndreas Gruenbacher 		dec_unacked(device);
100499920dc5SAndreas Gruenbacher 		return 0;
1005b411b363SPhilipp Reisner 	}
1006b411b363SPhilipp Reisner 
1007db830c46SAndreas Gruenbacher 	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
100869a22773SAndreas Gruenbacher 		err = drbd_send_block(first_peer_device(device), P_DATA_REPLY, peer_req);
1009b411b363SPhilipp Reisner 	} else {
1010b411b363SPhilipp Reisner 		if (__ratelimit(&drbd_ratelimit_state))
1011d0180171SAndreas Gruenbacher 			drbd_err(device, "Sending NegDReply. sector=%llus.\n",
1012db830c46SAndreas Gruenbacher 			    (unsigned long long)peer_req->i.sector);
1013b411b363SPhilipp Reisner 
101469a22773SAndreas Gruenbacher 		err = drbd_send_ack(first_peer_device(device), P_NEG_DREPLY, peer_req);
1015b411b363SPhilipp Reisner 	}
1016b411b363SPhilipp Reisner 
1017b30ab791SAndreas Gruenbacher 	dec_unacked(device);
1018b411b363SPhilipp Reisner 
1019b30ab791SAndreas Gruenbacher 	move_to_net_ee_or_free(device, peer_req);
1020b411b363SPhilipp Reisner 
102199920dc5SAndreas Gruenbacher 	if (unlikely(err))
1022d0180171SAndreas Gruenbacher 		drbd_err(device, "drbd_send_block() failed\n");
102399920dc5SAndreas Gruenbacher 	return err;
1024b411b363SPhilipp Reisner }
1025b411b363SPhilipp Reisner 
1026b411b363SPhilipp Reisner /**
1027a209b4aeSAndreas Gruenbacher  * w_e_end_rsdata_req() - Worker callback to send a P_RS_DATA_REPLY packet in response to a P_RS_DATA_REQUEST
1028b411b363SPhilipp Reisner  * @w:		work object.
1029b411b363SPhilipp Reisner  * @cancel:	The connection will be closed anyways
1030b411b363SPhilipp Reisner  */
103199920dc5SAndreas Gruenbacher int w_e_end_rsdata_req(struct drbd_work *w, int cancel)
1032b411b363SPhilipp Reisner {
1033a8cd15baSAndreas Gruenbacher 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
1034a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
103599920dc5SAndreas Gruenbacher 	int err;
1036b411b363SPhilipp Reisner 
1037b411b363SPhilipp Reisner 	if (unlikely(cancel)) {
1038b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
1039b30ab791SAndreas Gruenbacher 		dec_unacked(device);
104099920dc5SAndreas Gruenbacher 		return 0;
1041b411b363SPhilipp Reisner 	}
1042b411b363SPhilipp Reisner 
1043b30ab791SAndreas Gruenbacher 	if (get_ldev_if_state(device, D_FAILED)) {
1044b30ab791SAndreas Gruenbacher 		drbd_rs_complete_io(device, peer_req->i.sector);
1045b30ab791SAndreas Gruenbacher 		put_ldev(device);
1046b411b363SPhilipp Reisner 	}
1047b411b363SPhilipp Reisner 
1048b30ab791SAndreas Gruenbacher 	if (device->state.conn == C_AHEAD) {
104969a22773SAndreas Gruenbacher 		err = drbd_send_ack(first_peer_device(device), P_RS_CANCEL, peer_req);
1050db830c46SAndreas Gruenbacher 	} else if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
1051b30ab791SAndreas Gruenbacher 		if (likely(device->state.pdsk >= D_INCONSISTENT)) {
1052b30ab791SAndreas Gruenbacher 			inc_rs_pending(device);
105369a22773SAndreas Gruenbacher 			err = drbd_send_block(first_peer_device(device), P_RS_DATA_REPLY, peer_req);
1054b411b363SPhilipp Reisner 		} else {
1055b411b363SPhilipp Reisner 			if (__ratelimit(&drbd_ratelimit_state))
1056d0180171SAndreas Gruenbacher 				drbd_err(device, "Not sending RSDataReply, "
1057b411b363SPhilipp Reisner 				    "partner DISKLESS!\n");
105899920dc5SAndreas Gruenbacher 			err = 0;
1059b411b363SPhilipp Reisner 		}
1060b411b363SPhilipp Reisner 	} else {
1061b411b363SPhilipp Reisner 		if (__ratelimit(&drbd_ratelimit_state))
1062d0180171SAndreas Gruenbacher 			drbd_err(device, "Sending NegRSDReply. sector %llus.\n",
1063db830c46SAndreas Gruenbacher 			    (unsigned long long)peer_req->i.sector);
1064b411b363SPhilipp Reisner 
106569a22773SAndreas Gruenbacher 		err = drbd_send_ack(first_peer_device(device), P_NEG_RS_DREPLY, peer_req);
1066b411b363SPhilipp Reisner 
1067b411b363SPhilipp Reisner 		/* update resync data with failure */
1068b30ab791SAndreas Gruenbacher 		drbd_rs_failed_io(device, peer_req->i.sector, peer_req->i.size);
1069b411b363SPhilipp Reisner 	}
1070b411b363SPhilipp Reisner 
1071b30ab791SAndreas Gruenbacher 	dec_unacked(device);
1072b411b363SPhilipp Reisner 
1073b30ab791SAndreas Gruenbacher 	move_to_net_ee_or_free(device, peer_req);
1074b411b363SPhilipp Reisner 
107599920dc5SAndreas Gruenbacher 	if (unlikely(err))
1076d0180171SAndreas Gruenbacher 		drbd_err(device, "drbd_send_block() failed\n");
107799920dc5SAndreas Gruenbacher 	return err;
1078b411b363SPhilipp Reisner }
1079b411b363SPhilipp Reisner 
108099920dc5SAndreas Gruenbacher int w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
1081b411b363SPhilipp Reisner {
1082a8cd15baSAndreas Gruenbacher 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
1083a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
1084b411b363SPhilipp Reisner 	struct digest_info *di;
1085b411b363SPhilipp Reisner 	int digest_size;
1086b411b363SPhilipp Reisner 	void *digest = NULL;
108799920dc5SAndreas Gruenbacher 	int err, eq = 0;
1088b411b363SPhilipp Reisner 
1089b411b363SPhilipp Reisner 	if (unlikely(cancel)) {
1090b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
1091b30ab791SAndreas Gruenbacher 		dec_unacked(device);
109299920dc5SAndreas Gruenbacher 		return 0;
1093b411b363SPhilipp Reisner 	}
1094b411b363SPhilipp Reisner 
1095b30ab791SAndreas Gruenbacher 	if (get_ldev(device)) {
1096b30ab791SAndreas Gruenbacher 		drbd_rs_complete_io(device, peer_req->i.sector);
1097b30ab791SAndreas Gruenbacher 		put_ldev(device);
10981d53f09eSLars Ellenberg 	}
1099b411b363SPhilipp Reisner 
1100db830c46SAndreas Gruenbacher 	di = peer_req->digest;
1101b411b363SPhilipp Reisner 
1102db830c46SAndreas Gruenbacher 	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
1103b411b363SPhilipp Reisner 		/* quick hack to try to avoid a race against reconfiguration.
1104b411b363SPhilipp Reisner 		 * a real fix would be much more involved,
1105b411b363SPhilipp Reisner 		 * introducing more locking mechanisms */
1106a6b32bc3SAndreas Gruenbacher 		if (first_peer_device(device)->connection->csums_tfm) {
1107a6b32bc3SAndreas Gruenbacher 			digest_size = crypto_hash_digestsize(first_peer_device(device)->connection->csums_tfm);
11080b0ba1efSAndreas Gruenbacher 			D_ASSERT(device, digest_size == di->digest_size);
1109b411b363SPhilipp Reisner 			digest = kmalloc(digest_size, GFP_NOIO);
1110b411b363SPhilipp Reisner 		}
1111b411b363SPhilipp Reisner 		if (digest) {
111279a3c8d3SAndreas Gruenbacher 			drbd_csum_ee(first_peer_device(device)->connection->csums_tfm, peer_req, digest);
1113b411b363SPhilipp Reisner 			eq = !memcmp(digest, di->digest, digest_size);
1114b411b363SPhilipp Reisner 			kfree(digest);
1115b411b363SPhilipp Reisner 		}
1116b411b363SPhilipp Reisner 
1117b411b363SPhilipp Reisner 		if (eq) {
1118b30ab791SAndreas Gruenbacher 			drbd_set_in_sync(device, peer_req->i.sector, peer_req->i.size);
1119676396d5SLars Ellenberg 			/* rs_same_csums unit is BM_BLOCK_SIZE */
1120b30ab791SAndreas Gruenbacher 			device->rs_same_csum += peer_req->i.size >> BM_BLOCK_SHIFT;
112169a22773SAndreas Gruenbacher 			err = drbd_send_ack(first_peer_device(device), P_RS_IS_IN_SYNC, peer_req);
1122b411b363SPhilipp Reisner 		} else {
1123b30ab791SAndreas Gruenbacher 			inc_rs_pending(device);
1124db830c46SAndreas Gruenbacher 			peer_req->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
1125db830c46SAndreas Gruenbacher 			peer_req->flags &= ~EE_HAS_DIGEST; /* This peer request no longer has a digest pointer */
1126204bba99SPhilipp Reisner 			kfree(di);
112769a22773SAndreas Gruenbacher 			err = drbd_send_block(first_peer_device(device), P_RS_DATA_REPLY, peer_req);
1128b411b363SPhilipp Reisner 		}
1129b411b363SPhilipp Reisner 	} else {
113069a22773SAndreas Gruenbacher 		err = drbd_send_ack(first_peer_device(device), P_NEG_RS_DREPLY, peer_req);
1131b411b363SPhilipp Reisner 		if (__ratelimit(&drbd_ratelimit_state))
1132d0180171SAndreas Gruenbacher 			drbd_err(device, "Sending NegDReply. I guess it gets messy.\n");
1133b411b363SPhilipp Reisner 	}
1134b411b363SPhilipp Reisner 
1135b30ab791SAndreas Gruenbacher 	dec_unacked(device);
1136b30ab791SAndreas Gruenbacher 	move_to_net_ee_or_free(device, peer_req);
1137b411b363SPhilipp Reisner 
113899920dc5SAndreas Gruenbacher 	if (unlikely(err))
1139d0180171SAndreas Gruenbacher 		drbd_err(device, "drbd_send_block/ack() failed\n");
114099920dc5SAndreas Gruenbacher 	return err;
1141b411b363SPhilipp Reisner }
1142b411b363SPhilipp Reisner 
114399920dc5SAndreas Gruenbacher int w_e_end_ov_req(struct drbd_work *w, int cancel)
1144b411b363SPhilipp Reisner {
1145a8cd15baSAndreas Gruenbacher 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
1146a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
1147db830c46SAndreas Gruenbacher 	sector_t sector = peer_req->i.sector;
1148db830c46SAndreas Gruenbacher 	unsigned int size = peer_req->i.size;
1149b411b363SPhilipp Reisner 	int digest_size;
1150b411b363SPhilipp Reisner 	void *digest;
115199920dc5SAndreas Gruenbacher 	int err = 0;
1152b411b363SPhilipp Reisner 
1153b411b363SPhilipp Reisner 	if (unlikely(cancel))
1154b411b363SPhilipp Reisner 		goto out;
1155b411b363SPhilipp Reisner 
1156a6b32bc3SAndreas Gruenbacher 	digest_size = crypto_hash_digestsize(first_peer_device(device)->connection->verify_tfm);
1157b411b363SPhilipp Reisner 	digest = kmalloc(digest_size, GFP_NOIO);
11588f21420eSPhilipp Reisner 	if (!digest) {
115999920dc5SAndreas Gruenbacher 		err = 1;	/* terminate the connection in case the allocation failed */
11608f21420eSPhilipp Reisner 		goto out;
11618f21420eSPhilipp Reisner 	}
11628f21420eSPhilipp Reisner 
1163db830c46SAndreas Gruenbacher 	if (likely(!(peer_req->flags & EE_WAS_ERROR)))
116479a3c8d3SAndreas Gruenbacher 		drbd_csum_ee(first_peer_device(device)->connection->verify_tfm, peer_req, digest);
11658f21420eSPhilipp Reisner 	else
11668f21420eSPhilipp Reisner 		memset(digest, 0, digest_size);
11678f21420eSPhilipp Reisner 
116853ea4331SLars Ellenberg 	/* Free e and pages before send.
116953ea4331SLars Ellenberg 	 * In case we block on congestion, we could otherwise run into
117053ea4331SLars Ellenberg 	 * some distributed deadlock, if the other side blocks on
117153ea4331SLars Ellenberg 	 * congestion as well, because our receiver blocks in
1172c37c8ecfSAndreas Gruenbacher 	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
1173b30ab791SAndreas Gruenbacher 	drbd_free_peer_req(device, peer_req);
1174db830c46SAndreas Gruenbacher 	peer_req = NULL;
1175b30ab791SAndreas Gruenbacher 	inc_rs_pending(device);
117669a22773SAndreas Gruenbacher 	err = drbd_send_drequest_csum(first_peer_device(device), sector, size, digest, digest_size, P_OV_REPLY);
117799920dc5SAndreas Gruenbacher 	if (err)
1178b30ab791SAndreas Gruenbacher 		dec_rs_pending(device);
1179b411b363SPhilipp Reisner 	kfree(digest);
1180b411b363SPhilipp Reisner 
1181b411b363SPhilipp Reisner out:
1182db830c46SAndreas Gruenbacher 	if (peer_req)
1183b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
1184b30ab791SAndreas Gruenbacher 	dec_unacked(device);
118599920dc5SAndreas Gruenbacher 	return err;
1186b411b363SPhilipp Reisner }
1187b411b363SPhilipp Reisner 
1188b30ab791SAndreas Gruenbacher void drbd_ov_out_of_sync_found(struct drbd_device *device, sector_t sector, int size)
1189b411b363SPhilipp Reisner {
1190b30ab791SAndreas Gruenbacher 	if (device->ov_last_oos_start + device->ov_last_oos_size == sector) {
1191b30ab791SAndreas Gruenbacher 		device->ov_last_oos_size += size>>9;
1192b411b363SPhilipp Reisner 	} else {
1193b30ab791SAndreas Gruenbacher 		device->ov_last_oos_start = sector;
1194b30ab791SAndreas Gruenbacher 		device->ov_last_oos_size = size>>9;
1195b411b363SPhilipp Reisner 	}
1196b30ab791SAndreas Gruenbacher 	drbd_set_out_of_sync(device, sector, size);
1197b411b363SPhilipp Reisner }
1198b411b363SPhilipp Reisner 
119999920dc5SAndreas Gruenbacher int w_e_end_ov_reply(struct drbd_work *w, int cancel)
1200b411b363SPhilipp Reisner {
1201a8cd15baSAndreas Gruenbacher 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
1202a8cd15baSAndreas Gruenbacher 	struct drbd_device *device = peer_req->peer_device->device;
1203b411b363SPhilipp Reisner 	struct digest_info *di;
1204b411b363SPhilipp Reisner 	void *digest;
1205db830c46SAndreas Gruenbacher 	sector_t sector = peer_req->i.sector;
1206db830c46SAndreas Gruenbacher 	unsigned int size = peer_req->i.size;
120753ea4331SLars Ellenberg 	int digest_size;
120899920dc5SAndreas Gruenbacher 	int err, eq = 0;
120958ffa580SLars Ellenberg 	bool stop_sector_reached = false;
1210b411b363SPhilipp Reisner 
1211b411b363SPhilipp Reisner 	if (unlikely(cancel)) {
1212b30ab791SAndreas Gruenbacher 		drbd_free_peer_req(device, peer_req);
1213b30ab791SAndreas Gruenbacher 		dec_unacked(device);
121499920dc5SAndreas Gruenbacher 		return 0;
1215b411b363SPhilipp Reisner 	}
1216b411b363SPhilipp Reisner 
1217b411b363SPhilipp Reisner 	/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
1218b411b363SPhilipp Reisner 	 * the resync lru has been cleaned up already */
1219b30ab791SAndreas Gruenbacher 	if (get_ldev(device)) {
1220b30ab791SAndreas Gruenbacher 		drbd_rs_complete_io(device, peer_req->i.sector);
1221b30ab791SAndreas Gruenbacher 		put_ldev(device);
12221d53f09eSLars Ellenberg 	}
1223b411b363SPhilipp Reisner 
1224db830c46SAndreas Gruenbacher 	di = peer_req->digest;
1225b411b363SPhilipp Reisner 
1226db830c46SAndreas Gruenbacher 	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
1227a6b32bc3SAndreas Gruenbacher 		digest_size = crypto_hash_digestsize(first_peer_device(device)->connection->verify_tfm);
1228b411b363SPhilipp Reisner 		digest = kmalloc(digest_size, GFP_NOIO);
1229b411b363SPhilipp Reisner 		if (digest) {
123079a3c8d3SAndreas Gruenbacher 			drbd_csum_ee(first_peer_device(device)->connection->verify_tfm, peer_req, digest);
1231b411b363SPhilipp Reisner 
12320b0ba1efSAndreas Gruenbacher 			D_ASSERT(device, digest_size == di->digest_size);
1233b411b363SPhilipp Reisner 			eq = !memcmp(digest, di->digest, digest_size);
1234b411b363SPhilipp Reisner 			kfree(digest);
1235b411b363SPhilipp Reisner 		}
1236b411b363SPhilipp Reisner 	}
1237b411b363SPhilipp Reisner 
12389676c760SLars Ellenberg 	/* Free peer_req and pages before send.
123953ea4331SLars Ellenberg 	 * In case we block on congestion, we could otherwise run into
124053ea4331SLars Ellenberg 	 * some distributed deadlock, if the other side blocks on
124153ea4331SLars Ellenberg 	 * congestion as well, because our receiver blocks in
1242c37c8ecfSAndreas Gruenbacher 	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
1243b30ab791SAndreas Gruenbacher 	drbd_free_peer_req(device, peer_req);
1244b411b363SPhilipp Reisner 	if (!eq)
1245b30ab791SAndreas Gruenbacher 		drbd_ov_out_of_sync_found(device, sector, size);
1246b411b363SPhilipp Reisner 	else
1247b30ab791SAndreas Gruenbacher 		ov_out_of_sync_print(device);
1248b411b363SPhilipp Reisner 
124969a22773SAndreas Gruenbacher 	err = drbd_send_ack_ex(first_peer_device(device), P_OV_RESULT, sector, size,
1250b411b363SPhilipp Reisner 			       eq ? ID_IN_SYNC : ID_OUT_OF_SYNC);
1251b411b363SPhilipp Reisner 
1252b30ab791SAndreas Gruenbacher 	dec_unacked(device);
1253b411b363SPhilipp Reisner 
1254b30ab791SAndreas Gruenbacher 	--device->ov_left;
1255ea5442afSLars Ellenberg 
1256ea5442afSLars Ellenberg 	/* let's advance progress step marks only for every other megabyte */
1257b30ab791SAndreas Gruenbacher 	if ((device->ov_left & 0x200) == 0x200)
1258b30ab791SAndreas Gruenbacher 		drbd_advance_rs_marks(device, device->ov_left);
1259ea5442afSLars Ellenberg 
1260b30ab791SAndreas Gruenbacher 	stop_sector_reached = verify_can_do_stop_sector(device) &&
1261b30ab791SAndreas Gruenbacher 		(sector + (size>>9)) >= device->ov_stop_sector;
126258ffa580SLars Ellenberg 
1263b30ab791SAndreas Gruenbacher 	if (device->ov_left == 0 || stop_sector_reached) {
1264b30ab791SAndreas Gruenbacher 		ov_out_of_sync_print(device);
1265b30ab791SAndreas Gruenbacher 		drbd_resync_finished(device);
1266b411b363SPhilipp Reisner 	}
1267b411b363SPhilipp Reisner 
126899920dc5SAndreas Gruenbacher 	return err;
1269b411b363SPhilipp Reisner }
1270b411b363SPhilipp Reisner 
1271b6dd1a89SLars Ellenberg /* FIXME
1272b6dd1a89SLars Ellenberg  * We need to track the number of pending barrier acks,
1273b6dd1a89SLars Ellenberg  * and to be able to wait for them.
1274b6dd1a89SLars Ellenberg  * See also comment in drbd_adm_attach before drbd_suspend_io.
1275b6dd1a89SLars Ellenberg  */
1276bde89a9eSAndreas Gruenbacher static int drbd_send_barrier(struct drbd_connection *connection)
1277b411b363SPhilipp Reisner {
12789f5bdc33SAndreas Gruenbacher 	struct p_barrier *p;
1279b6dd1a89SLars Ellenberg 	struct drbd_socket *sock;
1280b411b363SPhilipp Reisner 
1281bde89a9eSAndreas Gruenbacher 	sock = &connection->data;
1282bde89a9eSAndreas Gruenbacher 	p = conn_prepare_command(connection, sock);
12839f5bdc33SAndreas Gruenbacher 	if (!p)
12849f5bdc33SAndreas Gruenbacher 		return -EIO;
1285bde89a9eSAndreas Gruenbacher 	p->barrier = connection->send.current_epoch_nr;
1286b6dd1a89SLars Ellenberg 	p->pad = 0;
1287bde89a9eSAndreas Gruenbacher 	connection->send.current_epoch_writes = 0;
1288b6dd1a89SLars Ellenberg 
1289bde89a9eSAndreas Gruenbacher 	return conn_send_command(connection, sock, P_BARRIER, sizeof(*p), NULL, 0);
1290b411b363SPhilipp Reisner }
1291b411b363SPhilipp Reisner 
129299920dc5SAndreas Gruenbacher int w_send_write_hint(struct drbd_work *w, int cancel)
1293b411b363SPhilipp Reisner {
129484b8c06bSAndreas Gruenbacher 	struct drbd_device *device =
129584b8c06bSAndreas Gruenbacher 		container_of(w, struct drbd_device, unplug_work);
12969f5bdc33SAndreas Gruenbacher 	struct drbd_socket *sock;
12979f5bdc33SAndreas Gruenbacher 
1298b411b363SPhilipp Reisner 	if (cancel)
129999920dc5SAndreas Gruenbacher 		return 0;
1300a6b32bc3SAndreas Gruenbacher 	sock = &first_peer_device(device)->connection->data;
130169a22773SAndreas Gruenbacher 	if (!drbd_prepare_command(first_peer_device(device), sock))
13029f5bdc33SAndreas Gruenbacher 		return -EIO;
130369a22773SAndreas Gruenbacher 	return drbd_send_command(first_peer_device(device), sock, P_UNPLUG_REMOTE, 0, NULL, 0);
1304b411b363SPhilipp Reisner }
1305b411b363SPhilipp Reisner 
1306bde89a9eSAndreas Gruenbacher static void re_init_if_first_write(struct drbd_connection *connection, unsigned int epoch)
13074eb9b3cbSLars Ellenberg {
1308bde89a9eSAndreas Gruenbacher 	if (!connection->send.seen_any_write_yet) {
1309bde89a9eSAndreas Gruenbacher 		connection->send.seen_any_write_yet = true;
1310bde89a9eSAndreas Gruenbacher 		connection->send.current_epoch_nr = epoch;
1311bde89a9eSAndreas Gruenbacher 		connection->send.current_epoch_writes = 0;
13124eb9b3cbSLars Ellenberg 	}
13134eb9b3cbSLars Ellenberg }
13144eb9b3cbSLars Ellenberg 
1315bde89a9eSAndreas Gruenbacher static void maybe_send_barrier(struct drbd_connection *connection, unsigned int epoch)
13164eb9b3cbSLars Ellenberg {
13174eb9b3cbSLars Ellenberg 	/* re-init if first write on this connection */
1318bde89a9eSAndreas Gruenbacher 	if (!connection->send.seen_any_write_yet)
13194eb9b3cbSLars Ellenberg 		return;
1320bde89a9eSAndreas Gruenbacher 	if (connection->send.current_epoch_nr != epoch) {
1321bde89a9eSAndreas Gruenbacher 		if (connection->send.current_epoch_writes)
1322bde89a9eSAndreas Gruenbacher 			drbd_send_barrier(connection);
1323bde89a9eSAndreas Gruenbacher 		connection->send.current_epoch_nr = epoch;
13244eb9b3cbSLars Ellenberg 	}
13254eb9b3cbSLars Ellenberg }
13264eb9b3cbSLars Ellenberg 
13278f7bed77SAndreas Gruenbacher int w_send_out_of_sync(struct drbd_work *w, int cancel)
132873a01a18SPhilipp Reisner {
132973a01a18SPhilipp Reisner 	struct drbd_request *req = container_of(w, struct drbd_request, w);
133084b8c06bSAndreas Gruenbacher 	struct drbd_device *device = req->device;
1331a6b32bc3SAndreas Gruenbacher 	struct drbd_connection *connection = first_peer_device(device)->connection;
133299920dc5SAndreas Gruenbacher 	int err;
133373a01a18SPhilipp Reisner 
133473a01a18SPhilipp Reisner 	if (unlikely(cancel)) {
13358554df1cSAndreas Gruenbacher 		req_mod(req, SEND_CANCELED);
133699920dc5SAndreas Gruenbacher 		return 0;
133773a01a18SPhilipp Reisner 	}
133873a01a18SPhilipp Reisner 
1339bde89a9eSAndreas Gruenbacher 	/* this time, no connection->send.current_epoch_writes++;
1340b6dd1a89SLars Ellenberg 	 * If it was sent, it was the closing barrier for the last
1341b6dd1a89SLars Ellenberg 	 * replicated epoch, before we went into AHEAD mode.
1342b6dd1a89SLars Ellenberg 	 * No more barriers will be sent, until we leave AHEAD mode again. */
1343bde89a9eSAndreas Gruenbacher 	maybe_send_barrier(connection, req->epoch);
1344b6dd1a89SLars Ellenberg 
134569a22773SAndreas Gruenbacher 	err = drbd_send_out_of_sync(first_peer_device(device), req);
13468554df1cSAndreas Gruenbacher 	req_mod(req, OOS_HANDED_TO_NETWORK);
134773a01a18SPhilipp Reisner 
134899920dc5SAndreas Gruenbacher 	return err;
134973a01a18SPhilipp Reisner }
135073a01a18SPhilipp Reisner 
1351b411b363SPhilipp Reisner /**
1352b411b363SPhilipp Reisner  * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request
1353b411b363SPhilipp Reisner  * @w:		work object.
1354b411b363SPhilipp Reisner  * @cancel:	The connection will be closed anyways
1355b411b363SPhilipp Reisner  */
135699920dc5SAndreas Gruenbacher int w_send_dblock(struct drbd_work *w, int cancel)
1357b411b363SPhilipp Reisner {
1358b411b363SPhilipp Reisner 	struct drbd_request *req = container_of(w, struct drbd_request, w);
135984b8c06bSAndreas Gruenbacher 	struct drbd_device *device = req->device;
1360a6b32bc3SAndreas Gruenbacher 	struct drbd_connection *connection = first_peer_device(device)->connection;
136199920dc5SAndreas Gruenbacher 	int err;
1362b411b363SPhilipp Reisner 
1363b411b363SPhilipp Reisner 	if (unlikely(cancel)) {
13648554df1cSAndreas Gruenbacher 		req_mod(req, SEND_CANCELED);
136599920dc5SAndreas Gruenbacher 		return 0;
1366b411b363SPhilipp Reisner 	}
1367b411b363SPhilipp Reisner 
1368bde89a9eSAndreas Gruenbacher 	re_init_if_first_write(connection, req->epoch);
1369bde89a9eSAndreas Gruenbacher 	maybe_send_barrier(connection, req->epoch);
1370bde89a9eSAndreas Gruenbacher 	connection->send.current_epoch_writes++;
1371b6dd1a89SLars Ellenberg 
137269a22773SAndreas Gruenbacher 	err = drbd_send_dblock(first_peer_device(device), req);
137399920dc5SAndreas Gruenbacher 	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
1374b411b363SPhilipp Reisner 
137599920dc5SAndreas Gruenbacher 	return err;
1376b411b363SPhilipp Reisner }
1377b411b363SPhilipp Reisner 
1378b411b363SPhilipp Reisner /**
1379b411b363SPhilipp Reisner  * w_send_read_req() - Worker callback to send a read request (P_DATA_REQUEST) packet
1380b411b363SPhilipp Reisner  * @w:		work object.
1381b411b363SPhilipp Reisner  * @cancel:	The connection will be closed anyways
1382b411b363SPhilipp Reisner  */
138399920dc5SAndreas Gruenbacher int w_send_read_req(struct drbd_work *w, int cancel)
1384b411b363SPhilipp Reisner {
1385b411b363SPhilipp Reisner 	struct drbd_request *req = container_of(w, struct drbd_request, w);
138684b8c06bSAndreas Gruenbacher 	struct drbd_device *device = req->device;
1387a6b32bc3SAndreas Gruenbacher 	struct drbd_connection *connection = first_peer_device(device)->connection;
138899920dc5SAndreas Gruenbacher 	int err;
1389b411b363SPhilipp Reisner 
1390b411b363SPhilipp Reisner 	if (unlikely(cancel)) {
13918554df1cSAndreas Gruenbacher 		req_mod(req, SEND_CANCELED);
139299920dc5SAndreas Gruenbacher 		return 0;
1393b411b363SPhilipp Reisner 	}
1394b411b363SPhilipp Reisner 
1395b6dd1a89SLars Ellenberg 	/* Even read requests may close a write epoch,
1396b6dd1a89SLars Ellenberg 	 * if there was any yet. */
1397bde89a9eSAndreas Gruenbacher 	maybe_send_barrier(connection, req->epoch);
1398b6dd1a89SLars Ellenberg 
139969a22773SAndreas Gruenbacher 	err = drbd_send_drequest(first_peer_device(device), P_DATA_REQUEST, req->i.sector, req->i.size,
1400b411b363SPhilipp Reisner 				 (unsigned long)req);
1401b411b363SPhilipp Reisner 
140299920dc5SAndreas Gruenbacher 	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
1403b411b363SPhilipp Reisner 
140499920dc5SAndreas Gruenbacher 	return err;
1405b411b363SPhilipp Reisner }
1406b411b363SPhilipp Reisner 
140799920dc5SAndreas Gruenbacher int w_restart_disk_io(struct drbd_work *w, int cancel)
1408265be2d0SPhilipp Reisner {
1409265be2d0SPhilipp Reisner 	struct drbd_request *req = container_of(w, struct drbd_request, w);
141084b8c06bSAndreas Gruenbacher 	struct drbd_device *device = req->device;
1411265be2d0SPhilipp Reisner 
14120778286aSPhilipp Reisner 	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
1413b30ab791SAndreas Gruenbacher 		drbd_al_begin_io(device, &req->i, false);
1414265be2d0SPhilipp Reisner 
1415265be2d0SPhilipp Reisner 	drbd_req_make_private_bio(req, req->master_bio);
1416b30ab791SAndreas Gruenbacher 	req->private_bio->bi_bdev = device->ldev->backing_bdev;
1417265be2d0SPhilipp Reisner 	generic_make_request(req->private_bio);
1418265be2d0SPhilipp Reisner 
141999920dc5SAndreas Gruenbacher 	return 0;
1420265be2d0SPhilipp Reisner }
1421265be2d0SPhilipp Reisner 
1422b30ab791SAndreas Gruenbacher static int _drbd_may_sync_now(struct drbd_device *device)
1423b411b363SPhilipp Reisner {
1424b30ab791SAndreas Gruenbacher 	struct drbd_device *odev = device;
142595f8efd0SAndreas Gruenbacher 	int resync_after;
1426b411b363SPhilipp Reisner 
1427b411b363SPhilipp Reisner 	while (1) {
1428a3f8f7dcSLars Ellenberg 		if (!odev->ldev || odev->state.disk == D_DISKLESS)
1429438c8374SPhilipp Reisner 			return 1;
1430daeda1ccSPhilipp Reisner 		rcu_read_lock();
143195f8efd0SAndreas Gruenbacher 		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
1432daeda1ccSPhilipp Reisner 		rcu_read_unlock();
143395f8efd0SAndreas Gruenbacher 		if (resync_after == -1)
1434b411b363SPhilipp Reisner 			return 1;
1435b30ab791SAndreas Gruenbacher 		odev = minor_to_device(resync_after);
1436a3f8f7dcSLars Ellenberg 		if (!odev)
1437841ce241SAndreas Gruenbacher 			return 1;
1438b411b363SPhilipp Reisner 		if ((odev->state.conn >= C_SYNC_SOURCE &&
1439b411b363SPhilipp Reisner 		     odev->state.conn <= C_PAUSED_SYNC_T) ||
1440b411b363SPhilipp Reisner 		    odev->state.aftr_isp || odev->state.peer_isp ||
1441b411b363SPhilipp Reisner 		    odev->state.user_isp)
1442b411b363SPhilipp Reisner 			return 0;
1443b411b363SPhilipp Reisner 	}
1444b411b363SPhilipp Reisner }
1445b411b363SPhilipp Reisner 
1446b411b363SPhilipp Reisner /**
1447b411b363SPhilipp Reisner  * _drbd_pause_after() - Pause resync on all devices that may not resync now
1448b30ab791SAndreas Gruenbacher  * @device:	DRBD device.
1449b411b363SPhilipp Reisner  *
1450b411b363SPhilipp Reisner  * Called from process context only (admin command and after_state_ch).
1451b411b363SPhilipp Reisner  */
1452b30ab791SAndreas Gruenbacher static int _drbd_pause_after(struct drbd_device *device)
1453b411b363SPhilipp Reisner {
145454761697SAndreas Gruenbacher 	struct drbd_device *odev;
1455b411b363SPhilipp Reisner 	int i, rv = 0;
1456b411b363SPhilipp Reisner 
1457695d08faSPhilipp Reisner 	rcu_read_lock();
145805a10ec7SAndreas Gruenbacher 	idr_for_each_entry(&drbd_devices, odev, i) {
1459b411b363SPhilipp Reisner 		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
1460b411b363SPhilipp Reisner 			continue;
1461b411b363SPhilipp Reisner 		if (!_drbd_may_sync_now(odev))
1462b411b363SPhilipp Reisner 			rv |= (__drbd_set_state(_NS(odev, aftr_isp, 1), CS_HARD, NULL)
1463b411b363SPhilipp Reisner 			       != SS_NOTHING_TO_DO);
1464b411b363SPhilipp Reisner 	}
1465695d08faSPhilipp Reisner 	rcu_read_unlock();
1466b411b363SPhilipp Reisner 
1467b411b363SPhilipp Reisner 	return rv;
1468b411b363SPhilipp Reisner }
1469b411b363SPhilipp Reisner 
1470b411b363SPhilipp Reisner /**
1471b411b363SPhilipp Reisner  * _drbd_resume_next() - Resume resync on all devices that may resync now
1472b30ab791SAndreas Gruenbacher  * @device:	DRBD device.
1473b411b363SPhilipp Reisner  *
1474b411b363SPhilipp Reisner  * Called from process context only (admin command and worker).
1475b411b363SPhilipp Reisner  */
1476b30ab791SAndreas Gruenbacher static int _drbd_resume_next(struct drbd_device *device)
1477b411b363SPhilipp Reisner {
147854761697SAndreas Gruenbacher 	struct drbd_device *odev;
1479b411b363SPhilipp Reisner 	int i, rv = 0;
1480b411b363SPhilipp Reisner 
1481695d08faSPhilipp Reisner 	rcu_read_lock();
148205a10ec7SAndreas Gruenbacher 	idr_for_each_entry(&drbd_devices, odev, i) {
1483b411b363SPhilipp Reisner 		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
1484b411b363SPhilipp Reisner 			continue;
1485b411b363SPhilipp Reisner 		if (odev->state.aftr_isp) {
1486b411b363SPhilipp Reisner 			if (_drbd_may_sync_now(odev))
1487b411b363SPhilipp Reisner 				rv |= (__drbd_set_state(_NS(odev, aftr_isp, 0),
1488b411b363SPhilipp Reisner 							CS_HARD, NULL)
1489b411b363SPhilipp Reisner 				       != SS_NOTHING_TO_DO) ;
1490b411b363SPhilipp Reisner 		}
1491b411b363SPhilipp Reisner 	}
1492695d08faSPhilipp Reisner 	rcu_read_unlock();
1493b411b363SPhilipp Reisner 	return rv;
1494b411b363SPhilipp Reisner }
1495b411b363SPhilipp Reisner 
1496b30ab791SAndreas Gruenbacher void resume_next_sg(struct drbd_device *device)
1497b411b363SPhilipp Reisner {
1498b411b363SPhilipp Reisner 	write_lock_irq(&global_state_lock);
1499b30ab791SAndreas Gruenbacher 	_drbd_resume_next(device);
1500b411b363SPhilipp Reisner 	write_unlock_irq(&global_state_lock);
1501b411b363SPhilipp Reisner }
1502b411b363SPhilipp Reisner 
1503b30ab791SAndreas Gruenbacher void suspend_other_sg(struct drbd_device *device)
1504b411b363SPhilipp Reisner {
1505b411b363SPhilipp Reisner 	write_lock_irq(&global_state_lock);
1506b30ab791SAndreas Gruenbacher 	_drbd_pause_after(device);
1507b411b363SPhilipp Reisner 	write_unlock_irq(&global_state_lock);
1508b411b363SPhilipp Reisner }
1509b411b363SPhilipp Reisner 
1510dc97b708SPhilipp Reisner /* caller must hold global_state_lock */
1511b30ab791SAndreas Gruenbacher enum drbd_ret_code drbd_resync_after_valid(struct drbd_device *device, int o_minor)
1512b411b363SPhilipp Reisner {
151354761697SAndreas Gruenbacher 	struct drbd_device *odev;
151495f8efd0SAndreas Gruenbacher 	int resync_after;
1515b411b363SPhilipp Reisner 
1516b411b363SPhilipp Reisner 	if (o_minor == -1)
1517b411b363SPhilipp Reisner 		return NO_ERROR;
1518a3f8f7dcSLars Ellenberg 	if (o_minor < -1 || o_minor > MINORMASK)
151995f8efd0SAndreas Gruenbacher 		return ERR_RESYNC_AFTER;
1520b411b363SPhilipp Reisner 
1521b411b363SPhilipp Reisner 	/* check for loops */
1522b30ab791SAndreas Gruenbacher 	odev = minor_to_device(o_minor);
1523b411b363SPhilipp Reisner 	while (1) {
1524b30ab791SAndreas Gruenbacher 		if (odev == device)
152595f8efd0SAndreas Gruenbacher 			return ERR_RESYNC_AFTER_CYCLE;
1526b411b363SPhilipp Reisner 
1527a3f8f7dcSLars Ellenberg 		/* You are free to depend on diskless, non-existing,
1528a3f8f7dcSLars Ellenberg 		 * or not yet/no longer existing minors.
1529a3f8f7dcSLars Ellenberg 		 * We only reject dependency loops.
1530a3f8f7dcSLars Ellenberg 		 * We cannot follow the dependency chain beyond a detached or
1531a3f8f7dcSLars Ellenberg 		 * missing minor.
1532a3f8f7dcSLars Ellenberg 		 */
1533a3f8f7dcSLars Ellenberg 		if (!odev || !odev->ldev || odev->state.disk == D_DISKLESS)
1534a3f8f7dcSLars Ellenberg 			return NO_ERROR;
1535a3f8f7dcSLars Ellenberg 
1536daeda1ccSPhilipp Reisner 		rcu_read_lock();
153795f8efd0SAndreas Gruenbacher 		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
1538daeda1ccSPhilipp Reisner 		rcu_read_unlock();
1539b411b363SPhilipp Reisner 		/* dependency chain ends here, no cycles. */
154095f8efd0SAndreas Gruenbacher 		if (resync_after == -1)
1541b411b363SPhilipp Reisner 			return NO_ERROR;
1542b411b363SPhilipp Reisner 
1543b411b363SPhilipp Reisner 		/* follow the dependency chain */
1544b30ab791SAndreas Gruenbacher 		odev = minor_to_device(resync_after);
1545b411b363SPhilipp Reisner 	}
1546b411b363SPhilipp Reisner }
1547b411b363SPhilipp Reisner 
1548dc97b708SPhilipp Reisner /* caller must hold global_state_lock */
1549b30ab791SAndreas Gruenbacher void drbd_resync_after_changed(struct drbd_device *device)
1550b411b363SPhilipp Reisner {
1551b411b363SPhilipp Reisner 	int changes;
1552b411b363SPhilipp Reisner 
1553b411b363SPhilipp Reisner 	do {
1554b30ab791SAndreas Gruenbacher 		changes  = _drbd_pause_after(device);
1555b30ab791SAndreas Gruenbacher 		changes |= _drbd_resume_next(device);
1556b411b363SPhilipp Reisner 	} while (changes);
1557b411b363SPhilipp Reisner }
1558b411b363SPhilipp Reisner 
1559b30ab791SAndreas Gruenbacher void drbd_rs_controller_reset(struct drbd_device *device)
15609bd28d3cSLars Ellenberg {
1561813472ceSPhilipp Reisner 	struct fifo_buffer *plan;
1562813472ceSPhilipp Reisner 
1563b30ab791SAndreas Gruenbacher 	atomic_set(&device->rs_sect_in, 0);
1564b30ab791SAndreas Gruenbacher 	atomic_set(&device->rs_sect_ev, 0);
1565b30ab791SAndreas Gruenbacher 	device->rs_in_flight = 0;
1566813472ceSPhilipp Reisner 
1567813472ceSPhilipp Reisner 	/* Updating the RCU protected object in place is necessary since
1568813472ceSPhilipp Reisner 	   this function gets called from atomic context.
1569813472ceSPhilipp Reisner 	   It is valid since all other updates also lead to an completely
1570813472ceSPhilipp Reisner 	   empty fifo */
1571813472ceSPhilipp Reisner 	rcu_read_lock();
1572b30ab791SAndreas Gruenbacher 	plan = rcu_dereference(device->rs_plan_s);
1573813472ceSPhilipp Reisner 	plan->total = 0;
1574813472ceSPhilipp Reisner 	fifo_set(plan, 0);
1575813472ceSPhilipp Reisner 	rcu_read_unlock();
15769bd28d3cSLars Ellenberg }
15779bd28d3cSLars Ellenberg 
15781f04af33SPhilipp Reisner void start_resync_timer_fn(unsigned long data)
15791f04af33SPhilipp Reisner {
1580b30ab791SAndreas Gruenbacher 	struct drbd_device *device = (struct drbd_device *) data;
15811f04af33SPhilipp Reisner 
158284b8c06bSAndreas Gruenbacher 	drbd_queue_work(&first_peer_device(device)->connection->sender_work,
158384b8c06bSAndreas Gruenbacher 			&device->start_resync_work);
15841f04af33SPhilipp Reisner }
15851f04af33SPhilipp Reisner 
158699920dc5SAndreas Gruenbacher int w_start_resync(struct drbd_work *w, int cancel)
15871f04af33SPhilipp Reisner {
158884b8c06bSAndreas Gruenbacher 	struct drbd_device *device =
158984b8c06bSAndreas Gruenbacher 		container_of(w, struct drbd_device, start_resync_work);
159000d56944SPhilipp Reisner 
1591b30ab791SAndreas Gruenbacher 	if (atomic_read(&device->unacked_cnt) || atomic_read(&device->rs_pending_cnt)) {
1592d0180171SAndreas Gruenbacher 		drbd_warn(device, "w_start_resync later...\n");
1593b30ab791SAndreas Gruenbacher 		device->start_resync_timer.expires = jiffies + HZ/10;
1594b30ab791SAndreas Gruenbacher 		add_timer(&device->start_resync_timer);
159599920dc5SAndreas Gruenbacher 		return 0;
15961f04af33SPhilipp Reisner 	}
15971f04af33SPhilipp Reisner 
1598b30ab791SAndreas Gruenbacher 	drbd_start_resync(device, C_SYNC_SOURCE);
1599b30ab791SAndreas Gruenbacher 	clear_bit(AHEAD_TO_SYNC_SOURCE, &device->flags);
160099920dc5SAndreas Gruenbacher 	return 0;
16011f04af33SPhilipp Reisner }
16021f04af33SPhilipp Reisner 
1603b411b363SPhilipp Reisner /**
1604b411b363SPhilipp Reisner  * drbd_start_resync() - Start the resync process
1605b30ab791SAndreas Gruenbacher  * @device:	DRBD device.
1606b411b363SPhilipp Reisner  * @side:	Either C_SYNC_SOURCE or C_SYNC_TARGET
1607b411b363SPhilipp Reisner  *
1608b411b363SPhilipp Reisner  * This function might bring you directly into one of the
1609b411b363SPhilipp Reisner  * C_PAUSED_SYNC_* states.
1610b411b363SPhilipp Reisner  */
1611b30ab791SAndreas Gruenbacher void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
1612b411b363SPhilipp Reisner {
1613b411b363SPhilipp Reisner 	union drbd_state ns;
1614b411b363SPhilipp Reisner 	int r;
1615b411b363SPhilipp Reisner 
1616b30ab791SAndreas Gruenbacher 	if (device->state.conn >= C_SYNC_SOURCE && device->state.conn < C_AHEAD) {
1617d0180171SAndreas Gruenbacher 		drbd_err(device, "Resync already running!\n");
1618b411b363SPhilipp Reisner 		return;
1619b411b363SPhilipp Reisner 	}
1620b411b363SPhilipp Reisner 
1621b30ab791SAndreas Gruenbacher 	if (!test_bit(B_RS_H_DONE, &device->flags)) {
1622b411b363SPhilipp Reisner 		if (side == C_SYNC_TARGET) {
1623b411b363SPhilipp Reisner 			/* Since application IO was locked out during C_WF_BITMAP_T and
1624b411b363SPhilipp Reisner 			   C_WF_SYNC_UUID we are still unmodified. Before going to C_SYNC_TARGET
1625b411b363SPhilipp Reisner 			   we check that we might make the data inconsistent. */
1626b30ab791SAndreas Gruenbacher 			r = drbd_khelper(device, "before-resync-target");
1627b411b363SPhilipp Reisner 			r = (r >> 8) & 0xff;
1628b411b363SPhilipp Reisner 			if (r > 0) {
1629d0180171SAndreas Gruenbacher 				drbd_info(device, "before-resync-target handler returned %d, "
1630b411b363SPhilipp Reisner 					 "dropping connection.\n", r);
1631a6b32bc3SAndreas Gruenbacher 				conn_request_state(first_peer_device(device)->connection, NS(conn, C_DISCONNECTING), CS_HARD);
1632b411b363SPhilipp Reisner 				return;
1633b411b363SPhilipp Reisner 			}
163409b9e797SPhilipp Reisner 		} else /* C_SYNC_SOURCE */ {
1635b30ab791SAndreas Gruenbacher 			r = drbd_khelper(device, "before-resync-source");
163609b9e797SPhilipp Reisner 			r = (r >> 8) & 0xff;
163709b9e797SPhilipp Reisner 			if (r > 0) {
163809b9e797SPhilipp Reisner 				if (r == 3) {
1639d0180171SAndreas Gruenbacher 					drbd_info(device, "before-resync-source handler returned %d, "
164009b9e797SPhilipp Reisner 						 "ignoring. Old userland tools?", r);
164109b9e797SPhilipp Reisner 				} else {
1642d0180171SAndreas Gruenbacher 					drbd_info(device, "before-resync-source handler returned %d, "
164309b9e797SPhilipp Reisner 						 "dropping connection.\n", r);
1644a6b32bc3SAndreas Gruenbacher 					conn_request_state(first_peer_device(device)->connection,
1645a6b32bc3SAndreas Gruenbacher 							   NS(conn, C_DISCONNECTING), CS_HARD);
164609b9e797SPhilipp Reisner 					return;
164709b9e797SPhilipp Reisner 				}
164809b9e797SPhilipp Reisner 			}
1649b411b363SPhilipp Reisner 		}
1650e64a3294SPhilipp Reisner 	}
1651b411b363SPhilipp Reisner 
1652a6b32bc3SAndreas Gruenbacher 	if (current == first_peer_device(device)->connection->worker.task) {
1653dad20554SPhilipp Reisner 		/* The worker should not sleep waiting for state_mutex,
1654e64a3294SPhilipp Reisner 		   that can take long */
1655b30ab791SAndreas Gruenbacher 		if (!mutex_trylock(device->state_mutex)) {
1656b30ab791SAndreas Gruenbacher 			set_bit(B_RS_H_DONE, &device->flags);
1657b30ab791SAndreas Gruenbacher 			device->start_resync_timer.expires = jiffies + HZ/5;
1658b30ab791SAndreas Gruenbacher 			add_timer(&device->start_resync_timer);
1659e64a3294SPhilipp Reisner 			return;
1660e64a3294SPhilipp Reisner 		}
1661e64a3294SPhilipp Reisner 	} else {
1662b30ab791SAndreas Gruenbacher 		mutex_lock(device->state_mutex);
1663e64a3294SPhilipp Reisner 	}
1664b30ab791SAndreas Gruenbacher 	clear_bit(B_RS_H_DONE, &device->flags);
1665b411b363SPhilipp Reisner 
16660cfac5ddSPhilipp Reisner 	write_lock_irq(&global_state_lock);
1667a700471bSPhilipp Reisner 	/* Did some connection breakage or IO error race with us? */
1668b30ab791SAndreas Gruenbacher 	if (device->state.conn < C_CONNECTED
1669b30ab791SAndreas Gruenbacher 	|| !get_ldev_if_state(device, D_NEGOTIATING)) {
16700cfac5ddSPhilipp Reisner 		write_unlock_irq(&global_state_lock);
1671b30ab791SAndreas Gruenbacher 		mutex_unlock(device->state_mutex);
1672b411b363SPhilipp Reisner 		return;
1673b411b363SPhilipp Reisner 	}
1674b411b363SPhilipp Reisner 
1675b30ab791SAndreas Gruenbacher 	ns = drbd_read_state(device);
1676b411b363SPhilipp Reisner 
1677b30ab791SAndreas Gruenbacher 	ns.aftr_isp = !_drbd_may_sync_now(device);
1678b411b363SPhilipp Reisner 
1679b411b363SPhilipp Reisner 	ns.conn = side;
1680b411b363SPhilipp Reisner 
1681b411b363SPhilipp Reisner 	if (side == C_SYNC_TARGET)
1682b411b363SPhilipp Reisner 		ns.disk = D_INCONSISTENT;
1683b411b363SPhilipp Reisner 	else /* side == C_SYNC_SOURCE */
1684b411b363SPhilipp Reisner 		ns.pdsk = D_INCONSISTENT;
1685b411b363SPhilipp Reisner 
1686b30ab791SAndreas Gruenbacher 	r = __drbd_set_state(device, ns, CS_VERBOSE, NULL);
1687b30ab791SAndreas Gruenbacher 	ns = drbd_read_state(device);
1688b411b363SPhilipp Reisner 
1689b411b363SPhilipp Reisner 	if (ns.conn < C_CONNECTED)
1690b411b363SPhilipp Reisner 		r = SS_UNKNOWN_ERROR;
1691b411b363SPhilipp Reisner 
1692b411b363SPhilipp Reisner 	if (r == SS_SUCCESS) {
1693b30ab791SAndreas Gruenbacher 		unsigned long tw = drbd_bm_total_weight(device);
16941d7734a0SLars Ellenberg 		unsigned long now = jiffies;
16951d7734a0SLars Ellenberg 		int i;
16961d7734a0SLars Ellenberg 
1697b30ab791SAndreas Gruenbacher 		device->rs_failed    = 0;
1698b30ab791SAndreas Gruenbacher 		device->rs_paused    = 0;
1699b30ab791SAndreas Gruenbacher 		device->rs_same_csum = 0;
1700b30ab791SAndreas Gruenbacher 		device->rs_last_events = 0;
1701b30ab791SAndreas Gruenbacher 		device->rs_last_sect_ev = 0;
1702b30ab791SAndreas Gruenbacher 		device->rs_total     = tw;
1703b30ab791SAndreas Gruenbacher 		device->rs_start     = now;
17041d7734a0SLars Ellenberg 		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
1705b30ab791SAndreas Gruenbacher 			device->rs_mark_left[i] = tw;
1706b30ab791SAndreas Gruenbacher 			device->rs_mark_time[i] = now;
17071d7734a0SLars Ellenberg 		}
1708b30ab791SAndreas Gruenbacher 		_drbd_pause_after(device);
1709b411b363SPhilipp Reisner 	}
1710b411b363SPhilipp Reisner 	write_unlock_irq(&global_state_lock);
17115a22db89SLars Ellenberg 
17126c922ed5SLars Ellenberg 	if (r == SS_SUCCESS) {
1713328e0f12SPhilipp Reisner 		/* reset rs_last_bcast when a resync or verify is started,
1714328e0f12SPhilipp Reisner 		 * to deal with potential jiffies wrap. */
1715b30ab791SAndreas Gruenbacher 		device->rs_last_bcast = jiffies - HZ;
1716328e0f12SPhilipp Reisner 
1717d0180171SAndreas Gruenbacher 		drbd_info(device, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
17186c922ed5SLars Ellenberg 		     drbd_conn_str(ns.conn),
1719b30ab791SAndreas Gruenbacher 		     (unsigned long) device->rs_total << (BM_BLOCK_SHIFT-10),
1720b30ab791SAndreas Gruenbacher 		     (unsigned long) device->rs_total);
17215a22db89SLars Ellenberg 		if (side == C_SYNC_TARGET)
1722b30ab791SAndreas Gruenbacher 			device->bm_resync_fo = 0;
17235a22db89SLars Ellenberg 
17245a22db89SLars Ellenberg 		/* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
17255a22db89SLars Ellenberg 		 * with w_send_oos, or the sync target will get confused as to
17265a22db89SLars Ellenberg 		 * how much bits to resync.  We cannot do that always, because for an
17275a22db89SLars Ellenberg 		 * empty resync and protocol < 95, we need to do it here, as we call
17285a22db89SLars Ellenberg 		 * drbd_resync_finished from here in that case.
17295a22db89SLars Ellenberg 		 * We drbd_gen_and_send_sync_uuid here for protocol < 96,
17305a22db89SLars Ellenberg 		 * and from after_state_ch otherwise. */
1731a6b32bc3SAndreas Gruenbacher 		if (side == C_SYNC_SOURCE &&
1732a6b32bc3SAndreas Gruenbacher 		    first_peer_device(device)->connection->agreed_pro_version < 96)
173369a22773SAndreas Gruenbacher 			drbd_gen_and_send_sync_uuid(first_peer_device(device));
1734b411b363SPhilipp Reisner 
1735a6b32bc3SAndreas Gruenbacher 		if (first_peer_device(device)->connection->agreed_pro_version < 95 &&
1736a6b32bc3SAndreas Gruenbacher 		    device->rs_total == 0) {
1737af85e8e8SLars Ellenberg 			/* This still has a race (about when exactly the peers
1738af85e8e8SLars Ellenberg 			 * detect connection loss) that can lead to a full sync
1739af85e8e8SLars Ellenberg 			 * on next handshake. In 8.3.9 we fixed this with explicit
1740af85e8e8SLars Ellenberg 			 * resync-finished notifications, but the fix
1741af85e8e8SLars Ellenberg 			 * introduces a protocol change.  Sleeping for some
1742af85e8e8SLars Ellenberg 			 * time longer than the ping interval + timeout on the
1743af85e8e8SLars Ellenberg 			 * SyncSource, to give the SyncTarget the chance to
1744af85e8e8SLars Ellenberg 			 * detect connection loss, then waiting for a ping
1745af85e8e8SLars Ellenberg 			 * response (implicit in drbd_resync_finished) reduces
1746af85e8e8SLars Ellenberg 			 * the race considerably, but does not solve it. */
174744ed167dSPhilipp Reisner 			if (side == C_SYNC_SOURCE) {
174844ed167dSPhilipp Reisner 				struct net_conf *nc;
174944ed167dSPhilipp Reisner 				int timeo;
175044ed167dSPhilipp Reisner 
175144ed167dSPhilipp Reisner 				rcu_read_lock();
1752a6b32bc3SAndreas Gruenbacher 				nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
175344ed167dSPhilipp Reisner 				timeo = nc->ping_int * HZ + nc->ping_timeo * HZ / 9;
175444ed167dSPhilipp Reisner 				rcu_read_unlock();
175544ed167dSPhilipp Reisner 				schedule_timeout_interruptible(timeo);
175644ed167dSPhilipp Reisner 			}
1757b30ab791SAndreas Gruenbacher 			drbd_resync_finished(device);
1758b411b363SPhilipp Reisner 		}
1759b411b363SPhilipp Reisner 
1760b30ab791SAndreas Gruenbacher 		drbd_rs_controller_reset(device);
1761b30ab791SAndreas Gruenbacher 		/* ns.conn may already be != device->state.conn,
1762b411b363SPhilipp Reisner 		 * we may have been paused in between, or become paused until
1763b411b363SPhilipp Reisner 		 * the timer triggers.
1764b411b363SPhilipp Reisner 		 * No matter, that is handled in resync_timer_fn() */
1765b411b363SPhilipp Reisner 		if (ns.conn == C_SYNC_TARGET)
1766b30ab791SAndreas Gruenbacher 			mod_timer(&device->resync_timer, jiffies);
1767b411b363SPhilipp Reisner 
1768b30ab791SAndreas Gruenbacher 		drbd_md_sync(device);
1769b411b363SPhilipp Reisner 	}
1770b30ab791SAndreas Gruenbacher 	put_ldev(device);
1771b30ab791SAndreas Gruenbacher 	mutex_unlock(device->state_mutex);
1772b411b363SPhilipp Reisner }
1773b411b363SPhilipp Reisner 
1774b6dd1a89SLars Ellenberg /* If the resource already closed the current epoch, but we did not
1775b6dd1a89SLars Ellenberg  * (because we have not yet seen new requests), we should send the
1776b6dd1a89SLars Ellenberg  * corresponding barrier now.  Must be checked within the same spinlock
1777b6dd1a89SLars Ellenberg  * that is used to check for new requests. */
1778bde89a9eSAndreas Gruenbacher static bool need_to_send_barrier(struct drbd_connection *connection)
1779b6dd1a89SLars Ellenberg {
1780b6dd1a89SLars Ellenberg 	if (!connection->send.seen_any_write_yet)
1781b6dd1a89SLars Ellenberg 		return false;
1782b6dd1a89SLars Ellenberg 
1783b6dd1a89SLars Ellenberg 	/* Skip barriers that do not contain any writes.
1784b6dd1a89SLars Ellenberg 	 * This may happen during AHEAD mode. */
1785b6dd1a89SLars Ellenberg 	if (!connection->send.current_epoch_writes)
1786b6dd1a89SLars Ellenberg 		return false;
1787b6dd1a89SLars Ellenberg 
1788b6dd1a89SLars Ellenberg 	/* ->req_lock is held when requests are queued on
1789b6dd1a89SLars Ellenberg 	 * connection->sender_work, and put into ->transfer_log.
1790b6dd1a89SLars Ellenberg 	 * It is also held when ->current_tle_nr is increased.
1791b6dd1a89SLars Ellenberg 	 * So either there are already new requests queued,
1792b6dd1a89SLars Ellenberg 	 * and corresponding barriers will be send there.
1793b6dd1a89SLars Ellenberg 	 * Or nothing new is queued yet, so the difference will be 1.
1794b6dd1a89SLars Ellenberg 	 */
1795b6dd1a89SLars Ellenberg 	if (atomic_read(&connection->current_tle_nr) !=
1796b6dd1a89SLars Ellenberg 	    connection->send.current_epoch_nr + 1)
1797b6dd1a89SLars Ellenberg 		return false;
1798b6dd1a89SLars Ellenberg 
1799b6dd1a89SLars Ellenberg 	return true;
1800b6dd1a89SLars Ellenberg }
1801b6dd1a89SLars Ellenberg 
1802a186e478SRashika Kheria static bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
18038c0785a5SLars Ellenberg {
18048c0785a5SLars Ellenberg 	spin_lock_irq(&queue->q_lock);
18058c0785a5SLars Ellenberg 	list_splice_init(&queue->q, work_list);
18068c0785a5SLars Ellenberg 	spin_unlock_irq(&queue->q_lock);
18078c0785a5SLars Ellenberg 	return !list_empty(work_list);
18088c0785a5SLars Ellenberg }
18098c0785a5SLars Ellenberg 
1810a186e478SRashika Kheria static bool dequeue_work_item(struct drbd_work_queue *queue, struct list_head *work_list)
18118c0785a5SLars Ellenberg {
18128c0785a5SLars Ellenberg 	spin_lock_irq(&queue->q_lock);
18138c0785a5SLars Ellenberg 	if (!list_empty(&queue->q))
18148c0785a5SLars Ellenberg 		list_move(queue->q.next, work_list);
18158c0785a5SLars Ellenberg 	spin_unlock_irq(&queue->q_lock);
18168c0785a5SLars Ellenberg 	return !list_empty(work_list);
18178c0785a5SLars Ellenberg }
18188c0785a5SLars Ellenberg 
1819bde89a9eSAndreas Gruenbacher static void wait_for_work(struct drbd_connection *connection, struct list_head *work_list)
1820b6dd1a89SLars Ellenberg {
1821b6dd1a89SLars Ellenberg 	DEFINE_WAIT(wait);
1822b6dd1a89SLars Ellenberg 	struct net_conf *nc;
1823b6dd1a89SLars Ellenberg 	int uncork, cork;
1824b6dd1a89SLars Ellenberg 
1825b6dd1a89SLars Ellenberg 	dequeue_work_item(&connection->sender_work, work_list);
1826b6dd1a89SLars Ellenberg 	if (!list_empty(work_list))
1827b6dd1a89SLars Ellenberg 		return;
1828b6dd1a89SLars Ellenberg 
1829b6dd1a89SLars Ellenberg 	/* Still nothing to do?
1830b6dd1a89SLars Ellenberg 	 * Maybe we still need to close the current epoch,
1831b6dd1a89SLars Ellenberg 	 * even if no new requests are queued yet.
1832b6dd1a89SLars Ellenberg 	 *
1833b6dd1a89SLars Ellenberg 	 * Also, poke TCP, just in case.
1834b6dd1a89SLars Ellenberg 	 * Then wait for new work (or signal). */
1835b6dd1a89SLars Ellenberg 	rcu_read_lock();
1836b6dd1a89SLars Ellenberg 	nc = rcu_dereference(connection->net_conf);
1837b6dd1a89SLars Ellenberg 	uncork = nc ? nc->tcp_cork : 0;
1838b6dd1a89SLars Ellenberg 	rcu_read_unlock();
1839b6dd1a89SLars Ellenberg 	if (uncork) {
1840b6dd1a89SLars Ellenberg 		mutex_lock(&connection->data.mutex);
1841b6dd1a89SLars Ellenberg 		if (connection->data.socket)
1842b6dd1a89SLars Ellenberg 			drbd_tcp_uncork(connection->data.socket);
1843b6dd1a89SLars Ellenberg 		mutex_unlock(&connection->data.mutex);
1844b6dd1a89SLars Ellenberg 	}
1845b6dd1a89SLars Ellenberg 
1846b6dd1a89SLars Ellenberg 	for (;;) {
1847b6dd1a89SLars Ellenberg 		int send_barrier;
1848b6dd1a89SLars Ellenberg 		prepare_to_wait(&connection->sender_work.q_wait, &wait, TASK_INTERRUPTIBLE);
18490500813fSAndreas Gruenbacher 		spin_lock_irq(&connection->resource->req_lock);
1850b6dd1a89SLars Ellenberg 		spin_lock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
1851bc317a9eSLars Ellenberg 		/* dequeue single item only,
1852bc317a9eSLars Ellenberg 		 * we still use drbd_queue_work_front() in some places */
1853bc317a9eSLars Ellenberg 		if (!list_empty(&connection->sender_work.q))
1854bc317a9eSLars Ellenberg 			list_move(connection->sender_work.q.next, work_list);
1855b6dd1a89SLars Ellenberg 		spin_unlock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
1856b6dd1a89SLars Ellenberg 		if (!list_empty(work_list) || signal_pending(current)) {
18570500813fSAndreas Gruenbacher 			spin_unlock_irq(&connection->resource->req_lock);
1858b6dd1a89SLars Ellenberg 			break;
1859b6dd1a89SLars Ellenberg 		}
1860b6dd1a89SLars Ellenberg 		send_barrier = need_to_send_barrier(connection);
18610500813fSAndreas Gruenbacher 		spin_unlock_irq(&connection->resource->req_lock);
1862b6dd1a89SLars Ellenberg 		if (send_barrier) {
1863b6dd1a89SLars Ellenberg 			drbd_send_barrier(connection);
1864b6dd1a89SLars Ellenberg 			connection->send.current_epoch_nr++;
1865b6dd1a89SLars Ellenberg 		}
1866b6dd1a89SLars Ellenberg 		schedule();
1867b6dd1a89SLars Ellenberg 		/* may be woken up for other things but new work, too,
1868b6dd1a89SLars Ellenberg 		 * e.g. if the current epoch got closed.
1869b6dd1a89SLars Ellenberg 		 * In which case we send the barrier above. */
1870b6dd1a89SLars Ellenberg 	}
1871b6dd1a89SLars Ellenberg 	finish_wait(&connection->sender_work.q_wait, &wait);
1872b6dd1a89SLars Ellenberg 
1873b6dd1a89SLars Ellenberg 	/* someone may have changed the config while we have been waiting above. */
1874b6dd1a89SLars Ellenberg 	rcu_read_lock();
1875b6dd1a89SLars Ellenberg 	nc = rcu_dereference(connection->net_conf);
1876b6dd1a89SLars Ellenberg 	cork = nc ? nc->tcp_cork : 0;
1877b6dd1a89SLars Ellenberg 	rcu_read_unlock();
1878b6dd1a89SLars Ellenberg 	mutex_lock(&connection->data.mutex);
1879b6dd1a89SLars Ellenberg 	if (connection->data.socket) {
1880b6dd1a89SLars Ellenberg 		if (cork)
1881b6dd1a89SLars Ellenberg 			drbd_tcp_cork(connection->data.socket);
1882b6dd1a89SLars Ellenberg 		else if (!uncork)
1883b6dd1a89SLars Ellenberg 			drbd_tcp_uncork(connection->data.socket);
1884b6dd1a89SLars Ellenberg 	}
1885b6dd1a89SLars Ellenberg 	mutex_unlock(&connection->data.mutex);
1886b6dd1a89SLars Ellenberg }
1887b6dd1a89SLars Ellenberg 
1888b411b363SPhilipp Reisner int drbd_worker(struct drbd_thread *thi)
1889b411b363SPhilipp Reisner {
1890bde89a9eSAndreas Gruenbacher 	struct drbd_connection *connection = thi->connection;
18916db7e50aSAndreas Gruenbacher 	struct drbd_work *w = NULL;
1892c06ece6bSAndreas Gruenbacher 	struct drbd_peer_device *peer_device;
1893b411b363SPhilipp Reisner 	LIST_HEAD(work_list);
18948c0785a5SLars Ellenberg 	int vnr;
1895b411b363SPhilipp Reisner 
1896e77a0a5cSAndreas Gruenbacher 	while (get_t_state(thi) == RUNNING) {
189780822284SPhilipp Reisner 		drbd_thread_current_set_cpu(thi);
1898b411b363SPhilipp Reisner 
18998c0785a5SLars Ellenberg 		/* as long as we use drbd_queue_work_front(),
19008c0785a5SLars Ellenberg 		 * we may only dequeue single work items here, not batches. */
19018c0785a5SLars Ellenberg 		if (list_empty(&work_list))
1902bde89a9eSAndreas Gruenbacher 			wait_for_work(connection, &work_list);
1903b411b363SPhilipp Reisner 
19048c0785a5SLars Ellenberg 		if (signal_pending(current)) {
1905b411b363SPhilipp Reisner 			flush_signals(current);
190619393e10SPhilipp Reisner 			if (get_t_state(thi) == RUNNING) {
19071ec861ebSAndreas Gruenbacher 				drbd_warn(connection, "Worker got an unexpected signal\n");
1908b411b363SPhilipp Reisner 				continue;
190919393e10SPhilipp Reisner 			}
1910b411b363SPhilipp Reisner 			break;
1911b411b363SPhilipp Reisner 		}
1912b411b363SPhilipp Reisner 
1913e77a0a5cSAndreas Gruenbacher 		if (get_t_state(thi) != RUNNING)
1914b411b363SPhilipp Reisner 			break;
1915b411b363SPhilipp Reisner 
19168c0785a5SLars Ellenberg 		while (!list_empty(&work_list)) {
19176db7e50aSAndreas Gruenbacher 			w = list_first_entry(&work_list, struct drbd_work, list);
19186db7e50aSAndreas Gruenbacher 			list_del_init(&w->list);
19196db7e50aSAndreas Gruenbacher 			if (w->cb(w, connection->cstate < C_WF_REPORT_PARAMS) == 0)
19208c0785a5SLars Ellenberg 				continue;
1921bde89a9eSAndreas Gruenbacher 			if (connection->cstate >= C_WF_REPORT_PARAMS)
1922bde89a9eSAndreas Gruenbacher 				conn_request_state(connection, NS(conn, C_NETWORK_FAILURE), CS_HARD);
1923b411b363SPhilipp Reisner 		}
1924b411b363SPhilipp Reisner 	}
1925b411b363SPhilipp Reisner 
19268c0785a5SLars Ellenberg 	do {
1927b411b363SPhilipp Reisner 		while (!list_empty(&work_list)) {
19286db7e50aSAndreas Gruenbacher 			w = list_first_entry(&work_list, struct drbd_work, list);
19296db7e50aSAndreas Gruenbacher 			list_del_init(&w->list);
19306db7e50aSAndreas Gruenbacher 			w->cb(w, 1);
1931b411b363SPhilipp Reisner 		}
1932bde89a9eSAndreas Gruenbacher 		dequeue_work_batch(&connection->sender_work, &work_list);
19338c0785a5SLars Ellenberg 	} while (!list_empty(&work_list));
1934b411b363SPhilipp Reisner 
1935c141ebdaSPhilipp Reisner 	rcu_read_lock();
1936c06ece6bSAndreas Gruenbacher 	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
1937c06ece6bSAndreas Gruenbacher 		struct drbd_device *device = peer_device->device;
19380b0ba1efSAndreas Gruenbacher 		D_ASSERT(device, device->state.disk == D_DISKLESS && device->state.conn == C_STANDALONE);
1939b30ab791SAndreas Gruenbacher 		kref_get(&device->kref);
1940c141ebdaSPhilipp Reisner 		rcu_read_unlock();
1941b30ab791SAndreas Gruenbacher 		drbd_device_cleanup(device);
194205a10ec7SAndreas Gruenbacher 		kref_put(&device->kref, drbd_destroy_device);
1943c141ebdaSPhilipp Reisner 		rcu_read_lock();
19440e29d163SPhilipp Reisner 	}
1945c141ebdaSPhilipp Reisner 	rcu_read_unlock();
1946b411b363SPhilipp Reisner 
1947b411b363SPhilipp Reisner 	return 0;
1948b411b363SPhilipp Reisner }
1949