*/
#include "qemu/osdep.h"
+#include "qemu-common.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-sockets.h"
#include "qapi/qapi-visit-block-core.h"
#include "qapi/qobject-output-visitor.h"
#include "qemu/uri.h"
#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/sockets.h"
#include "block/block_int.h"
+#include "block/qdict.h"
#include "sysemu/block-backend.h"
#include "qemu/bitops.h"
#include "qemu/cutils.h"
+#include "trace.h"
#define SD_PROTO_VER 0x01
(1UL << inode->block_size_shift));
}
-#undef DPRINTF
-#ifdef DEBUG_SDOG
-#define DEBUG_SDOG_PRINT 1
-#else
-#define DEBUG_SDOG_PRINT 0
-#endif
-#define DPRINTF(fmt, args...) \
- do { \
- if (DEBUG_SDOG_PRINT) { \
- fprintf(stderr, "%s %d: " fmt, __func__, __LINE__, ##args); \
- } \
- } while (0)
-
typedef struct SheepdogAIOCB SheepdogAIOCB;
typedef struct BDRVSheepdogState BDRVSheepdogState;
uint32_t aioreq_seq_num;
/* Every aio request must be linked to either of these queues. */
- QLIST_HEAD(inflight_aio_head, AIOReq) inflight_aio_head;
- QLIST_HEAD(failed_aio_head, AIOReq) failed_aio_head;
+ QLIST_HEAD(, AIOReq) inflight_aio_head;
+ QLIST_HEAD(, AIOReq) failed_aio_head;
CoMutex queue_lock;
CoQueue overlapping_queue;
- QLIST_HEAD(inflight_aiocb_head, SheepdogAIOCB) inflight_aiocb_head;
+ QLIST_HEAD(, SheepdogAIOCB) inflight_aiocb_head;
};
typedef struct BDRVSheepdogReopenState {
static SocketAddress *sd_server_config(QDict *options, Error **errp)
{
QDict *server = NULL;
- QObject *crumpled_server = NULL;
Visitor *iv = NULL;
SocketAddress *saddr = NULL;
Error *local_err = NULL;
qdict_extract_subqdict(options, &server, "server.");
- crumpled_server = qdict_crumple(server, errp);
- if (!crumpled_server) {
+ iv = qobject_input_visitor_new_flat_confused(server, errp);
+ if (!iv) {
goto done;
}
- /*
- * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive
- * server.type=inet. .to doesn't matter, it's ignored anyway.
- * That's because when @options come from -blockdev or
- * blockdev_add, members are typed according to the QAPI schema,
- * but when they come from -drive, they're all QString. The
- * visitor expects the former.
- */
- iv = qobject_input_visitor_new(crumpled_server);
visit_type_SocketAddress(iv, NULL, &saddr, &local_err);
if (local_err) {
error_propagate(errp, local_err);
done:
visit_free(iv);
- qobject_unref(crumpled_server);
qobject_unref(server);
return saddr;
}
if (s->addr->type == SOCKET_ADDRESS_TYPE_INET && fd >= 0) {
int ret = socket_set_nodelay(fd);
if (ret < 0) {
- error_report("%s", strerror(errno));
+ warn_report("can't set TCP_NODELAY: %s", strerror(errno));
}
}
Error *local_err = NULL;
s->fd = get_sheep_fd(s, &local_err);
if (s->fd < 0) {
- DPRINTF("Wait for connection to be established\n");
+ trace_sheepdog_reconnect_to_sdog();
error_report_err(local_err);
qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000000ULL);
}
break;
case AIOCB_FLUSH_CACHE:
if (rsp.result == SD_RES_INVALID_PARMS) {
- DPRINTF("disable cache since the server doesn't support it\n");
+ trace_sheepdog_aio_read_response();
s->cache_flags = SD_FLAG_CMD_DIRECT;
rsp.result = SD_RES_SUCCESS;
}
SheepdogVdiReq hdr;
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
unsigned int wlen, rlen = 0;
- char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];
+ char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN] QEMU_NONSTRING;
fd = connect_to_sdog(s, errp);
if (fd < 0) {
s->discard_supported = true;
if (snap_id || tag[0]) {
- DPRINTF("%" PRIx32 " snapshot inode was open.\n", vid);
+ trace_sheepdog_open(vid);
s->is_snapshot = true;
}
void *buf = NULL;
int ret;
- blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
+ blk = blk_new(bdrv_get_aio_context(bs),
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
BLK_PERM_ALL);
ret = blk_insert_bs(blk, bs, errp);
{
BlockdevCreateOptions *create_options = NULL;
QDict *qdict, *location_qdict;
- QObject *crumpled;
Visitor *v;
char *redundancy;
Error *local_err = NULL;
}
/* Get the QAPI object */
- crumpled = qdict_crumple(qdict, errp);
- if (crumpled == NULL) {
+ v = qobject_input_visitor_new_flat_confused(qdict, errp);
+ if (!v) {
ret = -EINVAL;
goto fail;
}
- v = qobject_input_visitor_new_keyval(crumpled);
visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
visit_free(v);
- qobject_unref(crumpled);
if (local_err) {
error_propagate(errp, local_err);
unsigned int wlen, rlen = 0;
int fd, ret;
- DPRINTF("%s\n", s->name);
+ trace_sheepdog_close(s->name);
fd = connect_to_sdog(s, &local_err);
if (fd < 0) {
return s->inode.vdi_size;
}
-static int sd_truncate(BlockDriverState *bs, int64_t offset,
- PreallocMode prealloc, Error **errp)
+static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
+ PreallocMode prealloc, Error **errp)
{
BDRVSheepdogState *s = bs->opaque;
int ret, fd;
}
/* we don't need to update entire object */
- datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
+ datalen = SD_INODE_HEADER_SIZE;
s->inode.vdi_size = offset;
ret = write_object(fd, s->bs, (char *)&s->inode,
vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
char *buf;
bool deleted;
- DPRINTF("%" PRIx32 " is snapshot.\n", s->inode.vdi_id);
+ trace_sheepdog_create_branch_snapshot(s->inode.vdi_id);
buf = g_malloc(SD_INODE_SIZE);
goto out;
}
- DPRINTF("%" PRIx32 " is created.\n", vid);
+ trace_sheepdog_create_branch_created(vid);
fd = connect_to_sdog(s, &local_err);
if (fd < 0) {
s->is_snapshot = false;
ret = 0;
- DPRINTF("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
+ trace_sheepdog_create_branch_new(s->inode.vdi_id);
out:
g_free(buf);
}
if (create) {
- DPRINTF("update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld\n",
- inode->vdi_id, oid,
- vid_to_data_oid(inode->data_vdi_id[idx], idx), idx);
+ trace_sheepdog_co_rw_vector_update(inode->vdi_id, oid,
+ vid_to_data_oid(inode->data_vdi_id[idx], idx),
+ idx);
oid = vid_to_data_oid(inode->vdi_id, idx);
- DPRINTF("new oid %" PRIx64 "\n", oid);
+ trace_sheepdog_co_rw_vector_new(oid);
}
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, create,
assert(!flags);
if (offset > s->inode.vdi_size) {
- ret = sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
+ ret = sd_co_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
if (ret < 0) {
return ret;
}
SheepdogInode *inode;
unsigned int datalen;
- DPRINTF("sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " "
- "is_snapshot %d\n", sn_info->name, sn_info->id_str,
- s->name, sn_info->vm_state_size, s->is_snapshot);
+ trace_sheepdog_snapshot_create_info(sn_info->name, sn_info->id_str, s->name,
+ sn_info->vm_state_size, s->is_snapshot);
if (s->is_snapshot) {
error_report("You can't create a snapshot of a snapshot VDI, "
return -EINVAL;
}
- DPRINTF("%s %s\n", sn_info->name, sn_info->id_str);
+ trace_sheepdog_snapshot_create(sn_info->name, sn_info->id_str);
s->inode.vm_state_size = sn_info->vm_state_size;
s->inode.vm_clock_nsec = sn_info->vm_clock_nsec;
*/
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
/* we don't need to update entire object */
- datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
+ datalen = SD_INODE_HEADER_SIZE;
inode = g_malloc(datalen);
/* refresh inode. */
}
memcpy(&s->inode, inode, datalen);
- DPRINTF("s->inode: name %s snap_id %x oid %x\n",
- s->inode.name, s->inode.snap_id, s->inode.vdi_id);
+ trace_sheepdog_snapshot_create_inode(s->inode.name, s->inode.snap_id,
+ s->inode.vdi_id);
cleanup:
g_free(inode);
QEMUSnapshotInfo *sn_tab = NULL;
unsigned wlen, rlen;
int found = 0;
- static SheepdogInode inode;
+ SheepdogInode *inode;
unsigned long *vdi_inuse;
unsigned int start_nr;
uint64_t hval;
uint32_t vid;
vdi_inuse = g_malloc(max);
+ inode = g_malloc(SD_INODE_HEADER_SIZE);
fd = connect_to_sdog(s, &local_err);
if (fd < 0) {
}
/* we don't need to read entire object */
- ret = read_object(fd, s->bs, (char *)&inode,
+ ret = read_object(fd, s->bs, (char *)inode,
vid_to_vdi_oid(vid),
- 0, SD_INODE_SIZE - sizeof(inode.data_vdi_id), 0,
+ 0, SD_INODE_HEADER_SIZE, 0,
s->cache_flags);
if (ret) {
continue;
}
- if (!strcmp(inode.name, s->name) && is_snapshot(&inode)) {
- sn_tab[found].date_sec = inode.snap_ctime >> 32;
- sn_tab[found].date_nsec = inode.snap_ctime & 0xffffffff;
- sn_tab[found].vm_state_size = inode.vm_state_size;
- sn_tab[found].vm_clock_nsec = inode.vm_clock_nsec;
+ if (!strcmp(inode->name, s->name) && is_snapshot(inode)) {
+ sn_tab[found].date_sec = inode->snap_ctime >> 32;
+ sn_tab[found].date_nsec = inode->snap_ctime & 0xffffffff;
+ sn_tab[found].vm_state_size = inode->vm_state_size;
+ sn_tab[found].vm_clock_nsec = inode->vm_clock_nsec;
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str),
- "%" PRIu32, inode.snap_id);
+ "%" PRIu32, inode->snap_id);
pstrcpy(sn_tab[found].name,
- MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)),
- inode.tag);
+ MIN(sizeof(sn_tab[found].name), sizeof(inode->tag)),
+ inode->tag);
found++;
}
}
*psn_tab = sn_tab;
g_free(vdi_inuse);
+ g_free(inode);
if (ret < 0) {
return ret;
}
};
+static const char *const sd_strong_runtime_opts[] = {
+ "vdi",
+ "snap-id",
+ "tag",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_sheepdog = {
.format_name = "sheepdog",
.protocol_name = "sheepdog",
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
- .bdrv_truncate = sd_truncate,
+ .bdrv_co_truncate = sd_co_truncate,
.bdrv_co_readv = sd_co_readv,
.bdrv_co_writev = sd_co_writev,
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static BlockDriver bdrv_sheepdog_tcp = {
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
- .bdrv_truncate = sd_truncate,
+ .bdrv_co_truncate = sd_co_truncate,
.bdrv_co_readv = sd_co_readv,
.bdrv_co_writev = sd_co_writev,
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static BlockDriver bdrv_sheepdog_unix = {
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
- .bdrv_truncate = sd_truncate,
+ .bdrv_co_truncate = sd_co_truncate,
.bdrv_co_readv = sd_co_readv,
.bdrv_co_writev = sd_co_writev,
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static void bdrv_sheepdog_init(void)