]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd_wnbd/wnbd_handler.h
import ceph quincy 17.2.6
[ceph.git] / ceph / src / tools / rbd_wnbd / wnbd_handler.h
CommitLineData
f67539c2
TL
1/*
2 * Ceph - scalable distributed file system
3 *
4 * Copyright (C) 2020 SUSE LINUX GmbH
5 *
6 * This is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software
9 * Foundation. See file COPYING.
10 *
11 */
12
13#ifndef WNBD_HANDLER_H
14#define WNBD_HANDLER_H
15
16#include <wnbd.h>
17
18#include "common/admin_socket.h"
19#include "common/ceph_context.h"
20#include "common/Thread.h"
21
22#include "include/rbd/librbd.hpp"
23#include "include/xlist.h"
24
25#include "global/global_context.h"
26
27// TODO: make this configurable.
28#define RBD_WNBD_MAX_TRANSFER 2 * 1024 * 1024
29#define SOFT_REMOVE_RETRY_INTERVAL 2
30#define DEFAULT_SOFT_REMOVE_TIMEOUT 15
31#define DEFAULT_IO_WORKER_COUNT 4
32
33// Not defined by mingw.
34#ifndef SCSI_ADSENSE_UNRECOVERED_ERROR
35#define SCSI_ADSENSE_UNRECOVERED_ERROR 0x11
36#endif
37
38// The following will be assigned to the "Owner" field of the WNBD
39// parameters, which can be used to determine the application managing
40// a disk. We'll ignore other disks.
41#define RBD_WNBD_OWNER_NAME "ceph-rbd-wnbd"
42
43class WnbdHandler;
44
45class WnbdAdminHook : public AdminSocketHook {
46 WnbdHandler *m_handler;
47
48public:
49 explicit WnbdAdminHook(WnbdHandler *handler) :
50 m_handler(handler) {
51 g_ceph_context->get_admin_socket()->register_command(
52 "wnbd stats", this, "get WNBD stats");
53 }
54 ~WnbdAdminHook() override {
55 g_ceph_context->get_admin_socket()->unregister_commands(this);
56 }
57
58 int call(std::string_view command, const cmdmap_t& cmdmap,
39ae355f
TL
59 const bufferlist&,
60 Formatter *f, std::ostream& errss, bufferlist& out) override;
f67539c2
TL
61};
62
63
64class WnbdHandler
65{
66private:
67 librbd::Image &image;
68 std::string instance_name;
69 uint64_t block_count;
70 uint32_t block_size;
71 bool readonly;
72 bool rbd_cache_enabled;
73 uint32_t io_req_workers;
74 uint32_t io_reply_workers;
75 WnbdAdminHook* admin_hook;
76 boost::asio::thread_pool* reply_tpool;
77
78public:
79 WnbdHandler(librbd::Image& _image, std::string _instance_name,
80 uint64_t _block_count, uint32_t _block_size,
81 bool _readonly, bool _rbd_cache_enabled,
82 uint32_t _io_req_workers,
83 uint32_t _io_reply_workers)
84 : image(_image)
85 , instance_name(_instance_name)
86 , block_count(_block_count)
87 , block_size(_block_size)
88 , readonly(_readonly)
89 , rbd_cache_enabled(_rbd_cache_enabled)
90 , io_req_workers(_io_req_workers)
91 , io_reply_workers(_io_reply_workers)
92 {
93 admin_hook = new WnbdAdminHook(this);
94 // Instead of relying on librbd's own thread pool, we're going to use a
95 // separate one. This allows us to make assumptions on the threads that
96 // are going to send the IO replies and thus be able to cache Windows
97 // OVERLAPPED structures.
98 reply_tpool = new boost::asio::thread_pool(_io_reply_workers);
99 }
100
101 int start();
102 // Wait for the handler to stop, which normally happens when the driver
103 // passes the "Disconnect" request.
104 int wait();
105 void shutdown();
106
107 int dump_stats(Formatter *f);
108
109 ~WnbdHandler();
110
111 static VOID LogMessage(
112 WnbdLogLevel LogLevel,
113 const char* Message,
114 const char* FileName,
115 UINT32 Line,
116 const char* FunctionName);
117
118private:
119 ceph::mutex shutdown_lock = ceph::make_mutex("WnbdHandler::DisconnectLocker");
120 bool started = false;
121 bool terminated = false;
122 WNBD_DISK* wnbd_disk = nullptr;
123
124 struct IOContext
125 {
126 xlist<IOContext*>::item item;
127 WnbdHandler *handler = nullptr;
128 WNBD_STATUS wnbd_status = {0};
129 WnbdRequestType req_type = WnbdReqTypeUnknown;
130 uint64_t req_handle = 0;
131 uint32_t err_code = 0;
132 size_t req_size;
133 uint64_t req_from;
134 bufferlist data;
135
136 IOContext()
137 : item(this)
138 {}
139
140 void set_sense(uint8_t sense_key, uint8_t asc, uint64_t info);
141 void set_sense(uint8_t sense_key, uint8_t asc);
142 };
143
144 friend std::ostream &operator<<(std::ostream &os, const IOContext &ctx);
145
146 void send_io_response(IOContext *ctx);
147
148 static void aio_callback(librbd::completion_t cb, void *arg);
149
150 // WNBD IO entry points
151 static void Read(
152 PWNBD_DISK Disk,
153 UINT64 RequestHandle,
154 PVOID Buffer,
155 UINT64 BlockAddress,
156 UINT32 BlockCount,
157 BOOLEAN ForceUnitAccess);
158 static void Write(
159 PWNBD_DISK Disk,
160 UINT64 RequestHandle,
161 PVOID Buffer,
162 UINT64 BlockAddress,
163 UINT32 BlockCount,
164 BOOLEAN ForceUnitAccess);
165 static void Flush(
166 PWNBD_DISK Disk,
167 UINT64 RequestHandle,
168 UINT64 BlockAddress,
169 UINT32 BlockCount);
170 static void Unmap(
171 PWNBD_DISK Disk,
172 UINT64 RequestHandle,
173 PWNBD_UNMAP_DESCRIPTOR Descriptors,
174 UINT32 Count);
175
176 static constexpr WNBD_INTERFACE RbdWnbdInterface =
177 {
178 Read,
179 Write,
180 Flush,
181 Unmap,
182 };
183};
184
185std::ostream &operator<<(std::ostream &os, const WnbdHandler::IOContext &ctx);
186
187#endif // WNBD_HANDLER_H