int main(int argc, const char **argv) { rados_t cluster; rados_ioctx_t io_ctx; rbd_image_t image; srand(time(0)); assert(rados_create(&cluster, NULL) == 0); assert(rados_conf_parse_argv(cluster, argc, argv) == 0); assert(rados_conf_read_file(cluster, NULL) == 0); assert(rados_connect(cluster) == 0); if (rados_pool_lookup(cluster, TEST_POOL) != -ENOENT) { int r = rados_pool_delete(cluster, TEST_POOL); printf("rados_pool_delete returned %d\n", r); } int r = rados_pool_create(cluster, TEST_POOL); printf("rados_pool_create returned %d\n", r); assert(rados_ioctx_create(cluster, TEST_POOL, &io_ctx) == 0); test_ls(io_ctx, 0); test_create_and_stat(io_ctx, TEST_IMAGE, MB_BYTES(1)); assert(rbd_open(io_ctx, TEST_IMAGE, &image, NULL) == 0); test_ls(io_ctx, 1, TEST_IMAGE); test_ls_snaps(image, 0); test_create_snap(image, TEST_SNAP); test_ls_snaps(image, 1, TEST_SNAP, MB_BYTES(1)); test_resize_and_stat(image, MB_BYTES(2)); test_io(io_ctx, image); test_create_snap(image, TEST_SNAP "1"); test_ls_snaps(image, 2, TEST_SNAP, MB_BYTES(1), TEST_SNAP "1", MB_BYTES(2)); test_delete_snap(image, TEST_SNAP); test_ls_snaps(image, 1, TEST_SNAP "1", MB_BYTES(2)); test_delete_snap(image, TEST_SNAP "1"); test_ls_snaps(image, 0); test_io_to_snapshot(io_ctx, image, MB_BYTES(2)); assert(rbd_close(image) == 0); test_create_and_stat(io_ctx, TEST_IMAGE "1", MB_BYTES(2)); test_ls(io_ctx, 2, TEST_IMAGE, TEST_IMAGE "1"); test_delete(io_ctx, TEST_IMAGE); test_ls(io_ctx, 1, TEST_IMAGE "1"); test_delete(io_ctx, TEST_IMAGE "1"); test_ls(io_ctx, 0); rados_ioctx_destroy(io_ctx); rados_shutdown(cluster); return 0; }
static void qemu_rbd_close(BlockDriverState *bs) { BDRVRBDState *s = bs->opaque; rbd_close(s->image); rados_ioctx_destroy(s->io_ctx); g_free(s->snap); rados_shutdown(s->cluster); }
void do_clone() { char filename[1024]; char imagename[1024]; char lastimagename[1024]; int ret, fd; int order = 0, stripe_unit = 0, stripe_count = 0; if (randomize_striping) { order = 18 + rand() % 8; stripe_unit = 1ull << (order - 1 - (rand() % 8)); stripe_count = 2 + rand() % 14; } log4(OP_CLONE, 0, 0, 0); ++num_clones; prt("%lu clone\t%d order %d su %d sc %d\n", testcalls, num_clones, order, stripe_unit, stripe_count); clone_filename(filename, sizeof(filename), num_clones); if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { simple_err("do_clone: open", -errno); exit(162); } save_buffer(good_buf, file_size, fd); if ((ret = close(fd)) < 0) { simple_err("do_clone: close", -errno); exit(163); } if ((ret = rbd_snap_create(image, "snap")) < 0) { simple_err("do_clone: rbd create snap", ret); exit(164); } if ((ret = rbd_snap_protect(image, "snap")) < 0) { simple_err("do_clone: rbd protect snap", ret); exit(164); } clone_imagename(imagename, sizeof(imagename), num_clones); clone_imagename(lastimagename, sizeof(lastimagename), num_clones - 1); ret = rbd_clone2(ioctx, lastimagename, "snap", ioctx, imagename, RBD_FEATURES_ALL, &order, stripe_unit, stripe_count); if (ret < 0) { simple_err("do_clone: rbd clone", ret); exit(165); } rbd_close(image); if ((ret = rbd_open(ioctx, imagename, &image, NULL)) < 0) { simple_err("do_clone: rbd open", ret); exit(166); } }
static void bs_rbd_close(struct scsi_lu *lu) { struct active_rbd *rbd = RBDP(lu->fd); if (rbd->rbd_image) { rbd_close(rbd->rbd_image); rados_ioctx_destroy(rbd->ioctx); rbd->rbd_image = rbd->ioctx = NULL; } }
void test_create_and_stat(rados_ioctx_t io_ctx, const char *name, size_t size) { rbd_image_info_t info; rbd_image_t image; int order = 0; assert(rbd_create(io_ctx, name, size, &order) == 0); assert(rbd_open(io_ctx, name, &image, NULL) == 0); assert(rbd_stat(image, &info, sizeof(info)) == 0); printf("image has size %llu and order %d\n", (unsigned long long) info.size, info.order); assert(info.size == size); assert(info.order == order); assert(rbd_close(image) == 0); }
int rbdfs_unlink(const char *path) { int fd = find_openrbd(path+1); if (fd != -1) { struct rbd_openimage *rbd = &opentbl[fd]; rbd_close(rbd->image); rbd->image = 0; free(rbd->image_name); rbd->rbd_stat.valid = 0; } return rbd_remove(ioctx, path+1); }
static void qemu_rbd_close(BlockDriverState *bs) { BDRVRBDState *s = bs->opaque; close(s->fds[0]); close(s->fds[1]); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL, NULL, NULL, NULL); rbd_close(s->image); rados_ioctx_destroy(s->io_ctx); g_free(s->snap); rados_shutdown(s->cluster); }
void check_clones() { char filename[1024]; char imagename[1024]; int ret, fd; rbd_image_t cur_image; struct stat file_info; while (num_clones > 0) { prt("checking clone #%d\n", num_clones); --num_clones; clone_imagename(imagename, sizeof(imagename), num_clones); if ((ret = rbd_open(ioctx, imagename, &cur_image, NULL)) < 0) { simple_err("check_clones: rbd open", ret); exit(167); } clone_filename(filename, sizeof(filename), num_clones + 1); if ((fd = open(filename, O_RDONLY)) < 0) { simple_err("check_clones: open", -errno); exit(168); } prt("checking image %s against file %s\n", imagename, filename); if ((ret = fstat(fd, &file_info)) < 0) { simple_err("check_clones: fstat", -errno); exit(169); } if ((ret = pread(fd, good_buf, file_info.st_size, 0)) < 0) { simple_err("check_clones: pread", -errno); exit(170); } if ((ret = rbd_read(cur_image, 0, file_info.st_size, temp_buf)) < 0) { simple_err("check_clones: rbd_read", ret); exit(171); } close(fd); check_buffers(0, file_info.st_size); unlink(filename); /* remove the snapshot if it exists, ignore the error from the last clone. */ rbd_snap_unprotect(cur_image, "snap"); rbd_snap_remove(cur_image, "snap"); rbd_close(cur_image); rbd_remove(ioctx, imagename); } }
static int volStorageBackendRBDRefreshVolInfo(virStorageVolDefPtr vol, virStoragePoolObjPtr pool, virStorageBackendRBDStatePtr ptr) { int ret = -1; rbd_image_t image; if (rbd_open(ptr.ioctx, vol->name, &image, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to open the RBD image '%s'"), vol->name); return ret; } rbd_image_info_t info; if (rbd_stat(image, &info, sizeof(info)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to stat the RBD image")); goto cleanup; } VIR_DEBUG("Refreshed RBD image %s/%s (size: %llu obj_size: %llu num_objs: %llu)", pool->def->source.name, vol->name, (unsigned long long)info.size, (unsigned long long)info.obj_size, (unsigned long long)info.num_objs); vol->capacity = info.size; vol->allocation = info.obj_size * info.num_objs; vol->type = VIR_STORAGE_VOL_NETWORK; VIR_FREE(vol->target.path); if (virAsprintf(&vol->target.path, "%s/%s", pool->def->source.name, vol->name) == -1) { virReportOOMError(); goto cleanup; } VIR_FREE(vol->key); if (virAsprintf(&vol->key, "%s/%s", pool->def->source.name, vol->name) == -1) { virReportOOMError(); goto cleanup; } ret = 0; cleanup: rbd_close(image); return ret; }
static int virStorageBackendRBDResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, virStorageVolDefPtr vol, unsigned long long capacity, unsigned int flags) { virStorageBackendRBDStatePtr ptr; ptr.cluster = NULL; ptr.ioctx = NULL; rbd_image_t image = NULL; int ret = -1; virCheckFlags(0, -1); if (virStorageBackendRBDOpenRADOSConn(&ptr, conn, pool) < 0) { goto cleanup; } if (rados_ioctx_create(ptr.cluster, pool->def->source.name, &ptr.ioctx) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to create the RBD IoCTX. Does the pool '%s' exist?"), pool->def->source.name); goto cleanup; } if (rbd_open(ptr.ioctx, vol->name, &image, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to open the RBD image '%s'"), vol->name); goto cleanup; } if (rbd_resize(image, capacity) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to resize the RBD image '%s'"), vol->name); goto cleanup; } ret = 0; cleanup: if (image != NULL) rbd_close(image); virStorageBackendRBDCloseRADOSConn(ptr); return ret; }
static int virStorageBackendRBDResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, virStorageVolDefPtr vol, unsigned long long capacity, unsigned int flags) { virStorageBackendRBDState ptr; ptr.cluster = NULL; ptr.ioctx = NULL; rbd_image_t image = NULL; int ret = -1; int r = 0; virCheckFlags(0, -1); if (virStorageBackendRBDOpenRADOSConn(&ptr, conn, pool) < 0) { goto cleanup; } if (virStorageBackendRBDOpenIoCTX(&ptr, pool) < 0) { goto cleanup; } r = rbd_open(ptr.ioctx, vol->name, &image, NULL); if (r < 0) { virReportSystemError(-r, _("failed to open the RBD image '%s'"), vol->name); goto cleanup; } r = rbd_resize(image, capacity); if (r < 0) { virReportSystemError(-r, _("failed to resize the RBD image '%s'"), vol->name); goto cleanup; } ret = 0; cleanup: if (image != NULL) rbd_close(image); virStorageBackendRBDCloseRADOSConn(&ptr); return ret; }
void docloseopen(void) { int ret; if (testcalls <= simulatedopcount) return; if (debug) prt("%lu close/open\n", testcalls); if ((ret = rbd_close(image)) < 0) { prterrcode("docloseopen: close", ret); report_failure(180); } ret = rbd_open(ioctx, iname, &image, NULL); if (ret < 0) { prterrcode("docloseopen: open", ret); report_failure(181); } }
int __librbd_close(struct rbd_ctx *ctx) { int ret; assert(ctx->name && ctx->image); ret = rbd_close(ctx->image); if (ret < 0) { prt("rbd_close(%s) failed\n", ctx->name); return ret; } free((void *)ctx->name); ctx->name = NULL; ctx->image = NULL; return 0; }
static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; char clientname_buf[RBD_MAX_CONF_SIZE]; char *clientname; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { return -EINVAL; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); return r; } s->snap = NULL; if (snap_buf[0] != '\0') { s->snap = g_strdup(snap_buf); } /* * Fallback to more conservative semantics if setting cache * options fails. Ignore errors from setting rbd_cache because the * only possible error is that the option does not exist, and * librbd defaults to no caching. If write through caching cannot * be set up, fall back to no caching. */ if (flags & BDRV_O_NOCACHE) { rados_conf_set(s->cluster, "rbd_cache", "false"); } else { rados_conf_set(s->cluster, "rbd_cache", "true"); } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(s->cluster, NULL); } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); goto failed_shutdown; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); if (r < 0) { error_report("error opening eventfd"); goto failed; } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, NULL, qemu_rbd_aio_flush_cb, s); return 0; failed: rbd_close(s->image); failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); return r; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; BlockdevOptionsRbd *opts = NULL; const QDictEntry *e; Error *local_err = NULL; char *keypairs, *secretid; int r; keypairs = g_strdup(qdict_get_try_str(options, "=keyvalue-pairs")); if (keypairs) { qdict_del(options, "=keyvalue-pairs"); } secretid = g_strdup(qdict_get_try_str(options, "password-secret")); if (secretid) { qdict_del(options, "password-secret"); } r = qemu_rbd_convert_options(options, &opts, &local_err); if (local_err) { /* If keypairs are present, that means some options are present in * the modern option format. Don't attempt to parse legacy option * formats, as we won't support mixed usage. */ if (keypairs) { error_propagate(errp, local_err); goto out; } /* If the initial attempt to convert and process the options failed, * we may be attempting to open an image file that has the rbd options * specified in the older format consisting of all key/value pairs * encoded in the filename. Go ahead and attempt to parse the * filename, and see if we can pull out the required options. */ r = qemu_rbd_attempt_legacy_options(options, &opts, &keypairs); if (r < 0) { /* Propagate the original error, not the legacy parsing fallback * error, as the latter was just a best-effort attempt. */ error_propagate(errp, local_err); goto out; } /* Take care whenever deciding to actually deprecate; once this ability * is removed, we will not be able to open any images with legacy-styled * backing image strings. */ warn_report("RBD options encoded in the filename as keyvalue pairs " "is deprecated"); } /* Remove the processed options from the QDict (the visitor processes * _all_ options in the QDict) */ while ((e = qdict_first(options))) { qdict_del(options, e->key); } r = qemu_rbd_connect(&s->cluster, &s->io_ctx, opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid, errp); if (r < 0) { goto out; } s->snap = g_strdup(opts->snapshot); s->image_name = g_strdup(opts->image); /* rbd_open is always r/w */ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->image_name); goto failed_open; } /* If we are using an rbd snapshot, we must be r/o, otherwise * leave as-is */ if (s->snap != NULL) { r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp); if (r < 0) { rbd_close(s->image); goto failed_open; } } r = 0; goto out; failed_open: rados_ioctx_destroy(s->io_ctx); g_free(s->snap); g_free(s->image_name); rados_shutdown(s->cluster); out: qapi_free_BlockdevOptionsRbd(opts); g_free(keypairs); g_free(secretid); return r; }
void test_io_to_snapshot(rados_ioctx_t io_ctx, rbd_image_t image, size_t isize) { int i, r; rbd_image_t image_at_snap; char orig_data[TEST_IO_TO_SNAP_SIZE + 1]; char test_data[TEST_IO_TO_SNAP_SIZE + 1]; for (i = 0; i < TEST_IO_TO_SNAP_SIZE - 1; ++i) test_data[i] = (char) (i + 48); test_data[TEST_IO_TO_SNAP_SIZE] = '\0'; orig_data[TEST_IO_TO_SNAP_SIZE] = '\0'; r = rbd_read(image, 0, TEST_IO_TO_SNAP_SIZE, orig_data); assert(r == TEST_IO_TO_SNAP_SIZE); test_ls_snaps(image, 0); test_create_snap(image, "orig"); test_ls_snaps(image, 1, "orig", isize); read_test_data(image, orig_data, 0, TEST_IO_TO_SNAP_SIZE); printf("write test data!\n"); write_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE); test_create_snap(image, "written"); test_ls_snaps(image, 2, "orig", isize, "written", isize); read_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE); rbd_snap_set(image, "orig"); read_test_data(image, orig_data, 0, TEST_IO_TO_SNAP_SIZE); rbd_snap_set(image, "written"); read_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE); rbd_snap_set(image, "orig"); r = rbd_write(image, 0, TEST_IO_TO_SNAP_SIZE, test_data); printf("write to snapshot returned %d\n", r); assert(r < 0); printf("%s\n", strerror(-r)); read_test_data(image, orig_data, 0, TEST_IO_TO_SNAP_SIZE); rbd_snap_set(image, "written"); read_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE); r = rbd_snap_rollback(image, "orig"); printf("rbd_snap_rollback returned %d\n", r); assert(r >= 0); r = rbd_snap_set(image, NULL); assert(r == 0); write_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE); printf("opening testimg@orig\n"); assert(rbd_open(io_ctx, TEST_IMAGE, &image_at_snap, "orig") >= 0); read_test_data(image_at_snap, orig_data, 0, TEST_IO_TO_SNAP_SIZE); r = rbd_write(image_at_snap, 0, TEST_IO_TO_SNAP_SIZE, test_data); printf("write to snapshot returned %d\n", r); assert(r < 0); printf("%s\n", strerror(-r)); assert(rbd_close(image_at_snap) == 0); test_ls_snaps(image, 2, "orig", isize, "written", isize); test_delete_snap(image, "written"); test_ls_snaps(image, 1, "orig", isize); test_delete_snap(image, "orig"); test_ls_snaps(image, 0); }
static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; char clientname_buf[RBD_MAX_CONF_SIZE]; char *clientname; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { return -EINVAL; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); return r; } s->snap = NULL; if (snap_buf[0] != '\0') { s->snap = g_strdup(snap_buf); } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(s->cluster, NULL); } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); goto failed_shutdown; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); if (r < 0) { error_report("error opening eventfd"); goto failed; } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, NULL, qemu_rbd_aio_flush_cb, NULL, s); return 0; failed: rbd_close(s->image); failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); return r; }