#include <linux/module.h>
#include <linux/uaccess.h>
#include <net/sock.h>
#include <linux/drbd.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/in.h>
#include <linux/mm.h>
#include <linux/memcontrol.h>
#include <linux/mm_inline.h>
#include <linux/slab.h>
#include <uapi/linux/sched/types.h>
#include <linux/sched/signal.h>
#include <linux/pkt_sched.h>
#include <linux/unistd.h>
#include <linux/vmalloc.h>
#include <linux/random.h>
#include <linux/string.h>
#include <linux/scatterlist.h>
#include <linux/part_stat.h>
#include "drbd_int.h"
#include "drbd_protocol.h"
#include "drbd_req.h"
#include "drbd_vli.h"
#define PRO_FEATURES …
struct packet_info { … };
enum finish_epoch { … };
static int drbd_do_features(struct drbd_connection *connection);
static int drbd_do_auth(struct drbd_connection *connection);
static int drbd_disconnected(struct drbd_peer_device *);
static void conn_wait_active_ee_empty(struct drbd_connection *connection);
static enum finish_epoch drbd_may_finish_epoch(struct drbd_connection *, struct drbd_epoch *, enum epoch_event);
static int e_end_block(struct drbd_work *, int);
#define GFP_TRY …
static struct page *page_chain_del(struct page **head, int n)
{ … }
static struct page *page_chain_tail(struct page *page, int *len)
{ … }
static int page_chain_free(struct page *page)
{ … }
static void page_chain_add(struct page **head,
struct page *chain_first, struct page *chain_last)
{ … }
static struct page *__drbd_alloc_pages(struct drbd_device *device,
unsigned int number)
{ … }
static void reclaim_finished_net_peer_reqs(struct drbd_device *device,
struct list_head *to_be_freed)
{ … }
static void drbd_reclaim_net_peer_reqs(struct drbd_device *device)
{ … }
static void conn_reclaim_net_peer_reqs(struct drbd_connection *connection)
{ … }
struct page *drbd_alloc_pages(struct drbd_peer_device *peer_device, unsigned int number,
bool retry)
{ … }
static void drbd_free_pages(struct drbd_device *device, struct page *page, int is_net)
{ … }
struct drbd_peer_request *
drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
unsigned int request_size, unsigned int payload_size, gfp_t gfp_mask) __must_hold(local)
{ … }
void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *peer_req,
int is_net)
{ … }
int drbd_free_peer_reqs(struct drbd_device *device, struct list_head *list)
{ … }
static int drbd_finish_peer_reqs(struct drbd_device *device)
{ … }
static void _drbd_wait_ee_list_empty(struct drbd_device *device,
struct list_head *head)
{ … }
static void drbd_wait_ee_list_empty(struct drbd_device *device,
struct list_head *head)
{ … }
static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flags)
{ … }
static int drbd_recv(struct drbd_connection *connection, void *buf, size_t size)
{ … }
static int drbd_recv_all(struct drbd_connection *connection, void *buf, size_t size)
{ … }
static int drbd_recv_all_warn(struct drbd_connection *connection, void *buf, size_t size)
{ … }
static void drbd_setbufsize(struct socket *sock, unsigned int snd,
unsigned int rcv)
{ … }
static struct socket *drbd_try_connect(struct drbd_connection *connection)
{ … }
struct accept_wait_data { … };
static void drbd_incoming_connection(struct sock *sk)
{ … }
static int prepare_listen_socket(struct drbd_connection *connection, struct accept_wait_data *ad)
{ … }
static void unregister_state_change(struct sock *sk, struct accept_wait_data *ad)
{ … }
static struct socket *drbd_wait_for_connect(struct drbd_connection *connection, struct accept_wait_data *ad)
{ … }
static int decode_header(struct drbd_connection *, void *, struct packet_info *);
static int send_first_packet(struct drbd_connection *connection, struct drbd_socket *sock,
enum drbd_packet cmd)
{ … }
static int receive_first_packet(struct drbd_connection *connection, struct socket *sock)
{ … }
static bool drbd_socket_okay(struct socket **sock)
{ … }
static bool connection_established(struct drbd_connection *connection,
struct socket **sock1,
struct socket **sock2)
{ … }
int drbd_connected(struct drbd_peer_device *peer_device)
{ … }
static int conn_connect(struct drbd_connection *connection)
{ … }
static int decode_header(struct drbd_connection *connection, void *header, struct packet_info *pi)
{ … }
static void drbd_unplug_all_devices(struct drbd_connection *connection)
{ … }
static int drbd_recv_header(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int drbd_recv_header_maybe_unplug(struct drbd_connection *connection, struct packet_info *pi)
{ … }
struct issue_flush_context { … };
struct one_flush_context { … };
static void one_flush_endio(struct bio *bio)
{ … }
static void submit_one_flush(struct drbd_device *device, struct issue_flush_context *ctx)
{ … }
static void drbd_flush(struct drbd_connection *connection)
{ … }
static enum finish_epoch drbd_may_finish_epoch(struct drbd_connection *connection,
struct drbd_epoch *epoch,
enum epoch_event ev)
{ … }
static enum write_ordering_e
max_allowed_wo(struct drbd_backing_dev *bdev, enum write_ordering_e wo)
{ … }
void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backing_dev *bdev,
enum write_ordering_e wo)
{ … }
int drbd_issue_discard_or_zero_out(struct drbd_device *device, sector_t start, unsigned int nr_sectors, int flags)
{ … }
static bool can_do_reliable_discards(struct drbd_device *device)
{ … }
static void drbd_issue_peer_discard_or_zero_out(struct drbd_device *device, struct drbd_peer_request *peer_req)
{ … }
static int peer_request_fault_type(struct drbd_peer_request *peer_req)
{ … }
int drbd_submit_peer_request(struct drbd_peer_request *peer_req)
{ … }
static void drbd_remove_epoch_entry_interval(struct drbd_device *device,
struct drbd_peer_request *peer_req)
{ … }
static void conn_wait_active_ee_empty(struct drbd_connection *connection)
{ … }
static int receive_Barrier(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static void drbd_csum_ee_size(struct crypto_shash *h,
struct drbd_peer_request *r, void *d,
unsigned int payload_size)
{ … }
static struct drbd_peer_request *
read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
struct packet_info *pi) __must_hold(local)
{ … }
static int drbd_drain_block(struct drbd_peer_device *peer_device, int data_size)
{ … }
static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_request *req,
sector_t sector, int data_size)
{ … }
static int e_end_resync_block(struct drbd_work *w, int unused)
{ … }
static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t sector,
struct packet_info *pi) __releases(local)
{ … }
static struct drbd_request *
find_request(struct drbd_device *device, struct rb_root *root, u64 id,
sector_t sector, bool missing_ok, const char *func)
{ … }
static int receive_DataReply(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_RSDataReply(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static void restart_conflicting_writes(struct drbd_device *device,
sector_t sector, int size)
{ … }
static int e_end_block(struct drbd_work *w, int cancel)
{ … }
static int e_send_ack(struct drbd_work *w, enum drbd_packet ack)
{ … }
static int e_send_superseded(struct drbd_work *w, int unused)
{ … }
static int e_send_retry_write(struct drbd_work *w, int unused)
{ … }
static bool seq_greater(u32 a, u32 b)
{ … }
static u32 seq_max(u32 a, u32 b)
{ … }
static void update_peer_seq(struct drbd_peer_device *peer_device, unsigned int peer_seq)
{ … }
static inline int overlaps(sector_t s1, int l1, sector_t s2, int l2)
{ … }
static bool overlapping_resync_write(struct drbd_device *device, struct drbd_peer_request *peer_req)
{ … }
static int wait_for_and_update_peer_seq(struct drbd_peer_device *peer_device, const u32 peer_seq)
{ … }
static enum req_op wire_flags_to_bio_op(u32 dpf)
{ … }
static blk_opf_t wire_flags_to_bio(struct drbd_connection *connection, u32 dpf)
{ … }
static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
unsigned int size)
{ … }
static int handle_write_conflicts(struct drbd_device *device,
struct drbd_peer_request *peer_req)
{ … }
static int receive_Data(struct drbd_connection *connection, struct packet_info *pi)
{ … }
bool drbd_rs_should_slow_down(struct drbd_peer_device *peer_device, sector_t sector,
bool throttle_if_app_is_waiting)
{ … }
bool drbd_rs_c_min_rate_throttle(struct drbd_device *device)
{ … }
static int receive_DataRequest(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold(local)
{ … }
static int drbd_asb_recover_1p(struct drbd_peer_device *peer_device) __must_hold(local)
{ … }
static int drbd_asb_recover_2p(struct drbd_peer_device *peer_device) __must_hold(local)
{ … }
static void drbd_uuid_dump(struct drbd_device *device, char *text, u64 *uuid,
u64 bits, u64 flags)
{ … }
static int drbd_uuid_compare(struct drbd_peer_device *const peer_device,
enum drbd_role const peer_role, int *rule_nr) __must_hold(local)
{ … }
static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
enum drbd_role peer_role,
enum drbd_disk_state peer_disk) __must_hold(local)
{ … }
static enum drbd_after_sb_p convert_after_sb(enum drbd_after_sb_p peer)
{ … }
static int receive_protocol(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static struct crypto_shash *drbd_crypto_alloc_digest_safe(
const struct drbd_device *device,
const char *alg, const char *name)
{ … }
static int ignore_remaining_packet(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int config_unknown_volume(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_SyncParam(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static void warn_if_differ_considerably(struct drbd_device *device,
const char *s, sector_t a, sector_t b)
{ … }
static int receive_sizes(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_uuids(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static union drbd_state convert_state(union drbd_state ps)
{ … }
static int receive_req_state(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_req_conn_state(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_state(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_sync_uuid(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int
receive_bitmap_plain(struct drbd_peer_device *peer_device, unsigned int size,
unsigned long *p, struct bm_xfer_ctx *c)
{ … }
static enum drbd_bitmap_code dcbp_get_code(struct p_compressed_bm *p)
{ … }
static int dcbp_get_start(struct p_compressed_bm *p)
{ … }
static int dcbp_get_pad_bits(struct p_compressed_bm *p)
{ … }
static int
recv_bm_rle_bits(struct drbd_peer_device *peer_device,
struct p_compressed_bm *p,
struct bm_xfer_ctx *c,
unsigned int len)
{ … }
static int
decode_bitmap_c(struct drbd_peer_device *peer_device,
struct p_compressed_bm *p,
struct bm_xfer_ctx *c,
unsigned int len)
{ … }
void INFO_bm_xfer_stats(struct drbd_peer_device *peer_device,
const char *direction, struct bm_xfer_ctx *c)
{ … }
static int receive_bitmap(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_skip(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_UnplugRemote(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_out_of_sync(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int receive_rs_deallocated(struct drbd_connection *connection, struct packet_info *pi)
{ … }
struct data_cmd { … };
static struct data_cmd drbd_cmd_handler[] = …;
static void drbdd(struct drbd_connection *connection)
{ … }
static void conn_disconnect(struct drbd_connection *connection)
{ … }
static int drbd_disconnected(struct drbd_peer_device *peer_device)
{ … }
static int drbd_send_features(struct drbd_connection *connection)
{ … }
static int drbd_do_features(struct drbd_connection *connection)
{ … }
#if !defined(CONFIG_CRYPTO_HMAC) && !defined(CONFIG_CRYPTO_HMAC_MODULE)
static int drbd_do_auth(struct drbd_connection *connection)
{
drbd_err(connection, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
drbd_err(connection, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
return -1;
}
#else
#define CHALLENGE_LEN …
static int drbd_do_auth(struct drbd_connection *connection)
{ … }
#endif
int drbd_receiver(struct drbd_thread *thi)
{ … }
static int got_conn_RqSReply(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_RqSReply(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_Ping(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_PingAck(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_IsInSync(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int
validate_req_change_req_state(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
struct rb_root *root, const char *func,
enum drbd_req_event what, bool missing_ok)
{ … }
static int got_BlockAck(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_NegAck(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_NegDReply(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_NegRSDReply(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_BarrierAck(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_OVResult(struct drbd_connection *connection, struct packet_info *pi)
{ … }
static int got_skip(struct drbd_connection *connection, struct packet_info *pi)
{ … }
struct meta_sock_cmd { … };
static void set_rcvtimeo(struct drbd_connection *connection, bool ping_timeout)
{ … }
static void set_ping_timeout(struct drbd_connection *connection)
{ … }
static void set_idle_timeout(struct drbd_connection *connection)
{ … }
static struct meta_sock_cmd ack_receiver_tbl[] = …;
int drbd_ack_receiver(struct drbd_thread *thi)
{ … }
void drbd_send_acks_wf(struct work_struct *ws)
{ … }