Compare commits

...

1 Commits

Author SHA1 Message Date
bbd168da43 Add qemu_file_mirror_path option to the config to allow to trick Veeam
All checks were successful
Test / test_write (push) Successful in 30s
Test / test_switch_primary (push) Successful in 34s
Test / test_write_xor (push) Successful in 34s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_iothreads (push) Successful in 38s
Test / test_heal_pg_size_2 (push) Successful in 2m16s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_local_read (push) Successful in 2m22s
Test / test_heal_antietcd (push) Successful in 2m18s
Test / test_heal_csum_32k_dmj (push) Successful in 2m20s
Test / test_heal_csum_32k (push) Successful in 2m19s
Test / test_heal_csum_32k_dj (push) Successful in 2m21s
Test / test_resize (push) Successful in 13s
Test / test_heal_csum_4k_dmj (push) Successful in 2m21s
Test / test_resize_auto (push) Successful in 8s
Test / test_osd_tags (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 14s
Test / test_enospc (push) Successful in 9s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 15s
Test / test_scrub (push) Successful in 13s
Test / test_scrub_zero_osd_2 (push) Successful in 14s
Test / test_scrub_xor (push) Successful in 15s
Test / test_scrub_pg_size_3 (push) Successful in 15s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 15s
Test / test_nfs (push) Successful in 12s
Test / test_scrub_ec (push) Successful in 15s
Test / test_heal_csum_4k_dj (push) Successful in 2m18s
Test / test_heal_csum_4k (push) Successful in 2m19s
When qemu_file_mirror_path is set to "/dir/" in /etc/vitastor/vitastor.conf, QEMU driver
returns "/dir/image_name" as the filename in qemu-img info and in QAPI to trick software
like Veeam which expects file-based access. After that, vitastor-nfs can be mounted to that
directory to make backups work :-)
2025-08-01 01:57:03 +03:00

View File

@@ -14,6 +14,7 @@
#endif
#include "block/block_int.h"
#include "qapi/error.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
@@ -65,6 +66,7 @@ typedef struct VitastorClient
char *etcd_host;
char *etcd_prefix;
char *image;
char *file_mirror_path;
int skip_parents;
uint64_t inode;
uint64_t pool;
@@ -432,6 +434,70 @@ static void strarray_free(str_array *a)
}
#endif
static void check_config(VitastorClient *client)
{
size_t bufsize = 64*1024, maxsize = 1024*1024, done = 0;
ssize_t r = 0;
char *data = NULL;
QObject *obj = NULL;
QDict *qd = NULL;
int fd = open(client->config_path, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "vitastor: failed to read %s: %s\n", client->config_path, strerror(errno));
return;
}
data = (char*)malloc(bufsize);
if (!data)
{
fprintf(stderr, "vitastor: memory allocation failed\n");
goto end_free;
}
while (1)
{
if (bufsize <= done)
{
if (bufsize >= maxsize)
{
fprintf(stderr, "vitastor: config file exceeds %zu bytes\n", maxsize);
goto end_free;
}
bufsize *= 2;
data = (char*)realloc(data, bufsize);
if (!data)
{
fprintf(stderr, "vitastor: memory allocation failed\n");
goto end_free;
}
}
r = read(fd, data+done, bufsize-done);
if (r < 0)
{
if (errno == EAGAIN || errno == EINTR)
continue;
fprintf(stderr, "vitastor: failed to read %s: %s\n", client->config_path, strerror(errno));
break;
}
done += r;
}
obj = qobject_from_json(data
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 9 || QEMU_VERSION_MAJOR >= 3
, NULL
#endif
);
qd = qobject_to(QDict, obj);
if (qd)
{
client->file_mirror_path = g_strdup(qdict_get_try_str(qd, "qemu_file_mirror_path"));
}
end_free:
if (obj)
qobject_unref(obj);
if (data)
free(data);
close(fd);
}
static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
{
VitastorRPC task;
@@ -450,6 +516,10 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
client->rdma_gid_index = qdict_get_try_int(options, "rdma-gid-index", 0);
client->rdma_mtu = qdict_get_try_int(options, "rdma-mtu", 0);
client->ctx = bdrv_get_aio_context(bs);
if (client->config_path && strlen(client->config_path))
{
check_config(client);
}
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
str_array opt = {};
char version_buffer[32];
@@ -624,6 +694,11 @@ static void vitastor_refresh_filename(BlockDriverState *bs)
VitastorClient *client = bs->opaque;
size_t len = 0;
int n = 0;
if (client->image && client->file_mirror_path)
{
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s%s", client->file_mirror_path, client->image);
return;
}
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), "vitastor://");
if (len < sizeof(bs->exact_filename))
{