]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/librbd.cc
db07e5e2275bb9138de81ac95e71a09aeb722c46
[ceph.git] / ceph / src / librbd / librbd.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14 #include "include/int_types.h"
15
16 #include <errno.h>
17
18 #include "cls/rbd/cls_rbd_types.h"
19 #include "common/dout.h"
20 #include "common/errno.h"
21 #include "common/TracepointProvider.h"
22 #include "include/Context.h"
23
24 #include "cls/rbd/cls_rbd_client.h"
25 #include "cls/rbd/cls_rbd_types.h"
26 #include "librbd/ImageCtx.h"
27 #include "librbd/ImageState.h"
28 #include "librbd/internal.h"
29 #include "librbd/Operations.h"
30 #include "librbd/api/DiffIterate.h"
31 #include "librbd/api/Mirror.h"
32 #include "librbd/io/AioCompletion.h"
33 #include "librbd/io/ImageRequestWQ.h"
34 #include "librbd/io/ReadResult.h"
35 #include <algorithm>
36 #include <string>
37 #include <vector>
38
39 #ifdef WITH_LTTNG
40 #define TRACEPOINT_DEFINE
41 #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
42 #include "tracing/librbd.h"
43 #undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
44 #undef TRACEPOINT_DEFINE
45 #else
46 #define tracepoint(...)
47 #endif
48
49 #define dout_subsys ceph_subsys_rbd
50 #undef dout_prefix
51 #define dout_prefix *_dout << "librbd: "
52
53 using std::string;
54 using std::vector;
55
56 using ceph::bufferlist;
57 using librados::snap_t;
58 using librados::IoCtx;
59
60 namespace {
61
62 TracepointProvider::Traits tracepoint_traits("librbd_tp.so", "rbd_tracing");
63
64 buffer::raw* create_write_raw(librbd::ImageCtx *ictx, const char *buf,
65 size_t len) {
66 // TODO: until librados can guarantee memory won't be referenced after
67 // it ACKs a request, always make a copy of the user-provided memory
68 return buffer::copy(buf, len);
69 }
70
71 CephContext* get_cct(IoCtx &io_ctx) {
72 return reinterpret_cast<CephContext*>(io_ctx.cct());
73 }
74
75 librbd::io::AioCompletion* get_aio_completion(librbd::RBD::AioCompletion *comp) {
76 return reinterpret_cast<librbd::io::AioCompletion *>(comp->pc);
77 }
78
79 struct C_AioCompletion : public Context {
80 CephContext *cct;
81 librbd::io::aio_type_t aio_type;
82 librbd::io::AioCompletion* aio_comp;
83
84 C_AioCompletion(librbd::ImageCtx *ictx, librbd::io::aio_type_t aio_type,
85 librbd::io::AioCompletion* aio_comp)
86 : cct(ictx->cct), aio_type(aio_type), aio_comp(aio_comp) {
87 aio_comp->init_time(ictx, aio_type);
88 aio_comp->get();
89 }
90
91 void finish(int r) override {
92 ldout(cct, 20) << "C_AioComplete::finish: r=" << r << dendl;
93 if (r < 0) {
94 aio_comp->fail(r);
95 } else {
96 aio_comp->lock.Lock();
97 aio_comp->complete();
98 aio_comp->put_unlock();
99 }
100 }
101 };
102
103 struct C_OpenComplete : public C_AioCompletion {
104 librbd::ImageCtx *ictx;
105 void **ictxp;
106 C_OpenComplete(librbd::ImageCtx *ictx, librbd::io::AioCompletion* comp,
107 void **ictxp)
108 : C_AioCompletion(ictx, librbd::io::AIO_TYPE_OPEN, comp),
109 ictx(ictx), ictxp(ictxp) {
110 }
111 void finish(int r) override {
112 ldout(ictx->cct, 20) << "C_OpenComplete::finish: r=" << r << dendl;
113 if (r < 0) {
114 *ictxp = nullptr;
115 } else {
116 *ictxp = ictx;
117 }
118
119 C_AioCompletion::finish(r);
120 }
121 };
122
123 struct C_OpenAfterCloseComplete : public Context {
124 librbd::ImageCtx *ictx;
125 librbd::io::AioCompletion* comp;
126 void **ictxp;
127 C_OpenAfterCloseComplete(librbd::ImageCtx *ictx,
128 librbd::io::AioCompletion* comp,
129 void **ictxp)
130 : ictx(ictx), comp(comp), ictxp(ictxp) {
131 }
132 void finish(int r) override {
133 ldout(ictx->cct, 20) << "C_OpenAfterCloseComplete::finish: r=" << r
134 << dendl;
135 delete reinterpret_cast<librbd::ImageCtx*>(*ictxp);
136 *ictxp = nullptr;
137
138 ictx->state->open(false, new C_OpenComplete(ictx, comp, ictxp));
139 }
140 };
141
142 struct C_UpdateWatchCB : public librbd::UpdateWatchCtx {
143 rbd_update_callback_t watch_cb;
144 void *arg;
145 uint64_t handle = 0;
146
147 C_UpdateWatchCB(rbd_update_callback_t watch_cb, void *arg) :
148 watch_cb(watch_cb), arg(arg) {
149 }
150 void handle_notify() override {
151 watch_cb(arg);
152 }
153 };
154
155 void mirror_image_info_cpp_to_c(const librbd::mirror_image_info_t &cpp_info,
156 rbd_mirror_image_info_t *c_info) {
157 c_info->global_id = strdup(cpp_info.global_id.c_str());
158 c_info->state = cpp_info.state;
159 c_info->primary = cpp_info.primary;
160 }
161
162 void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_status,
163 rbd_mirror_image_status_t *c_status) {
164 c_status->name = strdup(cpp_status.name.c_str());
165 mirror_image_info_cpp_to_c(cpp_status.info, &c_status->info);
166 c_status->state = cpp_status.state;
167 c_status->description = strdup(cpp_status.description.c_str());
168 c_status->last_update = cpp_status.last_update;
169 c_status->up = cpp_status.up;
170 }
171
172 void trash_image_info_cpp_to_c(const librbd::trash_image_info_t &cpp_info,
173 rbd_trash_image_info_t *c_info) {
174 c_info->id = strdup(cpp_info.id.c_str());
175 c_info->name = strdup(cpp_info.name.c_str());
176 c_info->source = cpp_info.source;
177 c_info->deletion_time = cpp_info.deletion_time;
178 c_info->deferment_end_time = cpp_info.deferment_end_time;
179 }
180
181 struct C_MirrorImageGetInfo : public Context {
182 rbd_mirror_image_info_t *mirror_image_info;
183 Context *on_finish;
184
185 librbd::mirror_image_info_t cpp_mirror_image_info;
186
187 C_MirrorImageGetInfo(rbd_mirror_image_info_t *mirror_image_info,
188 Context *on_finish)
189 : mirror_image_info(mirror_image_info), on_finish(on_finish) {
190 }
191
192 void finish(int r) override {
193 if (r < 0) {
194 on_finish->complete(r);
195 return;
196 }
197
198 mirror_image_info_cpp_to_c(cpp_mirror_image_info, mirror_image_info);
199 on_finish->complete(0);
200 }
201 };
202
203 struct C_MirrorImageGetStatus : public Context {
204 rbd_mirror_image_status_t *mirror_image_status;
205 Context *on_finish;
206
207 librbd::mirror_image_status_t cpp_mirror_image_status;
208
209 C_MirrorImageGetStatus(rbd_mirror_image_status_t *mirror_image_status,
210 Context *on_finish)
211 : mirror_image_status(mirror_image_status), on_finish(on_finish) {
212 }
213
214 void finish(int r) override {
215 if (r < 0) {
216 on_finish->complete(r);
217 return;
218 }
219
220 mirror_image_status_cpp_to_c(cpp_mirror_image_status, mirror_image_status);
221 on_finish->complete(0);
222 }
223 };
224
225 } // anonymous namespace
226
227 namespace librbd {
228 ProgressContext::~ProgressContext()
229 {
230 }
231
232 class CProgressContext : public ProgressContext
233 {
234 public:
235 CProgressContext(librbd_progress_fn_t fn, void *data)
236 : m_fn(fn), m_data(data)
237 {
238 }
239 int update_progress(uint64_t offset, uint64_t src_size) override
240 {
241 return m_fn(offset, src_size, m_data);
242 }
243 private:
244 librbd_progress_fn_t m_fn;
245 void *m_data;
246 };
247
248 /*
249 RBD
250 */
251 RBD::RBD()
252 {
253 }
254
255 RBD::~RBD()
256 {
257 }
258
259 void RBD::version(int *major, int *minor, int *extra)
260 {
261 rbd_version(major, minor, extra);
262 }
263
264 int RBD::open(IoCtx& io_ctx, Image& image, const char *name)
265 {
266 return open(io_ctx, image, name, NULL);
267 }
268
269 int RBD::open_by_id(IoCtx& io_ctx, Image& image, const char *id)
270 {
271 return open_by_id(io_ctx, image, id, nullptr);
272 }
273
274 int RBD::open(IoCtx& io_ctx, Image& image, const char *name,
275 const char *snap_name)
276 {
277 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
278 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
279 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
280
281 if (image.ctx != NULL) {
282 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
283 image.ctx = NULL;
284 }
285
286 int r = ictx->state->open(false);
287 if (r < 0) {
288 tracepoint(librbd, open_image_exit, r);
289 return r;
290 }
291
292 image.ctx = (image_ctx_t) ictx;
293 tracepoint(librbd, open_image_exit, 0);
294 return 0;
295 }
296
297 int RBD::open_by_id(IoCtx& io_ctx, Image& image, const char *id,
298 const char *snap_name)
299 {
300 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, false);
301 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
302 tracepoint(librbd, open_image_by_id_enter, ictx, ictx->id.c_str(),
303 ictx->snap_name.c_str(), ictx->read_only);
304
305 if (image.ctx != nullptr) {
306 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
307 image.ctx = nullptr;
308 }
309
310 int r = ictx->state->open(false);
311 if (r < 0) {
312 tracepoint(librbd, open_image_by_id_exit, r);
313 return r;
314 }
315
316 image.ctx = (image_ctx_t) ictx;
317 tracepoint(librbd, open_image_by_id_exit, 0);
318 return 0;
319 }
320
321 int RBD::aio_open(IoCtx& io_ctx, Image& image, const char *name,
322 const char *snap_name, RBD::AioCompletion *c)
323 {
324 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
325 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
326 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
327
328 if (image.ctx != NULL) {
329 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
330 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
331 } else {
332 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
333 &image.ctx));
334 }
335 tracepoint(librbd, aio_open_image_exit, 0);
336 return 0;
337 }
338
339 int RBD::aio_open_by_id(IoCtx& io_ctx, Image& image, const char *id,
340 const char *snap_name, RBD::AioCompletion *c)
341 {
342 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, false);
343 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
344 tracepoint(librbd, aio_open_image_by_id_enter, ictx, ictx->id.c_str(),
345 ictx->snap_name.c_str(), ictx->read_only, c->pc);
346
347 if (image.ctx != nullptr) {
348 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
349 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
350 } else {
351 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
352 &image.ctx));
353 }
354 tracepoint(librbd, aio_open_image_by_id_exit, 0);
355 return 0;
356 }
357
358 int RBD::open_read_only(IoCtx& io_ctx, Image& image, const char *name,
359 const char *snap_name)
360 {
361 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, true);
362 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
363 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
364
365 if (image.ctx != NULL) {
366 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
367 image.ctx = NULL;
368 }
369
370 int r = ictx->state->open(false);
371 if (r < 0) {
372 tracepoint(librbd, open_image_exit, r);
373 return r;
374 }
375
376 image.ctx = (image_ctx_t) ictx;
377 tracepoint(librbd, open_image_exit, 0);
378 return 0;
379 }
380
381 int RBD::open_by_id_read_only(IoCtx& io_ctx, Image& image, const char *id,
382 const char *snap_name)
383 {
384 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, true);
385 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
386 tracepoint(librbd, open_image_by_id_enter, ictx, ictx->id.c_str(),
387 ictx->snap_name.c_str(), ictx->read_only);
388
389 if (image.ctx != nullptr) {
390 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
391 image.ctx = nullptr;
392 }
393
394 int r = ictx->state->open(false);
395 if (r < 0) {
396 tracepoint(librbd, open_image_by_id_exit, r);
397 return r;
398 }
399
400 image.ctx = (image_ctx_t) ictx;
401 tracepoint(librbd, open_image_by_id_exit, 0);
402 return 0;
403 }
404
405 int RBD::aio_open_read_only(IoCtx& io_ctx, Image& image, const char *name,
406 const char *snap_name, RBD::AioCompletion *c)
407 {
408 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, true);
409 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
410 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
411
412 if (image.ctx != NULL) {
413 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
414 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
415 } else {
416 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
417 &image.ctx));
418 }
419 tracepoint(librbd, aio_open_image_exit, 0);
420 return 0;
421 }
422
423 int RBD::aio_open_by_id_read_only(IoCtx& io_ctx, Image& image, const char *id,
424 const char *snap_name, RBD::AioCompletion *c)
425 {
426 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, true);
427 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
428 tracepoint(librbd, aio_open_image_by_id_enter, ictx, ictx->id.c_str(),
429 ictx->snap_name.c_str(), ictx->read_only, c->pc);
430
431 if (image.ctx != nullptr) {
432 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
433 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
434 } else {
435 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
436 &image.ctx));
437 }
438 tracepoint(librbd, aio_open_image_by_id_exit, 0);
439 return 0;
440 }
441
442 int RBD::create(IoCtx& io_ctx, const char *name, uint64_t size, int *order)
443 {
444 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
445 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
446 int r = librbd::create(io_ctx, name, size, order);
447 tracepoint(librbd, create_exit, r, *order);
448 return r;
449 }
450
451 int RBD::create2(IoCtx& io_ctx, const char *name, uint64_t size,
452 uint64_t features, int *order)
453 {
454 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
455 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
456 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
457 tracepoint(librbd, create2_exit, r, *order);
458 return r;
459 }
460
461 int RBD::create3(IoCtx& io_ctx, const char *name, uint64_t size,
462 uint64_t features, int *order, uint64_t stripe_unit,
463 uint64_t stripe_count)
464 {
465 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
466 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
467 int r = librbd::create(io_ctx, name, size, false, features, order,
468 stripe_unit, stripe_count);
469 tracepoint(librbd, create3_exit, r, *order);
470 return r;
471 }
472
473 int RBD::create4(IoCtx& io_ctx, const char *name, uint64_t size,
474 ImageOptions& opts)
475 {
476 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
477 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts.opts);
478 int r = librbd::create(io_ctx, name, "", size, opts, "", "", false);
479 tracepoint(librbd, create4_exit, r);
480 return r;
481 }
482
483 int RBD::clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
484 IoCtx& c_ioctx, const char *c_name, uint64_t features,
485 int *c_order)
486 {
487 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
488 tracepoint(librbd, clone_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, features);
489 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
490 features, c_order, 0, 0);
491 tracepoint(librbd, clone_exit, r, *c_order);
492 return r;
493 }
494
495 int RBD::clone2(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
496 IoCtx& c_ioctx, const char *c_name, uint64_t features,
497 int *c_order, uint64_t stripe_unit, int stripe_count)
498 {
499 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
500 tracepoint(librbd, clone2_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, features, stripe_unit, stripe_count);
501 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
502 features, c_order, stripe_unit, stripe_count);
503 tracepoint(librbd, clone2_exit, r, *c_order);
504 return r;
505 }
506
507 int RBD::clone3(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
508 IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts)
509 {
510 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
511 tracepoint(librbd, clone3_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, c_opts.opts);
512 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
513 c_opts);
514 tracepoint(librbd, clone3_exit, r);
515 return r;
516 }
517
518 int RBD::remove(IoCtx& io_ctx, const char *name)
519 {
520 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
521 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
522 librbd::NoOpProgressContext prog_ctx;
523 int r = librbd::remove(io_ctx, name, "", prog_ctx);
524 tracepoint(librbd, remove_exit, r);
525 return r;
526 }
527
528 int RBD::remove_with_progress(IoCtx& io_ctx, const char *name,
529 ProgressContext& pctx)
530 {
531 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
532 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
533 int r = librbd::remove(io_ctx, name, "", pctx);
534 tracepoint(librbd, remove_exit, r);
535 return r;
536 }
537
538 int RBD::trash_move(IoCtx &io_ctx, const char *name, uint64_t delay) {
539 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
540 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
541 io_ctx.get_id(), name);
542 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name,
543 delay);
544 tracepoint(librbd, trash_move_exit, r);
545 return r;
546 }
547
548 int RBD::trash_get(IoCtx &io_ctx, const char *id, trash_image_info_t *info) {
549 return librbd::trash_get(io_ctx, id, info);
550 }
551
552 int RBD::trash_list(IoCtx &io_ctx, vector<trash_image_info_t> &entries) {
553 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
554 tracepoint(librbd, trash_list_enter,
555 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
556 int r = librbd::trash_list(io_ctx, entries);
557 #ifdef WITH_LTTNG
558 if (r >= 0) {
559 for (const auto& entry : entries) {
560 tracepoint(librbd, trash_list_entry, entry.id.c_str());
561 }
562 }
563 #endif
564 tracepoint(librbd, trash_list_exit, r, r);
565 return r;
566 }
567
568 int RBD::trash_remove(IoCtx &io_ctx, const char *image_id, bool force) {
569 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
570 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
571 io_ctx.get_id(), image_id, force);
572 librbd::NoOpProgressContext prog_ctx;
573 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
574 tracepoint(librbd, trash_remove_exit, r);
575 return r;
576 }
577
578 int RBD::trash_remove_with_progress(IoCtx &io_ctx, const char *image_id,
579 bool force, ProgressContext &pctx) {
580 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
581 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
582 io_ctx.get_id(), image_id, force);
583 int r = librbd::trash_remove(io_ctx, image_id, force, pctx);
584 tracepoint(librbd, trash_remove_exit, r);
585 return r;
586 }
587
588 int RBD::trash_restore(IoCtx &io_ctx, const char *id, const char *name) {
589 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
590 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
591 io_ctx.get_id(), id, name);
592 int r = librbd::trash_restore(io_ctx, id, name);
593 tracepoint(librbd, trash_undelete_exit, r);
594 return r;
595 }
596
597 int RBD::list(IoCtx& io_ctx, vector<string>& names)
598 {
599 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
600 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
601 int r = librbd::list(io_ctx, names);
602 if (r >= 0) {
603 for (vector<string>::iterator itr = names.begin(), end = names.end(); itr != end; ++itr) {
604 tracepoint(librbd, list_entry, itr->c_str());
605 }
606 }
607 tracepoint(librbd, list_exit, r, r);
608 return r;
609 }
610
611 int RBD::rename(IoCtx& src_io_ctx, const char *srcname, const char *destname)
612 {
613 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
614 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
615 int r = librbd::rename(src_io_ctx, srcname, destname);
616 tracepoint(librbd, rename_exit, r);
617 return r;
618 }
619
620 int RBD::mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) {
621 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
622 }
623
624 int RBD::mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) {
625 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
626 }
627
628 int RBD::mirror_peer_add(IoCtx& io_ctx, std::string *uuid,
629 const std::string &cluster_name,
630 const std::string &client_name) {
631 return librbd::api::Mirror<>::peer_add(io_ctx, uuid, cluster_name,
632 client_name);
633 }
634
635 int RBD::mirror_peer_remove(IoCtx& io_ctx, const std::string &uuid) {
636 return librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
637 }
638
639 int RBD::mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers) {
640 return librbd::api::Mirror<>::peer_list(io_ctx, peers);
641 }
642
643 int RBD::mirror_peer_set_client(IoCtx& io_ctx, const std::string &uuid,
644 const std::string &client_name) {
645 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
646 }
647
648 int RBD::mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
649 const std::string &cluster_name) {
650 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
651 }
652
653 int RBD::mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
654 size_t max, std::map<std::string, mirror_image_status_t> *images) {
655 return librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
656 images);
657 }
658
659 int RBD::mirror_image_status_summary(IoCtx& io_ctx,
660 std::map<mirror_image_status_state_t, int> *states) {
661 return librbd::api::Mirror<>::image_status_summary(io_ctx, states);
662 }
663
664 RBD::AioCompletion::AioCompletion(void *cb_arg, callback_t complete_cb)
665 {
666 pc = reinterpret_cast<void*>(librbd::io::AioCompletion::create(
667 cb_arg, complete_cb, this));
668 }
669
670 bool RBD::AioCompletion::is_complete()
671 {
672 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
673 return c->is_complete();
674 }
675
676 int RBD::AioCompletion::wait_for_complete()
677 {
678 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
679 return c->wait_for_complete();
680 }
681
682 ssize_t RBD::AioCompletion::get_return_value()
683 {
684 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
685 return c->get_return_value();
686 }
687
688 void *RBD::AioCompletion::get_arg()
689 {
690 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
691 return c->get_arg();
692 }
693
694 void RBD::AioCompletion::release()
695 {
696 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
697 c->release();
698 delete this;
699 }
700
701 /*
702 ImageOptions
703 */
704
705 ImageOptions::ImageOptions()
706 {
707 librbd::image_options_create(&opts);
708 }
709
710 ImageOptions::ImageOptions(rbd_image_options_t opts_)
711 {
712 librbd::image_options_create_ref(&opts, opts_);
713 }
714
715 ImageOptions::ImageOptions(const ImageOptions &imgopts)
716 {
717 librbd::image_options_copy(&opts, imgopts);
718 }
719
720 ImageOptions::~ImageOptions()
721 {
722 librbd::image_options_destroy(opts);
723 }
724
725 int ImageOptions::set(int optname, const std::string& optval)
726 {
727 return librbd::image_options_set(opts, optname, optval);
728 }
729
730 int ImageOptions::set(int optname, uint64_t optval)
731 {
732 return librbd::image_options_set(opts, optname, optval);
733 }
734
735 int ImageOptions::get(int optname, std::string* optval) const
736 {
737 return librbd::image_options_get(opts, optname, optval);
738 }
739
740 int ImageOptions::get(int optname, uint64_t* optval) const
741 {
742 return librbd::image_options_get(opts, optname, optval);
743 }
744
745 int ImageOptions::is_set(int optname, bool* is_set)
746 {
747 return librbd::image_options_is_set(opts, optname, is_set);
748 }
749
750 int ImageOptions::unset(int optname)
751 {
752 return librbd::image_options_unset(opts, optname);
753 }
754
755 void ImageOptions::clear()
756 {
757 librbd::image_options_clear(opts);
758 }
759
760 bool ImageOptions::empty() const
761 {
762 return librbd::image_options_is_empty(opts);
763 }
764
765 /*
766 Image
767 */
768
769 Image::Image() : ctx(NULL)
770 {
771 }
772
773 Image::~Image()
774 {
775 close();
776 }
777
778 int Image::close()
779 {
780 int r = 0;
781 if (ctx) {
782 ImageCtx *ictx = (ImageCtx *)ctx;
783 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
784
785 r = ictx->state->close();
786 ctx = NULL;
787
788 tracepoint(librbd, close_image_exit, r);
789 }
790 return r;
791 }
792
793 int Image::aio_close(RBD::AioCompletion *c)
794 {
795 if (!ctx) {
796 return -EINVAL;
797 }
798
799 ImageCtx *ictx = (ImageCtx *)ctx;
800 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), c->pc);
801
802 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
803 get_aio_completion(c)));
804 ctx = NULL;
805
806 tracepoint(librbd, aio_close_image_exit, 0);
807 return 0;
808 }
809
810 int Image::resize(uint64_t size)
811 {
812 ImageCtx *ictx = (ImageCtx *)ctx;
813 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
814 librbd::NoOpProgressContext prog_ctx;
815 int r = ictx->operations->resize(size, true, prog_ctx);
816 tracepoint(librbd, resize_exit, r);
817 return r;
818 }
819
820 int Image::resize2(uint64_t size, bool allow_shrink, librbd::ProgressContext& pctx)
821 {
822 ImageCtx *ictx = (ImageCtx *)ctx;
823 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
824 int r = ictx->operations->resize(size, allow_shrink, pctx);
825 tracepoint(librbd, resize_exit, r);
826 return r;
827 }
828
829 int Image::resize_with_progress(uint64_t size, librbd::ProgressContext& pctx)
830 {
831 ImageCtx *ictx = (ImageCtx *)ctx;
832 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
833 int r = ictx->operations->resize(size, true, pctx);
834 tracepoint(librbd, resize_exit, r);
835 return r;
836 }
837
838 int Image::stat(image_info_t& info, size_t infosize)
839 {
840 ImageCtx *ictx = (ImageCtx *)ctx;
841 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
842 int r = librbd::info(ictx, info, infosize);
843 tracepoint(librbd, stat_exit, r, &info);
844 return r;
845 }
846
847 int Image::old_format(uint8_t *old)
848 {
849 ImageCtx *ictx = (ImageCtx *)ctx;
850 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
851 int r = librbd::get_old_format(ictx, old);
852 tracepoint(librbd, get_old_format_exit, r, *old);
853 return r;
854 }
855
856 int Image::size(uint64_t *size)
857 {
858 ImageCtx *ictx = (ImageCtx *)ctx;
859 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
860 int r = librbd::get_size(ictx, size);
861 tracepoint(librbd, get_size_exit, r, *size);
862 return r;
863 }
864
865 int Image::features(uint64_t *features)
866 {
867 ImageCtx *ictx = (ImageCtx *)ctx;
868 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
869 int r = librbd::get_features(ictx, features);
870 tracepoint(librbd, get_features_exit, r, *features);
871 return r;
872 }
873
874 int Image::update_features(uint64_t features, bool enabled)
875 {
876 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
877 tracepoint(librbd, update_features_enter, ictx, features, enabled);
878 int r = ictx->operations->update_features(features, enabled);
879 tracepoint(librbd, update_features_exit, r);
880 return r;
881 }
882
883 uint64_t Image::get_stripe_unit() const
884 {
885 ImageCtx *ictx = (ImageCtx *)ctx;
886 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
887 uint64_t stripe_unit = ictx->get_stripe_unit();
888 tracepoint(librbd, get_stripe_unit_exit, 0, stripe_unit);
889 return stripe_unit;
890 }
891
892 uint64_t Image::get_stripe_count() const
893 {
894 ImageCtx *ictx = (ImageCtx *)ctx;
895 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
896 uint64_t stripe_count = ictx->get_stripe_count();
897 tracepoint(librbd, get_stripe_count_exit, 0, stripe_count);
898 return stripe_count;
899 }
900
901 int Image::get_create_timestamp(struct timespec *timestamp)
902 {
903 ImageCtx *ictx = (ImageCtx *)ctx;
904 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
905 ictx->read_only);
906 utime_t time = ictx->get_create_timestamp();
907 time.to_timespec(timestamp);
908 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
909 return 0;
910 }
911
912 int Image::overlap(uint64_t *overlap)
913 {
914 ImageCtx *ictx = (ImageCtx *)ctx;
915 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
916 int r = librbd::get_overlap(ictx, overlap);
917 tracepoint(librbd, get_overlap_exit, r, *overlap);
918 return r;
919 }
920
921 int Image::get_id(std::string *id)
922 {
923 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
924 if (ictx->old_format) {
925 return -EINVAL;
926 }
927 *id = ictx->id;
928 return 0;
929 }
930
931 std::string Image::get_block_name_prefix()
932 {
933 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
934 return ictx->object_prefix;
935 }
936
937 int64_t Image::get_data_pool_id()
938 {
939 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
940 return ictx->data_ctx.get_id();
941 }
942
943 int Image::parent_info(string *parent_pool_name, string *parent_name,
944 string *parent_snap_name)
945 {
946 return parent_info2(parent_pool_name, parent_name, nullptr,
947 parent_snap_name);
948 }
949
950 int Image::parent_info2(string *parent_pool_name, string *parent_name,
951 string *parent_id, string *parent_snap_name)
952 {
953 ImageCtx *ictx = (ImageCtx *)ctx;
954 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
955 ictx->snap_name.c_str(), ictx->read_only);
956 int r = librbd::get_parent_info(ictx, parent_pool_name, parent_name,
957 parent_id, parent_snap_name);
958 tracepoint(librbd, get_parent_info_exit, r,
959 parent_pool_name ? parent_pool_name->c_str() : NULL,
960 parent_name ? parent_name->c_str() : NULL,
961 parent_id ? parent_id->c_str() : NULL,
962 parent_snap_name ? parent_snap_name->c_str() : NULL);
963 return r;
964 }
965
966 int Image::get_flags(uint64_t *flags)
967 {
968 ImageCtx *ictx = (ImageCtx *)ctx;
969 tracepoint(librbd, get_flags_enter, ictx);
970 int r = librbd::get_flags(ictx, flags);
971 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
972 return r;
973 }
974
975 int Image::set_image_notification(int fd, int type)
976 {
977 ImageCtx *ictx = (ImageCtx *)ctx;
978 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
979 int r = librbd::set_image_notification(ictx, fd, type);
980 tracepoint(librbd, set_image_notification_exit, ictx, r);
981 return r;
982 }
983
984 int Image::is_exclusive_lock_owner(bool *is_owner)
985 {
986 ImageCtx *ictx = (ImageCtx *)ctx;
987 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
988 int r = librbd::is_exclusive_lock_owner(ictx, is_owner);
989 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
990 return r;
991 }
992
993 int Image::lock_acquire(rbd_lock_mode_t lock_mode)
994 {
995 ImageCtx *ictx = (ImageCtx *)ctx;
996 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
997 int r = librbd::lock_acquire(ictx, lock_mode);
998 tracepoint(librbd, lock_acquire_exit, ictx, r);
999 return r;
1000 }
1001
1002 int Image::lock_release()
1003 {
1004 ImageCtx *ictx = (ImageCtx *)ctx;
1005 tracepoint(librbd, lock_release_enter, ictx);
1006 int r = librbd::lock_release(ictx);
1007 tracepoint(librbd, lock_release_exit, ictx, r);
1008 return r;
1009 }
1010
1011 int Image::lock_get_owners(rbd_lock_mode_t *lock_mode,
1012 std::list<std::string> *lock_owners)
1013 {
1014 ImageCtx *ictx = (ImageCtx *)ctx;
1015 tracepoint(librbd, lock_get_owners_enter, ictx);
1016 int r = librbd::lock_get_owners(ictx, lock_mode, lock_owners);
1017 tracepoint(librbd, lock_get_owners_exit, ictx, r);
1018 return r;
1019 }
1020
1021 int Image::lock_break(rbd_lock_mode_t lock_mode,
1022 const std::string &lock_owner)
1023 {
1024 ImageCtx *ictx = (ImageCtx *)ctx;
1025 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner.c_str());
1026 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
1027 tracepoint(librbd, lock_break_exit, ictx, r);
1028 return r;
1029 }
1030
1031 int Image::rebuild_object_map(ProgressContext &prog_ctx)
1032 {
1033 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1034 return ictx->operations->rebuild_object_map(prog_ctx);
1035 }
1036
1037 int Image::check_object_map(ProgressContext &prog_ctx)
1038 {
1039 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1040 return ictx->operations->check_object_map(prog_ctx);
1041 }
1042
1043 int Image::copy(IoCtx& dest_io_ctx, const char *destname)
1044 {
1045 ImageCtx *ictx = (ImageCtx *)ctx;
1046 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
1047 ImageOptions opts;
1048 librbd::NoOpProgressContext prog_ctx;
1049 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1050 tracepoint(librbd, copy_exit, r);
1051 return r;
1052 }
1053
1054 int Image::copy2(Image& dest)
1055 {
1056 ImageCtx *srcctx = (ImageCtx *)ctx;
1057 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1058 tracepoint(librbd, copy2_enter, srcctx, srcctx->name.c_str(), srcctx->snap_name.c_str(), srcctx->read_only, destctx, destctx->name.c_str(), destctx->snap_name.c_str(), destctx->read_only);
1059 librbd::NoOpProgressContext prog_ctx;
1060 int r = librbd::copy(srcctx, destctx, prog_ctx, 0);
1061 tracepoint(librbd, copy2_exit, r);
1062 return r;
1063 }
1064
1065 int Image::copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts)
1066 {
1067 ImageCtx *ictx = (ImageCtx *)ctx;
1068 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
1069 librbd::NoOpProgressContext prog_ctx;
1070 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1071 tracepoint(librbd, copy3_exit, r);
1072 return r;
1073 }
1074
1075 int Image::copy4(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts, size_t sparse_size)
1076 {
1077 ImageCtx *ictx = (ImageCtx *)ctx;
1078 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts, sparse_size);
1079 librbd::NoOpProgressContext prog_ctx;
1080 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, sparse_size);
1081 tracepoint(librbd, copy4_exit, r);
1082 return r;
1083 }
1084
1085 int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
1086 librbd::ProgressContext &pctx)
1087 {
1088 ImageCtx *ictx = (ImageCtx *)ctx;
1089 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
1090 ImageOptions opts;
1091 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1092 tracepoint(librbd, copy_exit, r);
1093 return r;
1094 }
1095
1096 int Image::copy_with_progress2(Image& dest, librbd::ProgressContext &pctx)
1097 {
1098 ImageCtx *srcctx = (ImageCtx *)ctx;
1099 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1100 tracepoint(librbd, copy2_enter, srcctx, srcctx->name.c_str(), srcctx->snap_name.c_str(), srcctx->read_only, destctx, destctx->name.c_str(), destctx->snap_name.c_str(), destctx->read_only);
1101 int r = librbd::copy(srcctx, destctx, pctx, 0);
1102 tracepoint(librbd, copy2_exit, r);
1103 return r;
1104 }
1105
1106 int Image::copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
1107 ImageOptions& opts,
1108 librbd::ProgressContext &pctx)
1109 {
1110 ImageCtx *ictx = (ImageCtx *)ctx;
1111 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
1112 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1113 tracepoint(librbd, copy3_exit, r);
1114 return r;
1115 }
1116
1117 int Image::copy_with_progress4(IoCtx& dest_io_ctx, const char *destname,
1118 ImageOptions& opts,
1119 librbd::ProgressContext &pctx,
1120 size_t sparse_size)
1121 {
1122 ImageCtx *ictx = (ImageCtx *)ctx;
1123 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts, sparse_size);
1124 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, sparse_size);
1125 tracepoint(librbd, copy4_exit, r);
1126 return r;
1127 }
1128
1129 int Image::flatten()
1130 {
1131 ImageCtx *ictx = (ImageCtx *)ctx;
1132 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1133 librbd::NoOpProgressContext prog_ctx;
1134 int r = ictx->operations->flatten(prog_ctx);
1135 tracepoint(librbd, flatten_exit, r);
1136 return r;
1137 }
1138
1139 int Image::flatten_with_progress(librbd::ProgressContext& prog_ctx)
1140 {
1141 ImageCtx *ictx = (ImageCtx *)ctx;
1142 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1143 int r = ictx->operations->flatten(prog_ctx);
1144 tracepoint(librbd, flatten_exit, r);
1145 return r;
1146 }
1147
1148 int Image::list_children(set<pair<string, string> > *children)
1149 {
1150 ImageCtx *ictx = (ImageCtx *)ctx;
1151 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1152 int r = librbd::list_children(ictx, *children);
1153 if (r >= 0) {
1154 for (set<pair<string, string> >::const_iterator it = children->begin();
1155 it != children->end(); ++it) {
1156 tracepoint(librbd, list_children_entry, it->first.c_str(), it->second.c_str());
1157 }
1158 }
1159 tracepoint(librbd, list_children_exit, r);
1160 return r;
1161 }
1162
1163 int Image::list_lockers(std::list<librbd::locker_t> *lockers,
1164 bool *exclusive, string *tag)
1165 {
1166 ImageCtx *ictx = (ImageCtx *)ctx;
1167 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1168 int r = librbd::list_lockers(ictx, lockers, exclusive, tag);
1169 if (r >= 0) {
1170 for (std::list<librbd::locker_t>::const_iterator it = lockers->begin();
1171 it != lockers->end(); ++it) {
1172 tracepoint(librbd, list_lockers_entry, it->client.c_str(), it->cookie.c_str(), it->address.c_str());
1173 }
1174 }
1175 tracepoint(librbd, list_lockers_exit, r);
1176 return r;
1177 }
1178
1179 int Image::lock_exclusive(const string& cookie)
1180 {
1181 ImageCtx *ictx = (ImageCtx *)ctx;
1182 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1183 int r = librbd::lock(ictx, true, cookie, "");
1184 tracepoint(librbd, lock_exclusive_exit, r);
1185 return r;
1186 }
1187
1188 int Image::lock_shared(const string& cookie, const std::string& tag)
1189 {
1190 ImageCtx *ictx = (ImageCtx *)ctx;
1191 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str(), tag.c_str());
1192 int r = librbd::lock(ictx, false, cookie, tag);
1193 tracepoint(librbd, lock_shared_exit, r);
1194 return r;
1195 }
1196
1197 int Image::unlock(const string& cookie)
1198 {
1199 ImageCtx *ictx = (ImageCtx *)ctx;
1200 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1201 int r = librbd::unlock(ictx, cookie);
1202 tracepoint(librbd, unlock_exit, r);
1203 return r;
1204 }
1205
1206 int Image::break_lock(const string& client, const string& cookie)
1207 {
1208 ImageCtx *ictx = (ImageCtx *)ctx;
1209 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client.c_str(), cookie.c_str());
1210 int r = librbd::break_lock(ictx, client, cookie);
1211 tracepoint(librbd, break_lock_exit, r);
1212 return r;
1213 }
1214
1215 int Image::snap_create(const char *snap_name)
1216 {
1217 ImageCtx *ictx = (ImageCtx *)ctx;
1218 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1219 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
1220 snap_name);
1221 tracepoint(librbd, snap_create_exit, r);
1222 return r;
1223 }
1224
1225 int Image::snap_remove(const char *snap_name)
1226 {
1227 ImageCtx *ictx = (ImageCtx *)ctx;
1228 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1229 librbd::NoOpProgressContext prog_ctx;
1230 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
1231 tracepoint(librbd, snap_remove_exit, r);
1232 return r;
1233 }
1234
1235 int Image::snap_remove2(const char *snap_name, uint32_t flags, ProgressContext& pctx)
1236 {
1237 ImageCtx *ictx = (ImageCtx *)ctx;
1238 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
1239 int r = librbd::snap_remove(ictx, snap_name, flags, pctx);
1240 tracepoint(librbd, snap_remove_exit, r);
1241 return r;
1242 }
1243
1244 int Image::snap_rollback(const char *snap_name)
1245 {
1246 ImageCtx *ictx = (ImageCtx *)ctx;
1247 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1248 librbd::NoOpProgressContext prog_ctx;
1249 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1250 tracepoint(librbd, snap_rollback_exit, r);
1251 return r;
1252 }
1253
1254 int Image::snap_rename(const char *srcname, const char *dstname)
1255 {
1256 ImageCtx *ictx = (ImageCtx *)ctx;
1257 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
1258 int r = ictx->operations->snap_rename(srcname, dstname);
1259 tracepoint(librbd, snap_rename_exit, r);
1260 return r;
1261 }
1262
1263 int Image::snap_rollback_with_progress(const char *snap_name,
1264 ProgressContext& prog_ctx)
1265 {
1266 ImageCtx *ictx = (ImageCtx *)ctx;
1267 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1268 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1269 tracepoint(librbd, snap_rollback_exit, r);
1270 return r;
1271 }
1272
1273 int Image::snap_protect(const char *snap_name)
1274 {
1275 ImageCtx *ictx = (ImageCtx *)ctx;
1276 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1277 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
1278 tracepoint(librbd, snap_protect_exit, r);
1279 return r;
1280 }
1281
1282 int Image::snap_unprotect(const char *snap_name)
1283 {
1284 ImageCtx *ictx = (ImageCtx *)ctx;
1285 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1286 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
1287 tracepoint(librbd, snap_unprotect_exit, r);
1288 return r;
1289 }
1290
1291 int Image::snap_is_protected(const char *snap_name, bool *is_protected)
1292 {
1293 ImageCtx *ictx = (ImageCtx *)ctx;
1294 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1295 int r = librbd::snap_is_protected(ictx, snap_name, is_protected);
1296 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
1297 return r;
1298 }
1299
1300 int Image::snap_list(vector<librbd::snap_info_t>& snaps)
1301 {
1302 ImageCtx *ictx = (ImageCtx *)ctx;
1303 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, &snaps);
1304 int r = librbd::snap_list(ictx, snaps);
1305 if (r >= 0) {
1306 for (int i = 0, n = snaps.size(); i < n; i++) {
1307 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name.c_str());
1308 }
1309 }
1310 tracepoint(librbd, snap_list_exit, r, snaps.size());
1311 if (r >= 0) {
1312 // A little ugly, but the C++ API doesn't need a Image::snap_list_end,
1313 // and we want the tracepoints to mirror the C API
1314 tracepoint(librbd, snap_list_end_enter, &snaps);
1315 tracepoint(librbd, snap_list_end_exit);
1316 }
1317 return r;
1318 }
1319
1320 bool Image::snap_exists(const char *snap_name)
1321 {
1322 ImageCtx *ictx = (ImageCtx *)ctx;
1323 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
1324 ictx->snap_name.c_str(), ictx->read_only, snap_name);
1325 bool exists;
1326 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, &exists);
1327 tracepoint(librbd, snap_exists_exit, r, exists);
1328 if (r < 0) {
1329 // lie to caller since we don't know the real answer yet.
1330 return false;
1331 }
1332 return exists;
1333 }
1334
1335 // A safer verion of snap_exists.
1336 int Image::snap_exists2(const char *snap_name, bool *exists)
1337 {
1338 ImageCtx *ictx = (ImageCtx *)ctx;
1339 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
1340 ictx->snap_name.c_str(), ictx->read_only, snap_name);
1341 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, exists);
1342 tracepoint(librbd, snap_exists_exit, r, *exists);
1343 return r;
1344 }
1345
1346 int Image::snap_get_timestamp(uint64_t snap_id, struct timespec *timestamp)
1347 {
1348 ImageCtx *ictx = (ImageCtx *)ctx;
1349 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
1350 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
1351 tracepoint(librbd, snap_get_timestamp_exit, r);
1352 return r;
1353 }
1354
1355 int Image::snap_get_limit(uint64_t *limit)
1356 {
1357 ImageCtx *ictx = (ImageCtx *)ctx;
1358 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
1359 int r = librbd::snap_get_limit(ictx, limit);
1360 tracepoint(librbd, snap_get_limit_exit, r, *limit);
1361 return r;
1362 }
1363
1364 int Image::snap_set_limit(uint64_t limit)
1365 {
1366 ImageCtx *ictx = (ImageCtx *)ctx;
1367
1368 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
1369 int r = ictx->operations->snap_set_limit(limit);
1370 tracepoint(librbd, snap_set_limit_exit, r);
1371 return r;
1372 }
1373
1374 int Image::snap_set(const char *snap_name)
1375 {
1376 ImageCtx *ictx = (ImageCtx *)ctx;
1377 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1378 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
1379 tracepoint(librbd, snap_set_exit, r);
1380 return r;
1381 }
1382
1383 ssize_t Image::read(uint64_t ofs, size_t len, bufferlist& bl)
1384 {
1385 ImageCtx *ictx = (ImageCtx *)ctx;
1386 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1387 bufferptr ptr(len);
1388 bl.push_back(std::move(ptr));
1389 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, 0);
1390 tracepoint(librbd, read_exit, r);
1391 return r;
1392 }
1393
1394 ssize_t Image::read2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1395 {
1396 ImageCtx *ictx = (ImageCtx *)ctx;
1397 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1398 ictx->read_only, ofs, len, op_flags);
1399 bufferptr ptr(len);
1400 bl.push_back(std::move(ptr));
1401 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, op_flags);
1402 tracepoint(librbd, read_exit, r);
1403 return r;
1404 }
1405
1406 int64_t Image::read_iterate(uint64_t ofs, size_t len,
1407 int (*cb)(uint64_t, size_t, const char *, void *),
1408 void *arg)
1409 {
1410 ImageCtx *ictx = (ImageCtx *)ctx;
1411 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1412 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
1413 tracepoint(librbd, read_iterate_exit, r);
1414 return r;
1415 }
1416
1417 int Image::read_iterate2(uint64_t ofs, uint64_t len,
1418 int (*cb)(uint64_t, size_t, const char *, void *),
1419 void *arg)
1420 {
1421 ImageCtx *ictx = (ImageCtx *)ctx;
1422 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1423 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
1424 if (r > 0)
1425 r = 0;
1426 tracepoint(librbd, read_iterate2_exit, r);
1427 return (int)r;
1428 }
1429
1430 int Image::diff_iterate(const char *fromsnapname,
1431 uint64_t ofs, uint64_t len,
1432 int (*cb)(uint64_t, size_t, int, void *),
1433 void *arg)
1434 {
1435 ImageCtx *ictx = (ImageCtx *)ctx;
1436 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
1437 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
1438 true, false);
1439 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
1440 cls::rbd::UserSnapshotNamespace(),
1441 fromsnapname, ofs,
1442 len, true, false, cb, arg);
1443 tracepoint(librbd, diff_iterate_exit, r);
1444 return r;
1445 }
1446
1447 int Image::diff_iterate2(const char *fromsnapname, uint64_t ofs, uint64_t len,
1448 bool include_parent, bool whole_object,
1449 int (*cb)(uint64_t, size_t, int, void *), void *arg)
1450 {
1451 ImageCtx *ictx = (ImageCtx *)ctx;
1452 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
1453 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
1454 include_parent, whole_object);
1455 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
1456 cls::rbd::UserSnapshotNamespace(),
1457 fromsnapname, ofs,
1458 len, include_parent,
1459 whole_object, cb, arg);
1460 tracepoint(librbd, diff_iterate_exit, r);
1461 return r;
1462 }
1463
1464 ssize_t Image::write(uint64_t ofs, size_t len, bufferlist& bl)
1465 {
1466 ImageCtx *ictx = (ImageCtx *)ctx;
1467 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, bl.length() < len ? NULL : bl.c_str());
1468 if (bl.length() < len) {
1469 tracepoint(librbd, write_exit, -EINVAL);
1470 return -EINVAL;
1471 }
1472 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, 0);
1473 tracepoint(librbd, write_exit, r);
1474 return r;
1475 }
1476
1477 ssize_t Image::write2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1478 {
1479 ImageCtx *ictx = (ImageCtx *)ctx;
1480 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only,
1481 ofs, len, bl.length() < len ? NULL : bl.c_str(), op_flags);
1482 if (bl.length() < len) {
1483 tracepoint(librbd, write_exit, -EINVAL);
1484 return -EINVAL;
1485 }
1486 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, op_flags);
1487 tracepoint(librbd, write_exit, r);
1488 return r;
1489 }
1490
1491 int Image::discard(uint64_t ofs, uint64_t len)
1492 {
1493 ImageCtx *ictx = (ImageCtx *)ctx;
1494 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1495 if (len > std::numeric_limits<int32_t>::max()) {
1496 tracepoint(librbd, discard_exit, -EINVAL);
1497 return -EINVAL;
1498 }
1499 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
1500 tracepoint(librbd, discard_exit, r);
1501 return r;
1502 }
1503
1504 ssize_t Image::writesame(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1505 {
1506 ImageCtx *ictx = (ImageCtx *)ctx;
1507 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1508 ictx->read_only, ofs, len, bl.length() <= 0 ? NULL : bl.c_str(), bl.length(),
1509 op_flags);
1510 if (bl.length() <= 0 || len % bl.length() ||
1511 len > std::numeric_limits<int>::max()) {
1512 tracepoint(librbd, writesame_exit, -EINVAL);
1513 return -EINVAL;
1514 }
1515
1516 if (mem_is_zero(bl.c_str(), bl.length())) {
1517 int r = ictx->io_work_queue->discard(ofs, len, false);
1518 tracepoint(librbd, writesame_exit, r);
1519 return r;
1520 }
1521
1522 int r = ictx->io_work_queue->writesame(ofs, len, bufferlist{bl}, op_flags);
1523 tracepoint(librbd, writesame_exit, r);
1524 return r;
1525 }
1526
1527 ssize_t Image::compare_and_write(uint64_t ofs, size_t len,
1528 ceph::bufferlist &cmp_bl, ceph::bufferlist& bl,
1529 uint64_t *mismatch_off, int op_flags)
1530 {
1531 ImageCtx *ictx = (ImageCtx *)ctx;
1532 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
1533 ictx->snap_name.c_str(),
1534 ictx->read_only, ofs, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
1535 bl.length() < len ? NULL : bl.c_str(), op_flags);
1536
1537 if (bl.length() < len) {
1538 tracepoint(librbd, write_exit, -EINVAL);
1539 return -EINVAL;
1540 }
1541
1542 int r = ictx->io_work_queue->compare_and_write(ofs, len, bufferlist{cmp_bl},
1543 bufferlist{bl}, mismatch_off,
1544 op_flags);
1545
1546 tracepoint(librbd, compare_and_write_exit, r);
1547
1548 return r;
1549 }
1550 int Image::aio_write(uint64_t off, size_t len, bufferlist& bl,
1551 RBD::AioCompletion *c)
1552 {
1553 ImageCtx *ictx = (ImageCtx *)ctx;
1554 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc);
1555 if (bl.length() < len) {
1556 tracepoint(librbd, aio_write_exit, -EINVAL);
1557 return -EINVAL;
1558 }
1559 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1560 bufferlist{bl}, 0);
1561 tracepoint(librbd, aio_write_exit, 0);
1562 return 0;
1563 }
1564
1565 int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
1566 RBD::AioCompletion *c, int op_flags)
1567 {
1568 ImageCtx *ictx = (ImageCtx *)ctx;
1569 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1570 ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1571 if (bl.length() < len) {
1572 tracepoint(librbd, aio_write_exit, -EINVAL);
1573 return -EINVAL;
1574 }
1575 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1576 bufferlist{bl}, op_flags);
1577 tracepoint(librbd, aio_write_exit, 0);
1578 return 0;
1579 }
1580
1581 int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
1582 {
1583 ImageCtx *ictx = (ImageCtx *)ctx;
1584 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
1585 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard);
1586 tracepoint(librbd, aio_discard_exit, 0);
1587 return 0;
1588 }
1589
1590 int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
1591 RBD::AioCompletion *c)
1592 {
1593 ImageCtx *ictx = (ImageCtx *)ctx;
1594 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, bl.c_str(), c->pc);
1595 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1596 << (void *)(bl.c_str() + len - 1) << dendl;
1597 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1598 io::ReadResult{&bl}, 0);
1599 tracepoint(librbd, aio_read_exit, 0);
1600 return 0;
1601 }
1602
1603 int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
1604 RBD::AioCompletion *c, int op_flags)
1605 {
1606 ImageCtx *ictx = (ImageCtx *)ctx;
1607 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1608 ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
1609 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1610 << (void *)(bl.c_str() + len - 1) << dendl;
1611 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1612 io::ReadResult{&bl}, op_flags);
1613 tracepoint(librbd, aio_read_exit, 0);
1614 return 0;
1615 }
1616
1617 int Image::flush()
1618 {
1619 ImageCtx *ictx = (ImageCtx *)ctx;
1620 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1621 int r = librbd::flush(ictx);
1622 tracepoint(librbd, flush_exit, r);
1623 return r;
1624 }
1625
1626 int Image::aio_flush(RBD::AioCompletion *c)
1627 {
1628 ImageCtx *ictx = (ImageCtx *)ctx;
1629 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
1630 ictx->io_work_queue->aio_flush(get_aio_completion(c));
1631 tracepoint(librbd, aio_flush_exit, 0);
1632 return 0;
1633 }
1634
1635 int Image::aio_writesame(uint64_t off, size_t len, bufferlist& bl,
1636 RBD::AioCompletion *c, int op_flags)
1637 {
1638 ImageCtx *ictx = (ImageCtx *)ctx;
1639 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1640 ictx->read_only, off, len, bl.length() <= len ? NULL : bl.c_str(), bl.length(),
1641 c->pc, op_flags);
1642 if (bl.length() <= 0 || len % bl.length()) {
1643 tracepoint(librbd, aio_writesame_exit, -EINVAL);
1644 return -EINVAL;
1645 }
1646
1647 if (mem_is_zero(bl.c_str(), bl.length())) {
1648 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false);
1649 tracepoint(librbd, aio_writesame_exit, 0);
1650 return 0;
1651 }
1652
1653 ictx->io_work_queue->aio_writesame(get_aio_completion(c), off, len,
1654 bufferlist{bl}, op_flags);
1655 tracepoint(librbd, aio_writesame_exit, 0);
1656 return 0;
1657 }
1658
1659 int Image::aio_compare_and_write(uint64_t off, size_t len,
1660 ceph::bufferlist& cmp_bl, ceph::bufferlist& bl,
1661 RBD::AioCompletion *c, uint64_t *mismatch_off,
1662 int op_flags)
1663 {
1664 ImageCtx *ictx = (ImageCtx *)ctx;
1665 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(),
1666 ictx->snap_name.c_str(),
1667 ictx->read_only, off, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
1668 bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1669
1670 if (bl.length() < len) {
1671 tracepoint(librbd, compare_and_write_exit, -EINVAL);
1672 return -EINVAL;
1673 }
1674
1675 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(c), off, len,
1676 bufferlist{cmp_bl}, bufferlist{bl},
1677 mismatch_off, op_flags, false);
1678
1679 tracepoint(librbd, aio_compare_and_write_exit, 0);
1680
1681 return 0;
1682 }
1683
1684 int Image::invalidate_cache()
1685 {
1686 ImageCtx *ictx = (ImageCtx *)ctx;
1687 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1688 int r = librbd::invalidate_cache(ictx);
1689 tracepoint(librbd, invalidate_cache_exit, r);
1690 return r;
1691 }
1692
1693 int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp)
1694 {
1695 io::AioCompletion *cs[numcomp];
1696 ImageCtx *ictx = (ImageCtx *)ctx;
1697 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
1698 int r = librbd::poll_io_events(ictx, cs, numcomp);
1699 tracepoint(librbd, poll_io_events_exit, r);
1700 if (r > 0) {
1701 for (int i = 0; i < numcomp; ++i)
1702 comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
1703 }
1704 return r;
1705 }
1706
1707 int Image::metadata_get(const std::string &key, std::string *value)
1708 {
1709 ImageCtx *ictx = (ImageCtx *)ctx;
1710 tracepoint(librbd, metadata_get_enter, ictx, key.c_str());
1711 int r = librbd::metadata_get(ictx, key, value);
1712 if (r < 0) {
1713 tracepoint(librbd, metadata_get_exit, r, key.c_str(), NULL);
1714 } else {
1715 tracepoint(librbd, metadata_get_exit, r, key.c_str(), value->c_str());
1716 }
1717 return r;
1718 }
1719
1720 int Image::metadata_set(const std::string &key, const std::string &value)
1721 {
1722 ImageCtx *ictx = (ImageCtx *)ctx;
1723 tracepoint(librbd, metadata_set_enter, ictx, key.c_str(), value.c_str());
1724 int r = ictx->operations->metadata_set(key, value);
1725 tracepoint(librbd, metadata_set_exit, r);
1726 return r;
1727 }
1728
1729 int Image::metadata_remove(const std::string &key)
1730 {
1731 ImageCtx *ictx = (ImageCtx *)ctx;
1732 tracepoint(librbd, metadata_remove_enter, ictx, key.c_str());
1733 int r = ictx->operations->metadata_remove(key);
1734 tracepoint(librbd, metadata_remove_exit, r);
1735 return r;
1736 }
1737
1738 int Image::metadata_list(const std::string &start, uint64_t max, map<string, bufferlist> *pairs)
1739 {
1740 ImageCtx *ictx = (ImageCtx *)ctx;
1741 tracepoint(librbd, metadata_list_enter, ictx);
1742 int r = librbd::metadata_list(ictx, start, max, pairs);
1743 if (r >= 0) {
1744 for (map<string, bufferlist>::iterator it = pairs->begin();
1745 it != pairs->end(); ++it) {
1746 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
1747 }
1748 }
1749 tracepoint(librbd, metadata_list_exit, r);
1750 return r;
1751 }
1752
1753 int Image::mirror_image_enable() {
1754 ImageCtx *ictx = (ImageCtx *)ctx;
1755 return librbd::api::Mirror<>::image_enable(ictx, false);
1756 }
1757
1758 int Image::mirror_image_disable(bool force) {
1759 ImageCtx *ictx = (ImageCtx *)ctx;
1760 return librbd::api::Mirror<>::image_disable(ictx, force);
1761 }
1762
1763 int Image::mirror_image_promote(bool force) {
1764 ImageCtx *ictx = (ImageCtx *)ctx;
1765 return librbd::api::Mirror<>::image_promote(ictx, force);
1766 }
1767
1768 int Image::mirror_image_demote() {
1769 ImageCtx *ictx = (ImageCtx *)ctx;
1770 return librbd::api::Mirror<>::image_demote(ictx);
1771 }
1772
1773 int Image::mirror_image_resync()
1774 {
1775 ImageCtx *ictx = (ImageCtx *)ctx;
1776 return librbd::api::Mirror<>::image_resync(ictx);
1777 }
1778
1779 int Image::mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1780 size_t info_size) {
1781 ImageCtx *ictx = (ImageCtx *)ctx;
1782 return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info,
1783 info_size);
1784 }
1785
1786 int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
1787 size_t status_size) {
1788 ImageCtx *ictx = (ImageCtx *)ctx;
1789 return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status,
1790 status_size);
1791 }
1792
1793 int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
1794 ImageCtx *ictx = (ImageCtx *)ctx;
1795 librbd::api::Mirror<>::image_promote(
1796 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1797 get_aio_completion(c)));
1798 return 0;
1799 }
1800
1801 int Image::aio_mirror_image_demote(RBD::AioCompletion *c) {
1802 ImageCtx *ictx = (ImageCtx *)ctx;
1803 librbd::api::Mirror<>::image_demote(
1804 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1805 get_aio_completion(c)));
1806 return 0;
1807 }
1808
1809 int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1810 size_t info_size,
1811 RBD::AioCompletion *c) {
1812 ImageCtx *ictx = (ImageCtx *)ctx;
1813 librbd::api::Mirror<>::image_get_info(
1814 ictx, mirror_image_info, info_size,
1815 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1816 get_aio_completion(c)));
1817 return 0;
1818 }
1819
1820 int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
1821 size_t status_size,
1822 RBD::AioCompletion *c) {
1823 ImageCtx *ictx = (ImageCtx *)ctx;
1824 librbd::api::Mirror<>::image_get_status(
1825 ictx, status, status_size,
1826 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1827 get_aio_completion(c)));
1828 return 0;
1829 }
1830
1831 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
1832 ImageCtx *ictx = (ImageCtx *)ctx;
1833 tracepoint(librbd, update_watch_enter, ictx, wctx);
1834 int r = ictx->state->register_update_watcher(wctx, handle);
1835 tracepoint(librbd, update_watch_exit, r, *handle);
1836 return r;
1837 }
1838
1839 int Image::update_unwatch(uint64_t handle) {
1840 ImageCtx *ictx = (ImageCtx *)ctx;
1841 tracepoint(librbd, update_unwatch_enter, ictx, handle);
1842 int r = ictx->state->unregister_update_watcher(handle);
1843 tracepoint(librbd, update_unwatch_exit, r);
1844 return r;
1845 }
1846
1847 } // namespace librbd
1848
1849 extern "C" void rbd_version(int *major, int *minor, int *extra)
1850 {
1851 if (major)
1852 *major = LIBRBD_VER_MAJOR;
1853 if (minor)
1854 *minor = LIBRBD_VER_MINOR;
1855 if (extra)
1856 *extra = LIBRBD_VER_EXTRA;
1857 }
1858
1859 extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
1860 {
1861 librbd::image_options_create(opts);
1862 }
1863
1864 extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
1865 {
1866 librbd::image_options_destroy(opts);
1867 }
1868
1869 extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
1870 const char* optval)
1871 {
1872 return librbd::image_options_set(opts, optname, optval);
1873 }
1874
1875 extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
1876 uint64_t optval)
1877 {
1878 return librbd::image_options_set(opts, optname, optval);
1879 }
1880
1881 extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
1882 char* optval, size_t maxlen)
1883 {
1884 std::string optval_;
1885
1886 int r = librbd::image_options_get(opts, optname, &optval_);
1887
1888 if (r < 0) {
1889 return r;
1890 }
1891
1892 if (optval_.size() >= maxlen) {
1893 return -E2BIG;
1894 }
1895
1896 strncpy(optval, optval_.c_str(), maxlen);
1897
1898 return 0;
1899 }
1900
1901 extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
1902 uint64_t* optval)
1903 {
1904 return librbd::image_options_get(opts, optname, optval);
1905 }
1906
1907 extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
1908 bool* is_set)
1909 {
1910 return librbd::image_options_is_set(opts, optname, is_set);
1911 }
1912
1913 extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
1914 {
1915 return librbd::image_options_unset(opts, optname);
1916 }
1917
1918 extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
1919 {
1920 librbd::image_options_clear(opts);
1921 }
1922
1923 extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
1924 {
1925 return librbd::image_options_is_empty(opts);
1926 }
1927
1928 /* pool mirroring */
1929 extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
1930 rbd_mirror_mode_t *mirror_mode) {
1931 librados::IoCtx io_ctx;
1932 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1933 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
1934 }
1935
1936 extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
1937 rbd_mirror_mode_t mirror_mode) {
1938 librados::IoCtx io_ctx;
1939 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1940 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
1941 }
1942
1943 extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
1944 size_t uuid_max_length,
1945 const char *cluster_name,
1946 const char *client_name) {
1947 static const std::size_t UUID_LENGTH = 36;
1948
1949 librados::IoCtx io_ctx;
1950 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1951
1952 if (uuid_max_length < UUID_LENGTH + 1) {
1953 return -E2BIG;
1954 }
1955
1956 std::string uuid_str;
1957 int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
1958 client_name);
1959 if (r >= 0) {
1960 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
1961 uuid[uuid_max_length - 1] = '\0';
1962 }
1963 return r;
1964 }
1965
1966 extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
1967 librados::IoCtx io_ctx;
1968 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1969 int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
1970 return r;
1971 }
1972
1973 extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
1974 rbd_mirror_peer_t *peers, int *max_peers) {
1975 librados::IoCtx io_ctx;
1976 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1977
1978 std::vector<librbd::mirror_peer_t> peer_vector;
1979 int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
1980 if (r < 0) {
1981 return r;
1982 }
1983
1984 if (*max_peers < static_cast<int>(peer_vector.size())) {
1985 *max_peers = static_cast<int>(peer_vector.size());
1986 return -ERANGE;
1987 }
1988
1989 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
1990 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
1991 peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
1992 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
1993 }
1994 *max_peers = static_cast<int>(peer_vector.size());
1995 return 0;
1996 }
1997
1998 extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
1999 int max_peers) {
2000 for (int i = 0; i < max_peers; ++i) {
2001 free(peers[i].uuid);
2002 free(peers[i].cluster_name);
2003 free(peers[i].client_name);
2004 }
2005 }
2006
2007 extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
2008 const char *client_name) {
2009 librados::IoCtx io_ctx;
2010 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2011 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
2012 }
2013
2014 extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
2015 const char *cluster_name) {
2016 librados::IoCtx io_ctx;
2017 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2018 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
2019 }
2020
2021 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
2022 const char *start_id, size_t max, char **image_ids,
2023 rbd_mirror_image_status_t *images, size_t *len) {
2024 librados::IoCtx io_ctx;
2025 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2026 std::map<std::string, librbd::mirror_image_status_t> cpp_images;
2027
2028 int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
2029 &cpp_images);
2030 if (r < 0) {
2031 return r;
2032 }
2033
2034 size_t i = 0;
2035 for (auto &it : cpp_images) {
2036 assert(i < max);
2037 const std::string &image_id = it.first;
2038 image_ids[i] = strdup(image_id.c_str());
2039 mirror_image_status_cpp_to_c(it.second, &images[i]);
2040 i++;
2041 }
2042 *len = i;
2043 return 0;
2044 }
2045
2046 extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
2047 rbd_mirror_image_status_t *images, size_t len) {
2048 for (size_t i = 0; i < len; i++) {
2049 free(image_ids[i]);
2050 free(images[i].name);
2051 free(images[i].info.global_id);
2052 free(images[i].description);
2053 }
2054 }
2055
2056 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
2057 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
2058
2059 librados::IoCtx io_ctx;
2060 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2061
2062 std::map<librbd::mirror_image_status_state_t, int> states_;
2063 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
2064 if (r < 0) {
2065 return r;
2066 }
2067
2068 size_t i = 0;
2069 for (auto &it : states_) {
2070 if (i == *maxlen) {
2071 return -ERANGE;
2072 }
2073 states[i] = it.first;
2074 counts[i] = it.second;
2075 i++;
2076 }
2077 *maxlen = i;
2078 return 0;
2079 }
2080
2081 /* images */
2082 extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
2083 {
2084 librados::IoCtx io_ctx;
2085 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2086 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2087 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2088 vector<string> cpp_names;
2089 int r = librbd::list(io_ctx, cpp_names);
2090 if (r < 0) {
2091 tracepoint(librbd, list_exit, r, *size);
2092 return r;
2093 }
2094
2095 size_t expected_size = 0;
2096
2097 for (size_t i = 0; i < cpp_names.size(); i++) {
2098 expected_size += cpp_names[i].size() + 1;
2099 }
2100 if (*size < expected_size) {
2101 *size = expected_size;
2102 tracepoint(librbd, list_exit, -ERANGE, *size);
2103 return -ERANGE;
2104 }
2105
2106 if (!names)
2107 return -EINVAL;
2108
2109 for (int i = 0; i < (int)cpp_names.size(); i++) {
2110 const char* name = cpp_names[i].c_str();
2111 tracepoint(librbd, list_entry, name);
2112 strcpy(names, name);
2113 names += strlen(names) + 1;
2114 }
2115 tracepoint(librbd, list_exit, (int)expected_size, *size);
2116 return (int)expected_size;
2117 }
2118
2119 extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
2120 {
2121 librados::IoCtx io_ctx;
2122 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2123 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2124 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
2125 int r = librbd::create(io_ctx, name, size, order);
2126 tracepoint(librbd, create_exit, r, *order);
2127 return r;
2128 }
2129
2130 extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
2131 uint64_t size, uint64_t features,
2132 int *order)
2133 {
2134 librados::IoCtx io_ctx;
2135 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2136 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2137 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
2138 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
2139 tracepoint(librbd, create2_exit, r, *order);
2140 return r;
2141 }
2142
2143 extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
2144 uint64_t size, uint64_t features,
2145 int *order,
2146 uint64_t stripe_unit, uint64_t stripe_count)
2147 {
2148 librados::IoCtx io_ctx;
2149 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2150 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2151 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
2152 int r = librbd::create(io_ctx, name, size, false, features, order,
2153 stripe_unit, stripe_count);
2154 tracepoint(librbd, create3_exit, r, *order);
2155 return r;
2156 }
2157
2158 extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
2159 uint64_t size, rbd_image_options_t opts)
2160 {
2161 librados::IoCtx io_ctx;
2162 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2163 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2164 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
2165 librbd::ImageOptions opts_(opts);
2166 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
2167 tracepoint(librbd, create4_exit, r);
2168 return r;
2169 }
2170
2171 extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
2172 const char *p_snap_name, rados_ioctx_t c_ioctx,
2173 const char *c_name, uint64_t features, int *c_order)
2174 {
2175 librados::IoCtx p_ioc, c_ioc;
2176 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2177 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2178 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2179 tracepoint(librbd, clone_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, features);
2180 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2181 features, c_order, 0, 0);
2182 tracepoint(librbd, clone_exit, r, *c_order);
2183 return r;
2184 }
2185
2186 extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
2187 const char *p_snap_name, rados_ioctx_t c_ioctx,
2188 const char *c_name, uint64_t features, int *c_order,
2189 uint64_t stripe_unit, int stripe_count)
2190 {
2191 librados::IoCtx p_ioc, c_ioc;
2192 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2193 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2194 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2195 tracepoint(librbd, clone2_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, features, stripe_unit, stripe_count);
2196 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2197 features, c_order, stripe_unit, stripe_count);
2198 tracepoint(librbd, clone2_exit, r, *c_order);
2199 return r;
2200 }
2201
2202 extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
2203 const char *p_snap_name, rados_ioctx_t c_ioctx,
2204 const char *c_name, rbd_image_options_t c_opts)
2205 {
2206 librados::IoCtx p_ioc, c_ioc;
2207 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2208 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2209 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2210 tracepoint(librbd, clone3_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, c_opts);
2211 librbd::ImageOptions c_opts_(c_opts);
2212 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_);
2213 tracepoint(librbd, clone3_exit, r);
2214 return r;
2215 }
2216
2217 extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
2218 {
2219 librados::IoCtx io_ctx;
2220 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2221 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2222 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2223 librbd::NoOpProgressContext prog_ctx;
2224 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2225 tracepoint(librbd, remove_exit, r);
2226 return r;
2227 }
2228
2229 extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
2230 librbd_progress_fn_t cb, void *cbdata)
2231 {
2232 librados::IoCtx io_ctx;
2233 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2234 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2235 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2236 librbd::CProgressContext prog_ctx(cb, cbdata);
2237 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2238 tracepoint(librbd, remove_exit, r);
2239 return r;
2240 }
2241
2242 extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
2243 uint64_t delay) {
2244 librados::IoCtx io_ctx;
2245 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2246 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2247 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
2248 io_ctx.get_id(), name);
2249 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, delay);
2250 tracepoint(librbd, trash_move_exit, r);
2251 return r;
2252 }
2253
2254 extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
2255 rbd_trash_image_info_t *info) {
2256 librados::IoCtx io_ctx;
2257 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
2258
2259 librbd::trash_image_info_t cpp_info;
2260 int r = librbd::trash_get(io_ctx, id, &cpp_info);
2261 if (r < 0) {
2262 return r;
2263 }
2264
2265 trash_image_info_cpp_to_c(cpp_info, info);
2266 return 0;
2267 }
2268
2269 extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
2270 free(info->id);
2271 free(info->name);
2272 }
2273
2274 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
2275 size_t *num_entries) {
2276 librados::IoCtx io_ctx;
2277 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2278 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2279 tracepoint(librbd, trash_list_enter,
2280 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2281
2282 vector<librbd::trash_image_info_t> cpp_entries;
2283 int r = librbd::trash_list(io_ctx, cpp_entries);
2284 if (r < 0) {
2285 tracepoint(librbd, trash_list_exit, r, *num_entries);
2286 return r;
2287 }
2288
2289 if (*num_entries < cpp_entries.size()) {
2290 *num_entries = cpp_entries.size();
2291 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
2292 return -ERANGE;
2293 }
2294
2295 int i=0;
2296 for (const auto &entry : cpp_entries) {
2297 trash_image_info_cpp_to_c(entry, &entries[i++]);
2298 }
2299 *num_entries = cpp_entries.size();
2300
2301 return *num_entries;
2302 }
2303
2304 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
2305 size_t num_entries) {
2306 for (size_t i=0; i < num_entries; i++) {
2307 rbd_trash_get_cleanup(&entries[i]);
2308 }
2309 }
2310
2311 extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
2312 bool force) {
2313 librados::IoCtx io_ctx;
2314 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2315 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2316 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2317 io_ctx.get_id(), image_id, force);
2318 librbd::NoOpProgressContext prog_ctx;
2319 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2320 tracepoint(librbd, trash_remove_exit, r);
2321 return r;
2322 }
2323
2324 extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
2325 const char *image_id,
2326 bool force,
2327 librbd_progress_fn_t cb,
2328 void *cbdata) {
2329 librados::IoCtx io_ctx;
2330 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2331 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2332 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2333 io_ctx.get_id(), image_id, force);
2334 librbd::CProgressContext prog_ctx(cb, cbdata);
2335 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2336 tracepoint(librbd, trash_remove_exit, r);
2337 return r;
2338 }
2339
2340 extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
2341 const char *name) {
2342 librados::IoCtx io_ctx;
2343 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2344 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2345 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
2346 io_ctx.get_id(), id, name);
2347 int r = librbd::trash_restore(io_ctx, id, name);
2348 tracepoint(librbd, trash_undelete_exit, r);
2349 return r;
2350 }
2351
2352 extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
2353 const char *destname)
2354 {
2355 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2356 librados::IoCtx dest_io_ctx;
2357 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2358 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
2359 librbd::ImageOptions opts;
2360 librbd::NoOpProgressContext prog_ctx;
2361 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2362 tracepoint(librbd, copy_exit, r);
2363 return r;
2364 }
2365
2366 extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
2367 {
2368 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2369 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2370 tracepoint(librbd, copy2_enter, src, src->name.c_str(), src->snap_name.c_str(), src->read_only, dest, dest->name.c_str(), dest->snap_name.c_str(), dest->read_only);
2371 librbd::NoOpProgressContext prog_ctx;
2372 int r = librbd::copy(src, dest, prog_ctx, 0);
2373 tracepoint(librbd, copy2_exit, r);
2374 return r;
2375 }
2376
2377 extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
2378 const char *destname, rbd_image_options_t c_opts)
2379 {
2380 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2381 librados::IoCtx dest_io_ctx;
2382 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2383 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts);
2384 librbd::ImageOptions c_opts_(c_opts);
2385 librbd::NoOpProgressContext prog_ctx;
2386 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
2387 tracepoint(librbd, copy3_exit, r);
2388 return r;
2389 }
2390
2391 extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
2392 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
2393 {
2394 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2395 librados::IoCtx dest_io_ctx;
2396 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2397 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts, sparse_size);
2398 librbd::ImageOptions c_opts_(c_opts);
2399 librbd::NoOpProgressContext prog_ctx;
2400 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
2401 tracepoint(librbd, copy4_exit, r);
2402 return r;
2403 }
2404
2405 extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
2406 const char *destname,
2407 librbd_progress_fn_t fn, void *data)
2408 {
2409 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2410 librados::IoCtx dest_io_ctx;
2411 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2412 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
2413 librbd::ImageOptions opts;
2414 librbd::CProgressContext prog_ctx(fn, data);
2415 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2416 tracepoint(librbd, copy_exit, ret);
2417 return ret;
2418 }
2419
2420 extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
2421 librbd_progress_fn_t fn, void *data)
2422 {
2423 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2424 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2425 tracepoint(librbd, copy2_enter, src, src->name.c_str(), src->snap_name.c_str(), src->read_only, dest, dest->name.c_str(), dest->snap_name.c_str(), dest->read_only);
2426 librbd::CProgressContext prog_ctx(fn, data);
2427 int ret = librbd::copy(src, dest, prog_ctx, 0);
2428 tracepoint(librbd, copy2_exit, ret);
2429 return ret;
2430 }
2431
2432 extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
2433 const char *destname,
2434 rbd_image_options_t dest_opts,
2435 librbd_progress_fn_t fn, void *data)
2436 {
2437 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2438 librados::IoCtx dest_io_ctx;
2439 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2440 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, dest_opts);
2441 librbd::ImageOptions dest_opts_(dest_opts);
2442 librbd::CProgressContext prog_ctx(fn, data);
2443 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
2444 tracepoint(librbd, copy3_exit, ret);
2445 return ret;
2446 }
2447
2448 extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
2449 const char *destname,
2450 rbd_image_options_t dest_opts,
2451 librbd_progress_fn_t fn, void *data, size_t sparse_size)
2452 {
2453 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2454 librados::IoCtx dest_io_ctx;
2455 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2456 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, dest_opts, sparse_size);
2457 librbd::ImageOptions dest_opts_(dest_opts);
2458 librbd::CProgressContext prog_ctx(fn, data);
2459 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
2460 tracepoint(librbd, copy4_exit, ret);
2461 return ret;
2462 }
2463
2464
2465 extern "C" int rbd_flatten(rbd_image_t image)
2466 {
2467 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2468 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2469 librbd::NoOpProgressContext prog_ctx;
2470 int r = ictx->operations->flatten(prog_ctx);
2471 tracepoint(librbd, flatten_exit, r);
2472 return r;
2473 }
2474
2475 extern "C" int rbd_flatten_with_progress(rbd_image_t image,
2476 librbd_progress_fn_t cb, void *cbdata)
2477 {
2478 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2479 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2480 librbd::CProgressContext prog_ctx(cb, cbdata);
2481 int r = ictx->operations->flatten(prog_ctx);
2482 tracepoint(librbd, flatten_exit, r);
2483 return r;
2484 }
2485
2486 extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
2487 const char *destname)
2488 {
2489 librados::IoCtx src_io_ctx;
2490 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
2491 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
2492 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
2493 int r = librbd::rename(src_io_ctx, srcname, destname);
2494 tracepoint(librbd, rename_exit, r);
2495 return r;
2496 }
2497
2498 extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
2499 const char *snap_name)
2500 {
2501 librados::IoCtx io_ctx;
2502 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2503 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2504 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2505 false);
2506 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2507
2508 int r = ictx->state->open(false);
2509 if (r >= 0) {
2510 *image = (rbd_image_t)ictx;
2511 }
2512 tracepoint(librbd, open_image_exit, r);
2513 return r;
2514 }
2515
2516 extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
2517 rbd_image_t *image, const char *snap_name)
2518 {
2519 librados::IoCtx io_ctx;
2520 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2521 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2522 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2523 false);
2524 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2525 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2526
2527 int r = ictx->state->open(false);
2528 if (r < 0) {
2529 delete ictx;
2530 } else {
2531 *image = (rbd_image_t)ictx;
2532 }
2533 tracepoint(librbd, open_image_exit, r);
2534 return r;
2535 }
2536
2537 extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
2538 rbd_image_t *image, const char *snap_name,
2539 rbd_completion_t c)
2540 {
2541 librados::IoCtx io_ctx;
2542 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2543 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2544 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2545 false);
2546 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2547 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2548 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2549 tracepoint(librbd, aio_open_image_exit, 0);
2550 return 0;
2551 }
2552
2553 extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
2554 rbd_image_t *image, const char *snap_name,
2555 rbd_completion_t c)
2556 {
2557 librados::IoCtx io_ctx;
2558 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2559 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2560 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2561 false);
2562 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2563 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2564 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
2565 comp->pc);
2566 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2567 tracepoint(librbd, aio_open_image_exit, 0);
2568 return 0;
2569 }
2570
2571 extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
2572 rbd_image_t *image, const char *snap_name)
2573 {
2574 librados::IoCtx io_ctx;
2575 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2576 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2577 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2578 true);
2579 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2580
2581 int r = ictx->state->open(false);
2582 if (r >= 0) {
2583 *image = (rbd_image_t)ictx;
2584 }
2585 tracepoint(librbd, open_image_exit, r);
2586 return r;
2587 }
2588
2589 extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
2590 rbd_image_t *image, const char *snap_name)
2591 {
2592 librados::IoCtx io_ctx;
2593 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2594 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2595 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2596 true);
2597 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2598 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2599
2600 int r = ictx->state->open(false);
2601 if (r < 0) {
2602 delete ictx;
2603 } else {
2604 *image = (rbd_image_t)ictx;
2605 }
2606 tracepoint(librbd, open_image_exit, r);
2607 return r;
2608 }
2609
2610 extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
2611 rbd_image_t *image, const char *snap_name,
2612 rbd_completion_t c)
2613 {
2614 librados::IoCtx io_ctx;
2615 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2616 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2617 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2618 true);
2619 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2620 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2621 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2622 image));
2623 tracepoint(librbd, aio_open_image_exit, 0);
2624 return 0;
2625 }
2626
2627 extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
2628 rbd_image_t *image,
2629 const char *snap_name,
2630 rbd_completion_t c)
2631 {
2632 librados::IoCtx io_ctx;
2633 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2634 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2635 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2636 true);
2637 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2638 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2639 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2640 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2641 image));
2642 tracepoint(librbd, aio_open_image_exit, 0);
2643 return 0;
2644 }
2645
2646 extern "C" int rbd_close(rbd_image_t image)
2647 {
2648 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2649 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2650
2651 int r = ictx->state->close();
2652
2653 tracepoint(librbd, close_image_exit, r);
2654 return r;
2655 }
2656
2657 extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
2658 {
2659 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2660 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2661 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
2662 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
2663 get_aio_completion(comp)));
2664 tracepoint(librbd, aio_close_image_exit, 0);
2665 return 0;
2666 }
2667
2668 extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
2669 {
2670 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2671 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2672 librbd::NoOpProgressContext prog_ctx;
2673 int r = ictx->operations->resize(size, true, prog_ctx);
2674 tracepoint(librbd, resize_exit, r);
2675 return r;
2676 }
2677
2678 extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
2679 librbd_progress_fn_t cb, void *cbdata)
2680 {
2681 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2682 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2683 librbd::CProgressContext prog_ctx(cb, cbdata);
2684 int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
2685 tracepoint(librbd, resize_exit, r);
2686 return r;
2687 }
2688
2689 extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
2690 librbd_progress_fn_t cb, void *cbdata)
2691 {
2692 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2693 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2694 librbd::CProgressContext prog_ctx(cb, cbdata);
2695 int r = ictx->operations->resize(size, true, prog_ctx);
2696 tracepoint(librbd, resize_exit, r);
2697 return r;
2698 }
2699
2700 extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
2701 size_t infosize)
2702 {
2703 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2704 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2705 int r = librbd::info(ictx, *info, infosize);
2706 tracepoint(librbd, stat_exit, r, info);
2707 return r;
2708 }
2709
2710 extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
2711 {
2712 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2713 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2714 int r = librbd::get_old_format(ictx, old);
2715 tracepoint(librbd, get_old_format_exit, r, *old);
2716 return r;
2717 }
2718
2719 extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
2720 {
2721 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2722 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2723 int r = librbd::get_size(ictx, size);
2724 tracepoint(librbd, get_size_exit, r, *size);
2725 return r;
2726 }
2727
2728 extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
2729 {
2730 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2731 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2732 int r = librbd::get_features(ictx, features);
2733 tracepoint(librbd, get_features_exit, r, *features);
2734 return r;
2735 }
2736
2737 extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
2738 uint8_t enabled)
2739 {
2740 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2741 bool features_enabled = enabled != 0;
2742 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
2743 int r = ictx->operations->update_features(features, features_enabled);
2744 tracepoint(librbd, update_features_exit, r);
2745 return r;
2746 }
2747
2748 extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
2749 {
2750 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2751 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2752 *stripe_unit = ictx->get_stripe_unit();
2753 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
2754 return 0;
2755 }
2756
2757 extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
2758 {
2759 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2760 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2761 *stripe_count = ictx->get_stripe_count();
2762 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
2763 return 0;
2764 }
2765
2766 extern "C" int rbd_get_create_timestamp(rbd_image_t image,
2767 struct timespec *timestamp)
2768 {
2769 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2770 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
2771 ictx->read_only);
2772 utime_t time = ictx->get_create_timestamp();
2773 time.to_timespec(timestamp);
2774 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
2775 return 0;
2776 }
2777
2778 extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
2779 {
2780 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2781 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2782 int r = librbd::get_overlap(ictx, overlap);
2783 tracepoint(librbd, get_overlap_exit, r, *overlap);
2784 return r;
2785 }
2786
2787 extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
2788 {
2789 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2790 if (ictx->old_format) {
2791 return -EINVAL;
2792 }
2793 if (ictx->id.size() >= id_len) {
2794 return -ERANGE;
2795 }
2796
2797 strncpy(id, ictx->id.c_str(), id_len - 1);
2798 id[id_len - 1] = '\0';
2799 return 0;
2800 }
2801
2802 extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
2803 size_t prefix_len)
2804 {
2805 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2806 if (ictx->object_prefix.size() >= prefix_len) {
2807 return -ERANGE;
2808 }
2809
2810 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
2811 prefix[prefix_len - 1] = '\0';
2812 return 0;
2813 }
2814
2815 extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
2816 {
2817 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2818 return ictx->data_ctx.get_id();
2819 }
2820
2821 extern "C" int rbd_get_parent_info(rbd_image_t image,
2822 char *parent_pool_name, size_t ppool_namelen,
2823 char *parent_name, size_t pnamelen,
2824 char *parent_snap_name, size_t psnap_namelen)
2825 {
2826 return rbd_get_parent_info2(image, parent_pool_name, ppool_namelen,
2827 parent_name, pnamelen, nullptr, 0,
2828 parent_snap_name, psnap_namelen);
2829 }
2830
2831 extern "C" int rbd_get_parent_info2(rbd_image_t image,
2832 char *parent_pool_name,
2833 size_t ppool_namelen,
2834 char *parent_name, size_t pnamelen,
2835 char *parent_id, size_t pidlen,
2836 char *parent_snap_name,
2837 size_t psnap_namelen)
2838 {
2839 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2840 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
2841 ictx->snap_name.c_str(), ictx->read_only);
2842 string p_pool_name, p_name, p_id, p_snap_name;
2843
2844 int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_id,
2845 &p_snap_name);
2846 if (r < 0) {
2847 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
2848 return r;
2849 }
2850
2851 if (parent_pool_name) {
2852 if (p_pool_name.length() + 1 > ppool_namelen) {
2853 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2854 return -ERANGE;
2855 }
2856
2857 strcpy(parent_pool_name, p_pool_name.c_str());
2858 }
2859 if (parent_name) {
2860 if (p_name.length() + 1 > pnamelen) {
2861 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2862 return -ERANGE;
2863 }
2864
2865 strcpy(parent_name, p_name.c_str());
2866 }
2867 if (parent_id) {
2868 if (p_id.length() + 1 > pidlen) {
2869 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2870 return -ERANGE;
2871 }
2872
2873 strcpy(parent_id, p_id.c_str());
2874 }
2875 if (parent_snap_name) {
2876 if (p_snap_name.length() + 1 > psnap_namelen) {
2877 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2878 return -ERANGE;
2879 }
2880
2881 strcpy(parent_snap_name, p_snap_name.c_str());
2882 }
2883
2884 tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name,
2885 parent_id, parent_snap_name);
2886 return 0;
2887 }
2888
2889 extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
2890 {
2891 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2892 tracepoint(librbd, get_flags_enter, ictx);
2893 int r = librbd::get_flags(ictx, flags);
2894 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
2895 return r;
2896 }
2897
2898 extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
2899 {
2900 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2901 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
2902 int r = librbd::set_image_notification(ictx, fd, type);
2903 tracepoint(librbd, set_image_notification_exit, ictx, r);
2904 return r;
2905 }
2906
2907 extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
2908 {
2909 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2910 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
2911 bool owner;
2912 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
2913 *is_owner = owner ? 1 : 0;
2914 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
2915 return r;
2916 }
2917
2918 extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
2919 {
2920 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2921 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
2922 int r = librbd::lock_acquire(ictx, lock_mode);
2923 tracepoint(librbd, lock_acquire_exit, ictx, r);
2924 return r;
2925 }
2926
2927 extern "C" int rbd_lock_release(rbd_image_t image)
2928 {
2929 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2930 tracepoint(librbd, lock_release_enter, ictx);
2931 int r = librbd::lock_release(ictx);
2932 tracepoint(librbd, lock_release_exit, ictx, r);
2933 return r;
2934 }
2935
2936 extern "C" int rbd_lock_get_owners(rbd_image_t image,
2937 rbd_lock_mode_t *lock_mode,
2938 char **lock_owners,
2939 size_t *max_lock_owners)
2940 {
2941 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2942 tracepoint(librbd, lock_get_owners_enter, ictx);
2943 std::list<std::string> lock_owner_list;
2944 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
2945 if (r >= 0) {
2946 if (*max_lock_owners >= lock_owner_list.size()) {
2947 *max_lock_owners = 0;
2948 for (auto &lock_owner : lock_owner_list) {
2949 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
2950 }
2951 } else {
2952 *max_lock_owners = lock_owner_list.size();
2953 r = -ERANGE;
2954 }
2955 }
2956 tracepoint(librbd, lock_get_owners_exit, ictx, r);
2957 return r;
2958 }
2959
2960 extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
2961 size_t lock_owner_count)
2962 {
2963 for (size_t i = 0; i < lock_owner_count; ++i) {
2964 free(lock_owners[i]);
2965 }
2966 }
2967
2968 extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
2969 const char *lock_owner)
2970 {
2971 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2972 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
2973 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
2974 tracepoint(librbd, lock_break_exit, ictx, r);
2975 return r;
2976 }
2977
2978 extern "C" int rbd_rebuild_object_map(rbd_image_t image,
2979 librbd_progress_fn_t cb, void *cbdata)
2980 {
2981 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2982 librbd::CProgressContext prog_ctx(cb, cbdata);
2983 return ictx->operations->rebuild_object_map(prog_ctx);
2984 }
2985
2986 /* snapshots */
2987 extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
2988 {
2989 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2990 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
2991 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
2992 snap_name);
2993 tracepoint(librbd, snap_create_exit, r);
2994 return r;
2995 }
2996
2997 extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
2998 {
2999 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3000 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
3001 int r = ictx->operations->snap_rename(srcname, dstname);
3002 tracepoint(librbd, snap_rename_exit, r);
3003 return r;
3004 }
3005
3006 extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
3007 {
3008 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3009 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3010 librbd::NoOpProgressContext prog_ctx;
3011 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
3012 tracepoint(librbd, snap_remove_exit, r);
3013 return r;
3014 }
3015
3016 extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
3017 librbd_progress_fn_t cb, void *cbdata)
3018 {
3019 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3020 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
3021 librbd::CProgressContext prog_ctx(cb, cbdata);
3022 int r = librbd::snap_remove(ictx, snap_name, flags, prog_ctx);
3023 tracepoint(librbd, snap_remove_exit, r);
3024 return r;
3025 }
3026
3027 extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
3028 {
3029 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3030 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3031 librbd::NoOpProgressContext prog_ctx;
3032 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3033 tracepoint(librbd, snap_rollback_exit, r);
3034 return r;
3035 }
3036
3037 extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
3038 const char *snap_name,
3039 librbd_progress_fn_t cb,
3040 void *cbdata)
3041 {
3042 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3043 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3044 librbd::CProgressContext prog_ctx(cb, cbdata);
3045 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3046 tracepoint(librbd, snap_rollback_exit, r);
3047 return r;
3048 }
3049
3050 extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
3051 int *max_snaps)
3052 {
3053 vector<librbd::snap_info_t> cpp_snaps;
3054 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3055 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
3056
3057 if (!max_snaps) {
3058 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
3059 return -EINVAL;
3060 }
3061
3062 int r = librbd::snap_list(ictx, cpp_snaps);
3063 if (r == -ENOENT) {
3064 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
3065 return 0;
3066 }
3067 if (r < 0) {
3068 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3069 return r;
3070 }
3071 if (*max_snaps < (int)cpp_snaps.size() + 1) {
3072 *max_snaps = (int)cpp_snaps.size() + 1;
3073 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
3074 return -ERANGE;
3075 }
3076
3077 int i;
3078
3079 for (i = 0; i < (int)cpp_snaps.size(); i++) {
3080 snaps[i].id = cpp_snaps[i].id;
3081 snaps[i].size = cpp_snaps[i].size;
3082 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
3083 if (!snaps[i].name) {
3084 for (int j = 0; j < i; j++)
3085 free((void *)snaps[j].name);
3086 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
3087 return -ENOMEM;
3088 }
3089 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
3090 }
3091 snaps[i].id = 0;
3092 snaps[i].size = 0;
3093 snaps[i].name = NULL;
3094
3095 r = (int)cpp_snaps.size();
3096 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3097 return r;
3098 }
3099
3100 extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
3101 {
3102 tracepoint(librbd, snap_list_end_enter, snaps);
3103 while (snaps->name) {
3104 free((void *)snaps->name);
3105 snaps++;
3106 }
3107 tracepoint(librbd, snap_list_end_exit);
3108 }
3109
3110 extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
3111 {
3112 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3113 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3114 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
3115 tracepoint(librbd, snap_protect_exit, r);
3116 return r;
3117 }
3118
3119 extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
3120 {
3121 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3122 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3123 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
3124 tracepoint(librbd, snap_unprotect_exit, r);
3125 return r;
3126 }
3127
3128 extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
3129 int *is_protected)
3130 {
3131 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3132 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3133 bool protected_snap;
3134 int r = librbd::snap_is_protected(ictx, snap_name, &protected_snap);
3135 if (r < 0) {
3136 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
3137 return r;
3138 }
3139 *is_protected = protected_snap ? 1 : 0;
3140 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
3141 return 0;
3142 }
3143
3144 extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
3145 {
3146 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3147 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
3148 int r = librbd::snap_get_limit(ictx, limit);
3149 tracepoint(librbd, snap_get_limit_exit, r, *limit);
3150 return r;
3151 }
3152
3153 extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
3154 {
3155 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3156 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
3157 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
3158 tracepoint(librbd, snap_get_timestamp_exit, r);
3159 return r;
3160 }
3161
3162 extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
3163 {
3164 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3165 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
3166 int r = librbd::snap_set_limit(ictx, limit);
3167 tracepoint(librbd, snap_set_limit_exit, r);
3168 return r;
3169 }
3170
3171 extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
3172 {
3173 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3174 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3175 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
3176 tracepoint(librbd, snap_set_exit, r);
3177 return r;
3178 }
3179
3180 extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
3181 size_t *pools_len, char *images,
3182 size_t *images_len)
3183 {
3184 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3185 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3186 set<pair<string, string> > image_set;
3187
3188 int r = librbd::list_children(ictx, image_set);
3189 if (r < 0) {
3190 tracepoint(librbd, list_children_exit, r);
3191 return r;
3192 }
3193
3194 size_t pools_total = 0;
3195 size_t images_total = 0;
3196 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3197 it != image_set.end(); ++it) {
3198 pools_total += it->first.length() + 1;
3199 images_total += it->second.length() + 1;
3200 }
3201
3202 bool too_short = false;
3203 if (pools_total > *pools_len)
3204 too_short = true;
3205 if (images_total > *images_len)
3206 too_short = true;
3207 *pools_len = pools_total;
3208 *images_len = images_total;
3209 if (too_short) {
3210 tracepoint(librbd, list_children_exit, -ERANGE);
3211 return -ERANGE;
3212 }
3213
3214 char *pools_p = pools;
3215 char *images_p = images;
3216 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3217 it != image_set.end(); ++it) {
3218 const char* pool = it->first.c_str();
3219 strcpy(pools_p, pool);
3220 pools_p += it->first.length() + 1;
3221 const char* image = it->second.c_str();
3222 strcpy(images_p, image);
3223 images_p += it->second.length() + 1;
3224 tracepoint(librbd, list_children_entry, pool, image);
3225 }
3226
3227 ssize_t ret = image_set.size();
3228 tracepoint(librbd, list_children_exit, ret);
3229 return ret;
3230 }
3231
3232 extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
3233 char *tag, size_t *tag_len,
3234 char *clients, size_t *clients_len,
3235 char *cookies, size_t *cookies_len,
3236 char *addrs, size_t *addrs_len)
3237 {
3238 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3239 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3240 std::list<librbd::locker_t> lockers;
3241 bool exclusive_bool;
3242 string tag_str;
3243
3244 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
3245 if (r < 0) {
3246 tracepoint(librbd, list_lockers_exit, r);
3247 return r;
3248 }
3249
3250 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
3251
3252 *exclusive = (int)exclusive_bool;
3253 size_t clients_total = 0;
3254 size_t cookies_total = 0;
3255 size_t addrs_total = 0;
3256 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3257 it != lockers.end(); ++it) {
3258 clients_total += it->client.length() + 1;
3259 cookies_total += it->cookie.length() + 1;
3260 addrs_total += it->address.length() + 1;
3261 }
3262
3263 bool too_short = ((clients_total > *clients_len) ||
3264 (cookies_total > *cookies_len) ||
3265 (addrs_total > *addrs_len) ||
3266 (tag_str.length() + 1 > *tag_len));
3267 *clients_len = clients_total;
3268 *cookies_len = cookies_total;
3269 *addrs_len = addrs_total;
3270 *tag_len = tag_str.length() + 1;
3271 if (too_short) {
3272 tracepoint(librbd, list_lockers_exit, -ERANGE);
3273 return -ERANGE;
3274 }
3275
3276 strcpy(tag, tag_str.c_str());
3277 char *clients_p = clients;
3278 char *cookies_p = cookies;
3279 char *addrs_p = addrs;
3280 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3281 it != lockers.end(); ++it) {
3282 const char* client = it->client.c_str();
3283 strcpy(clients_p, client);
3284 clients_p += it->client.length() + 1;
3285 const char* cookie = it->cookie.c_str();
3286 strcpy(cookies_p, cookie);
3287 cookies_p += it->cookie.length() + 1;
3288 const char* address = it->address.c_str();
3289 strcpy(addrs_p, address);
3290 addrs_p += it->address.length() + 1;
3291 tracepoint(librbd, list_lockers_entry, client, cookie, address);
3292 }
3293
3294 ssize_t ret = lockers.size();
3295 tracepoint(librbd, list_lockers_exit, ret);
3296 return ret;
3297 }
3298
3299 extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
3300 {
3301 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3302 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3303 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
3304 tracepoint(librbd, lock_exclusive_exit, r);
3305 return r;
3306 }
3307
3308 extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
3309 const char *tag)
3310 {
3311 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3312 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
3313 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
3314 tracepoint(librbd, lock_shared_exit, r);
3315 return r;
3316 }
3317
3318 extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
3319 {
3320 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3321 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3322 int r = librbd::unlock(ictx, cookie ? cookie : "");
3323 tracepoint(librbd, unlock_exit, r);
3324 return r;
3325 }
3326
3327 extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
3328 const char *cookie)
3329 {
3330 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3331 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
3332 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
3333 tracepoint(librbd, break_lock_exit, r);
3334 return r;
3335 }
3336
3337 /* I/O */
3338 extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
3339 char *buf)
3340 {
3341 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3342 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3343 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3344 0);
3345 tracepoint(librbd, read_exit, r);
3346 return r;
3347 }
3348
3349 extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
3350 char *buf, int op_flags)
3351 {
3352 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3353 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
3354 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
3355 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3356 op_flags);
3357 tracepoint(librbd, read_exit, r);
3358 return r;
3359 }
3360
3361
3362 extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_t len,
3363 int (*cb)(uint64_t, size_t, const char *, void *),
3364 void *arg)
3365 {
3366 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3367 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3368 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3369 tracepoint(librbd, read_iterate_exit, r);
3370 return r;
3371 }
3372
3373 extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
3374 int (*cb)(uint64_t, size_t, const char *, void *),
3375 void *arg)
3376 {
3377 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3378 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3379 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3380 if (r > 0)
3381 r = 0;
3382 tracepoint(librbd, read_iterate2_exit, r);
3383 return (int)r;
3384 }
3385
3386 extern "C" int rbd_diff_iterate(rbd_image_t image,
3387 const char *fromsnapname,
3388 uint64_t ofs, uint64_t len,
3389 int (*cb)(uint64_t, size_t, int, void *),
3390 void *arg)
3391 {
3392 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3393 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3394 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3395 true, false);
3396 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3397 cls::rbd::UserSnapshotNamespace(),
3398 fromsnapname, ofs, len,
3399 true, false, cb, arg);
3400 tracepoint(librbd, diff_iterate_exit, r);
3401 return r;
3402 }
3403
3404 extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
3405 uint64_t ofs, uint64_t len,
3406 uint8_t include_parent, uint8_t whole_object,
3407 int (*cb)(uint64_t, size_t, int, void *),
3408 void *arg)
3409 {
3410 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3411 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3412 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3413 include_parent != 0, whole_object != 0);
3414 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3415 cls::rbd::UserSnapshotNamespace(),
3416 fromsnapname, ofs, len,
3417 include_parent, whole_object,
3418 cb, arg);
3419 tracepoint(librbd, diff_iterate_exit, r);
3420 return r;
3421 }
3422
3423 extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
3424 const char *buf)
3425 {
3426 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3427 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
3428
3429 bufferlist bl;
3430 bl.push_back(create_write_raw(ictx, buf, len));
3431 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
3432 tracepoint(librbd, write_exit, r);
3433 return r;
3434 }
3435
3436 extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
3437 const char *buf, int op_flags)
3438 {
3439 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3440 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
3441 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
3442
3443 bufferlist bl;
3444 bl.push_back(create_write_raw(ictx, buf, len));
3445 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
3446 tracepoint(librbd, write_exit, r);
3447 return r;
3448 }
3449
3450
3451 extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
3452 {
3453 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3454 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(),
3455 ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3456 if (len > std::numeric_limits<int>::max()) {
3457 tracepoint(librbd, discard_exit, -EINVAL);
3458 return -EINVAL;
3459 }
3460
3461 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
3462 tracepoint(librbd, discard_exit, r);
3463 return r;
3464 }
3465
3466 extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
3467 const char *buf, size_t data_len, int op_flags)
3468 {
3469 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3470 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3471 ictx->read_only, ofs, len, data_len <= 0 ? NULL : buf, data_len, op_flags);
3472
3473 if (data_len == 0 || len % data_len ||
3474 len > std::numeric_limits<int>::max()) {
3475 tracepoint(librbd, writesame_exit, -EINVAL);
3476 return -EINVAL;
3477 }
3478
3479 if (mem_is_zero(buf, data_len)) {
3480 int r = ictx->io_work_queue->discard(ofs, len, false);
3481 tracepoint(librbd, writesame_exit, r);
3482 return r;
3483 }
3484
3485 bufferlist bl;
3486 bl.push_back(create_write_raw(ictx, buf, data_len));
3487 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
3488 tracepoint(librbd, writesame_exit, r);
3489 return r;
3490 }
3491
3492 extern "C" ssize_t rbd_compare_and_write(rbd_image_t image,
3493 uint64_t ofs, size_t len,
3494 const char *cmp_buf,
3495 const char *buf,
3496 uint64_t *mismatch_off,
3497 int op_flags)
3498 {
3499 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3500 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
3501 ictx->snap_name.c_str(), ictx->read_only, ofs,
3502 len, cmp_buf, buf, op_flags);
3503
3504 bufferlist cmp_bl;
3505 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len));
3506 bufferlist bl;
3507 bl.push_back(create_write_raw(ictx, buf, len));
3508
3509 int r = ictx->io_work_queue->compare_and_write(ofs, len, std::move(cmp_bl),
3510 std::move(bl), mismatch_off,
3511 op_flags);
3512 tracepoint(librbd, compare_and_write_exit, r);
3513 return r;
3514 }
3515
3516 extern "C" int rbd_aio_create_completion(void *cb_arg,
3517 rbd_callback_t complete_cb,
3518 rbd_completion_t *c)
3519 {
3520 librbd::RBD::AioCompletion *rbd_comp =
3521 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
3522 *c = (rbd_completion_t) rbd_comp;
3523 return 0;
3524 }
3525
3526 extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
3527 const char *buf, rbd_completion_t c)
3528 {
3529 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3530 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3531 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3532
3533 bufferlist bl;
3534 bl.push_back(create_write_raw(ictx, buf, len));
3535 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3536 std::move(bl), 0);
3537 tracepoint(librbd, aio_write_exit, 0);
3538 return 0;
3539 }
3540
3541 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
3542 const char *buf, rbd_completion_t c, int op_flags)
3543 {
3544 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3545 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3546 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3547 ictx->read_only, off, len, buf, comp->pc, op_flags);
3548
3549 bufferlist bl;
3550 bl.push_back(create_write_raw(ictx, buf, len));
3551 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3552 std::move(bl), op_flags);
3553 tracepoint(librbd, aio_write_exit, 0);
3554 return 0;
3555 }
3556
3557 extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
3558 int iovcnt, uint64_t off, rbd_completion_t c)
3559 {
3560 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3561 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3562
3563 // convert the scatter list into a bufferlist
3564 ssize_t len = 0;
3565 bufferlist bl;
3566 for (int i = 0; i < iovcnt; ++i) {
3567 const struct iovec &io = iov[i];
3568 len += io.iov_len;
3569 if (len < 0) {
3570 break;
3571 }
3572
3573 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
3574 io.iov_len));
3575 }
3576
3577 int r = 0;
3578 if (iovcnt <= 0 || len < 0) {
3579 r = -EINVAL;
3580 }
3581
3582 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
3583 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3584 comp->pc);
3585 if (r == 0) {
3586 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3587 std::move(bl), 0);
3588 }
3589 tracepoint(librbd, aio_write_exit, r);
3590 return r;
3591 }
3592
3593 extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
3594 rbd_completion_t c)
3595 {
3596 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3597 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3598 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
3599 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard);
3600 tracepoint(librbd, aio_discard_exit, 0);
3601 return 0;
3602 }
3603
3604 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
3605 char *buf, rbd_completion_t c)
3606 {
3607 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3608 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3609 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3610 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3611 librbd::io::ReadResult{buf, len}, 0);
3612 tracepoint(librbd, aio_read_exit, 0);
3613 return 0;
3614 }
3615
3616 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
3617 char *buf, rbd_completion_t c, int op_flags)
3618 {
3619 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3620 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3621 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3622 ictx->read_only, off, len, buf, comp->pc, op_flags);
3623 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3624 librbd::io::ReadResult{buf, len},op_flags);
3625 tracepoint(librbd, aio_read_exit, 0);
3626 return 0;
3627 }
3628
3629 extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
3630 int iovcnt, uint64_t off, rbd_completion_t c)
3631 {
3632 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3633 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3634
3635 ssize_t len = 0;
3636 for (int i = 0; i < iovcnt; ++i) {
3637 len += iov[i].iov_len;
3638 if (len < 0) {
3639 break;
3640 }
3641 }
3642
3643 int r = 0;
3644 if (iovcnt == 0 || len < 0) {
3645 r = -EINVAL;
3646 }
3647
3648 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
3649 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3650 comp->pc);
3651 if (r == 0) {
3652 librbd::io::ReadResult read_result;
3653 if (iovcnt == 1) {
3654 read_result = librbd::io::ReadResult(
3655 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
3656 } else {
3657 read_result = librbd::io::ReadResult(iov, iovcnt);
3658 }
3659 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3660 std::move(read_result), 0);
3661 }
3662 tracepoint(librbd, aio_read_exit, r);
3663 return r;
3664 }
3665
3666 extern "C" int rbd_flush(rbd_image_t image)
3667 {
3668 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3669 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3670 int r = librbd::flush(ictx);
3671 tracepoint(librbd, flush_exit, r);
3672 return r;
3673 }
3674
3675 extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
3676 {
3677 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3678 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3679 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
3680 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
3681 tracepoint(librbd, aio_flush_exit, 0);
3682 return 0;
3683 }
3684
3685 extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
3686 const char *buf, size_t data_len, rbd_completion_t c,
3687 int op_flags)
3688 {
3689 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3690 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3691 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3692 ictx->read_only, off, len, data_len <= 0 ? NULL : buf, data_len, comp->pc,
3693 op_flags);
3694
3695 if (data_len <= 0 || len % data_len) {
3696 tracepoint(librbd, aio_writesame_exit, -EINVAL);
3697 return -EINVAL;
3698 }
3699
3700 if (mem_is_zero(buf, data_len)) {
3701 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false);
3702 tracepoint(librbd, aio_writesame_exit, 0);
3703 return 0;
3704 }
3705
3706 bufferlist bl;
3707 bl.push_back(create_write_raw(ictx, buf, data_len));
3708 ictx->io_work_queue->aio_writesame(get_aio_completion(comp), off, len,
3709 std::move(bl), op_flags);
3710 tracepoint(librbd, aio_writesame_exit, 0);
3711 return 0;
3712 }
3713
3714 extern "C" ssize_t rbd_aio_compare_and_write(rbd_image_t image, uint64_t off,
3715 size_t len, const char *cmp_buf,
3716 const char *buf, rbd_completion_t c,
3717 uint64_t *mismatch_off,
3718 int op_flags)
3719 {
3720 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3721 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3722 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3723 ictx->read_only, off, len, cmp_buf, buf, comp->pc, op_flags);
3724
3725 bufferlist cmp_bl;
3726 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len));
3727 bufferlist bl;
3728 bl.push_back(create_write_raw(ictx, buf, len));
3729 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(comp), off, len,
3730 std::move(cmp_bl), std::move(bl),
3731 mismatch_off, op_flags, false);
3732
3733 tracepoint(librbd, aio_compare_and_write_exit, 0);
3734 return 0;
3735 }
3736
3737 extern "C" int rbd_invalidate_cache(rbd_image_t image)
3738 {
3739 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3740 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3741 int r = librbd::invalidate_cache(ictx);
3742 tracepoint(librbd, invalidate_cache_exit, r);
3743 return r;
3744 }
3745
3746 extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
3747 {
3748 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3749 librbd::io::AioCompletion *cs[numcomp];
3750 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
3751 int r = librbd::poll_io_events(ictx, cs, numcomp);
3752 tracepoint(librbd, poll_io_events_exit, r);
3753 if (r > 0) {
3754 for (int i = 0; i < r; ++i)
3755 comps[i] = cs[i]->rbd_comp;
3756 }
3757 return r;
3758 }
3759
3760 extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
3761 {
3762 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3763 string val_s;
3764 tracepoint(librbd, metadata_get_enter, ictx, key);
3765 int r = librbd::metadata_get(ictx, key, &val_s);
3766 if (r < 0) {
3767 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3768 return r;
3769 }
3770 if (*vallen < val_s.size() + 1) {
3771 r = -ERANGE;
3772 *vallen = val_s.size() + 1;
3773 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3774 } else {
3775 strncpy(value, val_s.c_str(), val_s.size() + 1);
3776 tracepoint(librbd, metadata_get_exit, r, key, value);
3777 }
3778 return r;
3779 }
3780
3781 extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
3782 {
3783 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3784 tracepoint(librbd, metadata_set_enter, ictx, key, value);
3785 int r = ictx->operations->metadata_set(key, value);
3786 tracepoint(librbd, metadata_set_exit, r);
3787 return r;
3788 }
3789
3790 extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
3791 {
3792 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3793 tracepoint(librbd, metadata_remove_enter, ictx, key);
3794 int r = ictx->operations->metadata_remove(key);
3795 tracepoint(librbd, metadata_remove_exit, r);
3796 return r;
3797 }
3798
3799 extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
3800 char *key, size_t *key_len, char *value, size_t *val_len)
3801 {
3802 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3803 tracepoint(librbd, metadata_list_enter, ictx);
3804 map<string, bufferlist> pairs;
3805 int r = librbd::metadata_list(ictx, start, max, &pairs);
3806 size_t key_total_len = 0, val_total_len = 0;
3807 bool too_short = false;
3808 for (map<string, bufferlist>::iterator it = pairs.begin();
3809 it != pairs.end(); ++it) {
3810 key_total_len += it->first.size() + 1;
3811 val_total_len += it->second.length() + 1;
3812 }
3813 if (*key_len < key_total_len || *val_len < val_total_len)
3814 too_short = true;
3815 *key_len = key_total_len;
3816 *val_len = val_total_len;
3817 if (too_short) {
3818 tracepoint(librbd, metadata_list_exit, -ERANGE);
3819 return -ERANGE;
3820 }
3821
3822 char *key_p = key, *value_p = value;
3823
3824 for (map<string, bufferlist>::iterator it = pairs.begin();
3825 it != pairs.end(); ++it) {
3826 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
3827 key_p += it->first.size() + 1;
3828 strncpy(value_p, it->second.c_str(), it->second.length());
3829 value_p += it->second.length();
3830 *value_p = '\0';
3831 value_p++;
3832 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
3833 }
3834 tracepoint(librbd, metadata_list_exit, r);
3835 return r;
3836 }
3837
3838 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
3839 {
3840 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3841 return librbd::api::Mirror<>::image_enable(ictx, false);
3842 }
3843
3844 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
3845 {
3846 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3847 return librbd::api::Mirror<>::image_disable(ictx, force);
3848 }
3849
3850 extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
3851 {
3852 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3853 return librbd::api::Mirror<>::image_promote(ictx, force);
3854 }
3855
3856 extern "C" int rbd_mirror_image_demote(rbd_image_t image)
3857 {
3858 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3859 return librbd::api::Mirror<>::image_demote(ictx);
3860 }
3861
3862 extern "C" int rbd_mirror_image_resync(rbd_image_t image)
3863 {
3864 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3865 return librbd::api::Mirror<>::image_resync(ictx);
3866 }
3867
3868 extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
3869 rbd_mirror_image_info_t *mirror_image_info,
3870 size_t info_size)
3871 {
3872 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3873
3874 librbd::mirror_image_info_t cpp_mirror_image;
3875 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image,
3876 sizeof(cpp_mirror_image));
3877 if (r < 0) {
3878 return r;
3879 }
3880
3881 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
3882 return 0;
3883 }
3884
3885 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
3886 rbd_mirror_image_status_t *status,
3887 size_t status_size)
3888 {
3889 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3890
3891 librbd::mirror_image_status_t cpp_status;
3892 int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status,
3893 sizeof(cpp_status));
3894 if (r < 0) {
3895 return r;
3896 }
3897
3898 mirror_image_status_cpp_to_c(cpp_status, status);
3899 return 0;
3900 }
3901
3902 extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
3903 rbd_completion_t c) {
3904 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3905 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3906 librbd::api::Mirror<>::image_promote(
3907 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3908 get_aio_completion(comp)));
3909 return 0;
3910 }
3911
3912 extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
3913 rbd_completion_t c) {
3914 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3915 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3916 librbd::api::Mirror<>::image_demote(
3917 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3918 get_aio_completion(comp)));
3919 return 0;
3920 }
3921
3922 extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
3923 rbd_mirror_image_info_t *info,
3924 size_t info_size,
3925 rbd_completion_t c) {
3926 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3927 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3928
3929 if (sizeof(rbd_mirror_image_info_t) > info_size) {
3930 return -ERANGE;
3931 }
3932
3933 auto ctx = new C_MirrorImageGetInfo(
3934 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3935 get_aio_completion(comp)));
3936 librbd::api::Mirror<>::image_get_info(
3937 ictx, &ctx->cpp_mirror_image_info, sizeof(ctx->cpp_mirror_image_info), ctx);
3938 return 0;
3939 }
3940
3941 extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
3942 rbd_mirror_image_status_t *status,
3943 size_t status_size,
3944 rbd_completion_t c) {
3945 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3946 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3947
3948 if (sizeof(rbd_mirror_image_status_t) > status_size) {
3949 return -ERANGE;
3950 }
3951
3952 auto ctx = new C_MirrorImageGetStatus(
3953 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3954 get_aio_completion(comp)));
3955 librbd::api::Mirror<>::image_get_status(
3956 ictx, &ctx->cpp_mirror_image_status, sizeof(ctx->cpp_mirror_image_status),
3957 ctx);
3958 return 0;
3959 }
3960
3961 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
3962 rbd_update_callback_t watch_cb, void *arg)
3963 {
3964 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3965 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
3966 tracepoint(librbd, update_watch_enter, ictx, wctx);
3967 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
3968 tracepoint(librbd, update_watch_exit, r, wctx->handle);
3969 *handle = reinterpret_cast<uint64_t>(wctx);
3970 return r;
3971 }
3972
3973 extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
3974 {
3975 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3976 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
3977 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
3978 int r = ictx->state->unregister_update_watcher(wctx->handle);
3979 delete wctx;
3980 tracepoint(librbd, update_unwatch_exit, r);
3981 return r;
3982 }
3983
3984 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
3985 {
3986 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3987 return comp->is_complete();
3988 }
3989
3990 extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
3991 {
3992 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3993 return comp->wait_for_complete();
3994 }
3995
3996 extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
3997 {
3998 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3999 return comp->get_return_value();
4000 }
4001
4002 extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
4003 {
4004 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4005 return comp->get_arg();
4006 }
4007
4008 extern "C" void rbd_aio_release(rbd_completion_t c)
4009 {
4010 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4011 comp->release();
4012 }
4013