summaryrefslogtreecommitdiffstats
path: root/src/kernel/dnbd3_main.h
blob: a932ba2f41d59e1e7c6c48fa1ec33047a6387bcb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * This file is part of the Distributed Network Block Device 3
 *
 * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de>
 *
 * This file may be licensed under the terms of the
 * GNU General Public License Version 2 (the ``GPL'').
 *
 * Software distributed under the License is distributed
 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the GPL for the specific language
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef DNBD_H_
#define DNBD_H_

#include <dnbd3/config/client.h>

#include <linux/version.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <net/sock.h>

#include <dnbd3/config.h>
#include <dnbd3/types.h>
#include <dnbd3/shared/serialize.h>

#include <linux/blk-mq.h>

#if defined(RHEL_RELEASE_CODE) && defined(RHEL_RELEASE_VERSION)
#define RHEL_CHECK_VERSION(CONDITION) (CONDITION)
#else
#define RHEL_CHECK_VERSION(CONDITION) (0)
#endif

extern int major;

typedef struct {
	unsigned long rtts[DISCOVER_HISTORY_SIZE]; // Last X round trip time measurements in µs
	uint16_t protocol_version; // dnbd3 protocol version of this server
	uint8_t failures;          // How many times the server was unreachable
	uint8_t best_count;        // Number of times server measured best
	struct sockaddr_storage host; // Address of server
} dnbd3_alt_server_t;

typedef struct {
	// block
	int                        index;
	struct gendisk            *disk;
	struct blk_mq_tag_set      tag_set;
	struct request_queue      *queue;
	spinlock_t                 blk_lock;

	// sysfs
	struct kobject             kobj;

	char                      *imgname;
	uint16_t                   rid;
	struct socket             *sock;
	struct { // use blk_lock
		unsigned long           rtt;
		struct sockaddr_storage host;
		uint16_t                protocol_version;
	}              cur_server;
	serialized_buffer_t        payload_buffer;
	struct mutex               alt_servers_lock;
	dnbd3_alt_server_t         alt_servers[NUMBER_SERVERS];
	bool                       use_server_provided_alts;
	bool                       panic;
	u8                         panic_count;
	bool                       update_available;
	atomic_t                   connection_lock;
	// Size if image/device - this is 0 if the device is not in use,
	// otherwise this is also the value we expect from alt servers.
	uint64_t                   reported_size;
	struct delayed_work        keepalive_work;

	// sending
	struct workqueue_struct   *send_wq;
	spinlock_t                 send_queue_lock;
	struct list_head           send_queue;
	struct mutex               send_mutex;
	struct work_struct         send_work;
	// receiving
	struct workqueue_struct   *recv_wq;
	spinlock_t                 recv_queue_lock;
	struct list_head           recv_queue;
	struct mutex               recv_mutex;
	struct work_struct         recv_work;
	// discover
	atomic_t                   discover_running;
	struct delayed_work        discover_work;
	u32                        discover_interval;
	u32                        discover_count;

} dnbd3_device_t;

struct dnbd3_cmd {
	u64        handle;
};

extern inline struct device *dnbd3_device_to_dev(dnbd3_device_t *dev);

extern inline int is_same_server(const struct sockaddr_storage *const x, const struct sockaddr_storage *const y);

extern int dnbd3_host_to_sockaddr(const dnbd3_host_t *host, struct sockaddr_storage *dest);

extern dnbd3_alt_server_t *get_existing_alt_from_host(const dnbd3_host_t *const host, dnbd3_device_t *const dev);

extern dnbd3_alt_server_t *get_existing_alt_from_addr(const struct sockaddr_storage *const addr,
		dnbd3_device_t *const dev);

extern int dnbd3_add_server(dnbd3_device_t *dev, dnbd3_host_t *host);

extern int dnbd3_rem_server(dnbd3_device_t *dev, dnbd3_host_t *host);

#define dnbd3_flag_get(x) (atomic_cmpxchg(&(x), 0, 1) == 0)
#define dnbd3_flag_reset(x) atomic_set(&(x), 0)
#define dnbd3_flag_taken(x) (atomic_read(&(x)) != 0)

/*
 * shims for making older kernels look like the current one, if possible, to avoid too
 * much inline #ifdef which makes code harder to read.
 */

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
#define BLK_EH_DONE BLK_EH_NOT_HANDLED
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
#define blk_status_t int
#define	BLK_STS_OK 0
#define	BLK_STS_IOERR (-EIO)
#define	BLK_STS_TIMEOUT (-ETIME)
#define	BLK_STS_NOTSUPP (-ENOTSUPP)
#endif

#endif /* DNBD_H_ */