]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/librbd.cc
update sources to v12.1.3
[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 tracepoint(librbd, writesame_exit, -EINVAL);
1512 return -EINVAL;
1513 }
1514
1515 if (mem_is_zero(bl.c_str(), bl.length())) {
1516 int r = ictx->io_work_queue->discard(ofs, len, false);
1517 tracepoint(librbd, writesame_exit, r);
1518 return r;
1519 }
1520
1521 int r = ictx->io_work_queue->writesame(ofs, len, bufferlist{bl}, op_flags);
1522 tracepoint(librbd, writesame_exit, r);
1523 return r;
1524 }
1525
1526 ssize_t Image::compare_and_write(uint64_t ofs, size_t len,
1527 ceph::bufferlist &cmp_bl, ceph::bufferlist& bl,
1528 uint64_t *mismatch_off, int op_flags)
1529 {
1530 ImageCtx *ictx = (ImageCtx *)ctx;
1531 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
1532 ictx->snap_name.c_str(),
1533 ictx->read_only, ofs, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
1534 bl.length() < len ? NULL : bl.c_str(), op_flags);
1535
1536 if (bl.length() < len) {
1537 tracepoint(librbd, write_exit, -EINVAL);
1538 return -EINVAL;
1539 }
1540
1541 int r = ictx->io_work_queue->compare_and_write(ofs, len, bufferlist{cmp_bl},
1542 bufferlist{bl}, mismatch_off,
1543 op_flags);
1544
1545 tracepoint(librbd, compare_and_write_exit, r);
1546
1547 return r;
1548 }
1549 int Image::aio_write(uint64_t off, size_t len, bufferlist& bl,
1550 RBD::AioCompletion *c)
1551 {
1552 ImageCtx *ictx = (ImageCtx *)ctx;
1553 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);
1554 if (bl.length() < len) {
1555 tracepoint(librbd, aio_write_exit, -EINVAL);
1556 return -EINVAL;
1557 }
1558 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1559 bufferlist{bl}, 0);
1560 tracepoint(librbd, aio_write_exit, 0);
1561 return 0;
1562 }
1563
1564 int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
1565 RBD::AioCompletion *c, int op_flags)
1566 {
1567 ImageCtx *ictx = (ImageCtx *)ctx;
1568 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1569 ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1570 if (bl.length() < len) {
1571 tracepoint(librbd, aio_write_exit, -EINVAL);
1572 return -EINVAL;
1573 }
1574 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1575 bufferlist{bl}, op_flags);
1576 tracepoint(librbd, aio_write_exit, 0);
1577 return 0;
1578 }
1579
1580 int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
1581 {
1582 ImageCtx *ictx = (ImageCtx *)ctx;
1583 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
1584 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard);
1585 tracepoint(librbd, aio_discard_exit, 0);
1586 return 0;
1587 }
1588
1589 int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
1590 RBD::AioCompletion *c)
1591 {
1592 ImageCtx *ictx = (ImageCtx *)ctx;
1593 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);
1594 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1595 << (void *)(bl.c_str() + len - 1) << dendl;
1596 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1597 io::ReadResult{&bl}, 0);
1598 tracepoint(librbd, aio_read_exit, 0);
1599 return 0;
1600 }
1601
1602 int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
1603 RBD::AioCompletion *c, int op_flags)
1604 {
1605 ImageCtx *ictx = (ImageCtx *)ctx;
1606 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1607 ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
1608 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1609 << (void *)(bl.c_str() + len - 1) << dendl;
1610 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1611 io::ReadResult{&bl}, op_flags);
1612 tracepoint(librbd, aio_read_exit, 0);
1613 return 0;
1614 }
1615
1616 int Image::flush()
1617 {
1618 ImageCtx *ictx = (ImageCtx *)ctx;
1619 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1620 int r = librbd::flush(ictx);
1621 tracepoint(librbd, flush_exit, r);
1622 return r;
1623 }
1624
1625 int Image::aio_flush(RBD::AioCompletion *c)
1626 {
1627 ImageCtx *ictx = (ImageCtx *)ctx;
1628 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
1629 ictx->io_work_queue->aio_flush(get_aio_completion(c));
1630 tracepoint(librbd, aio_flush_exit, 0);
1631 return 0;
1632 }
1633
1634 int Image::aio_writesame(uint64_t off, size_t len, bufferlist& bl,
1635 RBD::AioCompletion *c, int op_flags)
1636 {
1637 ImageCtx *ictx = (ImageCtx *)ctx;
1638 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1639 ictx->read_only, off, len, bl.length() <= len ? NULL : bl.c_str(), bl.length(),
1640 c->pc, op_flags);
1641 if (bl.length() <= 0 || len % bl.length()) {
1642 tracepoint(librbd, aio_writesame_exit, -EINVAL);
1643 return -EINVAL;
1644 }
1645
1646 if (mem_is_zero(bl.c_str(), bl.length())) {
1647 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false);
1648 tracepoint(librbd, aio_writesame_exit, 0);
1649 return 0;
1650 }
1651
1652 ictx->io_work_queue->aio_writesame(get_aio_completion(c), off, len,
1653 bufferlist{bl}, op_flags);
1654 tracepoint(librbd, aio_writesame_exit, 0);
1655 return 0;
1656 }
1657
1658 int Image::aio_compare_and_write(uint64_t off, size_t len,
1659 ceph::bufferlist& cmp_bl, ceph::bufferlist& bl,
1660 RBD::AioCompletion *c, uint64_t *mismatch_off,
1661 int op_flags)
1662 {
1663 ImageCtx *ictx = (ImageCtx *)ctx;
1664 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(),
1665 ictx->snap_name.c_str(),
1666 ictx->read_only, off, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
1667 bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1668
1669 if (bl.length() < len) {
1670 tracepoint(librbd, compare_and_write_exit, -EINVAL);
1671 return -EINVAL;
1672 }
1673
1674 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(c), off, len,
1675 bufferlist{cmp_bl}, bufferlist{bl},
1676 mismatch_off, op_flags, false);
1677
1678 tracepoint(librbd, aio_compare_and_write_exit, 0);
1679
1680 return 0;
1681 }
1682
1683 int Image::invalidate_cache()
1684 {
1685 ImageCtx *ictx = (ImageCtx *)ctx;
1686 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1687 int r = librbd::invalidate_cache(ictx);
1688 tracepoint(librbd, invalidate_cache_exit, r);
1689 return r;
1690 }
1691
1692 int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp)
1693 {
1694 io::AioCompletion *cs[numcomp];
1695 ImageCtx *ictx = (ImageCtx *)ctx;
1696 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
1697 int r = librbd::poll_io_events(ictx, cs, numcomp);
1698 tracepoint(librbd, poll_io_events_exit, r);
1699 if (r > 0) {
1700 for (int i = 0; i < numcomp; ++i)
1701 comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
1702 }
1703 return r;
1704 }
1705
1706 int Image::metadata_get(const std::string &key, std::string *value)
1707 {
1708 ImageCtx *ictx = (ImageCtx *)ctx;
1709 tracepoint(librbd, metadata_get_enter, ictx, key.c_str());
1710 int r = librbd::metadata_get(ictx, key, value);
1711 if (r < 0) {
1712 tracepoint(librbd, metadata_get_exit, r, key.c_str(), NULL);
1713 } else {
1714 tracepoint(librbd, metadata_get_exit, r, key.c_str(), value->c_str());
1715 }
1716 return r;
1717 }
1718
1719 int Image::metadata_set(const std::string &key, const std::string &value)
1720 {
1721 ImageCtx *ictx = (ImageCtx *)ctx;
1722 tracepoint(librbd, metadata_set_enter, ictx, key.c_str(), value.c_str());
1723 int r = ictx->operations->metadata_set(key, value);
1724 tracepoint(librbd, metadata_set_exit, r);
1725 return r;
1726 }
1727
1728 int Image::metadata_remove(const std::string &key)
1729 {
1730 ImageCtx *ictx = (ImageCtx *)ctx;
1731 tracepoint(librbd, metadata_remove_enter, ictx, key.c_str());
1732 int r = ictx->operations->metadata_remove(key);
1733 tracepoint(librbd, metadata_remove_exit, r);
1734 return r;
1735 }
1736
1737 int Image::metadata_list(const std::string &start, uint64_t max, map<string, bufferlist> *pairs)
1738 {
1739 ImageCtx *ictx = (ImageCtx *)ctx;
1740 tracepoint(librbd, metadata_list_enter, ictx);
1741 int r = librbd::metadata_list(ictx, start, max, pairs);
1742 if (r >= 0) {
1743 for (map<string, bufferlist>::iterator it = pairs->begin();
1744 it != pairs->end(); ++it) {
1745 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
1746 }
1747 }
1748 tracepoint(librbd, metadata_list_exit, r);
1749 return r;
1750 }
1751
1752 int Image::mirror_image_enable() {
1753 ImageCtx *ictx = (ImageCtx *)ctx;
1754 return librbd::api::Mirror<>::image_enable(ictx, false);
1755 }
1756
1757 int Image::mirror_image_disable(bool force) {
1758 ImageCtx *ictx = (ImageCtx *)ctx;
1759 return librbd::api::Mirror<>::image_disable(ictx, force);
1760 }
1761
1762 int Image::mirror_image_promote(bool force) {
1763 ImageCtx *ictx = (ImageCtx *)ctx;
1764 return librbd::api::Mirror<>::image_promote(ictx, force);
1765 }
1766
1767 int Image::mirror_image_demote() {
1768 ImageCtx *ictx = (ImageCtx *)ctx;
1769 return librbd::api::Mirror<>::image_demote(ictx);
1770 }
1771
1772 int Image::mirror_image_resync()
1773 {
1774 ImageCtx *ictx = (ImageCtx *)ctx;
1775 return librbd::api::Mirror<>::image_resync(ictx);
1776 }
1777
1778 int Image::mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1779 size_t info_size) {
1780 ImageCtx *ictx = (ImageCtx *)ctx;
1781 return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info,
1782 info_size);
1783 }
1784
1785 int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
1786 size_t status_size) {
1787 ImageCtx *ictx = (ImageCtx *)ctx;
1788 return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status,
1789 status_size);
1790 }
1791
1792 int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
1793 ImageCtx *ictx = (ImageCtx *)ctx;
1794 librbd::api::Mirror<>::image_promote(
1795 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1796 get_aio_completion(c)));
1797 return 0;
1798 }
1799
1800 int Image::aio_mirror_image_demote(RBD::AioCompletion *c) {
1801 ImageCtx *ictx = (ImageCtx *)ctx;
1802 librbd::api::Mirror<>::image_demote(
1803 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1804 get_aio_completion(c)));
1805 return 0;
1806 }
1807
1808 int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1809 size_t info_size,
1810 RBD::AioCompletion *c) {
1811 ImageCtx *ictx = (ImageCtx *)ctx;
1812 librbd::api::Mirror<>::image_get_info(
1813 ictx, mirror_image_info, info_size,
1814 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1815 get_aio_completion(c)));
1816 return 0;
1817 }
1818
1819 int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
1820 size_t status_size,
1821 RBD::AioCompletion *c) {
1822 ImageCtx *ictx = (ImageCtx *)ctx;
1823 librbd::api::Mirror<>::image_get_status(
1824 ictx, status, status_size,
1825 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1826 get_aio_completion(c)));
1827 return 0;
1828 }
1829
1830 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
1831 ImageCtx *ictx = (ImageCtx *)ctx;
1832 tracepoint(librbd, update_watch_enter, ictx, wctx);
1833 int r = ictx->state->register_update_watcher(wctx, handle);
1834 tracepoint(librbd, update_watch_exit, r, *handle);
1835 return r;
1836 }
1837
1838 int Image::update_unwatch(uint64_t handle) {
1839 ImageCtx *ictx = (ImageCtx *)ctx;
1840 tracepoint(librbd, update_unwatch_enter, ictx, handle);
1841 int r = ictx->state->unregister_update_watcher(handle);
1842 tracepoint(librbd, update_unwatch_exit, r);
1843 return r;
1844 }
1845
1846 } // namespace librbd
1847
1848 extern "C" void rbd_version(int *major, int *minor, int *extra)
1849 {
1850 if (major)
1851 *major = LIBRBD_VER_MAJOR;
1852 if (minor)
1853 *minor = LIBRBD_VER_MINOR;
1854 if (extra)
1855 *extra = LIBRBD_VER_EXTRA;
1856 }
1857
1858 extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
1859 {
1860 librbd::image_options_create(opts);
1861 }
1862
1863 extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
1864 {
1865 librbd::image_options_destroy(opts);
1866 }
1867
1868 extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
1869 const char* optval)
1870 {
1871 return librbd::image_options_set(opts, optname, optval);
1872 }
1873
1874 extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
1875 uint64_t optval)
1876 {
1877 return librbd::image_options_set(opts, optname, optval);
1878 }
1879
1880 extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
1881 char* optval, size_t maxlen)
1882 {
1883 std::string optval_;
1884
1885 int r = librbd::image_options_get(opts, optname, &optval_);
1886
1887 if (r < 0) {
1888 return r;
1889 }
1890
1891 if (optval_.size() >= maxlen) {
1892 return -E2BIG;
1893 }
1894
1895 strncpy(optval, optval_.c_str(), maxlen);
1896
1897 return 0;
1898 }
1899
1900 extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
1901 uint64_t* optval)
1902 {
1903 return librbd::image_options_get(opts, optname, optval);
1904 }
1905
1906 extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
1907 bool* is_set)
1908 {
1909 return librbd::image_options_is_set(opts, optname, is_set);
1910 }
1911
1912 extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
1913 {
1914 return librbd::image_options_unset(opts, optname);
1915 }
1916
1917 extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
1918 {
1919 librbd::image_options_clear(opts);
1920 }
1921
1922 extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
1923 {
1924 return librbd::image_options_is_empty(opts);
1925 }
1926
1927 /* pool mirroring */
1928 extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
1929 rbd_mirror_mode_t *mirror_mode) {
1930 librados::IoCtx io_ctx;
1931 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1932 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
1933 }
1934
1935 extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
1936 rbd_mirror_mode_t mirror_mode) {
1937 librados::IoCtx io_ctx;
1938 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1939 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
1940 }
1941
1942 extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
1943 size_t uuid_max_length,
1944 const char *cluster_name,
1945 const char *client_name) {
1946 static const std::size_t UUID_LENGTH = 36;
1947
1948 librados::IoCtx io_ctx;
1949 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1950
1951 if (uuid_max_length < UUID_LENGTH + 1) {
1952 return -E2BIG;
1953 }
1954
1955 std::string uuid_str;
1956 int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
1957 client_name);
1958 if (r >= 0) {
1959 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
1960 uuid[uuid_max_length - 1] = '\0';
1961 }
1962 return r;
1963 }
1964
1965 extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
1966 librados::IoCtx io_ctx;
1967 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1968 int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
1969 return r;
1970 }
1971
1972 extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
1973 rbd_mirror_peer_t *peers, int *max_peers) {
1974 librados::IoCtx io_ctx;
1975 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1976
1977 std::vector<librbd::mirror_peer_t> peer_vector;
1978 int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
1979 if (r < 0) {
1980 return r;
1981 }
1982
1983 if (*max_peers < static_cast<int>(peer_vector.size())) {
1984 *max_peers = static_cast<int>(peer_vector.size());
1985 return -ERANGE;
1986 }
1987
1988 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
1989 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
1990 peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
1991 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
1992 }
1993 *max_peers = static_cast<int>(peer_vector.size());
1994 return 0;
1995 }
1996
1997 extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
1998 int max_peers) {
1999 for (int i = 0; i < max_peers; ++i) {
2000 free(peers[i].uuid);
2001 free(peers[i].cluster_name);
2002 free(peers[i].client_name);
2003 }
2004 }
2005
2006 extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
2007 const char *client_name) {
2008 librados::IoCtx io_ctx;
2009 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2010 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
2011 }
2012
2013 extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
2014 const char *cluster_name) {
2015 librados::IoCtx io_ctx;
2016 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2017 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
2018 }
2019
2020 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
2021 const char *start_id, size_t max, char **image_ids,
2022 rbd_mirror_image_status_t *images, size_t *len) {
2023 librados::IoCtx io_ctx;
2024 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2025 std::map<std::string, librbd::mirror_image_status_t> cpp_images;
2026
2027 int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
2028 &cpp_images);
2029 if (r < 0) {
2030 return r;
2031 }
2032
2033 size_t i = 0;
2034 for (auto &it : cpp_images) {
2035 assert(i < max);
2036 const std::string &image_id = it.first;
2037 image_ids[i] = strdup(image_id.c_str());
2038 mirror_image_status_cpp_to_c(it.second, &images[i]);
2039 i++;
2040 }
2041 *len = i;
2042 return 0;
2043 }
2044
2045 extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
2046 rbd_mirror_image_status_t *images, size_t len) {
2047 for (size_t i = 0; i < len; i++) {
2048 free(image_ids[i]);
2049 free(images[i].name);
2050 free(images[i].info.global_id);
2051 free(images[i].description);
2052 }
2053 }
2054
2055 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
2056 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
2057
2058 librados::IoCtx io_ctx;
2059 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2060
2061 std::map<librbd::mirror_image_status_state_t, int> states_;
2062 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
2063 if (r < 0) {
2064 return r;
2065 }
2066
2067 size_t i = 0;
2068 for (auto &it : states_) {
2069 if (i == *maxlen) {
2070 return -ERANGE;
2071 }
2072 states[i] = it.first;
2073 counts[i] = it.second;
2074 i++;
2075 }
2076 *maxlen = i;
2077 return 0;
2078 }
2079
2080 /* images */
2081 extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
2082 {
2083 librados::IoCtx io_ctx;
2084 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2085 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2086 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2087 vector<string> cpp_names;
2088 int r = librbd::list(io_ctx, cpp_names);
2089 if (r < 0) {
2090 tracepoint(librbd, list_exit, r, *size);
2091 return r;
2092 }
2093
2094 size_t expected_size = 0;
2095
2096 for (size_t i = 0; i < cpp_names.size(); i++) {
2097 expected_size += cpp_names[i].size() + 1;
2098 }
2099 if (*size < expected_size) {
2100 *size = expected_size;
2101 tracepoint(librbd, list_exit, -ERANGE, *size);
2102 return -ERANGE;
2103 }
2104
2105 if (!names)
2106 return -EINVAL;
2107
2108 for (int i = 0; i < (int)cpp_names.size(); i++) {
2109 const char* name = cpp_names[i].c_str();
2110 tracepoint(librbd, list_entry, name);
2111 strcpy(names, name);
2112 names += strlen(names) + 1;
2113 }
2114 tracepoint(librbd, list_exit, (int)expected_size, *size);
2115 return (int)expected_size;
2116 }
2117
2118 extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
2119 {
2120 librados::IoCtx io_ctx;
2121 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2122 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2123 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
2124 int r = librbd::create(io_ctx, name, size, order);
2125 tracepoint(librbd, create_exit, r, *order);
2126 return r;
2127 }
2128
2129 extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
2130 uint64_t size, uint64_t features,
2131 int *order)
2132 {
2133 librados::IoCtx io_ctx;
2134 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2135 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2136 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
2137 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
2138 tracepoint(librbd, create2_exit, r, *order);
2139 return r;
2140 }
2141
2142 extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
2143 uint64_t size, uint64_t features,
2144 int *order,
2145 uint64_t stripe_unit, uint64_t stripe_count)
2146 {
2147 librados::IoCtx io_ctx;
2148 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2149 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2150 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
2151 int r = librbd::create(io_ctx, name, size, false, features, order,
2152 stripe_unit, stripe_count);
2153 tracepoint(librbd, create3_exit, r, *order);
2154 return r;
2155 }
2156
2157 extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
2158 uint64_t size, rbd_image_options_t opts)
2159 {
2160 librados::IoCtx io_ctx;
2161 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2162 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2163 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
2164 librbd::ImageOptions opts_(opts);
2165 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
2166 tracepoint(librbd, create4_exit, r);
2167 return r;
2168 }
2169
2170 extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
2171 const char *p_snap_name, rados_ioctx_t c_ioctx,
2172 const char *c_name, uint64_t features, int *c_order)
2173 {
2174 librados::IoCtx p_ioc, c_ioc;
2175 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2176 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2177 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2178 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);
2179 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2180 features, c_order, 0, 0);
2181 tracepoint(librbd, clone_exit, r, *c_order);
2182 return r;
2183 }
2184
2185 extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
2186 const char *p_snap_name, rados_ioctx_t c_ioctx,
2187 const char *c_name, uint64_t features, int *c_order,
2188 uint64_t stripe_unit, int stripe_count)
2189 {
2190 librados::IoCtx p_ioc, c_ioc;
2191 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2192 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2193 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2194 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);
2195 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2196 features, c_order, stripe_unit, stripe_count);
2197 tracepoint(librbd, clone2_exit, r, *c_order);
2198 return r;
2199 }
2200
2201 extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
2202 const char *p_snap_name, rados_ioctx_t c_ioctx,
2203 const char *c_name, rbd_image_options_t c_opts)
2204 {
2205 librados::IoCtx p_ioc, c_ioc;
2206 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2207 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2208 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2209 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);
2210 librbd::ImageOptions c_opts_(c_opts);
2211 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_);
2212 tracepoint(librbd, clone3_exit, r);
2213 return r;
2214 }
2215
2216 extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
2217 {
2218 librados::IoCtx io_ctx;
2219 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2220 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2221 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2222 librbd::NoOpProgressContext prog_ctx;
2223 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2224 tracepoint(librbd, remove_exit, r);
2225 return r;
2226 }
2227
2228 extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
2229 librbd_progress_fn_t cb, void *cbdata)
2230 {
2231 librados::IoCtx io_ctx;
2232 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2233 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2234 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2235 librbd::CProgressContext prog_ctx(cb, cbdata);
2236 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2237 tracepoint(librbd, remove_exit, r);
2238 return r;
2239 }
2240
2241 extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
2242 uint64_t delay) {
2243 librados::IoCtx io_ctx;
2244 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2245 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2246 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
2247 io_ctx.get_id(), name);
2248 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, delay);
2249 tracepoint(librbd, trash_move_exit, r);
2250 return r;
2251 }
2252
2253 extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
2254 rbd_trash_image_info_t *info) {
2255 librados::IoCtx io_ctx;
2256 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
2257
2258 librbd::trash_image_info_t cpp_info;
2259 int r = librbd::trash_get(io_ctx, id, &cpp_info);
2260 if (r < 0) {
2261 return r;
2262 }
2263
2264 trash_image_info_cpp_to_c(cpp_info, info);
2265 return 0;
2266 }
2267
2268 extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
2269 free(info->id);
2270 free(info->name);
2271 }
2272
2273 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
2274 size_t *num_entries) {
2275 librados::IoCtx io_ctx;
2276 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2277 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2278 tracepoint(librbd, trash_list_enter,
2279 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2280
2281 vector<librbd::trash_image_info_t> cpp_entries;
2282 int r = librbd::trash_list(io_ctx, cpp_entries);
2283 if (r < 0) {
2284 tracepoint(librbd, trash_list_exit, r, *num_entries);
2285 return r;
2286 }
2287
2288 if (*num_entries < cpp_entries.size()) {
2289 *num_entries = cpp_entries.size();
2290 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
2291 return -ERANGE;
2292 }
2293
2294 int i=0;
2295 for (const auto &entry : cpp_entries) {
2296 trash_image_info_cpp_to_c(entry, &entries[i++]);
2297 }
2298 *num_entries = cpp_entries.size();
2299
2300 return *num_entries;
2301 }
2302
2303 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
2304 size_t num_entries) {
2305 for (size_t i=0; i < num_entries; i++) {
2306 rbd_trash_get_cleanup(&entries[i]);
2307 }
2308 }
2309
2310 extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
2311 bool force) {
2312 librados::IoCtx io_ctx;
2313 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2314 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2315 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2316 io_ctx.get_id(), image_id, force);
2317 librbd::NoOpProgressContext prog_ctx;
2318 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2319 tracepoint(librbd, trash_remove_exit, r);
2320 return r;
2321 }
2322
2323 extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
2324 const char *image_id,
2325 bool force,
2326 librbd_progress_fn_t cb,
2327 void *cbdata) {
2328 librados::IoCtx io_ctx;
2329 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2330 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2331 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2332 io_ctx.get_id(), image_id, force);
2333 librbd::CProgressContext prog_ctx(cb, cbdata);
2334 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2335 tracepoint(librbd, trash_remove_exit, r);
2336 return r;
2337 }
2338
2339 extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
2340 const char *name) {
2341 librados::IoCtx io_ctx;
2342 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2343 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2344 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
2345 io_ctx.get_id(), id, name);
2346 int r = librbd::trash_restore(io_ctx, id, name);
2347 tracepoint(librbd, trash_undelete_exit, r);
2348 return r;
2349 }
2350
2351 extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
2352 const char *destname)
2353 {
2354 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2355 librados::IoCtx dest_io_ctx;
2356 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2357 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);
2358 librbd::ImageOptions opts;
2359 librbd::NoOpProgressContext prog_ctx;
2360 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2361 tracepoint(librbd, copy_exit, r);
2362 return r;
2363 }
2364
2365 extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
2366 {
2367 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2368 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2369 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);
2370 librbd::NoOpProgressContext prog_ctx;
2371 int r = librbd::copy(src, dest, prog_ctx, 0);
2372 tracepoint(librbd, copy2_exit, r);
2373 return r;
2374 }
2375
2376 extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
2377 const char *destname, rbd_image_options_t c_opts)
2378 {
2379 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2380 librados::IoCtx dest_io_ctx;
2381 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2382 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);
2383 librbd::ImageOptions c_opts_(c_opts);
2384 librbd::NoOpProgressContext prog_ctx;
2385 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
2386 tracepoint(librbd, copy3_exit, r);
2387 return r;
2388 }
2389
2390 extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
2391 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
2392 {
2393 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2394 librados::IoCtx dest_io_ctx;
2395 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2396 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);
2397 librbd::ImageOptions c_opts_(c_opts);
2398 librbd::NoOpProgressContext prog_ctx;
2399 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
2400 tracepoint(librbd, copy4_exit, r);
2401 return r;
2402 }
2403
2404 extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
2405 const char *destname,
2406 librbd_progress_fn_t fn, void *data)
2407 {
2408 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2409 librados::IoCtx dest_io_ctx;
2410 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2411 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);
2412 librbd::ImageOptions opts;
2413 librbd::CProgressContext prog_ctx(fn, data);
2414 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2415 tracepoint(librbd, copy_exit, ret);
2416 return ret;
2417 }
2418
2419 extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
2420 librbd_progress_fn_t fn, void *data)
2421 {
2422 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2423 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2424 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);
2425 librbd::CProgressContext prog_ctx(fn, data);
2426 int ret = librbd::copy(src, dest, prog_ctx, 0);
2427 tracepoint(librbd, copy2_exit, ret);
2428 return ret;
2429 }
2430
2431 extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
2432 const char *destname,
2433 rbd_image_options_t dest_opts,
2434 librbd_progress_fn_t fn, void *data)
2435 {
2436 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2437 librados::IoCtx dest_io_ctx;
2438 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2439 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);
2440 librbd::ImageOptions dest_opts_(dest_opts);
2441 librbd::CProgressContext prog_ctx(fn, data);
2442 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
2443 tracepoint(librbd, copy3_exit, ret);
2444 return ret;
2445 }
2446
2447 extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
2448 const char *destname,
2449 rbd_image_options_t dest_opts,
2450 librbd_progress_fn_t fn, void *data, size_t sparse_size)
2451 {
2452 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2453 librados::IoCtx dest_io_ctx;
2454 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2455 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);
2456 librbd::ImageOptions dest_opts_(dest_opts);
2457 librbd::CProgressContext prog_ctx(fn, data);
2458 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
2459 tracepoint(librbd, copy4_exit, ret);
2460 return ret;
2461 }
2462
2463
2464 extern "C" int rbd_flatten(rbd_image_t image)
2465 {
2466 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2467 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2468 librbd::NoOpProgressContext prog_ctx;
2469 int r = ictx->operations->flatten(prog_ctx);
2470 tracepoint(librbd, flatten_exit, r);
2471 return r;
2472 }
2473
2474 extern "C" int rbd_flatten_with_progress(rbd_image_t image,
2475 librbd_progress_fn_t cb, void *cbdata)
2476 {
2477 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2478 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2479 librbd::CProgressContext prog_ctx(cb, cbdata);
2480 int r = ictx->operations->flatten(prog_ctx);
2481 tracepoint(librbd, flatten_exit, r);
2482 return r;
2483 }
2484
2485 extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
2486 const char *destname)
2487 {
2488 librados::IoCtx src_io_ctx;
2489 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
2490 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
2491 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
2492 int r = librbd::rename(src_io_ctx, srcname, destname);
2493 tracepoint(librbd, rename_exit, r);
2494 return r;
2495 }
2496
2497 extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
2498 const char *snap_name)
2499 {
2500 librados::IoCtx io_ctx;
2501 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2502 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2503 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2504 false);
2505 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2506
2507 int r = ictx->state->open(false);
2508 if (r >= 0) {
2509 *image = (rbd_image_t)ictx;
2510 }
2511 tracepoint(librbd, open_image_exit, r);
2512 return r;
2513 }
2514
2515 extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
2516 rbd_image_t *image, const char *snap_name)
2517 {
2518 librados::IoCtx io_ctx;
2519 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2520 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2521 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2522 false);
2523 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2524 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2525
2526 int r = ictx->state->open(false);
2527 if (r < 0) {
2528 delete ictx;
2529 } else {
2530 *image = (rbd_image_t)ictx;
2531 }
2532 tracepoint(librbd, open_image_exit, r);
2533 return r;
2534 }
2535
2536 extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
2537 rbd_image_t *image, const char *snap_name,
2538 rbd_completion_t c)
2539 {
2540 librados::IoCtx io_ctx;
2541 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2542 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2543 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2544 false);
2545 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2546 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);
2547 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2548 tracepoint(librbd, aio_open_image_exit, 0);
2549 return 0;
2550 }
2551
2552 extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
2553 rbd_image_t *image, const char *snap_name,
2554 rbd_completion_t c)
2555 {
2556 librados::IoCtx io_ctx;
2557 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2558 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2559 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2560 false);
2561 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2562 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2563 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
2564 comp->pc);
2565 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2566 tracepoint(librbd, aio_open_image_exit, 0);
2567 return 0;
2568 }
2569
2570 extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
2571 rbd_image_t *image, const char *snap_name)
2572 {
2573 librados::IoCtx io_ctx;
2574 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2575 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2576 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2577 true);
2578 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2579
2580 int r = ictx->state->open(false);
2581 if (r >= 0) {
2582 *image = (rbd_image_t)ictx;
2583 }
2584 tracepoint(librbd, open_image_exit, r);
2585 return r;
2586 }
2587
2588 extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
2589 rbd_image_t *image, const char *snap_name)
2590 {
2591 librados::IoCtx io_ctx;
2592 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2593 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2594 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2595 true);
2596 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2597 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2598
2599 int r = ictx->state->open(false);
2600 if (r < 0) {
2601 delete ictx;
2602 } else {
2603 *image = (rbd_image_t)ictx;
2604 }
2605 tracepoint(librbd, open_image_exit, r);
2606 return r;
2607 }
2608
2609 extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
2610 rbd_image_t *image, const char *snap_name,
2611 rbd_completion_t c)
2612 {
2613 librados::IoCtx io_ctx;
2614 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2615 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2616 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2617 true);
2618 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2619 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);
2620 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2621 image));
2622 tracepoint(librbd, aio_open_image_exit, 0);
2623 return 0;
2624 }
2625
2626 extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
2627 rbd_image_t *image,
2628 const char *snap_name,
2629 rbd_completion_t c)
2630 {
2631 librados::IoCtx io_ctx;
2632 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2633 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2634 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2635 true);
2636 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2637 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2638 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2639 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2640 image));
2641 tracepoint(librbd, aio_open_image_exit, 0);
2642 return 0;
2643 }
2644
2645 extern "C" int rbd_close(rbd_image_t image)
2646 {
2647 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2648 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2649
2650 int r = ictx->state->close();
2651
2652 tracepoint(librbd, close_image_exit, r);
2653 return r;
2654 }
2655
2656 extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
2657 {
2658 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2659 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2660 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
2661 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
2662 get_aio_completion(comp)));
2663 tracepoint(librbd, aio_close_image_exit, 0);
2664 return 0;
2665 }
2666
2667 extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
2668 {
2669 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2670 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2671 librbd::NoOpProgressContext prog_ctx;
2672 int r = ictx->operations->resize(size, true, prog_ctx);
2673 tracepoint(librbd, resize_exit, r);
2674 return r;
2675 }
2676
2677 extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
2678 librbd_progress_fn_t cb, void *cbdata)
2679 {
2680 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2681 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2682 librbd::CProgressContext prog_ctx(cb, cbdata);
2683 int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
2684 tracepoint(librbd, resize_exit, r);
2685 return r;
2686 }
2687
2688 extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
2689 librbd_progress_fn_t cb, void *cbdata)
2690 {
2691 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2692 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2693 librbd::CProgressContext prog_ctx(cb, cbdata);
2694 int r = ictx->operations->resize(size, true, prog_ctx);
2695 tracepoint(librbd, resize_exit, r);
2696 return r;
2697 }
2698
2699 extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
2700 size_t infosize)
2701 {
2702 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2703 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2704 int r = librbd::info(ictx, *info, infosize);
2705 tracepoint(librbd, stat_exit, r, info);
2706 return r;
2707 }
2708
2709 extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
2710 {
2711 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2712 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2713 int r = librbd::get_old_format(ictx, old);
2714 tracepoint(librbd, get_old_format_exit, r, *old);
2715 return r;
2716 }
2717
2718 extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
2719 {
2720 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2721 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2722 int r = librbd::get_size(ictx, size);
2723 tracepoint(librbd, get_size_exit, r, *size);
2724 return r;
2725 }
2726
2727 extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
2728 {
2729 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2730 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2731 int r = librbd::get_features(ictx, features);
2732 tracepoint(librbd, get_features_exit, r, *features);
2733 return r;
2734 }
2735
2736 extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
2737 uint8_t enabled)
2738 {
2739 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2740 bool features_enabled = enabled != 0;
2741 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
2742 int r = ictx->operations->update_features(features, features_enabled);
2743 tracepoint(librbd, update_features_exit, r);
2744 return r;
2745 }
2746
2747 extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
2748 {
2749 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2750 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2751 *stripe_unit = ictx->get_stripe_unit();
2752 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
2753 return 0;
2754 }
2755
2756 extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
2757 {
2758 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2759 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2760 *stripe_count = ictx->get_stripe_count();
2761 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
2762 return 0;
2763 }
2764
2765 extern "C" int rbd_get_create_timestamp(rbd_image_t image,
2766 struct timespec *timestamp)
2767 {
2768 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2769 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
2770 ictx->read_only);
2771 utime_t time = ictx->get_create_timestamp();
2772 time.to_timespec(timestamp);
2773 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
2774 return 0;
2775 }
2776
2777 extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
2778 {
2779 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2780 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2781 int r = librbd::get_overlap(ictx, overlap);
2782 tracepoint(librbd, get_overlap_exit, r, *overlap);
2783 return r;
2784 }
2785
2786 extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
2787 {
2788 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2789 if (ictx->old_format) {
2790 return -EINVAL;
2791 }
2792 if (ictx->id.size() >= id_len) {
2793 return -ERANGE;
2794 }
2795
2796 strncpy(id, ictx->id.c_str(), id_len - 1);
2797 id[id_len - 1] = '\0';
2798 return 0;
2799 }
2800
2801 extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
2802 size_t prefix_len)
2803 {
2804 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2805 if (ictx->object_prefix.size() >= prefix_len) {
2806 return -ERANGE;
2807 }
2808
2809 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
2810 prefix[prefix_len - 1] = '\0';
2811 return 0;
2812 }
2813
2814 extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
2815 {
2816 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2817 return ictx->data_ctx.get_id();
2818 }
2819
2820 extern "C" int rbd_get_parent_info(rbd_image_t image,
2821 char *parent_pool_name, size_t ppool_namelen,
2822 char *parent_name, size_t pnamelen,
2823 char *parent_snap_name, size_t psnap_namelen)
2824 {
2825 return rbd_get_parent_info2(image, parent_pool_name, ppool_namelen,
2826 parent_name, pnamelen, nullptr, 0,
2827 parent_snap_name, psnap_namelen);
2828 }
2829
2830 extern "C" int rbd_get_parent_info2(rbd_image_t image,
2831 char *parent_pool_name,
2832 size_t ppool_namelen,
2833 char *parent_name, size_t pnamelen,
2834 char *parent_id, size_t pidlen,
2835 char *parent_snap_name,
2836 size_t psnap_namelen)
2837 {
2838 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2839 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
2840 ictx->snap_name.c_str(), ictx->read_only);
2841 string p_pool_name, p_name, p_id, p_snap_name;
2842
2843 int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_id,
2844 &p_snap_name);
2845 if (r < 0) {
2846 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
2847 return r;
2848 }
2849
2850 if (parent_pool_name) {
2851 if (p_pool_name.length() + 1 > ppool_namelen) {
2852 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2853 return -ERANGE;
2854 }
2855
2856 strcpy(parent_pool_name, p_pool_name.c_str());
2857 }
2858 if (parent_name) {
2859 if (p_name.length() + 1 > pnamelen) {
2860 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2861 return -ERANGE;
2862 }
2863
2864 strcpy(parent_name, p_name.c_str());
2865 }
2866 if (parent_id) {
2867 if (p_id.length() + 1 > pidlen) {
2868 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2869 return -ERANGE;
2870 }
2871
2872 strcpy(parent_id, p_id.c_str());
2873 }
2874 if (parent_snap_name) {
2875 if (p_snap_name.length() + 1 > psnap_namelen) {
2876 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2877 return -ERANGE;
2878 }
2879
2880 strcpy(parent_snap_name, p_snap_name.c_str());
2881 }
2882
2883 tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name,
2884 parent_id, parent_snap_name);
2885 return 0;
2886 }
2887
2888 extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
2889 {
2890 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2891 tracepoint(librbd, get_flags_enter, ictx);
2892 int r = librbd::get_flags(ictx, flags);
2893 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
2894 return r;
2895 }
2896
2897 extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
2898 {
2899 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2900 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
2901 int r = librbd::set_image_notification(ictx, fd, type);
2902 tracepoint(librbd, set_image_notification_exit, ictx, r);
2903 return r;
2904 }
2905
2906 extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
2907 {
2908 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2909 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
2910 bool owner;
2911 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
2912 *is_owner = owner ? 1 : 0;
2913 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
2914 return r;
2915 }
2916
2917 extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
2918 {
2919 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2920 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
2921 int r = librbd::lock_acquire(ictx, lock_mode);
2922 tracepoint(librbd, lock_acquire_exit, ictx, r);
2923 return r;
2924 }
2925
2926 extern "C" int rbd_lock_release(rbd_image_t image)
2927 {
2928 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2929 tracepoint(librbd, lock_release_enter, ictx);
2930 int r = librbd::lock_release(ictx);
2931 tracepoint(librbd, lock_release_exit, ictx, r);
2932 return r;
2933 }
2934
2935 extern "C" int rbd_lock_get_owners(rbd_image_t image,
2936 rbd_lock_mode_t *lock_mode,
2937 char **lock_owners,
2938 size_t *max_lock_owners)
2939 {
2940 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2941 tracepoint(librbd, lock_get_owners_enter, ictx);
2942 std::list<std::string> lock_owner_list;
2943 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
2944 if (r >= 0) {
2945 if (*max_lock_owners >= lock_owner_list.size()) {
2946 *max_lock_owners = 0;
2947 for (auto &lock_owner : lock_owner_list) {
2948 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
2949 }
2950 } else {
2951 *max_lock_owners = lock_owner_list.size();
2952 r = -ERANGE;
2953 }
2954 }
2955 tracepoint(librbd, lock_get_owners_exit, ictx, r);
2956 return r;
2957 }
2958
2959 extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
2960 size_t lock_owner_count)
2961 {
2962 for (size_t i = 0; i < lock_owner_count; ++i) {
2963 free(lock_owners[i]);
2964 }
2965 }
2966
2967 extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
2968 const char *lock_owner)
2969 {
2970 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2971 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
2972 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
2973 tracepoint(librbd, lock_break_exit, ictx, r);
2974 return r;
2975 }
2976
2977 extern "C" int rbd_rebuild_object_map(rbd_image_t image,
2978 librbd_progress_fn_t cb, void *cbdata)
2979 {
2980 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2981 librbd::CProgressContext prog_ctx(cb, cbdata);
2982 return ictx->operations->rebuild_object_map(prog_ctx);
2983 }
2984
2985 /* snapshots */
2986 extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
2987 {
2988 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2989 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
2990 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
2991 snap_name);
2992 tracepoint(librbd, snap_create_exit, r);
2993 return r;
2994 }
2995
2996 extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
2997 {
2998 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2999 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
3000 int r = ictx->operations->snap_rename(srcname, dstname);
3001 tracepoint(librbd, snap_rename_exit, r);
3002 return r;
3003 }
3004
3005 extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
3006 {
3007 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3008 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3009 librbd::NoOpProgressContext prog_ctx;
3010 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
3011 tracepoint(librbd, snap_remove_exit, r);
3012 return r;
3013 }
3014
3015 extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
3016 librbd_progress_fn_t cb, void *cbdata)
3017 {
3018 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3019 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
3020 librbd::CProgressContext prog_ctx(cb, cbdata);
3021 int r = librbd::snap_remove(ictx, snap_name, flags, prog_ctx);
3022 tracepoint(librbd, snap_remove_exit, r);
3023 return r;
3024 }
3025
3026 extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
3027 {
3028 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3029 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3030 librbd::NoOpProgressContext prog_ctx;
3031 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3032 tracepoint(librbd, snap_rollback_exit, r);
3033 return r;
3034 }
3035
3036 extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
3037 const char *snap_name,
3038 librbd_progress_fn_t cb,
3039 void *cbdata)
3040 {
3041 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3042 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3043 librbd::CProgressContext prog_ctx(cb, cbdata);
3044 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3045 tracepoint(librbd, snap_rollback_exit, r);
3046 return r;
3047 }
3048
3049 extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
3050 int *max_snaps)
3051 {
3052 vector<librbd::snap_info_t> cpp_snaps;
3053 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3054 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
3055
3056 if (!max_snaps) {
3057 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
3058 return -EINVAL;
3059 }
3060
3061 int r = librbd::snap_list(ictx, cpp_snaps);
3062 if (r == -ENOENT) {
3063 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
3064 return 0;
3065 }
3066 if (r < 0) {
3067 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3068 return r;
3069 }
3070 if (*max_snaps < (int)cpp_snaps.size() + 1) {
3071 *max_snaps = (int)cpp_snaps.size() + 1;
3072 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
3073 return -ERANGE;
3074 }
3075
3076 int i;
3077
3078 for (i = 0; i < (int)cpp_snaps.size(); i++) {
3079 snaps[i].id = cpp_snaps[i].id;
3080 snaps[i].size = cpp_snaps[i].size;
3081 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
3082 if (!snaps[i].name) {
3083 for (int j = 0; j < i; j++)
3084 free((void *)snaps[j].name);
3085 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
3086 return -ENOMEM;
3087 }
3088 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
3089 }
3090 snaps[i].id = 0;
3091 snaps[i].size = 0;
3092 snaps[i].name = NULL;
3093
3094 r = (int)cpp_snaps.size();
3095 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3096 return r;
3097 }
3098
3099 extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
3100 {
3101 tracepoint(librbd, snap_list_end_enter, snaps);
3102 while (snaps->name) {
3103 free((void *)snaps->name);
3104 snaps++;
3105 }
3106 tracepoint(librbd, snap_list_end_exit);
3107 }
3108
3109 extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
3110 {
3111 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3112 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3113 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
3114 tracepoint(librbd, snap_protect_exit, r);
3115 return r;
3116 }
3117
3118 extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
3119 {
3120 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3121 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3122 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
3123 tracepoint(librbd, snap_unprotect_exit, r);
3124 return r;
3125 }
3126
3127 extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
3128 int *is_protected)
3129 {
3130 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3131 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3132 bool protected_snap;
3133 int r = librbd::snap_is_protected(ictx, snap_name, &protected_snap);
3134 if (r < 0) {
3135 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
3136 return r;
3137 }
3138 *is_protected = protected_snap ? 1 : 0;
3139 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
3140 return 0;
3141 }
3142
3143 extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
3144 {
3145 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3146 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
3147 int r = librbd::snap_get_limit(ictx, limit);
3148 tracepoint(librbd, snap_get_limit_exit, r, *limit);
3149 return r;
3150 }
3151
3152 extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
3153 {
3154 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3155 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
3156 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
3157 tracepoint(librbd, snap_get_timestamp_exit, r);
3158 return r;
3159 }
3160
3161 extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
3162 {
3163 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3164 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
3165 int r = librbd::snap_set_limit(ictx, limit);
3166 tracepoint(librbd, snap_set_limit_exit, r);
3167 return r;
3168 }
3169
3170 extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
3171 {
3172 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3173 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3174 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
3175 tracepoint(librbd, snap_set_exit, r);
3176 return r;
3177 }
3178
3179 extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
3180 size_t *pools_len, char *images,
3181 size_t *images_len)
3182 {
3183 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3184 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3185 set<pair<string, string> > image_set;
3186
3187 int r = librbd::list_children(ictx, image_set);
3188 if (r < 0) {
3189 tracepoint(librbd, list_children_exit, r);
3190 return r;
3191 }
3192
3193 size_t pools_total = 0;
3194 size_t images_total = 0;
3195 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3196 it != image_set.end(); ++it) {
3197 pools_total += it->first.length() + 1;
3198 images_total += it->second.length() + 1;
3199 }
3200
3201 bool too_short = false;
3202 if (pools_total > *pools_len)
3203 too_short = true;
3204 if (images_total > *images_len)
3205 too_short = true;
3206 *pools_len = pools_total;
3207 *images_len = images_total;
3208 if (too_short) {
3209 tracepoint(librbd, list_children_exit, -ERANGE);
3210 return -ERANGE;
3211 }
3212
3213 char *pools_p = pools;
3214 char *images_p = images;
3215 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3216 it != image_set.end(); ++it) {
3217 const char* pool = it->first.c_str();
3218 strcpy(pools_p, pool);
3219 pools_p += it->first.length() + 1;
3220 const char* image = it->second.c_str();
3221 strcpy(images_p, image);
3222 images_p += it->second.length() + 1;
3223 tracepoint(librbd, list_children_entry, pool, image);
3224 }
3225
3226 ssize_t ret = image_set.size();
3227 tracepoint(librbd, list_children_exit, ret);
3228 return ret;
3229 }
3230
3231 extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
3232 char *tag, size_t *tag_len,
3233 char *clients, size_t *clients_len,
3234 char *cookies, size_t *cookies_len,
3235 char *addrs, size_t *addrs_len)
3236 {
3237 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3238 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3239 std::list<librbd::locker_t> lockers;
3240 bool exclusive_bool;
3241 string tag_str;
3242
3243 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
3244 if (r < 0) {
3245 tracepoint(librbd, list_lockers_exit, r);
3246 return r;
3247 }
3248
3249 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
3250
3251 *exclusive = (int)exclusive_bool;
3252 size_t clients_total = 0;
3253 size_t cookies_total = 0;
3254 size_t addrs_total = 0;
3255 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3256 it != lockers.end(); ++it) {
3257 clients_total += it->client.length() + 1;
3258 cookies_total += it->cookie.length() + 1;
3259 addrs_total += it->address.length() + 1;
3260 }
3261
3262 bool too_short = ((clients_total > *clients_len) ||
3263 (cookies_total > *cookies_len) ||
3264 (addrs_total > *addrs_len) ||
3265 (tag_str.length() + 1 > *tag_len));
3266 *clients_len = clients_total;
3267 *cookies_len = cookies_total;
3268 *addrs_len = addrs_total;
3269 *tag_len = tag_str.length() + 1;
3270 if (too_short) {
3271 tracepoint(librbd, list_lockers_exit, -ERANGE);
3272 return -ERANGE;
3273 }
3274
3275 strcpy(tag, tag_str.c_str());
3276 char *clients_p = clients;
3277 char *cookies_p = cookies;
3278 char *addrs_p = addrs;
3279 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3280 it != lockers.end(); ++it) {
3281 const char* client = it->client.c_str();
3282 strcpy(clients_p, client);
3283 clients_p += it->client.length() + 1;
3284 const char* cookie = it->cookie.c_str();
3285 strcpy(cookies_p, cookie);
3286 cookies_p += it->cookie.length() + 1;
3287 const char* address = it->address.c_str();
3288 strcpy(addrs_p, address);
3289 addrs_p += it->address.length() + 1;
3290 tracepoint(librbd, list_lockers_entry, client, cookie, address);
3291 }
3292
3293 ssize_t ret = lockers.size();
3294 tracepoint(librbd, list_lockers_exit, ret);
3295 return ret;
3296 }
3297
3298 extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
3299 {
3300 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3301 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3302 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
3303 tracepoint(librbd, lock_exclusive_exit, r);
3304 return r;
3305 }
3306
3307 extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
3308 const char *tag)
3309 {
3310 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3311 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
3312 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
3313 tracepoint(librbd, lock_shared_exit, r);
3314 return r;
3315 }
3316
3317 extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
3318 {
3319 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3320 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3321 int r = librbd::unlock(ictx, cookie ? cookie : "");
3322 tracepoint(librbd, unlock_exit, r);
3323 return r;
3324 }
3325
3326 extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
3327 const char *cookie)
3328 {
3329 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3330 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
3331 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
3332 tracepoint(librbd, break_lock_exit, r);
3333 return r;
3334 }
3335
3336 /* I/O */
3337 extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
3338 char *buf)
3339 {
3340 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3341 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3342 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3343 0);
3344 tracepoint(librbd, read_exit, r);
3345 return r;
3346 }
3347
3348 extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
3349 char *buf, int op_flags)
3350 {
3351 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3352 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
3353 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
3354 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3355 op_flags);
3356 tracepoint(librbd, read_exit, r);
3357 return r;
3358 }
3359
3360
3361 extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_t len,
3362 int (*cb)(uint64_t, size_t, const char *, void *),
3363 void *arg)
3364 {
3365 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3366 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3367 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3368 tracepoint(librbd, read_iterate_exit, r);
3369 return r;
3370 }
3371
3372 extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
3373 int (*cb)(uint64_t, size_t, const char *, void *),
3374 void *arg)
3375 {
3376 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3377 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3378 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3379 if (r > 0)
3380 r = 0;
3381 tracepoint(librbd, read_iterate2_exit, r);
3382 return (int)r;
3383 }
3384
3385 extern "C" int rbd_diff_iterate(rbd_image_t image,
3386 const char *fromsnapname,
3387 uint64_t ofs, uint64_t len,
3388 int (*cb)(uint64_t, size_t, int, void *),
3389 void *arg)
3390 {
3391 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3392 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3393 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3394 true, false);
3395 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3396 cls::rbd::UserSnapshotNamespace(),
3397 fromsnapname, ofs, len,
3398 true, false, cb, arg);
3399 tracepoint(librbd, diff_iterate_exit, r);
3400 return r;
3401 }
3402
3403 extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
3404 uint64_t ofs, uint64_t len,
3405 uint8_t include_parent, uint8_t whole_object,
3406 int (*cb)(uint64_t, size_t, int, void *),
3407 void *arg)
3408 {
3409 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3410 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3411 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3412 include_parent != 0, whole_object != 0);
3413 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3414 cls::rbd::UserSnapshotNamespace(),
3415 fromsnapname, ofs, len,
3416 include_parent, whole_object,
3417 cb, arg);
3418 tracepoint(librbd, diff_iterate_exit, r);
3419 return r;
3420 }
3421
3422 extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
3423 const char *buf)
3424 {
3425 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3426 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
3427
3428 bufferlist bl;
3429 bl.push_back(create_write_raw(ictx, buf, len));
3430 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
3431 tracepoint(librbd, write_exit, r);
3432 return r;
3433 }
3434
3435 extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
3436 const char *buf, int op_flags)
3437 {
3438 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3439 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
3440 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
3441
3442 bufferlist bl;
3443 bl.push_back(create_write_raw(ictx, buf, len));
3444 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
3445 tracepoint(librbd, write_exit, r);
3446 return r;
3447 }
3448
3449
3450 extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
3451 {
3452 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3453 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3454 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
3455 tracepoint(librbd, discard_exit, r);
3456 return r;
3457 }
3458
3459 extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
3460 const char *buf, size_t data_len, int op_flags)
3461 {
3462 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3463 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3464 ictx->read_only, ofs, len, data_len <= 0 ? NULL : buf, data_len, op_flags);
3465
3466 if (data_len <= 0 || len % data_len) {
3467 tracepoint(librbd, writesame_exit, -EINVAL);
3468 return -EINVAL;
3469 }
3470
3471 if (mem_is_zero(buf, data_len)) {
3472 int r = ictx->io_work_queue->discard(ofs, len, false);
3473 tracepoint(librbd, writesame_exit, r);
3474 return r;
3475 }
3476
3477 bufferlist bl;
3478 bl.push_back(create_write_raw(ictx, buf, data_len));
3479 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
3480 tracepoint(librbd, writesame_exit, r);
3481 return r;
3482 }
3483
3484 extern "C" ssize_t rbd_compare_and_write(rbd_image_t image,
3485 uint64_t ofs, size_t len,
3486 const char *cmp_buf,
3487 const char *buf,
3488 uint64_t *mismatch_off,
3489 int op_flags)
3490 {
3491 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3492 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
3493 ictx->snap_name.c_str(), ictx->read_only, ofs,
3494 len, cmp_buf, buf, op_flags);
3495
3496 bufferlist cmp_bl;
3497 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len));
3498 bufferlist bl;
3499 bl.push_back(create_write_raw(ictx, buf, len));
3500
3501 int r = ictx->io_work_queue->compare_and_write(ofs, len, std::move(cmp_bl),
3502 std::move(bl), mismatch_off,
3503 op_flags);
3504 tracepoint(librbd, compare_and_write_exit, r);
3505 return r;
3506 }
3507
3508 extern "C" int rbd_aio_create_completion(void *cb_arg,
3509 rbd_callback_t complete_cb,
3510 rbd_completion_t *c)
3511 {
3512 librbd::RBD::AioCompletion *rbd_comp =
3513 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
3514 *c = (rbd_completion_t) rbd_comp;
3515 return 0;
3516 }
3517
3518 extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
3519 const char *buf, rbd_completion_t c)
3520 {
3521 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3522 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3523 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3524
3525 bufferlist bl;
3526 bl.push_back(create_write_raw(ictx, buf, len));
3527 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3528 std::move(bl), 0);
3529 tracepoint(librbd, aio_write_exit, 0);
3530 return 0;
3531 }
3532
3533 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
3534 const char *buf, rbd_completion_t c, int op_flags)
3535 {
3536 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3537 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3538 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3539 ictx->read_only, off, len, buf, comp->pc, op_flags);
3540
3541 bufferlist bl;
3542 bl.push_back(create_write_raw(ictx, buf, len));
3543 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3544 std::move(bl), op_flags);
3545 tracepoint(librbd, aio_write_exit, 0);
3546 return 0;
3547 }
3548
3549 extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
3550 int iovcnt, uint64_t off, rbd_completion_t c)
3551 {
3552 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3553 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3554
3555 // convert the scatter list into a bufferlist
3556 ssize_t len = 0;
3557 bufferlist bl;
3558 for (int i = 0; i < iovcnt; ++i) {
3559 const struct iovec &io = iov[i];
3560 len += io.iov_len;
3561 if (len < 0) {
3562 break;
3563 }
3564
3565 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
3566 io.iov_len));
3567 }
3568
3569 int r = 0;
3570 if (iovcnt <= 0 || len < 0) {
3571 r = -EINVAL;
3572 }
3573
3574 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
3575 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3576 comp->pc);
3577 if (r == 0) {
3578 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3579 std::move(bl), 0);
3580 }
3581 tracepoint(librbd, aio_write_exit, r);
3582 return r;
3583 }
3584
3585 extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
3586 rbd_completion_t c)
3587 {
3588 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3589 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3590 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
3591 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard);
3592 tracepoint(librbd, aio_discard_exit, 0);
3593 return 0;
3594 }
3595
3596 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
3597 char *buf, rbd_completion_t c)
3598 {
3599 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3600 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3601 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3602 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3603 librbd::io::ReadResult{buf, len}, 0);
3604 tracepoint(librbd, aio_read_exit, 0);
3605 return 0;
3606 }
3607
3608 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
3609 char *buf, rbd_completion_t c, int op_flags)
3610 {
3611 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3612 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3613 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3614 ictx->read_only, off, len, buf, comp->pc, op_flags);
3615 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3616 librbd::io::ReadResult{buf, len},op_flags);
3617 tracepoint(librbd, aio_read_exit, 0);
3618 return 0;
3619 }
3620
3621 extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
3622 int iovcnt, uint64_t off, rbd_completion_t c)
3623 {
3624 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3625 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3626
3627 ssize_t len = 0;
3628 for (int i = 0; i < iovcnt; ++i) {
3629 len += iov[i].iov_len;
3630 if (len < 0) {
3631 break;
3632 }
3633 }
3634
3635 int r = 0;
3636 if (iovcnt == 0 || len < 0) {
3637 r = -EINVAL;
3638 }
3639
3640 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
3641 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3642 comp->pc);
3643 if (r == 0) {
3644 librbd::io::ReadResult read_result;
3645 if (iovcnt == 1) {
3646 read_result = librbd::io::ReadResult(
3647 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
3648 } else {
3649 read_result = librbd::io::ReadResult(iov, iovcnt);
3650 }
3651 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3652 std::move(read_result), 0);
3653 }
3654 tracepoint(librbd, aio_read_exit, r);
3655 return r;
3656 }
3657
3658 extern "C" int rbd_flush(rbd_image_t image)
3659 {
3660 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3661 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3662 int r = librbd::flush(ictx);
3663 tracepoint(librbd, flush_exit, r);
3664 return r;
3665 }
3666
3667 extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
3668 {
3669 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3670 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3671 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
3672 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
3673 tracepoint(librbd, aio_flush_exit, 0);
3674 return 0;
3675 }
3676
3677 extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
3678 const char *buf, size_t data_len, rbd_completion_t c,
3679 int op_flags)
3680 {
3681 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3682 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3683 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3684 ictx->read_only, off, len, data_len <= 0 ? NULL : buf, data_len, comp->pc,
3685 op_flags);
3686
3687 if (data_len <= 0 || len % data_len) {
3688 tracepoint(librbd, aio_writesame_exit, -EINVAL);
3689 return -EINVAL;
3690 }
3691
3692 if (mem_is_zero(buf, data_len)) {
3693 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false);
3694 tracepoint(librbd, aio_writesame_exit, 0);
3695 return 0;
3696 }
3697
3698 bufferlist bl;
3699 bl.push_back(create_write_raw(ictx, buf, data_len));
3700 ictx->io_work_queue->aio_writesame(get_aio_completion(comp), off, len,
3701 std::move(bl), op_flags);
3702 tracepoint(librbd, aio_writesame_exit, 0);
3703 return 0;
3704 }
3705
3706 extern "C" ssize_t rbd_aio_compare_and_write(rbd_image_t image, uint64_t off,
3707 size_t len, const char *cmp_buf,
3708 const char *buf, rbd_completion_t c,
3709 uint64_t *mismatch_off,
3710 int op_flags)
3711 {
3712 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3713 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3714 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3715 ictx->read_only, off, len, cmp_buf, buf, comp->pc, op_flags);
3716
3717 bufferlist cmp_bl;
3718 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len));
3719 bufferlist bl;
3720 bl.push_back(create_write_raw(ictx, buf, len));
3721 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(comp), off, len,
3722 std::move(cmp_bl), std::move(bl),
3723 mismatch_off, op_flags, false);
3724
3725 tracepoint(librbd, aio_compare_and_write_exit, 0);
3726 return 0;
3727 }
3728
3729 extern "C" int rbd_invalidate_cache(rbd_image_t image)
3730 {
3731 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3732 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3733 int r = librbd::invalidate_cache(ictx);
3734 tracepoint(librbd, invalidate_cache_exit, r);
3735 return r;
3736 }
3737
3738 extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
3739 {
3740 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3741 librbd::io::AioCompletion *cs[numcomp];
3742 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
3743 int r = librbd::poll_io_events(ictx, cs, numcomp);
3744 tracepoint(librbd, poll_io_events_exit, r);
3745 if (r > 0) {
3746 for (int i = 0; i < r; ++i)
3747 comps[i] = cs[i]->rbd_comp;
3748 }
3749 return r;
3750 }
3751
3752 extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
3753 {
3754 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3755 string val_s;
3756 tracepoint(librbd, metadata_get_enter, ictx, key);
3757 int r = librbd::metadata_get(ictx, key, &val_s);
3758 if (r < 0) {
3759 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3760 return r;
3761 }
3762 if (*vallen < val_s.size() + 1) {
3763 r = -ERANGE;
3764 *vallen = val_s.size() + 1;
3765 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3766 } else {
3767 strncpy(value, val_s.c_str(), val_s.size() + 1);
3768 tracepoint(librbd, metadata_get_exit, r, key, value);
3769 }
3770 return r;
3771 }
3772
3773 extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
3774 {
3775 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3776 tracepoint(librbd, metadata_set_enter, ictx, key, value);
3777 int r = ictx->operations->metadata_set(key, value);
3778 tracepoint(librbd, metadata_set_exit, r);
3779 return r;
3780 }
3781
3782 extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
3783 {
3784 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3785 tracepoint(librbd, metadata_remove_enter, ictx, key);
3786 int r = ictx->operations->metadata_remove(key);
3787 tracepoint(librbd, metadata_remove_exit, r);
3788 return r;
3789 }
3790
3791 extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
3792 char *key, size_t *key_len, char *value, size_t *val_len)
3793 {
3794 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3795 tracepoint(librbd, metadata_list_enter, ictx);
3796 map<string, bufferlist> pairs;
3797 int r = librbd::metadata_list(ictx, start, max, &pairs);
3798 size_t key_total_len = 0, val_total_len = 0;
3799 bool too_short = false;
3800 for (map<string, bufferlist>::iterator it = pairs.begin();
3801 it != pairs.end(); ++it) {
3802 key_total_len += it->first.size() + 1;
3803 val_total_len += it->second.length() + 1;
3804 }
3805 if (*key_len < key_total_len || *val_len < val_total_len)
3806 too_short = true;
3807 *key_len = key_total_len;
3808 *val_len = val_total_len;
3809 if (too_short) {
3810 tracepoint(librbd, metadata_list_exit, -ERANGE);
3811 return -ERANGE;
3812 }
3813
3814 char *key_p = key, *value_p = value;
3815
3816 for (map<string, bufferlist>::iterator it = pairs.begin();
3817 it != pairs.end(); ++it) {
3818 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
3819 key_p += it->first.size() + 1;
3820 strncpy(value_p, it->second.c_str(), it->second.length());
3821 value_p += it->second.length();
3822 *value_p = '\0';
3823 value_p++;
3824 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
3825 }
3826 tracepoint(librbd, metadata_list_exit, r);
3827 return r;
3828 }
3829
3830 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
3831 {
3832 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3833 return librbd::api::Mirror<>::image_enable(ictx, false);
3834 }
3835
3836 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
3837 {
3838 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3839 return librbd::api::Mirror<>::image_disable(ictx, force);
3840 }
3841
3842 extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
3843 {
3844 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3845 return librbd::api::Mirror<>::image_promote(ictx, force);
3846 }
3847
3848 extern "C" int rbd_mirror_image_demote(rbd_image_t image)
3849 {
3850 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3851 return librbd::api::Mirror<>::image_demote(ictx);
3852 }
3853
3854 extern "C" int rbd_mirror_image_resync(rbd_image_t image)
3855 {
3856 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3857 return librbd::api::Mirror<>::image_resync(ictx);
3858 }
3859
3860 extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
3861 rbd_mirror_image_info_t *mirror_image_info,
3862 size_t info_size)
3863 {
3864 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3865
3866 librbd::mirror_image_info_t cpp_mirror_image;
3867 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image,
3868 sizeof(cpp_mirror_image));
3869 if (r < 0) {
3870 return r;
3871 }
3872
3873 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
3874 return 0;
3875 }
3876
3877 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
3878 rbd_mirror_image_status_t *status,
3879 size_t status_size)
3880 {
3881 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3882
3883 librbd::mirror_image_status_t cpp_status;
3884 int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status,
3885 sizeof(cpp_status));
3886 if (r < 0) {
3887 return r;
3888 }
3889
3890 mirror_image_status_cpp_to_c(cpp_status, status);
3891 return 0;
3892 }
3893
3894 extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
3895 rbd_completion_t c) {
3896 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3897 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3898 librbd::api::Mirror<>::image_promote(
3899 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3900 get_aio_completion(comp)));
3901 return 0;
3902 }
3903
3904 extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
3905 rbd_completion_t c) {
3906 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3907 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3908 librbd::api::Mirror<>::image_demote(
3909 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3910 get_aio_completion(comp)));
3911 return 0;
3912 }
3913
3914 extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
3915 rbd_mirror_image_info_t *info,
3916 size_t info_size,
3917 rbd_completion_t c) {
3918 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3919 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3920
3921 if (sizeof(rbd_mirror_image_info_t) > info_size) {
3922 return -ERANGE;
3923 }
3924
3925 auto ctx = new C_MirrorImageGetInfo(
3926 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3927 get_aio_completion(comp)));
3928 librbd::api::Mirror<>::image_get_info(
3929 ictx, &ctx->cpp_mirror_image_info, sizeof(ctx->cpp_mirror_image_info), ctx);
3930 return 0;
3931 }
3932
3933 extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
3934 rbd_mirror_image_status_t *status,
3935 size_t status_size,
3936 rbd_completion_t c) {
3937 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3938 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3939
3940 if (sizeof(rbd_mirror_image_status_t) > status_size) {
3941 return -ERANGE;
3942 }
3943
3944 auto ctx = new C_MirrorImageGetStatus(
3945 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3946 get_aio_completion(comp)));
3947 librbd::api::Mirror<>::image_get_status(
3948 ictx, &ctx->cpp_mirror_image_status, sizeof(ctx->cpp_mirror_image_status),
3949 ctx);
3950 return 0;
3951 }
3952
3953 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
3954 rbd_update_callback_t watch_cb, void *arg)
3955 {
3956 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3957 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
3958 tracepoint(librbd, update_watch_enter, ictx, wctx);
3959 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
3960 tracepoint(librbd, update_watch_exit, r, wctx->handle);
3961 *handle = reinterpret_cast<uint64_t>(wctx);
3962 return r;
3963 }
3964
3965 extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
3966 {
3967 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3968 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
3969 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
3970 int r = ictx->state->unregister_update_watcher(wctx->handle);
3971 delete wctx;
3972 tracepoint(librbd, update_unwatch_exit, r);
3973 return r;
3974 }
3975
3976 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
3977 {
3978 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3979 return comp->is_complete();
3980 }
3981
3982 extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
3983 {
3984 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3985 return comp->wait_for_complete();
3986 }
3987
3988 extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
3989 {
3990 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3991 return comp->get_return_value();
3992 }
3993
3994 extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
3995 {
3996 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3997 return comp->get_arg();
3998 }
3999
4000 extern "C" void rbd_aio_release(rbd_completion_t c)
4001 {
4002 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4003 comp->release();
4004 }
4005