Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' i…
Browse files Browse the repository at this point in the history
…nto staging

# gpg: Signature made Tue 19 Apr 2016 17:28:01 BST using RSA key ID C0DE3057
# gpg: Good signature from "Jeffrey Cody <jcody@redhat.com>"
# gpg:                 aka "Jeffrey Cody <jeff@codyprime.org>"
# gpg:                 aka "Jeffrey Cody <codyprime@gmail.com>"

* remotes/cody/tags/block-pull-request:
  block/gluster: prevent data loss after i/o error
  block/gluster: code movement of qemu_gluster_close()
  block/gluster: return correct error value

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Apr 20, 2016
2 parents 1f7685f + d85fa9e commit fe98b18
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 13 deletions.
77 changes: 64 additions & 13 deletions block/gluster.c
Expand Up @@ -247,7 +247,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
if (!ret || ret == acb->size) {
acb->ret = 0; /* Success */
} else if (ret < 0) {
acb->ret = ret; /* Read/Write failed */
acb->ret = -errno; /* Read/Write failed */
} else {
acb->ret = -EIO; /* Partial read/write - fail it */
}
Expand Down Expand Up @@ -314,6 +314,23 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
goto out;
}

#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
/* Without this, if fsync fails for a recoverable reason (for instance,
* ENOSPC), gluster will dump its cache, preventing retries. This means
* almost certain data loss. Not all gluster versions support the
* 'resync-failed-syncs-after-fsync' key value, but there is no way to
* discover during runtime if it is supported (this api returns success for
* unknown key/value pairs) */
ret = glfs_set_xlator_option(s->glfs, "*-write-behind",
"resync-failed-syncs-after-fsync",
"on");
if (ret < 0) {
error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
ret = -errno;
goto out;
}
#endif

qemu_gluster_parse_flags(bdrv_flags, &open_flags);

s->fd = glfs_open(s->glfs, gconf->image, open_flags);
Expand Down Expand Up @@ -366,6 +383,16 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
goto exit;
}

#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
ret = glfs_set_xlator_option(reop_s->glfs, "*-write-behind",
"resync-failed-syncs-after-fsync", "on");
if (ret < 0) {
error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
ret = -errno;
goto exit;
}
#endif

reop_s->fd = glfs_open(reop_s->glfs, gconf->image, open_flags);
if (reop_s->fd == NULL) {
/* reops->glfs will be cleaned up in _abort */
Expand Down Expand Up @@ -589,6 +616,17 @@ static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
}

static void qemu_gluster_close(BlockDriverState *bs)
{
BDRVGlusterState *s = bs->opaque;

if (s->fd) {
glfs_close(s->fd);
s->fd = NULL;
}
glfs_fini(s->glfs);
}

static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
{
int ret;
Expand All @@ -602,11 +640,35 @@ static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)

ret = glfs_fsync_async(s->fd, gluster_finish_aiocb, &acb);
if (ret < 0) {
return -errno;
ret = -errno;
goto error;
}

qemu_coroutine_yield();
if (acb.ret < 0) {
ret = acb.ret;
goto error;
}

return acb.ret;

error:
/* Some versions of Gluster (3.5.6 -> 3.5.8?) will not retain its cache
* after a fsync failure, so we have no way of allowing the guest to safely
* continue. Gluster versions prior to 3.5.6 don't retain the cache
* either, but will invalidate the fd on error, so this is again our only
* option.
*
* The 'resync-failed-syncs-after-fsync' xlator option for the
* write-behind cache will cause later gluster versions to retain its
* cache after error, so long as the fd remains open. However, we
* currently have no way of knowing if this option is supported.
*
* TODO: Once gluster provides a way for us to determine if the option
* is supported, bypass the closure and setting drv to NULL. */
qemu_gluster_close(bs);
bs->drv = NULL;
return ret;
}

#ifdef CONFIG_GLUSTERFS_DISCARD
Expand Down Expand Up @@ -661,17 +723,6 @@ static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs)
}
}

static void qemu_gluster_close(BlockDriverState *bs)
{
BDRVGlusterState *s = bs->opaque;

if (s->fd) {
glfs_close(s->fd);
s->fd = NULL;
}
glfs_fini(s->glfs);
}

static int qemu_gluster_has_zero_init(BlockDriverState *bs)
{
/* GlusterFS volume could be backed by a block device */
Expand Down
8 changes: 8 additions & 0 deletions configure
Expand Up @@ -298,6 +298,7 @@ coroutine=""
coroutine_pool=""
seccomp=""
glusterfs=""
glusterfs_xlator_opt="no"
glusterfs_discard="no"
glusterfs_zerofill="no"
archipelago="no"
Expand Down Expand Up @@ -3400,6 +3401,9 @@ if test "$glusterfs" != "no" ; then
glusterfs="yes"
glusterfs_cflags=`$pkg_config --cflags glusterfs-api`
glusterfs_libs=`$pkg_config --libs glusterfs-api`
if $pkg_config --atleast-version=4 glusterfs-api; then
glusterfs_xlator_opt="yes"
fi
if $pkg_config --atleast-version=5 glusterfs-api; then
glusterfs_discard="yes"
fi
Expand Down Expand Up @@ -5342,6 +5346,10 @@ if test "$glusterfs" = "yes" ; then
echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak
fi

if test "$glusterfs_xlator_opt" = "yes" ; then
echo "CONFIG_GLUSTERFS_XLATOR_OPT=y" >> $config_host_mak
fi

if test "$glusterfs_discard" = "yes" ; then
echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak
fi
Expand Down

0 comments on commit fe98b18

Please sign in to comment.