#include "qemu-error.h"
#include "qemu_socket.h"
#include "block_int.h"
+#include "bitops.h"
#define SD_PROTO_VER 0x01
return hval;
}
-static inline int is_data_obj_writeable(SheepdogInode *inode, unsigned int idx)
+static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
{
return inode->vdi_id == inode->data_vdi_id[idx];
}
int ret;
enum AIOCBState aiocb_type;
- QEMUBH *bh;
+ Coroutine *coroutine;
void (*aio_done_func)(SheepdogAIOCB *);
int canceled;
char *port;
int fd;
+ CoMutex lock;
+ Coroutine *co_send;
+ Coroutine *co_recv;
+
uint32_t aioreq_seq_num;
QLIST_HEAD(outstanding_aio_head, AIOReq) outstanding_aio_head;
} BDRVSheepdogState;
/*
* Sheepdog I/O handling:
*
- * 1. In the sd_aio_readv/writev, read/write requests are added to the
- * QEMU Bottom Halves.
- *
- * 2. In sd_readv_writev_bh_cb, the callbacks of BHs, we send the I/O
- * requests to the server and link the requests to the
- * outstanding_list in the BDRVSheepdogState. we exits the
- * function without waiting for receiving the response.
+ * 1. In sd_co_rw_vector, we send the I/O requests to the server and
+ * link the requests to the outstanding_list in the
+ * BDRVSheepdogState. The function exits without waiting for
+ * receiving the response.
*
- * 3. We receive the response in aio_read_response, the fd handler to
+ * 2. We receive the response in aio_read_response, the fd handler to
* the sheepdog connection. If metadata update is needed, we send
* the write request to the vdi object in sd_write_done, the write
- * completion function. The AIOCB callback is not called until all
- * the requests belonging to the AIOCB are finished.
+ * completion function. We switch back to sd_co_readv/writev after
+ * all the requests belonging to the AIOCB are finished.
*/
static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
{
AIOReq *aio_req;
- aio_req = qemu_malloc(sizeof(*aio_req));
+ aio_req = g_malloc(sizeof(*aio_req));
aio_req->aiocb = acb;
aio_req->iov_offset = iov_offset;
aio_req->oid = oid;
SheepdogAIOCB *acb = aio_req->aiocb;
QLIST_REMOVE(aio_req, outstanding_aio_siblings);
QLIST_REMOVE(aio_req, aioreq_siblings);
- qemu_free(aio_req);
+ g_free(aio_req);
return !QLIST_EMPTY(&acb->aioreq_head);
}
static void sd_finish_aiocb(SheepdogAIOCB *acb)
{
if (!acb->canceled) {
- acb->common.cb(acb->common.opaque, acb->ret);
+ qemu_coroutine_enter(acb->coroutine, NULL);
}
qemu_aio_release(acb);
}
* Sheepdog cannot cancel the requests which are already sent to
* the servers, so we just complete the request with -EIO here.
*/
- acb->common.cb(acb->common.opaque, -EIO);
+ acb->ret = -EIO;
+ qemu_coroutine_enter(acb->coroutine, NULL);
acb->canceled = 1;
}
acb->aio_done_func = NULL;
acb->canceled = 0;
- acb->bh = NULL;
+ acb->coroutine = qemu_coroutine_self();
acb->ret = 0;
QLIST_INIT(&acb->aioreq_head);
return acb;
}
-static int sd_schedule_bh(QEMUBHFunc *cb, SheepdogAIOCB *acb)
-{
- if (acb->bh) {
- error_report("bug: %d %d\n", acb->aiocb_type, acb->aiocb_type);
- return -EIO;
- }
-
- acb->bh = qemu_bh_new(cb, acb);
- if (!acb->bh) {
- error_report("oom: %d %d\n", acb->aiocb_type, acb->aiocb_type);
- return -EIO;
- }
-
- qemu_bh_schedule(acb->bh);
-
- return 0;
-}
-
#ifdef _WIN32
struct msghdr {
for (i = 0; i < msg->msg_iovlen; i++) {
size += msg->msg_iov[i].iov_len;
}
- buf = qemu_malloc(size);
+ buf = g_malloc(size);
p = buf;
for (i = 0; i < msg->msg_iovlen; i++) {
ret = send(s, buf, size, flags);
- qemu_free(buf);
+ g_free(buf);
return ret;
}
for (i = 0; i < msg->msg_iovlen; i++) {
size += msg->msg_iov[i].iov_len;
}
- buf = qemu_malloc(size);
+ buf = g_malloc(size);
- ret = recv(s, buf, size, flags);
+ ret = qemu_recv(s, buf, size, flags);
if (ret < 0) {
goto out;
}
p += msg->msg_iov[i].iov_len;
}
out:
- qemu_free(buf);
+ g_free(buf);
return ret;
}
ret = getaddrinfo(addr, port, &hints, &res0);
if (ret) {
- error_report("unable to get address info %s, %s\n",
+ error_report("unable to get address info %s, %s",
addr, strerror(errno));
return -1;
}
goto success;
}
fd = -1;
- error_report("failed connect to %s:%s\n", addr, port);
+ error_report("failed connect to %s:%s", addr, port);
success:
freeaddrinfo(res0);
return fd;
again:
ret = do_send_recv(sockfd, iov, len, iov_offset, write);
if (ret < 0) {
- if (errno == EINTR || errno == EAGAIN) {
+ if (errno == EINTR) {
+ goto again;
+ }
+ if (errno == EAGAIN) {
+ if (qemu_in_coroutine()) {
+ qemu_coroutine_yield();
+ }
goto again;
}
- error_report("failed to recv a rsp, %s\n", strerror(errno));
+ error_report("failed to recv a rsp, %s", strerror(errno));
return 1;
}
ret = do_writev(sockfd, iov, sizeof(*hdr) + *wlen, 0);
if (ret) {
- error_report("failed to send a req, %s\n", strerror(errno));
+ error_report("failed to send a req, %s", strerror(errno));
ret = -1;
}
ret = do_read(sockfd, hdr, sizeof(*hdr));
if (ret) {
- error_report("failed to get a rsp, %s\n", strerror(errno));
+ error_report("failed to get a rsp, %s", strerror(errno));
ret = -1;
goto out;
}
if (*rlen) {
ret = do_read(sockfd, data, *rlen);
if (ret) {
- error_report("failed to get the data, %s\n", strerror(errno));
+ error_report("failed to get the data, %s", strerror(errno));
ret = -1;
goto out;
}
ret = add_aio_request(s, aio_req, acb->qiov->iov,
acb->qiov->niov, 0, acb->aiocb_type);
if (ret < 0) {
- error_report("add_aio_request is failed\n");
+ error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
if (QLIST_EMPTY(&acb->aioreq_head)) {
sd_finish_aiocb(acb);
unsigned long idx;
if (QLIST_EMPTY(&s->outstanding_aio_head)) {
- return;
+ goto out;
}
/* read a header */
ret = do_read(fd, &rsp, sizeof(rsp));
if (ret) {
- error_report("failed to get the header, %s\n", strerror(errno));
- return;
+ error_report("failed to get the header, %s", strerror(errno));
+ goto out;
}
/* find the right aio_req from the outstanding_aio list */
}
}
if (!aio_req) {
- error_report("cannot find aio_req %x\n", rsp.id);
- return;
+ error_report("cannot find aio_req %x", rsp.id);
+ goto out;
}
acb = aio_req->aiocb;
ret = do_readv(fd, acb->qiov->iov, rsp.data_length,
aio_req->iov_offset);
if (ret) {
- error_report("failed to get the data, %s\n", strerror(errno));
- return;
+ error_report("failed to get the data, %s", strerror(errno));
+ goto out;
}
break;
}
if (rsp.result != SD_RES_SUCCESS) {
acb->ret = -EIO;
- error_report("%s\n", sd_strerror(rsp.result));
+ error_report("%s", sd_strerror(rsp.result));
}
rest = free_aio_req(s, aio_req);
if (!rest) {
/*
* We've finished all requests which belong to the AIOCB, so
- * we can call the callback now.
+ * we can switch back to sd_co_readv/writev now.
*/
acb->aio_done_func(acb);
}
+out:
+ s->co_recv = NULL;
+}
+
+static void co_read_response(void *opaque)
+{
+ BDRVSheepdogState *s = opaque;
+
+ if (!s->co_recv) {
+ s->co_recv = qemu_coroutine_create(aio_read_response);
+ }
+
+ qemu_coroutine_enter(s->co_recv, opaque);
+}
+
+static void co_write_request(void *opaque)
+{
+ BDRVSheepdogState *s = opaque;
+
+ qemu_coroutine_enter(s->co_send, NULL);
}
static int aio_flush_request(void *opaque)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("%s\n", strerror(errno));
+ error_report("%s", strerror(errno));
return -1;
}
ret = set_nodelay(fd);
if (ret) {
- error_report("%s\n", strerror(errno));
+ error_report("%s", strerror(errno));
closesocket(fd);
return -1;
}
- qemu_aio_set_fd_handler(fd, aio_read_response, NULL, aio_flush_request,
+ qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request,
NULL, s);
return fd;
}
char *p, *q;
int nr_sep;
- p = q = qemu_strdup(filename);
+ p = q = g_strdup(filename);
/* count the number of separators */
nr_sep = 0;
}
if (s->addr == NULL) {
- qemu_free(q);
+ g_free(q);
}
return 0;
}
if (rsp->result != SD_RES_SUCCESS) {
- error_report("cannot get vdi info, %s, %s %d %s\n",
+ error_report("cannot get vdi info, %s, %s %d %s",
sd_strerror(rsp->result), filename, snapid, tag);
ret = -1;
goto out;
uint64_t old_oid = aio_req->base_oid;
if (!nr_copies) {
- error_report("bug\n");
+ error_report("bug");
}
memset(&hdr, 0, sizeof(hdr));
hdr.id = aio_req->id;
+ qemu_co_mutex_lock(&s->lock);
+ s->co_send = qemu_coroutine_self();
+ qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request,
+ aio_flush_request, NULL, s);
set_cork(s->fd, 1);
/* send a header */
ret = do_write(s->fd, &hdr, sizeof(hdr));
if (ret) {
- error_report("failed to send a req, %s\n", strerror(errno));
+ error_report("failed to send a req, %s", strerror(errno));
return -EIO;
}
if (wlen) {
ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
if (ret) {
- error_report("failed to send a data, %s\n", strerror(errno));
+ error_report("failed to send a data, %s", strerror(errno));
return -EIO;
}
}
set_cork(s->fd, 0);
+ qemu_aio_set_fd_handler(s->fd, co_read_response, NULL,
+ aio_flush_request, NULL, s);
+ qemu_co_mutex_unlock(&s->lock);
return 0;
}
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
if (ret) {
- error_report("failed to send a request to the sheep\n");
+ error_report("failed to send a request to the sheep");
return -1;
}
case SD_RES_SUCCESS:
return 0;
default:
- error_report("%s\n", sd_strerror(rsp->result));
+ error_report("%s", sd_strerror(rsp->result));
return -1;
}
}
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
- buf = qemu_malloc(SD_INODE_SIZE);
+ buf = g_malloc(SD_INODE_SIZE);
ret = read_object(fd, buf, vid_to_vdi_oid(vid), 0, SD_INODE_SIZE, 0);
closesocket(fd);
bs->total_sectors = s->inode.vdi_size / SECTOR_SIZE;
strncpy(s->name, vdi, sizeof(s->name));
- qemu_free(buf);
+ qemu_co_mutex_init(&s->lock);
+ g_free(buf);
return 0;
out:
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL, NULL);
if (s->fd >= 0) {
closesocket(s->fd);
}
- qemu_free(buf);
+ g_free(buf);
return -1;
}
}
if (rsp->result != SD_RES_SUCCESS) {
- error_report("%s, %s\n", sd_strerror(rsp->result), filename);
+ error_report("%s, %s", sd_strerror(rsp->result), filename);
return -EIO;
}
return 0;
}
+static int sd_prealloc(const char *filename)
+{
+ BlockDriverState *bs = NULL;
+ uint32_t idx, max_idx;
+ int64_t vdi_size;
+ void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
+ int ret;
+
+ ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
+ if (ret < 0) {
+ goto out;
+ }
+
+ vdi_size = bdrv_getlength(bs);
+ if (vdi_size < 0) {
+ ret = vdi_size;
+ goto out;
+ }
+ max_idx = DIV_ROUND_UP(vdi_size, SD_DATA_OBJ_SIZE);
+
+ for (idx = 0; idx < max_idx; idx++) {
+ /*
+ * The created image can be a cloned image, so we need to read
+ * a data from the source image.
+ */
+ ret = bdrv_pread(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
+ if (ret < 0) {
+ goto out;
+ }
+ ret = bdrv_pwrite(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
+ if (ret < 0) {
+ goto out;
+ }
+ }
+out:
+ if (bs) {
+ bdrv_delete(bs);
+ }
+ g_free(buf);
+
+ return ret;
+}
+
static int sd_create(const char *filename, QEMUOptionParameter *options)
{
int ret;
BDRVSheepdogState s;
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
uint32_t snapid;
+ int prealloc = 0;
+ const char *vdiname;
- strstart(filename, "sheepdog:", (const char **)&filename);
+ strstart(filename, "sheepdog:", &vdiname);
memset(&s, 0, sizeof(s));
memset(vdi, 0, sizeof(vdi));
memset(tag, 0, sizeof(tag));
- if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
- error_report("invalid filename\n");
+ if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
+ error_report("invalid filename");
return -EINVAL;
}
vdi_size = options->value.n;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
+ if (!options->value.s || !strcmp(options->value.s, "off")) {
+ prealloc = 0;
+ } else if (!strcmp(options->value.s, "full")) {
+ prealloc = 1;
+ } else {
+ error_report("Invalid preallocation mode: '%s'",
+ options->value.s);
+ return -EINVAL;
+ }
}
options++;
}
if (vdi_size > SD_MAX_VDI_SIZE) {
- error_report("too big image size\n");
+ error_report("too big image size");
return -EINVAL;
}
/* Currently, only Sheepdog backing image is supported. */
drv = bdrv_find_protocol(backing_file);
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
- error_report("backing_file must be a sheepdog image\n");
+ error_report("backing_file must be a sheepdog image");
return -EINVAL;
}
s = bs->opaque;
if (!is_snapshot(&s->inode)) {
- error_report("cannot clone from a non snapshot vdi\n");
+ error_report("cannot clone from a non snapshot vdi");
bdrv_delete(bs);
return -EINVAL;
}
bdrv_delete(bs);
}
- return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+ ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+ if (!prealloc || ret) {
+ return ret;
+ }
+
+ return sd_prealloc(filename);
}
static void sd_close(BlockDriverState *bs)
if (!ret && rsp->result != SD_RES_SUCCESS &&
rsp->result != SD_RES_VDI_NOT_LOCKED) {
- error_report("%s, %s\n", sd_strerror(rsp->result), s->name);
+ error_report("%s, %s", sd_strerror(rsp->result), s->name);
}
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL, NULL);
closesocket(s->fd);
- qemu_free(s->addr);
+ g_free(s->addr);
}
static int64_t sd_getlength(BlockDriverState *bs)
unsigned int datalen;
if (offset < s->inode.vdi_size) {
- error_report("shrinking is not supported\n");
+ error_report("shrinking is not supported");
return -EINVAL;
} else if (offset > SD_MAX_VDI_SIZE) {
- error_report("too big image size\n");
+ error_report("too big image size");
return -EINVAL;
}
close(fd);
if (ret < 0) {
- error_report("failed to update an inode.\n");
+ error_report("failed to update an inode.");
return -EIO;
}
/*
* This function is called after writing data objects. If we need to
* update metadata, this sends a write request to the vdi object.
- * Otherwise, this calls the AIOCB callback.
+ * Otherwise, this switches back to sd_co_readv/writev.
*/
static void sd_write_done(SheepdogAIOCB *acb)
{
dprintf("%" PRIx32 " is snapshot.\n", s->inode.vdi_id);
- buf = qemu_malloc(SD_INODE_SIZE);
+ buf = g_malloc(SD_INODE_SIZE);
ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &vid, 1,
s->addr, s->port);
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
dprintf("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
out:
- qemu_free(buf);
+ g_free(buf);
return ret;
}
* waiting the response. The responses are received in the
* `aio_read_response' function which is called from the main loop as
* a fd handler.
+ *
+ * Returns 1 when we need to wait a response, 0 when there is no sent
+ * request and -errno in error cases.
*/
-static void sd_readv_writev_bh_cb(void *p)
+static int sd_co_rw_vector(void *p)
{
SheepdogAIOCB *acb = p;
int ret = 0;
SheepdogInode *inode = &s->inode;
AIOReq *aio_req;
- qemu_bh_delete(acb->bh);
- acb->bh = NULL;
-
if (acb->aiocb_type == AIOCB_WRITE_UDATA && s->is_snapshot) {
/*
* In the case we open the snapshot VDI, Sheepdog creates the
create = 1;
} else if (acb->aiocb_type == AIOCB_WRITE_UDATA
- && !is_data_obj_writeable(inode, idx)) {
+ && !is_data_obj_writable(inode, idx)) {
/* Copy-On-Write */
create = 1;
old_oid = oid;
ret = add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
create, acb->aiocb_type);
if (ret < 0) {
- error_report("add_aio_request is failed\n");
+ error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
acb->ret = -EIO;
goto out;
}
out:
if (QLIST_EMPTY(&acb->aioreq_head)) {
- sd_finish_aiocb(acb);
+ return acb->ret;
}
+ return 1;
}
-static BlockDriverAIOCB *sd_aio_writev(BlockDriverState *bs, int64_t sector_num,
- QEMUIOVector *qiov, int nb_sectors,
- BlockDriverCompletionFunc *cb,
- void *opaque)
+static int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, QEMUIOVector *qiov)
{
SheepdogAIOCB *acb;
+ int ret;
if (bs->growable && sector_num + nb_sectors > bs->total_sectors) {
/* TODO: shouldn't block here */
if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) {
- return NULL;
+ return -EIO;
}
bs->total_sectors = sector_num + nb_sectors;
}
- acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, cb, opaque);
+ acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL);
acb->aio_done_func = sd_write_done;
acb->aiocb_type = AIOCB_WRITE_UDATA;
- sd_schedule_bh(sd_readv_writev_bh_cb, acb);
- return &acb->common;
+ ret = sd_co_rw_vector(acb);
+ if (ret <= 0) {
+ qemu_aio_release(acb);
+ return ret;
+ }
+
+ qemu_coroutine_yield();
+
+ return acb->ret;
}
-static BlockDriverAIOCB *sd_aio_readv(BlockDriverState *bs, int64_t sector_num,
- QEMUIOVector *qiov, int nb_sectors,
- BlockDriverCompletionFunc *cb,
- void *opaque)
+static int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, QEMUIOVector *qiov)
{
SheepdogAIOCB *acb;
- int i;
+ int i, ret;
- acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, cb, opaque);
+ acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL);
acb->aiocb_type = AIOCB_READ_UDATA;
acb->aio_done_func = sd_finish_aiocb;
memset(qiov->iov[i].iov_base, 0, qiov->iov[i].iov_len);
}
- sd_schedule_bh(sd_readv_writev_bh_cb, acb);
- return &acb->common;
+ ret = sd_co_rw_vector(acb);
+ if (ret <= 0) {
+ qemu_aio_release(acb);
+ return ret;
+ }
+
+ qemu_coroutine_yield();
+
+ return acb->ret;
}
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
if (s->is_snapshot) {
error_report("You can't create a snapshot of a snapshot VDI, "
- "%s (%" PRIu32 ").\n", s->name, s->inode.vdi_id);
+ "%s (%" PRIu32 ").", s->name, s->inode.vdi_id);
return -EINVAL;
}
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
s->inode.nr_copies, datalen, 0, 0);
if (ret < 0) {
- error_report("failed to write snapshot's inode.\n");
+ error_report("failed to write snapshot's inode.");
ret = -EIO;
goto cleanup;
}
ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid, 1,
s->addr, s->port);
if (ret < 0) {
- error_report("failed to create inode for snapshot. %s\n",
+ error_report("failed to create inode for snapshot. %s",
strerror(errno));
ret = -EIO;
goto cleanup;
}
- inode = (SheepdogInode *)qemu_malloc(datalen);
+ inode = (SheepdogInode *)g_malloc(datalen);
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
s->inode.nr_copies, datalen, 0);
if (ret < 0) {
- error_report("failed to read new inode info. %s\n", strerror(errno));
+ error_report("failed to read new inode info. %s", strerror(errno));
ret = -EIO;
goto cleanup;
}
uint32_t snapid = 0;
int ret = -ENOENT, fd;
- old_s = qemu_malloc(sizeof(BDRVSheepdogState));
+ old_s = g_malloc(sizeof(BDRVSheepdogState));
memcpy(old_s, s, sizeof(BDRVSheepdogState));
ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
if (ret) {
- error_report("Failed to find_vdi_name\n");
+ error_report("Failed to find_vdi_name");
ret = -ENOENT;
goto out;
}
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
- buf = qemu_malloc(SD_INODE_SIZE);
+ buf = g_malloc(SD_INODE_SIZE);
ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
SD_INODE_SIZE, 0);
memcpy(&s->inode, buf, sizeof(s->inode));
if (!s->inode.vm_state_size) {
- error_report("Invalid snapshot\n");
+ error_report("Invalid snapshot");
ret = -ENOENT;
goto out;
}
s->is_snapshot = 1;
- qemu_free(buf);
- qemu_free(old_s);
+ g_free(buf);
+ g_free(old_s);
return 0;
out:
/* recover bdrv_sd_state */
memcpy(s, old_s, sizeof(BDRVSheepdogState));
- qemu_free(buf);
- qemu_free(old_s);
+ g_free(buf);
+ g_free(old_s);
- error_report("failed to open. recover old bdrv_sd_state.\n");
+ error_report("failed to open. recover old bdrv_sd_state.");
return ret;
}
return 0;
}
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define BITS_PER_BYTE 8
-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define DECLARE_BITMAP(name,bits) \
- unsigned long name[BITS_TO_LONGS(bits)]
-
-#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
-
-static inline int test_bit(unsigned int nr, const unsigned long *addr)
-{
- return ((1UL << (nr % BITS_PER_LONG)) &
- (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
-}
-
static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
{
BDRVSheepdogState *s = bs->opaque;
uint64_t hval;
uint32_t vid;
- vdi_inuse = qemu_malloc(max);
+ vdi_inuse = g_malloc(max);
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
goto out;
}
- sn_tab = qemu_mallocz(nr * sizeof(*sn_tab));
+ sn_tab = g_malloc0(nr * sizeof(*sn_tab));
/* calculate a vdi id with hash function */
hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT);
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
out:
*psn_tab = sn_tab;
- qemu_free(vdi_inuse);
+ g_free(vdi_inuse);
return found;
}
}
if (ret < 0) {
- error_report("failed to save vmstate %s\n", strerror(errno));
+ error_report("failed to save vmstate %s", strerror(errno));
ret = -EIO;
goto cleanup;
}
.type = OPT_STRING,
.help = "File name of a base image"
},
+ {
+ .name = BLOCK_OPT_PREALLOC,
+ .type = OPT_STRING,
+ .help = "Preallocation mode (allowed values: off, full)"
+ },
{ NULL }
};
.bdrv_getlength = sd_getlength,
.bdrv_truncate = sd_truncate,
- .bdrv_aio_readv = sd_aio_readv,
- .bdrv_aio_writev = sd_aio_writev,
+ .bdrv_co_readv = sd_co_readv,
+ .bdrv_co_writev = sd_co_writev,
.bdrv_snapshot_create = sd_snapshot_create,
.bdrv_snapshot_goto = sd_snapshot_goto,