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; }
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) { int64_t bytes = 0; int64_t objsize; int obj_order = 0; char pool[RBD_MAX_POOL_NAME_SIZE]; char name[RBD_MAX_IMAGE_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; rados_t cluster; rados_ioctx_t io_ctx; int ret; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), name, sizeof(name), conf, sizeof(conf)) < 0) { return -EINVAL; } /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { bytes = options->value.n; } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { if (options->value.n) { objsize = options->value.n; if ((objsize - 1) & objsize) { /* not a power of 2? */ error_report("obj size needs to be power of 2"); return -EINVAL; } if (objsize < 4096) { error_report("obj size too small"); return -EINVAL; } obj_order = ffs(objsize) - 1; } } options++; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); if (rados_create(&cluster, clientname) < 0) { error_report("error initializing"); return -EIO; } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(cluster, NULL); } if (conf[0] != '\0' && qemu_rbd_set_conf(cluster, conf) < 0) { error_report("error setting config options"); rados_shutdown(cluster); return -EIO; } if (rados_connect(cluster) < 0) { error_report("error connecting"); rados_shutdown(cluster); return -EIO; } if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) { error_report("error opening pool %s", pool); rados_shutdown(cluster); return -EIO; } ret = rbd_create(io_ctx, name, bytes, &obj_order); rados_ioctx_destroy(io_ctx); rados_shutdown(cluster); return ret; }
static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) { Error *local_err = NULL; int64_t bytes = 0; int64_t objsize; int obj_order = 0; const char *pool, *name, *conf, *clientname, *keypairs; const char *secretid; rados_t cluster; rados_ioctx_t io_ctx; QDict *options = NULL; int ret = 0; secretid = qemu_opt_get(opts, "password-secret"); /* Read out options */ bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); if (objsize) { if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); ret = -EINVAL; goto exit; } if (objsize < 4096) { error_setg(errp, "obj size too small"); ret = -EINVAL; goto exit; } obj_order = ctz32(objsize); } options = qdict_new(); qemu_rbd_parse_filename(filename, options, &local_err); if (local_err) { ret = -EINVAL; error_propagate(errp, local_err); goto exit; } pool = qdict_get_try_str(options, "pool"); conf = qdict_get_try_str(options, "conf"); clientname = qdict_get_try_str(options, "user"); name = qdict_get_try_str(options, "image"); keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); ret = rados_create(&cluster, clientname); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); goto exit; } /* try default location when conf=NULL, but ignore failure */ ret = rados_conf_read_file(cluster, conf); if (conf && ret < 0) { error_setg_errno(errp, -ret, "error reading conf file %s", conf); ret = -EIO; goto shutdown; } ret = qemu_rbd_set_keypairs(cluster, keypairs, errp); if (ret < 0) { ret = -EIO; goto shutdown; } if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { ret = -EIO; goto shutdown; } ret = rados_connect(cluster); if (ret < 0) { error_setg_errno(errp, -ret, "error connecting"); goto shutdown; } ret = rados_ioctx_create(cluster, pool, &io_ctx); if (ret < 0) { error_setg_errno(errp, -ret, "error opening pool %s", pool); goto shutdown; } ret = rbd_create(io_ctx, name, bytes, &obj_order); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); } rados_ioctx_destroy(io_ctx); shutdown: rados_shutdown(cluster); exit: QDECREF(options); return ret; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; const char *pool, *snap, *conf, *clientname, *name, *keypairs; const char *secretid; QemuOpts *opts; Error *local_err = NULL; char *mon_host = NULL; int r; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } mon_host = qemu_rbd_mon_host(options, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } secretid = qemu_opt_get(opts, "password-secret"); pool = qemu_opt_get(opts, "pool"); conf = qemu_opt_get(opts, "conf"); snap = qemu_opt_get(opts, "snapshot"); clientname = qemu_opt_get(opts, "user"); name = qemu_opt_get(opts, "image"); keypairs = qemu_opt_get(opts, "=keyvalue-pairs"); if (!pool || !name) { error_setg(errp, "Parameters 'pool' and 'image' are required"); r = -EINVAL; goto failed_opts; } r = rados_create(&s->cluster, clientname); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } s->snap = g_strdup(snap); s->name = g_strdup(name); /* try default location when conf=NULL, but ignore failure */ r = rados_conf_read_file(s->cluster, conf); if (conf && r < 0) { error_setg_errno(errp, -r, "error reading conf file %s", conf); goto failed_shutdown; } r = qemu_rbd_set_keypairs(s->cluster, keypairs, errp); if (r < 0) { goto failed_shutdown; } if (mon_host) { r = rados_conf_set(s->cluster, "mon_host", mon_host); if (r < 0) { goto failed_shutdown; } } if (qemu_rbd_set_auth(s->cluster, secretid, errp) < 0) { r = -EIO; goto failed_shutdown; } /* * 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"); } r = rados_connect(s->cluster); if (r < 0) { error_setg_errno(errp, -r, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_setg_errno(errp, -r, "error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); qemu_opts_del(opts); return 0; failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); g_free(s->name); failed_opts: qemu_opts_del(opts); g_free(mon_host); return r; }
static int testrados(void) { char tmp[32]; int i, r; int ret = 1; //set 1 as error case rados_t cl; if (rados_create(&cl, NULL) < 0) { printf("error initializing\n"); return 1; } if (rados_conf_read_file(cl, NULL)) { printf("error reading configuration file\n"); goto out_err; } // Try to set a configuration option that doesn't exist. // This should fail. if (!rados_conf_set(cl, "config option that doesn't exist", "some random value")) { printf("error: succeeded in setting nonexistent config option\n"); goto out_err; } if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { printf("error: failed to read log_to_stderr from config\n"); goto out_err; } // Can we change it? if (rados_conf_set(cl, "log to stderr", "true")) { printf("error: error setting log_to_stderr\n"); goto out_err; } if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { printf("error: failed to read log_to_stderr from config\n"); goto out_err; } if (strcmp(tmp, "true")) { printf("error: new setting for log_to_stderr failed to take effect.\n"); goto out_err; } if (rados_connect(cl)) { printf("error connecting\n"); goto out_err; } if (rados_connect(cl) == 0) { printf("second connect attempt didn't return an error\n"); goto out_err; } /* create an io_ctx */ r = rados_pool_create(cl, "foo"); printf("rados_pool_create = %d\n", r); rados_ioctx_t io_ctx; r = rados_ioctx_create(cl, "foo", &io_ctx); if (r < 0) { printf("error creating ioctx\n"); goto out_err; } printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx); /* list all pools */ { int buf_sz = rados_pool_list(cl, NULL, 0); printf("need buffer size of %d\n", buf_sz); char buf[buf_sz]; int r = rados_pool_list(cl, buf, buf_sz); if (r != buf_sz) { printf("buffer size mismatch: got %d the first time, but %d " "the second.\n", buf_sz, r); goto out_err_cleanup; } const char *b = buf; printf("begin pools.\n"); while (1) { if (b[0] == '\0') break; printf(" pool: '%s'\n", b); b += strlen(b) + 1; }; printf("end pools.\n"); } /* stat */ struct rados_pool_stat_t st; r = rados_ioctx_pool_stat(io_ctx, &st); printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects); /* snapshots */ r = rados_ioctx_snap_create(io_ctx, "snap1"); printf("rados_ioctx_snap_create snap1 = %d\n", r); rados_snap_t snaps[10]; r = rados_ioctx_snap_list(io_ctx, snaps, 10); for (i=0; i<r; i++) { char name[100]; rados_ioctx_snap_get_name(io_ctx, snaps[i], name, sizeof(name)); printf("rados_ioctx_snap_list got snap %lld %s\n", (long long)snaps[i], name); } rados_snap_t snapid; r = rados_ioctx_snap_lookup(io_ctx, "snap1", &snapid); printf("rados_ioctx_snap_lookup snap1 got %lld, result %d\n", (long long)snapid, r); r = rados_ioctx_snap_remove(io_ctx, "snap1"); printf("rados_ioctx_snap_remove snap1 = %d\n", r); /* sync io */ time_t tm; char buf[128], buf2[128]; time(&tm); snprintf(buf, 128, "%s", ctime(&tm)); const char *oid = "foo_object"; r = rados_write(io_ctx, oid, buf, strlen(buf) + 1, 0); printf("rados_write = %d\n", r); r = rados_read(io_ctx, oid, buf2, sizeof(buf2), 0); printf("rados_read = %d\n", r); if (memcmp(buf, buf2, r)) printf("*** content mismatch ***\n"); /* attrs */ if (do_rados_setxattr(io_ctx, oid, "b", "2")) goto out_err_cleanup; if (do_rados_setxattr(io_ctx, oid, "a", "1")) goto out_err_cleanup; if (do_rados_setxattr(io_ctx, oid, "c", "3")) goto out_err_cleanup; if (do_rados_getxattr(io_ctx, oid, "a", "1")) goto out_err_cleanup; if (do_rados_getxattr(io_ctx, oid, "b", "2")) goto out_err_cleanup; if (do_rados_getxattr(io_ctx, oid, "c", "3")) goto out_err_cleanup; const char *exkeys[] = { "a", "b", "c", NULL }; const char *exvals[] = { "1", "2", "3", NULL }; if (do_rados_getxattrs(io_ctx, oid, exkeys, exvals)) goto out_err_cleanup; uint64_t size; time_t mtime; r = rados_stat(io_ctx, oid, &size, &mtime); printf("rados_stat size = %lld mtime = %d = %d\n", (long long)size, (int)mtime, r); r = rados_stat(io_ctx, "does_not_exist", NULL, NULL); printf("rados_stat(does_not_exist) = %d\n", r); /* exec */ rados_exec(io_ctx, oid, "crypto", "md5", buf, strlen(buf) + 1, buf, 128); printf("exec result=%s\n", buf); r = rados_read(io_ctx, oid, buf2, 128, 0); printf("read result=%s\n", buf2); printf("size=%d\n", r); /* aio */ rados_completion_t a, b; rados_aio_create_completion(0, 0, 0, &a); rados_aio_create_completion(0, 0, 0, &b); rados_aio_write(io_ctx, "a", a, buf, 100, 0); rados_aio_write(io_ctx, "../b/bb_bb_bb\\foo\\bar", b, buf, 100, 0); rados_aio_wait_for_safe(a); printf("a safe\n"); rados_aio_wait_for_safe(b); printf("b safe\n"); rados_aio_release(a); rados_aio_release(b); /* test flush */ printf("testing aio flush\n"); rados_completion_t c; rados_aio_create_completion(0, 0, 0, &c); rados_aio_write(io_ctx, "c", c, buf, 100, 0); int safe = rados_aio_is_safe(c); printf("a should not yet be safe and ... %s\n", safe ? "is":"is not"); assert(!safe); rados_aio_flush(io_ctx); safe = rados_aio_is_safe(c); printf("a should be safe and ... %s\n", safe ? "is":"is not"); assert(safe); rados_aio_release(c); rados_read(io_ctx, "../b/bb_bb_bb\\foo\\bar", buf2, 128, 0); /* list objects */ rados_list_ctx_t h; r = rados_nobjects_list_open(io_ctx, &h); printf("rados_nobjects_list_open = %d, h = %p\n", r, h); const char *poolname; while (rados_nobjects_list_next(h, &poolname, NULL, NULL) == 0) printf("rados_nobjects_list_next got object '%s'\n", poolname); rados_nobjects_list_close(h); /* stat */ r = rados_ioctx_pool_stat(io_ctx, &st); printf("rados_stat_pool = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects); ret = 0; out_err_cleanup: /* delete a pool */ rados_ioctx_destroy(io_ctx); r = rados_pool_delete(cl, "foo"); printf("rados_delete_pool = %d\n", r); out_err: rados_shutdown(cl); return ret; }
static void ctdb_mutex_rados_ctx_destroy(rados_t ceph_cluster, rados_ioctx_t ioctx) { rados_ioctx_destroy(ioctx); rados_shutdown(ceph_cluster); }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, 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; QemuOpts *opts; Error *local_err = NULL; const char *filename; int r; opts = qemu_opts_create_nofail(&runtime_opts); qemu_opts_absorb_qdict(opts, options, &local_err); if (error_is_set(&local_err)) { qerror_report_err(local_err); error_free(local_err); qemu_opts_del(opts); return -EINVAL; } filename = qemu_opt_get(opts, "filename"); if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { r = -EINVAL; goto failed_opts; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); goto failed_opts; } 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, s); qemu_opts_del(opts); 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); failed_opts: qemu_opts_del(opts); return r; }
int main() { int ret,len = 0; rados_t cluster; char *buf, *out_buf = NULL; char *pool = "rbd"; char *rbd_name = "vol1"; int fd = -1; int i = 0; rados_completion_t read_comp, write_comp; rbd_image_t rbd_image; time_t start_t, end_t, total_t = 0; unsigned char *cipher_key = (unsigned char *) "7190c8bc27ac4a1bbe1ab1cf55cf3b097190c8bc27ac4a1bbe1ab1cf55cf3b09"; unsigned char *iv = (unsigned char *) "dcbfdd41e40f74a2"; ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); ret = rados_create(&cluster, NULL); if (ret) { printf("error creating rados_t object\n"); return -1; } ret = rados_conf_read_file(cluster,"/home/shishir/repos/ceph/src/ceph.conf"); if (ret) { printf("Error reading conf files \n"); return -1; } ret = rados_connect(cluster); if (ret) { printf("Could not connect to cluster\n"); return -1; } rados_ioctx_t io; ret = rados_ioctx_create(cluster, pool, &io); if (ret) { printf("Could not open connection to cluster\n"); return -1; } ret = rbd_open(io, rbd_name, &rbd_image, NULL); if (ret) { printf("Failed to open image %s\n",rbd_name); return -1; } posix_memalign((void**)&buf, 4096, 65536); if (!buf) { printf("Failed to malloc\n"); return -1; } fd = open("/tmp/input_file", O_RDONLY); if (fd > 0) { read(fd, buf, 65536); close(fd); } posix_memalign((void**)&out_buf, 4096, 65536); if (!out_buf) { printf("Failed to malloc\n"); return -1; } len = strlen((char*)buf); //printf("plain text length %lld\n",strlen((char*)buf)); //printf("===========plain text========\n"); //BIO_dump_fp(stdout,(const char*)buf,len); //printf("=================\n"); start_t = clock(); len = encrypt (buf, strlen((char*)buf), cipher_key, iv, out_buf); end_t = clock(); total_t = (double)(end_t - start_t)/ CLOCKS_PER_SEC; //printf("encrypted len is %d timetaken is %fsec\n",len,total_t); //printf("===========encrypted text========\n"); //BIO_dump_fp(stdout,(const char*)out_buf,len); //printf("=================\n"); fd = open("/tmp/encrypted_file", O_CREAT|O_RDWR); if (fd > 0) { write(fd, out_buf, 65536); close(fd); } ret = rbd_aio_create_completion(NULL, NULL, &write_comp); if (ret) { printf ("Failed to create aio completion\n"); return -1; } ret = rbd_aio_write(rbd_image, 0, 65536, out_buf, write_comp); if (ret < 0) { printf ("Failed to write aio completion\n"); return -1; } rbd_aio_wait_for_complete(write_comp); rbd_aio_release(write_comp); ret = rbd_aio_create_completion(NULL, NULL, &read_comp); if (ret) { printf ("Failed to create aio completion\n"); return -1; } memset(buf, 0, 65536); memset(out_buf, 0, 65536); ret = rbd_aio_read(rbd_image, 0, 65536, buf, read_comp); if (ret < 0) { printf ("Failed to read aio completion\n"); return -1; } rbd_aio_wait_for_complete(read_comp); rbd_aio_release(read_comp); len=65536; start_t = clock(); len = decrypt(buf, len, cipher_key, iv, out_buf); end_t = clock(); total_t = (double)(end_t - start_t)/ CLOCKS_PER_SEC; //printf("decrypted len is %d time taken: %fs\n",len,total_t); //printf("===========decrypted text========\n"); //BIO_dump_fp(stdout,(const char*)out_buf,len); //printf("=================\n"); fd = open("/tmp/decrypted_file", O_CREAT|O_RDWR); if (fd > 0) { write(fd, out_buf, 65536); close(fd); } rados_ioctx_destroy(io); rados_shutdown(cluster); free(buf); free(out_buf); return 0; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; BlockdevOptionsRbd *opts = NULL; Visitor *v; QObject *crumpled = NULL; const QDictEntry *e; Error *local_err = NULL; const char *filename; char *keypairs, *secretid; int r; /* If we are given a filename, parse the filename, with precedence given to * filename encoded options */ filename = qdict_get_try_str(options, "filename"); if (filename) { warn_report("'filename' option specified. " "This is an unsupported option, and may be deprecated " "in the future"); qemu_rbd_parse_filename(filename, options, &local_err); qdict_del(options, "filename"); if (local_err) { error_propagate(errp, local_err); return -EINVAL; } } 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"); } /* Convert the remaining options into a QAPI object */ crumpled = qdict_crumple(options, errp); if (crumpled == NULL) { r = -EINVAL; goto out; } v = qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err); visit_free(v); qobject_unref(crumpled); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto out; } /* 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) { if (!bdrv_is_read_only(bs)) { error_report("Opening rbd snapshots without an explicit " "read-only=on option is deprecated. Future versions " "will refuse to open the image instead of " "automatically marking the image read-only."); r = bdrv_set_read_only(bs, true, &local_err); if (r < 0) { error_propagate(errp, local_err); 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; }
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx, BlockdevOptionsRbd *opts, bool cache, const char *keypairs, const char *secretid, Error **errp) { char *mon_host = NULL; Error *local_err = NULL; int r; mon_host = qemu_rbd_mon_host(opts, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } r = rados_create(cluster, opts->user); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } /* try default location when conf=NULL, but ignore failure */ r = rados_conf_read_file(*cluster, opts->conf); if (opts->has_conf && r < 0) { error_setg_errno(errp, -r, "error reading conf file %s", opts->conf); goto failed_shutdown; } r = qemu_rbd_set_keypairs(*cluster, keypairs, errp); if (r < 0) { goto failed_shutdown; } if (mon_host) { r = rados_conf_set(*cluster, "mon_host", mon_host); if (r < 0) { goto failed_shutdown; } } if (qemu_rbd_set_auth(*cluster, secretid, errp) < 0) { r = -EIO; goto failed_shutdown; } /* * 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 (cache) { rados_conf_set(*cluster, "rbd_cache", "true"); } else { rados_conf_set(*cluster, "rbd_cache", "false"); } r = rados_connect(*cluster); if (r < 0) { error_setg_errno(errp, -r, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(*cluster, opts->pool, io_ctx); if (r < 0) { error_setg_errno(errp, -r, "error opening pool %s", opts->pool); goto failed_shutdown; } return 0; failed_shutdown: rados_shutdown(*cluster); failed_opts: g_free(mon_host); return r; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { 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; const char *secretid; QemuOpts *opts; Error *local_err = NULL; const char *filename; int r; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { error_propagate(errp, local_err); qemu_opts_del(opts); return -EINVAL; } filename = qemu_opt_get(opts, "filename"); secretid = qemu_opt_get(opts, "password-secret"); if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf), errp) < 0) { r = -EINVAL; goto failed_opts; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } 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); } else if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf, true, errp); if (r < 0) { goto failed_shutdown; } } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf, false, errp); if (r < 0) { goto failed_shutdown; } } if (qemu_rbd_set_auth(s->cluster, secretid, errp) < 0) { r = -EIO; goto failed_shutdown; } /* * 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"); } r = rados_connect(s->cluster); if (r < 0) { error_setg_errno(errp, -r, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_setg_errno(errp, -r, "error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); qemu_opts_del(opts); return 0; failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); failed_opts: qemu_opts_del(opts); return r; }
static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) { Error *local_err = NULL; int64_t bytes = 0; int64_t objsize; int obj_order = 0; char pool[RBD_MAX_POOL_NAME_SIZE]; char name[RBD_MAX_IMAGE_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; const char *secretid; rados_t cluster; rados_ioctx_t io_ctx; int ret; secretid = qemu_opt_get(opts, "password-secret"); if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), name, sizeof(name), conf, sizeof(conf), &local_err) < 0) { error_propagate(errp, local_err); return -EINVAL; } /* Read out options */ bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); if (objsize) { if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); return -EINVAL; } if (objsize < 4096) { error_setg(errp, "obj size too small"); return -EINVAL; } obj_order = ctz32(objsize); } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); ret = rados_create(&cluster, clientname); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); return ret; } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(cluster, NULL); } else if (conf[0] != '\0' && qemu_rbd_set_conf(cluster, conf, true, &local_err) < 0) { rados_shutdown(cluster); error_propagate(errp, local_err); return -EIO; } if (conf[0] != '\0' && qemu_rbd_set_conf(cluster, conf, false, &local_err) < 0) { rados_shutdown(cluster); error_propagate(errp, local_err); return -EIO; } if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { rados_shutdown(cluster); return -EIO; } ret = rados_connect(cluster); if (ret < 0) { error_setg_errno(errp, -ret, "error connecting"); rados_shutdown(cluster); return ret; } ret = rados_ioctx_create(cluster, pool, &io_ctx); if (ret < 0) { error_setg_errno(errp, -ret, "error opening pool %s", pool); rados_shutdown(cluster); return ret; } ret = rbd_create(io_ctx, name, bytes, &obj_order); rados_ioctx_destroy(io_ctx); rados_shutdown(cluster); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); return ret; } return ret; }
struct storage_backend * init_storage_rados(const char * connection_string) { #ifndef HAVE_LIBRADOS log_message(STORE_LOGLVL_ERR,"init_storage_rados: Support for rados has not been compiled into this program"); return NULL; #else struct rados_ctx * ctx = malloc(sizeof(struct rados_ctx)); struct storage_backend * store = malloc(sizeof(struct storage_backend)); char * conf = NULL; const char * tmp; int err; int i; if (ctx == NULL) { return NULL; } tmp = &(connection_string[strlen("rados://")]); i = 0; while ((tmp[i] != '/') && (tmp[i] != 0)) i++; ctx->pool = calloc(i + 1, sizeof(char)); memcpy(ctx->pool, tmp, i*sizeof(char)); conf = strdup(&(tmp[i])); err = rados_create(&(ctx->cluster), NULL); if (err < 0) { log_message(STORE_LOGLVL_ERR,"init_storage_rados: cannot create a cluster handle: %s", strerror(-err)); free(ctx); free(store); return NULL; } err = rados_conf_read_file(ctx->cluster, conf); if (err < 0) { log_message(STORE_LOGLVL_ERR,"init_storage_rados: failed to read rados config file %s: %s", conf, strerror(-err)); free(ctx); free(store); return NULL; } pthread_mutex_lock(&qLock); err = rados_connect(ctx->cluster); pthread_mutex_unlock(&qLock); if (err < 0) { log_message(STORE_LOGLVL_ERR,"init_storage_rados: failed to connect to rados cluster: %s", strerror(-err)); free(ctx); free(store); return NULL; } err = rados_ioctx_create(ctx->cluster, ctx->pool, &(ctx->io)); if (err < 0) { log_message(STORE_LOGLVL_ERR,"init_storage_rados: failed to initialise rados io context to pool %s: %s", ctx->pool, strerror(-err)); rados_shutdown(ctx->cluster); free(ctx); free(store); return NULL; } log_message(STORE_LOGLVL_DEBUG,"init_storage_rados: Initialised rados backend for pool %s with config %s", ctx->pool, conf); ctx->metadata_cache.data = malloc(sizeof(struct stat_info) + sizeof(struct meta_layout) + METATILE*METATILE*sizeof(struct entry)); if (ctx->metadata_cache.data == NULL) { rados_ioctx_destroy(ctx->io); rados_shutdown(ctx->cluster); free(ctx); free(store); return NULL; } free(conf); ctx->metadata_cache.x = -1; ctx->metadata_cache.y = -1; ctx->metadata_cache.z = -1; ctx->metadata_cache.xmlname[0] = 0; store->storage_ctx = ctx; store->tile_read = &rados_tile_read; store->tile_stat = &rados_tile_stat; store->metatile_write = &rados_metatile_write; store->metatile_delete = &rados_metatile_delete; store->metatile_expire = &rados_metatile_expire; store->tile_storage_id = &rados_tile_storage_id; store->close_storage = &rados_close_storage; return store; #endif }