linux/drivers/block/nbd.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Network block device - make block devices work over TCP
 *
 * Note that you can not swap over this thing, yet. Seems to work but
 * deadlocks sometimes - you can not swap over TCP in general.
 * 
 * Copyright 1997-2000, 2008 Pavel Machek <[email protected]>
 * Parts copyright 2001 Steven Whitehouse <[email protected]>
 *
 * (part of code stolen from loop.c)
 */

#define pr_fmt(fmt)

#include <linux/major.h>

#include <linux/blkdev.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/mutex.h>
#include <linux/compiler.h>
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <linux/net.h>
#include <linux/kthread.h>
#include <linux/types.h>
#include <linux/debugfs.h>
#include <linux/blk-mq.h>

#include <linux/uaccess.h>
#include <asm/types.h>

#include <linux/nbd.h>
#include <linux/nbd-netlink.h>
#include <net/genetlink.h>

#define CREATE_TRACE_POINTS
#include <trace/events/nbd.h>

static DEFINE_IDR(nbd_index_idr);
static DEFINE_MUTEX(nbd_index_mutex);
static struct workqueue_struct *nbd_del_wq;
static int nbd_total_devices =;

struct nbd_sock {};

struct recv_thread_args {};

struct link_dead_args {};

#define NBD_RT_TIMEDOUT
#define NBD_RT_DISCONNECT_REQUESTED
#define NBD_RT_DISCONNECTED
#define NBD_RT_HAS_PID_FILE
#define NBD_RT_HAS_CONFIG_REF
#define NBD_RT_BOUND
#define NBD_RT_DISCONNECT_ON_CLOSE
#define NBD_RT_HAS_BACKEND_FILE

#define NBD_DESTROY_ON_DISCONNECT
#define NBD_DISCONNECT_REQUESTED

struct nbd_config {};

static inline unsigned int nbd_blksize(struct nbd_config *config)
{}

struct nbd_device {};

#define NBD_CMD_REQUEUED
/*
 * This flag will be set if nbd_queue_rq() succeed, and will be checked and
 * cleared in completion. Both setting and clearing of the flag are protected
 * by cmd->lock.
 */
#define NBD_CMD_INFLIGHT

struct nbd_cmd {};

#if IS_ENABLED(CONFIG_DEBUG_FS)
static struct dentry *nbd_dbg_dir;
#endif

#define nbd_name(nbd)

#define NBD_DEF_BLKSIZE_BITS

static unsigned int nbds_max =;
static int max_part =;
static int part_shift;

static int nbd_dev_dbg_init(struct nbd_device *nbd);
static void nbd_dev_dbg_close(struct nbd_device *nbd);
static void nbd_config_put(struct nbd_device *nbd);
static void nbd_connect_reply(struct genl_info *info, int index);
static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
static void nbd_dead_link_work(struct work_struct *work);
static void nbd_disconnect_and_put(struct nbd_device *nbd);

static inline struct device *nbd_to_dev(struct nbd_device *nbd)
{}

static void nbd_requeue_cmd(struct nbd_cmd *cmd)
{}

#define NBD_COOKIE_BITS

static u64 nbd_cmd_handle(struct nbd_cmd *cmd)
{}

static u32 nbd_handle_to_tag(u64 handle)
{}

static u32 nbd_handle_to_cookie(u64 handle)
{}

static const char *nbdcmd_to_ascii(int cmd)
{}

static ssize_t pid_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{}

static const struct device_attribute pid_attr =;

static ssize_t backend_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{}

static const struct device_attribute backend_attr =;

static void nbd_dev_remove(struct nbd_device *nbd)
{}

static void nbd_dev_remove_work(struct work_struct *work)
{}

static void nbd_put(struct nbd_device *nbd)
{}

static int nbd_disconnected(struct nbd_config *config)
{}

static void nbd_mark_nsock_dead(struct nbd_device *nbd, struct nbd_sock *nsock,
				int notify)
{}

static int __nbd_set_size(struct nbd_device *nbd, loff_t bytesize,
		loff_t blksize)
{}

static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize,
		loff_t blksize)
{}

static void nbd_complete_rq(struct request *req)
{}

/*
 * Forcibly shutdown the socket causing all listeners to error
 */
static void sock_shutdown(struct nbd_device *nbd)
{}

static u32 req_to_nbd_cmd_type(struct request *req)
{}

static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
{}

static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
{}

static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
		       struct iov_iter *iter, int msg_flags, int *sent)
{}

/*
 *  Send or receive packet. Return a positive value on success and
 *  negtive value on failure, and never return 0.
 */
static int sock_xmit(struct nbd_device *nbd, int index, int send,
		     struct iov_iter *iter, int msg_flags, int *sent)
{}

/*
 * Different settings for sk->sk_sndtimeo can result in different return values
 * if there is a signal pending when we enter sendmsg, because reasons?
 */
static inline int was_interrupted(int result)
{}

/*
 * Returns BLK_STS_RESOURCE if the caller should retry after a delay.
 * Returns BLK_STS_IOERR if sending failed.
 */
static blk_status_t nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd,
				 int index)
{}

static int nbd_read_reply(struct nbd_device *nbd, struct socket *sock,
			  struct nbd_reply *reply)
{}

/* NULL returned = something went wrong, inform userspace */
static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,
					struct nbd_reply *reply)
{}

static void recv_work(struct work_struct *work)
{}

static bool nbd_clear_req(struct request *req, void *data)
{}

static void nbd_clear_que(struct nbd_device *nbd)
{}

static int find_fallback(struct nbd_device *nbd, int index)
{}

static int wait_for_reconnect(struct nbd_device *nbd)
{}

static blk_status_t nbd_handle_cmd(struct nbd_cmd *cmd, int index)
{}

static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
			const struct blk_mq_queue_data *bd)
{}

static struct socket *nbd_get_socket(struct nbd_device *nbd, unsigned long fd,
				     int *err)
{}

static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
			  bool netlink)
{}

static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
{}

static void nbd_bdev_reset(struct nbd_device *nbd)
{}

static void nbd_parse_flags(struct nbd_device *nbd)
{}

static void send_disconnects(struct nbd_device *nbd)
{}

static int nbd_disconnect(struct nbd_device *nbd)
{}

static void nbd_clear_sock(struct nbd_device *nbd)
{}

static void nbd_config_put(struct nbd_device *nbd)
{}

static int nbd_start_device(struct nbd_device *nbd)
{}

static int nbd_start_device_ioctl(struct nbd_device *nbd)
{}

static void nbd_clear_sock_ioctl(struct nbd_device *nbd)
{}

static void nbd_set_cmd_timeout(struct nbd_device *nbd, u64 timeout)
{}

/* Must be called with config_lock held */
static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
		       unsigned int cmd, unsigned long arg)
{}

static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,
		     unsigned int cmd, unsigned long arg)
{}

static int nbd_alloc_and_init_config(struct nbd_device *nbd)
{}

static int nbd_open(struct gendisk *disk, blk_mode_t mode)
{}

static void nbd_release(struct gendisk *disk)
{}

static void nbd_free_disk(struct gendisk *disk)
{}

static const struct block_device_operations nbd_fops =;

#if IS_ENABLED(CONFIG_DEBUG_FS)

static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)
{}

DEFINE_SHOW_ATTRIBUTE();

static int nbd_dbg_flags_show(struct seq_file *s, void *unused)
{}

DEFINE_SHOW_ATTRIBUTE();

static int nbd_dev_dbg_init(struct nbd_device *nbd)
{}

static void nbd_dev_dbg_close(struct nbd_device *nbd)
{}

static int nbd_dbg_init(void)
{}

static void nbd_dbg_close(void)
{}

#else  /* IS_ENABLED(CONFIG_DEBUG_FS) */

static int nbd_dev_dbg_init(struct nbd_device *nbd)
{
	return 0;
}

static void nbd_dev_dbg_close(struct nbd_device *nbd)
{
}

static int nbd_dbg_init(void)
{
	return 0;
}

static void nbd_dbg_close(void)
{
}

#endif

static int nbd_init_request(struct blk_mq_tag_set *set, struct request *rq,
			    unsigned int hctx_idx, unsigned int numa_node)
{}

static const struct blk_mq_ops nbd_mq_ops =;

static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
{}

static struct nbd_device *nbd_find_get_unused(void)
{}

/* Netlink interface. */
static const struct nla_policy nbd_attr_policy[NBD_ATTR_MAX + 1] =;

static const struct nla_policy nbd_sock_policy[NBD_SOCK_MAX + 1] =;

/* We don't use this right now since we don't parse the incoming list, but we
 * still want it here so userspace knows what to expect.
 */
static const struct nla_policy __attribute__((unused))
nbd_device_policy[NBD_DEVICE_ATTR_MAX + 1] =;

static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd)
{}

static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
{}

static void nbd_disconnect_and_put(struct nbd_device *nbd)
{}

static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
{}

static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
{}

static const struct genl_small_ops nbd_connect_genl_ops[] =;

static const struct genl_multicast_group nbd_mcast_grps[] =;

static struct genl_family nbd_genl_family __ro_after_init =;
MODULE_ALIAS_GENL_FAMILY();

static int populate_nbd_status(struct nbd_device *nbd, struct sk_buff *reply)
{}

static int status_cb(int id, void *ptr, void *data)
{}

static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info)
{}

static void nbd_connect_reply(struct genl_info *info, int index)
{}

static void nbd_mcast_index(int index)
{}

static void nbd_dead_link_work(struct work_struct *work)
{}

static int __init nbd_init(void)
{}

static int nbd_exit_cb(int id, void *ptr, void *data)
{}

static void __exit nbd_cleanup(void)
{}

module_init();
module_exit(nbd_cleanup);

MODULE_DESCRIPTION();
MODULE_LICENSE();

module_param(nbds_max, int, 0444);
MODULE_PARM_DESC();
module_param(max_part, int, 0444);
MODULE_PARM_DESC();