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