2020-09-17 23:02:40 +03:00
|
|
|
// Copyright (c) Vitaliy Filippov, 2019+
|
2021-02-06 01:26:07 +03:00
|
|
|
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
|
2020-09-17 23:02:40 +03:00
|
|
|
|
2020-06-25 11:59:31 +03:00
|
|
|
// QEMU block driver
|
|
|
|
|
2021-11-29 01:40:59 +03:00
|
|
|
#ifdef VITASTOR_SOURCE_TREE
|
2020-11-04 23:10:29 +03:00
|
|
|
#define BUILD_DSO
|
2020-06-25 11:59:31 +03:00
|
|
|
#define _GNU_SOURCE
|
2021-11-29 01:40:59 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
#include "qemu/osdep.h"
|
2021-12-02 01:03:19 +03:00
|
|
|
#include "qemu/main-loop.h"
|
2023-04-25 01:39:20 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 8
|
|
|
|
#include "block/block-io.h"
|
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
#include "block/block_int.h"
|
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "qapi/qmp/qdict.h"
|
|
|
|
#include "qapi/qmp/qerror.h"
|
|
|
|
#include "qemu/uri.h"
|
|
|
|
#include "qemu/error-report.h"
|
|
|
|
#include "qemu/module.h"
|
|
|
|
#include "qemu/option.h"
|
2020-11-06 20:04:56 +03:00
|
|
|
|
|
|
|
#if QEMU_VERSION_MAJOR >= 3
|
|
|
|
#include "qemu/units.h"
|
|
|
|
#include "block/qdict.h"
|
2020-06-25 11:59:31 +03:00
|
|
|
#include "qemu/cutils.h"
|
2021-11-08 20:41:23 +03:00
|
|
|
#elif QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 10
|
|
|
|
#include "qemu/cutils.h"
|
|
|
|
#include "qapi/qmp/qstring.h"
|
|
|
|
#include "qapi/qmp/qjson.h"
|
2020-11-06 20:04:56 +03:00
|
|
|
#else
|
|
|
|
#include "qapi/qmp/qint.h"
|
|
|
|
#define qdict_put_int(options, name, num_val) qdict_put_obj(options, name, QOBJECT(qint_from_int(num_val)))
|
|
|
|
#define qdict_put_str(options, name, value) qdict_put_obj(options, name, QOBJECT(qstring_from_str(value)))
|
|
|
|
#define qobject_unref QDECREF
|
|
|
|
#endif
|
2023-06-21 02:09:12 +03:00
|
|
|
#if QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2 || QEMU_VERSION_MAJOR > 4
|
|
|
|
#include "sysemu/replay.h"
|
|
|
|
#else
|
|
|
|
#include "sysemu/sysemu.h"
|
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2021-06-19 00:23:28 +03:00
|
|
|
#include "vitastor_c.h"
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2021-11-29 01:40:59 +03:00
|
|
|
#ifdef VITASTOR_SOURCE_TREE
|
2020-11-04 23:10:29 +03:00
|
|
|
void qemu_module_dummy(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSO_STAMP_FUN(void)
|
|
|
|
{
|
|
|
|
}
|
2021-11-29 01:40:59 +03:00
|
|
|
#endif
|
2020-11-04 23:10:29 +03:00
|
|
|
|
2023-06-21 02:09:12 +03:00
|
|
|
typedef struct VitastorFdData VitastorFdData;
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
typedef struct VitastorClient
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
void *proxy;
|
2023-07-03 00:42:31 +03:00
|
|
|
int uring_eventfd;
|
|
|
|
|
2021-02-10 01:21:57 +03:00
|
|
|
void *watch;
|
2021-04-30 01:06:21 +03:00
|
|
|
char *config_path;
|
2020-06-26 02:18:58 +03:00
|
|
|
char *etcd_host;
|
|
|
|
char *etcd_prefix;
|
2021-02-10 01:21:57 +03:00
|
|
|
char *image;
|
2023-01-06 17:33:49 +03:00
|
|
|
int skip_parents;
|
2020-06-25 11:59:31 +03:00
|
|
|
uint64_t inode;
|
2020-09-05 17:09:20 +03:00
|
|
|
uint64_t pool;
|
2020-06-25 11:59:31 +03:00
|
|
|
uint64_t size;
|
2021-02-10 01:21:57 +03:00
|
|
|
long readonly;
|
2021-06-19 00:23:28 +03:00
|
|
|
int use_rdma;
|
2021-04-29 01:31:58 +03:00
|
|
|
char *rdma_device;
|
|
|
|
int rdma_port_num;
|
|
|
|
int rdma_gid_index;
|
|
|
|
int rdma_mtu;
|
2020-06-25 11:59:31 +03:00
|
|
|
QemuMutex mutex;
|
2023-06-21 02:09:12 +03:00
|
|
|
AioContext *ctx;
|
|
|
|
VitastorFdData **fds;
|
|
|
|
int fd_count, fd_alloc;
|
2023-07-03 02:18:52 +03:00
|
|
|
int bh_uring_scheduled;
|
2023-01-06 17:33:49 +03:00
|
|
|
|
|
|
|
uint64_t last_bitmap_inode, last_bitmap_offset, last_bitmap_len;
|
|
|
|
uint32_t last_bitmap_granularity;
|
|
|
|
uint8_t *last_bitmap;
|
2020-08-03 23:50:50 +03:00
|
|
|
} VitastorClient;
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2023-06-21 02:09:12 +03:00
|
|
|
typedef struct VitastorFdData
|
|
|
|
{
|
|
|
|
VitastorClient *cli;
|
|
|
|
int fd;
|
|
|
|
IOHandler *fd_read, *fd_write;
|
|
|
|
void *opaque;
|
|
|
|
} VitastorFdData;
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
typedef struct VitastorRPC
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
BlockDriverState *bs;
|
|
|
|
Coroutine *co;
|
|
|
|
QEMUIOVector *iov;
|
2021-02-10 01:21:57 +03:00
|
|
|
long ret;
|
2020-06-25 11:59:31 +03:00
|
|
|
int complete;
|
2023-01-06 17:33:49 +03:00
|
|
|
uint64_t inode, offset, len;
|
|
|
|
uint32_t bitmap_granularity;
|
|
|
|
uint8_t *bitmap;
|
2023-06-21 02:09:12 +03:00
|
|
|
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
|
|
QEMUBH *bh;
|
|
|
|
#endif
|
2020-08-03 23:50:50 +03:00
|
|
|
} VitastorRPC;
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2023-07-03 02:18:52 +03:00
|
|
|
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
|
|
typedef struct VitastorBH
|
|
|
|
{
|
|
|
|
VitastorClient *cli;
|
|
|
|
QEMUBH *bh;
|
|
|
|
} VitastorBH;
|
|
|
|
#endif
|
|
|
|
|
2021-02-10 01:21:57 +03:00
|
|
|
static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task);
|
2023-06-21 02:09:12 +03:00
|
|
|
static void vitastor_co_generic_cb(void *opaque, long retval);
|
2021-06-19 01:00:52 +03:00
|
|
|
static void vitastor_co_read_cb(void *opaque, long retval, uint64_t version);
|
2021-02-10 01:21:57 +03:00
|
|
|
static void vitastor_close(BlockDriverState *bs);
|
|
|
|
|
2021-07-02 23:10:32 +03:00
|
|
|
static char *qemu_vitastor_next_tok(char *src, char delim, char **p)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
char *end;
|
|
|
|
*p = NULL;
|
|
|
|
for (end = src; *end; ++end)
|
|
|
|
{
|
|
|
|
if (*end == delim)
|
|
|
|
break;
|
|
|
|
if (*end == '\\' && end[1] != '\0')
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
if (*end == delim)
|
|
|
|
{
|
|
|
|
*p = end + 1;
|
|
|
|
*end = '\0';
|
|
|
|
}
|
|
|
|
return src;
|
|
|
|
}
|
|
|
|
|
2021-07-02 23:10:32 +03:00
|
|
|
static void qemu_vitastor_unescape(char *src)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
for (p = src; *src; ++src, ++p)
|
|
|
|
{
|
|
|
|
if (*src == '\\' && src[1] != '\0')
|
|
|
|
src++;
|
|
|
|
*p = *src;
|
|
|
|
}
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
// vitastor[:key=value]*
|
2021-04-30 01:06:21 +03:00
|
|
|
// vitastor[:etcd_host=127.0.0.1]:inode=1:pool=1[:rdma_gid_index=3]
|
|
|
|
// vitastor:config_path=/etc/vitastor/vitastor.conf:image=testimg
|
2020-08-03 23:50:50 +03:00
|
|
|
static void vitastor_parse_filename(const char *filename, QDict *options, Error **errp)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
const char *start;
|
|
|
|
char *p, *buf;
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
if (!strstart(filename, "vitastor:", &start))
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
error_setg(errp, "File name must start with 'vitastor:'");
|
2020-06-25 11:59:31 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = g_strdup(start);
|
|
|
|
p = buf;
|
|
|
|
|
|
|
|
// The following are all key/value pairs
|
|
|
|
while (p)
|
|
|
|
{
|
2021-11-24 11:28:10 +03:00
|
|
|
int i;
|
2020-06-25 11:59:31 +03:00
|
|
|
char *name, *value;
|
2021-07-02 23:10:32 +03:00
|
|
|
name = qemu_vitastor_next_tok(p, '=', &p);
|
2020-06-25 11:59:31 +03:00
|
|
|
if (!p)
|
|
|
|
{
|
|
|
|
error_setg(errp, "conf option %s has no value", name);
|
|
|
|
break;
|
|
|
|
}
|
2021-11-24 11:28:10 +03:00
|
|
|
for (i = 0; i < strlen(name); i++)
|
2021-11-21 16:16:46 +03:00
|
|
|
if (name[i] == '_')
|
|
|
|
name[i] = '-';
|
2021-07-02 23:10:32 +03:00
|
|
|
qemu_vitastor_unescape(name);
|
|
|
|
value = qemu_vitastor_next_tok(p, ':', &p);
|
|
|
|
qemu_vitastor_unescape(value);
|
2021-04-29 01:31:58 +03:00
|
|
|
if (!strcmp(name, "inode") ||
|
|
|
|
!strcmp(name, "pool") ||
|
|
|
|
!strcmp(name, "size") ||
|
2023-01-06 17:33:49 +03:00
|
|
|
!strcmp(name, "skip-parents") ||
|
2021-11-21 16:16:46 +03:00
|
|
|
!strcmp(name, "use-rdma") ||
|
|
|
|
!strcmp(name, "rdma-port_num") ||
|
|
|
|
!strcmp(name, "rdma-gid-index") ||
|
|
|
|
!strcmp(name, "rdma-mtu"))
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2023-08-24 02:23:55 +03:00
|
|
|
#if QEMU_VERSION_MAJOR < 8 || QEMU_VERSION_MAJOR == 8 && QEMU_VERSION_MINOR < 1
|
2023-12-04 01:59:07 +03:00
|
|
|
unsigned long long num_val;
|
2020-06-25 11:59:31 +03:00
|
|
|
if (parse_uint_full(value, &num_val, 0))
|
2023-08-24 02:23:55 +03:00
|
|
|
#else
|
2023-12-04 01:59:07 +03:00
|
|
|
uint64_t num_val;
|
2023-08-24 02:23:55 +03:00
|
|
|
if (parse_uint_full(value, 0, &num_val))
|
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
error_setg(errp, "Illegal %s: %s", name, value);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
qdict_put_int(options, name, num_val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qdict_put_str(options, name, value);
|
|
|
|
}
|
|
|
|
}
|
2021-02-10 01:21:57 +03:00
|
|
|
if (!qdict_get_try_str(options, "image"))
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2021-02-10 01:21:57 +03:00
|
|
|
if (!qdict_get_try_int(options, "inode", 0))
|
|
|
|
{
|
|
|
|
error_setg(errp, "one of image (name) and inode (number) must be specified");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (!(qdict_get_try_int(options, "inode", 0) >> (64-POOL_ID_BITS)) &&
|
|
|
|
!qdict_get_try_int(options, "pool", 0))
|
|
|
|
{
|
|
|
|
error_setg(errp, "pool number must be specified or included in the inode number");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (!qdict_get_try_int(options, "size", 0))
|
|
|
|
{
|
|
|
|
error_setg(errp, "size must be specified when inode number is used instead of image name");
|
|
|
|
goto out;
|
|
|
|
}
|
2020-06-25 11:59:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
g_free(buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-18 01:35:08 +03:00
|
|
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
2023-07-03 00:42:31 +03:00
|
|
|
static void vitastor_uring_handler(void *opaque)
|
|
|
|
{
|
|
|
|
VitastorClient *client = (VitastorClient*)opaque;
|
|
|
|
qemu_mutex_lock(&client->mutex);
|
2023-07-03 02:18:52 +03:00
|
|
|
client->bh_uring_scheduled = 0;
|
2023-07-20 22:53:53 +03:00
|
|
|
vitastor_c_uring_handle_events(client->proxy);
|
2023-07-03 00:42:31 +03:00
|
|
|
qemu_mutex_unlock(&client->mutex);
|
|
|
|
}
|
|
|
|
|
2023-07-03 02:18:52 +03:00
|
|
|
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
|
|
static void vitastor_bh_uring_handler(void *opaque)
|
|
|
|
{
|
|
|
|
VitastorBH *vbh = opaque;
|
|
|
|
vitastor_bh_handler(vbh->cli);
|
|
|
|
qemu_bh_delete(vbh->bh);
|
|
|
|
free(vbh);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-07-03 00:42:31 +03:00
|
|
|
static void vitastor_schedule_uring_handler(VitastorClient *client)
|
|
|
|
{
|
|
|
|
void *opaque = client;
|
2023-07-04 00:23:59 +03:00
|
|
|
if (client->uring_eventfd >= 0 && !client->bh_uring_scheduled)
|
2023-07-03 02:18:52 +03:00
|
|
|
{
|
|
|
|
client->bh_uring_scheduled = 1;
|
2023-07-03 00:42:31 +03:00
|
|
|
#if QEMU_VERSION_MAJOR > 4 || QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2
|
2023-07-03 02:18:52 +03:00
|
|
|
replay_bh_schedule_oneshot_event(client->ctx, vitastor_uring_handler, opaque);
|
2023-07-03 00:42:31 +03:00
|
|
|
#elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
|
2023-07-03 02:18:52 +03:00
|
|
|
aio_bh_schedule_oneshot(client->ctx, vitastor_uring_handler, opaque);
|
2023-07-18 23:30:20 +03:00
|
|
|
#else
|
2023-07-03 02:18:52 +03:00
|
|
|
VitastorBH *vbh = (VitastorBH*)malloc(sizeof(VitastorBH));
|
|
|
|
vbh->cli = client;
|
2023-07-18 23:30:20 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 2
|
2023-07-03 02:18:52 +03:00
|
|
|
vbh->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_bh_uring_handler, vbh);
|
2023-07-03 00:42:31 +03:00
|
|
|
#else
|
2023-07-18 23:30:20 +03:00
|
|
|
vbh->bh = qemu_bh_new(vitastor_bh_uring_handler, vbh);
|
|
|
|
#endif
|
|
|
|
qemu_bh_schedule(vbh->bh);
|
2023-07-03 00:42:31 +03:00
|
|
|
#endif
|
2023-07-03 02:18:52 +03:00
|
|
|
}
|
2023-07-03 00:42:31 +03:00
|
|
|
}
|
2023-07-18 01:35:08 +03:00
|
|
|
#else
|
|
|
|
static void vitastor_schedule_uring_handler(VitastorClient *client)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
2023-07-03 00:42:31 +03:00
|
|
|
|
2021-02-10 01:21:57 +03:00
|
|
|
static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
|
|
|
|
{
|
|
|
|
BlockDriverState *bs = task->bs;
|
|
|
|
VitastorClient *client = bs->opaque;
|
|
|
|
task->co = qemu_coroutine_self();
|
|
|
|
|
|
|
|
qemu_mutex_lock(&client->mutex);
|
2023-06-21 02:09:12 +03:00
|
|
|
vitastor_c_watch_inode(client->proxy, client->image, vitastor_co_generic_cb, task);
|
2023-07-03 00:42:31 +03:00
|
|
|
vitastor_schedule_uring_handler(client);
|
2021-02-10 01:21:57 +03:00
|
|
|
qemu_mutex_unlock(&client->mutex);
|
|
|
|
|
|
|
|
while (!task->complete)
|
|
|
|
{
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-21 02:09:12 +03:00
|
|
|
static void vitastor_aio_fd_read(void *fddv)
|
2022-12-15 03:01:05 +03:00
|
|
|
{
|
2023-06-21 02:09:12 +03:00
|
|
|
VitastorFdData *fdd = (VitastorFdData*)fddv;
|
|
|
|
qemu_mutex_lock(&fdd->cli->mutex);
|
|
|
|
fdd->fd_read(fdd->opaque);
|
2023-07-03 01:32:32 +03:00
|
|
|
vitastor_schedule_uring_handler(fdd->cli);
|
2023-06-21 02:09:12 +03:00
|
|
|
qemu_mutex_unlock(&fdd->cli->mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vitastor_aio_fd_write(void *fddv)
|
|
|
|
{
|
|
|
|
VitastorFdData *fdd = (VitastorFdData*)fddv;
|
|
|
|
qemu_mutex_lock(&fdd->cli->mutex);
|
|
|
|
fdd->fd_write(fdd->opaque);
|
2023-07-03 01:32:32 +03:00
|
|
|
vitastor_schedule_uring_handler(fdd->cli);
|
2023-06-21 02:09:12 +03:00
|
|
|
qemu_mutex_unlock(&fdd->cli->mutex);
|
|
|
|
}
|
|
|
|
|
2023-07-03 00:42:31 +03:00
|
|
|
static void universal_aio_set_fd_handler(AioContext *ctx, int fd, IOHandler *fd_read, IOHandler *fd_write, void *opaque)
|
|
|
|
{
|
|
|
|
aio_set_fd_handler(ctx, fd,
|
2023-08-24 02:23:55 +03:00
|
|
|
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 5 || QEMU_VERSION_MAJOR >= 3 && (QEMU_VERSION_MAJOR < 8 || QEMU_VERSION_MAJOR == 8 && QEMU_VERSION_MINOR < 1)
|
2023-07-03 00:42:31 +03:00
|
|
|
0 /*is_external*/,
|
|
|
|
#endif
|
|
|
|
fd_read,
|
|
|
|
fd_write,
|
|
|
|
#if QEMU_VERSION_MAJOR == 1 && QEMU_VERSION_MINOR <= 6 || QEMU_VERSION_MAJOR < 1
|
|
|
|
NULL /*io_flush*/,
|
|
|
|
#endif
|
|
|
|
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 9 || QEMU_VERSION_MAJOR >= 3
|
|
|
|
NULL /*io_poll*/,
|
|
|
|
#endif
|
|
|
|
#if QEMU_VERSION_MAJOR >= 7
|
|
|
|
NULL /*io_poll_ready*/,
|
|
|
|
#endif
|
|
|
|
opaque);
|
|
|
|
}
|
|
|
|
|
2023-06-21 02:09:12 +03:00
|
|
|
static void vitastor_aio_set_fd_handler(void *vcli, int fd, int unused1, IOHandler *fd_read, IOHandler *fd_write, void *unused2, void *opaque)
|
|
|
|
{
|
|
|
|
VitastorClient *client = (VitastorClient*)vcli;
|
|
|
|
VitastorFdData *fdd = NULL;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < client->fd_count; i++)
|
|
|
|
{
|
|
|
|
if (client->fds[i]->fd == fd)
|
|
|
|
{
|
|
|
|
if (fd_read || fd_write)
|
|
|
|
{
|
|
|
|
fdd = client->fds[i];
|
|
|
|
fdd->opaque = opaque;
|
|
|
|
fdd->fd_read = fd_read;
|
|
|
|
fdd->fd_write = fd_write;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int j = i+1; j < client->fd_count; j++)
|
|
|
|
client->fds[j-1] = client->fds[j];
|
|
|
|
client->fd_count--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((fd_read || fd_write) && !fdd)
|
|
|
|
{
|
|
|
|
fdd = (VitastorFdData*)malloc(sizeof(VitastorFdData));
|
|
|
|
fdd->cli = client;
|
|
|
|
fdd->fd = fd;
|
|
|
|
fdd->fd_read = fd_read;
|
|
|
|
fdd->fd_write = fd_write;
|
|
|
|
fdd->opaque = opaque;
|
|
|
|
if (client->fd_count >= client->fd_alloc)
|
|
|
|
{
|
|
|
|
client->fd_alloc = client->fd_alloc*2;
|
|
|
|
if (client->fd_alloc < 16)
|
|
|
|
client->fd_alloc = 16;
|
|
|
|
client->fds = (VitastorFdData**)realloc(client->fds, sizeof(VitastorFdData*) * client->fd_alloc);
|
|
|
|
}
|
|
|
|
client->fds[client->fd_count++] = fdd;
|
|
|
|
}
|
2023-07-03 00:42:31 +03:00
|
|
|
universal_aio_set_fd_handler(
|
|
|
|
client->ctx, fd, fd_read ? vitastor_aio_fd_read : NULL, fd_write ? vitastor_aio_fd_write : NULL, fdd
|
|
|
|
);
|
2022-12-15 03:01:05 +03:00
|
|
|
}
|
|
|
|
|
2023-10-26 17:43:47 +03:00
|
|
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
2023-08-12 20:26:40 +03:00
|
|
|
typedef struct str_array
|
|
|
|
{
|
|
|
|
const char **items;
|
|
|
|
int len, alloc;
|
|
|
|
} str_array;
|
|
|
|
|
|
|
|
static void strarray_push(str_array *a, const char *str)
|
|
|
|
{
|
|
|
|
if (a->len >= a->alloc)
|
|
|
|
{
|
|
|
|
a->alloc = !a->alloc ? 4 : 2*a->alloc;
|
|
|
|
a->items = (const char**)realloc(a->items, a->alloc*sizeof(char*));
|
|
|
|
if (!a->items)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "bad alloc\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
a->items[a->len++] = str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void strarray_push_kv(str_array *a, const char *key, const char *value)
|
|
|
|
{
|
|
|
|
if (key && value)
|
|
|
|
{
|
|
|
|
strarray_push(a, key);
|
|
|
|
strarray_push(a, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void strarray_free(str_array *a)
|
|
|
|
{
|
|
|
|
free(a->items);
|
|
|
|
a->items = NULL;
|
|
|
|
a->len = a->alloc = 0;
|
|
|
|
}
|
2023-10-26 17:43:47 +03:00
|
|
|
#endif
|
2023-08-12 20:26:40 +03:00
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2023-01-06 17:33:49 +03:00
|
|
|
VitastorRPC task;
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
2023-01-06 17:33:49 +03:00
|
|
|
void *image = NULL;
|
2020-06-25 11:59:31 +03:00
|
|
|
int64_t ret = 0;
|
2021-02-10 01:21:57 +03:00
|
|
|
qemu_mutex_init(&client->mutex);
|
2021-11-21 16:16:46 +03:00
|
|
|
client->config_path = g_strdup(qdict_get_try_str(options, "config-path"));
|
2021-07-02 22:47:01 +03:00
|
|
|
// FIXME: Rename to etcd_address
|
2021-11-21 16:16:46 +03:00
|
|
|
client->etcd_host = g_strdup(qdict_get_try_str(options, "etcd-host"));
|
|
|
|
client->etcd_prefix = g_strdup(qdict_get_try_str(options, "etcd-prefix"));
|
2023-01-06 17:33:49 +03:00
|
|
|
client->skip_parents = qdict_get_try_int(options, "skip-parents", 0);
|
2021-11-21 16:16:46 +03:00
|
|
|
client->use_rdma = qdict_get_try_int(options, "use-rdma", -1);
|
|
|
|
client->rdma_device = g_strdup(qdict_get_try_str(options, "rdma-device"));
|
|
|
|
client->rdma_port_num = qdict_get_try_int(options, "rdma-port-num", 0);
|
|
|
|
client->rdma_gid_index = qdict_get_try_int(options, "rdma-gid-index", 0);
|
|
|
|
client->rdma_mtu = qdict_get_try_int(options, "rdma-mtu", 0);
|
2023-06-21 02:09:12 +03:00
|
|
|
client->ctx = bdrv_get_aio_context(bs);
|
2023-10-26 17:43:47 +03:00
|
|
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
2023-08-12 20:26:40 +03:00
|
|
|
str_array opt = {};
|
|
|
|
strarray_push_kv(&opt, "config_path", qdict_get_try_str(options, "config-path"));
|
|
|
|
strarray_push_kv(&opt, "etcd_address", qdict_get_try_str(options, "etcd-host"));
|
|
|
|
strarray_push_kv(&opt, "etcd_prefix", qdict_get_try_str(options, "etcd-prefix"));
|
|
|
|
strarray_push_kv(&opt, "use_rdma", qdict_get_try_str(options, "use-rdma"));
|
|
|
|
strarray_push_kv(&opt, "rdma_device", qdict_get_try_str(options, "rdma-device"));
|
|
|
|
strarray_push_kv(&opt, "rdma_port_num", qdict_get_try_str(options, "rdma-port-num"));
|
|
|
|
strarray_push_kv(&opt, "rdma_gid_index", qdict_get_try_str(options, "rdma-gid-index"));
|
|
|
|
strarray_push_kv(&opt, "rdma_mtu", qdict_get_try_str(options, "rdma-mtu"));
|
|
|
|
strarray_push_kv(&opt, "client_writeback_allowed", (flags & BDRV_O_NOCACHE) ? "0" : "1");
|
|
|
|
client->proxy = vitastor_c_create_uring_json(opt.items, opt.len);
|
|
|
|
strarray_free(&opt);
|
|
|
|
if (client->proxy)
|
2023-07-04 00:23:59 +03:00
|
|
|
{
|
|
|
|
client->uring_eventfd = vitastor_c_uring_register_eventfd(client->proxy);
|
|
|
|
if (client->uring_eventfd < 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "vitastor: failed to create io_uring eventfd: %s\n", strerror(errno));
|
|
|
|
error_setg(errp, "failed to create io_uring eventfd");
|
|
|
|
vitastor_close(bs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
universal_aio_set_fd_handler(client->ctx, client->uring_eventfd, vitastor_uring_handler, NULL, client);
|
2023-07-03 00:42:31 +03:00
|
|
|
}
|
2023-08-12 20:26:40 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Writeback cache is unusable without io_uring because the client can't correctly flush on exit
|
|
|
|
fprintf(stderr, "vitastor: failed to create io_uring: %s - I/O will be slower%s\n",
|
|
|
|
strerror(errno), (flags & BDRV_O_NOCACHE ? "" : " and writeback cache will be disabled"));
|
2023-10-26 17:43:47 +03:00
|
|
|
#endif
|
2023-08-12 20:26:40 +03:00
|
|
|
client->uring_eventfd = -1;
|
|
|
|
client->proxy = vitastor_c_create_qemu(
|
|
|
|
vitastor_aio_set_fd_handler, client, client->config_path, client->etcd_host, client->etcd_prefix,
|
|
|
|
client->use_rdma, client->rdma_device, client->rdma_port_num, client->rdma_gid_index, client->rdma_mtu, 0
|
|
|
|
);
|
2023-10-26 17:43:47 +03:00
|
|
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
2023-08-12 20:26:40 +03:00
|
|
|
}
|
2023-10-26 17:43:47 +03:00
|
|
|
#endif
|
2023-01-06 17:33:49 +03:00
|
|
|
image = client->image = g_strdup(qdict_get_try_str(options, "image"));
|
2021-02-10 01:21:57 +03:00
|
|
|
client->readonly = (flags & BDRV_O_RDWR) ? 1 : 0;
|
2023-01-06 17:33:49 +03:00
|
|
|
// Get image metadata (size and readonly flag) or just wait until the client is ready
|
|
|
|
if (!image)
|
2023-01-13 23:44:33 +03:00
|
|
|
client->image = (char*)"x";
|
2023-01-06 17:33:49 +03:00
|
|
|
task.complete = 0;
|
|
|
|
task.bs = bs;
|
|
|
|
if (qemu_in_coroutine())
|
|
|
|
{
|
|
|
|
vitastor_co_get_metadata(&task);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-04-25 01:39:20 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 8
|
|
|
|
aio_co_enter(bdrv_get_aio_context(bs), qemu_coroutine_create((void(*)(void*))vitastor_co_get_metadata, &task));
|
|
|
|
#elif QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 9 || QEMU_VERSION_MAJOR >= 3
|
2023-01-06 17:33:49 +03:00
|
|
|
bdrv_coroutine_enter(bs, qemu_coroutine_create((void(*)(void*))vitastor_co_get_metadata, &task));
|
2023-04-25 01:39:20 +03:00
|
|
|
#else
|
|
|
|
qemu_coroutine_enter(qemu_coroutine_create((void(*)(void*))vitastor_co_get_metadata, &task));
|
|
|
|
#endif
|
2023-01-06 17:33:49 +03:00
|
|
|
BDRV_POLL_WHILE(bs, !task.complete);
|
|
|
|
}
|
|
|
|
client->image = image;
|
2021-02-10 01:21:57 +03:00
|
|
|
if (client->image)
|
|
|
|
{
|
|
|
|
client->watch = (void*)task.ret;
|
2021-06-19 00:23:28 +03:00
|
|
|
client->readonly = client->readonly || vitastor_c_inode_get_readonly(client->watch);
|
|
|
|
client->size = vitastor_c_inode_get_size(client->watch);
|
|
|
|
if (!vitastor_c_inode_get_num(client->watch))
|
2021-02-10 01:21:57 +03:00
|
|
|
{
|
|
|
|
error_setg(errp, "image does not exist");
|
|
|
|
vitastor_close(bs);
|
2021-12-03 00:41:49 +03:00
|
|
|
return -1;
|
2021-02-10 01:21:57 +03:00
|
|
|
}
|
|
|
|
if (!client->size)
|
|
|
|
{
|
2021-12-03 00:22:03 +03:00
|
|
|
client->size = qdict_get_try_int(options, "size", 0);
|
2021-02-10 01:21:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
client->watch = NULL;
|
2021-12-03 00:22:03 +03:00
|
|
|
client->inode = qdict_get_try_int(options, "inode", 0);
|
|
|
|
client->pool = qdict_get_try_int(options, "pool", 0);
|
2021-02-10 01:21:57 +03:00
|
|
|
if (client->pool)
|
|
|
|
{
|
2022-04-16 01:39:55 +03:00
|
|
|
client->inode = (client->inode & (((uint64_t)1 << (64-POOL_ID_BITS)) - 1)) | (client->pool << (64-POOL_ID_BITS));
|
2021-02-10 01:21:57 +03:00
|
|
|
}
|
2021-12-03 00:22:03 +03:00
|
|
|
client->size = qdict_get_try_int(options, "size", 0);
|
2023-01-06 17:33:49 +03:00
|
|
|
vitastor_c_close_watch(client->proxy, (void*)task.ret);
|
2021-02-10 01:21:57 +03:00
|
|
|
}
|
|
|
|
if (!client->size)
|
|
|
|
{
|
|
|
|
error_setg(errp, "image size not specified");
|
|
|
|
vitastor_close(bs);
|
|
|
|
return -1;
|
|
|
|
}
|
2020-06-25 11:59:31 +03:00
|
|
|
bs->total_sectors = client->size / BDRV_SECTOR_SIZE;
|
2023-09-06 17:37:52 +03:00
|
|
|
#if QEMU_VERSION_MAJOR > 5 || QEMU_VERSION_MAJOR == 5 && QEMU_VERSION_MINOR >= 1
|
|
|
|
/* When extending regular files, we get zeros from the OS */
|
|
|
|
bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
|
|
|
|
#endif
|
2021-02-10 01:21:57 +03:00
|
|
|
//client->aio_context = bdrv_get_aio_context(bs);
|
2021-11-21 16:16:46 +03:00
|
|
|
qdict_del(options, "use-rdma");
|
|
|
|
qdict_del(options, "rdma-mtu");
|
|
|
|
qdict_del(options, "rdma-gid-index");
|
|
|
|
qdict_del(options, "rdma-port-num");
|
|
|
|
qdict_del(options, "rdma-device");
|
|
|
|
qdict_del(options, "config-path");
|
|
|
|
qdict_del(options, "etcd-host");
|
|
|
|
qdict_del(options, "etcd-prefix");
|
2021-02-10 01:21:57 +03:00
|
|
|
qdict_del(options, "image");
|
2020-06-26 02:18:58 +03:00
|
|
|
qdict_del(options, "inode");
|
2020-09-05 17:09:20 +03:00
|
|
|
qdict_del(options, "pool");
|
2020-06-26 02:18:58 +03:00
|
|
|
qdict_del(options, "size");
|
2023-01-06 17:33:49 +03:00
|
|
|
qdict_del(options, "skip-parents");
|
2020-06-25 11:59:31 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static void vitastor_close(BlockDriverState *bs)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
2021-06-19 00:23:28 +03:00
|
|
|
vitastor_c_destroy(client->proxy);
|
2023-06-21 02:09:12 +03:00
|
|
|
if (client->fds)
|
|
|
|
{
|
|
|
|
free(client->fds);
|
|
|
|
client->fds = NULL;
|
|
|
|
client->fd_alloc = client->fd_count = 0;
|
|
|
|
}
|
2020-06-26 02:18:58 +03:00
|
|
|
qemu_mutex_destroy(&client->mutex);
|
2021-04-30 01:06:21 +03:00
|
|
|
if (client->config_path)
|
|
|
|
g_free(client->config_path);
|
|
|
|
if (client->etcd_host)
|
|
|
|
g_free(client->etcd_host);
|
2020-06-26 02:18:58 +03:00
|
|
|
if (client->etcd_prefix)
|
|
|
|
g_free(client->etcd_prefix);
|
2021-02-10 01:21:57 +03:00
|
|
|
if (client->image)
|
|
|
|
g_free(client->image);
|
2023-01-06 17:33:49 +03:00
|
|
|
free(client->last_bitmap);
|
|
|
|
client->last_bitmap = NULL;
|
2020-06-25 11:59:31 +03:00
|
|
|
}
|
|
|
|
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
|
2020-08-03 23:50:50 +03:00
|
|
|
static int vitastor_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
bsz->phys = 4096;
|
2021-12-08 23:43:36 +03:00
|
|
|
bsz->log = 512;
|
2020-06-25 11:59:31 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2020-11-06 20:04:56 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2021-12-02 02:25:50 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 12
|
2020-09-20 01:46:07 +03:00
|
|
|
static int coroutine_fn vitastor_co_create_opts(
|
|
|
|
#if QEMU_VERSION_MAJOR >= 4
|
|
|
|
BlockDriver *drv,
|
|
|
|
#endif
|
|
|
|
const char *url, QemuOpts *opts, Error **errp)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
QDict *options;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
options = qdict_new();
|
2020-08-03 23:50:50 +03:00
|
|
|
vitastor_parse_filename(url, options, errp);
|
2020-06-26 02:18:58 +03:00
|
|
|
if (*errp)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
ret = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
// inodes don't require creation in Vitastor. FIXME: They will when there will be some metadata
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
out:
|
|
|
|
qobject_unref(options);
|
|
|
|
return ret;
|
|
|
|
}
|
2021-11-08 20:41:23 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-11-06 20:04:56 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3
|
2020-09-20 01:46:07 +03:00
|
|
|
static int coroutine_fn vitastor_co_truncate(BlockDriverState *bs, int64_t offset,
|
|
|
|
#if QEMU_VERSION_MAJOR >= 4
|
|
|
|
bool exact,
|
|
|
|
#endif
|
2020-10-06 02:35:11 +03:00
|
|
|
PreallocMode prealloc,
|
2021-12-02 01:03:19 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 5 && QEMU_VERSION_MINOR >= 1 || QEMU_VERSION_MAJOR > 5 || defined RHEL_BDRV_CO_TRUNCATE_FLAGS
|
2020-10-06 02:35:11 +03:00
|
|
|
BdrvRequestFlags flags,
|
|
|
|
#endif
|
|
|
|
Error **errp)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
if (prealloc != PREALLOC_MODE_OFF)
|
|
|
|
{
|
|
|
|
error_setg(errp, "Unsupported preallocation mode '%s'", PreallocMode_str(prealloc));
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Resize inode to <offset> bytes
|
2023-08-22 02:12:12 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 4
|
|
|
|
client->size = exact || client->size < offset ? offset : client->size;
|
|
|
|
#else
|
|
|
|
client->size = offset;
|
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-11-06 20:04:56 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static int vitastor_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
|
|
|
bdi->cluster_size = 4096;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static int64_t vitastor_getlength(BlockDriverState *bs)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
2020-06-25 11:59:31 +03:00
|
|
|
return client->size;
|
|
|
|
}
|
|
|
|
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 0
|
2020-08-03 23:50:50 +03:00
|
|
|
static void vitastor_refresh_limits(BlockDriverState *bs, Error **errp)
|
2020-11-06 20:04:56 +03:00
|
|
|
#else
|
|
|
|
static int vitastor_refresh_limits(BlockDriverState *bs)
|
|
|
|
#endif
|
2020-06-26 02:18:58 +03:00
|
|
|
{
|
|
|
|
bs->bl.request_alignment = 4096;
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 3
|
2020-06-26 02:18:58 +03:00
|
|
|
bs->bl.min_mem_alignment = 4096;
|
2020-11-06 20:04:56 +03:00
|
|
|
#endif
|
2020-06-26 02:18:58 +03:00
|
|
|
bs->bl.opt_mem_alignment = 4096;
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR < 2 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR == 0
|
2020-11-06 20:04:56 +03:00
|
|
|
return 0;
|
|
|
|
#endif
|
2020-06-26 02:18:58 +03:00
|
|
|
}
|
|
|
|
|
2021-12-02 01:03:19 +03:00
|
|
|
//static int64_t vitastor_get_allocated_file_size(BlockDriverState *bs)
|
|
|
|
//{
|
|
|
|
// return 0;
|
|
|
|
//}
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
*task = (VitastorRPC) {
|
2020-06-25 11:59:31 +03:00
|
|
|
.co = qemu_coroutine_self(),
|
|
|
|
.bs = bs,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-06-21 02:09:12 +03:00
|
|
|
static void vitastor_co_generic_bh_cb(void *opaque)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorRPC *task = opaque;
|
2020-06-25 11:59:31 +03:00
|
|
|
task->complete = 1;
|
2020-06-26 02:18:58 +03:00
|
|
|
if (qemu_coroutine_self() != task->co)
|
|
|
|
{
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 8
|
2020-06-26 02:18:58 +03:00
|
|
|
aio_co_wake(task->co);
|
2020-11-06 20:04:56 +03:00
|
|
|
#else
|
2023-06-21 02:09:12 +03:00
|
|
|
#if QEMU_VERSION_MAJOR == 2
|
|
|
|
qemu_bh_delete(task->bh);
|
|
|
|
#endif
|
2020-11-06 20:04:56 +03:00
|
|
|
qemu_coroutine_enter(task->co, NULL);
|
|
|
|
qemu_aio_release(task);
|
|
|
|
#endif
|
2020-06-26 02:18:58 +03:00
|
|
|
}
|
2020-06-25 11:59:31 +03:00
|
|
|
}
|
|
|
|
|
2023-06-21 02:09:12 +03:00
|
|
|
static void vitastor_co_generic_cb(void *opaque, long retval)
|
|
|
|
{
|
|
|
|
VitastorRPC *task = opaque;
|
|
|
|
task->ret = retval;
|
|
|
|
#if QEMU_VERSION_MAJOR > 4 || QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2
|
|
|
|
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
|
|
#elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
|
|
|
|
aio_bh_schedule_oneshot(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
|
|
#elif QEMU_VERSION_MAJOR >= 2
|
|
|
|
task->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
|
|
qemu_bh_schedule(task->bh);
|
|
|
|
#else
|
2023-07-18 23:30:20 +03:00
|
|
|
task->bh = qemu_bh_new(vitastor_co_generic_bh_cb, opaque);
|
|
|
|
qemu_bh_schedule(task->bh);
|
2023-06-21 02:09:12 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-06-19 01:00:52 +03:00
|
|
|
static void vitastor_co_read_cb(void *opaque, long retval, uint64_t version)
|
|
|
|
{
|
2023-06-21 02:09:12 +03:00
|
|
|
vitastor_co_generic_cb(opaque, retval);
|
2021-06-19 01:00:52 +03:00
|
|
|
}
|
|
|
|
|
2022-12-15 03:01:05 +03:00
|
|
|
static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
|
|
|
|
#if QEMU_VERSION_MAJOR >= 7 || QEMU_VERSION_MAJOR == 6 && QEMU_VERSION_MINOR >= 2
|
|
|
|
int64_t offset, int64_t bytes, QEMUIOVector *iov, BdrvRequestFlags flags
|
|
|
|
#else
|
|
|
|
uint64_t offset, uint64_t bytes, QEMUIOVector *iov, int flags
|
|
|
|
#endif
|
|
|
|
)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
|
|
|
VitastorRPC task;
|
|
|
|
vitastor_co_init_task(bs, &task);
|
2020-06-25 11:59:31 +03:00
|
|
|
task.iov = iov;
|
|
|
|
|
2021-06-19 00:23:28 +03:00
|
|
|
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
2020-06-25 11:59:31 +03:00
|
|
|
qemu_mutex_lock(&client->mutex);
|
2021-06-19 01:00:52 +03:00
|
|
|
vitastor_c_read(client->proxy, inode, offset, bytes, iov->iov, iov->niov, vitastor_co_read_cb, &task);
|
2023-07-03 00:42:31 +03:00
|
|
|
vitastor_schedule_uring_handler(client);
|
2020-06-25 11:59:31 +03:00
|
|
|
qemu_mutex_unlock(&client->mutex);
|
|
|
|
|
|
|
|
while (!task.complete)
|
|
|
|
{
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
}
|
|
|
|
|
|
|
|
return task.ret;
|
|
|
|
}
|
|
|
|
|
2022-12-15 03:01:05 +03:00
|
|
|
static int coroutine_fn vitastor_co_pwritev(BlockDriverState *bs,
|
|
|
|
#if QEMU_VERSION_MAJOR >= 7 || QEMU_VERSION_MAJOR == 6 && QEMU_VERSION_MINOR >= 2
|
|
|
|
int64_t offset, int64_t bytes, QEMUIOVector *iov, BdrvRequestFlags flags
|
|
|
|
#else
|
|
|
|
uint64_t offset, uint64_t bytes, QEMUIOVector *iov, int flags
|
|
|
|
#endif
|
|
|
|
)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
|
|
|
VitastorRPC task;
|
|
|
|
vitastor_co_init_task(bs, &task);
|
2020-06-25 11:59:31 +03:00
|
|
|
task.iov = iov;
|
|
|
|
|
2023-01-06 17:33:49 +03:00
|
|
|
if (client->last_bitmap)
|
|
|
|
{
|
|
|
|
// Invalidate last bitmap on write
|
|
|
|
free(client->last_bitmap);
|
|
|
|
client->last_bitmap = NULL;
|
|
|
|
}
|
|
|
|
|
2021-06-19 00:23:28 +03:00
|
|
|
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
2020-06-25 11:59:31 +03:00
|
|
|
qemu_mutex_lock(&client->mutex);
|
2023-06-21 02:09:12 +03:00
|
|
|
vitastor_c_write(client->proxy, inode, offset, bytes, 0, iov->iov, iov->niov, vitastor_co_generic_cb, &task);
|
2023-07-03 00:42:31 +03:00
|
|
|
vitastor_schedule_uring_handler(client);
|
2020-06-25 11:59:31 +03:00
|
|
|
qemu_mutex_unlock(&client->mutex);
|
|
|
|
|
|
|
|
while (!task.complete)
|
|
|
|
{
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
}
|
|
|
|
|
|
|
|
return task.ret;
|
|
|
|
}
|
|
|
|
|
2023-01-06 17:33:49 +03:00
|
|
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 1
|
|
|
|
#if QEMU_VERSION_MAJOR >= 2 || QEMU_VERSION_MAJOR == 1 && QEMU_VERSION_MINOR >= 7
|
|
|
|
static void vitastor_co_read_bitmap_cb(void *opaque, long retval, uint8_t *bitmap)
|
|
|
|
{
|
|
|
|
VitastorRPC *task = opaque;
|
|
|
|
VitastorClient *client = task->bs->opaque;
|
|
|
|
task->ret = retval;
|
|
|
|
if (retval >= 0)
|
|
|
|
{
|
|
|
|
task->bitmap = bitmap;
|
|
|
|
if (client->last_bitmap_inode == task->inode &&
|
|
|
|
client->last_bitmap_offset == task->offset &&
|
|
|
|
client->last_bitmap_len == task->len)
|
|
|
|
{
|
|
|
|
free(client->last_bitmap);
|
|
|
|
client->last_bitmap = bitmap;
|
|
|
|
}
|
|
|
|
}
|
2023-07-18 23:30:20 +03:00
|
|
|
#if QEMU_VERSION_MAJOR > 4 || QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2
|
|
|
|
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
|
|
#elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
|
|
|
|
aio_bh_schedule_oneshot(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
|
|
#elif QEMU_VERSION_MAJOR >= 2
|
|
|
|
task->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
|
|
qemu_bh_schedule(task->bh);
|
2023-01-06 17:33:49 +03:00
|
|
|
#else
|
2023-07-18 23:30:20 +03:00
|
|
|
task->bh = qemu_bh_new(vitastor_co_generic_bh_cb, opaque);
|
|
|
|
qemu_bh_schedule(task->bh);
|
2023-01-06 17:33:49 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static int coroutine_fn vitastor_co_block_status(
|
|
|
|
BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
|
|
|
|
int64_t *pnum, int64_t *map, BlockDriverState **file)
|
|
|
|
{
|
|
|
|
// Allocated => return BDRV_BLOCK_DATA|BDRV_BLOCK_OFFSET_VALID
|
|
|
|
// Not allocated => return 0
|
|
|
|
// Error => return -errno
|
|
|
|
// Set pnum to length of the extent, `*map` = `offset`, `*file` = `bs`
|
|
|
|
VitastorRPC task;
|
|
|
|
VitastorClient *client = bs->opaque;
|
|
|
|
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
|
|
|
uint8_t bit = 0;
|
|
|
|
if (client->last_bitmap && client->last_bitmap_inode == inode &&
|
|
|
|
client->last_bitmap_offset <= offset &&
|
|
|
|
client->last_bitmap_offset+client->last_bitmap_len >= (want_zero ? offset+1 : offset+bytes))
|
|
|
|
{
|
|
|
|
// Use the previously read bitmap
|
|
|
|
task.bitmap_granularity = client->last_bitmap_granularity;
|
|
|
|
task.offset = client->last_bitmap_offset;
|
|
|
|
task.len = client->last_bitmap_len;
|
|
|
|
task.bitmap = client->last_bitmap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Read bitmap from this position, rounding to full inode PG blocks
|
|
|
|
uint32_t block_size = vitastor_c_inode_get_block_size(client->proxy, inode);
|
|
|
|
if (!block_size)
|
|
|
|
return -EAGAIN;
|
|
|
|
// Init coroutine
|
|
|
|
vitastor_co_init_task(bs, &task);
|
|
|
|
free(client->last_bitmap);
|
|
|
|
task.inode = client->last_bitmap_inode = inode;
|
|
|
|
task.bitmap_granularity = client->last_bitmap_granularity = vitastor_c_inode_get_bitmap_granularity(client->proxy, inode);
|
|
|
|
task.offset = client->last_bitmap_offset = offset / block_size * block_size;
|
|
|
|
task.len = client->last_bitmap_len = (offset+bytes+block_size-1) / block_size * block_size - task.offset;
|
|
|
|
task.bitmap = client->last_bitmap = NULL;
|
|
|
|
qemu_mutex_lock(&client->mutex);
|
|
|
|
vitastor_c_read_bitmap(client->proxy, task.inode, task.offset, task.len, !client->skip_parents, vitastor_co_read_bitmap_cb, &task);
|
2023-07-03 00:42:31 +03:00
|
|
|
vitastor_schedule_uring_handler(client);
|
2023-01-06 17:33:49 +03:00
|
|
|
qemu_mutex_unlock(&client->mutex);
|
|
|
|
while (!task.complete)
|
|
|
|
{
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
}
|
|
|
|
if (task.ret < 0)
|
|
|
|
{
|
|
|
|
// Error
|
|
|
|
return task.ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (want_zero)
|
|
|
|
{
|
|
|
|
// Get precise mapping with all holes
|
|
|
|
uint64_t bmp_pos = (offset-task.offset) / task.bitmap_granularity;
|
|
|
|
uint64_t bmp_len = task.len / task.bitmap_granularity;
|
|
|
|
uint64_t bmp_end = bmp_pos+1;
|
|
|
|
bit = (task.bitmap[bmp_pos >> 3] >> (bmp_pos & 0x7)) & 1;
|
|
|
|
while (bmp_end < bmp_len && ((task.bitmap[bmp_end >> 3] >> (bmp_end & 0x7)) & 1) == bit)
|
|
|
|
{
|
|
|
|
bmp_end++;
|
|
|
|
}
|
|
|
|
*pnum = (bmp_end-bmp_pos) * task.bitmap_granularity;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Get larger allocated extents, possibly with false positives
|
|
|
|
uint64_t bmp_pos = (offset-task.offset) / task.bitmap_granularity;
|
|
|
|
uint64_t bmp_end = (offset+bytes-task.offset) / task.bitmap_granularity - bmp_pos;
|
|
|
|
while (bmp_pos < bmp_end)
|
|
|
|
{
|
|
|
|
if (!(bmp_pos & 7) && bmp_end >= bmp_pos+8)
|
|
|
|
{
|
|
|
|
bit = bit || task.bitmap[bmp_pos >> 3];
|
|
|
|
bmp_pos += 8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bit = bit || ((task.bitmap[bmp_pos >> 3] >> (bmp_pos & 0x7)) & 1);
|
|
|
|
bmp_pos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*pnum = bytes;
|
|
|
|
}
|
|
|
|
if (bit)
|
|
|
|
{
|
|
|
|
*map = offset;
|
|
|
|
*file = bs;
|
|
|
|
}
|
|
|
|
return (bit ? (BDRV_BLOCK_DATA|BDRV_BLOCK_OFFSET_VALID) : 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if QEMU_VERSION_MAJOR == 1 && QEMU_VERSION_MINOR >= 7 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 12
|
|
|
|
// QEMU 1.7-2.11
|
|
|
|
static int64_t coroutine_fn vitastor_co_get_block_status(BlockDriverState *bs,
|
|
|
|
int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
|
|
|
|
{
|
|
|
|
int64_t map = 0;
|
|
|
|
int64_t pnumbytes = 0;
|
|
|
|
int r = vitastor_co_block_status(bs, 1, sector_num*BDRV_SECTOR_SIZE, nb_sectors*BDRV_SECTOR_SIZE, &pnumbytes, &map, &file);
|
|
|
|
*pnum = pnumbytes/BDRV_SECTOR_SIZE;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2021-12-02 02:25:50 +03:00
|
|
|
#if !( QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 7 )
|
2020-11-06 20:04:56 +03:00
|
|
|
static int coroutine_fn vitastor_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov)
|
|
|
|
{
|
|
|
|
return vitastor_co_preadv(bs, sector_num*BDRV_SECTOR_SIZE, nb_sectors*BDRV_SECTOR_SIZE, iov, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int coroutine_fn vitastor_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov)
|
|
|
|
{
|
|
|
|
return vitastor_co_pwritev(bs, sector_num*BDRV_SECTOR_SIZE, nb_sectors*BDRV_SECTOR_SIZE, iov, 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static int coroutine_fn vitastor_co_flush(BlockDriverState *bs)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
VitastorClient *client = bs->opaque;
|
|
|
|
VitastorRPC task;
|
|
|
|
vitastor_co_init_task(bs, &task);
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
qemu_mutex_lock(&client->mutex);
|
2023-06-21 02:09:12 +03:00
|
|
|
vitastor_c_sync(client->proxy, vitastor_co_generic_cb, &task);
|
2023-07-03 00:42:31 +03:00
|
|
|
vitastor_schedule_uring_handler(client);
|
2020-06-25 11:59:31 +03:00
|
|
|
qemu_mutex_unlock(&client->mutex);
|
|
|
|
|
|
|
|
while (!task.complete)
|
|
|
|
{
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
}
|
|
|
|
|
|
|
|
return task.ret;
|
|
|
|
}
|
|
|
|
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 0
|
2020-08-03 23:50:50 +03:00
|
|
|
static QemuOptsList vitastor_create_opts = {
|
|
|
|
.name = "vitastor-create-opts",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(vitastor_create_opts.head),
|
2020-06-25 11:59:31 +03:00
|
|
|
.desc = {
|
|
|
|
{
|
|
|
|
.name = BLOCK_OPT_SIZE,
|
|
|
|
.type = QEMU_OPT_SIZE,
|
|
|
|
.help = "Virtual disk size"
|
|
|
|
},
|
|
|
|
{ /* end of list */ }
|
|
|
|
}
|
|
|
|
};
|
2020-11-06 20:04:56 +03:00
|
|
|
#else
|
|
|
|
static QEMUOptionParameter vitastor_create_opts[] = {
|
|
|
|
{
|
|
|
|
.name = BLOCK_OPT_SIZE,
|
|
|
|
.type = OPT_SIZE,
|
|
|
|
.help = "Virtual disk size"
|
|
|
|
},
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2021-12-02 02:25:50 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 4
|
2020-08-03 23:50:50 +03:00
|
|
|
static const char *vitastor_strong_runtime_opts[] = {
|
2020-06-26 02:18:58 +03:00
|
|
|
"inode",
|
2020-09-05 17:09:20 +03:00
|
|
|
"pool",
|
2021-11-21 16:16:46 +03:00
|
|
|
"config-path",
|
|
|
|
"etcd-host",
|
|
|
|
"etcd-prefix",
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
NULL
|
|
|
|
};
|
2021-12-02 02:25:50 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static BlockDriver bdrv_vitastor = {
|
|
|
|
.format_name = "vitastor",
|
|
|
|
.protocol_name = "vitastor",
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
.instance_size = sizeof(VitastorClient),
|
|
|
|
.bdrv_parse_filename = vitastor_parse_filename,
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
2023-04-25 01:39:20 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 8
|
|
|
|
.bdrv_co_get_info = vitastor_get_info,
|
|
|
|
.bdrv_co_getlength = vitastor_getlength,
|
|
|
|
#else
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_get_info = vitastor_get_info,
|
|
|
|
.bdrv_getlength = vitastor_getlength,
|
2023-04-25 01:39:20 +03:00
|
|
|
#endif
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_probe_blocksizes = vitastor_probe_blocksizes,
|
2020-11-06 20:04:56 +03:00
|
|
|
#endif
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_refresh_limits = vitastor_refresh_limits,
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
// FIXME: Implement it along with per-inode statistics
|
2020-08-03 23:50:50 +03:00
|
|
|
//.bdrv_get_allocated_file_size = vitastor_get_allocated_file_size,
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_file_open = vitastor_file_open,
|
|
|
|
.bdrv_close = vitastor_close,
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
// Option list for the create operation
|
2021-11-08 20:41:23 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 0
|
2020-08-03 23:50:50 +03:00
|
|
|
.create_opts = &vitastor_create_opts,
|
2020-11-06 20:04:56 +03:00
|
|
|
#else
|
|
|
|
.create_options = vitastor_create_opts,
|
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
|
|
|
// For qmp_blockdev_create(), used by the qemu monitor / QAPI
|
|
|
|
// Requires patching QAPI IDL, thus unimplemented
|
2020-08-03 23:50:50 +03:00
|
|
|
//.bdrv_co_create = vitastor_co_create,
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2021-12-02 02:25:50 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 12
|
2020-06-25 11:59:31 +03:00
|
|
|
// For bdrv_create(), used by qemu-img
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_co_create_opts = vitastor_co_create_opts,
|
2021-12-02 02:25:50 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2021-12-02 02:25:50 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_co_truncate = vitastor_co_truncate,
|
2021-12-02 02:25:50 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2023-01-06 17:33:49 +03:00
|
|
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 1
|
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 12
|
|
|
|
// For snapshot export
|
|
|
|
.bdrv_co_block_status = vitastor_co_block_status,
|
|
|
|
#elif QEMU_VERSION_MAJOR == 1 && QEMU_VERSION_MINOR >= 7 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 12
|
|
|
|
.bdrv_co_get_block_status = vitastor_co_get_block_status,
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2021-12-02 02:25:50 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 7
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_co_preadv = vitastor_co_preadv,
|
|
|
|
.bdrv_co_pwritev = vitastor_co_pwritev,
|
2020-11-06 20:04:56 +03:00
|
|
|
#else
|
|
|
|
.bdrv_co_readv = vitastor_co_readv,
|
|
|
|
.bdrv_co_writev = vitastor_co_writev,
|
|
|
|
#endif
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
.bdrv_co_flush_to_disk = vitastor_co_flush,
|
2020-06-25 11:59:31 +03:00
|
|
|
|
2020-09-20 01:46:07 +03:00
|
|
|
#if QEMU_VERSION_MAJOR >= 4
|
2020-08-03 23:50:50 +03:00
|
|
|
.strong_runtime_opts = vitastor_strong_runtime_opts,
|
2020-09-20 01:46:07 +03:00
|
|
|
#endif
|
2020-06-25 11:59:31 +03:00
|
|
|
};
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
static void vitastor_block_init(void)
|
2020-06-25 11:59:31 +03:00
|
|
|
{
|
2020-08-03 23:50:50 +03:00
|
|
|
bdrv_register(&bdrv_vitastor);
|
2020-06-25 11:59:31 +03:00
|
|
|
}
|
|
|
|
|
2020-08-03 23:50:50 +03:00
|
|
|
block_init(vitastor_block_init);
|