summaryrefslogtreecommitdiffstats
path: root/xlators/features/qemu-block/src/qemu-block.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2013-09-18 07:03:07 -0400
committerAnand Avati <avati@redhat.com>2013-11-10 23:02:37 -0800
commit0826f9073a93c6d499f3d2077695455854d0fa7f (patch)
tree3d29ab1f7c8414c307b52eff411063a74177d675 /xlators/features/qemu-block/src/qemu-block.c
parentc8fef37c5d566c906728b5f6f27baaa9a8d2a20d (diff)
features/qemu-block: add qemu backing image support (clone)
Add basic backing image support to the block-format mechanism. This is a functionality checkpoint that enables the raw mechanism required to support client driven "snapshot" and "clone" requests. This change enhances the block-format setxattr command to support an additional and optional backing image reference. For example: setxattr -n trusted.glusterfs.block-format -v "qcow2:10GB:<bimg>" ./newimage ... where <bimg> refers to the backing image for unallocated blocks in newimage. <bimg> can be provided in one of two formats: - a gfid string in the following format (assuming a valid gfid): <gfid:00000000-0000-0000-0000-000000000000> - or a filename that must be resident in the same directory as the new clone file being formatted. E.g., setxattr -n trusted.glusterfs.block-format -v "qcow2:10GB:baseimg" ./newimage This latter format is more restrictive, simply provided for convenience or until something more refined is available. This change makes no assumptions about the backing image file and affords no additional protection. It is up to the user/client to recognize the relationship between the files and manage them appropriately (i.e., no writes to the backing image, etc.). BUG: 986775 Change-Id: I7aff7bdc59b85a6459001a6bfeae4db6bf74f703 Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-on: http://review.gluster.org/5967 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Anand Avati <avati@redhat.com>
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;