Skip to content

Commit 6fd11c0

Browse files
committed
librbd/migration/NBDStream: abstract out libnbd and add unit tests
Signed-off-by: Ilya Dryomov <[email protected]>
1 parent 3260b8f commit 6fd11c0

File tree

3 files changed

+738
-32
lines changed

3 files changed

+738
-32
lines changed

src/librbd/migration/NBDStream.cc

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,61 @@ int extent_cb(void* data, const char* metacontext, uint64_t offset,
4747

4848
} // anonymous namespace
4949

50+
template <typename>
51+
class NBDClient {
52+
public:
53+
static NBDClient* create() {
54+
return new NBDClient();
55+
}
56+
57+
const char* get_error() {
58+
return nbd_get_error();
59+
}
60+
61+
int get_errno() {
62+
return nbd_get_errno();
63+
}
64+
65+
int init() {
66+
m_handle.reset(nbd_create());
67+
return m_handle != nullptr ? 0 : -1;
68+
}
69+
70+
int add_meta_context(const char* name) {
71+
return nbd_add_meta_context(m_handle.get(), name);
72+
}
73+
74+
int connect_uri(const char* uri) {
75+
return nbd_connect_uri(m_handle.get(), uri);
76+
}
77+
78+
int64_t get_size() {
79+
return nbd_get_size(m_handle.get());
80+
}
81+
82+
int pread(void* buf, size_t count, uint64_t offset, uint32_t flags) {
83+
return nbd_pread(m_handle.get(), buf, count, offset, flags);
84+
}
85+
86+
int block_status(uint64_t count, uint64_t offset,
87+
nbd_extent_callback extent_callback, uint32_t flags) {
88+
return nbd_block_status(m_handle.get(), count, offset, extent_callback,
89+
flags);
90+
}
91+
92+
int shutdown(uint32_t flags) {
93+
return nbd_shutdown(m_handle.get(), flags);
94+
}
95+
96+
private:
97+
struct nbd_handle_deleter {
98+
void operator()(nbd_handle* h) {
99+
nbd_close(h);
100+
}
101+
};
102+
std::unique_ptr<nbd_handle, nbd_handle_deleter> m_handle;
103+
};
104+
50105
#define dout_subsys ceph_subsys_rbd
51106
#undef dout_prefix
52107
#define dout_prefix *_dout << "librbd::migration::NBDStream::ReadRequest: " \
@@ -84,14 +139,14 @@ struct NBDStream<I>::ReadRequest {
84139
ldout(cct, 20) << "byte_offset=" << byte_offset << " byte_length="
85140
<< byte_length << dendl;
86141

142+
auto& nbd_client = nbd_stream->m_nbd_client;
87143
auto ptr = buffer::ptr_node::create(buffer::create_small_page_aligned(
88144
byte_length));
89-
int rc = nbd_pread(nbd_stream->m_nbd, ptr->c_str(), byte_length,
90-
byte_offset, 0);
145+
int rc = nbd_client->pread(ptr->c_str(), byte_length, byte_offset, 0);
91146
if (rc == -1) {
92-
rc = nbd_get_errno();
147+
rc = nbd_client->get_errno();
93148
lderr(cct) << "pread " << byte_offset << "~" << byte_length << ": "
94-
<< nbd_get_error() << " (errno = " << rc << ")"
149+
<< nbd_client->get_error() << " (errno = " << rc << ")"
95150
<< dendl;
96151
finish(from_nbd_errno(rc));
97152
return;
@@ -160,12 +215,13 @@ struct NBDStream<I>::ListSparseExtentsRequest {
160215
tmp_sparse_extents.insert(byte_offset, byte_length,
161216
{io::SPARSE_EXTENT_STATE_DATA, byte_length});
162217

163-
int rc = nbd_block_status(nbd_stream->m_nbd, byte_length, byte_offset,
164-
{extent_cb, &tmp_sparse_extents}, 0);
218+
auto& nbd_client = nbd_stream->m_nbd_client;
219+
int rc = nbd_client->block_status(byte_length, byte_offset,
220+
{extent_cb, &tmp_sparse_extents}, 0);
165221
if (rc == -1) {
166-
rc = nbd_get_errno();
222+
rc = nbd_client->get_errno();
167223
lderr(cct) << "block_status " << byte_offset << "~" << byte_length << ": "
168-
<< nbd_get_error() << " (errno = " << rc << ")"
224+
<< nbd_client->get_error() << " (errno = " << rc << ")"
169225
<< dendl;
170226
// don't propagate errors -- we are set up to list any missing
171227
// parts of the range as DATA if nbd_block_status() returns less
@@ -201,9 +257,6 @@ NBDStream<I>::NBDStream(I* image_ctx, const json_spirit::mObject& json_object)
201257

202258
template <typename I>
203259
NBDStream<I>::~NBDStream() {
204-
if (m_nbd != nullptr) {
205-
nbd_close(m_nbd);
206-
}
207260
}
208261

209262
template <typename I>
@@ -228,28 +281,29 @@ void NBDStream<I>::open(Context* on_finish) {
228281

229282
ldout(m_cct, 10) << "uri=" << uri << dendl;
230283

231-
m_nbd = nbd_create();
232-
if (m_nbd == nullptr) {
233-
rc = nbd_get_errno();
234-
lderr(m_cct) << "create: " << nbd_get_error()
284+
m_nbd_client.reset(NBDClient<I>::create());
285+
rc = m_nbd_client->init();
286+
if (rc == -1) {
287+
rc = m_nbd_client->get_errno();
288+
lderr(m_cct) << "init: " << m_nbd_client->get_error()
235289
<< " (errno = " << rc << ")" << dendl;
236290
on_finish->complete(from_nbd_errno(rc));
237291
return;
238292
}
239293

240-
rc = nbd_add_meta_context(m_nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
294+
rc = m_nbd_client->add_meta_context(LIBNBD_CONTEXT_BASE_ALLOCATION);
241295
if (rc == -1) {
242-
rc = nbd_get_errno();
243-
lderr(m_cct) << "add_meta_context: " << nbd_get_error()
296+
rc = m_nbd_client->get_errno();
297+
lderr(m_cct) << "add_meta_context: " << m_nbd_client->get_error()
244298
<< " (errno = " << rc << ")" << dendl;
245299
on_finish->complete(from_nbd_errno(rc));
246300
return;
247301
}
248302

249-
rc = nbd_connect_uri(m_nbd, uri.c_str());
303+
rc = m_nbd_client->connect_uri(uri.c_str());
250304
if (rc == -1) {
251-
rc = nbd_get_errno();
252-
lderr(m_cct) << "connect_uri: " << nbd_get_error()
305+
rc = m_nbd_client->get_errno();
306+
lderr(m_cct) << "connect_uri: " << m_nbd_client->get_error()
253307
<< " (errno = " << rc << ")" << dendl;
254308
on_finish->complete(from_nbd_errno(rc));
255309
return;
@@ -262,15 +316,13 @@ template <typename I>
262316
void NBDStream<I>::close(Context* on_finish) {
263317
ldout(m_cct, 20) << dendl;
264318

265-
if (m_nbd != nullptr) {
319+
if (m_nbd_client != nullptr) {
266320
// send a graceful shutdown to the server
267321
// ignore errors -- we are read-only, also from the client's
268322
// POV there is no disadvantage to abruptly closing the socket
269323
// in nbd_close()
270-
nbd_shutdown(m_nbd, 0);
271-
272-
nbd_close(m_nbd);
273-
m_nbd = nullptr;
324+
m_nbd_client->shutdown(0);
325+
m_nbd_client.reset();
274326
}
275327

276328
on_finish->complete(0);
@@ -280,10 +332,10 @@ template <typename I>
280332
void NBDStream<I>::get_size(uint64_t* size, Context* on_finish) {
281333
ldout(m_cct, 20) << dendl;
282334

283-
int64_t rc = nbd_get_size(m_nbd);
335+
int64_t rc = m_nbd_client->get_size();
284336
if (rc == -1) {
285-
rc = nbd_get_errno();
286-
lderr(m_cct) << "get_size: " << nbd_get_error()
337+
rc = m_nbd_client->get_errno();
338+
lderr(m_cct) << "get_size: " << m_nbd_client->get_error()
287339
<< " (errno = " << rc << ")" << dendl;
288340
on_finish->complete(from_nbd_errno(rc));
289341
return;

src/librbd/migration/NBDStream.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212

1313
struct Context;
1414

15-
struct nbd_handle;
16-
1715
namespace librbd {
1816

1917
struct AsioEngine;
2018
struct ImageCtx;
2119

2220
namespace migration {
2321

22+
template <typename> class NBDClient;
23+
2424
template <typename ImageCtxT>
2525
class NBDStream : public StreamInterface {
2626
public:
@@ -53,7 +53,7 @@ class NBDStream : public StreamInterface {
5353
json_spirit::mObject m_json_object;
5454
boost::asio::strand<boost::asio::io_context::executor_type> m_strand;
5555

56-
struct nbd_handle* m_nbd = nullptr;
56+
std::unique_ptr<NBDClient<ImageCtxT>> m_nbd_client;
5757

5858
struct ReadRequest;
5959
struct ListSparseExtentsRequest;

0 commit comments

Comments
 (0)