-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1
 
 iQIcBAABAgAGBQJXFlyRAAoJEL2+eyfA3jBXVSoP/iU/1FzrNeDTKtCkmUAXdzb4
 ixhvEvwhAQJQ19SHIK31FTD+hfEZO7hV9XKIDlzOPG5Qy4K2dVQEEjrgruWp3eHs
 2wrOVUqN366KVw2db2JFrd2aGMJq3d84nYHlGauYa/hTxAEoptGIuyHE0ACMrF76
 Kv0APsYlAPwU1Qmkr0GnNz7Cbfrlec+gq7ZL7vxj4odOcdQCtc1JdUpvK3BmFunh
 k+hIooUEzK7/6EUjpgjEjlbNQELdXhm8fnLXAS7/RA32LML1heg7W696BS4EkFcI
 NospLIzwmQU+6HkSaq3TDK4rf7f84N3Cxf8aFFZB+aatmhfu37lacKYsGJXga10M
 GWkj7T6JNZMH9eB5J67Garv0lwYxVSGxK+VrNqH/EcHGkzFerGAQbTXzzfkfrr5J
 rGrcD+bctjLWk4HXU1MyZ0PLjgva9dRinYBCSIM5KK1v6yc4mwSAwuIuf4uQIlkL
 gDBvqtzd9BPHWwOjO20Txk+sinz+No+ZPOHdPw1yRU/zJR0gtFytFnxx1xvtOvfX
 k94/aOQq+BBFY/hx3bI2fWI5zz0uS8Yf8WQ21Da2oirCLTOQqbpRd+7ZprcyugCE
 MQzY2om4y5b6aIKvvnU2e5BZbiHkagOmlTdf8nBietixEi8anizJT4AGLCGPgMeE
 Ur+TxJYxnm5yavYnB5/e
 =QJoE
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into 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>
This commit is contained in:
Peter Maydell 2016-04-20 14:42:09 +01:00
commit fe98b18b6f
2 changed files with 72 additions and 13 deletions

View File

@ -247,7 +247,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
if (!ret || ret == acb->size) { if (!ret || ret == acb->size) {
acb->ret = 0; /* Success */ acb->ret = 0; /* Success */
} else if (ret < 0) { } else if (ret < 0) {
acb->ret = ret; /* Read/Write failed */ acb->ret = -errno; /* Read/Write failed */
} else { } else {
acb->ret = -EIO; /* Partial read/write - fail it */ acb->ret = -EIO; /* Partial read/write - fail it */
} }
@ -314,6 +314,23 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
goto out; 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); qemu_gluster_parse_flags(bdrv_flags, &open_flags);
s->fd = glfs_open(s->glfs, gconf->image, open_flags); s->fd = glfs_open(s->glfs, gconf->image, open_flags);
@ -366,6 +383,16 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
goto exit; 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); reop_s->fd = glfs_open(reop_s->glfs, gconf->image, open_flags);
if (reop_s->fd == NULL) { if (reop_s->fd == NULL) {
/* reops->glfs will be cleaned up in _abort */ /* reops->glfs will be cleaned up in _abort */
@ -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); 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) static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
{ {
int ret; int ret;
@ -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); ret = glfs_fsync_async(s->fd, gluster_finish_aiocb, &acb);
if (ret < 0) { if (ret < 0) {
return -errno; ret = -errno;
goto error;
} }
qemu_coroutine_yield(); qemu_coroutine_yield();
if (acb.ret < 0) {
ret = acb.ret;
goto error;
}
return acb.ret; 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 #ifdef CONFIG_GLUSTERFS_DISCARD
@ -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) static int qemu_gluster_has_zero_init(BlockDriverState *bs)
{ {
/* GlusterFS volume could be backed by a block device */ /* GlusterFS volume could be backed by a block device */

8
configure vendored
View File

@ -298,6 +298,7 @@ coroutine=""
coroutine_pool="" coroutine_pool=""
seccomp="" seccomp=""
glusterfs="" glusterfs=""
glusterfs_xlator_opt="no"
glusterfs_discard="no" glusterfs_discard="no"
glusterfs_zerofill="no" glusterfs_zerofill="no"
archipelago="no" archipelago="no"
@ -3400,6 +3401,9 @@ if test "$glusterfs" != "no" ; then
glusterfs="yes" glusterfs="yes"
glusterfs_cflags=`$pkg_config --cflags glusterfs-api` glusterfs_cflags=`$pkg_config --cflags glusterfs-api`
glusterfs_libs=`$pkg_config --libs 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 if $pkg_config --atleast-version=5 glusterfs-api; then
glusterfs_discard="yes" glusterfs_discard="yes"
fi fi
@ -5342,6 +5346,10 @@ if test "$glusterfs" = "yes" ; then
echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak
fi fi
if test "$glusterfs_xlator_opt" = "yes" ; then
echo "CONFIG_GLUSTERFS_XLATOR_OPT=y" >> $config_host_mak
fi
if test "$glusterfs_discard" = "yes" ; then if test "$glusterfs_discard" = "yes" ; then
echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak
fi fi