X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=block%2Fgluster.c;h=e664ca4462441b1125728a312d28761cbc9a7fb8;hb=de23e72bb7515888fdea2a58c58a2e02370123bd;hp=296e036b3dccbc64221b0dd4385f9a047dfc35bd;hpb=55901900ec69d6fd6f332003d8ab81b2f8a38529;p=mirror_qemu.git diff --git a/block/gluster.c b/block/gluster.c index 296e036b3d..e664ca4462 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -9,8 +9,10 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include #include "block/block_int.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" @@ -19,6 +21,10 @@ #include "qemu/option.h" #include "qemu/cutils.h" +#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT +# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL) +#endif + #define GLUSTER_OPT_FILENAME "filename" #define GLUSTER_OPT_VOLUME "volume" #define GLUSTER_OPT_PATH "path" @@ -36,6 +42,12 @@ #define GLUSTER_DEBUG_MAX 9 #define GLUSTER_OPT_LOGFILE "logfile" #define GLUSTER_LOGFILE_DEFAULT "-" /* handled in libgfapi as /dev/stderr */ +/* + * Several versions of GlusterFS (3.12? -> 6.0.1) fail when the transfer size + * is greater or equal to 1024 MiB, so we are limiting the transfer size to 512 + * MiB to avoid this rare issue. + */ +#define GLUSTER_MAX_TRANSFER (512 * MiB) #define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n" @@ -71,7 +83,7 @@ typedef struct ListElement { GlfsPreopened saved; } ListElement; -static QLIST_HEAD(glfs_list, ListElement) glfs_list; +static QLIST_HEAD(, ListElement) glfs_list; static QemuOptsList qemu_gluster_create_opts = { .name = "qemu-gluster-create-opts", @@ -167,7 +179,12 @@ static QemuOptsList runtime_unix_opts = { { .name = GLUSTER_OPT_SOCKET, .type = QEMU_OPT_STRING, - .help = "socket file path)", + .help = "socket file path (legacy)", + }, + { + .name = GLUSTER_OPT_PATH, + .type = QEMU_OPT_STRING, + .help = "socket file path (QAPI)", }, { /* end of list */ } }, @@ -615,10 +632,18 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, goto out; } - ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET); + ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH); + if (!ptr) { + ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET); + } else if (qemu_opt_get(opts, GLUSTER_OPT_SOCKET)) { + error_setg(&local_err, + "Conflicting parameters 'path' and 'socket'"); + error_append_hint(&local_err, GERR_INDEX_HINT, i); + goto out; + } if (!ptr) { error_setg(&local_err, QERR_MISSING_PARAMETER, - GLUSTER_OPT_SOCKET); + GLUSTER_OPT_PATH); error_append_hint(&local_err, GERR_INDEX_HINT, i); goto out; } @@ -637,7 +662,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, } gsconf = NULL; - QDECREF(backing_options); + qobject_unref(backing_options); backing_options = NULL; g_free(str); str = NULL; @@ -650,7 +675,7 @@ out: qapi_free_SocketAddress(gsconf); qemu_opts_del(opts); g_free(str); - QDECREF(backing_options); + qobject_unref(backing_options); errno = EINVAL; return -errno; } @@ -684,7 +709,7 @@ static int qemu_gluster_parse(BlockdevOptionsGluster *gconf, "file.server.0.host=1.2.3.4," "file.server.0.port=24007," "file.server.1.transport=unix," - "file.server.1.socket=/var/run/glusterd.socket ..." + "file.server.1.path=/var/run/glusterd.socket ..." "\n"); return ret; } @@ -711,7 +736,11 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf, /* * AIO callback routine called from GlusterFS thread. */ -static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) +static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, +#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT + struct glfs_stat *pre, struct glfs_stat *post, +#endif + void *arg) { GlusterAIOCB *acb = (GlusterAIOCB *)arg; @@ -835,8 +864,16 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options, qemu_gluster_parse_flags(bdrv_flags, &open_flags); s->fd = glfs_open(s->glfs, gconf->path, open_flags); - if (!s->fd) { - ret = -errno; + ret = s->fd ? 0 : -errno; + + if (ret == -EACCES || ret == -EROFS) { + /* Try to degrade to read-only, but if it doesn't work, still use the + * normal error message. */ + if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) { + open_flags = (open_flags & ~O_RDWR) | O_RDONLY; + s->fd = glfs_open(s->glfs, gconf->path, open_flags); + ret = s->fd ? 0 : -errno; + } } s->supports_seek_data = qemu_gluster_test_seek(s->fd); @@ -857,6 +894,11 @@ out: return ret; } +static void qemu_gluster_refresh_limits(BlockDriverState *bs, Error **errp) +{ + bs->bl.max_transfer = GLUSTER_MAX_TRANSFER; +} + static int qemu_gluster_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) { @@ -1163,8 +1205,10 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs, return acb.ret; } -static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs, + int64_t offset, + PreallocMode prealloc, + Error **errp) { BDRVGlusterState *s = bs->opaque; return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp); @@ -1181,8 +1225,10 @@ static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs, static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - QEMUIOVector *qiov) + QEMUIOVector *qiov, + int flags) { + assert(!flags); return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1); } @@ -1308,7 +1354,7 @@ static int qemu_gluster_has_zero_init(BlockDriverState *bs) * If @start is in a trailing hole or beyond EOF, return -ENXIO. * If we can't find out, return a negative errno other than -ENXIO. * - * (Shamefully copied from file-posix.c, only miniscule adaptions.) + * (Shamefully copied from file-posix.c, only minuscule adaptions.) */ static int find_allocation(BlockDriverState *bs, off_t start, off_t *data, off_t *hole) @@ -1469,6 +1515,21 @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs, } +static const char *const gluster_strong_open_opts[] = { + GLUSTER_OPT_VOLUME, + GLUSTER_OPT_PATH, + GLUSTER_OPT_TYPE, + GLUSTER_OPT_SERVER_PATTERN, + GLUSTER_OPT_HOST, + GLUSTER_OPT_PORT, + GLUSTER_OPT_TO, + GLUSTER_OPT_IPV4, + GLUSTER_OPT_IPV6, + GLUSTER_OPT_SOCKET, + + NULL +}; + static BlockDriver bdrv_gluster = { .format_name = "gluster", .protocol_name = "gluster", @@ -1483,7 +1544,7 @@ static BlockDriver bdrv_gluster = { .bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_getlength = qemu_gluster_getlength, .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, - .bdrv_truncate = qemu_gluster_truncate, + .bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, @@ -1495,7 +1556,9 @@ static BlockDriver bdrv_gluster = { .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, #endif .bdrv_co_block_status = qemu_gluster_co_block_status, + .bdrv_refresh_limits = qemu_gluster_refresh_limits, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; static BlockDriver bdrv_gluster_tcp = { @@ -1512,7 +1575,7 @@ static BlockDriver bdrv_gluster_tcp = { .bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_getlength = qemu_gluster_getlength, .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, - .bdrv_truncate = qemu_gluster_truncate, + .bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, @@ -1524,7 +1587,9 @@ static BlockDriver bdrv_gluster_tcp = { .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, #endif .bdrv_co_block_status = qemu_gluster_co_block_status, + .bdrv_refresh_limits = qemu_gluster_refresh_limits, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; static BlockDriver bdrv_gluster_unix = { @@ -1541,7 +1606,7 @@ static BlockDriver bdrv_gluster_unix = { .bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_getlength = qemu_gluster_getlength, .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, - .bdrv_truncate = qemu_gluster_truncate, + .bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, @@ -1553,7 +1618,9 @@ static BlockDriver bdrv_gluster_unix = { .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, #endif .bdrv_co_block_status = qemu_gluster_co_block_status, + .bdrv_refresh_limits = qemu_gluster_refresh_limits, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; /* rdma is deprecated (actually never supported for volfile fetch). @@ -1576,7 +1643,7 @@ static BlockDriver bdrv_gluster_rdma = { .bdrv_co_create_opts = qemu_gluster_co_create_opts, .bdrv_getlength = qemu_gluster_getlength, .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, - .bdrv_truncate = qemu_gluster_truncate, + .bdrv_co_truncate = qemu_gluster_co_truncate, .bdrv_co_readv = qemu_gluster_co_readv, .bdrv_co_writev = qemu_gluster_co_writev, .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, @@ -1588,7 +1655,9 @@ static BlockDriver bdrv_gluster_rdma = { .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, #endif .bdrv_co_block_status = qemu_gluster_co_block_status, + .bdrv_refresh_limits = qemu_gluster_refresh_limits, .create_opts = &qemu_gluster_create_opts, + .strong_runtime_opts = gluster_strong_open_opts, }; static void bdrv_gluster_init(void)