summaryrefslogtreecommitdiffstats
path: root/xlators/features/qemu-block/src/qemu-block.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/qemu-block/src/qemu-block.c')
-rw-r--r--xlators/features/qemu-block/src/qemu-block.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/xlators/features/qemu-block/src/qemu-block.c b/xlators/features/qemu-block/src/qemu-block.c
index 416ae44383c..0edb7b9493d 100644
--- a/xlators/features/qemu-block/src/qemu-block.c
+++ b/xlators/features/qemu-block/src/qemu-block.c
@@ -108,42 +108,76 @@ qb_iatt_fixup (xlator_t *this, inode_t *inode, struct iatt *iatt)
int
qb_format_extract (xlator_t *this, char *format, inode_t *inode)
{
- char *s = NULL;
+ char *s, *save;
uint64_t size = 0;
char fmt[QB_XATTR_VAL_MAX+1] = {0, };
qb_inode_t *qb_inode = NULL;
+ char *formatstr = NULL;
+ uuid_t gfid = {0,};
+ char gfid_str[64] = {0,};
+ int ret;
- strncpy (fmt, format, QB_XATTR_VAL_MAX);
- s = strchr (fmt, ':');
+ strncpy(fmt, format, QB_XATTR_VAL_MAX);
+
+ s = strtok_r(fmt, ":", &save);
if (!s)
goto invalid;
- if (s == fmt)
- goto invalid;
+ formatstr = gf_strdup(s);
- *s = 0; s++;
- if (!*s || strchr (s, ':'))
+ s = strtok_r(NULL, ":", &save);
+ if (!s)
goto invalid;
-
if (gf_string2bytesize (s, &size))
goto invalid;
-
if (!size)
goto invalid;
+ s = strtok_r(NULL, "\0", &save);
+ if (s && !strncmp(s, "<gfid:", strlen("<gfid:"))) {
+ /*
+ * Check for valid gfid backing image specifier.
+ */
+ if (strlen(s) + 1 > sizeof(gfid_str))
+ goto invalid;
+ ret = sscanf(s, "<gfid:%[^>]s", gfid_str);
+ if (ret == 1) {
+ ret = uuid_parse(gfid_str, gfid);
+ if (ret < 0)
+ goto invalid;
+ }
+ }
+
qb_inode = qb_inode_ctx_get (this, inode);
if (!qb_inode)
qb_inode = GF_CALLOC (1, sizeof (*qb_inode),
gf_qb_mt_qb_inode_t);
- if (!qb_inode)
+ if (!qb_inode) {
+ GF_FREE(formatstr);
return ENOMEM;
+ }
- strncpy (qb_inode->fmt, fmt, QB_XATTR_VAL_MAX);
+ strncpy(qb_inode->fmt, formatstr, QB_XATTR_VAL_MAX);
qb_inode->size = size;
- qb_inode->size_str = s;
+
+ /*
+ * If a backing gfid was not specified, interpret any remaining bytes
+ * associated with a backing image as a filename local to the parent
+ * directory. The format processing will validate further.
+ */
+ if (!uuid_is_null(gfid))
+ uuid_copy(qb_inode->backing_gfid, gfid);
+ else if (s)
+ qb_inode->backing_fname = gf_strdup(s);
inode_ctx_set (inode, this, (void *)&qb_inode);
+
+ GF_FREE(formatstr);
+
return 0;
+
invalid:
+ GF_FREE(formatstr);
+
gf_log (this->name, GF_LOG_WARNING,
"invalid format '%s' in inode %s", format,
uuid_utoa (inode->gfid));
@@ -191,6 +225,15 @@ qb_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == -1)
goto out;
+ /*
+ * Cache the root inode for dealing with backing images. The format
+ * coroutine and the gluster qemu backend driver both use the root inode
+ * table to verify and/or redirect I/O to the backing image via
+ * anonymous fd's.
+ */
+ if (!conf->root_inode && __is_root_gfid(inode->gfid))
+ conf->root_inode = inode_ref(inode);
+
if (!xdata)
goto out;
@@ -249,6 +292,7 @@ qb_setxattr_format (call_frame_t *frame, xlator_t *this, call_stub_t *stub,
int op_errno = 0;
qb_local_t *qb_local = NULL;
data_t *data = NULL;
+ qb_inode_t *qb_inode;
if (!(data = dict_get (xattr, "trusted.glusterfs.block-format"))) {
QB_STUB_RESUME (stub);
@@ -264,12 +308,15 @@ qb_setxattr_format (call_frame_t *frame, xlator_t *this, call_stub_t *stub,
QB_STUB_UNWIND (stub, -1, op_errno);
return 0;
}
+ qb_inode = qb_inode_ctx_get(this, inode);
qb_local = frame->local;
qb_local->stub = stub;
qb_local->inode = inode_ref (inode);
- strncpy (qb_local->fmt, format, QB_XATTR_VAL_MAX);
+
+ snprintf(qb_local->fmt, QB_XATTR_VAL_MAX, "%s:%lu", qb_inode->fmt,
+ qb_inode->size);
qb_coroutine (frame, qb_format_and_resume);
@@ -1041,6 +1088,8 @@ fini (xlator_t *this)
this->private = NULL;
+ if (conf->root_inode)
+ inode_unref(conf->root_inode);
GF_FREE (conf);
return;