18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci   drbd.c
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci   This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci   Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
88c2ecf20Sopenharmony_ci   Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
98c2ecf20Sopenharmony_ci   Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci   Thanks to Carter Burden, Bart Grantham and Gennadiy Nerubayev
128c2ecf20Sopenharmony_ci   from Logicworks, Inc. for making SDP replication support possible.
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
218c2ecf20Sopenharmony_ci#include <linux/drbd.h>
228c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
238c2ecf20Sopenharmony_ci#include <asm/types.h>
248c2ecf20Sopenharmony_ci#include <net/sock.h>
258c2ecf20Sopenharmony_ci#include <linux/ctype.h>
268c2ecf20Sopenharmony_ci#include <linux/mutex.h>
278c2ecf20Sopenharmony_ci#include <linux/fs.h>
288c2ecf20Sopenharmony_ci#include <linux/file.h>
298c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
308c2ecf20Sopenharmony_ci#include <linux/init.h>
318c2ecf20Sopenharmony_ci#include <linux/mm.h>
328c2ecf20Sopenharmony_ci#include <linux/memcontrol.h>
338c2ecf20Sopenharmony_ci#include <linux/mm_inline.h>
348c2ecf20Sopenharmony_ci#include <linux/slab.h>
358c2ecf20Sopenharmony_ci#include <linux/random.h>
368c2ecf20Sopenharmony_ci#include <linux/reboot.h>
378c2ecf20Sopenharmony_ci#include <linux/notifier.h>
388c2ecf20Sopenharmony_ci#include <linux/kthread.h>
398c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
408c2ecf20Sopenharmony_ci#define __KERNEL_SYSCALLS__
418c2ecf20Sopenharmony_ci#include <linux/unistd.h>
428c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
438c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include <linux/drbd_limits.h>
468c2ecf20Sopenharmony_ci#include "drbd_int.h"
478c2ecf20Sopenharmony_ci#include "drbd_protocol.h"
488c2ecf20Sopenharmony_ci#include "drbd_req.h" /* only for _req_mod in tl_release and tl_clear */
498c2ecf20Sopenharmony_ci#include "drbd_vli.h"
508c2ecf20Sopenharmony_ci#include "drbd_debugfs.h"
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(drbd_main_mutex);
538c2ecf20Sopenharmony_cistatic int drbd_open(struct block_device *bdev, fmode_t mode);
548c2ecf20Sopenharmony_cistatic void drbd_release(struct gendisk *gd, fmode_t mode);
558c2ecf20Sopenharmony_cistatic void md_sync_timer_fn(struct timer_list *t);
568c2ecf20Sopenharmony_cistatic int w_bitmap_io(struct drbd_work *w, int unused);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ciMODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
598c2ecf20Sopenharmony_ci	      "Lars Ellenberg <lars@linbit.com>");
608c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION);
618c2ecf20Sopenharmony_ciMODULE_VERSION(REL_VERSION);
628c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
638c2ecf20Sopenharmony_ciMODULE_PARM_DESC(minor_count, "Approximate number of drbd devices ("
648c2ecf20Sopenharmony_ci		 __stringify(DRBD_MINOR_COUNT_MIN) "-" __stringify(DRBD_MINOR_COUNT_MAX) ")");
658c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(DRBD_MAJOR);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
688c2ecf20Sopenharmony_ci/* thanks to these macros, if compiled into the kernel (not-module),
698c2ecf20Sopenharmony_ci * these become boot parameters (e.g., drbd.minor_count) */
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci#ifdef CONFIG_DRBD_FAULT_INJECTION
728c2ecf20Sopenharmony_ciint drbd_enable_faults;
738c2ecf20Sopenharmony_ciint drbd_fault_rate;
748c2ecf20Sopenharmony_cistatic int drbd_fault_count;
758c2ecf20Sopenharmony_cistatic int drbd_fault_devs;
768c2ecf20Sopenharmony_ci/* bitmap of enabled faults */
778c2ecf20Sopenharmony_cimodule_param_named(enable_faults, drbd_enable_faults, int, 0664);
788c2ecf20Sopenharmony_ci/* fault rate % value - applies to all enabled faults */
798c2ecf20Sopenharmony_cimodule_param_named(fault_rate, drbd_fault_rate, int, 0664);
808c2ecf20Sopenharmony_ci/* count of faults inserted */
818c2ecf20Sopenharmony_cimodule_param_named(fault_count, drbd_fault_count, int, 0664);
828c2ecf20Sopenharmony_ci/* bitmap of devices to insert faults on */
838c2ecf20Sopenharmony_cimodule_param_named(fault_devs, drbd_fault_devs, int, 0644);
848c2ecf20Sopenharmony_ci#endif
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/* module parameters we can keep static */
878c2ecf20Sopenharmony_cistatic bool drbd_allow_oos; /* allow_open_on_secondary */
888c2ecf20Sopenharmony_cistatic bool drbd_disable_sendpage;
898c2ecf20Sopenharmony_ciMODULE_PARM_DESC(allow_oos, "DONT USE!");
908c2ecf20Sopenharmony_cimodule_param_named(allow_oos, drbd_allow_oos, bool, 0);
918c2ecf20Sopenharmony_cimodule_param_named(disable_sendpage, drbd_disable_sendpage, bool, 0644);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* module parameters we share */
948c2ecf20Sopenharmony_ciint drbd_proc_details; /* Detail level in proc drbd*/
958c2ecf20Sopenharmony_cimodule_param_named(proc_details, drbd_proc_details, int, 0644);
968c2ecf20Sopenharmony_ci/* module parameters shared with defaults */
978c2ecf20Sopenharmony_ciunsigned int drbd_minor_count = DRBD_MINOR_COUNT_DEF;
988c2ecf20Sopenharmony_ci/* Module parameter for setting the user mode helper program
998c2ecf20Sopenharmony_ci * to run. Default is /sbin/drbdadm */
1008c2ecf20Sopenharmony_cichar drbd_usermode_helper[80] = "/sbin/drbdadm";
1018c2ecf20Sopenharmony_cimodule_param_named(minor_count, drbd_minor_count, uint, 0444);
1028c2ecf20Sopenharmony_cimodule_param_string(usermode_helper, drbd_usermode_helper, sizeof(drbd_usermode_helper), 0644);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci/* in 2.6.x, our device mapping and config info contains our virtual gendisks
1058c2ecf20Sopenharmony_ci * as member "struct gendisk *vdisk;"
1068c2ecf20Sopenharmony_ci */
1078c2ecf20Sopenharmony_cistruct idr drbd_devices;
1088c2ecf20Sopenharmony_cistruct list_head drbd_resources;
1098c2ecf20Sopenharmony_cistruct mutex resources_mutex;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistruct kmem_cache *drbd_request_cache;
1128c2ecf20Sopenharmony_cistruct kmem_cache *drbd_ee_cache;	/* peer requests */
1138c2ecf20Sopenharmony_cistruct kmem_cache *drbd_bm_ext_cache;	/* bitmap extents */
1148c2ecf20Sopenharmony_cistruct kmem_cache *drbd_al_ext_cache;	/* activity log extents */
1158c2ecf20Sopenharmony_cimempool_t drbd_request_mempool;
1168c2ecf20Sopenharmony_cimempool_t drbd_ee_mempool;
1178c2ecf20Sopenharmony_cimempool_t drbd_md_io_page_pool;
1188c2ecf20Sopenharmony_cistruct bio_set drbd_md_io_bio_set;
1198c2ecf20Sopenharmony_cistruct bio_set drbd_io_bio_set;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci/* I do not use a standard mempool, because:
1228c2ecf20Sopenharmony_ci   1) I want to hand out the pre-allocated objects first.
1238c2ecf20Sopenharmony_ci   2) I want to be able to interrupt sleeping allocation with a signal.
1248c2ecf20Sopenharmony_ci   Note: This is a single linked list, the next pointer is the private
1258c2ecf20Sopenharmony_ci	 member of struct page.
1268c2ecf20Sopenharmony_ci */
1278c2ecf20Sopenharmony_cistruct page *drbd_pp_pool;
1288c2ecf20Sopenharmony_cispinlock_t   drbd_pp_lock;
1298c2ecf20Sopenharmony_ciint          drbd_pp_vacant;
1308c2ecf20Sopenharmony_ciwait_queue_head_t drbd_pp_wait;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ciDEFINE_RATELIMIT_STATE(drbd_ratelimit_state, 5 * HZ, 5);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic const struct block_device_operations drbd_ops = {
1358c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
1368c2ecf20Sopenharmony_ci	.submit_bio	= drbd_submit_bio,
1378c2ecf20Sopenharmony_ci	.open		= drbd_open,
1388c2ecf20Sopenharmony_ci	.release	= drbd_release,
1398c2ecf20Sopenharmony_ci};
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistruct bio *bio_alloc_drbd(gfp_t gfp_mask)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	struct bio *bio;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	if (!bioset_initialized(&drbd_md_io_bio_set))
1468c2ecf20Sopenharmony_ci		return bio_alloc(gfp_mask, 1);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	bio = bio_alloc_bioset(gfp_mask, 1, &drbd_md_io_bio_set);
1498c2ecf20Sopenharmony_ci	if (!bio)
1508c2ecf20Sopenharmony_ci		return NULL;
1518c2ecf20Sopenharmony_ci	return bio;
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci#ifdef __CHECKER__
1558c2ecf20Sopenharmony_ci/* When checking with sparse, and this is an inline function, sparse will
1568c2ecf20Sopenharmony_ci   give tons of false positives. When this is a real functions sparse works.
1578c2ecf20Sopenharmony_ci */
1588c2ecf20Sopenharmony_ciint _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	int io_allowed;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	atomic_inc(&device->local_cnt);
1638c2ecf20Sopenharmony_ci	io_allowed = (device->state.disk >= mins);
1648c2ecf20Sopenharmony_ci	if (!io_allowed) {
1658c2ecf20Sopenharmony_ci		if (atomic_dec_and_test(&device->local_cnt))
1668c2ecf20Sopenharmony_ci			wake_up(&device->misc_wait);
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci	return io_allowed;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci#endif
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/**
1748c2ecf20Sopenharmony_ci * tl_release() - mark as BARRIER_ACKED all requests in the corresponding transfer log epoch
1758c2ecf20Sopenharmony_ci * @connection:	DRBD connection.
1768c2ecf20Sopenharmony_ci * @barrier_nr:	Expected identifier of the DRBD write barrier packet.
1778c2ecf20Sopenharmony_ci * @set_size:	Expected number of requests before that barrier.
1788c2ecf20Sopenharmony_ci *
1798c2ecf20Sopenharmony_ci * In case the passed barrier_nr or set_size does not match the oldest
1808c2ecf20Sopenharmony_ci * epoch of not yet barrier-acked requests, this function will cause a
1818c2ecf20Sopenharmony_ci * termination of the connection.
1828c2ecf20Sopenharmony_ci */
1838c2ecf20Sopenharmony_civoid tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
1848c2ecf20Sopenharmony_ci		unsigned int set_size)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	struct drbd_request *r;
1878c2ecf20Sopenharmony_ci	struct drbd_request *req = NULL, *tmp = NULL;
1888c2ecf20Sopenharmony_ci	int expect_epoch = 0;
1898c2ecf20Sopenharmony_ci	int expect_size = 0;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	spin_lock_irq(&connection->resource->req_lock);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/* find oldest not yet barrier-acked write request,
1948c2ecf20Sopenharmony_ci	 * count writes in its epoch. */
1958c2ecf20Sopenharmony_ci	list_for_each_entry(r, &connection->transfer_log, tl_requests) {
1968c2ecf20Sopenharmony_ci		const unsigned s = r->rq_state;
1978c2ecf20Sopenharmony_ci		if (!req) {
1988c2ecf20Sopenharmony_ci			if (!(s & RQ_WRITE))
1998c2ecf20Sopenharmony_ci				continue;
2008c2ecf20Sopenharmony_ci			if (!(s & RQ_NET_MASK))
2018c2ecf20Sopenharmony_ci				continue;
2028c2ecf20Sopenharmony_ci			if (s & RQ_NET_DONE)
2038c2ecf20Sopenharmony_ci				continue;
2048c2ecf20Sopenharmony_ci			req = r;
2058c2ecf20Sopenharmony_ci			expect_epoch = req->epoch;
2068c2ecf20Sopenharmony_ci			expect_size ++;
2078c2ecf20Sopenharmony_ci		} else {
2088c2ecf20Sopenharmony_ci			if (r->epoch != expect_epoch)
2098c2ecf20Sopenharmony_ci				break;
2108c2ecf20Sopenharmony_ci			if (!(s & RQ_WRITE))
2118c2ecf20Sopenharmony_ci				continue;
2128c2ecf20Sopenharmony_ci			/* if (s & RQ_DONE): not expected */
2138c2ecf20Sopenharmony_ci			/* if (!(s & RQ_NET_MASK)): not expected */
2148c2ecf20Sopenharmony_ci			expect_size++;
2158c2ecf20Sopenharmony_ci		}
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	/* first some paranoia code */
2198c2ecf20Sopenharmony_ci	if (req == NULL) {
2208c2ecf20Sopenharmony_ci		drbd_err(connection, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
2218c2ecf20Sopenharmony_ci			 barrier_nr);
2228c2ecf20Sopenharmony_ci		goto bail;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci	if (expect_epoch != barrier_nr) {
2258c2ecf20Sopenharmony_ci		drbd_err(connection, "BAD! BarrierAck #%u received, expected #%u!\n",
2268c2ecf20Sopenharmony_ci			 barrier_nr, expect_epoch);
2278c2ecf20Sopenharmony_ci		goto bail;
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (expect_size != set_size) {
2318c2ecf20Sopenharmony_ci		drbd_err(connection, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
2328c2ecf20Sopenharmony_ci			 barrier_nr, set_size, expect_size);
2338c2ecf20Sopenharmony_ci		goto bail;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	/* Clean up list of requests processed during current epoch. */
2378c2ecf20Sopenharmony_ci	/* this extra list walk restart is paranoia,
2388c2ecf20Sopenharmony_ci	 * to catch requests being barrier-acked "unexpectedly".
2398c2ecf20Sopenharmony_ci	 * It usually should find the same req again, or some READ preceding it. */
2408c2ecf20Sopenharmony_ci	list_for_each_entry(req, &connection->transfer_log, tl_requests)
2418c2ecf20Sopenharmony_ci		if (req->epoch == expect_epoch) {
2428c2ecf20Sopenharmony_ci			tmp = req;
2438c2ecf20Sopenharmony_ci			break;
2448c2ecf20Sopenharmony_ci		}
2458c2ecf20Sopenharmony_ci	req = list_prepare_entry(tmp, &connection->transfer_log, tl_requests);
2468c2ecf20Sopenharmony_ci	list_for_each_entry_safe_from(req, r, &connection->transfer_log, tl_requests) {
2478c2ecf20Sopenharmony_ci		if (req->epoch != expect_epoch)
2488c2ecf20Sopenharmony_ci			break;
2498c2ecf20Sopenharmony_ci		_req_mod(req, BARRIER_ACKED);
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci	spin_unlock_irq(&connection->resource->req_lock);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	return;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cibail:
2568c2ecf20Sopenharmony_ci	spin_unlock_irq(&connection->resource->req_lock);
2578c2ecf20Sopenharmony_ci	conn_request_state(connection, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/**
2628c2ecf20Sopenharmony_ci * _tl_restart() - Walks the transfer log, and applies an action to all requests
2638c2ecf20Sopenharmony_ci * @connection:	DRBD connection to operate on.
2648c2ecf20Sopenharmony_ci * @what:       The action/event to perform with all request objects
2658c2ecf20Sopenharmony_ci *
2668c2ecf20Sopenharmony_ci * @what might be one of CONNECTION_LOST_WHILE_PENDING, RESEND, FAIL_FROZEN_DISK_IO,
2678c2ecf20Sopenharmony_ci * RESTART_FROZEN_DISK_IO.
2688c2ecf20Sopenharmony_ci */
2698c2ecf20Sopenharmony_ci/* must hold resource->req_lock */
2708c2ecf20Sopenharmony_civoid _tl_restart(struct drbd_connection *connection, enum drbd_req_event what)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct drbd_request *req, *r;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests)
2758c2ecf20Sopenharmony_ci		_req_mod(req, what);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_civoid tl_restart(struct drbd_connection *connection, enum drbd_req_event what)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	spin_lock_irq(&connection->resource->req_lock);
2818c2ecf20Sopenharmony_ci	_tl_restart(connection, what);
2828c2ecf20Sopenharmony_ci	spin_unlock_irq(&connection->resource->req_lock);
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/**
2868c2ecf20Sopenharmony_ci * tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
2878c2ecf20Sopenharmony_ci * @device:	DRBD device.
2888c2ecf20Sopenharmony_ci *
2898c2ecf20Sopenharmony_ci * This is called after the connection to the peer was lost. The storage covered
2908c2ecf20Sopenharmony_ci * by the requests on the transfer gets marked as our of sync. Called from the
2918c2ecf20Sopenharmony_ci * receiver thread and the worker thread.
2928c2ecf20Sopenharmony_ci */
2938c2ecf20Sopenharmony_civoid tl_clear(struct drbd_connection *connection)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	tl_restart(connection, CONNECTION_LOST_WHILE_PENDING);
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci/**
2998c2ecf20Sopenharmony_ci * tl_abort_disk_io() - Abort disk I/O for all requests for a certain device in the TL
3008c2ecf20Sopenharmony_ci * @device:	DRBD device.
3018c2ecf20Sopenharmony_ci */
3028c2ecf20Sopenharmony_civoid tl_abort_disk_io(struct drbd_device *device)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct drbd_connection *connection = first_peer_device(device)->connection;
3058c2ecf20Sopenharmony_ci	struct drbd_request *req, *r;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	spin_lock_irq(&connection->resource->req_lock);
3088c2ecf20Sopenharmony_ci	list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests) {
3098c2ecf20Sopenharmony_ci		if (!(req->rq_state & RQ_LOCAL_PENDING))
3108c2ecf20Sopenharmony_ci			continue;
3118c2ecf20Sopenharmony_ci		if (req->device != device)
3128c2ecf20Sopenharmony_ci			continue;
3138c2ecf20Sopenharmony_ci		_req_mod(req, ABORT_DISK_IO);
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci	spin_unlock_irq(&connection->resource->req_lock);
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_cistatic int drbd_thread_setup(void *arg)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	struct drbd_thread *thi = (struct drbd_thread *) arg;
3218c2ecf20Sopenharmony_ci	struct drbd_resource *resource = thi->resource;
3228c2ecf20Sopenharmony_ci	unsigned long flags;
3238c2ecf20Sopenharmony_ci	int retval;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	snprintf(current->comm, sizeof(current->comm), "drbd_%c_%s",
3268c2ecf20Sopenharmony_ci		 thi->name[0],
3278c2ecf20Sopenharmony_ci		 resource->name);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	allow_kernel_signal(DRBD_SIGKILL);
3308c2ecf20Sopenharmony_ci	allow_kernel_signal(SIGXCPU);
3318c2ecf20Sopenharmony_cirestart:
3328c2ecf20Sopenharmony_ci	retval = thi->function(thi);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	spin_lock_irqsave(&thi->t_lock, flags);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	/* if the receiver has been "EXITING", the last thing it did
3378c2ecf20Sopenharmony_ci	 * was set the conn state to "StandAlone",
3388c2ecf20Sopenharmony_ci	 * if now a re-connect request comes in, conn state goes C_UNCONNECTED,
3398c2ecf20Sopenharmony_ci	 * and receiver thread will be "started".
3408c2ecf20Sopenharmony_ci	 * drbd_thread_start needs to set "RESTARTING" in that case.
3418c2ecf20Sopenharmony_ci	 * t_state check and assignment needs to be within the same spinlock,
3428c2ecf20Sopenharmony_ci	 * so either thread_start sees EXITING, and can remap to RESTARTING,
3438c2ecf20Sopenharmony_ci	 * or thread_start see NONE, and can proceed as normal.
3448c2ecf20Sopenharmony_ci	 */
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	if (thi->t_state == RESTARTING) {
3478c2ecf20Sopenharmony_ci		drbd_info(resource, "Restarting %s thread\n", thi->name);
3488c2ecf20Sopenharmony_ci		thi->t_state = RUNNING;
3498c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&thi->t_lock, flags);
3508c2ecf20Sopenharmony_ci		goto restart;
3518c2ecf20Sopenharmony_ci	}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	thi->task = NULL;
3548c2ecf20Sopenharmony_ci	thi->t_state = NONE;
3558c2ecf20Sopenharmony_ci	smp_mb();
3568c2ecf20Sopenharmony_ci	complete_all(&thi->stop);
3578c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&thi->t_lock, flags);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	drbd_info(resource, "Terminating %s\n", current->comm);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/* Release mod reference taken when thread was started */
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	if (thi->connection)
3648c2ecf20Sopenharmony_ci		kref_put(&thi->connection->kref, drbd_destroy_connection);
3658c2ecf20Sopenharmony_ci	kref_put(&resource->kref, drbd_destroy_resource);
3668c2ecf20Sopenharmony_ci	module_put(THIS_MODULE);
3678c2ecf20Sopenharmony_ci	return retval;
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_cistatic void drbd_thread_init(struct drbd_resource *resource, struct drbd_thread *thi,
3718c2ecf20Sopenharmony_ci			     int (*func) (struct drbd_thread *), const char *name)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	spin_lock_init(&thi->t_lock);
3748c2ecf20Sopenharmony_ci	thi->task    = NULL;
3758c2ecf20Sopenharmony_ci	thi->t_state = NONE;
3768c2ecf20Sopenharmony_ci	thi->function = func;
3778c2ecf20Sopenharmony_ci	thi->resource = resource;
3788c2ecf20Sopenharmony_ci	thi->connection = NULL;
3798c2ecf20Sopenharmony_ci	thi->name = name;
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ciint drbd_thread_start(struct drbd_thread *thi)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	struct drbd_resource *resource = thi->resource;
3858c2ecf20Sopenharmony_ci	struct task_struct *nt;
3868c2ecf20Sopenharmony_ci	unsigned long flags;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	/* is used from state engine doing drbd_thread_stop_nowait,
3898c2ecf20Sopenharmony_ci	 * while holding the req lock irqsave */
3908c2ecf20Sopenharmony_ci	spin_lock_irqsave(&thi->t_lock, flags);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	switch (thi->t_state) {
3938c2ecf20Sopenharmony_ci	case NONE:
3948c2ecf20Sopenharmony_ci		drbd_info(resource, "Starting %s thread (from %s [%d])\n",
3958c2ecf20Sopenharmony_ci			 thi->name, current->comm, current->pid);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci		/* Get ref on module for thread - this is released when thread exits */
3988c2ecf20Sopenharmony_ci		if (!try_module_get(THIS_MODULE)) {
3998c2ecf20Sopenharmony_ci			drbd_err(resource, "Failed to get module reference in drbd_thread_start\n");
4008c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&thi->t_lock, flags);
4018c2ecf20Sopenharmony_ci			return false;
4028c2ecf20Sopenharmony_ci		}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		kref_get(&resource->kref);
4058c2ecf20Sopenharmony_ci		if (thi->connection)
4068c2ecf20Sopenharmony_ci			kref_get(&thi->connection->kref);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci		init_completion(&thi->stop);
4098c2ecf20Sopenharmony_ci		thi->reset_cpu_mask = 1;
4108c2ecf20Sopenharmony_ci		thi->t_state = RUNNING;
4118c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&thi->t_lock, flags);
4128c2ecf20Sopenharmony_ci		flush_signals(current); /* otherw. may get -ERESTARTNOINTR */
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci		nt = kthread_create(drbd_thread_setup, (void *) thi,
4158c2ecf20Sopenharmony_ci				    "drbd_%c_%s", thi->name[0], thi->resource->name);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci		if (IS_ERR(nt)) {
4188c2ecf20Sopenharmony_ci			drbd_err(resource, "Couldn't start thread\n");
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci			if (thi->connection)
4218c2ecf20Sopenharmony_ci				kref_put(&thi->connection->kref, drbd_destroy_connection);
4228c2ecf20Sopenharmony_ci			kref_put(&resource->kref, drbd_destroy_resource);
4238c2ecf20Sopenharmony_ci			module_put(THIS_MODULE);
4248c2ecf20Sopenharmony_ci			return false;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci		spin_lock_irqsave(&thi->t_lock, flags);
4278c2ecf20Sopenharmony_ci		thi->task = nt;
4288c2ecf20Sopenharmony_ci		thi->t_state = RUNNING;
4298c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&thi->t_lock, flags);
4308c2ecf20Sopenharmony_ci		wake_up_process(nt);
4318c2ecf20Sopenharmony_ci		break;
4328c2ecf20Sopenharmony_ci	case EXITING:
4338c2ecf20Sopenharmony_ci		thi->t_state = RESTARTING;
4348c2ecf20Sopenharmony_ci		drbd_info(resource, "Restarting %s thread (from %s [%d])\n",
4358c2ecf20Sopenharmony_ci				thi->name, current->comm, current->pid);
4368c2ecf20Sopenharmony_ci		fallthrough;
4378c2ecf20Sopenharmony_ci	case RUNNING:
4388c2ecf20Sopenharmony_ci	case RESTARTING:
4398c2ecf20Sopenharmony_ci	default:
4408c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&thi->t_lock, flags);
4418c2ecf20Sopenharmony_ci		break;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	return true;
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_civoid _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
4498c2ecf20Sopenharmony_ci{
4508c2ecf20Sopenharmony_ci	unsigned long flags;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	enum drbd_thread_state ns = restart ? RESTARTING : EXITING;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	/* may be called from state engine, holding the req lock irqsave */
4558c2ecf20Sopenharmony_ci	spin_lock_irqsave(&thi->t_lock, flags);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	if (thi->t_state == NONE) {
4588c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&thi->t_lock, flags);
4598c2ecf20Sopenharmony_ci		if (restart)
4608c2ecf20Sopenharmony_ci			drbd_thread_start(thi);
4618c2ecf20Sopenharmony_ci		return;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (thi->t_state != ns) {
4658c2ecf20Sopenharmony_ci		if (thi->task == NULL) {
4668c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&thi->t_lock, flags);
4678c2ecf20Sopenharmony_ci			return;
4688c2ecf20Sopenharmony_ci		}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		thi->t_state = ns;
4718c2ecf20Sopenharmony_ci		smp_mb();
4728c2ecf20Sopenharmony_ci		init_completion(&thi->stop);
4738c2ecf20Sopenharmony_ci		if (thi->task != current)
4748c2ecf20Sopenharmony_ci			send_sig(DRBD_SIGKILL, thi->task, 1);
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&thi->t_lock, flags);
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	if (wait)
4808c2ecf20Sopenharmony_ci		wait_for_completion(&thi->stop);
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ciint conn_lowest_minor(struct drbd_connection *connection)
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	struct drbd_peer_device *peer_device;
4868c2ecf20Sopenharmony_ci	int vnr = 0, minor = -1;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	rcu_read_lock();
4898c2ecf20Sopenharmony_ci	peer_device = idr_get_next(&connection->peer_devices, &vnr);
4908c2ecf20Sopenharmony_ci	if (peer_device)
4918c2ecf20Sopenharmony_ci		minor = device_to_minor(peer_device->device);
4928c2ecf20Sopenharmony_ci	rcu_read_unlock();
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	return minor;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
4988c2ecf20Sopenharmony_ci/**
4998c2ecf20Sopenharmony_ci * drbd_calc_cpu_mask() - Generate CPU masks, spread over all CPUs
5008c2ecf20Sopenharmony_ci *
5018c2ecf20Sopenharmony_ci * Forces all threads of a resource onto the same CPU. This is beneficial for
5028c2ecf20Sopenharmony_ci * DRBD's performance. May be overwritten by user's configuration.
5038c2ecf20Sopenharmony_ci */
5048c2ecf20Sopenharmony_cistatic void drbd_calc_cpu_mask(cpumask_var_t *cpu_mask)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	unsigned int *resources_per_cpu, min_index = ~0;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	resources_per_cpu = kcalloc(nr_cpu_ids, sizeof(*resources_per_cpu),
5098c2ecf20Sopenharmony_ci				    GFP_KERNEL);
5108c2ecf20Sopenharmony_ci	if (resources_per_cpu) {
5118c2ecf20Sopenharmony_ci		struct drbd_resource *resource;
5128c2ecf20Sopenharmony_ci		unsigned int cpu, min = ~0;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci		rcu_read_lock();
5158c2ecf20Sopenharmony_ci		for_each_resource_rcu(resource, &drbd_resources) {
5168c2ecf20Sopenharmony_ci			for_each_cpu(cpu, resource->cpu_mask)
5178c2ecf20Sopenharmony_ci				resources_per_cpu[cpu]++;
5188c2ecf20Sopenharmony_ci		}
5198c2ecf20Sopenharmony_ci		rcu_read_unlock();
5208c2ecf20Sopenharmony_ci		for_each_online_cpu(cpu) {
5218c2ecf20Sopenharmony_ci			if (resources_per_cpu[cpu] < min) {
5228c2ecf20Sopenharmony_ci				min = resources_per_cpu[cpu];
5238c2ecf20Sopenharmony_ci				min_index = cpu;
5248c2ecf20Sopenharmony_ci			}
5258c2ecf20Sopenharmony_ci		}
5268c2ecf20Sopenharmony_ci		kfree(resources_per_cpu);
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci	if (min_index == ~0) {
5298c2ecf20Sopenharmony_ci		cpumask_setall(*cpu_mask);
5308c2ecf20Sopenharmony_ci		return;
5318c2ecf20Sopenharmony_ci	}
5328c2ecf20Sopenharmony_ci	cpumask_set_cpu(min_index, *cpu_mask);
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci/**
5368c2ecf20Sopenharmony_ci * drbd_thread_current_set_cpu() - modifies the cpu mask of the _current_ thread
5378c2ecf20Sopenharmony_ci * @device:	DRBD device.
5388c2ecf20Sopenharmony_ci * @thi:	drbd_thread object
5398c2ecf20Sopenharmony_ci *
5408c2ecf20Sopenharmony_ci * call in the "main loop" of _all_ threads, no need for any mutex, current won't die
5418c2ecf20Sopenharmony_ci * prematurely.
5428c2ecf20Sopenharmony_ci */
5438c2ecf20Sopenharmony_civoid drbd_thread_current_set_cpu(struct drbd_thread *thi)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct drbd_resource *resource = thi->resource;
5468c2ecf20Sopenharmony_ci	struct task_struct *p = current;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (!thi->reset_cpu_mask)
5498c2ecf20Sopenharmony_ci		return;
5508c2ecf20Sopenharmony_ci	thi->reset_cpu_mask = 0;
5518c2ecf20Sopenharmony_ci	set_cpus_allowed_ptr(p, resource->cpu_mask);
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci#else
5548c2ecf20Sopenharmony_ci#define drbd_calc_cpu_mask(A) ({})
5558c2ecf20Sopenharmony_ci#endif
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci/**
5588c2ecf20Sopenharmony_ci * drbd_header_size  -  size of a packet header
5598c2ecf20Sopenharmony_ci *
5608c2ecf20Sopenharmony_ci * The header size is a multiple of 8, so any payload following the header is
5618c2ecf20Sopenharmony_ci * word aligned on 64-bit architectures.  (The bitmap send and receive code
5628c2ecf20Sopenharmony_ci * relies on this.)
5638c2ecf20Sopenharmony_ci */
5648c2ecf20Sopenharmony_ciunsigned int drbd_header_size(struct drbd_connection *connection)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	if (connection->agreed_pro_version >= 100) {
5678c2ecf20Sopenharmony_ci		BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header100), 8));
5688c2ecf20Sopenharmony_ci		return sizeof(struct p_header100);
5698c2ecf20Sopenharmony_ci	} else {
5708c2ecf20Sopenharmony_ci		BUILD_BUG_ON(sizeof(struct p_header80) !=
5718c2ecf20Sopenharmony_ci			     sizeof(struct p_header95));
5728c2ecf20Sopenharmony_ci		BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header80), 8));
5738c2ecf20Sopenharmony_ci		return sizeof(struct p_header80);
5748c2ecf20Sopenharmony_ci	}
5758c2ecf20Sopenharmony_ci}
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_cistatic unsigned int prepare_header80(struct p_header80 *h, enum drbd_packet cmd, int size)
5788c2ecf20Sopenharmony_ci{
5798c2ecf20Sopenharmony_ci	h->magic   = cpu_to_be32(DRBD_MAGIC);
5808c2ecf20Sopenharmony_ci	h->command = cpu_to_be16(cmd);
5818c2ecf20Sopenharmony_ci	h->length  = cpu_to_be16(size);
5828c2ecf20Sopenharmony_ci	return sizeof(struct p_header80);
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_cistatic unsigned int prepare_header95(struct p_header95 *h, enum drbd_packet cmd, int size)
5868c2ecf20Sopenharmony_ci{
5878c2ecf20Sopenharmony_ci	h->magic   = cpu_to_be16(DRBD_MAGIC_BIG);
5888c2ecf20Sopenharmony_ci	h->command = cpu_to_be16(cmd);
5898c2ecf20Sopenharmony_ci	h->length = cpu_to_be32(size);
5908c2ecf20Sopenharmony_ci	return sizeof(struct p_header95);
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistatic unsigned int prepare_header100(struct p_header100 *h, enum drbd_packet cmd,
5948c2ecf20Sopenharmony_ci				      int size, int vnr)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	h->magic = cpu_to_be32(DRBD_MAGIC_100);
5978c2ecf20Sopenharmony_ci	h->volume = cpu_to_be16(vnr);
5988c2ecf20Sopenharmony_ci	h->command = cpu_to_be16(cmd);
5998c2ecf20Sopenharmony_ci	h->length = cpu_to_be32(size);
6008c2ecf20Sopenharmony_ci	h->pad = 0;
6018c2ecf20Sopenharmony_ci	return sizeof(struct p_header100);
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_cistatic unsigned int prepare_header(struct drbd_connection *connection, int vnr,
6058c2ecf20Sopenharmony_ci				   void *buffer, enum drbd_packet cmd, int size)
6068c2ecf20Sopenharmony_ci{
6078c2ecf20Sopenharmony_ci	if (connection->agreed_pro_version >= 100)
6088c2ecf20Sopenharmony_ci		return prepare_header100(buffer, cmd, size, vnr);
6098c2ecf20Sopenharmony_ci	else if (connection->agreed_pro_version >= 95 &&
6108c2ecf20Sopenharmony_ci		 size > DRBD_MAX_SIZE_H80_PACKET)
6118c2ecf20Sopenharmony_ci		return prepare_header95(buffer, cmd, size);
6128c2ecf20Sopenharmony_ci	else
6138c2ecf20Sopenharmony_ci		return prepare_header80(buffer, cmd, size);
6148c2ecf20Sopenharmony_ci}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_cistatic void *__conn_prepare_command(struct drbd_connection *connection,
6178c2ecf20Sopenharmony_ci				    struct drbd_socket *sock)
6188c2ecf20Sopenharmony_ci{
6198c2ecf20Sopenharmony_ci	if (!sock->socket)
6208c2ecf20Sopenharmony_ci		return NULL;
6218c2ecf20Sopenharmony_ci	return sock->sbuf + drbd_header_size(connection);
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_civoid *conn_prepare_command(struct drbd_connection *connection, struct drbd_socket *sock)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	void *p;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	mutex_lock(&sock->mutex);
6298c2ecf20Sopenharmony_ci	p = __conn_prepare_command(connection, sock);
6308c2ecf20Sopenharmony_ci	if (!p)
6318c2ecf20Sopenharmony_ci		mutex_unlock(&sock->mutex);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	return p;
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_civoid *drbd_prepare_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock)
6378c2ecf20Sopenharmony_ci{
6388c2ecf20Sopenharmony_ci	return conn_prepare_command(peer_device->connection, sock);
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic int __send_command(struct drbd_connection *connection, int vnr,
6428c2ecf20Sopenharmony_ci			  struct drbd_socket *sock, enum drbd_packet cmd,
6438c2ecf20Sopenharmony_ci			  unsigned int header_size, void *data,
6448c2ecf20Sopenharmony_ci			  unsigned int size)
6458c2ecf20Sopenharmony_ci{
6468c2ecf20Sopenharmony_ci	int msg_flags;
6478c2ecf20Sopenharmony_ci	int err;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	/*
6508c2ecf20Sopenharmony_ci	 * Called with @data == NULL and the size of the data blocks in @size
6518c2ecf20Sopenharmony_ci	 * for commands that send data blocks.  For those commands, omit the
6528c2ecf20Sopenharmony_ci	 * MSG_MORE flag: this will increase the likelihood that data blocks
6538c2ecf20Sopenharmony_ci	 * which are page aligned on the sender will end up page aligned on the
6548c2ecf20Sopenharmony_ci	 * receiver.
6558c2ecf20Sopenharmony_ci	 */
6568c2ecf20Sopenharmony_ci	msg_flags = data ? MSG_MORE : 0;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	header_size += prepare_header(connection, vnr, sock->sbuf, cmd,
6598c2ecf20Sopenharmony_ci				      header_size + size);
6608c2ecf20Sopenharmony_ci	err = drbd_send_all(connection, sock->socket, sock->sbuf, header_size,
6618c2ecf20Sopenharmony_ci			    msg_flags);
6628c2ecf20Sopenharmony_ci	if (data && !err)
6638c2ecf20Sopenharmony_ci		err = drbd_send_all(connection, sock->socket, data, size, 0);
6648c2ecf20Sopenharmony_ci	/* DRBD protocol "pings" are latency critical.
6658c2ecf20Sopenharmony_ci	 * This is supposed to trigger tcp_push_pending_frames() */
6668c2ecf20Sopenharmony_ci	if (!err && (cmd == P_PING || cmd == P_PING_ACK))
6678c2ecf20Sopenharmony_ci		tcp_sock_set_nodelay(sock->socket->sk);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	return err;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic int __conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
6738c2ecf20Sopenharmony_ci			       enum drbd_packet cmd, unsigned int header_size,
6748c2ecf20Sopenharmony_ci			       void *data, unsigned int size)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	return __send_command(connection, 0, sock, cmd, header_size, data, size);
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ciint conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
6808c2ecf20Sopenharmony_ci		      enum drbd_packet cmd, unsigned int header_size,
6818c2ecf20Sopenharmony_ci		      void *data, unsigned int size)
6828c2ecf20Sopenharmony_ci{
6838c2ecf20Sopenharmony_ci	int err;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	err = __conn_send_command(connection, sock, cmd, header_size, data, size);
6868c2ecf20Sopenharmony_ci	mutex_unlock(&sock->mutex);
6878c2ecf20Sopenharmony_ci	return err;
6888c2ecf20Sopenharmony_ci}
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ciint drbd_send_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock,
6918c2ecf20Sopenharmony_ci		      enum drbd_packet cmd, unsigned int header_size,
6928c2ecf20Sopenharmony_ci		      void *data, unsigned int size)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	int err;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	err = __send_command(peer_device->connection, peer_device->device->vnr,
6978c2ecf20Sopenharmony_ci			     sock, cmd, header_size, data, size);
6988c2ecf20Sopenharmony_ci	mutex_unlock(&sock->mutex);
6998c2ecf20Sopenharmony_ci	return err;
7008c2ecf20Sopenharmony_ci}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ciint drbd_send_ping(struct drbd_connection *connection)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	sock = &connection->meta;
7078c2ecf20Sopenharmony_ci	if (!conn_prepare_command(connection, sock))
7088c2ecf20Sopenharmony_ci		return -EIO;
7098c2ecf20Sopenharmony_ci	return conn_send_command(connection, sock, P_PING, 0, NULL, 0);
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ciint drbd_send_ping_ack(struct drbd_connection *connection)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	sock = &connection->meta;
7178c2ecf20Sopenharmony_ci	if (!conn_prepare_command(connection, sock))
7188c2ecf20Sopenharmony_ci		return -EIO;
7198c2ecf20Sopenharmony_ci	return conn_send_command(connection, sock, P_PING_ACK, 0, NULL, 0);
7208c2ecf20Sopenharmony_ci}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ciint drbd_send_sync_param(struct drbd_peer_device *peer_device)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
7258c2ecf20Sopenharmony_ci	struct p_rs_param_95 *p;
7268c2ecf20Sopenharmony_ci	int size;
7278c2ecf20Sopenharmony_ci	const int apv = peer_device->connection->agreed_pro_version;
7288c2ecf20Sopenharmony_ci	enum drbd_packet cmd;
7298c2ecf20Sopenharmony_ci	struct net_conf *nc;
7308c2ecf20Sopenharmony_ci	struct disk_conf *dc;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
7338c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
7348c2ecf20Sopenharmony_ci	if (!p)
7358c2ecf20Sopenharmony_ci		return -EIO;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	rcu_read_lock();
7388c2ecf20Sopenharmony_ci	nc = rcu_dereference(peer_device->connection->net_conf);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	size = apv <= 87 ? sizeof(struct p_rs_param)
7418c2ecf20Sopenharmony_ci		: apv == 88 ? sizeof(struct p_rs_param)
7428c2ecf20Sopenharmony_ci			+ strlen(nc->verify_alg) + 1
7438c2ecf20Sopenharmony_ci		: apv <= 94 ? sizeof(struct p_rs_param_89)
7448c2ecf20Sopenharmony_ci		: /* apv >= 95 */ sizeof(struct p_rs_param_95);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	/* initialize verify_alg and csums_alg */
7498c2ecf20Sopenharmony_ci	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	if (get_ldev(peer_device->device)) {
7528c2ecf20Sopenharmony_ci		dc = rcu_dereference(peer_device->device->ldev->disk_conf);
7538c2ecf20Sopenharmony_ci		p->resync_rate = cpu_to_be32(dc->resync_rate);
7548c2ecf20Sopenharmony_ci		p->c_plan_ahead = cpu_to_be32(dc->c_plan_ahead);
7558c2ecf20Sopenharmony_ci		p->c_delay_target = cpu_to_be32(dc->c_delay_target);
7568c2ecf20Sopenharmony_ci		p->c_fill_target = cpu_to_be32(dc->c_fill_target);
7578c2ecf20Sopenharmony_ci		p->c_max_rate = cpu_to_be32(dc->c_max_rate);
7588c2ecf20Sopenharmony_ci		put_ldev(peer_device->device);
7598c2ecf20Sopenharmony_ci	} else {
7608c2ecf20Sopenharmony_ci		p->resync_rate = cpu_to_be32(DRBD_RESYNC_RATE_DEF);
7618c2ecf20Sopenharmony_ci		p->c_plan_ahead = cpu_to_be32(DRBD_C_PLAN_AHEAD_DEF);
7628c2ecf20Sopenharmony_ci		p->c_delay_target = cpu_to_be32(DRBD_C_DELAY_TARGET_DEF);
7638c2ecf20Sopenharmony_ci		p->c_fill_target = cpu_to_be32(DRBD_C_FILL_TARGET_DEF);
7648c2ecf20Sopenharmony_ci		p->c_max_rate = cpu_to_be32(DRBD_C_MAX_RATE_DEF);
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	if (apv >= 88)
7688c2ecf20Sopenharmony_ci		strcpy(p->verify_alg, nc->verify_alg);
7698c2ecf20Sopenharmony_ci	if (apv >= 89)
7708c2ecf20Sopenharmony_ci		strcpy(p->csums_alg, nc->csums_alg);
7718c2ecf20Sopenharmony_ci	rcu_read_unlock();
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, cmd, size, NULL, 0);
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ciint __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cmd)
7778c2ecf20Sopenharmony_ci{
7788c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
7798c2ecf20Sopenharmony_ci	struct p_protocol *p;
7808c2ecf20Sopenharmony_ci	struct net_conf *nc;
7818c2ecf20Sopenharmony_ci	int size, cf;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	sock = &connection->data;
7848c2ecf20Sopenharmony_ci	p = __conn_prepare_command(connection, sock);
7858c2ecf20Sopenharmony_ci	if (!p)
7868c2ecf20Sopenharmony_ci		return -EIO;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	rcu_read_lock();
7898c2ecf20Sopenharmony_ci	nc = rcu_dereference(connection->net_conf);
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	if (nc->tentative && connection->agreed_pro_version < 92) {
7928c2ecf20Sopenharmony_ci		rcu_read_unlock();
7938c2ecf20Sopenharmony_ci		drbd_err(connection, "--dry-run is not supported by peer");
7948c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
7958c2ecf20Sopenharmony_ci	}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	size = sizeof(*p);
7988c2ecf20Sopenharmony_ci	if (connection->agreed_pro_version >= 87)
7998c2ecf20Sopenharmony_ci		size += strlen(nc->integrity_alg) + 1;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	p->protocol      = cpu_to_be32(nc->wire_protocol);
8028c2ecf20Sopenharmony_ci	p->after_sb_0p   = cpu_to_be32(nc->after_sb_0p);
8038c2ecf20Sopenharmony_ci	p->after_sb_1p   = cpu_to_be32(nc->after_sb_1p);
8048c2ecf20Sopenharmony_ci	p->after_sb_2p   = cpu_to_be32(nc->after_sb_2p);
8058c2ecf20Sopenharmony_ci	p->two_primaries = cpu_to_be32(nc->two_primaries);
8068c2ecf20Sopenharmony_ci	cf = 0;
8078c2ecf20Sopenharmony_ci	if (nc->discard_my_data)
8088c2ecf20Sopenharmony_ci		cf |= CF_DISCARD_MY_DATA;
8098c2ecf20Sopenharmony_ci	if (nc->tentative)
8108c2ecf20Sopenharmony_ci		cf |= CF_DRY_RUN;
8118c2ecf20Sopenharmony_ci	p->conn_flags    = cpu_to_be32(cf);
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	if (connection->agreed_pro_version >= 87)
8148c2ecf20Sopenharmony_ci		strcpy(p->integrity_alg, nc->integrity_alg);
8158c2ecf20Sopenharmony_ci	rcu_read_unlock();
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	return __conn_send_command(connection, sock, cmd, size, NULL, 0);
8188c2ecf20Sopenharmony_ci}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ciint drbd_send_protocol(struct drbd_connection *connection)
8218c2ecf20Sopenharmony_ci{
8228c2ecf20Sopenharmony_ci	int err;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	mutex_lock(&connection->data.mutex);
8258c2ecf20Sopenharmony_ci	err = __drbd_send_protocol(connection, P_PROTOCOL);
8268c2ecf20Sopenharmony_ci	mutex_unlock(&connection->data.mutex);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	return err;
8298c2ecf20Sopenharmony_ci}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_cistatic int _drbd_send_uuids(struct drbd_peer_device *peer_device, u64 uuid_flags)
8328c2ecf20Sopenharmony_ci{
8338c2ecf20Sopenharmony_ci	struct drbd_device *device = peer_device->device;
8348c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
8358c2ecf20Sopenharmony_ci	struct p_uuids *p;
8368c2ecf20Sopenharmony_ci	int i;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (!get_ldev_if_state(device, D_NEGOTIATING))
8398c2ecf20Sopenharmony_ci		return 0;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
8428c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
8438c2ecf20Sopenharmony_ci	if (!p) {
8448c2ecf20Sopenharmony_ci		put_ldev(device);
8458c2ecf20Sopenharmony_ci		return -EIO;
8468c2ecf20Sopenharmony_ci	}
8478c2ecf20Sopenharmony_ci	spin_lock_irq(&device->ldev->md.uuid_lock);
8488c2ecf20Sopenharmony_ci	for (i = UI_CURRENT; i < UI_SIZE; i++)
8498c2ecf20Sopenharmony_ci		p->uuid[i] = cpu_to_be64(device->ldev->md.uuid[i]);
8508c2ecf20Sopenharmony_ci	spin_unlock_irq(&device->ldev->md.uuid_lock);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	device->comm_bm_set = drbd_bm_total_weight(device);
8538c2ecf20Sopenharmony_ci	p->uuid[UI_SIZE] = cpu_to_be64(device->comm_bm_set);
8548c2ecf20Sopenharmony_ci	rcu_read_lock();
8558c2ecf20Sopenharmony_ci	uuid_flags |= rcu_dereference(peer_device->connection->net_conf)->discard_my_data ? 1 : 0;
8568c2ecf20Sopenharmony_ci	rcu_read_unlock();
8578c2ecf20Sopenharmony_ci	uuid_flags |= test_bit(CRASHED_PRIMARY, &device->flags) ? 2 : 0;
8588c2ecf20Sopenharmony_ci	uuid_flags |= device->new_state_tmp.disk == D_INCONSISTENT ? 4 : 0;
8598c2ecf20Sopenharmony_ci	p->uuid[UI_FLAGS] = cpu_to_be64(uuid_flags);
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	put_ldev(device);
8628c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_UUIDS, sizeof(*p), NULL, 0);
8638c2ecf20Sopenharmony_ci}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ciint drbd_send_uuids(struct drbd_peer_device *peer_device)
8668c2ecf20Sopenharmony_ci{
8678c2ecf20Sopenharmony_ci	return _drbd_send_uuids(peer_device, 0);
8688c2ecf20Sopenharmony_ci}
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ciint drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *peer_device)
8718c2ecf20Sopenharmony_ci{
8728c2ecf20Sopenharmony_ci	return _drbd_send_uuids(peer_device, 8);
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_civoid drbd_print_uuids(struct drbd_device *device, const char *text)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	if (get_ldev_if_state(device, D_NEGOTIATING)) {
8788c2ecf20Sopenharmony_ci		u64 *uuid = device->ldev->md.uuid;
8798c2ecf20Sopenharmony_ci		drbd_info(device, "%s %016llX:%016llX:%016llX:%016llX\n",
8808c2ecf20Sopenharmony_ci		     text,
8818c2ecf20Sopenharmony_ci		     (unsigned long long)uuid[UI_CURRENT],
8828c2ecf20Sopenharmony_ci		     (unsigned long long)uuid[UI_BITMAP],
8838c2ecf20Sopenharmony_ci		     (unsigned long long)uuid[UI_HISTORY_START],
8848c2ecf20Sopenharmony_ci		     (unsigned long long)uuid[UI_HISTORY_END]);
8858c2ecf20Sopenharmony_ci		put_ldev(device);
8868c2ecf20Sopenharmony_ci	} else {
8878c2ecf20Sopenharmony_ci		drbd_info(device, "%s effective data uuid: %016llX\n",
8888c2ecf20Sopenharmony_ci				text,
8898c2ecf20Sopenharmony_ci				(unsigned long long)device->ed_uuid);
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_civoid drbd_gen_and_send_sync_uuid(struct drbd_peer_device *peer_device)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	struct drbd_device *device = peer_device->device;
8968c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
8978c2ecf20Sopenharmony_ci	struct p_rs_uuid *p;
8988c2ecf20Sopenharmony_ci	u64 uuid;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	D_ASSERT(device, device->state.disk == D_UP_TO_DATE);
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	uuid = device->ldev->md.uuid[UI_BITMAP];
9038c2ecf20Sopenharmony_ci	if (uuid && uuid != UUID_JUST_CREATED)
9048c2ecf20Sopenharmony_ci		uuid = uuid + UUID_NEW_BM_OFFSET;
9058c2ecf20Sopenharmony_ci	else
9068c2ecf20Sopenharmony_ci		get_random_bytes(&uuid, sizeof(u64));
9078c2ecf20Sopenharmony_ci	drbd_uuid_set(device, UI_BITMAP, uuid);
9088c2ecf20Sopenharmony_ci	drbd_print_uuids(device, "updated sync UUID");
9098c2ecf20Sopenharmony_ci	drbd_md_sync(device);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
9128c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
9138c2ecf20Sopenharmony_ci	if (p) {
9148c2ecf20Sopenharmony_ci		p->uuid = cpu_to_be64(uuid);
9158c2ecf20Sopenharmony_ci		drbd_send_command(peer_device, sock, P_SYNC_UUID, sizeof(*p), NULL, 0);
9168c2ecf20Sopenharmony_ci	}
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci/* communicated if (agreed_features & DRBD_FF_WSAME) */
9208c2ecf20Sopenharmony_cistatic void
9218c2ecf20Sopenharmony_ciassign_p_sizes_qlim(struct drbd_device *device, struct p_sizes *p,
9228c2ecf20Sopenharmony_ci					struct request_queue *q)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	if (q) {
9258c2ecf20Sopenharmony_ci		p->qlim->physical_block_size = cpu_to_be32(queue_physical_block_size(q));
9268c2ecf20Sopenharmony_ci		p->qlim->logical_block_size = cpu_to_be32(queue_logical_block_size(q));
9278c2ecf20Sopenharmony_ci		p->qlim->alignment_offset = cpu_to_be32(queue_alignment_offset(q));
9288c2ecf20Sopenharmony_ci		p->qlim->io_min = cpu_to_be32(queue_io_min(q));
9298c2ecf20Sopenharmony_ci		p->qlim->io_opt = cpu_to_be32(queue_io_opt(q));
9308c2ecf20Sopenharmony_ci		p->qlim->discard_enabled = blk_queue_discard(q);
9318c2ecf20Sopenharmony_ci		p->qlim->write_same_capable = !!q->limits.max_write_same_sectors;
9328c2ecf20Sopenharmony_ci	} else {
9338c2ecf20Sopenharmony_ci		q = device->rq_queue;
9348c2ecf20Sopenharmony_ci		p->qlim->physical_block_size = cpu_to_be32(queue_physical_block_size(q));
9358c2ecf20Sopenharmony_ci		p->qlim->logical_block_size = cpu_to_be32(queue_logical_block_size(q));
9368c2ecf20Sopenharmony_ci		p->qlim->alignment_offset = 0;
9378c2ecf20Sopenharmony_ci		p->qlim->io_min = cpu_to_be32(queue_io_min(q));
9388c2ecf20Sopenharmony_ci		p->qlim->io_opt = cpu_to_be32(queue_io_opt(q));
9398c2ecf20Sopenharmony_ci		p->qlim->discard_enabled = 0;
9408c2ecf20Sopenharmony_ci		p->qlim->write_same_capable = 0;
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ciint drbd_send_sizes(struct drbd_peer_device *peer_device, int trigger_reply, enum dds_flags flags)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	struct drbd_device *device = peer_device->device;
9478c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
9488c2ecf20Sopenharmony_ci	struct p_sizes *p;
9498c2ecf20Sopenharmony_ci	sector_t d_size, u_size;
9508c2ecf20Sopenharmony_ci	int q_order_type;
9518c2ecf20Sopenharmony_ci	unsigned int max_bio_size;
9528c2ecf20Sopenharmony_ci	unsigned int packet_size;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
9558c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
9568c2ecf20Sopenharmony_ci	if (!p)
9578c2ecf20Sopenharmony_ci		return -EIO;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	packet_size = sizeof(*p);
9608c2ecf20Sopenharmony_ci	if (peer_device->connection->agreed_features & DRBD_FF_WSAME)
9618c2ecf20Sopenharmony_ci		packet_size += sizeof(p->qlim[0]);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	memset(p, 0, packet_size);
9648c2ecf20Sopenharmony_ci	if (get_ldev_if_state(device, D_NEGOTIATING)) {
9658c2ecf20Sopenharmony_ci		struct request_queue *q = bdev_get_queue(device->ldev->backing_bdev);
9668c2ecf20Sopenharmony_ci		d_size = drbd_get_max_capacity(device->ldev);
9678c2ecf20Sopenharmony_ci		rcu_read_lock();
9688c2ecf20Sopenharmony_ci		u_size = rcu_dereference(device->ldev->disk_conf)->disk_size;
9698c2ecf20Sopenharmony_ci		rcu_read_unlock();
9708c2ecf20Sopenharmony_ci		q_order_type = drbd_queue_order_type(device);
9718c2ecf20Sopenharmony_ci		max_bio_size = queue_max_hw_sectors(q) << 9;
9728c2ecf20Sopenharmony_ci		max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE);
9738c2ecf20Sopenharmony_ci		assign_p_sizes_qlim(device, p, q);
9748c2ecf20Sopenharmony_ci		put_ldev(device);
9758c2ecf20Sopenharmony_ci	} else {
9768c2ecf20Sopenharmony_ci		d_size = 0;
9778c2ecf20Sopenharmony_ci		u_size = 0;
9788c2ecf20Sopenharmony_ci		q_order_type = QUEUE_ORDERED_NONE;
9798c2ecf20Sopenharmony_ci		max_bio_size = DRBD_MAX_BIO_SIZE; /* ... multiple BIOs per peer_request */
9808c2ecf20Sopenharmony_ci		assign_p_sizes_qlim(device, p, NULL);
9818c2ecf20Sopenharmony_ci	}
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	if (peer_device->connection->agreed_pro_version <= 94)
9848c2ecf20Sopenharmony_ci		max_bio_size = min(max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
9858c2ecf20Sopenharmony_ci	else if (peer_device->connection->agreed_pro_version < 100)
9868c2ecf20Sopenharmony_ci		max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE_P95);
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	p->d_size = cpu_to_be64(d_size);
9898c2ecf20Sopenharmony_ci	p->u_size = cpu_to_be64(u_size);
9908c2ecf20Sopenharmony_ci	if (trigger_reply)
9918c2ecf20Sopenharmony_ci		p->c_size = 0;
9928c2ecf20Sopenharmony_ci	else
9938c2ecf20Sopenharmony_ci		p->c_size = cpu_to_be64(get_capacity(device->vdisk));
9948c2ecf20Sopenharmony_ci	p->max_bio_size = cpu_to_be32(max_bio_size);
9958c2ecf20Sopenharmony_ci	p->queue_order_type = cpu_to_be16(q_order_type);
9968c2ecf20Sopenharmony_ci	p->dds_flags = cpu_to_be16(flags);
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_SIZES, packet_size, NULL, 0);
9998c2ecf20Sopenharmony_ci}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci/**
10028c2ecf20Sopenharmony_ci * drbd_send_current_state() - Sends the drbd state to the peer
10038c2ecf20Sopenharmony_ci * @peer_device:	DRBD peer device.
10048c2ecf20Sopenharmony_ci */
10058c2ecf20Sopenharmony_ciint drbd_send_current_state(struct drbd_peer_device *peer_device)
10068c2ecf20Sopenharmony_ci{
10078c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
10088c2ecf20Sopenharmony_ci	struct p_state *p;
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
10118c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
10128c2ecf20Sopenharmony_ci	if (!p)
10138c2ecf20Sopenharmony_ci		return -EIO;
10148c2ecf20Sopenharmony_ci	p->state = cpu_to_be32(peer_device->device->state.i); /* Within the send mutex */
10158c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_STATE, sizeof(*p), NULL, 0);
10168c2ecf20Sopenharmony_ci}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci/**
10198c2ecf20Sopenharmony_ci * drbd_send_state() - After a state change, sends the new state to the peer
10208c2ecf20Sopenharmony_ci * @peer_device:      DRBD peer device.
10218c2ecf20Sopenharmony_ci * @state:     the state to send, not necessarily the current state.
10228c2ecf20Sopenharmony_ci *
10238c2ecf20Sopenharmony_ci * Each state change queues an "after_state_ch" work, which will eventually
10248c2ecf20Sopenharmony_ci * send the resulting new state to the peer. If more state changes happen
10258c2ecf20Sopenharmony_ci * between queuing and processing of the after_state_ch work, we still
10268c2ecf20Sopenharmony_ci * want to send each intermediary state in the order it occurred.
10278c2ecf20Sopenharmony_ci */
10288c2ecf20Sopenharmony_ciint drbd_send_state(struct drbd_peer_device *peer_device, union drbd_state state)
10298c2ecf20Sopenharmony_ci{
10308c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
10318c2ecf20Sopenharmony_ci	struct p_state *p;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
10348c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
10358c2ecf20Sopenharmony_ci	if (!p)
10368c2ecf20Sopenharmony_ci		return -EIO;
10378c2ecf20Sopenharmony_ci	p->state = cpu_to_be32(state.i); /* Within the send mutex */
10388c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_STATE, sizeof(*p), NULL, 0);
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ciint drbd_send_state_req(struct drbd_peer_device *peer_device, union drbd_state mask, union drbd_state val)
10428c2ecf20Sopenharmony_ci{
10438c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
10448c2ecf20Sopenharmony_ci	struct p_req_state *p;
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
10478c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
10488c2ecf20Sopenharmony_ci	if (!p)
10498c2ecf20Sopenharmony_ci		return -EIO;
10508c2ecf20Sopenharmony_ci	p->mask = cpu_to_be32(mask.i);
10518c2ecf20Sopenharmony_ci	p->val = cpu_to_be32(val.i);
10528c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_STATE_CHG_REQ, sizeof(*p), NULL, 0);
10538c2ecf20Sopenharmony_ci}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ciint conn_send_state_req(struct drbd_connection *connection, union drbd_state mask, union drbd_state val)
10568c2ecf20Sopenharmony_ci{
10578c2ecf20Sopenharmony_ci	enum drbd_packet cmd;
10588c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
10598c2ecf20Sopenharmony_ci	struct p_req_state *p;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	cmd = connection->agreed_pro_version < 100 ? P_STATE_CHG_REQ : P_CONN_ST_CHG_REQ;
10628c2ecf20Sopenharmony_ci	sock = &connection->data;
10638c2ecf20Sopenharmony_ci	p = conn_prepare_command(connection, sock);
10648c2ecf20Sopenharmony_ci	if (!p)
10658c2ecf20Sopenharmony_ci		return -EIO;
10668c2ecf20Sopenharmony_ci	p->mask = cpu_to_be32(mask.i);
10678c2ecf20Sopenharmony_ci	p->val = cpu_to_be32(val.i);
10688c2ecf20Sopenharmony_ci	return conn_send_command(connection, sock, cmd, sizeof(*p), NULL, 0);
10698c2ecf20Sopenharmony_ci}
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_civoid drbd_send_sr_reply(struct drbd_peer_device *peer_device, enum drbd_state_rv retcode)
10728c2ecf20Sopenharmony_ci{
10738c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
10748c2ecf20Sopenharmony_ci	struct p_req_state_reply *p;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	sock = &peer_device->connection->meta;
10778c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
10788c2ecf20Sopenharmony_ci	if (p) {
10798c2ecf20Sopenharmony_ci		p->retcode = cpu_to_be32(retcode);
10808c2ecf20Sopenharmony_ci		drbd_send_command(peer_device, sock, P_STATE_CHG_REPLY, sizeof(*p), NULL, 0);
10818c2ecf20Sopenharmony_ci	}
10828c2ecf20Sopenharmony_ci}
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_civoid conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode)
10858c2ecf20Sopenharmony_ci{
10868c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
10878c2ecf20Sopenharmony_ci	struct p_req_state_reply *p;
10888c2ecf20Sopenharmony_ci	enum drbd_packet cmd = connection->agreed_pro_version < 100 ? P_STATE_CHG_REPLY : P_CONN_ST_CHG_REPLY;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	sock = &connection->meta;
10918c2ecf20Sopenharmony_ci	p = conn_prepare_command(connection, sock);
10928c2ecf20Sopenharmony_ci	if (p) {
10938c2ecf20Sopenharmony_ci		p->retcode = cpu_to_be32(retcode);
10948c2ecf20Sopenharmony_ci		conn_send_command(connection, sock, cmd, sizeof(*p), NULL, 0);
10958c2ecf20Sopenharmony_ci	}
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic void dcbp_set_code(struct p_compressed_bm *p, enum drbd_bitmap_code code)
10998c2ecf20Sopenharmony_ci{
11008c2ecf20Sopenharmony_ci	BUG_ON(code & ~0xf);
11018c2ecf20Sopenharmony_ci	p->encoding = (p->encoding & ~0xf) | code;
11028c2ecf20Sopenharmony_ci}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_cistatic void dcbp_set_start(struct p_compressed_bm *p, int set)
11058c2ecf20Sopenharmony_ci{
11068c2ecf20Sopenharmony_ci	p->encoding = (p->encoding & ~0x80) | (set ? 0x80 : 0);
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_cistatic void dcbp_set_pad_bits(struct p_compressed_bm *p, int n)
11108c2ecf20Sopenharmony_ci{
11118c2ecf20Sopenharmony_ci	BUG_ON(n & ~0x7);
11128c2ecf20Sopenharmony_ci	p->encoding = (p->encoding & (~0x7 << 4)) | (n << 4);
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic int fill_bitmap_rle_bits(struct drbd_device *device,
11168c2ecf20Sopenharmony_ci			 struct p_compressed_bm *p,
11178c2ecf20Sopenharmony_ci			 unsigned int size,
11188c2ecf20Sopenharmony_ci			 struct bm_xfer_ctx *c)
11198c2ecf20Sopenharmony_ci{
11208c2ecf20Sopenharmony_ci	struct bitstream bs;
11218c2ecf20Sopenharmony_ci	unsigned long plain_bits;
11228c2ecf20Sopenharmony_ci	unsigned long tmp;
11238c2ecf20Sopenharmony_ci	unsigned long rl;
11248c2ecf20Sopenharmony_ci	unsigned len;
11258c2ecf20Sopenharmony_ci	unsigned toggle;
11268c2ecf20Sopenharmony_ci	int bits, use_rle;
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	/* may we use this feature? */
11298c2ecf20Sopenharmony_ci	rcu_read_lock();
11308c2ecf20Sopenharmony_ci	use_rle = rcu_dereference(first_peer_device(device)->connection->net_conf)->use_rle;
11318c2ecf20Sopenharmony_ci	rcu_read_unlock();
11328c2ecf20Sopenharmony_ci	if (!use_rle || first_peer_device(device)->connection->agreed_pro_version < 90)
11338c2ecf20Sopenharmony_ci		return 0;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	if (c->bit_offset >= c->bm_bits)
11368c2ecf20Sopenharmony_ci		return 0; /* nothing to do. */
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	/* use at most thus many bytes */
11398c2ecf20Sopenharmony_ci	bitstream_init(&bs, p->code, size, 0);
11408c2ecf20Sopenharmony_ci	memset(p->code, 0, size);
11418c2ecf20Sopenharmony_ci	/* plain bits covered in this code string */
11428c2ecf20Sopenharmony_ci	plain_bits = 0;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	/* p->encoding & 0x80 stores whether the first run length is set.
11458c2ecf20Sopenharmony_ci	 * bit offset is implicit.
11468c2ecf20Sopenharmony_ci	 * start with toggle == 2 to be able to tell the first iteration */
11478c2ecf20Sopenharmony_ci	toggle = 2;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	/* see how much plain bits we can stuff into one packet
11508c2ecf20Sopenharmony_ci	 * using RLE and VLI. */
11518c2ecf20Sopenharmony_ci	do {
11528c2ecf20Sopenharmony_ci		tmp = (toggle == 0) ? _drbd_bm_find_next_zero(device, c->bit_offset)
11538c2ecf20Sopenharmony_ci				    : _drbd_bm_find_next(device, c->bit_offset);
11548c2ecf20Sopenharmony_ci		if (tmp == -1UL)
11558c2ecf20Sopenharmony_ci			tmp = c->bm_bits;
11568c2ecf20Sopenharmony_ci		rl = tmp - c->bit_offset;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci		if (toggle == 2) { /* first iteration */
11598c2ecf20Sopenharmony_ci			if (rl == 0) {
11608c2ecf20Sopenharmony_ci				/* the first checked bit was set,
11618c2ecf20Sopenharmony_ci				 * store start value, */
11628c2ecf20Sopenharmony_ci				dcbp_set_start(p, 1);
11638c2ecf20Sopenharmony_ci				/* but skip encoding of zero run length */
11648c2ecf20Sopenharmony_ci				toggle = !toggle;
11658c2ecf20Sopenharmony_ci				continue;
11668c2ecf20Sopenharmony_ci			}
11678c2ecf20Sopenharmony_ci			dcbp_set_start(p, 0);
11688c2ecf20Sopenharmony_ci		}
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci		/* paranoia: catch zero runlength.
11718c2ecf20Sopenharmony_ci		 * can only happen if bitmap is modified while we scan it. */
11728c2ecf20Sopenharmony_ci		if (rl == 0) {
11738c2ecf20Sopenharmony_ci			drbd_err(device, "unexpected zero runlength while encoding bitmap "
11748c2ecf20Sopenharmony_ci			    "t:%u bo:%lu\n", toggle, c->bit_offset);
11758c2ecf20Sopenharmony_ci			return -1;
11768c2ecf20Sopenharmony_ci		}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci		bits = vli_encode_bits(&bs, rl);
11798c2ecf20Sopenharmony_ci		if (bits == -ENOBUFS) /* buffer full */
11808c2ecf20Sopenharmony_ci			break;
11818c2ecf20Sopenharmony_ci		if (bits <= 0) {
11828c2ecf20Sopenharmony_ci			drbd_err(device, "error while encoding bitmap: %d\n", bits);
11838c2ecf20Sopenharmony_ci			return 0;
11848c2ecf20Sopenharmony_ci		}
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci		toggle = !toggle;
11878c2ecf20Sopenharmony_ci		plain_bits += rl;
11888c2ecf20Sopenharmony_ci		c->bit_offset = tmp;
11898c2ecf20Sopenharmony_ci	} while (c->bit_offset < c->bm_bits);
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	len = bs.cur.b - p->code + !!bs.cur.bit;
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	if (plain_bits < (len << 3)) {
11948c2ecf20Sopenharmony_ci		/* incompressible with this method.
11958c2ecf20Sopenharmony_ci		 * we need to rewind both word and bit position. */
11968c2ecf20Sopenharmony_ci		c->bit_offset -= plain_bits;
11978c2ecf20Sopenharmony_ci		bm_xfer_ctx_bit_to_word_offset(c);
11988c2ecf20Sopenharmony_ci		c->bit_offset = c->word_offset * BITS_PER_LONG;
11998c2ecf20Sopenharmony_ci		return 0;
12008c2ecf20Sopenharmony_ci	}
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	/* RLE + VLI was able to compress it just fine.
12038c2ecf20Sopenharmony_ci	 * update c->word_offset. */
12048c2ecf20Sopenharmony_ci	bm_xfer_ctx_bit_to_word_offset(c);
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	/* store pad_bits */
12078c2ecf20Sopenharmony_ci	dcbp_set_pad_bits(p, (8 - bs.cur.bit) & 0x7);
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	return len;
12108c2ecf20Sopenharmony_ci}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci/**
12138c2ecf20Sopenharmony_ci * send_bitmap_rle_or_plain
12148c2ecf20Sopenharmony_ci *
12158c2ecf20Sopenharmony_ci * Return 0 when done, 1 when another iteration is needed, and a negative error
12168c2ecf20Sopenharmony_ci * code upon failure.
12178c2ecf20Sopenharmony_ci */
12188c2ecf20Sopenharmony_cistatic int
12198c2ecf20Sopenharmony_cisend_bitmap_rle_or_plain(struct drbd_device *device, struct bm_xfer_ctx *c)
12208c2ecf20Sopenharmony_ci{
12218c2ecf20Sopenharmony_ci	struct drbd_socket *sock = &first_peer_device(device)->connection->data;
12228c2ecf20Sopenharmony_ci	unsigned int header_size = drbd_header_size(first_peer_device(device)->connection);
12238c2ecf20Sopenharmony_ci	struct p_compressed_bm *p = sock->sbuf + header_size;
12248c2ecf20Sopenharmony_ci	int len, err;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	len = fill_bitmap_rle_bits(device, p,
12278c2ecf20Sopenharmony_ci			DRBD_SOCKET_BUFFER_SIZE - header_size - sizeof(*p), c);
12288c2ecf20Sopenharmony_ci	if (len < 0)
12298c2ecf20Sopenharmony_ci		return -EIO;
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	if (len) {
12328c2ecf20Sopenharmony_ci		dcbp_set_code(p, RLE_VLI_Bits);
12338c2ecf20Sopenharmony_ci		err = __send_command(first_peer_device(device)->connection, device->vnr, sock,
12348c2ecf20Sopenharmony_ci				     P_COMPRESSED_BITMAP, sizeof(*p) + len,
12358c2ecf20Sopenharmony_ci				     NULL, 0);
12368c2ecf20Sopenharmony_ci		c->packets[0]++;
12378c2ecf20Sopenharmony_ci		c->bytes[0] += header_size + sizeof(*p) + len;
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci		if (c->bit_offset >= c->bm_bits)
12408c2ecf20Sopenharmony_ci			len = 0; /* DONE */
12418c2ecf20Sopenharmony_ci	} else {
12428c2ecf20Sopenharmony_ci		/* was not compressible.
12438c2ecf20Sopenharmony_ci		 * send a buffer full of plain text bits instead. */
12448c2ecf20Sopenharmony_ci		unsigned int data_size;
12458c2ecf20Sopenharmony_ci		unsigned long num_words;
12468c2ecf20Sopenharmony_ci		unsigned long *p = sock->sbuf + header_size;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci		data_size = DRBD_SOCKET_BUFFER_SIZE - header_size;
12498c2ecf20Sopenharmony_ci		num_words = min_t(size_t, data_size / sizeof(*p),
12508c2ecf20Sopenharmony_ci				  c->bm_words - c->word_offset);
12518c2ecf20Sopenharmony_ci		len = num_words * sizeof(*p);
12528c2ecf20Sopenharmony_ci		if (len)
12538c2ecf20Sopenharmony_ci			drbd_bm_get_lel(device, c->word_offset, num_words, p);
12548c2ecf20Sopenharmony_ci		err = __send_command(first_peer_device(device)->connection, device->vnr, sock, P_BITMAP, len, NULL, 0);
12558c2ecf20Sopenharmony_ci		c->word_offset += num_words;
12568c2ecf20Sopenharmony_ci		c->bit_offset = c->word_offset * BITS_PER_LONG;
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci		c->packets[1]++;
12598c2ecf20Sopenharmony_ci		c->bytes[1] += header_size + len;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci		if (c->bit_offset > c->bm_bits)
12628c2ecf20Sopenharmony_ci			c->bit_offset = c->bm_bits;
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci	if (!err) {
12658c2ecf20Sopenharmony_ci		if (len == 0) {
12668c2ecf20Sopenharmony_ci			INFO_bm_xfer_stats(device, "send", c);
12678c2ecf20Sopenharmony_ci			return 0;
12688c2ecf20Sopenharmony_ci		} else
12698c2ecf20Sopenharmony_ci			return 1;
12708c2ecf20Sopenharmony_ci	}
12718c2ecf20Sopenharmony_ci	return -EIO;
12728c2ecf20Sopenharmony_ci}
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci/* See the comment at receive_bitmap() */
12758c2ecf20Sopenharmony_cistatic int _drbd_send_bitmap(struct drbd_device *device)
12768c2ecf20Sopenharmony_ci{
12778c2ecf20Sopenharmony_ci	struct bm_xfer_ctx c;
12788c2ecf20Sopenharmony_ci	int err;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	if (!expect(device->bitmap))
12818c2ecf20Sopenharmony_ci		return false;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	if (get_ldev(device)) {
12848c2ecf20Sopenharmony_ci		if (drbd_md_test_flag(device->ldev, MDF_FULL_SYNC)) {
12858c2ecf20Sopenharmony_ci			drbd_info(device, "Writing the whole bitmap, MDF_FullSync was set.\n");
12868c2ecf20Sopenharmony_ci			drbd_bm_set_all(device);
12878c2ecf20Sopenharmony_ci			if (drbd_bm_write(device)) {
12888c2ecf20Sopenharmony_ci				/* write_bm did fail! Leave full sync flag set in Meta P_DATA
12898c2ecf20Sopenharmony_ci				 * but otherwise process as per normal - need to tell other
12908c2ecf20Sopenharmony_ci				 * side that a full resync is required! */
12918c2ecf20Sopenharmony_ci				drbd_err(device, "Failed to write bitmap to disk!\n");
12928c2ecf20Sopenharmony_ci			} else {
12938c2ecf20Sopenharmony_ci				drbd_md_clear_flag(device, MDF_FULL_SYNC);
12948c2ecf20Sopenharmony_ci				drbd_md_sync(device);
12958c2ecf20Sopenharmony_ci			}
12968c2ecf20Sopenharmony_ci		}
12978c2ecf20Sopenharmony_ci		put_ldev(device);
12988c2ecf20Sopenharmony_ci	}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	c = (struct bm_xfer_ctx) {
13018c2ecf20Sopenharmony_ci		.bm_bits = drbd_bm_bits(device),
13028c2ecf20Sopenharmony_ci		.bm_words = drbd_bm_words(device),
13038c2ecf20Sopenharmony_ci	};
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	do {
13068c2ecf20Sopenharmony_ci		err = send_bitmap_rle_or_plain(device, &c);
13078c2ecf20Sopenharmony_ci	} while (err > 0);
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	return err == 0;
13108c2ecf20Sopenharmony_ci}
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ciint drbd_send_bitmap(struct drbd_device *device)
13138c2ecf20Sopenharmony_ci{
13148c2ecf20Sopenharmony_ci	struct drbd_socket *sock = &first_peer_device(device)->connection->data;
13158c2ecf20Sopenharmony_ci	int err = -1;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	mutex_lock(&sock->mutex);
13188c2ecf20Sopenharmony_ci	if (sock->socket)
13198c2ecf20Sopenharmony_ci		err = !_drbd_send_bitmap(device);
13208c2ecf20Sopenharmony_ci	mutex_unlock(&sock->mutex);
13218c2ecf20Sopenharmony_ci	return err;
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_civoid drbd_send_b_ack(struct drbd_connection *connection, u32 barrier_nr, u32 set_size)
13258c2ecf20Sopenharmony_ci{
13268c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
13278c2ecf20Sopenharmony_ci	struct p_barrier_ack *p;
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	if (connection->cstate < C_WF_REPORT_PARAMS)
13308c2ecf20Sopenharmony_ci		return;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	sock = &connection->meta;
13338c2ecf20Sopenharmony_ci	p = conn_prepare_command(connection, sock);
13348c2ecf20Sopenharmony_ci	if (!p)
13358c2ecf20Sopenharmony_ci		return;
13368c2ecf20Sopenharmony_ci	p->barrier = barrier_nr;
13378c2ecf20Sopenharmony_ci	p->set_size = cpu_to_be32(set_size);
13388c2ecf20Sopenharmony_ci	conn_send_command(connection, sock, P_BARRIER_ACK, sizeof(*p), NULL, 0);
13398c2ecf20Sopenharmony_ci}
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci/**
13428c2ecf20Sopenharmony_ci * _drbd_send_ack() - Sends an ack packet
13438c2ecf20Sopenharmony_ci * @device:	DRBD device.
13448c2ecf20Sopenharmony_ci * @cmd:	Packet command code.
13458c2ecf20Sopenharmony_ci * @sector:	sector, needs to be in big endian byte order
13468c2ecf20Sopenharmony_ci * @blksize:	size in byte, needs to be in big endian byte order
13478c2ecf20Sopenharmony_ci * @block_id:	Id, big endian byte order
13488c2ecf20Sopenharmony_ci */
13498c2ecf20Sopenharmony_cistatic int _drbd_send_ack(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
13508c2ecf20Sopenharmony_ci			  u64 sector, u32 blksize, u64 block_id)
13518c2ecf20Sopenharmony_ci{
13528c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
13538c2ecf20Sopenharmony_ci	struct p_block_ack *p;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	if (peer_device->device->state.conn < C_CONNECTED)
13568c2ecf20Sopenharmony_ci		return -EIO;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	sock = &peer_device->connection->meta;
13598c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
13608c2ecf20Sopenharmony_ci	if (!p)
13618c2ecf20Sopenharmony_ci		return -EIO;
13628c2ecf20Sopenharmony_ci	p->sector = sector;
13638c2ecf20Sopenharmony_ci	p->block_id = block_id;
13648c2ecf20Sopenharmony_ci	p->blksize = blksize;
13658c2ecf20Sopenharmony_ci	p->seq_num = cpu_to_be32(atomic_inc_return(&peer_device->device->packet_seq));
13668c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, cmd, sizeof(*p), NULL, 0);
13678c2ecf20Sopenharmony_ci}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci/* dp->sector and dp->block_id already/still in network byte order,
13708c2ecf20Sopenharmony_ci * data_size is payload size according to dp->head,
13718c2ecf20Sopenharmony_ci * and may need to be corrected for digest size. */
13728c2ecf20Sopenharmony_civoid drbd_send_ack_dp(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
13738c2ecf20Sopenharmony_ci		      struct p_data *dp, int data_size)
13748c2ecf20Sopenharmony_ci{
13758c2ecf20Sopenharmony_ci	if (peer_device->connection->peer_integrity_tfm)
13768c2ecf20Sopenharmony_ci		data_size -= crypto_shash_digestsize(peer_device->connection->peer_integrity_tfm);
13778c2ecf20Sopenharmony_ci	_drbd_send_ack(peer_device, cmd, dp->sector, cpu_to_be32(data_size),
13788c2ecf20Sopenharmony_ci		       dp->block_id);
13798c2ecf20Sopenharmony_ci}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_civoid drbd_send_ack_rp(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
13828c2ecf20Sopenharmony_ci		      struct p_block_req *rp)
13838c2ecf20Sopenharmony_ci{
13848c2ecf20Sopenharmony_ci	_drbd_send_ack(peer_device, cmd, rp->sector, rp->blksize, rp->block_id);
13858c2ecf20Sopenharmony_ci}
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci/**
13888c2ecf20Sopenharmony_ci * drbd_send_ack() - Sends an ack packet
13898c2ecf20Sopenharmony_ci * @device:	DRBD device
13908c2ecf20Sopenharmony_ci * @cmd:	packet command code
13918c2ecf20Sopenharmony_ci * @peer_req:	peer request
13928c2ecf20Sopenharmony_ci */
13938c2ecf20Sopenharmony_ciint drbd_send_ack(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
13948c2ecf20Sopenharmony_ci		  struct drbd_peer_request *peer_req)
13958c2ecf20Sopenharmony_ci{
13968c2ecf20Sopenharmony_ci	return _drbd_send_ack(peer_device, cmd,
13978c2ecf20Sopenharmony_ci			      cpu_to_be64(peer_req->i.sector),
13988c2ecf20Sopenharmony_ci			      cpu_to_be32(peer_req->i.size),
13998c2ecf20Sopenharmony_ci			      peer_req->block_id);
14008c2ecf20Sopenharmony_ci}
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci/* This function misuses the block_id field to signal if the blocks
14038c2ecf20Sopenharmony_ci * are is sync or not. */
14048c2ecf20Sopenharmony_ciint drbd_send_ack_ex(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
14058c2ecf20Sopenharmony_ci		     sector_t sector, int blksize, u64 block_id)
14068c2ecf20Sopenharmony_ci{
14078c2ecf20Sopenharmony_ci	return _drbd_send_ack(peer_device, cmd,
14088c2ecf20Sopenharmony_ci			      cpu_to_be64(sector),
14098c2ecf20Sopenharmony_ci			      cpu_to_be32(blksize),
14108c2ecf20Sopenharmony_ci			      cpu_to_be64(block_id));
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ciint drbd_send_rs_deallocated(struct drbd_peer_device *peer_device,
14148c2ecf20Sopenharmony_ci			     struct drbd_peer_request *peer_req)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
14178c2ecf20Sopenharmony_ci	struct p_block_desc *p;
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
14208c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
14218c2ecf20Sopenharmony_ci	if (!p)
14228c2ecf20Sopenharmony_ci		return -EIO;
14238c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(peer_req->i.sector);
14248c2ecf20Sopenharmony_ci	p->blksize = cpu_to_be32(peer_req->i.size);
14258c2ecf20Sopenharmony_ci	p->pad = 0;
14268c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_RS_DEALLOCATED, sizeof(*p), NULL, 0);
14278c2ecf20Sopenharmony_ci}
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ciint drbd_send_drequest(struct drbd_peer_device *peer_device, int cmd,
14308c2ecf20Sopenharmony_ci		       sector_t sector, int size, u64 block_id)
14318c2ecf20Sopenharmony_ci{
14328c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
14338c2ecf20Sopenharmony_ci	struct p_block_req *p;
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
14368c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
14378c2ecf20Sopenharmony_ci	if (!p)
14388c2ecf20Sopenharmony_ci		return -EIO;
14398c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(sector);
14408c2ecf20Sopenharmony_ci	p->block_id = block_id;
14418c2ecf20Sopenharmony_ci	p->blksize = cpu_to_be32(size);
14428c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, cmd, sizeof(*p), NULL, 0);
14438c2ecf20Sopenharmony_ci}
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ciint drbd_send_drequest_csum(struct drbd_peer_device *peer_device, sector_t sector, int size,
14468c2ecf20Sopenharmony_ci			    void *digest, int digest_size, enum drbd_packet cmd)
14478c2ecf20Sopenharmony_ci{
14488c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
14498c2ecf20Sopenharmony_ci	struct p_block_req *p;
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci	/* FIXME: Put the digest into the preallocated socket buffer.  */
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
14548c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
14558c2ecf20Sopenharmony_ci	if (!p)
14568c2ecf20Sopenharmony_ci		return -EIO;
14578c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(sector);
14588c2ecf20Sopenharmony_ci	p->block_id = ID_SYNCER /* unused */;
14598c2ecf20Sopenharmony_ci	p->blksize = cpu_to_be32(size);
14608c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, cmd, sizeof(*p), digest, digest_size);
14618c2ecf20Sopenharmony_ci}
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ciint drbd_send_ov_request(struct drbd_peer_device *peer_device, sector_t sector, int size)
14648c2ecf20Sopenharmony_ci{
14658c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
14668c2ecf20Sopenharmony_ci	struct p_block_req *p;
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
14698c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
14708c2ecf20Sopenharmony_ci	if (!p)
14718c2ecf20Sopenharmony_ci		return -EIO;
14728c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(sector);
14738c2ecf20Sopenharmony_ci	p->block_id = ID_SYNCER /* unused */;
14748c2ecf20Sopenharmony_ci	p->blksize = cpu_to_be32(size);
14758c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_OV_REQUEST, sizeof(*p), NULL, 0);
14768c2ecf20Sopenharmony_ci}
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci/* called on sndtimeo
14798c2ecf20Sopenharmony_ci * returns false if we should retry,
14808c2ecf20Sopenharmony_ci * true if we think connection is dead
14818c2ecf20Sopenharmony_ci */
14828c2ecf20Sopenharmony_cistatic int we_should_drop_the_connection(struct drbd_connection *connection, struct socket *sock)
14838c2ecf20Sopenharmony_ci{
14848c2ecf20Sopenharmony_ci	int drop_it;
14858c2ecf20Sopenharmony_ci	/* long elapsed = (long)(jiffies - device->last_received); */
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	drop_it =   connection->meta.socket == sock
14888c2ecf20Sopenharmony_ci		|| !connection->ack_receiver.task
14898c2ecf20Sopenharmony_ci		|| get_t_state(&connection->ack_receiver) != RUNNING
14908c2ecf20Sopenharmony_ci		|| connection->cstate < C_WF_REPORT_PARAMS;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	if (drop_it)
14938c2ecf20Sopenharmony_ci		return true;
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	drop_it = !--connection->ko_count;
14968c2ecf20Sopenharmony_ci	if (!drop_it) {
14978c2ecf20Sopenharmony_ci		drbd_err(connection, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
14988c2ecf20Sopenharmony_ci			 current->comm, current->pid, connection->ko_count);
14998c2ecf20Sopenharmony_ci		request_ping(connection);
15008c2ecf20Sopenharmony_ci	}
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	return drop_it; /* && (device->state == R_PRIMARY) */;
15038c2ecf20Sopenharmony_ci}
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_cistatic void drbd_update_congested(struct drbd_connection *connection)
15068c2ecf20Sopenharmony_ci{
15078c2ecf20Sopenharmony_ci	struct sock *sk = connection->data.socket->sk;
15088c2ecf20Sopenharmony_ci	if (sk->sk_wmem_queued > sk->sk_sndbuf * 4 / 5)
15098c2ecf20Sopenharmony_ci		set_bit(NET_CONGESTED, &connection->flags);
15108c2ecf20Sopenharmony_ci}
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci/* The idea of sendpage seems to be to put some kind of reference
15138c2ecf20Sopenharmony_ci * to the page into the skb, and to hand it over to the NIC. In
15148c2ecf20Sopenharmony_ci * this process get_page() gets called.
15158c2ecf20Sopenharmony_ci *
15168c2ecf20Sopenharmony_ci * As soon as the page was really sent over the network put_page()
15178c2ecf20Sopenharmony_ci * gets called by some part of the network layer. [ NIC driver? ]
15188c2ecf20Sopenharmony_ci *
15198c2ecf20Sopenharmony_ci * [ get_page() / put_page() increment/decrement the count. If count
15208c2ecf20Sopenharmony_ci *   reaches 0 the page will be freed. ]
15218c2ecf20Sopenharmony_ci *
15228c2ecf20Sopenharmony_ci * This works nicely with pages from FSs.
15238c2ecf20Sopenharmony_ci * But this means that in protocol A we might signal IO completion too early!
15248c2ecf20Sopenharmony_ci *
15258c2ecf20Sopenharmony_ci * In order not to corrupt data during a resync we must make sure
15268c2ecf20Sopenharmony_ci * that we do not reuse our own buffer pages (EEs) to early, therefore
15278c2ecf20Sopenharmony_ci * we have the net_ee list.
15288c2ecf20Sopenharmony_ci *
15298c2ecf20Sopenharmony_ci * XFS seems to have problems, still, it submits pages with page_count == 0!
15308c2ecf20Sopenharmony_ci * As a workaround, we disable sendpage on pages
15318c2ecf20Sopenharmony_ci * with page_count == 0 or PageSlab.
15328c2ecf20Sopenharmony_ci */
15338c2ecf20Sopenharmony_cistatic int _drbd_no_send_page(struct drbd_peer_device *peer_device, struct page *page,
15348c2ecf20Sopenharmony_ci			      int offset, size_t size, unsigned msg_flags)
15358c2ecf20Sopenharmony_ci{
15368c2ecf20Sopenharmony_ci	struct socket *socket;
15378c2ecf20Sopenharmony_ci	void *addr;
15388c2ecf20Sopenharmony_ci	int err;
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	socket = peer_device->connection->data.socket;
15418c2ecf20Sopenharmony_ci	addr = kmap(page) + offset;
15428c2ecf20Sopenharmony_ci	err = drbd_send_all(peer_device->connection, socket, addr, size, msg_flags);
15438c2ecf20Sopenharmony_ci	kunmap(page);
15448c2ecf20Sopenharmony_ci	if (!err)
15458c2ecf20Sopenharmony_ci		peer_device->device->send_cnt += size >> 9;
15468c2ecf20Sopenharmony_ci	return err;
15478c2ecf20Sopenharmony_ci}
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_cistatic int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *page,
15508c2ecf20Sopenharmony_ci		    int offset, size_t size, unsigned msg_flags)
15518c2ecf20Sopenharmony_ci{
15528c2ecf20Sopenharmony_ci	struct socket *socket = peer_device->connection->data.socket;
15538c2ecf20Sopenharmony_ci	int len = size;
15548c2ecf20Sopenharmony_ci	int err = -EIO;
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	/* e.g. XFS meta- & log-data is in slab pages, which have a
15578c2ecf20Sopenharmony_ci	 * page_count of 0 and/or have PageSlab() set.
15588c2ecf20Sopenharmony_ci	 * we cannot use send_page for those, as that does get_page();
15598c2ecf20Sopenharmony_ci	 * put_page(); and would cause either a VM_BUG directly, or
15608c2ecf20Sopenharmony_ci	 * __page_cache_release a page that would actually still be referenced
15618c2ecf20Sopenharmony_ci	 * by someone, leading to some obscure delayed Oops somewhere else. */
15628c2ecf20Sopenharmony_ci	if (drbd_disable_sendpage || !sendpage_ok(page))
15638c2ecf20Sopenharmony_ci		return _drbd_no_send_page(peer_device, page, offset, size, msg_flags);
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci	msg_flags |= MSG_NOSIGNAL;
15668c2ecf20Sopenharmony_ci	drbd_update_congested(peer_device->connection);
15678c2ecf20Sopenharmony_ci	do {
15688c2ecf20Sopenharmony_ci		int sent;
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci		sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
15718c2ecf20Sopenharmony_ci		if (sent <= 0) {
15728c2ecf20Sopenharmony_ci			if (sent == -EAGAIN) {
15738c2ecf20Sopenharmony_ci				if (we_should_drop_the_connection(peer_device->connection, socket))
15748c2ecf20Sopenharmony_ci					break;
15758c2ecf20Sopenharmony_ci				continue;
15768c2ecf20Sopenharmony_ci			}
15778c2ecf20Sopenharmony_ci			drbd_warn(peer_device->device, "%s: size=%d len=%d sent=%d\n",
15788c2ecf20Sopenharmony_ci			     __func__, (int)size, len, sent);
15798c2ecf20Sopenharmony_ci			if (sent < 0)
15808c2ecf20Sopenharmony_ci				err = sent;
15818c2ecf20Sopenharmony_ci			break;
15828c2ecf20Sopenharmony_ci		}
15838c2ecf20Sopenharmony_ci		len    -= sent;
15848c2ecf20Sopenharmony_ci		offset += sent;
15858c2ecf20Sopenharmony_ci	} while (len > 0 /* THINK && device->cstate >= C_CONNECTED*/);
15868c2ecf20Sopenharmony_ci	clear_bit(NET_CONGESTED, &peer_device->connection->flags);
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	if (len == 0) {
15898c2ecf20Sopenharmony_ci		err = 0;
15908c2ecf20Sopenharmony_ci		peer_device->device->send_cnt += size >> 9;
15918c2ecf20Sopenharmony_ci	}
15928c2ecf20Sopenharmony_ci	return err;
15938c2ecf20Sopenharmony_ci}
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_cistatic int _drbd_send_bio(struct drbd_peer_device *peer_device, struct bio *bio)
15968c2ecf20Sopenharmony_ci{
15978c2ecf20Sopenharmony_ci	struct bio_vec bvec;
15988c2ecf20Sopenharmony_ci	struct bvec_iter iter;
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	/* hint all but last page with MSG_MORE */
16018c2ecf20Sopenharmony_ci	bio_for_each_segment(bvec, bio, iter) {
16028c2ecf20Sopenharmony_ci		int err;
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci		err = _drbd_no_send_page(peer_device, bvec.bv_page,
16058c2ecf20Sopenharmony_ci					 bvec.bv_offset, bvec.bv_len,
16068c2ecf20Sopenharmony_ci					 bio_iter_last(bvec, iter)
16078c2ecf20Sopenharmony_ci					 ? 0 : MSG_MORE);
16088c2ecf20Sopenharmony_ci		if (err)
16098c2ecf20Sopenharmony_ci			return err;
16108c2ecf20Sopenharmony_ci		/* REQ_OP_WRITE_SAME has only one segment */
16118c2ecf20Sopenharmony_ci		if (bio_op(bio) == REQ_OP_WRITE_SAME)
16128c2ecf20Sopenharmony_ci			break;
16138c2ecf20Sopenharmony_ci	}
16148c2ecf20Sopenharmony_ci	return 0;
16158c2ecf20Sopenharmony_ci}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_cistatic int _drbd_send_zc_bio(struct drbd_peer_device *peer_device, struct bio *bio)
16188c2ecf20Sopenharmony_ci{
16198c2ecf20Sopenharmony_ci	struct bio_vec bvec;
16208c2ecf20Sopenharmony_ci	struct bvec_iter iter;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	/* hint all but last page with MSG_MORE */
16238c2ecf20Sopenharmony_ci	bio_for_each_segment(bvec, bio, iter) {
16248c2ecf20Sopenharmony_ci		int err;
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci		err = _drbd_send_page(peer_device, bvec.bv_page,
16278c2ecf20Sopenharmony_ci				      bvec.bv_offset, bvec.bv_len,
16288c2ecf20Sopenharmony_ci				      bio_iter_last(bvec, iter) ? 0 : MSG_MORE);
16298c2ecf20Sopenharmony_ci		if (err)
16308c2ecf20Sopenharmony_ci			return err;
16318c2ecf20Sopenharmony_ci		/* REQ_OP_WRITE_SAME has only one segment */
16328c2ecf20Sopenharmony_ci		if (bio_op(bio) == REQ_OP_WRITE_SAME)
16338c2ecf20Sopenharmony_ci			break;
16348c2ecf20Sopenharmony_ci	}
16358c2ecf20Sopenharmony_ci	return 0;
16368c2ecf20Sopenharmony_ci}
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_cistatic int _drbd_send_zc_ee(struct drbd_peer_device *peer_device,
16398c2ecf20Sopenharmony_ci			    struct drbd_peer_request *peer_req)
16408c2ecf20Sopenharmony_ci{
16418c2ecf20Sopenharmony_ci	struct page *page = peer_req->pages;
16428c2ecf20Sopenharmony_ci	unsigned len = peer_req->i.size;
16438c2ecf20Sopenharmony_ci	int err;
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	/* hint all but last page with MSG_MORE */
16468c2ecf20Sopenharmony_ci	page_chain_for_each(page) {
16478c2ecf20Sopenharmony_ci		unsigned l = min_t(unsigned, len, PAGE_SIZE);
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci		err = _drbd_send_page(peer_device, page, 0, l,
16508c2ecf20Sopenharmony_ci				      page_chain_next(page) ? MSG_MORE : 0);
16518c2ecf20Sopenharmony_ci		if (err)
16528c2ecf20Sopenharmony_ci			return err;
16538c2ecf20Sopenharmony_ci		len -= l;
16548c2ecf20Sopenharmony_ci	}
16558c2ecf20Sopenharmony_ci	return 0;
16568c2ecf20Sopenharmony_ci}
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_cistatic u32 bio_flags_to_wire(struct drbd_connection *connection,
16598c2ecf20Sopenharmony_ci			     struct bio *bio)
16608c2ecf20Sopenharmony_ci{
16618c2ecf20Sopenharmony_ci	if (connection->agreed_pro_version >= 95)
16628c2ecf20Sopenharmony_ci		return  (bio->bi_opf & REQ_SYNC ? DP_RW_SYNC : 0) |
16638c2ecf20Sopenharmony_ci			(bio->bi_opf & REQ_FUA ? DP_FUA : 0) |
16648c2ecf20Sopenharmony_ci			(bio->bi_opf & REQ_PREFLUSH ? DP_FLUSH : 0) |
16658c2ecf20Sopenharmony_ci			(bio_op(bio) == REQ_OP_WRITE_SAME ? DP_WSAME : 0) |
16668c2ecf20Sopenharmony_ci			(bio_op(bio) == REQ_OP_DISCARD ? DP_DISCARD : 0) |
16678c2ecf20Sopenharmony_ci			(bio_op(bio) == REQ_OP_WRITE_ZEROES ?
16688c2ecf20Sopenharmony_ci			  ((connection->agreed_features & DRBD_FF_WZEROES) ?
16698c2ecf20Sopenharmony_ci			   (DP_ZEROES |(!(bio->bi_opf & REQ_NOUNMAP) ? DP_DISCARD : 0))
16708c2ecf20Sopenharmony_ci			   : DP_DISCARD)
16718c2ecf20Sopenharmony_ci			: 0);
16728c2ecf20Sopenharmony_ci	else
16738c2ecf20Sopenharmony_ci		return bio->bi_opf & REQ_SYNC ? DP_RW_SYNC : 0;
16748c2ecf20Sopenharmony_ci}
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci/* Used to send write or TRIM aka REQ_OP_DISCARD requests
16778c2ecf20Sopenharmony_ci * R_PRIMARY -> Peer	(P_DATA, P_TRIM)
16788c2ecf20Sopenharmony_ci */
16798c2ecf20Sopenharmony_ciint drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request *req)
16808c2ecf20Sopenharmony_ci{
16818c2ecf20Sopenharmony_ci	struct drbd_device *device = peer_device->device;
16828c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
16838c2ecf20Sopenharmony_ci	struct p_data *p;
16848c2ecf20Sopenharmony_ci	struct p_wsame *wsame = NULL;
16858c2ecf20Sopenharmony_ci	void *digest_out;
16868c2ecf20Sopenharmony_ci	unsigned int dp_flags = 0;
16878c2ecf20Sopenharmony_ci	int digest_size;
16888c2ecf20Sopenharmony_ci	int err;
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
16918c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
16928c2ecf20Sopenharmony_ci	digest_size = peer_device->connection->integrity_tfm ?
16938c2ecf20Sopenharmony_ci		      crypto_shash_digestsize(peer_device->connection->integrity_tfm) : 0;
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	if (!p)
16968c2ecf20Sopenharmony_ci		return -EIO;
16978c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(req->i.sector);
16988c2ecf20Sopenharmony_ci	p->block_id = (unsigned long)req;
16998c2ecf20Sopenharmony_ci	p->seq_num = cpu_to_be32(atomic_inc_return(&device->packet_seq));
17008c2ecf20Sopenharmony_ci	dp_flags = bio_flags_to_wire(peer_device->connection, req->master_bio);
17018c2ecf20Sopenharmony_ci	if (device->state.conn >= C_SYNC_SOURCE &&
17028c2ecf20Sopenharmony_ci	    device->state.conn <= C_PAUSED_SYNC_T)
17038c2ecf20Sopenharmony_ci		dp_flags |= DP_MAY_SET_IN_SYNC;
17048c2ecf20Sopenharmony_ci	if (peer_device->connection->agreed_pro_version >= 100) {
17058c2ecf20Sopenharmony_ci		if (req->rq_state & RQ_EXP_RECEIVE_ACK)
17068c2ecf20Sopenharmony_ci			dp_flags |= DP_SEND_RECEIVE_ACK;
17078c2ecf20Sopenharmony_ci		/* During resync, request an explicit write ack,
17088c2ecf20Sopenharmony_ci		 * even in protocol != C */
17098c2ecf20Sopenharmony_ci		if (req->rq_state & RQ_EXP_WRITE_ACK
17108c2ecf20Sopenharmony_ci		|| (dp_flags & DP_MAY_SET_IN_SYNC))
17118c2ecf20Sopenharmony_ci			dp_flags |= DP_SEND_WRITE_ACK;
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci	p->dp_flags = cpu_to_be32(dp_flags);
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	if (dp_flags & (DP_DISCARD|DP_ZEROES)) {
17168c2ecf20Sopenharmony_ci		enum drbd_packet cmd = (dp_flags & DP_ZEROES) ? P_ZEROES : P_TRIM;
17178c2ecf20Sopenharmony_ci		struct p_trim *t = (struct p_trim*)p;
17188c2ecf20Sopenharmony_ci		t->size = cpu_to_be32(req->i.size);
17198c2ecf20Sopenharmony_ci		err = __send_command(peer_device->connection, device->vnr, sock, cmd, sizeof(*t), NULL, 0);
17208c2ecf20Sopenharmony_ci		goto out;
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci	if (dp_flags & DP_WSAME) {
17238c2ecf20Sopenharmony_ci		/* this will only work if DRBD_FF_WSAME is set AND the
17248c2ecf20Sopenharmony_ci		 * handshake agreed that all nodes and backend devices are
17258c2ecf20Sopenharmony_ci		 * WRITE_SAME capable and agree on logical_block_size */
17268c2ecf20Sopenharmony_ci		wsame = (struct p_wsame*)p;
17278c2ecf20Sopenharmony_ci		digest_out = wsame + 1;
17288c2ecf20Sopenharmony_ci		wsame->size = cpu_to_be32(req->i.size);
17298c2ecf20Sopenharmony_ci	} else
17308c2ecf20Sopenharmony_ci		digest_out = p + 1;
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	/* our digest is still only over the payload.
17338c2ecf20Sopenharmony_ci	 * TRIM does not carry any payload. */
17348c2ecf20Sopenharmony_ci	if (digest_size)
17358c2ecf20Sopenharmony_ci		drbd_csum_bio(peer_device->connection->integrity_tfm, req->master_bio, digest_out);
17368c2ecf20Sopenharmony_ci	if (wsame) {
17378c2ecf20Sopenharmony_ci		err =
17388c2ecf20Sopenharmony_ci		    __send_command(peer_device->connection, device->vnr, sock, P_WSAME,
17398c2ecf20Sopenharmony_ci				   sizeof(*wsame) + digest_size, NULL,
17408c2ecf20Sopenharmony_ci				   bio_iovec(req->master_bio).bv_len);
17418c2ecf20Sopenharmony_ci	} else
17428c2ecf20Sopenharmony_ci		err =
17438c2ecf20Sopenharmony_ci		    __send_command(peer_device->connection, device->vnr, sock, P_DATA,
17448c2ecf20Sopenharmony_ci				   sizeof(*p) + digest_size, NULL, req->i.size);
17458c2ecf20Sopenharmony_ci	if (!err) {
17468c2ecf20Sopenharmony_ci		/* For protocol A, we have to memcpy the payload into
17478c2ecf20Sopenharmony_ci		 * socket buffers, as we may complete right away
17488c2ecf20Sopenharmony_ci		 * as soon as we handed it over to tcp, at which point the data
17498c2ecf20Sopenharmony_ci		 * pages may become invalid.
17508c2ecf20Sopenharmony_ci		 *
17518c2ecf20Sopenharmony_ci		 * For data-integrity enabled, we copy it as well, so we can be
17528c2ecf20Sopenharmony_ci		 * sure that even if the bio pages may still be modified, it
17538c2ecf20Sopenharmony_ci		 * won't change the data on the wire, thus if the digest checks
17548c2ecf20Sopenharmony_ci		 * out ok after sending on this side, but does not fit on the
17558c2ecf20Sopenharmony_ci		 * receiving side, we sure have detected corruption elsewhere.
17568c2ecf20Sopenharmony_ci		 */
17578c2ecf20Sopenharmony_ci		if (!(req->rq_state & (RQ_EXP_RECEIVE_ACK | RQ_EXP_WRITE_ACK)) || digest_size)
17588c2ecf20Sopenharmony_ci			err = _drbd_send_bio(peer_device, req->master_bio);
17598c2ecf20Sopenharmony_ci		else
17608c2ecf20Sopenharmony_ci			err = _drbd_send_zc_bio(peer_device, req->master_bio);
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci		/* double check digest, sometimes buffers have been modified in flight. */
17638c2ecf20Sopenharmony_ci		if (digest_size > 0 && digest_size <= 64) {
17648c2ecf20Sopenharmony_ci			/* 64 byte, 512 bit, is the largest digest size
17658c2ecf20Sopenharmony_ci			 * currently supported in kernel crypto. */
17668c2ecf20Sopenharmony_ci			unsigned char digest[64];
17678c2ecf20Sopenharmony_ci			drbd_csum_bio(peer_device->connection->integrity_tfm, req->master_bio, digest);
17688c2ecf20Sopenharmony_ci			if (memcmp(p + 1, digest, digest_size)) {
17698c2ecf20Sopenharmony_ci				drbd_warn(device,
17708c2ecf20Sopenharmony_ci					"Digest mismatch, buffer modified by upper layers during write: %llus +%u\n",
17718c2ecf20Sopenharmony_ci					(unsigned long long)req->i.sector, req->i.size);
17728c2ecf20Sopenharmony_ci			}
17738c2ecf20Sopenharmony_ci		} /* else if (digest_size > 64) {
17748c2ecf20Sopenharmony_ci		     ... Be noisy about digest too large ...
17758c2ecf20Sopenharmony_ci		} */
17768c2ecf20Sopenharmony_ci	}
17778c2ecf20Sopenharmony_ciout:
17788c2ecf20Sopenharmony_ci	mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	return err;
17818c2ecf20Sopenharmony_ci}
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_ci/* answer packet, used to send data back for read requests:
17848c2ecf20Sopenharmony_ci *  Peer       -> (diskless) R_PRIMARY   (P_DATA_REPLY)
17858c2ecf20Sopenharmony_ci *  C_SYNC_SOURCE -> C_SYNC_TARGET         (P_RS_DATA_REPLY)
17868c2ecf20Sopenharmony_ci */
17878c2ecf20Sopenharmony_ciint drbd_send_block(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
17888c2ecf20Sopenharmony_ci		    struct drbd_peer_request *peer_req)
17898c2ecf20Sopenharmony_ci{
17908c2ecf20Sopenharmony_ci	struct drbd_device *device = peer_device->device;
17918c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
17928c2ecf20Sopenharmony_ci	struct p_data *p;
17938c2ecf20Sopenharmony_ci	int err;
17948c2ecf20Sopenharmony_ci	int digest_size;
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
17978c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	digest_size = peer_device->connection->integrity_tfm ?
18008c2ecf20Sopenharmony_ci		      crypto_shash_digestsize(peer_device->connection->integrity_tfm) : 0;
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci	if (!p)
18038c2ecf20Sopenharmony_ci		return -EIO;
18048c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(peer_req->i.sector);
18058c2ecf20Sopenharmony_ci	p->block_id = peer_req->block_id;
18068c2ecf20Sopenharmony_ci	p->seq_num = 0;  /* unused */
18078c2ecf20Sopenharmony_ci	p->dp_flags = 0;
18088c2ecf20Sopenharmony_ci	if (digest_size)
18098c2ecf20Sopenharmony_ci		drbd_csum_ee(peer_device->connection->integrity_tfm, peer_req, p + 1);
18108c2ecf20Sopenharmony_ci	err = __send_command(peer_device->connection, device->vnr, sock, cmd, sizeof(*p) + digest_size, NULL, peer_req->i.size);
18118c2ecf20Sopenharmony_ci	if (!err)
18128c2ecf20Sopenharmony_ci		err = _drbd_send_zc_ee(peer_device, peer_req);
18138c2ecf20Sopenharmony_ci	mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	return err;
18168c2ecf20Sopenharmony_ci}
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ciint drbd_send_out_of_sync(struct drbd_peer_device *peer_device, struct drbd_request *req)
18198c2ecf20Sopenharmony_ci{
18208c2ecf20Sopenharmony_ci	struct drbd_socket *sock;
18218c2ecf20Sopenharmony_ci	struct p_block_desc *p;
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	sock = &peer_device->connection->data;
18248c2ecf20Sopenharmony_ci	p = drbd_prepare_command(peer_device, sock);
18258c2ecf20Sopenharmony_ci	if (!p)
18268c2ecf20Sopenharmony_ci		return -EIO;
18278c2ecf20Sopenharmony_ci	p->sector = cpu_to_be64(req->i.sector);
18288c2ecf20Sopenharmony_ci	p->blksize = cpu_to_be32(req->i.size);
18298c2ecf20Sopenharmony_ci	return drbd_send_command(peer_device, sock, P_OUT_OF_SYNC, sizeof(*p), NULL, 0);
18308c2ecf20Sopenharmony_ci}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci/*
18338c2ecf20Sopenharmony_ci  drbd_send distinguishes two cases:
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci  Packets sent via the data socket "sock"
18368c2ecf20Sopenharmony_ci  and packets sent via the meta data socket "msock"
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci		    sock                      msock
18398c2ecf20Sopenharmony_ci  -----------------+-------------------------+------------------------------
18408c2ecf20Sopenharmony_ci  timeout           conf.timeout / 2          conf.timeout / 2
18418c2ecf20Sopenharmony_ci  timeout action    send a ping via msock     Abort communication
18428c2ecf20Sopenharmony_ci					      and close all sockets
18438c2ecf20Sopenharmony_ci*/
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci/*
18468c2ecf20Sopenharmony_ci * you must have down()ed the appropriate [m]sock_mutex elsewhere!
18478c2ecf20Sopenharmony_ci */
18488c2ecf20Sopenharmony_ciint drbd_send(struct drbd_connection *connection, struct socket *sock,
18498c2ecf20Sopenharmony_ci	      void *buf, size_t size, unsigned msg_flags)
18508c2ecf20Sopenharmony_ci{
18518c2ecf20Sopenharmony_ci	struct kvec iov = {.iov_base = buf, .iov_len = size};
18528c2ecf20Sopenharmony_ci	struct msghdr msg = {.msg_flags = msg_flags | MSG_NOSIGNAL};
18538c2ecf20Sopenharmony_ci	int rv, sent = 0;
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci	if (!sock)
18568c2ecf20Sopenharmony_ci		return -EBADR;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	/* THINK  if (signal_pending) return ... ? */
18598c2ecf20Sopenharmony_ci
18608c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, &iov, 1, size);
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci	if (sock == connection->data.socket) {
18638c2ecf20Sopenharmony_ci		rcu_read_lock();
18648c2ecf20Sopenharmony_ci		connection->ko_count = rcu_dereference(connection->net_conf)->ko_count;
18658c2ecf20Sopenharmony_ci		rcu_read_unlock();
18668c2ecf20Sopenharmony_ci		drbd_update_congested(connection);
18678c2ecf20Sopenharmony_ci	}
18688c2ecf20Sopenharmony_ci	do {
18698c2ecf20Sopenharmony_ci		rv = sock_sendmsg(sock, &msg);
18708c2ecf20Sopenharmony_ci		if (rv == -EAGAIN) {
18718c2ecf20Sopenharmony_ci			if (we_should_drop_the_connection(connection, sock))
18728c2ecf20Sopenharmony_ci				break;
18738c2ecf20Sopenharmony_ci			else
18748c2ecf20Sopenharmony_ci				continue;
18758c2ecf20Sopenharmony_ci		}
18768c2ecf20Sopenharmony_ci		if (rv == -EINTR) {
18778c2ecf20Sopenharmony_ci			flush_signals(current);
18788c2ecf20Sopenharmony_ci			rv = 0;
18798c2ecf20Sopenharmony_ci		}
18808c2ecf20Sopenharmony_ci		if (rv < 0)
18818c2ecf20Sopenharmony_ci			break;
18828c2ecf20Sopenharmony_ci		sent += rv;
18838c2ecf20Sopenharmony_ci	} while (sent < size);
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci	if (sock == connection->data.socket)
18868c2ecf20Sopenharmony_ci		clear_bit(NET_CONGESTED, &connection->flags);
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	if (rv <= 0) {
18898c2ecf20Sopenharmony_ci		if (rv != -EAGAIN) {
18908c2ecf20Sopenharmony_ci			drbd_err(connection, "%s_sendmsg returned %d\n",
18918c2ecf20Sopenharmony_ci				 sock == connection->meta.socket ? "msock" : "sock",
18928c2ecf20Sopenharmony_ci				 rv);
18938c2ecf20Sopenharmony_ci			conn_request_state(connection, NS(conn, C_BROKEN_PIPE), CS_HARD);
18948c2ecf20Sopenharmony_ci		} else
18958c2ecf20Sopenharmony_ci			conn_request_state(connection, NS(conn, C_TIMEOUT), CS_HARD);
18968c2ecf20Sopenharmony_ci	}
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	return sent;
18998c2ecf20Sopenharmony_ci}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci/**
19028c2ecf20Sopenharmony_ci * drbd_send_all  -  Send an entire buffer
19038c2ecf20Sopenharmony_ci *
19048c2ecf20Sopenharmony_ci * Returns 0 upon success and a negative error value otherwise.
19058c2ecf20Sopenharmony_ci */
19068c2ecf20Sopenharmony_ciint drbd_send_all(struct drbd_connection *connection, struct socket *sock, void *buffer,
19078c2ecf20Sopenharmony_ci		  size_t size, unsigned msg_flags)
19088c2ecf20Sopenharmony_ci{
19098c2ecf20Sopenharmony_ci	int err;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	err = drbd_send(connection, sock, buffer, size, msg_flags);
19128c2ecf20Sopenharmony_ci	if (err < 0)
19138c2ecf20Sopenharmony_ci		return err;
19148c2ecf20Sopenharmony_ci	if (err != size)
19158c2ecf20Sopenharmony_ci		return -EIO;
19168c2ecf20Sopenharmony_ci	return 0;
19178c2ecf20Sopenharmony_ci}
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_cistatic int drbd_open(struct block_device *bdev, fmode_t mode)
19208c2ecf20Sopenharmony_ci{
19218c2ecf20Sopenharmony_ci	struct drbd_device *device = bdev->bd_disk->private_data;
19228c2ecf20Sopenharmony_ci	unsigned long flags;
19238c2ecf20Sopenharmony_ci	int rv = 0;
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci	mutex_lock(&drbd_main_mutex);
19268c2ecf20Sopenharmony_ci	spin_lock_irqsave(&device->resource->req_lock, flags);
19278c2ecf20Sopenharmony_ci	/* to have a stable device->state.role
19288c2ecf20Sopenharmony_ci	 * and no race with updating open_cnt */
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	if (device->state.role != R_PRIMARY) {
19318c2ecf20Sopenharmony_ci		if (mode & FMODE_WRITE)
19328c2ecf20Sopenharmony_ci			rv = -EROFS;
19338c2ecf20Sopenharmony_ci		else if (!drbd_allow_oos)
19348c2ecf20Sopenharmony_ci			rv = -EMEDIUMTYPE;
19358c2ecf20Sopenharmony_ci	}
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ci	if (!rv)
19388c2ecf20Sopenharmony_ci		device->open_cnt++;
19398c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&device->resource->req_lock, flags);
19408c2ecf20Sopenharmony_ci	mutex_unlock(&drbd_main_mutex);
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	return rv;
19438c2ecf20Sopenharmony_ci}
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_cistatic void drbd_release(struct gendisk *gd, fmode_t mode)
19468c2ecf20Sopenharmony_ci{
19478c2ecf20Sopenharmony_ci	struct drbd_device *device = gd->private_data;
19488c2ecf20Sopenharmony_ci	mutex_lock(&drbd_main_mutex);
19498c2ecf20Sopenharmony_ci	device->open_cnt--;
19508c2ecf20Sopenharmony_ci	mutex_unlock(&drbd_main_mutex);
19518c2ecf20Sopenharmony_ci}
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci/* need to hold resource->req_lock */
19548c2ecf20Sopenharmony_civoid drbd_queue_unplug(struct drbd_device *device)
19558c2ecf20Sopenharmony_ci{
19568c2ecf20Sopenharmony_ci	if (device->state.pdsk >= D_INCONSISTENT && device->state.conn >= C_CONNECTED) {
19578c2ecf20Sopenharmony_ci		D_ASSERT(device, device->state.role == R_PRIMARY);
19588c2ecf20Sopenharmony_ci		if (test_and_clear_bit(UNPLUG_REMOTE, &device->flags)) {
19598c2ecf20Sopenharmony_ci			drbd_queue_work_if_unqueued(
19608c2ecf20Sopenharmony_ci				&first_peer_device(device)->connection->sender_work,
19618c2ecf20Sopenharmony_ci				&device->unplug_work);
19628c2ecf20Sopenharmony_ci		}
19638c2ecf20Sopenharmony_ci	}
19648c2ecf20Sopenharmony_ci}
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_cistatic void drbd_set_defaults(struct drbd_device *device)
19678c2ecf20Sopenharmony_ci{
19688c2ecf20Sopenharmony_ci	/* Beware! The actual layout differs
19698c2ecf20Sopenharmony_ci	 * between big endian and little endian */
19708c2ecf20Sopenharmony_ci	device->state = (union drbd_dev_state) {
19718c2ecf20Sopenharmony_ci		{ .role = R_SECONDARY,
19728c2ecf20Sopenharmony_ci		  .peer = R_UNKNOWN,
19738c2ecf20Sopenharmony_ci		  .conn = C_STANDALONE,
19748c2ecf20Sopenharmony_ci		  .disk = D_DISKLESS,
19758c2ecf20Sopenharmony_ci		  .pdsk = D_UNKNOWN,
19768c2ecf20Sopenharmony_ci		} };
19778c2ecf20Sopenharmony_ci}
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_civoid drbd_init_set_defaults(struct drbd_device *device)
19808c2ecf20Sopenharmony_ci{
19818c2ecf20Sopenharmony_ci	/* the memset(,0,) did most of this.
19828c2ecf20Sopenharmony_ci	 * note: only assignments, no allocation in here */
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	drbd_set_defaults(device);
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	atomic_set(&device->ap_bio_cnt, 0);
19878c2ecf20Sopenharmony_ci	atomic_set(&device->ap_actlog_cnt, 0);
19888c2ecf20Sopenharmony_ci	atomic_set(&device->ap_pending_cnt, 0);
19898c2ecf20Sopenharmony_ci	atomic_set(&device->rs_pending_cnt, 0);
19908c2ecf20Sopenharmony_ci	atomic_set(&device->unacked_cnt, 0);
19918c2ecf20Sopenharmony_ci	atomic_set(&device->local_cnt, 0);
19928c2ecf20Sopenharmony_ci	atomic_set(&device->pp_in_use_by_net, 0);
19938c2ecf20Sopenharmony_ci	atomic_set(&device->rs_sect_in, 0);
19948c2ecf20Sopenharmony_ci	atomic_set(&device->rs_sect_ev, 0);
19958c2ecf20Sopenharmony_ci	atomic_set(&device->ap_in_flight, 0);
19968c2ecf20Sopenharmony_ci	atomic_set(&device->md_io.in_use, 0);
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	mutex_init(&device->own_state_mutex);
19998c2ecf20Sopenharmony_ci	device->state_mutex = &device->own_state_mutex;
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	spin_lock_init(&device->al_lock);
20028c2ecf20Sopenharmony_ci	spin_lock_init(&device->peer_seq_lock);
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->active_ee);
20058c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->sync_ee);
20068c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->done_ee);
20078c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->read_ee);
20088c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->net_ee);
20098c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->resync_reads);
20108c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->resync_work.list);
20118c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->unplug_work.list);
20128c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->bm_io_work.w.list);
20138c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->pending_master_completion[0]);
20148c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->pending_master_completion[1]);
20158c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->pending_completion[0]);
20168c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->pending_completion[1]);
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci	device->resync_work.cb  = w_resync_timer;
20198c2ecf20Sopenharmony_ci	device->unplug_work.cb  = w_send_write_hint;
20208c2ecf20Sopenharmony_ci	device->bm_io_work.w.cb = w_bitmap_io;
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	timer_setup(&device->resync_timer, resync_timer_fn, 0);
20238c2ecf20Sopenharmony_ci	timer_setup(&device->md_sync_timer, md_sync_timer_fn, 0);
20248c2ecf20Sopenharmony_ci	timer_setup(&device->start_resync_timer, start_resync_timer_fn, 0);
20258c2ecf20Sopenharmony_ci	timer_setup(&device->request_timer, request_timer_fn, 0);
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	init_waitqueue_head(&device->misc_wait);
20288c2ecf20Sopenharmony_ci	init_waitqueue_head(&device->state_wait);
20298c2ecf20Sopenharmony_ci	init_waitqueue_head(&device->ee_wait);
20308c2ecf20Sopenharmony_ci	init_waitqueue_head(&device->al_wait);
20318c2ecf20Sopenharmony_ci	init_waitqueue_head(&device->seq_wait);
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	device->resync_wenr = LC_FREE;
20348c2ecf20Sopenharmony_ci	device->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
20358c2ecf20Sopenharmony_ci	device->local_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
20368c2ecf20Sopenharmony_ci}
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_civoid drbd_set_my_capacity(struct drbd_device *device, sector_t size)
20398c2ecf20Sopenharmony_ci{
20408c2ecf20Sopenharmony_ci	char ppb[10];
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci	set_capacity(device->vdisk, size);
20438c2ecf20Sopenharmony_ci	revalidate_disk_size(device->vdisk, false);
20448c2ecf20Sopenharmony_ci
20458c2ecf20Sopenharmony_ci	drbd_info(device, "size = %s (%llu KB)\n",
20468c2ecf20Sopenharmony_ci		ppsize(ppb, size>>1), (unsigned long long)size>>1);
20478c2ecf20Sopenharmony_ci}
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_civoid drbd_device_cleanup(struct drbd_device *device)
20508c2ecf20Sopenharmony_ci{
20518c2ecf20Sopenharmony_ci	int i;
20528c2ecf20Sopenharmony_ci	if (first_peer_device(device)->connection->receiver.t_state != NONE)
20538c2ecf20Sopenharmony_ci		drbd_err(device, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
20548c2ecf20Sopenharmony_ci				first_peer_device(device)->connection->receiver.t_state);
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	device->al_writ_cnt  =
20578c2ecf20Sopenharmony_ci	device->bm_writ_cnt  =
20588c2ecf20Sopenharmony_ci	device->read_cnt     =
20598c2ecf20Sopenharmony_ci	device->recv_cnt     =
20608c2ecf20Sopenharmony_ci	device->send_cnt     =
20618c2ecf20Sopenharmony_ci	device->writ_cnt     =
20628c2ecf20Sopenharmony_ci	device->p_size       =
20638c2ecf20Sopenharmony_ci	device->rs_start     =
20648c2ecf20Sopenharmony_ci	device->rs_total     =
20658c2ecf20Sopenharmony_ci	device->rs_failed    = 0;
20668c2ecf20Sopenharmony_ci	device->rs_last_events = 0;
20678c2ecf20Sopenharmony_ci	device->rs_last_sect_ev = 0;
20688c2ecf20Sopenharmony_ci	for (i = 0; i < DRBD_SYNC_MARKS; i++) {
20698c2ecf20Sopenharmony_ci		device->rs_mark_left[i] = 0;
20708c2ecf20Sopenharmony_ci		device->rs_mark_time[i] = 0;
20718c2ecf20Sopenharmony_ci	}
20728c2ecf20Sopenharmony_ci	D_ASSERT(device, first_peer_device(device)->connection->net_conf == NULL);
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	set_capacity(device->vdisk, 0);
20758c2ecf20Sopenharmony_ci	revalidate_disk_size(device->vdisk, false);
20768c2ecf20Sopenharmony_ci	if (device->bitmap) {
20778c2ecf20Sopenharmony_ci		/* maybe never allocated. */
20788c2ecf20Sopenharmony_ci		drbd_bm_resize(device, 0, 1);
20798c2ecf20Sopenharmony_ci		drbd_bm_cleanup(device);
20808c2ecf20Sopenharmony_ci	}
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	drbd_backing_dev_free(device, device->ldev);
20838c2ecf20Sopenharmony_ci	device->ldev = NULL;
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	clear_bit(AL_SUSPENDED, &device->flags);
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->active_ee));
20888c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->sync_ee));
20898c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->done_ee));
20908c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->read_ee));
20918c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->net_ee));
20928c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->resync_reads));
20938c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&first_peer_device(device)->connection->sender_work.q));
20948c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->resync_work.list));
20958c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->unplug_work.list));
20968c2ecf20Sopenharmony_ci
20978c2ecf20Sopenharmony_ci	drbd_set_defaults(device);
20988c2ecf20Sopenharmony_ci}
20998c2ecf20Sopenharmony_ci
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_cistatic void drbd_destroy_mempools(void)
21028c2ecf20Sopenharmony_ci{
21038c2ecf20Sopenharmony_ci	struct page *page;
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci	while (drbd_pp_pool) {
21068c2ecf20Sopenharmony_ci		page = drbd_pp_pool;
21078c2ecf20Sopenharmony_ci		drbd_pp_pool = (struct page *)page_private(page);
21088c2ecf20Sopenharmony_ci		__free_page(page);
21098c2ecf20Sopenharmony_ci		drbd_pp_vacant--;
21108c2ecf20Sopenharmony_ci	}
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci	/* D_ASSERT(device, atomic_read(&drbd_pp_vacant)==0); */
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci	bioset_exit(&drbd_io_bio_set);
21158c2ecf20Sopenharmony_ci	bioset_exit(&drbd_md_io_bio_set);
21168c2ecf20Sopenharmony_ci	mempool_exit(&drbd_md_io_page_pool);
21178c2ecf20Sopenharmony_ci	mempool_exit(&drbd_ee_mempool);
21188c2ecf20Sopenharmony_ci	mempool_exit(&drbd_request_mempool);
21198c2ecf20Sopenharmony_ci	kmem_cache_destroy(drbd_ee_cache);
21208c2ecf20Sopenharmony_ci	kmem_cache_destroy(drbd_request_cache);
21218c2ecf20Sopenharmony_ci	kmem_cache_destroy(drbd_bm_ext_cache);
21228c2ecf20Sopenharmony_ci	kmem_cache_destroy(drbd_al_ext_cache);
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci	drbd_ee_cache        = NULL;
21258c2ecf20Sopenharmony_ci	drbd_request_cache   = NULL;
21268c2ecf20Sopenharmony_ci	drbd_bm_ext_cache    = NULL;
21278c2ecf20Sopenharmony_ci	drbd_al_ext_cache    = NULL;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	return;
21308c2ecf20Sopenharmony_ci}
21318c2ecf20Sopenharmony_ci
21328c2ecf20Sopenharmony_cistatic int drbd_create_mempools(void)
21338c2ecf20Sopenharmony_ci{
21348c2ecf20Sopenharmony_ci	struct page *page;
21358c2ecf20Sopenharmony_ci	const int number = (DRBD_MAX_BIO_SIZE/PAGE_SIZE) * drbd_minor_count;
21368c2ecf20Sopenharmony_ci	int i, ret;
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci	/* caches */
21398c2ecf20Sopenharmony_ci	drbd_request_cache = kmem_cache_create(
21408c2ecf20Sopenharmony_ci		"drbd_req", sizeof(struct drbd_request), 0, 0, NULL);
21418c2ecf20Sopenharmony_ci	if (drbd_request_cache == NULL)
21428c2ecf20Sopenharmony_ci		goto Enomem;
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	drbd_ee_cache = kmem_cache_create(
21458c2ecf20Sopenharmony_ci		"drbd_ee", sizeof(struct drbd_peer_request), 0, 0, NULL);
21468c2ecf20Sopenharmony_ci	if (drbd_ee_cache == NULL)
21478c2ecf20Sopenharmony_ci		goto Enomem;
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_ci	drbd_bm_ext_cache = kmem_cache_create(
21508c2ecf20Sopenharmony_ci		"drbd_bm", sizeof(struct bm_extent), 0, 0, NULL);
21518c2ecf20Sopenharmony_ci	if (drbd_bm_ext_cache == NULL)
21528c2ecf20Sopenharmony_ci		goto Enomem;
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	drbd_al_ext_cache = kmem_cache_create(
21558c2ecf20Sopenharmony_ci		"drbd_al", sizeof(struct lc_element), 0, 0, NULL);
21568c2ecf20Sopenharmony_ci	if (drbd_al_ext_cache == NULL)
21578c2ecf20Sopenharmony_ci		goto Enomem;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	/* mempools */
21608c2ecf20Sopenharmony_ci	ret = bioset_init(&drbd_io_bio_set, BIO_POOL_SIZE, 0, 0);
21618c2ecf20Sopenharmony_ci	if (ret)
21628c2ecf20Sopenharmony_ci		goto Enomem;
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci	ret = bioset_init(&drbd_md_io_bio_set, DRBD_MIN_POOL_PAGES, 0,
21658c2ecf20Sopenharmony_ci			  BIOSET_NEED_BVECS);
21668c2ecf20Sopenharmony_ci	if (ret)
21678c2ecf20Sopenharmony_ci		goto Enomem;
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	ret = mempool_init_page_pool(&drbd_md_io_page_pool, DRBD_MIN_POOL_PAGES, 0);
21708c2ecf20Sopenharmony_ci	if (ret)
21718c2ecf20Sopenharmony_ci		goto Enomem;
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci	ret = mempool_init_slab_pool(&drbd_request_mempool, number,
21748c2ecf20Sopenharmony_ci				     drbd_request_cache);
21758c2ecf20Sopenharmony_ci	if (ret)
21768c2ecf20Sopenharmony_ci		goto Enomem;
21778c2ecf20Sopenharmony_ci
21788c2ecf20Sopenharmony_ci	ret = mempool_init_slab_pool(&drbd_ee_mempool, number, drbd_ee_cache);
21798c2ecf20Sopenharmony_ci	if (ret)
21808c2ecf20Sopenharmony_ci		goto Enomem;
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	/* drbd's page pool */
21838c2ecf20Sopenharmony_ci	spin_lock_init(&drbd_pp_lock);
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ci	for (i = 0; i < number; i++) {
21868c2ecf20Sopenharmony_ci		page = alloc_page(GFP_HIGHUSER);
21878c2ecf20Sopenharmony_ci		if (!page)
21888c2ecf20Sopenharmony_ci			goto Enomem;
21898c2ecf20Sopenharmony_ci		set_page_private(page, (unsigned long)drbd_pp_pool);
21908c2ecf20Sopenharmony_ci		drbd_pp_pool = page;
21918c2ecf20Sopenharmony_ci	}
21928c2ecf20Sopenharmony_ci	drbd_pp_vacant = number;
21938c2ecf20Sopenharmony_ci
21948c2ecf20Sopenharmony_ci	return 0;
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ciEnomem:
21978c2ecf20Sopenharmony_ci	drbd_destroy_mempools(); /* in case we allocated some */
21988c2ecf20Sopenharmony_ci	return -ENOMEM;
21998c2ecf20Sopenharmony_ci}
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_cistatic void drbd_release_all_peer_reqs(struct drbd_device *device)
22028c2ecf20Sopenharmony_ci{
22038c2ecf20Sopenharmony_ci	int rr;
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci	rr = drbd_free_peer_reqs(device, &device->active_ee);
22068c2ecf20Sopenharmony_ci	if (rr)
22078c2ecf20Sopenharmony_ci		drbd_err(device, "%d EEs in active list found!\n", rr);
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci	rr = drbd_free_peer_reqs(device, &device->sync_ee);
22108c2ecf20Sopenharmony_ci	if (rr)
22118c2ecf20Sopenharmony_ci		drbd_err(device, "%d EEs in sync list found!\n", rr);
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	rr = drbd_free_peer_reqs(device, &device->read_ee);
22148c2ecf20Sopenharmony_ci	if (rr)
22158c2ecf20Sopenharmony_ci		drbd_err(device, "%d EEs in read list found!\n", rr);
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci	rr = drbd_free_peer_reqs(device, &device->done_ee);
22188c2ecf20Sopenharmony_ci	if (rr)
22198c2ecf20Sopenharmony_ci		drbd_err(device, "%d EEs in done list found!\n", rr);
22208c2ecf20Sopenharmony_ci
22218c2ecf20Sopenharmony_ci	rr = drbd_free_peer_reqs(device, &device->net_ee);
22228c2ecf20Sopenharmony_ci	if (rr)
22238c2ecf20Sopenharmony_ci		drbd_err(device, "%d EEs in net list found!\n", rr);
22248c2ecf20Sopenharmony_ci}
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci/* caution. no locking. */
22278c2ecf20Sopenharmony_civoid drbd_destroy_device(struct kref *kref)
22288c2ecf20Sopenharmony_ci{
22298c2ecf20Sopenharmony_ci	struct drbd_device *device = container_of(kref, struct drbd_device, kref);
22308c2ecf20Sopenharmony_ci	struct drbd_resource *resource = device->resource;
22318c2ecf20Sopenharmony_ci	struct drbd_peer_device *peer_device, *tmp_peer_device;
22328c2ecf20Sopenharmony_ci
22338c2ecf20Sopenharmony_ci	del_timer_sync(&device->request_timer);
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ci	/* paranoia asserts */
22368c2ecf20Sopenharmony_ci	D_ASSERT(device, device->open_cnt == 0);
22378c2ecf20Sopenharmony_ci	/* end paranoia asserts */
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	/* cleanup stuff that may have been allocated during
22408c2ecf20Sopenharmony_ci	 * device (re-)configuration or state changes */
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci	drbd_backing_dev_free(device, device->ldev);
22438c2ecf20Sopenharmony_ci	device->ldev = NULL;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci	drbd_release_all_peer_reqs(device);
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	lc_destroy(device->act_log);
22488c2ecf20Sopenharmony_ci	lc_destroy(device->resync);
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci	kfree(device->p_uuid);
22518c2ecf20Sopenharmony_ci	/* device->p_uuid = NULL; */
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	if (device->bitmap) /* should no longer be there. */
22548c2ecf20Sopenharmony_ci		drbd_bm_cleanup(device);
22558c2ecf20Sopenharmony_ci	__free_page(device->md_io.page);
22568c2ecf20Sopenharmony_ci	put_disk(device->vdisk);
22578c2ecf20Sopenharmony_ci	blk_cleanup_queue(device->rq_queue);
22588c2ecf20Sopenharmony_ci	kfree(device->rs_plan_s);
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci	/* not for_each_connection(connection, resource):
22618c2ecf20Sopenharmony_ci	 * those may have been cleaned up and disassociated already.
22628c2ecf20Sopenharmony_ci	 */
22638c2ecf20Sopenharmony_ci	for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
22648c2ecf20Sopenharmony_ci		kref_put(&peer_device->connection->kref, drbd_destroy_connection);
22658c2ecf20Sopenharmony_ci		kfree(peer_device);
22668c2ecf20Sopenharmony_ci	}
22678c2ecf20Sopenharmony_ci	memset(device, 0xfd, sizeof(*device));
22688c2ecf20Sopenharmony_ci	kfree(device);
22698c2ecf20Sopenharmony_ci	kref_put(&resource->kref, drbd_destroy_resource);
22708c2ecf20Sopenharmony_ci}
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci/* One global retry thread, if we need to push back some bio and have it
22738c2ecf20Sopenharmony_ci * reinserted through our make request function.
22748c2ecf20Sopenharmony_ci */
22758c2ecf20Sopenharmony_cistatic struct retry_worker {
22768c2ecf20Sopenharmony_ci	struct workqueue_struct *wq;
22778c2ecf20Sopenharmony_ci	struct work_struct worker;
22788c2ecf20Sopenharmony_ci
22798c2ecf20Sopenharmony_ci	spinlock_t lock;
22808c2ecf20Sopenharmony_ci	struct list_head writes;
22818c2ecf20Sopenharmony_ci} retry;
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_cistatic void do_retry(struct work_struct *ws)
22848c2ecf20Sopenharmony_ci{
22858c2ecf20Sopenharmony_ci	struct retry_worker *retry = container_of(ws, struct retry_worker, worker);
22868c2ecf20Sopenharmony_ci	LIST_HEAD(writes);
22878c2ecf20Sopenharmony_ci	struct drbd_request *req, *tmp;
22888c2ecf20Sopenharmony_ci
22898c2ecf20Sopenharmony_ci	spin_lock_irq(&retry->lock);
22908c2ecf20Sopenharmony_ci	list_splice_init(&retry->writes, &writes);
22918c2ecf20Sopenharmony_ci	spin_unlock_irq(&retry->lock);
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	list_for_each_entry_safe(req, tmp, &writes, tl_requests) {
22948c2ecf20Sopenharmony_ci		struct drbd_device *device = req->device;
22958c2ecf20Sopenharmony_ci		struct bio *bio = req->master_bio;
22968c2ecf20Sopenharmony_ci		unsigned long start_jif = req->start_jif;
22978c2ecf20Sopenharmony_ci		bool expected;
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_ci		expected =
23008c2ecf20Sopenharmony_ci			expect(atomic_read(&req->completion_ref) == 0) &&
23018c2ecf20Sopenharmony_ci			expect(req->rq_state & RQ_POSTPONED) &&
23028c2ecf20Sopenharmony_ci			expect((req->rq_state & RQ_LOCAL_PENDING) == 0 ||
23038c2ecf20Sopenharmony_ci				(req->rq_state & RQ_LOCAL_ABORTED) != 0);
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci		if (!expected)
23068c2ecf20Sopenharmony_ci			drbd_err(device, "req=%p completion_ref=%d rq_state=%x\n",
23078c2ecf20Sopenharmony_ci				req, atomic_read(&req->completion_ref),
23088c2ecf20Sopenharmony_ci				req->rq_state);
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci		/* We still need to put one kref associated with the
23118c2ecf20Sopenharmony_ci		 * "completion_ref" going zero in the code path that queued it
23128c2ecf20Sopenharmony_ci		 * here.  The request object may still be referenced by a
23138c2ecf20Sopenharmony_ci		 * frozen local req->private_bio, in case we force-detached.
23148c2ecf20Sopenharmony_ci		 */
23158c2ecf20Sopenharmony_ci		kref_put(&req->kref, drbd_req_destroy);
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_ci		/* A single suspended or otherwise blocking device may stall
23188c2ecf20Sopenharmony_ci		 * all others as well.  Fortunately, this code path is to
23198c2ecf20Sopenharmony_ci		 * recover from a situation that "should not happen":
23208c2ecf20Sopenharmony_ci		 * concurrent writes in multi-primary setup.
23218c2ecf20Sopenharmony_ci		 * In a "normal" lifecycle, this workqueue is supposed to be
23228c2ecf20Sopenharmony_ci		 * destroyed without ever doing anything.
23238c2ecf20Sopenharmony_ci		 * If it turns out to be an issue anyways, we can do per
23248c2ecf20Sopenharmony_ci		 * resource (replication group) or per device (minor) retry
23258c2ecf20Sopenharmony_ci		 * workqueues instead.
23268c2ecf20Sopenharmony_ci		 */
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_ci		/* We are not just doing submit_bio_noacct(),
23298c2ecf20Sopenharmony_ci		 * as we want to keep the start_time information. */
23308c2ecf20Sopenharmony_ci		inc_ap_bio(device);
23318c2ecf20Sopenharmony_ci		__drbd_make_request(device, bio, start_jif);
23328c2ecf20Sopenharmony_ci	}
23338c2ecf20Sopenharmony_ci}
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci/* called via drbd_req_put_completion_ref(),
23368c2ecf20Sopenharmony_ci * holds resource->req_lock */
23378c2ecf20Sopenharmony_civoid drbd_restart_request(struct drbd_request *req)
23388c2ecf20Sopenharmony_ci{
23398c2ecf20Sopenharmony_ci	unsigned long flags;
23408c2ecf20Sopenharmony_ci	spin_lock_irqsave(&retry.lock, flags);
23418c2ecf20Sopenharmony_ci	list_move_tail(&req->tl_requests, &retry.writes);
23428c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&retry.lock, flags);
23438c2ecf20Sopenharmony_ci
23448c2ecf20Sopenharmony_ci	/* Drop the extra reference that would otherwise
23458c2ecf20Sopenharmony_ci	 * have been dropped by complete_master_bio.
23468c2ecf20Sopenharmony_ci	 * do_retry() needs to grab a new one. */
23478c2ecf20Sopenharmony_ci	dec_ap_bio(req->device);
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci	queue_work(retry.wq, &retry.worker);
23508c2ecf20Sopenharmony_ci}
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_civoid drbd_destroy_resource(struct kref *kref)
23538c2ecf20Sopenharmony_ci{
23548c2ecf20Sopenharmony_ci	struct drbd_resource *resource =
23558c2ecf20Sopenharmony_ci		container_of(kref, struct drbd_resource, kref);
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci	idr_destroy(&resource->devices);
23588c2ecf20Sopenharmony_ci	free_cpumask_var(resource->cpu_mask);
23598c2ecf20Sopenharmony_ci	kfree(resource->name);
23608c2ecf20Sopenharmony_ci	memset(resource, 0xf2, sizeof(*resource));
23618c2ecf20Sopenharmony_ci	kfree(resource);
23628c2ecf20Sopenharmony_ci}
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_civoid drbd_free_resource(struct drbd_resource *resource)
23658c2ecf20Sopenharmony_ci{
23668c2ecf20Sopenharmony_ci	struct drbd_connection *connection, *tmp;
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci	for_each_connection_safe(connection, tmp, resource) {
23698c2ecf20Sopenharmony_ci		list_del(&connection->connections);
23708c2ecf20Sopenharmony_ci		drbd_debugfs_connection_cleanup(connection);
23718c2ecf20Sopenharmony_ci		kref_put(&connection->kref, drbd_destroy_connection);
23728c2ecf20Sopenharmony_ci	}
23738c2ecf20Sopenharmony_ci	drbd_debugfs_resource_cleanup(resource);
23748c2ecf20Sopenharmony_ci	kref_put(&resource->kref, drbd_destroy_resource);
23758c2ecf20Sopenharmony_ci}
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_cistatic void drbd_cleanup(void)
23788c2ecf20Sopenharmony_ci{
23798c2ecf20Sopenharmony_ci	unsigned int i;
23808c2ecf20Sopenharmony_ci	struct drbd_device *device;
23818c2ecf20Sopenharmony_ci	struct drbd_resource *resource, *tmp;
23828c2ecf20Sopenharmony_ci
23838c2ecf20Sopenharmony_ci	/* first remove proc,
23848c2ecf20Sopenharmony_ci	 * drbdsetup uses it's presence to detect
23858c2ecf20Sopenharmony_ci	 * whether DRBD is loaded.
23868c2ecf20Sopenharmony_ci	 * If we would get stuck in proc removal,
23878c2ecf20Sopenharmony_ci	 * but have netlink already deregistered,
23888c2ecf20Sopenharmony_ci	 * some drbdsetup commands may wait forever
23898c2ecf20Sopenharmony_ci	 * for an answer.
23908c2ecf20Sopenharmony_ci	 */
23918c2ecf20Sopenharmony_ci	if (drbd_proc)
23928c2ecf20Sopenharmony_ci		remove_proc_entry("drbd", NULL);
23938c2ecf20Sopenharmony_ci
23948c2ecf20Sopenharmony_ci	if (retry.wq)
23958c2ecf20Sopenharmony_ci		destroy_workqueue(retry.wq);
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ci	drbd_genl_unregister();
23988c2ecf20Sopenharmony_ci
23998c2ecf20Sopenharmony_ci	idr_for_each_entry(&drbd_devices, device, i)
24008c2ecf20Sopenharmony_ci		drbd_delete_device(device);
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci	/* not _rcu since, no other updater anymore. Genl already unregistered */
24038c2ecf20Sopenharmony_ci	for_each_resource_safe(resource, tmp, &drbd_resources) {
24048c2ecf20Sopenharmony_ci		list_del(&resource->resources);
24058c2ecf20Sopenharmony_ci		drbd_free_resource(resource);
24068c2ecf20Sopenharmony_ci	}
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	drbd_debugfs_cleanup();
24098c2ecf20Sopenharmony_ci
24108c2ecf20Sopenharmony_ci	drbd_destroy_mempools();
24118c2ecf20Sopenharmony_ci	unregister_blkdev(DRBD_MAJOR, "drbd");
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_ci	idr_destroy(&drbd_devices);
24148c2ecf20Sopenharmony_ci
24158c2ecf20Sopenharmony_ci	pr_info("module cleanup done.\n");
24168c2ecf20Sopenharmony_ci}
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_cistatic void drbd_init_workqueue(struct drbd_work_queue* wq)
24198c2ecf20Sopenharmony_ci{
24208c2ecf20Sopenharmony_ci	spin_lock_init(&wq->q_lock);
24218c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&wq->q);
24228c2ecf20Sopenharmony_ci	init_waitqueue_head(&wq->q_wait);
24238c2ecf20Sopenharmony_ci}
24248c2ecf20Sopenharmony_ci
24258c2ecf20Sopenharmony_cistruct completion_work {
24268c2ecf20Sopenharmony_ci	struct drbd_work w;
24278c2ecf20Sopenharmony_ci	struct completion done;
24288c2ecf20Sopenharmony_ci};
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_cistatic int w_complete(struct drbd_work *w, int cancel)
24318c2ecf20Sopenharmony_ci{
24328c2ecf20Sopenharmony_ci	struct completion_work *completion_work =
24338c2ecf20Sopenharmony_ci		container_of(w, struct completion_work, w);
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	complete(&completion_work->done);
24368c2ecf20Sopenharmony_ci	return 0;
24378c2ecf20Sopenharmony_ci}
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_civoid drbd_flush_workqueue(struct drbd_work_queue *work_queue)
24408c2ecf20Sopenharmony_ci{
24418c2ecf20Sopenharmony_ci	struct completion_work completion_work;
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci	completion_work.w.cb = w_complete;
24448c2ecf20Sopenharmony_ci	init_completion(&completion_work.done);
24458c2ecf20Sopenharmony_ci	drbd_queue_work(work_queue, &completion_work.w);
24468c2ecf20Sopenharmony_ci	wait_for_completion(&completion_work.done);
24478c2ecf20Sopenharmony_ci}
24488c2ecf20Sopenharmony_ci
24498c2ecf20Sopenharmony_cistruct drbd_resource *drbd_find_resource(const char *name)
24508c2ecf20Sopenharmony_ci{
24518c2ecf20Sopenharmony_ci	struct drbd_resource *resource;
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci	if (!name || !name[0])
24548c2ecf20Sopenharmony_ci		return NULL;
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci	rcu_read_lock();
24578c2ecf20Sopenharmony_ci	for_each_resource_rcu(resource, &drbd_resources) {
24588c2ecf20Sopenharmony_ci		if (!strcmp(resource->name, name)) {
24598c2ecf20Sopenharmony_ci			kref_get(&resource->kref);
24608c2ecf20Sopenharmony_ci			goto found;
24618c2ecf20Sopenharmony_ci		}
24628c2ecf20Sopenharmony_ci	}
24638c2ecf20Sopenharmony_ci	resource = NULL;
24648c2ecf20Sopenharmony_cifound:
24658c2ecf20Sopenharmony_ci	rcu_read_unlock();
24668c2ecf20Sopenharmony_ci	return resource;
24678c2ecf20Sopenharmony_ci}
24688c2ecf20Sopenharmony_ci
24698c2ecf20Sopenharmony_cistruct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
24708c2ecf20Sopenharmony_ci				     void *peer_addr, int peer_addr_len)
24718c2ecf20Sopenharmony_ci{
24728c2ecf20Sopenharmony_ci	struct drbd_resource *resource;
24738c2ecf20Sopenharmony_ci	struct drbd_connection *connection;
24748c2ecf20Sopenharmony_ci
24758c2ecf20Sopenharmony_ci	rcu_read_lock();
24768c2ecf20Sopenharmony_ci	for_each_resource_rcu(resource, &drbd_resources) {
24778c2ecf20Sopenharmony_ci		for_each_connection_rcu(connection, resource) {
24788c2ecf20Sopenharmony_ci			if (connection->my_addr_len == my_addr_len &&
24798c2ecf20Sopenharmony_ci			    connection->peer_addr_len == peer_addr_len &&
24808c2ecf20Sopenharmony_ci			    !memcmp(&connection->my_addr, my_addr, my_addr_len) &&
24818c2ecf20Sopenharmony_ci			    !memcmp(&connection->peer_addr, peer_addr, peer_addr_len)) {
24828c2ecf20Sopenharmony_ci				kref_get(&connection->kref);
24838c2ecf20Sopenharmony_ci				goto found;
24848c2ecf20Sopenharmony_ci			}
24858c2ecf20Sopenharmony_ci		}
24868c2ecf20Sopenharmony_ci	}
24878c2ecf20Sopenharmony_ci	connection = NULL;
24888c2ecf20Sopenharmony_cifound:
24898c2ecf20Sopenharmony_ci	rcu_read_unlock();
24908c2ecf20Sopenharmony_ci	return connection;
24918c2ecf20Sopenharmony_ci}
24928c2ecf20Sopenharmony_ci
24938c2ecf20Sopenharmony_cistatic int drbd_alloc_socket(struct drbd_socket *socket)
24948c2ecf20Sopenharmony_ci{
24958c2ecf20Sopenharmony_ci	socket->rbuf = (void *) __get_free_page(GFP_KERNEL);
24968c2ecf20Sopenharmony_ci	if (!socket->rbuf)
24978c2ecf20Sopenharmony_ci		return -ENOMEM;
24988c2ecf20Sopenharmony_ci	socket->sbuf = (void *) __get_free_page(GFP_KERNEL);
24998c2ecf20Sopenharmony_ci	if (!socket->sbuf)
25008c2ecf20Sopenharmony_ci		return -ENOMEM;
25018c2ecf20Sopenharmony_ci	return 0;
25028c2ecf20Sopenharmony_ci}
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_cistatic void drbd_free_socket(struct drbd_socket *socket)
25058c2ecf20Sopenharmony_ci{
25068c2ecf20Sopenharmony_ci	free_page((unsigned long) socket->sbuf);
25078c2ecf20Sopenharmony_ci	free_page((unsigned long) socket->rbuf);
25088c2ecf20Sopenharmony_ci}
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_civoid conn_free_crypto(struct drbd_connection *connection)
25118c2ecf20Sopenharmony_ci{
25128c2ecf20Sopenharmony_ci	drbd_free_sock(connection);
25138c2ecf20Sopenharmony_ci
25148c2ecf20Sopenharmony_ci	crypto_free_shash(connection->csums_tfm);
25158c2ecf20Sopenharmony_ci	crypto_free_shash(connection->verify_tfm);
25168c2ecf20Sopenharmony_ci	crypto_free_shash(connection->cram_hmac_tfm);
25178c2ecf20Sopenharmony_ci	crypto_free_shash(connection->integrity_tfm);
25188c2ecf20Sopenharmony_ci	crypto_free_shash(connection->peer_integrity_tfm);
25198c2ecf20Sopenharmony_ci	kfree(connection->int_dig_in);
25208c2ecf20Sopenharmony_ci	kfree(connection->int_dig_vv);
25218c2ecf20Sopenharmony_ci
25228c2ecf20Sopenharmony_ci	connection->csums_tfm = NULL;
25238c2ecf20Sopenharmony_ci	connection->verify_tfm = NULL;
25248c2ecf20Sopenharmony_ci	connection->cram_hmac_tfm = NULL;
25258c2ecf20Sopenharmony_ci	connection->integrity_tfm = NULL;
25268c2ecf20Sopenharmony_ci	connection->peer_integrity_tfm = NULL;
25278c2ecf20Sopenharmony_ci	connection->int_dig_in = NULL;
25288c2ecf20Sopenharmony_ci	connection->int_dig_vv = NULL;
25298c2ecf20Sopenharmony_ci}
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_ciint set_resource_options(struct drbd_resource *resource, struct res_opts *res_opts)
25328c2ecf20Sopenharmony_ci{
25338c2ecf20Sopenharmony_ci	struct drbd_connection *connection;
25348c2ecf20Sopenharmony_ci	cpumask_var_t new_cpu_mask;
25358c2ecf20Sopenharmony_ci	int err;
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci	if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL))
25388c2ecf20Sopenharmony_ci		return -ENOMEM;
25398c2ecf20Sopenharmony_ci
25408c2ecf20Sopenharmony_ci	/* silently ignore cpu mask on UP kernel */
25418c2ecf20Sopenharmony_ci	if (nr_cpu_ids > 1 && res_opts->cpu_mask[0] != 0) {
25428c2ecf20Sopenharmony_ci		err = bitmap_parse(res_opts->cpu_mask, DRBD_CPU_MASK_SIZE,
25438c2ecf20Sopenharmony_ci				   cpumask_bits(new_cpu_mask), nr_cpu_ids);
25448c2ecf20Sopenharmony_ci		if (err == -EOVERFLOW) {
25458c2ecf20Sopenharmony_ci			/* So what. mask it out. */
25468c2ecf20Sopenharmony_ci			cpumask_var_t tmp_cpu_mask;
25478c2ecf20Sopenharmony_ci			if (zalloc_cpumask_var(&tmp_cpu_mask, GFP_KERNEL)) {
25488c2ecf20Sopenharmony_ci				cpumask_setall(tmp_cpu_mask);
25498c2ecf20Sopenharmony_ci				cpumask_and(new_cpu_mask, new_cpu_mask, tmp_cpu_mask);
25508c2ecf20Sopenharmony_ci				drbd_warn(resource, "Overflow in bitmap_parse(%.12s%s), truncating to %u bits\n",
25518c2ecf20Sopenharmony_ci					res_opts->cpu_mask,
25528c2ecf20Sopenharmony_ci					strlen(res_opts->cpu_mask) > 12 ? "..." : "",
25538c2ecf20Sopenharmony_ci					nr_cpu_ids);
25548c2ecf20Sopenharmony_ci				free_cpumask_var(tmp_cpu_mask);
25558c2ecf20Sopenharmony_ci				err = 0;
25568c2ecf20Sopenharmony_ci			}
25578c2ecf20Sopenharmony_ci		}
25588c2ecf20Sopenharmony_ci		if (err) {
25598c2ecf20Sopenharmony_ci			drbd_warn(resource, "bitmap_parse() failed with %d\n", err);
25608c2ecf20Sopenharmony_ci			/* retcode = ERR_CPU_MASK_PARSE; */
25618c2ecf20Sopenharmony_ci			goto fail;
25628c2ecf20Sopenharmony_ci		}
25638c2ecf20Sopenharmony_ci	}
25648c2ecf20Sopenharmony_ci	resource->res_opts = *res_opts;
25658c2ecf20Sopenharmony_ci	if (cpumask_empty(new_cpu_mask))
25668c2ecf20Sopenharmony_ci		drbd_calc_cpu_mask(&new_cpu_mask);
25678c2ecf20Sopenharmony_ci	if (!cpumask_equal(resource->cpu_mask, new_cpu_mask)) {
25688c2ecf20Sopenharmony_ci		cpumask_copy(resource->cpu_mask, new_cpu_mask);
25698c2ecf20Sopenharmony_ci		for_each_connection_rcu(connection, resource) {
25708c2ecf20Sopenharmony_ci			connection->receiver.reset_cpu_mask = 1;
25718c2ecf20Sopenharmony_ci			connection->ack_receiver.reset_cpu_mask = 1;
25728c2ecf20Sopenharmony_ci			connection->worker.reset_cpu_mask = 1;
25738c2ecf20Sopenharmony_ci		}
25748c2ecf20Sopenharmony_ci	}
25758c2ecf20Sopenharmony_ci	err = 0;
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_cifail:
25788c2ecf20Sopenharmony_ci	free_cpumask_var(new_cpu_mask);
25798c2ecf20Sopenharmony_ci	return err;
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci}
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_cistruct drbd_resource *drbd_create_resource(const char *name)
25848c2ecf20Sopenharmony_ci{
25858c2ecf20Sopenharmony_ci	struct drbd_resource *resource;
25868c2ecf20Sopenharmony_ci
25878c2ecf20Sopenharmony_ci	resource = kzalloc(sizeof(struct drbd_resource), GFP_KERNEL);
25888c2ecf20Sopenharmony_ci	if (!resource)
25898c2ecf20Sopenharmony_ci		goto fail;
25908c2ecf20Sopenharmony_ci	resource->name = kstrdup(name, GFP_KERNEL);
25918c2ecf20Sopenharmony_ci	if (!resource->name)
25928c2ecf20Sopenharmony_ci		goto fail_free_resource;
25938c2ecf20Sopenharmony_ci	if (!zalloc_cpumask_var(&resource->cpu_mask, GFP_KERNEL))
25948c2ecf20Sopenharmony_ci		goto fail_free_name;
25958c2ecf20Sopenharmony_ci	kref_init(&resource->kref);
25968c2ecf20Sopenharmony_ci	idr_init(&resource->devices);
25978c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&resource->connections);
25988c2ecf20Sopenharmony_ci	resource->write_ordering = WO_BDEV_FLUSH;
25998c2ecf20Sopenharmony_ci	list_add_tail_rcu(&resource->resources, &drbd_resources);
26008c2ecf20Sopenharmony_ci	mutex_init(&resource->conf_update);
26018c2ecf20Sopenharmony_ci	mutex_init(&resource->adm_mutex);
26028c2ecf20Sopenharmony_ci	spin_lock_init(&resource->req_lock);
26038c2ecf20Sopenharmony_ci	drbd_debugfs_resource_add(resource);
26048c2ecf20Sopenharmony_ci	return resource;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_cifail_free_name:
26078c2ecf20Sopenharmony_ci	kfree(resource->name);
26088c2ecf20Sopenharmony_cifail_free_resource:
26098c2ecf20Sopenharmony_ci	kfree(resource);
26108c2ecf20Sopenharmony_cifail:
26118c2ecf20Sopenharmony_ci	return NULL;
26128c2ecf20Sopenharmony_ci}
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci/* caller must be under adm_mutex */
26158c2ecf20Sopenharmony_cistruct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
26168c2ecf20Sopenharmony_ci{
26178c2ecf20Sopenharmony_ci	struct drbd_resource *resource;
26188c2ecf20Sopenharmony_ci	struct drbd_connection *connection;
26198c2ecf20Sopenharmony_ci
26208c2ecf20Sopenharmony_ci	connection = kzalloc(sizeof(struct drbd_connection), GFP_KERNEL);
26218c2ecf20Sopenharmony_ci	if (!connection)
26228c2ecf20Sopenharmony_ci		return NULL;
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	if (drbd_alloc_socket(&connection->data))
26258c2ecf20Sopenharmony_ci		goto fail;
26268c2ecf20Sopenharmony_ci	if (drbd_alloc_socket(&connection->meta))
26278c2ecf20Sopenharmony_ci		goto fail;
26288c2ecf20Sopenharmony_ci
26298c2ecf20Sopenharmony_ci	connection->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
26308c2ecf20Sopenharmony_ci	if (!connection->current_epoch)
26318c2ecf20Sopenharmony_ci		goto fail;
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&connection->transfer_log);
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&connection->current_epoch->list);
26368c2ecf20Sopenharmony_ci	connection->epochs = 1;
26378c2ecf20Sopenharmony_ci	spin_lock_init(&connection->epoch_lock);
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci	connection->send.seen_any_write_yet = false;
26408c2ecf20Sopenharmony_ci	connection->send.current_epoch_nr = 0;
26418c2ecf20Sopenharmony_ci	connection->send.current_epoch_writes = 0;
26428c2ecf20Sopenharmony_ci
26438c2ecf20Sopenharmony_ci	resource = drbd_create_resource(name);
26448c2ecf20Sopenharmony_ci	if (!resource)
26458c2ecf20Sopenharmony_ci		goto fail;
26468c2ecf20Sopenharmony_ci
26478c2ecf20Sopenharmony_ci	connection->cstate = C_STANDALONE;
26488c2ecf20Sopenharmony_ci	mutex_init(&connection->cstate_mutex);
26498c2ecf20Sopenharmony_ci	init_waitqueue_head(&connection->ping_wait);
26508c2ecf20Sopenharmony_ci	idr_init(&connection->peer_devices);
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci	drbd_init_workqueue(&connection->sender_work);
26538c2ecf20Sopenharmony_ci	mutex_init(&connection->data.mutex);
26548c2ecf20Sopenharmony_ci	mutex_init(&connection->meta.mutex);
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	drbd_thread_init(resource, &connection->receiver, drbd_receiver, "receiver");
26578c2ecf20Sopenharmony_ci	connection->receiver.connection = connection;
26588c2ecf20Sopenharmony_ci	drbd_thread_init(resource, &connection->worker, drbd_worker, "worker");
26598c2ecf20Sopenharmony_ci	connection->worker.connection = connection;
26608c2ecf20Sopenharmony_ci	drbd_thread_init(resource, &connection->ack_receiver, drbd_ack_receiver, "ack_recv");
26618c2ecf20Sopenharmony_ci	connection->ack_receiver.connection = connection;
26628c2ecf20Sopenharmony_ci
26638c2ecf20Sopenharmony_ci	kref_init(&connection->kref);
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci	connection->resource = resource;
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci	if (set_resource_options(resource, res_opts))
26688c2ecf20Sopenharmony_ci		goto fail_resource;
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	kref_get(&resource->kref);
26718c2ecf20Sopenharmony_ci	list_add_tail_rcu(&connection->connections, &resource->connections);
26728c2ecf20Sopenharmony_ci	drbd_debugfs_connection_add(connection);
26738c2ecf20Sopenharmony_ci	return connection;
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_cifail_resource:
26768c2ecf20Sopenharmony_ci	list_del(&resource->resources);
26778c2ecf20Sopenharmony_ci	drbd_free_resource(resource);
26788c2ecf20Sopenharmony_cifail:
26798c2ecf20Sopenharmony_ci	kfree(connection->current_epoch);
26808c2ecf20Sopenharmony_ci	drbd_free_socket(&connection->meta);
26818c2ecf20Sopenharmony_ci	drbd_free_socket(&connection->data);
26828c2ecf20Sopenharmony_ci	kfree(connection);
26838c2ecf20Sopenharmony_ci	return NULL;
26848c2ecf20Sopenharmony_ci}
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_civoid drbd_destroy_connection(struct kref *kref)
26878c2ecf20Sopenharmony_ci{
26888c2ecf20Sopenharmony_ci	struct drbd_connection *connection = container_of(kref, struct drbd_connection, kref);
26898c2ecf20Sopenharmony_ci	struct drbd_resource *resource = connection->resource;
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_ci	if (atomic_read(&connection->current_epoch->epoch_size) !=  0)
26928c2ecf20Sopenharmony_ci		drbd_err(connection, "epoch_size:%d\n", atomic_read(&connection->current_epoch->epoch_size));
26938c2ecf20Sopenharmony_ci	kfree(connection->current_epoch);
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci	idr_destroy(&connection->peer_devices);
26968c2ecf20Sopenharmony_ci
26978c2ecf20Sopenharmony_ci	drbd_free_socket(&connection->meta);
26988c2ecf20Sopenharmony_ci	drbd_free_socket(&connection->data);
26998c2ecf20Sopenharmony_ci	kfree(connection->int_dig_in);
27008c2ecf20Sopenharmony_ci	kfree(connection->int_dig_vv);
27018c2ecf20Sopenharmony_ci	memset(connection, 0xfc, sizeof(*connection));
27028c2ecf20Sopenharmony_ci	kfree(connection);
27038c2ecf20Sopenharmony_ci	kref_put(&resource->kref, drbd_destroy_resource);
27048c2ecf20Sopenharmony_ci}
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_cistatic int init_submitter(struct drbd_device *device)
27078c2ecf20Sopenharmony_ci{
27088c2ecf20Sopenharmony_ci	/* opencoded create_singlethread_workqueue(),
27098c2ecf20Sopenharmony_ci	 * to be able to say "drbd%d", ..., minor */
27108c2ecf20Sopenharmony_ci	device->submit.wq =
27118c2ecf20Sopenharmony_ci		alloc_ordered_workqueue("drbd%u_submit", WQ_MEM_RECLAIM, device->minor);
27128c2ecf20Sopenharmony_ci	if (!device->submit.wq)
27138c2ecf20Sopenharmony_ci		return -ENOMEM;
27148c2ecf20Sopenharmony_ci
27158c2ecf20Sopenharmony_ci	INIT_WORK(&device->submit.worker, do_submit);
27168c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->submit.writes);
27178c2ecf20Sopenharmony_ci	return 0;
27188c2ecf20Sopenharmony_ci}
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_cienum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsigned int minor)
27218c2ecf20Sopenharmony_ci{
27228c2ecf20Sopenharmony_ci	struct drbd_resource *resource = adm_ctx->resource;
27238c2ecf20Sopenharmony_ci	struct drbd_connection *connection, *n;
27248c2ecf20Sopenharmony_ci	struct drbd_device *device;
27258c2ecf20Sopenharmony_ci	struct drbd_peer_device *peer_device, *tmp_peer_device;
27268c2ecf20Sopenharmony_ci	struct gendisk *disk;
27278c2ecf20Sopenharmony_ci	struct request_queue *q;
27288c2ecf20Sopenharmony_ci	int id;
27298c2ecf20Sopenharmony_ci	int vnr = adm_ctx->volume;
27308c2ecf20Sopenharmony_ci	enum drbd_ret_code err = ERR_NOMEM;
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci	device = minor_to_device(minor);
27338c2ecf20Sopenharmony_ci	if (device)
27348c2ecf20Sopenharmony_ci		return ERR_MINOR_OR_VOLUME_EXISTS;
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	/* GFP_KERNEL, we are outside of all write-out paths */
27378c2ecf20Sopenharmony_ci	device = kzalloc(sizeof(struct drbd_device), GFP_KERNEL);
27388c2ecf20Sopenharmony_ci	if (!device)
27398c2ecf20Sopenharmony_ci		return ERR_NOMEM;
27408c2ecf20Sopenharmony_ci	kref_init(&device->kref);
27418c2ecf20Sopenharmony_ci
27428c2ecf20Sopenharmony_ci	kref_get(&resource->kref);
27438c2ecf20Sopenharmony_ci	device->resource = resource;
27448c2ecf20Sopenharmony_ci	device->minor = minor;
27458c2ecf20Sopenharmony_ci	device->vnr = vnr;
27468c2ecf20Sopenharmony_ci
27478c2ecf20Sopenharmony_ci	drbd_init_set_defaults(device);
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ci	q = blk_alloc_queue(NUMA_NO_NODE);
27508c2ecf20Sopenharmony_ci	if (!q)
27518c2ecf20Sopenharmony_ci		goto out_no_q;
27528c2ecf20Sopenharmony_ci	device->rq_queue = q;
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci	disk = alloc_disk(1);
27558c2ecf20Sopenharmony_ci	if (!disk)
27568c2ecf20Sopenharmony_ci		goto out_no_disk;
27578c2ecf20Sopenharmony_ci	device->vdisk = disk;
27588c2ecf20Sopenharmony_ci
27598c2ecf20Sopenharmony_ci	set_disk_ro(disk, true);
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	disk->queue = q;
27628c2ecf20Sopenharmony_ci	disk->major = DRBD_MAJOR;
27638c2ecf20Sopenharmony_ci	disk->first_minor = minor;
27648c2ecf20Sopenharmony_ci	disk->fops = &drbd_ops;
27658c2ecf20Sopenharmony_ci	sprintf(disk->disk_name, "drbd%d", minor);
27668c2ecf20Sopenharmony_ci	disk->private_data = device;
27678c2ecf20Sopenharmony_ci
27688c2ecf20Sopenharmony_ci	blk_queue_write_cache(q, true, true);
27698c2ecf20Sopenharmony_ci	/* Setting the max_hw_sectors to an odd value of 8kibyte here
27708c2ecf20Sopenharmony_ci	   This triggers a max_bio_size message upon first attach or connect */
27718c2ecf20Sopenharmony_ci	blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	device->md_io.page = alloc_page(GFP_KERNEL);
27748c2ecf20Sopenharmony_ci	if (!device->md_io.page)
27758c2ecf20Sopenharmony_ci		goto out_no_io_page;
27768c2ecf20Sopenharmony_ci
27778c2ecf20Sopenharmony_ci	if (drbd_bm_init(device))
27788c2ecf20Sopenharmony_ci		goto out_no_bitmap;
27798c2ecf20Sopenharmony_ci	device->read_requests = RB_ROOT;
27808c2ecf20Sopenharmony_ci	device->write_requests = RB_ROOT;
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_ci	id = idr_alloc(&drbd_devices, device, minor, minor + 1, GFP_KERNEL);
27838c2ecf20Sopenharmony_ci	if (id < 0) {
27848c2ecf20Sopenharmony_ci		if (id == -ENOSPC)
27858c2ecf20Sopenharmony_ci			err = ERR_MINOR_OR_VOLUME_EXISTS;
27868c2ecf20Sopenharmony_ci		goto out_no_minor_idr;
27878c2ecf20Sopenharmony_ci	}
27888c2ecf20Sopenharmony_ci	kref_get(&device->kref);
27898c2ecf20Sopenharmony_ci
27908c2ecf20Sopenharmony_ci	id = idr_alloc(&resource->devices, device, vnr, vnr + 1, GFP_KERNEL);
27918c2ecf20Sopenharmony_ci	if (id < 0) {
27928c2ecf20Sopenharmony_ci		if (id == -ENOSPC)
27938c2ecf20Sopenharmony_ci			err = ERR_MINOR_OR_VOLUME_EXISTS;
27948c2ecf20Sopenharmony_ci		goto out_idr_remove_minor;
27958c2ecf20Sopenharmony_ci	}
27968c2ecf20Sopenharmony_ci	kref_get(&device->kref);
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->peer_devices);
27998c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&device->pending_bitmap_io);
28008c2ecf20Sopenharmony_ci	for_each_connection(connection, resource) {
28018c2ecf20Sopenharmony_ci		peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL);
28028c2ecf20Sopenharmony_ci		if (!peer_device)
28038c2ecf20Sopenharmony_ci			goto out_idr_remove_from_resource;
28048c2ecf20Sopenharmony_ci		peer_device->connection = connection;
28058c2ecf20Sopenharmony_ci		peer_device->device = device;
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci		list_add(&peer_device->peer_devices, &device->peer_devices);
28088c2ecf20Sopenharmony_ci		kref_get(&device->kref);
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci		id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL);
28118c2ecf20Sopenharmony_ci		if (id < 0) {
28128c2ecf20Sopenharmony_ci			if (id == -ENOSPC)
28138c2ecf20Sopenharmony_ci				err = ERR_INVALID_REQUEST;
28148c2ecf20Sopenharmony_ci			goto out_idr_remove_from_resource;
28158c2ecf20Sopenharmony_ci		}
28168c2ecf20Sopenharmony_ci		kref_get(&connection->kref);
28178c2ecf20Sopenharmony_ci		INIT_WORK(&peer_device->send_acks_work, drbd_send_acks_wf);
28188c2ecf20Sopenharmony_ci	}
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	if (init_submitter(device)) {
28218c2ecf20Sopenharmony_ci		err = ERR_NOMEM;
28228c2ecf20Sopenharmony_ci		goto out_idr_remove_from_resource;
28238c2ecf20Sopenharmony_ci	}
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	add_disk(disk);
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	/* inherit the connection state */
28288c2ecf20Sopenharmony_ci	device->state.conn = first_connection(resource)->cstate;
28298c2ecf20Sopenharmony_ci	if (device->state.conn == C_WF_REPORT_PARAMS) {
28308c2ecf20Sopenharmony_ci		for_each_peer_device(peer_device, device)
28318c2ecf20Sopenharmony_ci			drbd_connected(peer_device);
28328c2ecf20Sopenharmony_ci	}
28338c2ecf20Sopenharmony_ci	/* move to create_peer_device() */
28348c2ecf20Sopenharmony_ci	for_each_peer_device(peer_device, device)
28358c2ecf20Sopenharmony_ci		drbd_debugfs_peer_device_add(peer_device);
28368c2ecf20Sopenharmony_ci	drbd_debugfs_device_add(device);
28378c2ecf20Sopenharmony_ci	return NO_ERROR;
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ciout_idr_remove_from_resource:
28408c2ecf20Sopenharmony_ci	for_each_connection_safe(connection, n, resource) {
28418c2ecf20Sopenharmony_ci		peer_device = idr_remove(&connection->peer_devices, vnr);
28428c2ecf20Sopenharmony_ci		if (peer_device)
28438c2ecf20Sopenharmony_ci			kref_put(&connection->kref, drbd_destroy_connection);
28448c2ecf20Sopenharmony_ci	}
28458c2ecf20Sopenharmony_ci	for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
28468c2ecf20Sopenharmony_ci		list_del(&peer_device->peer_devices);
28478c2ecf20Sopenharmony_ci		kfree(peer_device);
28488c2ecf20Sopenharmony_ci	}
28498c2ecf20Sopenharmony_ci	idr_remove(&resource->devices, vnr);
28508c2ecf20Sopenharmony_ciout_idr_remove_minor:
28518c2ecf20Sopenharmony_ci	idr_remove(&drbd_devices, minor);
28528c2ecf20Sopenharmony_ci	synchronize_rcu();
28538c2ecf20Sopenharmony_ciout_no_minor_idr:
28548c2ecf20Sopenharmony_ci	drbd_bm_cleanup(device);
28558c2ecf20Sopenharmony_ciout_no_bitmap:
28568c2ecf20Sopenharmony_ci	__free_page(device->md_io.page);
28578c2ecf20Sopenharmony_ciout_no_io_page:
28588c2ecf20Sopenharmony_ci	put_disk(disk);
28598c2ecf20Sopenharmony_ciout_no_disk:
28608c2ecf20Sopenharmony_ci	blk_cleanup_queue(q);
28618c2ecf20Sopenharmony_ciout_no_q:
28628c2ecf20Sopenharmony_ci	kref_put(&resource->kref, drbd_destroy_resource);
28638c2ecf20Sopenharmony_ci	kfree(device);
28648c2ecf20Sopenharmony_ci	return err;
28658c2ecf20Sopenharmony_ci}
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_civoid drbd_delete_device(struct drbd_device *device)
28688c2ecf20Sopenharmony_ci{
28698c2ecf20Sopenharmony_ci	struct drbd_resource *resource = device->resource;
28708c2ecf20Sopenharmony_ci	struct drbd_connection *connection;
28718c2ecf20Sopenharmony_ci	struct drbd_peer_device *peer_device;
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci	/* move to free_peer_device() */
28748c2ecf20Sopenharmony_ci	for_each_peer_device(peer_device, device)
28758c2ecf20Sopenharmony_ci		drbd_debugfs_peer_device_cleanup(peer_device);
28768c2ecf20Sopenharmony_ci	drbd_debugfs_device_cleanup(device);
28778c2ecf20Sopenharmony_ci	for_each_connection(connection, resource) {
28788c2ecf20Sopenharmony_ci		idr_remove(&connection->peer_devices, device->vnr);
28798c2ecf20Sopenharmony_ci		kref_put(&device->kref, drbd_destroy_device);
28808c2ecf20Sopenharmony_ci	}
28818c2ecf20Sopenharmony_ci	idr_remove(&resource->devices, device->vnr);
28828c2ecf20Sopenharmony_ci	kref_put(&device->kref, drbd_destroy_device);
28838c2ecf20Sopenharmony_ci	idr_remove(&drbd_devices, device_to_minor(device));
28848c2ecf20Sopenharmony_ci	kref_put(&device->kref, drbd_destroy_device);
28858c2ecf20Sopenharmony_ci	del_gendisk(device->vdisk);
28868c2ecf20Sopenharmony_ci	synchronize_rcu();
28878c2ecf20Sopenharmony_ci	kref_put(&device->kref, drbd_destroy_device);
28888c2ecf20Sopenharmony_ci}
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_cistatic int __init drbd_init(void)
28918c2ecf20Sopenharmony_ci{
28928c2ecf20Sopenharmony_ci	int err;
28938c2ecf20Sopenharmony_ci
28948c2ecf20Sopenharmony_ci	if (drbd_minor_count < DRBD_MINOR_COUNT_MIN || drbd_minor_count > DRBD_MINOR_COUNT_MAX) {
28958c2ecf20Sopenharmony_ci		pr_err("invalid minor_count (%d)\n", drbd_minor_count);
28968c2ecf20Sopenharmony_ci#ifdef MODULE
28978c2ecf20Sopenharmony_ci		return -EINVAL;
28988c2ecf20Sopenharmony_ci#else
28998c2ecf20Sopenharmony_ci		drbd_minor_count = DRBD_MINOR_COUNT_DEF;
29008c2ecf20Sopenharmony_ci#endif
29018c2ecf20Sopenharmony_ci	}
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci	err = register_blkdev(DRBD_MAJOR, "drbd");
29048c2ecf20Sopenharmony_ci	if (err) {
29058c2ecf20Sopenharmony_ci		pr_err("unable to register block device major %d\n",
29068c2ecf20Sopenharmony_ci		       DRBD_MAJOR);
29078c2ecf20Sopenharmony_ci		return err;
29088c2ecf20Sopenharmony_ci	}
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci	/*
29118c2ecf20Sopenharmony_ci	 * allocate all necessary structs
29128c2ecf20Sopenharmony_ci	 */
29138c2ecf20Sopenharmony_ci	init_waitqueue_head(&drbd_pp_wait);
29148c2ecf20Sopenharmony_ci
29158c2ecf20Sopenharmony_ci	drbd_proc = NULL; /* play safe for drbd_cleanup */
29168c2ecf20Sopenharmony_ci	idr_init(&drbd_devices);
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci	mutex_init(&resources_mutex);
29198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&drbd_resources);
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci	err = drbd_genl_register();
29228c2ecf20Sopenharmony_ci	if (err) {
29238c2ecf20Sopenharmony_ci		pr_err("unable to register generic netlink family\n");
29248c2ecf20Sopenharmony_ci		goto fail;
29258c2ecf20Sopenharmony_ci	}
29268c2ecf20Sopenharmony_ci
29278c2ecf20Sopenharmony_ci	err = drbd_create_mempools();
29288c2ecf20Sopenharmony_ci	if (err)
29298c2ecf20Sopenharmony_ci		goto fail;
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	err = -ENOMEM;
29328c2ecf20Sopenharmony_ci	drbd_proc = proc_create_single("drbd", S_IFREG | 0444 , NULL, drbd_seq_show);
29338c2ecf20Sopenharmony_ci	if (!drbd_proc)	{
29348c2ecf20Sopenharmony_ci		pr_err("unable to register proc file\n");
29358c2ecf20Sopenharmony_ci		goto fail;
29368c2ecf20Sopenharmony_ci	}
29378c2ecf20Sopenharmony_ci
29388c2ecf20Sopenharmony_ci	retry.wq = create_singlethread_workqueue("drbd-reissue");
29398c2ecf20Sopenharmony_ci	if (!retry.wq) {
29408c2ecf20Sopenharmony_ci		pr_err("unable to create retry workqueue\n");
29418c2ecf20Sopenharmony_ci		goto fail;
29428c2ecf20Sopenharmony_ci	}
29438c2ecf20Sopenharmony_ci	INIT_WORK(&retry.worker, do_retry);
29448c2ecf20Sopenharmony_ci	spin_lock_init(&retry.lock);
29458c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&retry.writes);
29468c2ecf20Sopenharmony_ci
29478c2ecf20Sopenharmony_ci	drbd_debugfs_init();
29488c2ecf20Sopenharmony_ci
29498c2ecf20Sopenharmony_ci	pr_info("initialized. "
29508c2ecf20Sopenharmony_ci	       "Version: " REL_VERSION " (api:%d/proto:%d-%d)\n",
29518c2ecf20Sopenharmony_ci	       API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX);
29528c2ecf20Sopenharmony_ci	pr_info("%s\n", drbd_buildtag());
29538c2ecf20Sopenharmony_ci	pr_info("registered as block device major %d\n", DRBD_MAJOR);
29548c2ecf20Sopenharmony_ci	return 0; /* Success! */
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_cifail:
29578c2ecf20Sopenharmony_ci	drbd_cleanup();
29588c2ecf20Sopenharmony_ci	if (err == -ENOMEM)
29598c2ecf20Sopenharmony_ci		pr_err("ran out of memory\n");
29608c2ecf20Sopenharmony_ci	else
29618c2ecf20Sopenharmony_ci		pr_err("initialization failure\n");
29628c2ecf20Sopenharmony_ci	return err;
29638c2ecf20Sopenharmony_ci}
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_cistatic void drbd_free_one_sock(struct drbd_socket *ds)
29668c2ecf20Sopenharmony_ci{
29678c2ecf20Sopenharmony_ci	struct socket *s;
29688c2ecf20Sopenharmony_ci	mutex_lock(&ds->mutex);
29698c2ecf20Sopenharmony_ci	s = ds->socket;
29708c2ecf20Sopenharmony_ci	ds->socket = NULL;
29718c2ecf20Sopenharmony_ci	mutex_unlock(&ds->mutex);
29728c2ecf20Sopenharmony_ci	if (s) {
29738c2ecf20Sopenharmony_ci		/* so debugfs does not need to mutex_lock() */
29748c2ecf20Sopenharmony_ci		synchronize_rcu();
29758c2ecf20Sopenharmony_ci		kernel_sock_shutdown(s, SHUT_RDWR);
29768c2ecf20Sopenharmony_ci		sock_release(s);
29778c2ecf20Sopenharmony_ci	}
29788c2ecf20Sopenharmony_ci}
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_civoid drbd_free_sock(struct drbd_connection *connection)
29818c2ecf20Sopenharmony_ci{
29828c2ecf20Sopenharmony_ci	if (connection->data.socket)
29838c2ecf20Sopenharmony_ci		drbd_free_one_sock(&connection->data);
29848c2ecf20Sopenharmony_ci	if (connection->meta.socket)
29858c2ecf20Sopenharmony_ci		drbd_free_one_sock(&connection->meta);
29868c2ecf20Sopenharmony_ci}
29878c2ecf20Sopenharmony_ci
29888c2ecf20Sopenharmony_ci/* meta data management */
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_civoid conn_md_sync(struct drbd_connection *connection)
29918c2ecf20Sopenharmony_ci{
29928c2ecf20Sopenharmony_ci	struct drbd_peer_device *peer_device;
29938c2ecf20Sopenharmony_ci	int vnr;
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci	rcu_read_lock();
29968c2ecf20Sopenharmony_ci	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
29978c2ecf20Sopenharmony_ci		struct drbd_device *device = peer_device->device;
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci		kref_get(&device->kref);
30008c2ecf20Sopenharmony_ci		rcu_read_unlock();
30018c2ecf20Sopenharmony_ci		drbd_md_sync(device);
30028c2ecf20Sopenharmony_ci		kref_put(&device->kref, drbd_destroy_device);
30038c2ecf20Sopenharmony_ci		rcu_read_lock();
30048c2ecf20Sopenharmony_ci	}
30058c2ecf20Sopenharmony_ci	rcu_read_unlock();
30068c2ecf20Sopenharmony_ci}
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_ci/* aligned 4kByte */
30098c2ecf20Sopenharmony_cistruct meta_data_on_disk {
30108c2ecf20Sopenharmony_ci	u64 la_size_sect;      /* last agreed size. */
30118c2ecf20Sopenharmony_ci	u64 uuid[UI_SIZE];   /* UUIDs. */
30128c2ecf20Sopenharmony_ci	u64 device_uuid;
30138c2ecf20Sopenharmony_ci	u64 reserved_u64_1;
30148c2ecf20Sopenharmony_ci	u32 flags;             /* MDF */
30158c2ecf20Sopenharmony_ci	u32 magic;
30168c2ecf20Sopenharmony_ci	u32 md_size_sect;
30178c2ecf20Sopenharmony_ci	u32 al_offset;         /* offset to this block */
30188c2ecf20Sopenharmony_ci	u32 al_nr_extents;     /* important for restoring the AL (userspace) */
30198c2ecf20Sopenharmony_ci	      /* `-- act_log->nr_elements <-- ldev->dc.al_extents */
30208c2ecf20Sopenharmony_ci	u32 bm_offset;         /* offset to the bitmap, from here */
30218c2ecf20Sopenharmony_ci	u32 bm_bytes_per_bit;  /* BM_BLOCK_SIZE */
30228c2ecf20Sopenharmony_ci	u32 la_peer_max_bio_size;   /* last peer max_bio_size */
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci	/* see al_tr_number_to_on_disk_sector() */
30258c2ecf20Sopenharmony_ci	u32 al_stripes;
30268c2ecf20Sopenharmony_ci	u32 al_stripe_size_4k;
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci	u8 reserved_u8[4096 - (7*8 + 10*4)];
30298c2ecf20Sopenharmony_ci} __packed;
30308c2ecf20Sopenharmony_ci
30318c2ecf20Sopenharmony_ci
30328c2ecf20Sopenharmony_ci
30338c2ecf20Sopenharmony_civoid drbd_md_write(struct drbd_device *device, void *b)
30348c2ecf20Sopenharmony_ci{
30358c2ecf20Sopenharmony_ci	struct meta_data_on_disk *buffer = b;
30368c2ecf20Sopenharmony_ci	sector_t sector;
30378c2ecf20Sopenharmony_ci	int i;
30388c2ecf20Sopenharmony_ci
30398c2ecf20Sopenharmony_ci	memset(buffer, 0, sizeof(*buffer));
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci	buffer->la_size_sect = cpu_to_be64(get_capacity(device->vdisk));
30428c2ecf20Sopenharmony_ci	for (i = UI_CURRENT; i < UI_SIZE; i++)
30438c2ecf20Sopenharmony_ci		buffer->uuid[i] = cpu_to_be64(device->ldev->md.uuid[i]);
30448c2ecf20Sopenharmony_ci	buffer->flags = cpu_to_be32(device->ldev->md.flags);
30458c2ecf20Sopenharmony_ci	buffer->magic = cpu_to_be32(DRBD_MD_MAGIC_84_UNCLEAN);
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	buffer->md_size_sect  = cpu_to_be32(device->ldev->md.md_size_sect);
30488c2ecf20Sopenharmony_ci	buffer->al_offset     = cpu_to_be32(device->ldev->md.al_offset);
30498c2ecf20Sopenharmony_ci	buffer->al_nr_extents = cpu_to_be32(device->act_log->nr_elements);
30508c2ecf20Sopenharmony_ci	buffer->bm_bytes_per_bit = cpu_to_be32(BM_BLOCK_SIZE);
30518c2ecf20Sopenharmony_ci	buffer->device_uuid = cpu_to_be64(device->ldev->md.device_uuid);
30528c2ecf20Sopenharmony_ci
30538c2ecf20Sopenharmony_ci	buffer->bm_offset = cpu_to_be32(device->ldev->md.bm_offset);
30548c2ecf20Sopenharmony_ci	buffer->la_peer_max_bio_size = cpu_to_be32(device->peer_max_bio_size);
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci	buffer->al_stripes = cpu_to_be32(device->ldev->md.al_stripes);
30578c2ecf20Sopenharmony_ci	buffer->al_stripe_size_4k = cpu_to_be32(device->ldev->md.al_stripe_size_4k);
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	D_ASSERT(device, drbd_md_ss(device->ldev) == device->ldev->md.md_offset);
30608c2ecf20Sopenharmony_ci	sector = device->ldev->md.md_offset;
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	if (drbd_md_sync_page_io(device, device->ldev, sector, REQ_OP_WRITE)) {
30638c2ecf20Sopenharmony_ci		/* this was a try anyways ... */
30648c2ecf20Sopenharmony_ci		drbd_err(device, "meta data update failed!\n");
30658c2ecf20Sopenharmony_ci		drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
30668c2ecf20Sopenharmony_ci	}
30678c2ecf20Sopenharmony_ci}
30688c2ecf20Sopenharmony_ci
30698c2ecf20Sopenharmony_ci/**
30708c2ecf20Sopenharmony_ci * drbd_md_sync() - Writes the meta data super block if the MD_DIRTY flag bit is set
30718c2ecf20Sopenharmony_ci * @device:	DRBD device.
30728c2ecf20Sopenharmony_ci */
30738c2ecf20Sopenharmony_civoid drbd_md_sync(struct drbd_device *device)
30748c2ecf20Sopenharmony_ci{
30758c2ecf20Sopenharmony_ci	struct meta_data_on_disk *buffer;
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	/* Don't accidentally change the DRBD meta data layout. */
30788c2ecf20Sopenharmony_ci	BUILD_BUG_ON(UI_SIZE != 4);
30798c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct meta_data_on_disk) != 4096);
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci	del_timer(&device->md_sync_timer);
30828c2ecf20Sopenharmony_ci	/* timer may be rearmed by drbd_md_mark_dirty() now. */
30838c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(MD_DIRTY, &device->flags))
30848c2ecf20Sopenharmony_ci		return;
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	/* We use here D_FAILED and not D_ATTACHING because we try to write
30878c2ecf20Sopenharmony_ci	 * metadata even if we detach due to a disk failure! */
30888c2ecf20Sopenharmony_ci	if (!get_ldev_if_state(device, D_FAILED))
30898c2ecf20Sopenharmony_ci		return;
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_ci	buffer = drbd_md_get_buffer(device, __func__);
30928c2ecf20Sopenharmony_ci	if (!buffer)
30938c2ecf20Sopenharmony_ci		goto out;
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci	drbd_md_write(device, buffer);
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ci	/* Update device->ldev->md.la_size_sect,
30988c2ecf20Sopenharmony_ci	 * since we updated it on metadata. */
30998c2ecf20Sopenharmony_ci	device->ldev->md.la_size_sect = get_capacity(device->vdisk);
31008c2ecf20Sopenharmony_ci
31018c2ecf20Sopenharmony_ci	drbd_md_put_buffer(device);
31028c2ecf20Sopenharmony_ciout:
31038c2ecf20Sopenharmony_ci	put_ldev(device);
31048c2ecf20Sopenharmony_ci}
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_cistatic int check_activity_log_stripe_size(struct drbd_device *device,
31078c2ecf20Sopenharmony_ci		struct meta_data_on_disk *on_disk,
31088c2ecf20Sopenharmony_ci		struct drbd_md *in_core)
31098c2ecf20Sopenharmony_ci{
31108c2ecf20Sopenharmony_ci	u32 al_stripes = be32_to_cpu(on_disk->al_stripes);
31118c2ecf20Sopenharmony_ci	u32 al_stripe_size_4k = be32_to_cpu(on_disk->al_stripe_size_4k);
31128c2ecf20Sopenharmony_ci	u64 al_size_4k;
31138c2ecf20Sopenharmony_ci
31148c2ecf20Sopenharmony_ci	/* both not set: default to old fixed size activity log */
31158c2ecf20Sopenharmony_ci	if (al_stripes == 0 && al_stripe_size_4k == 0) {
31168c2ecf20Sopenharmony_ci		al_stripes = 1;
31178c2ecf20Sopenharmony_ci		al_stripe_size_4k = MD_32kB_SECT/8;
31188c2ecf20Sopenharmony_ci	}
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci	/* some paranoia plausibility checks */
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	/* we need both values to be set */
31238c2ecf20Sopenharmony_ci	if (al_stripes == 0 || al_stripe_size_4k == 0)
31248c2ecf20Sopenharmony_ci		goto err;
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci	al_size_4k = (u64)al_stripes * al_stripe_size_4k;
31278c2ecf20Sopenharmony_ci
31288c2ecf20Sopenharmony_ci	/* Upper limit of activity log area, to avoid potential overflow
31298c2ecf20Sopenharmony_ci	 * problems in al_tr_number_to_on_disk_sector(). As right now, more
31308c2ecf20Sopenharmony_ci	 * than 72 * 4k blocks total only increases the amount of history,
31318c2ecf20Sopenharmony_ci	 * limiting this arbitrarily to 16 GB is not a real limitation ;-)  */
31328c2ecf20Sopenharmony_ci	if (al_size_4k > (16 * 1024 * 1024/4))
31338c2ecf20Sopenharmony_ci		goto err;
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci	/* Lower limit: we need at least 8 transaction slots (32kB)
31368c2ecf20Sopenharmony_ci	 * to not break existing setups */
31378c2ecf20Sopenharmony_ci	if (al_size_4k < MD_32kB_SECT/8)
31388c2ecf20Sopenharmony_ci		goto err;
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_ci	in_core->al_stripe_size_4k = al_stripe_size_4k;
31418c2ecf20Sopenharmony_ci	in_core->al_stripes = al_stripes;
31428c2ecf20Sopenharmony_ci	in_core->al_size_4k = al_size_4k;
31438c2ecf20Sopenharmony_ci
31448c2ecf20Sopenharmony_ci	return 0;
31458c2ecf20Sopenharmony_cierr:
31468c2ecf20Sopenharmony_ci	drbd_err(device, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
31478c2ecf20Sopenharmony_ci			al_stripes, al_stripe_size_4k);
31488c2ecf20Sopenharmony_ci	return -EINVAL;
31498c2ecf20Sopenharmony_ci}
31508c2ecf20Sopenharmony_ci
31518c2ecf20Sopenharmony_cistatic int check_offsets_and_sizes(struct drbd_device *device, struct drbd_backing_dev *bdev)
31528c2ecf20Sopenharmony_ci{
31538c2ecf20Sopenharmony_ci	sector_t capacity = drbd_get_capacity(bdev->md_bdev);
31548c2ecf20Sopenharmony_ci	struct drbd_md *in_core = &bdev->md;
31558c2ecf20Sopenharmony_ci	s32 on_disk_al_sect;
31568c2ecf20Sopenharmony_ci	s32 on_disk_bm_sect;
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_ci	/* The on-disk size of the activity log, calculated from offsets, and
31598c2ecf20Sopenharmony_ci	 * the size of the activity log calculated from the stripe settings,
31608c2ecf20Sopenharmony_ci	 * should match.
31618c2ecf20Sopenharmony_ci	 * Though we could relax this a bit: it is ok, if the striped activity log
31628c2ecf20Sopenharmony_ci	 * fits in the available on-disk activity log size.
31638c2ecf20Sopenharmony_ci	 * Right now, that would break how resize is implemented.
31648c2ecf20Sopenharmony_ci	 * TODO: make drbd_determine_dev_size() (and the drbdmeta tool) aware
31658c2ecf20Sopenharmony_ci	 * of possible unused padding space in the on disk layout. */
31668c2ecf20Sopenharmony_ci	if (in_core->al_offset < 0) {
31678c2ecf20Sopenharmony_ci		if (in_core->bm_offset > in_core->al_offset)
31688c2ecf20Sopenharmony_ci			goto err;
31698c2ecf20Sopenharmony_ci		on_disk_al_sect = -in_core->al_offset;
31708c2ecf20Sopenharmony_ci		on_disk_bm_sect = in_core->al_offset - in_core->bm_offset;
31718c2ecf20Sopenharmony_ci	} else {
31728c2ecf20Sopenharmony_ci		if (in_core->al_offset != MD_4kB_SECT)
31738c2ecf20Sopenharmony_ci			goto err;
31748c2ecf20Sopenharmony_ci		if (in_core->bm_offset < in_core->al_offset + in_core->al_size_4k * MD_4kB_SECT)
31758c2ecf20Sopenharmony_ci			goto err;
31768c2ecf20Sopenharmony_ci
31778c2ecf20Sopenharmony_ci		on_disk_al_sect = in_core->bm_offset - MD_4kB_SECT;
31788c2ecf20Sopenharmony_ci		on_disk_bm_sect = in_core->md_size_sect - in_core->bm_offset;
31798c2ecf20Sopenharmony_ci	}
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci	/* old fixed size meta data is exactly that: fixed. */
31828c2ecf20Sopenharmony_ci	if (in_core->meta_dev_idx >= 0) {
31838c2ecf20Sopenharmony_ci		if (in_core->md_size_sect != MD_128MB_SECT
31848c2ecf20Sopenharmony_ci		||  in_core->al_offset != MD_4kB_SECT
31858c2ecf20Sopenharmony_ci		||  in_core->bm_offset != MD_4kB_SECT + MD_32kB_SECT
31868c2ecf20Sopenharmony_ci		||  in_core->al_stripes != 1
31878c2ecf20Sopenharmony_ci		||  in_core->al_stripe_size_4k != MD_32kB_SECT/8)
31888c2ecf20Sopenharmony_ci			goto err;
31898c2ecf20Sopenharmony_ci	}
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci	if (capacity < in_core->md_size_sect)
31928c2ecf20Sopenharmony_ci		goto err;
31938c2ecf20Sopenharmony_ci	if (capacity - in_core->md_size_sect < drbd_md_first_sector(bdev))
31948c2ecf20Sopenharmony_ci		goto err;
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_ci	/* should be aligned, and at least 32k */
31978c2ecf20Sopenharmony_ci	if ((on_disk_al_sect & 7) || (on_disk_al_sect < MD_32kB_SECT))
31988c2ecf20Sopenharmony_ci		goto err;
31998c2ecf20Sopenharmony_ci
32008c2ecf20Sopenharmony_ci	/* should fit (for now: exactly) into the available on-disk space;
32018c2ecf20Sopenharmony_ci	 * overflow prevention is in check_activity_log_stripe_size() above. */
32028c2ecf20Sopenharmony_ci	if (on_disk_al_sect != in_core->al_size_4k * MD_4kB_SECT)
32038c2ecf20Sopenharmony_ci		goto err;
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	/* again, should be aligned */
32068c2ecf20Sopenharmony_ci	if (in_core->bm_offset & 7)
32078c2ecf20Sopenharmony_ci		goto err;
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci	/* FIXME check for device grow with flex external meta data? */
32108c2ecf20Sopenharmony_ci
32118c2ecf20Sopenharmony_ci	/* can the available bitmap space cover the last agreed device size? */
32128c2ecf20Sopenharmony_ci	if (on_disk_bm_sect < (in_core->la_size_sect+7)/MD_4kB_SECT/8/512)
32138c2ecf20Sopenharmony_ci		goto err;
32148c2ecf20Sopenharmony_ci
32158c2ecf20Sopenharmony_ci	return 0;
32168c2ecf20Sopenharmony_ci
32178c2ecf20Sopenharmony_cierr:
32188c2ecf20Sopenharmony_ci	drbd_err(device, "meta data offsets don't make sense: idx=%d "
32198c2ecf20Sopenharmony_ci			"al_s=%u, al_sz4k=%u, al_offset=%d, bm_offset=%d, "
32208c2ecf20Sopenharmony_ci			"md_size_sect=%u, la_size=%llu, md_capacity=%llu\n",
32218c2ecf20Sopenharmony_ci			in_core->meta_dev_idx,
32228c2ecf20Sopenharmony_ci			in_core->al_stripes, in_core->al_stripe_size_4k,
32238c2ecf20Sopenharmony_ci			in_core->al_offset, in_core->bm_offset, in_core->md_size_sect,
32248c2ecf20Sopenharmony_ci			(unsigned long long)in_core->la_size_sect,
32258c2ecf20Sopenharmony_ci			(unsigned long long)capacity);
32268c2ecf20Sopenharmony_ci
32278c2ecf20Sopenharmony_ci	return -EINVAL;
32288c2ecf20Sopenharmony_ci}
32298c2ecf20Sopenharmony_ci
32308c2ecf20Sopenharmony_ci
32318c2ecf20Sopenharmony_ci/**
32328c2ecf20Sopenharmony_ci * drbd_md_read() - Reads in the meta data super block
32338c2ecf20Sopenharmony_ci * @device:	DRBD device.
32348c2ecf20Sopenharmony_ci * @bdev:	Device from which the meta data should be read in.
32358c2ecf20Sopenharmony_ci *
32368c2ecf20Sopenharmony_ci * Return NO_ERROR on success, and an enum drbd_ret_code in case
32378c2ecf20Sopenharmony_ci * something goes wrong.
32388c2ecf20Sopenharmony_ci *
32398c2ecf20Sopenharmony_ci * Called exactly once during drbd_adm_attach(), while still being D_DISKLESS,
32408c2ecf20Sopenharmony_ci * even before @bdev is assigned to @device->ldev.
32418c2ecf20Sopenharmony_ci */
32428c2ecf20Sopenharmony_ciint drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
32438c2ecf20Sopenharmony_ci{
32448c2ecf20Sopenharmony_ci	struct meta_data_on_disk *buffer;
32458c2ecf20Sopenharmony_ci	u32 magic, flags;
32468c2ecf20Sopenharmony_ci	int i, rv = NO_ERROR;
32478c2ecf20Sopenharmony_ci
32488c2ecf20Sopenharmony_ci	if (device->state.disk != D_DISKLESS)
32498c2ecf20Sopenharmony_ci		return ERR_DISK_CONFIGURED;
32508c2ecf20Sopenharmony_ci
32518c2ecf20Sopenharmony_ci	buffer = drbd_md_get_buffer(device, __func__);
32528c2ecf20Sopenharmony_ci	if (!buffer)
32538c2ecf20Sopenharmony_ci		return ERR_NOMEM;
32548c2ecf20Sopenharmony_ci
32558c2ecf20Sopenharmony_ci	/* First, figure out where our meta data superblock is located,
32568c2ecf20Sopenharmony_ci	 * and read it. */
32578c2ecf20Sopenharmony_ci	bdev->md.meta_dev_idx = bdev->disk_conf->meta_dev_idx;
32588c2ecf20Sopenharmony_ci	bdev->md.md_offset = drbd_md_ss(bdev);
32598c2ecf20Sopenharmony_ci	/* Even for (flexible or indexed) external meta data,
32608c2ecf20Sopenharmony_ci	 * initially restrict us to the 4k superblock for now.
32618c2ecf20Sopenharmony_ci	 * Affects the paranoia out-of-range access check in drbd_md_sync_page_io(). */
32628c2ecf20Sopenharmony_ci	bdev->md.md_size_sect = 8;
32638c2ecf20Sopenharmony_ci
32648c2ecf20Sopenharmony_ci	if (drbd_md_sync_page_io(device, bdev, bdev->md.md_offset,
32658c2ecf20Sopenharmony_ci				 REQ_OP_READ)) {
32668c2ecf20Sopenharmony_ci		/* NOTE: can't do normal error processing here as this is
32678c2ecf20Sopenharmony_ci		   called BEFORE disk is attached */
32688c2ecf20Sopenharmony_ci		drbd_err(device, "Error while reading metadata.\n");
32698c2ecf20Sopenharmony_ci		rv = ERR_IO_MD_DISK;
32708c2ecf20Sopenharmony_ci		goto err;
32718c2ecf20Sopenharmony_ci	}
32728c2ecf20Sopenharmony_ci
32738c2ecf20Sopenharmony_ci	magic = be32_to_cpu(buffer->magic);
32748c2ecf20Sopenharmony_ci	flags = be32_to_cpu(buffer->flags);
32758c2ecf20Sopenharmony_ci	if (magic == DRBD_MD_MAGIC_84_UNCLEAN ||
32768c2ecf20Sopenharmony_ci	    (magic == DRBD_MD_MAGIC_08 && !(flags & MDF_AL_CLEAN))) {
32778c2ecf20Sopenharmony_ci			/* btw: that's Activity Log clean, not "all" clean. */
32788c2ecf20Sopenharmony_ci		drbd_err(device, "Found unclean meta data. Did you \"drbdadm apply-al\"?\n");
32798c2ecf20Sopenharmony_ci		rv = ERR_MD_UNCLEAN;
32808c2ecf20Sopenharmony_ci		goto err;
32818c2ecf20Sopenharmony_ci	}
32828c2ecf20Sopenharmony_ci
32838c2ecf20Sopenharmony_ci	rv = ERR_MD_INVALID;
32848c2ecf20Sopenharmony_ci	if (magic != DRBD_MD_MAGIC_08) {
32858c2ecf20Sopenharmony_ci		if (magic == DRBD_MD_MAGIC_07)
32868c2ecf20Sopenharmony_ci			drbd_err(device, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
32878c2ecf20Sopenharmony_ci		else
32888c2ecf20Sopenharmony_ci			drbd_err(device, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
32898c2ecf20Sopenharmony_ci		goto err;
32908c2ecf20Sopenharmony_ci	}
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) {
32938c2ecf20Sopenharmony_ci		drbd_err(device, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
32948c2ecf20Sopenharmony_ci		    be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE);
32958c2ecf20Sopenharmony_ci		goto err;
32968c2ecf20Sopenharmony_ci	}
32978c2ecf20Sopenharmony_ci
32988c2ecf20Sopenharmony_ci
32998c2ecf20Sopenharmony_ci	/* convert to in_core endian */
33008c2ecf20Sopenharmony_ci	bdev->md.la_size_sect = be64_to_cpu(buffer->la_size_sect);
33018c2ecf20Sopenharmony_ci	for (i = UI_CURRENT; i < UI_SIZE; i++)
33028c2ecf20Sopenharmony_ci		bdev->md.uuid[i] = be64_to_cpu(buffer->uuid[i]);
33038c2ecf20Sopenharmony_ci	bdev->md.flags = be32_to_cpu(buffer->flags);
33048c2ecf20Sopenharmony_ci	bdev->md.device_uuid = be64_to_cpu(buffer->device_uuid);
33058c2ecf20Sopenharmony_ci
33068c2ecf20Sopenharmony_ci	bdev->md.md_size_sect = be32_to_cpu(buffer->md_size_sect);
33078c2ecf20Sopenharmony_ci	bdev->md.al_offset = be32_to_cpu(buffer->al_offset);
33088c2ecf20Sopenharmony_ci	bdev->md.bm_offset = be32_to_cpu(buffer->bm_offset);
33098c2ecf20Sopenharmony_ci
33108c2ecf20Sopenharmony_ci	if (check_activity_log_stripe_size(device, buffer, &bdev->md))
33118c2ecf20Sopenharmony_ci		goto err;
33128c2ecf20Sopenharmony_ci	if (check_offsets_and_sizes(device, bdev))
33138c2ecf20Sopenharmony_ci		goto err;
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_ci	if (be32_to_cpu(buffer->bm_offset) != bdev->md.bm_offset) {
33168c2ecf20Sopenharmony_ci		drbd_err(device, "unexpected bm_offset: %d (expected %d)\n",
33178c2ecf20Sopenharmony_ci		    be32_to_cpu(buffer->bm_offset), bdev->md.bm_offset);
33188c2ecf20Sopenharmony_ci		goto err;
33198c2ecf20Sopenharmony_ci	}
33208c2ecf20Sopenharmony_ci	if (be32_to_cpu(buffer->md_size_sect) != bdev->md.md_size_sect) {
33218c2ecf20Sopenharmony_ci		drbd_err(device, "unexpected md_size: %u (expected %u)\n",
33228c2ecf20Sopenharmony_ci		    be32_to_cpu(buffer->md_size_sect), bdev->md.md_size_sect);
33238c2ecf20Sopenharmony_ci		goto err;
33248c2ecf20Sopenharmony_ci	}
33258c2ecf20Sopenharmony_ci
33268c2ecf20Sopenharmony_ci	rv = NO_ERROR;
33278c2ecf20Sopenharmony_ci
33288c2ecf20Sopenharmony_ci	spin_lock_irq(&device->resource->req_lock);
33298c2ecf20Sopenharmony_ci	if (device->state.conn < C_CONNECTED) {
33308c2ecf20Sopenharmony_ci		unsigned int peer;
33318c2ecf20Sopenharmony_ci		peer = be32_to_cpu(buffer->la_peer_max_bio_size);
33328c2ecf20Sopenharmony_ci		peer = max(peer, DRBD_MAX_BIO_SIZE_SAFE);
33338c2ecf20Sopenharmony_ci		device->peer_max_bio_size = peer;
33348c2ecf20Sopenharmony_ci	}
33358c2ecf20Sopenharmony_ci	spin_unlock_irq(&device->resource->req_lock);
33368c2ecf20Sopenharmony_ci
33378c2ecf20Sopenharmony_ci err:
33388c2ecf20Sopenharmony_ci	drbd_md_put_buffer(device);
33398c2ecf20Sopenharmony_ci
33408c2ecf20Sopenharmony_ci	return rv;
33418c2ecf20Sopenharmony_ci}
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci/**
33448c2ecf20Sopenharmony_ci * drbd_md_mark_dirty() - Mark meta data super block as dirty
33458c2ecf20Sopenharmony_ci * @device:	DRBD device.
33468c2ecf20Sopenharmony_ci *
33478c2ecf20Sopenharmony_ci * Call this function if you change anything that should be written to
33488c2ecf20Sopenharmony_ci * the meta-data super block. This function sets MD_DIRTY, and starts a
33498c2ecf20Sopenharmony_ci * timer that ensures that within five seconds you have to call drbd_md_sync().
33508c2ecf20Sopenharmony_ci */
33518c2ecf20Sopenharmony_civoid drbd_md_mark_dirty(struct drbd_device *device)
33528c2ecf20Sopenharmony_ci{
33538c2ecf20Sopenharmony_ci	if (!test_and_set_bit(MD_DIRTY, &device->flags))
33548c2ecf20Sopenharmony_ci		mod_timer(&device->md_sync_timer, jiffies + 5*HZ);
33558c2ecf20Sopenharmony_ci}
33568c2ecf20Sopenharmony_ci
33578c2ecf20Sopenharmony_civoid drbd_uuid_move_history(struct drbd_device *device) __must_hold(local)
33588c2ecf20Sopenharmony_ci{
33598c2ecf20Sopenharmony_ci	int i;
33608c2ecf20Sopenharmony_ci
33618c2ecf20Sopenharmony_ci	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
33628c2ecf20Sopenharmony_ci		device->ldev->md.uuid[i+1] = device->ldev->md.uuid[i];
33638c2ecf20Sopenharmony_ci}
33648c2ecf20Sopenharmony_ci
33658c2ecf20Sopenharmony_civoid __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
33668c2ecf20Sopenharmony_ci{
33678c2ecf20Sopenharmony_ci	if (idx == UI_CURRENT) {
33688c2ecf20Sopenharmony_ci		if (device->state.role == R_PRIMARY)
33698c2ecf20Sopenharmony_ci			val |= 1;
33708c2ecf20Sopenharmony_ci		else
33718c2ecf20Sopenharmony_ci			val &= ~((u64)1);
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_ci		drbd_set_ed_uuid(device, val);
33748c2ecf20Sopenharmony_ci	}
33758c2ecf20Sopenharmony_ci
33768c2ecf20Sopenharmony_ci	device->ldev->md.uuid[idx] = val;
33778c2ecf20Sopenharmony_ci	drbd_md_mark_dirty(device);
33788c2ecf20Sopenharmony_ci}
33798c2ecf20Sopenharmony_ci
33808c2ecf20Sopenharmony_civoid _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
33818c2ecf20Sopenharmony_ci{
33828c2ecf20Sopenharmony_ci	unsigned long flags;
33838c2ecf20Sopenharmony_ci	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
33848c2ecf20Sopenharmony_ci	__drbd_uuid_set(device, idx, val);
33858c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
33868c2ecf20Sopenharmony_ci}
33878c2ecf20Sopenharmony_ci
33888c2ecf20Sopenharmony_civoid drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
33898c2ecf20Sopenharmony_ci{
33908c2ecf20Sopenharmony_ci	unsigned long flags;
33918c2ecf20Sopenharmony_ci	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
33928c2ecf20Sopenharmony_ci	if (device->ldev->md.uuid[idx]) {
33938c2ecf20Sopenharmony_ci		drbd_uuid_move_history(device);
33948c2ecf20Sopenharmony_ci		device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[idx];
33958c2ecf20Sopenharmony_ci	}
33968c2ecf20Sopenharmony_ci	__drbd_uuid_set(device, idx, val);
33978c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
33988c2ecf20Sopenharmony_ci}
33998c2ecf20Sopenharmony_ci
34008c2ecf20Sopenharmony_ci/**
34018c2ecf20Sopenharmony_ci * drbd_uuid_new_current() - Creates a new current UUID
34028c2ecf20Sopenharmony_ci * @device:	DRBD device.
34038c2ecf20Sopenharmony_ci *
34048c2ecf20Sopenharmony_ci * Creates a new current UUID, and rotates the old current UUID into
34058c2ecf20Sopenharmony_ci * the bitmap slot. Causes an incremental resync upon next connect.
34068c2ecf20Sopenharmony_ci */
34078c2ecf20Sopenharmony_civoid drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
34088c2ecf20Sopenharmony_ci{
34098c2ecf20Sopenharmony_ci	u64 val;
34108c2ecf20Sopenharmony_ci	unsigned long long bm_uuid;
34118c2ecf20Sopenharmony_ci
34128c2ecf20Sopenharmony_ci	get_random_bytes(&val, sizeof(u64));
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_ci	spin_lock_irq(&device->ldev->md.uuid_lock);
34158c2ecf20Sopenharmony_ci	bm_uuid = device->ldev->md.uuid[UI_BITMAP];
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	if (bm_uuid)
34188c2ecf20Sopenharmony_ci		drbd_warn(device, "bm UUID was already set: %llX\n", bm_uuid);
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_ci	device->ldev->md.uuid[UI_BITMAP] = device->ldev->md.uuid[UI_CURRENT];
34218c2ecf20Sopenharmony_ci	__drbd_uuid_set(device, UI_CURRENT, val);
34228c2ecf20Sopenharmony_ci	spin_unlock_irq(&device->ldev->md.uuid_lock);
34238c2ecf20Sopenharmony_ci
34248c2ecf20Sopenharmony_ci	drbd_print_uuids(device, "new current UUID");
34258c2ecf20Sopenharmony_ci	/* get it to stable storage _now_ */
34268c2ecf20Sopenharmony_ci	drbd_md_sync(device);
34278c2ecf20Sopenharmony_ci}
34288c2ecf20Sopenharmony_ci
34298c2ecf20Sopenharmony_civoid drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
34308c2ecf20Sopenharmony_ci{
34318c2ecf20Sopenharmony_ci	unsigned long flags;
34328c2ecf20Sopenharmony_ci	if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
34338c2ecf20Sopenharmony_ci		return;
34348c2ecf20Sopenharmony_ci
34358c2ecf20Sopenharmony_ci	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
34368c2ecf20Sopenharmony_ci	if (val == 0) {
34378c2ecf20Sopenharmony_ci		drbd_uuid_move_history(device);
34388c2ecf20Sopenharmony_ci		device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];
34398c2ecf20Sopenharmony_ci		device->ldev->md.uuid[UI_BITMAP] = 0;
34408c2ecf20Sopenharmony_ci	} else {
34418c2ecf20Sopenharmony_ci		unsigned long long bm_uuid = device->ldev->md.uuid[UI_BITMAP];
34428c2ecf20Sopenharmony_ci		if (bm_uuid)
34438c2ecf20Sopenharmony_ci			drbd_warn(device, "bm UUID was already set: %llX\n", bm_uuid);
34448c2ecf20Sopenharmony_ci
34458c2ecf20Sopenharmony_ci		device->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
34468c2ecf20Sopenharmony_ci	}
34478c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
34488c2ecf20Sopenharmony_ci
34498c2ecf20Sopenharmony_ci	drbd_md_mark_dirty(device);
34508c2ecf20Sopenharmony_ci}
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci/**
34538c2ecf20Sopenharmony_ci * drbd_bmio_set_n_write() - io_fn for drbd_queue_bitmap_io() or drbd_bitmap_io()
34548c2ecf20Sopenharmony_ci * @device:	DRBD device.
34558c2ecf20Sopenharmony_ci *
34568c2ecf20Sopenharmony_ci * Sets all bits in the bitmap and writes the whole bitmap to stable storage.
34578c2ecf20Sopenharmony_ci */
34588c2ecf20Sopenharmony_ciint drbd_bmio_set_n_write(struct drbd_device *device) __must_hold(local)
34598c2ecf20Sopenharmony_ci{
34608c2ecf20Sopenharmony_ci	int rv = -EIO;
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_ci	drbd_md_set_flag(device, MDF_FULL_SYNC);
34638c2ecf20Sopenharmony_ci	drbd_md_sync(device);
34648c2ecf20Sopenharmony_ci	drbd_bm_set_all(device);
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci	rv = drbd_bm_write(device);
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	if (!rv) {
34698c2ecf20Sopenharmony_ci		drbd_md_clear_flag(device, MDF_FULL_SYNC);
34708c2ecf20Sopenharmony_ci		drbd_md_sync(device);
34718c2ecf20Sopenharmony_ci	}
34728c2ecf20Sopenharmony_ci
34738c2ecf20Sopenharmony_ci	return rv;
34748c2ecf20Sopenharmony_ci}
34758c2ecf20Sopenharmony_ci
34768c2ecf20Sopenharmony_ci/**
34778c2ecf20Sopenharmony_ci * drbd_bmio_clear_n_write() - io_fn for drbd_queue_bitmap_io() or drbd_bitmap_io()
34788c2ecf20Sopenharmony_ci * @device:	DRBD device.
34798c2ecf20Sopenharmony_ci *
34808c2ecf20Sopenharmony_ci * Clears all bits in the bitmap and writes the whole bitmap to stable storage.
34818c2ecf20Sopenharmony_ci */
34828c2ecf20Sopenharmony_ciint drbd_bmio_clear_n_write(struct drbd_device *device) __must_hold(local)
34838c2ecf20Sopenharmony_ci{
34848c2ecf20Sopenharmony_ci	drbd_resume_al(device);
34858c2ecf20Sopenharmony_ci	drbd_bm_clear_all(device);
34868c2ecf20Sopenharmony_ci	return drbd_bm_write(device);
34878c2ecf20Sopenharmony_ci}
34888c2ecf20Sopenharmony_ci
34898c2ecf20Sopenharmony_cistatic int w_bitmap_io(struct drbd_work *w, int unused)
34908c2ecf20Sopenharmony_ci{
34918c2ecf20Sopenharmony_ci	struct drbd_device *device =
34928c2ecf20Sopenharmony_ci		container_of(w, struct drbd_device, bm_io_work.w);
34938c2ecf20Sopenharmony_ci	struct bm_io_work *work = &device->bm_io_work;
34948c2ecf20Sopenharmony_ci	int rv = -EIO;
34958c2ecf20Sopenharmony_ci
34968c2ecf20Sopenharmony_ci	if (work->flags != BM_LOCKED_CHANGE_ALLOWED) {
34978c2ecf20Sopenharmony_ci		int cnt = atomic_read(&device->ap_bio_cnt);
34988c2ecf20Sopenharmony_ci		if (cnt)
34998c2ecf20Sopenharmony_ci			drbd_err(device, "FIXME: ap_bio_cnt %d, expected 0; queued for '%s'\n",
35008c2ecf20Sopenharmony_ci					cnt, work->why);
35018c2ecf20Sopenharmony_ci	}
35028c2ecf20Sopenharmony_ci
35038c2ecf20Sopenharmony_ci	if (get_ldev(device)) {
35048c2ecf20Sopenharmony_ci		drbd_bm_lock(device, work->why, work->flags);
35058c2ecf20Sopenharmony_ci		rv = work->io_fn(device);
35068c2ecf20Sopenharmony_ci		drbd_bm_unlock(device);
35078c2ecf20Sopenharmony_ci		put_ldev(device);
35088c2ecf20Sopenharmony_ci	}
35098c2ecf20Sopenharmony_ci
35108c2ecf20Sopenharmony_ci	clear_bit_unlock(BITMAP_IO, &device->flags);
35118c2ecf20Sopenharmony_ci	wake_up(&device->misc_wait);
35128c2ecf20Sopenharmony_ci
35138c2ecf20Sopenharmony_ci	if (work->done)
35148c2ecf20Sopenharmony_ci		work->done(device, rv);
35158c2ecf20Sopenharmony_ci
35168c2ecf20Sopenharmony_ci	clear_bit(BITMAP_IO_QUEUED, &device->flags);
35178c2ecf20Sopenharmony_ci	work->why = NULL;
35188c2ecf20Sopenharmony_ci	work->flags = 0;
35198c2ecf20Sopenharmony_ci
35208c2ecf20Sopenharmony_ci	return 0;
35218c2ecf20Sopenharmony_ci}
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_ci/**
35248c2ecf20Sopenharmony_ci * drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
35258c2ecf20Sopenharmony_ci * @device:	DRBD device.
35268c2ecf20Sopenharmony_ci * @io_fn:	IO callback to be called when bitmap IO is possible
35278c2ecf20Sopenharmony_ci * @done:	callback to be called after the bitmap IO was performed
35288c2ecf20Sopenharmony_ci * @why:	Descriptive text of the reason for doing the IO
35298c2ecf20Sopenharmony_ci *
35308c2ecf20Sopenharmony_ci * While IO on the bitmap happens we freeze application IO thus we ensure
35318c2ecf20Sopenharmony_ci * that drbd_set_out_of_sync() can not be called. This function MAY ONLY be
35328c2ecf20Sopenharmony_ci * called from worker context. It MUST NOT be used while a previous such
35338c2ecf20Sopenharmony_ci * work is still pending!
35348c2ecf20Sopenharmony_ci *
35358c2ecf20Sopenharmony_ci * Its worker function encloses the call of io_fn() by get_ldev() and
35368c2ecf20Sopenharmony_ci * put_ldev().
35378c2ecf20Sopenharmony_ci */
35388c2ecf20Sopenharmony_civoid drbd_queue_bitmap_io(struct drbd_device *device,
35398c2ecf20Sopenharmony_ci			  int (*io_fn)(struct drbd_device *),
35408c2ecf20Sopenharmony_ci			  void (*done)(struct drbd_device *, int),
35418c2ecf20Sopenharmony_ci			  char *why, enum bm_flag flags)
35428c2ecf20Sopenharmony_ci{
35438c2ecf20Sopenharmony_ci	D_ASSERT(device, current == first_peer_device(device)->connection->worker.task);
35448c2ecf20Sopenharmony_ci
35458c2ecf20Sopenharmony_ci	D_ASSERT(device, !test_bit(BITMAP_IO_QUEUED, &device->flags));
35468c2ecf20Sopenharmony_ci	D_ASSERT(device, !test_bit(BITMAP_IO, &device->flags));
35478c2ecf20Sopenharmony_ci	D_ASSERT(device, list_empty(&device->bm_io_work.w.list));
35488c2ecf20Sopenharmony_ci	if (device->bm_io_work.why)
35498c2ecf20Sopenharmony_ci		drbd_err(device, "FIXME going to queue '%s' but '%s' still pending?\n",
35508c2ecf20Sopenharmony_ci			why, device->bm_io_work.why);
35518c2ecf20Sopenharmony_ci
35528c2ecf20Sopenharmony_ci	device->bm_io_work.io_fn = io_fn;
35538c2ecf20Sopenharmony_ci	device->bm_io_work.done = done;
35548c2ecf20Sopenharmony_ci	device->bm_io_work.why = why;
35558c2ecf20Sopenharmony_ci	device->bm_io_work.flags = flags;
35568c2ecf20Sopenharmony_ci
35578c2ecf20Sopenharmony_ci	spin_lock_irq(&device->resource->req_lock);
35588c2ecf20Sopenharmony_ci	set_bit(BITMAP_IO, &device->flags);
35598c2ecf20Sopenharmony_ci	/* don't wait for pending application IO if the caller indicates that
35608c2ecf20Sopenharmony_ci	 * application IO does not conflict anyways. */
35618c2ecf20Sopenharmony_ci	if (flags == BM_LOCKED_CHANGE_ALLOWED || atomic_read(&device->ap_bio_cnt) == 0) {
35628c2ecf20Sopenharmony_ci		if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags))
35638c2ecf20Sopenharmony_ci			drbd_queue_work(&first_peer_device(device)->connection->sender_work,
35648c2ecf20Sopenharmony_ci					&device->bm_io_work.w);
35658c2ecf20Sopenharmony_ci	}
35668c2ecf20Sopenharmony_ci	spin_unlock_irq(&device->resource->req_lock);
35678c2ecf20Sopenharmony_ci}
35688c2ecf20Sopenharmony_ci
35698c2ecf20Sopenharmony_ci/**
35708c2ecf20Sopenharmony_ci * drbd_bitmap_io() -  Does an IO operation on the whole bitmap
35718c2ecf20Sopenharmony_ci * @device:	DRBD device.
35728c2ecf20Sopenharmony_ci * @io_fn:	IO callback to be called when bitmap IO is possible
35738c2ecf20Sopenharmony_ci * @why:	Descriptive text of the reason for doing the IO
35748c2ecf20Sopenharmony_ci *
35758c2ecf20Sopenharmony_ci * freezes application IO while that the actual IO operations runs. This
35768c2ecf20Sopenharmony_ci * functions MAY NOT be called from worker context.
35778c2ecf20Sopenharmony_ci */
35788c2ecf20Sopenharmony_ciint drbd_bitmap_io(struct drbd_device *device, int (*io_fn)(struct drbd_device *),
35798c2ecf20Sopenharmony_ci		char *why, enum bm_flag flags)
35808c2ecf20Sopenharmony_ci{
35818c2ecf20Sopenharmony_ci	/* Only suspend io, if some operation is supposed to be locked out */
35828c2ecf20Sopenharmony_ci	const bool do_suspend_io = flags & (BM_DONT_CLEAR|BM_DONT_SET|BM_DONT_TEST);
35838c2ecf20Sopenharmony_ci	int rv;
35848c2ecf20Sopenharmony_ci
35858c2ecf20Sopenharmony_ci	D_ASSERT(device, current != first_peer_device(device)->connection->worker.task);
35868c2ecf20Sopenharmony_ci
35878c2ecf20Sopenharmony_ci	if (do_suspend_io)
35888c2ecf20Sopenharmony_ci		drbd_suspend_io(device);
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci	drbd_bm_lock(device, why, flags);
35918c2ecf20Sopenharmony_ci	rv = io_fn(device);
35928c2ecf20Sopenharmony_ci	drbd_bm_unlock(device);
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci	if (do_suspend_io)
35958c2ecf20Sopenharmony_ci		drbd_resume_io(device);
35968c2ecf20Sopenharmony_ci
35978c2ecf20Sopenharmony_ci	return rv;
35988c2ecf20Sopenharmony_ci}
35998c2ecf20Sopenharmony_ci
36008c2ecf20Sopenharmony_civoid drbd_md_set_flag(struct drbd_device *device, int flag) __must_hold(local)
36018c2ecf20Sopenharmony_ci{
36028c2ecf20Sopenharmony_ci	if ((device->ldev->md.flags & flag) != flag) {
36038c2ecf20Sopenharmony_ci		drbd_md_mark_dirty(device);
36048c2ecf20Sopenharmony_ci		device->ldev->md.flags |= flag;
36058c2ecf20Sopenharmony_ci	}
36068c2ecf20Sopenharmony_ci}
36078c2ecf20Sopenharmony_ci
36088c2ecf20Sopenharmony_civoid drbd_md_clear_flag(struct drbd_device *device, int flag) __must_hold(local)
36098c2ecf20Sopenharmony_ci{
36108c2ecf20Sopenharmony_ci	if ((device->ldev->md.flags & flag) != 0) {
36118c2ecf20Sopenharmony_ci		drbd_md_mark_dirty(device);
36128c2ecf20Sopenharmony_ci		device->ldev->md.flags &= ~flag;
36138c2ecf20Sopenharmony_ci	}
36148c2ecf20Sopenharmony_ci}
36158c2ecf20Sopenharmony_ciint drbd_md_test_flag(struct drbd_backing_dev *bdev, int flag)
36168c2ecf20Sopenharmony_ci{
36178c2ecf20Sopenharmony_ci	return (bdev->md.flags & flag) != 0;
36188c2ecf20Sopenharmony_ci}
36198c2ecf20Sopenharmony_ci
36208c2ecf20Sopenharmony_cistatic void md_sync_timer_fn(struct timer_list *t)
36218c2ecf20Sopenharmony_ci{
36228c2ecf20Sopenharmony_ci	struct drbd_device *device = from_timer(device, t, md_sync_timer);
36238c2ecf20Sopenharmony_ci	drbd_device_post_work(device, MD_SYNC);
36248c2ecf20Sopenharmony_ci}
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_ciconst char *cmdname(enum drbd_packet cmd)
36278c2ecf20Sopenharmony_ci{
36288c2ecf20Sopenharmony_ci	/* THINK may need to become several global tables
36298c2ecf20Sopenharmony_ci	 * when we want to support more than
36308c2ecf20Sopenharmony_ci	 * one PRO_VERSION */
36318c2ecf20Sopenharmony_ci	static const char *cmdnames[] = {
36328c2ecf20Sopenharmony_ci
36338c2ecf20Sopenharmony_ci		[P_DATA]	        = "Data",
36348c2ecf20Sopenharmony_ci		[P_DATA_REPLY]	        = "DataReply",
36358c2ecf20Sopenharmony_ci		[P_RS_DATA_REPLY]	= "RSDataReply",
36368c2ecf20Sopenharmony_ci		[P_BARRIER]	        = "Barrier",
36378c2ecf20Sopenharmony_ci		[P_BITMAP]	        = "ReportBitMap",
36388c2ecf20Sopenharmony_ci		[P_BECOME_SYNC_TARGET]  = "BecomeSyncTarget",
36398c2ecf20Sopenharmony_ci		[P_BECOME_SYNC_SOURCE]  = "BecomeSyncSource",
36408c2ecf20Sopenharmony_ci		[P_UNPLUG_REMOTE]	= "UnplugRemote",
36418c2ecf20Sopenharmony_ci		[P_DATA_REQUEST]	= "DataRequest",
36428c2ecf20Sopenharmony_ci		[P_RS_DATA_REQUEST]     = "RSDataRequest",
36438c2ecf20Sopenharmony_ci		[P_SYNC_PARAM]	        = "SyncParam",
36448c2ecf20Sopenharmony_ci		[P_PROTOCOL]            = "ReportProtocol",
36458c2ecf20Sopenharmony_ci		[P_UUIDS]	        = "ReportUUIDs",
36468c2ecf20Sopenharmony_ci		[P_SIZES]	        = "ReportSizes",
36478c2ecf20Sopenharmony_ci		[P_STATE]	        = "ReportState",
36488c2ecf20Sopenharmony_ci		[P_SYNC_UUID]           = "ReportSyncUUID",
36498c2ecf20Sopenharmony_ci		[P_AUTH_CHALLENGE]      = "AuthChallenge",
36508c2ecf20Sopenharmony_ci		[P_AUTH_RESPONSE]	= "AuthResponse",
36518c2ecf20Sopenharmony_ci		[P_STATE_CHG_REQ]       = "StateChgRequest",
36528c2ecf20Sopenharmony_ci		[P_PING]		= "Ping",
36538c2ecf20Sopenharmony_ci		[P_PING_ACK]	        = "PingAck",
36548c2ecf20Sopenharmony_ci		[P_RECV_ACK]	        = "RecvAck",
36558c2ecf20Sopenharmony_ci		[P_WRITE_ACK]	        = "WriteAck",
36568c2ecf20Sopenharmony_ci		[P_RS_WRITE_ACK]	= "RSWriteAck",
36578c2ecf20Sopenharmony_ci		[P_SUPERSEDED]          = "Superseded",
36588c2ecf20Sopenharmony_ci		[P_NEG_ACK]	        = "NegAck",
36598c2ecf20Sopenharmony_ci		[P_NEG_DREPLY]	        = "NegDReply",
36608c2ecf20Sopenharmony_ci		[P_NEG_RS_DREPLY]	= "NegRSDReply",
36618c2ecf20Sopenharmony_ci		[P_BARRIER_ACK]	        = "BarrierAck",
36628c2ecf20Sopenharmony_ci		[P_STATE_CHG_REPLY]     = "StateChgReply",
36638c2ecf20Sopenharmony_ci		[P_OV_REQUEST]          = "OVRequest",
36648c2ecf20Sopenharmony_ci		[P_OV_REPLY]            = "OVReply",
36658c2ecf20Sopenharmony_ci		[P_OV_RESULT]           = "OVResult",
36668c2ecf20Sopenharmony_ci		[P_CSUM_RS_REQUEST]     = "CsumRSRequest",
36678c2ecf20Sopenharmony_ci		[P_RS_IS_IN_SYNC]	= "CsumRSIsInSync",
36688c2ecf20Sopenharmony_ci		[P_SYNC_PARAM89]	= "SyncParam89",
36698c2ecf20Sopenharmony_ci		[P_COMPRESSED_BITMAP]   = "CBitmap",
36708c2ecf20Sopenharmony_ci		[P_DELAY_PROBE]         = "DelayProbe",
36718c2ecf20Sopenharmony_ci		[P_OUT_OF_SYNC]		= "OutOfSync",
36728c2ecf20Sopenharmony_ci		[P_RS_CANCEL]		= "RSCancel",
36738c2ecf20Sopenharmony_ci		[P_CONN_ST_CHG_REQ]	= "conn_st_chg_req",
36748c2ecf20Sopenharmony_ci		[P_CONN_ST_CHG_REPLY]	= "conn_st_chg_reply",
36758c2ecf20Sopenharmony_ci		[P_RETRY_WRITE]		= "retry_write",
36768c2ecf20Sopenharmony_ci		[P_PROTOCOL_UPDATE]	= "protocol_update",
36778c2ecf20Sopenharmony_ci		[P_TRIM]	        = "Trim",
36788c2ecf20Sopenharmony_ci		[P_RS_THIN_REQ]         = "rs_thin_req",
36798c2ecf20Sopenharmony_ci		[P_RS_DEALLOCATED]      = "rs_deallocated",
36808c2ecf20Sopenharmony_ci		[P_WSAME]	        = "WriteSame",
36818c2ecf20Sopenharmony_ci		[P_ZEROES]		= "Zeroes",
36828c2ecf20Sopenharmony_ci
36838c2ecf20Sopenharmony_ci		/* enum drbd_packet, but not commands - obsoleted flags:
36848c2ecf20Sopenharmony_ci		 *	P_MAY_IGNORE
36858c2ecf20Sopenharmony_ci		 *	P_MAX_OPT_CMD
36868c2ecf20Sopenharmony_ci		 */
36878c2ecf20Sopenharmony_ci	};
36888c2ecf20Sopenharmony_ci
36898c2ecf20Sopenharmony_ci	/* too big for the array: 0xfffX */
36908c2ecf20Sopenharmony_ci	if (cmd == P_INITIAL_META)
36918c2ecf20Sopenharmony_ci		return "InitialMeta";
36928c2ecf20Sopenharmony_ci	if (cmd == P_INITIAL_DATA)
36938c2ecf20Sopenharmony_ci		return "InitialData";
36948c2ecf20Sopenharmony_ci	if (cmd == P_CONNECTION_FEATURES)
36958c2ecf20Sopenharmony_ci		return "ConnectionFeatures";
36968c2ecf20Sopenharmony_ci	if (cmd >= ARRAY_SIZE(cmdnames))
36978c2ecf20Sopenharmony_ci		return "Unknown";
36988c2ecf20Sopenharmony_ci	return cmdnames[cmd];
36998c2ecf20Sopenharmony_ci}
37008c2ecf20Sopenharmony_ci
37018c2ecf20Sopenharmony_ci/**
37028c2ecf20Sopenharmony_ci * drbd_wait_misc  -  wait for a request to make progress
37038c2ecf20Sopenharmony_ci * @device:	device associated with the request
37048c2ecf20Sopenharmony_ci * @i:		the struct drbd_interval embedded in struct drbd_request or
37058c2ecf20Sopenharmony_ci *		struct drbd_peer_request
37068c2ecf20Sopenharmony_ci */
37078c2ecf20Sopenharmony_ciint drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
37088c2ecf20Sopenharmony_ci{
37098c2ecf20Sopenharmony_ci	struct net_conf *nc;
37108c2ecf20Sopenharmony_ci	DEFINE_WAIT(wait);
37118c2ecf20Sopenharmony_ci	long timeout;
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci	rcu_read_lock();
37148c2ecf20Sopenharmony_ci	nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
37158c2ecf20Sopenharmony_ci	if (!nc) {
37168c2ecf20Sopenharmony_ci		rcu_read_unlock();
37178c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
37188c2ecf20Sopenharmony_ci	}
37198c2ecf20Sopenharmony_ci	timeout = nc->ko_count ? nc->timeout * HZ / 10 * nc->ko_count : MAX_SCHEDULE_TIMEOUT;
37208c2ecf20Sopenharmony_ci	rcu_read_unlock();
37218c2ecf20Sopenharmony_ci
37228c2ecf20Sopenharmony_ci	/* Indicate to wake up device->misc_wait on progress.  */
37238c2ecf20Sopenharmony_ci	i->waiting = true;
37248c2ecf20Sopenharmony_ci	prepare_to_wait(&device->misc_wait, &wait, TASK_INTERRUPTIBLE);
37258c2ecf20Sopenharmony_ci	spin_unlock_irq(&device->resource->req_lock);
37268c2ecf20Sopenharmony_ci	timeout = schedule_timeout(timeout);
37278c2ecf20Sopenharmony_ci	finish_wait(&device->misc_wait, &wait);
37288c2ecf20Sopenharmony_ci	spin_lock_irq(&device->resource->req_lock);
37298c2ecf20Sopenharmony_ci	if (!timeout || device->state.conn < C_CONNECTED)
37308c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
37318c2ecf20Sopenharmony_ci	if (signal_pending(current))
37328c2ecf20Sopenharmony_ci		return -ERESTARTSYS;
37338c2ecf20Sopenharmony_ci	return 0;
37348c2ecf20Sopenharmony_ci}
37358c2ecf20Sopenharmony_ci
37368c2ecf20Sopenharmony_civoid lock_all_resources(void)
37378c2ecf20Sopenharmony_ci{
37388c2ecf20Sopenharmony_ci	struct drbd_resource *resource;
37398c2ecf20Sopenharmony_ci	int __maybe_unused i = 0;
37408c2ecf20Sopenharmony_ci
37418c2ecf20Sopenharmony_ci	mutex_lock(&resources_mutex);
37428c2ecf20Sopenharmony_ci	local_irq_disable();
37438c2ecf20Sopenharmony_ci	for_each_resource(resource, &drbd_resources)
37448c2ecf20Sopenharmony_ci		spin_lock_nested(&resource->req_lock, i++);
37458c2ecf20Sopenharmony_ci}
37468c2ecf20Sopenharmony_ci
37478c2ecf20Sopenharmony_civoid unlock_all_resources(void)
37488c2ecf20Sopenharmony_ci{
37498c2ecf20Sopenharmony_ci	struct drbd_resource *resource;
37508c2ecf20Sopenharmony_ci
37518c2ecf20Sopenharmony_ci	for_each_resource(resource, &drbd_resources)
37528c2ecf20Sopenharmony_ci		spin_unlock(&resource->req_lock);
37538c2ecf20Sopenharmony_ci	local_irq_enable();
37548c2ecf20Sopenharmony_ci	mutex_unlock(&resources_mutex);
37558c2ecf20Sopenharmony_ci}
37568c2ecf20Sopenharmony_ci
37578c2ecf20Sopenharmony_ci#ifdef CONFIG_DRBD_FAULT_INJECTION
37588c2ecf20Sopenharmony_ci/* Fault insertion support including random number generator shamelessly
37598c2ecf20Sopenharmony_ci * stolen from kernel/rcutorture.c */
37608c2ecf20Sopenharmony_cistruct fault_random_state {
37618c2ecf20Sopenharmony_ci	unsigned long state;
37628c2ecf20Sopenharmony_ci	unsigned long count;
37638c2ecf20Sopenharmony_ci};
37648c2ecf20Sopenharmony_ci
37658c2ecf20Sopenharmony_ci#define FAULT_RANDOM_MULT 39916801  /* prime */
37668c2ecf20Sopenharmony_ci#define FAULT_RANDOM_ADD	479001701 /* prime */
37678c2ecf20Sopenharmony_ci#define FAULT_RANDOM_REFRESH 10000
37688c2ecf20Sopenharmony_ci
37698c2ecf20Sopenharmony_ci/*
37708c2ecf20Sopenharmony_ci * Crude but fast random-number generator.  Uses a linear congruential
37718c2ecf20Sopenharmony_ci * generator, with occasional help from get_random_bytes().
37728c2ecf20Sopenharmony_ci */
37738c2ecf20Sopenharmony_cistatic unsigned long
37748c2ecf20Sopenharmony_ci_drbd_fault_random(struct fault_random_state *rsp)
37758c2ecf20Sopenharmony_ci{
37768c2ecf20Sopenharmony_ci	long refresh;
37778c2ecf20Sopenharmony_ci
37788c2ecf20Sopenharmony_ci	if (!rsp->count--) {
37798c2ecf20Sopenharmony_ci		get_random_bytes(&refresh, sizeof(refresh));
37808c2ecf20Sopenharmony_ci		rsp->state += refresh;
37818c2ecf20Sopenharmony_ci		rsp->count = FAULT_RANDOM_REFRESH;
37828c2ecf20Sopenharmony_ci	}
37838c2ecf20Sopenharmony_ci	rsp->state = rsp->state * FAULT_RANDOM_MULT + FAULT_RANDOM_ADD;
37848c2ecf20Sopenharmony_ci	return swahw32(rsp->state);
37858c2ecf20Sopenharmony_ci}
37868c2ecf20Sopenharmony_ci
37878c2ecf20Sopenharmony_cistatic char *
37888c2ecf20Sopenharmony_ci_drbd_fault_str(unsigned int type) {
37898c2ecf20Sopenharmony_ci	static char *_faults[] = {
37908c2ecf20Sopenharmony_ci		[DRBD_FAULT_MD_WR] = "Meta-data write",
37918c2ecf20Sopenharmony_ci		[DRBD_FAULT_MD_RD] = "Meta-data read",
37928c2ecf20Sopenharmony_ci		[DRBD_FAULT_RS_WR] = "Resync write",
37938c2ecf20Sopenharmony_ci		[DRBD_FAULT_RS_RD] = "Resync read",
37948c2ecf20Sopenharmony_ci		[DRBD_FAULT_DT_WR] = "Data write",
37958c2ecf20Sopenharmony_ci		[DRBD_FAULT_DT_RD] = "Data read",
37968c2ecf20Sopenharmony_ci		[DRBD_FAULT_DT_RA] = "Data read ahead",
37978c2ecf20Sopenharmony_ci		[DRBD_FAULT_BM_ALLOC] = "BM allocation",
37988c2ecf20Sopenharmony_ci		[DRBD_FAULT_AL_EE] = "EE allocation",
37998c2ecf20Sopenharmony_ci		[DRBD_FAULT_RECEIVE] = "receive data corruption",
38008c2ecf20Sopenharmony_ci	};
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_ci	return (type < DRBD_FAULT_MAX) ? _faults[type] : "**Unknown**";
38038c2ecf20Sopenharmony_ci}
38048c2ecf20Sopenharmony_ci
38058c2ecf20Sopenharmony_ciunsigned int
38068c2ecf20Sopenharmony_ci_drbd_insert_fault(struct drbd_device *device, unsigned int type)
38078c2ecf20Sopenharmony_ci{
38088c2ecf20Sopenharmony_ci	static struct fault_random_state rrs = {0, 0};
38098c2ecf20Sopenharmony_ci
38108c2ecf20Sopenharmony_ci	unsigned int ret = (
38118c2ecf20Sopenharmony_ci		(drbd_fault_devs == 0 ||
38128c2ecf20Sopenharmony_ci			((1 << device_to_minor(device)) & drbd_fault_devs) != 0) &&
38138c2ecf20Sopenharmony_ci		(((_drbd_fault_random(&rrs) % 100) + 1) <= drbd_fault_rate));
38148c2ecf20Sopenharmony_ci
38158c2ecf20Sopenharmony_ci	if (ret) {
38168c2ecf20Sopenharmony_ci		drbd_fault_count++;
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ci		if (__ratelimit(&drbd_ratelimit_state))
38198c2ecf20Sopenharmony_ci			drbd_warn(device, "***Simulating %s failure\n",
38208c2ecf20Sopenharmony_ci				_drbd_fault_str(type));
38218c2ecf20Sopenharmony_ci	}
38228c2ecf20Sopenharmony_ci
38238c2ecf20Sopenharmony_ci	return ret;
38248c2ecf20Sopenharmony_ci}
38258c2ecf20Sopenharmony_ci#endif
38268c2ecf20Sopenharmony_ci
38278c2ecf20Sopenharmony_ciconst char *drbd_buildtag(void)
38288c2ecf20Sopenharmony_ci{
38298c2ecf20Sopenharmony_ci	/* DRBD built from external sources has here a reference to the
38308c2ecf20Sopenharmony_ci	   git hash of the source code. */
38318c2ecf20Sopenharmony_ci
38328c2ecf20Sopenharmony_ci	static char buildtag[38] = "\0uilt-in";
38338c2ecf20Sopenharmony_ci
38348c2ecf20Sopenharmony_ci	if (buildtag[0] == 0) {
38358c2ecf20Sopenharmony_ci#ifdef MODULE
38368c2ecf20Sopenharmony_ci		sprintf(buildtag, "srcversion: %-24s", THIS_MODULE->srcversion);
38378c2ecf20Sopenharmony_ci#else
38388c2ecf20Sopenharmony_ci		buildtag[0] = 'b';
38398c2ecf20Sopenharmony_ci#endif
38408c2ecf20Sopenharmony_ci	}
38418c2ecf20Sopenharmony_ci
38428c2ecf20Sopenharmony_ci	return buildtag;
38438c2ecf20Sopenharmony_ci}
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_cimodule_init(drbd_init)
38468c2ecf20Sopenharmony_cimodule_exit(drbd_cleanup)
38478c2ecf20Sopenharmony_ci
38488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drbd_conn_str);
38498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drbd_role_str);
38508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drbd_disk_str);
38518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drbd_set_st_err_str);
3852