@@ -22,13 +22,16 @@
/*
* When specifying the image filename use:
*
- * rbd:poolname/devicename
+ * rbd:poolname/devicename[@snapshotname][:option1=value1[:option2=value2...]]
*
* poolname must be the name of an existing rados pool
*
* devicename is the basename for all objects used to
* emulate the raw device.
*
+ * Each option given is used to configure rados, and may be any Ceph option, or "conf".
+ * The "conf" option specifies a Ceph configuration file to read.
+ *
* Metadata information (image size, ...) is stored in an
* object with the name "devicename.rbd".
*
@@ -121,7 +124,8 @@ static int qemu_rbd_next_tok(char *dst, int dst_len,
static int qemu_rbd_parsename(const char *filename,
char *pool, int pool_len,
char *snap, int snap_len,
- char *name, int name_len)
+ char *name, int name_len,
+ char *conf, int conf_len)
{
const char *start;
char *p, *buf;
@@ -133,28 +137,82 @@ static int qemu_rbd_parsename(const char *filename,
buf = qemu_strdup(start);
p = buf;
+ *snap = '\0';
+ *conf = '\0';
ret = qemu_rbd_next_tok(pool, pool_len, p, '/', "pool name", &p);
if (ret < 0 || !p) {
ret = -EINVAL;
goto done;
}
- ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p);
- if (ret < 0) {
- goto done;
+
+ if (strchr(p, '@')) {
+ ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p);
+ if (ret < 0) {
+ goto done;
+ }
+ ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p);
+ } else {
+ ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p);
}
- if (!p) {
- *snap = '\0';
+ if (ret < 0 || !p) {
goto done;
}
- ret = qemu_rbd_next_tok(snap, snap_len, p, '\0', "snap name", &p);
+ ret = qemu_rbd_next_tok(conf, conf_len, p, '\0', "configuration", &p);
done:
qemu_free(buf);
return ret;
}
+static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
+{
+ char *p, *buf;
+ char name[RBD_MAX_CONF_NAME_SIZE];
+ char value[RBD_MAX_CONF_VAL_SIZE];
+ int ret = 0;
+
+ buf = qemu_strdup(conf);
+ p = buf;
+
+ while (p) {
+ ret = qemu_rbd_next_tok(name, sizeof(name), p, '=', "conf option name", &p);
+ if (ret < 0) {
+ break;
+ }
+
+ if (!p) {
+ error_report("conf option %s has no value", name);
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = qemu_rbd_next_tok(value, sizeof(value), p, ':', "conf option value", &p);
+ if (ret < 0) {
+ break;
+ }
+
+ if (strncmp(name, "conf", strlen("conf"))) {
+ ret = rados_conf_set(cluster, name, value);
+ if (ret < 0) {
+ error_report("invalid conf option %s", name);
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ ret = rados_conf_read_file(cluster, value);
+ if (ret < 0) {
+ error_report("error reading conf file %s", value);
+ break;
+ }
+ }
+ }
+
+ qemu_free(buf);
+ return ret;
+}
+
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options)
{
int64_t bytes = 0;
@@ -163,6 +221,7 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options)
char pool[RBD_MAX_POOL_NAME_SIZE];
char name[RBD_MAX_IMAGE_NAME_SIZE];
char snap_buf[RBD_MAX_SNAP_NAME_SIZE];