diff options
author | Brian Foster <bfoster@redhat.com> | 2013-09-18 07:03:07 -0400 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-11-10 23:02:37 -0800 |
commit | 0826f9073a93c6d499f3d2077695455854d0fa7f (patch) | |
tree | 3d29ab1f7c8414c307b52eff411063a74177d675 /xlators/features/qemu-block/src/qemu-block.c | |
parent | c8fef37c5d566c906728b5f6f27baaa9a8d2a20d (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.c | 75 |
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; |