root/drivers/block/rnbd/rnbd-clt.h
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * RDMA Network Block Driver
 *
 * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.
 * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.
 * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.
 */

#ifndef RNBD_CLT_H
#define RNBD_CLT_H

#include <linux/wait.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/blk-mq.h>
#include <linux/refcount.h>

#include <rtrs.h>
#include "rnbd-proto.h"
#include "rnbd-log.h"

/*  time in seconds between reconnect tries, default to 30 s */
#define RECONNECT_DELAY 30
/*
 * Number of times to reconnect on error before giving up, 0 for * disabled,
 * -1 for forever
 */
#define MAX_RECONNECTS -1

enum rnbd_clt_dev_state {
        DEV_STATE_INIT,
        DEV_STATE_MAPPED,
        DEV_STATE_MAPPED_DISCONNECTED,
        DEV_STATE_UNMAPPED,
};

struct rnbd_iu_comp {
        wait_queue_head_t wait;
        int errno;
};

#ifdef CONFIG_ARCH_NO_SG_CHAIN
#define RNBD_INLINE_SG_CNT 0
#else
#define RNBD_INLINE_SG_CNT 2
#endif
#define RNBD_RDMA_SGL_SIZE (sizeof(struct scatterlist) * RNBD_INLINE_SG_CNT)

struct rnbd_iu {
        union {
                struct request *rq; /* for block io */
                void *buf; /* for user messages */
        };
        struct rtrs_permit      *permit;
        union {
                /* use to send msg associated with a dev */
                struct rnbd_clt_dev *dev;
                /* use to send msg associated with a sess */
                struct rnbd_clt_session *sess;
        };
        struct sg_table         sgt;
        struct work_struct      work;
        int                     errno;
        struct rnbd_iu_comp     comp;
        atomic_t                refcount;
        struct scatterlist      first_sgl[]; /* must be the last one */
};

struct rnbd_cpu_qlist {
        struct list_head        requeue_list;
        spinlock_t              requeue_lock;
        unsigned int            cpu;
};

struct rnbd_clt_session {
        struct list_head        list;
        struct rtrs_clt_sess        *rtrs;
        wait_queue_head_t       rtrs_waitq;
        bool                    rtrs_ready;
        struct rnbd_cpu_qlist   __percpu
                                *cpu_queues;
        DECLARE_BITMAP(cpu_queues_bm, NR_CPUS);
        int     __percpu        *cpu_rr; /* per-cpu var for CPU round-robin */
        atomic_t                busy;
        size_t                  queue_depth;
        u32                     max_io_size;
        u32                     max_segments;
        struct blk_mq_tag_set   tag_set;
        u32                     nr_poll_queues;
        struct mutex            lock; /* protects state and devs_list */
        struct list_head        devs_list; /* list of struct rnbd_clt_dev */
        refcount_t              refcount;
        char                    sessname[NAME_MAX];
        u8                      ver; /* protocol version */
};

/**
 * Submission queues.
 */
struct rnbd_queue {
        struct list_head        requeue_list;
        unsigned long           in_list;
        struct rnbd_clt_dev     *dev;
        struct blk_mq_hw_ctx    *hctx;
};

struct rnbd_clt_dev {
        struct kobject          kobj;
        struct rnbd_clt_session *sess;
        struct request_queue    *queue;
        struct rnbd_queue       *hw_queues;
        u32                     device_id;
        /* local Idr index - used to track minor number allocations. */
        int                     clt_device_id;
        struct mutex            lock;
        enum rnbd_clt_dev_state dev_state;
        refcount_t              refcount;
        char                    *pathname;
        enum rnbd_access_mode   access_mode;
        u32                     nr_poll_queues;
        u64                     size;           /* device size in bytes */
        struct list_head        list;
        struct gendisk          *gd;
        char                    *blk_symlink_name;
        struct work_struct      unmap_on_rmmod_work;
};

/* rnbd-clt.c */

struct rnbd_clt_dev *rnbd_clt_map_device(const char *sessname,
                                           struct rtrs_addr *paths,
                                           size_t path_cnt, u16 port_nr,
                                           const char *pathname,
                                           enum rnbd_access_mode access_mode,
                                           u32 nr_poll_queues);
int rnbd_clt_unmap_device(struct rnbd_clt_dev *dev, bool force,
                           const struct attribute *sysfs_self);

int rnbd_clt_remap_device(struct rnbd_clt_dev *dev);
int rnbd_clt_resize_disk(struct rnbd_clt_dev *dev, sector_t newsize);

/* rnbd-clt-sysfs.c */

int rnbd_clt_create_sysfs_files(void);

void rnbd_clt_destroy_sysfs_files(void);

void rnbd_clt_remove_dev_symlink(struct rnbd_clt_dev *dev);

#endif /* RNBD_CLT_H */