@@ -27,9 +27,6 @@ configure: ;
$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
LIBS+=-lz $(LIBS_TOOLS)
-ifdef CONFIG_RBD
-LIBS+=-lrados
-endif
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8
@@ -9,6 +9,7 @@
*/
#include "qemu-common.h"
+#include "qemu-error.h"
#include <sys/types.h>
#include <stdbool.h>
@@ -66,20 +67,19 @@ typedef struct RADOSCB {
char *buf;
} RADOSCB;
-typedef struct RBDRVRBDState {
+typedef struct BDRVRBDState {
rados_pool_t pool;
char name[RBD_MAX_OBJ_NAME_SIZE];
- int name_len;
uint64_t size;
uint64_t objsize;
-} RBDRVRBDState;
+} BDRVRBDState;
typedef struct rbd_obj_header_ondisk RbdHeader1;
static int rbd_parsename(const char *filename, char *pool, char *name)
{
const char *rbdname;
- char *p, *n;
+ char *p;
int l;
if (!strstart(filename, "rbd:", &rbdname)) {
@@ -93,19 +93,26 @@ static int rbd_parsename(const char *filename, char *pool, char *name)
}
*p = '\0';
- n = ++p;
-
- l = strlen(n);
+
+ l = strlen(pool);
+ if(l >= RBD_MAX_SEG_NAME_SIZE) {
+ error_report("pool name to long");
+ return -EINVAL;
+ } else if (l <= 0) {
+ error_report("pool name to short");
+ return -EINVAL;
+ }
- if (l > RBD_MAX_OBJ_NAME_SIZE) {
- fprintf(stderr, "object name to long\n");
+ l = strlen(++p);
+ if (l >= RBD_MAX_OBJ_NAME_SIZE) {
+ error_report("object name to long");
return -EINVAL;
} else if (l <= 0) {
- fprintf(stderr, "object name to short\n");
+ error_report("object name to short");
return -EINVAL;
}
- strcpy(name, n);
+ strcpy(name, p);
return l;
}
@@ -113,13 +120,11 @@ static int rbd_parsename(const char *filename, char *pool, char *name)
static int create_tmap_op(uint8_t op, const char *name, char **tmap_desc)
{
uint32_t len = strlen(name);
- uint32_t total_len = 1 + (sizeof(uint32_t) + len) + sizeof(uint32_t); /* encoding op + name + empty buffer */
- char *desc;
+ /* total_len = encoding op + name + empty buffer */
+ uint32_t total_len = 1 + (sizeof(uint32_t) + len) + sizeof(uint32_t);
+ char *desc = NULL;
- desc = qemu_malloc(total_len);
- if (!desc) {
- return -ENOMEM;
- }
+ qemu_malloc(total_len);
*tmap_desc = desc;
@@ -170,10 +175,9 @@ static int rbd_create(const char *filename, QEMUOptionParameter *options)
char name[RBD_MAX_SEG_NAME_SIZE];
RbdHeader1 header;
rados_pool_t p;
- int name_len;
int ret;
- if ((name_len = rbd_parsename(filename, pool, name)) < 0) {
+ if (rbd_parsename(filename, pool, name) < 0) {
return -EINVAL;
}
@@ -186,18 +190,19 @@ static int rbd_create(const char *filename, QEMUOptionParameter *options)
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
if (options->value.n) {
objsize = options->value.n;
- if (!objsize || ((objsize - 1) & objsize)) { /* not a power of 2? */
- fprintf(stderr, "obj size needs to be power of 2\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) {
- fprintf(stderr, "obj size too small\n");
+ error_report("obj size too small");
return -EINVAL;
}
for (obj_order = 0; obj_order < 64; obj_order++) {
- if (objsize == 1)
+ if (objsize == 1) {
break;
+ }
objsize >>= 1;
}
}
@@ -219,12 +224,13 @@ static int rbd_create(const char *filename, QEMUOptionParameter *options)
cpu_to_le32s(&header.snap_count);
if (rados_initialize(0, NULL) < 0) {
- fprintf(stderr, "error initializing\n");
+ error_report("error initializing");
return -EIO;
}
if (rados_open_pool(pool, &p)) {
- fprintf(stderr, "error opening pool %s\n", pool);
+ error_report("error opening pool %s", pool);
+ rados_deinitialize();
return -EIO;
}
@@ -251,53 +257,63 @@ done:
static int rbd_open(BlockDriverState *bs, const char *filename, int flags)
{
- RBDRVRBDState *s = bs->opaque;
+ BDRVRBDState *s = bs->opaque;
char pool[RBD_MAX_SEG_NAME_SIZE];
char n[RBD_MAX_SEG_NAME_SIZE];
char hbuf[4096];
+ int r;
- if ((s->name_len = rbd_parsename(filename, pool, s->name)) < 0) {
+ if (rbd_parsename(filename, pool, s->name) < 0) {
return -EINVAL;
}
snprintf(n, RBD_MAX_SEG_NAME_SIZE, "%s%s", s->name, RBD_SUFFIX);
- if (rados_initialize(0, NULL) < 0) {
- fprintf(stderr, "error initializing\n");
- return -EIO;
+ if ((r = rados_initialize(0, NULL)) < 0) {
+ error_report("error initializing");
+ return r;
}
- if (rados_open_pool(pool, &s->pool)) {
- fprintf(stderr, "error opening pool %s\n", pool);
- return -EIO;
+ if ((r = rados_open_pool(pool, &s->pool))) {
+ error_report("error opening pool %s", pool);
+ rados_deinitialize();
+ return r;
}
- if (rados_read(s->pool, n, 0, hbuf, 4096) < 0) {
- fprintf(stderr, "error reading header from %s\n", s->name);
- return -EIO;
+ if ((r = rados_read(s->pool, n, 0, hbuf, 4096)) < 0) {
+ error_report("error reading header from %s", s->name);
+ goto failed;
}
- if (!strncmp(hbuf + 64, rbd_signature, 4)) {
- if (!strncmp(hbuf + 68, rbd_version, 8)) {
- RbdHeader1 *header;
-
- header = (RbdHeader1 *) hbuf;
- le64_to_cpus((uint64_t *) & header->image_size);
- s->size = header->image_size;
- s->objsize = 1 << header->options.order;
- } else {
- fprintf(stderr, "Unknown image version %s\n", hbuf + 68);
- return -EIO;
- }
- } else {
- fprintf(stderr, "Invalid header signature %s\n", hbuf + 64);
- return -EIO;
+
+ if (strncmp(hbuf + 64, rbd_signature, 4)) {
+ error_report("Invalid header signature %s", hbuf + 64);
+ r = -EMEDIUMTYPE;
+ goto failed;
+ }
+
+ if (strncmp(hbuf + 68, rbd_version, 8)) {
+ error_report("Unknown image version %s", hbuf + 68);
+ r = -EMEDIUMTYPE;
+ goto failed;
}
+ RbdHeader1 *header;
+
+ header = (RbdHeader1 *) hbuf;
+ le64_to_cpus((uint64_t *) & header->image_size);
+ s->size = header->image_size;
+ s->objsize = 1 << header->options.order;
+
return 0;
+
+failed:
+ rados_close_pool(s->pool);
+ rados_deinitialize();
+ return r;
}
static void rbd_close(BlockDriverState *bs)
{
- RBDRVRBDState *s = bs->opaque;
+ BDRVRBDState *s = bs->opaque;
rados_close_pool(s->pool);
rados_deinitialize();
@@ -306,25 +322,24 @@ static void rbd_close(BlockDriverState *bs)
static int rbd_rw(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors, int write)
{
- RBDRVRBDState *s = bs->opaque;
+ BDRVRBDState *s = bs->opaque;
char n[RBD_MAX_SEG_NAME_SIZE];
int64_t segnr, segoffs, segsize, r;
int64_t off, size;
- off = sector_num * 512;
- size = nb_sectors * 512;
- segnr = (int64_t) (off / s->objsize);
- segoffs = (int64_t) (off % s->objsize);
- segsize = (int64_t) (s->objsize - segoffs);
+ off = sector_num * BDRV_SECTOR_SIZE;
+ size = nb_sectors * BDRV_SECTOR_SIZE;
+ segnr = off / s->objsize;
+ segoffs = off % s->objsize;
+ segsize = s->objsize - segoffs;
while (size > 0) {
if (size < segsize) {
segsize = size;
}
- snprintf(n, RBD_MAX_SEG_NAME_SIZE, "%s.%012llx", s->name,
- (long long unsigned int)segnr);
+ snprintf(n, RBD_MAX_SEG_NAME_SIZE, "%s.%012" PRIx64, s->name, segnr);
if (write) {
if ((r = rados_write(s->pool, n, segoffs, (const char *)buf,
@@ -336,11 +351,10 @@ static int rbd_rw(BlockDriverState *bs, int64_t sector_num,
if (r == -ENOENT) {
memset(buf, 0, segsize);
} else if (r < 0) {
- return(r);
+ return r;
} else if (r < segsize) {
memset(buf + r, 0, segsize - r);
}
- r = segsize;
}
buf += segsize;
@@ -350,7 +364,7 @@ static int rbd_rw(BlockDriverState *bs, int64_t sector_num,
segnr++;
}
- return (0);
+ return 0;
}
static int rbd_read(BlockDriverState *bs, int64_t sector_num,
@@ -450,7 +464,7 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
int64_t off, size;
char *buf;
- RBDRVRBDState *s = bs->opaque;
+ BDRVRBDState *s = bs->opaque;
acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
acb->write = write;
@@ -470,11 +484,11 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
buf = acb->bounce;
- off = sector_num * 512;
- size = nb_sectors * 512;
- segnr = (int64_t) (off / s->objsize);
- segoffs = (int64_t) (off % s->objsize);
- segsize = (int64_t) (s->objsize - segoffs);
+ off = sector_num * BDRV_SECTOR_SIZE;
+ size = nb_sectors * BDRV_SECTOR_SIZE;
+ segnr = off / s->objsize;
+ segoffs = off % s->objsize;
+ segsize = s->objsize - segoffs;
last_segnr = ((off + size - 1) / s->objsize);
acb->aiocnt = (last_segnr - segnr) + 1;
@@ -495,10 +509,12 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
if (write) {
rados_aio_create_completion(rcb, NULL,
- (rados_callback_t) rbd_finish_aiocb, &c);
+ (rados_callback_t) rbd_finish_aiocb,
+ &c);
rados_aio_write(s->pool, n, segoffs, buf, segsize, c);
} else {
- rados_aio_create_completion(rcb, (rados_callback_t) rbd_finish_aiocb,
+ rados_aio_create_completion(rcb,
+ (rados_callback_t) rbd_finish_aiocb,
NULL, &c);
rados_aio_read(s->pool, n, segoffs, buf, segsize, c);
}
@@ -533,14 +549,14 @@ static BlockDriverAIOCB *rbd_aio_writev(BlockDriverState * bs,
static int rbd_getinfo(BlockDriverState * bs, BlockDriverInfo * bdi)
{
- RBDRVRBDState *s = bs->opaque;
+ BDRVRBDState *s = bs->opaque;
bdi->cluster_size = s->objsize;
return 0;
}
static int64_t rbd_getlength(BlockDriverState * bs)
{
- RBDRVRBDState *s = bs->opaque;
+ BDRVRBDState *s = bs->opaque;
return s->size;
}
@@ -560,20 +576,20 @@ static QEMUOptionParameter rbd_create_options[] = {
};
static BlockDriver bdrv_rbd = {
- .format_name = "rbd",
- .instance_size = sizeof(RBDRVRBDState),
- .bdrv_open = rbd_open,
- .bdrv_read = rbd_read,
- .bdrv_write = rbd_write,
- .bdrv_close = rbd_close,
- .bdrv_create = rbd_create,
- .bdrv_get_info = rbd_getinfo,
- .create_options = rbd_create_options,
- .bdrv_getlength = rbd_getlength,
- .protocol_name = "rbd",
-
- .bdrv_aio_readv = rbd_aio_readv,
- .bdrv_aio_writev = rbd_aio_writev,
+ .format_name = "rbd",
+ .instance_size = sizeof(BDRVRBDState),
+ .bdrv_open = rbd_open,
+ .bdrv_read = rbd_read,
+ .bdrv_write = rbd_write,
+ .bdrv_close = rbd_close,
+ .bdrv_create = rbd_create,
+ .bdrv_get_info = rbd_getinfo,
+ .create_options = rbd_create_options,
+ .bdrv_getlength = rbd_getlength,
+ .protocol_name = "rbd",
+
+ .bdrv_aio_readv = rbd_aio_readv,
+ .bdrv_aio_writev = rbd_aio_writev,
};
static void bdrv_rbd_init(void)
@@ -314,7 +314,7 @@ kvm_kmod="no"
check_utests="no"
user_pie="no"
zero_malloc=""
-rbd="no"
+rbd=""
# OS specific
if check_define __linux__ ; then
@@ -695,6 +695,8 @@ for opt do
;;
--enable-vhost-net) vhost_net="yes"
;;
+ --disable-rbd) rbd="no"
+ ;;
--enable-rbd) rbd="yes"
;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
@@ -1703,9 +1705,11 @@ if test "$rbd" != "no" ; then
#include <rados/librados.h>
int main(void) { rados_initialize(0, NULL); return 0; }
EOF
- if compile_prog "" "-lrados -lcrypto" ; then
+ rbd_libs="-lrados -lcrypto"
+ if compile_prog "" "$rbd_libs" ; then
rbd=yes
- LIBS="$LIBS -lrados -lcrypto"
+ libs_tools="$rbd_libs $libs_tools"
+ libs_softmmu="$rbd_libs $libs_softmmu"
else
if test "$rbd" = "yes" ; then
feature_not_found "rados block device"