* THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
+#include "qemu/osdep.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
#include "block/block_int.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "qemu/uri.h"
#include "qapi/qmp/qint.h"
+#include "qapi/qmp/qstring.h"
/* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in
* this block driver code.
static int parse_uri(const char *filename, QDict *options, Error **errp)
{
URI *uri = NULL;
- QueryParams *qp = NULL;
+ QueryParams *qp;
int i;
uri = uri_parse(filename);
return 0;
err:
- if (qp) {
- query_params_free(qp);
- }
if (uri) {
uri_free(uri);
}
const char *host, *user, *path, *host_key_check;
int port;
+ if (!qdict_haskey(options, "host")) {
+ ret = -EINVAL;
+ error_setg(errp, "No hostname was specified");
+ goto err;
+ }
host = qdict_get_str(options, "host");
if (qdict_haskey(options, "port")) {
port = 22;
}
+ if (!qdict_haskey(options, "path")) {
+ ret = -EINVAL;
+ error_setg(errp, "No path was specified");
+ goto err;
+ }
path = qdict_get_str(options, "path");
if (qdict_haskey(options, "user")) {
/* Open the socket and connect. */
s->sock = inet_connect(s->hostport, errp);
if (s->sock < 0) {
- ret = -errno;
+ ret = -EIO;
goto err;
}
return ret;
}
-static QEMUOptionParameter ssh_create_options[] = {
- {
- .name = BLOCK_OPT_SIZE,
- .type = OPT_SIZE,
- .help = "Virtual disk size"
- },
- { NULL }
+static QemuOptsList ssh_create_opts = {
+ .name = "ssh-create-opts",
+ .head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head),
+ .desc = {
+ {
+ .name = BLOCK_OPT_SIZE,
+ .type = QEMU_OPT_SIZE,
+ .help = "Virtual disk size"
+ },
+ { /* end of list */ }
+ }
};
-static int ssh_create(const char *filename, QEMUOptionParameter *options,
- Error **errp)
+static int ssh_create(const char *filename, QemuOpts *opts, Error **errp)
{
int r, ret;
int64_t total_size = 0;
ssh_state_init(&s);
/* Get desired file size. */
- while (options && options->name) {
- if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
- total_size = options->value.n;
- }
- options++;
- }
+ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
+ BDRV_SECTOR_SIZE);
DPRINTF("total_size=%" PRIi64, total_size);
uri_options = qdict_new();
qemu_coroutine_enter(co, NULL);
}
-static coroutine_fn void set_fd_handler(BDRVSSHState *s)
+static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
{
int r;
IOHandler *rd_handler = NULL, *wr_handler = NULL;
DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
rd_handler, wr_handler);
- qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, co);
+ aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
+ false, rd_handler, wr_handler, co);
}
-static coroutine_fn void clear_fd_handler(BDRVSSHState *s)
+static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
+ BlockDriverState *bs)
{
DPRINTF("s->sock=%d", s->sock);
- qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL);
+ aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
+ false, NULL, NULL, NULL);
}
/* A non-blocking call returned EAGAIN, so yield, ensuring the
* handlers are set up so that we'll be rescheduled when there is an
* interesting event on the socket.
*/
-static coroutine_fn void co_yield(BDRVSSHState *s)
+static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
{
- set_fd_handler(s);
+ set_fd_handler(s, bs);
qemu_coroutine_yield();
- clear_fd_handler(s);
+ clear_fd_handler(s, bs);
}
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
}
}
-static coroutine_fn int ssh_read(BDRVSSHState *s,
+static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
int64_t offset, size_t size,
QEMUIOVector *qiov)
{
DPRINTF("sftp_read returned %zd", r);
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
- co_yield(s);
+ co_yield(s, bs);
goto again;
}
if (r < 0) {
int ret;
qemu_co_mutex_lock(&s->lock);
- ret = ssh_read(s, sector_num * BDRV_SECTOR_SIZE,
+ ret = ssh_read(s, bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE, qiov);
qemu_co_mutex_unlock(&s->lock);
return ret;
}
-static int ssh_write(BDRVSSHState *s,
+static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
int64_t offset, size_t size,
QEMUIOVector *qiov)
{
DPRINTF("sftp_write returned %zd", r);
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
- co_yield(s);
+ co_yield(s, bs);
goto again;
}
if (r < 0) {
*/
if (r == 0) {
ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE);
- co_yield(s);
+ co_yield(s, bs);
goto again;
}
int ret;
qemu_co_mutex_lock(&s->lock);
- ret = ssh_write(s, sector_num * BDRV_SECTOR_SIZE,
+ ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE, qiov);
qemu_co_mutex_unlock(&s->lock);
#ifdef HAS_LIBSSH2_SFTP_FSYNC
-static coroutine_fn int ssh_flush(BDRVSSHState *s)
+static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
{
int r;
again:
r = libssh2_sftp_fsync(s->sftp_handle);
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
- co_yield(s);
+ co_yield(s, bs);
goto again;
}
if (r == LIBSSH2_ERROR_SFTP_PROTOCOL &&
int ret;
qemu_co_mutex_lock(&s->lock);
- ret = ssh_flush(s);
+ ret = ssh_flush(s, bs);
qemu_co_mutex_unlock(&s->lock);
return ret;
.bdrv_co_writev = ssh_co_writev,
.bdrv_getlength = ssh_getlength,
.bdrv_co_flush_to_disk = ssh_co_flush,
- .create_options = ssh_create_options,
+ .create_opts = &ssh_create_opts,
};
static void bdrv_ssh_init(void)