From efc75e2a4cf7dfa62c7ccaa9a1016f27e5519003 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 18 Jan 2018 13:43:45 +0100 Subject: block: rename .bdrv_create() to .bdrv_co_create_opts() BlockDriver->bdrv_create() has been called from coroutine context since commit 5b7e1542cfa41a281af9629d31cef03704d976e6 ("block: make bdrv_create adopt coroutine"). Make this explicit by renaming to .bdrv_co_create_opts() and add the coroutine_fn annotation. This makes it obvious to block driver authors that they may yield, use CoMutex, or other coroutine_fn APIs. bdrv_co_create is reserved for the QAPI-based version that Kevin is working on. Signed-off-by: Stefan Hajnoczi Message-Id: <20170705102231.20711-2-stefanha@redhat.com> Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block/ssh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'block/ssh.c') diff --git a/block/ssh.c b/block/ssh.c index b63addcf94..36d5d888d5 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -816,7 +816,8 @@ static QemuOptsList ssh_create_opts = { } }; -static int ssh_create(const char *filename, QemuOpts *opts, Error **errp) +static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts, + Error **errp) { int r, ret; int64_t total_size = 0; @@ -1204,7 +1205,7 @@ static BlockDriver bdrv_ssh = { .instance_size = sizeof(BDRVSSHState), .bdrv_parse_filename = ssh_parse_filename, .bdrv_file_open = ssh_file_open, - .bdrv_create = ssh_create, + .bdrv_co_create_opts = ssh_co_create_opts, .bdrv_close = ssh_close, .bdrv_has_zero_init = ssh_has_zero_init, .bdrv_co_readv = ssh_co_readv, -- cgit v1.2.3 From 2b12a756ac2a5d3af5aa8116e3a3e62a1501ad61 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Wed, 14 Feb 2018 21:49:13 +0100 Subject: block/ssh: Pull ssh_grow_file() from ssh_create() If we ever want to offer even rudimentary truncation functionality for ssh, we should put the respective code into a reusable function. Signed-off-by: Max Reitz Message-id: 20180214204915.7980-2-mreitz@redhat.com Reviewed-by: Eric Blake Reviewed-by: Richard W.M. Jones Signed-off-by: Max Reitz --- block/ssh.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'block/ssh.c') diff --git a/block/ssh.c b/block/ssh.c index 36d5d888d5..d6a68cb880 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -803,6 +803,26 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, return ret; } +static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp) +{ + ssize_t ret; + char c[1] = { '\0' }; + + /* offset must be strictly greater than the current size so we do + * not overwrite anything */ + assert(offset > 0 && offset > s->attrs.filesize); + + libssh2_sftp_seek64(s->sftp_handle, offset - 1); + ret = libssh2_sftp_write(s->sftp_handle, c, 1); + if (ret < 0) { + sftp_error_setg(errp, s, "Failed to grow file"); + return -EIO; + } + + s->attrs.filesize = offset; + return 0; +} + static QemuOptsList ssh_create_opts = { .name = "ssh-create-opts", .head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head), @@ -823,8 +843,6 @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts, int64_t total_size = 0; QDict *uri_options = NULL; BDRVSSHState s; - ssize_t r2; - char c[1] = { '\0' }; ssh_state_init(&s); @@ -850,14 +868,10 @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts, } if (total_size > 0) { - libssh2_sftp_seek64(s.sftp_handle, total_size-1); - r2 = libssh2_sftp_write(s.sftp_handle, c, 1); - if (r2 < 0) { - sftp_error_setg(errp, &s, "truncate failed"); - ret = -EINVAL; + ret = ssh_grow_file(&s, total_size, errp); + if (ret < 0) { goto out; } - s.attrs.filesize = total_size; } ret = 0; -- cgit v1.2.3 From bd8e0e32dac0cfb7c4e42b5a2d2b407819df049f Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Wed, 14 Feb 2018 21:49:14 +0100 Subject: block/ssh: Make ssh_grow_file() blocking At runtime (that is, during a future ssh_truncate()), the SSH session is non-blocking. However, ssh_truncate() (or rather, bdrv_truncate() in general) is not a coroutine, so this resize operation needs to block. For ssh_create(), that is fine, too; the session is never set to non-blocking anyway. Signed-off-by: Max Reitz Message-id: 20180214204915.7980-3-mreitz@redhat.com Reviewed-by: Eric Blake Reviewed-by: Richard W.M. Jones Signed-off-by: Max Reitz --- block/ssh.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'block/ssh.c') diff --git a/block/ssh.c b/block/ssh.c index d6a68cb880..4bcf10334f 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -803,17 +803,24 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, return ret; } +/* Note: This is a blocking operation */ static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp) { ssize_t ret; char c[1] = { '\0' }; + int was_blocking = libssh2_session_get_blocking(s->session); /* offset must be strictly greater than the current size so we do * not overwrite anything */ assert(offset > 0 && offset > s->attrs.filesize); + libssh2_session_set_blocking(s->session, 1); + libssh2_sftp_seek64(s->sftp_handle, offset - 1); ret = libssh2_sftp_write(s->sftp_handle, c, 1); + + libssh2_session_set_blocking(s->session, was_blocking); + if (ret < 0) { sftp_error_setg(errp, s, "Failed to grow file"); return -EIO; -- cgit v1.2.3 From 624f3006b8a26bcf7a0b2be13265ac99c65fd117 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Wed, 14 Feb 2018 21:49:15 +0100 Subject: block/ssh: Add basic .bdrv_truncate() libssh2 does not seem to offer real truncation support, so we can only grow files -- but that is better than nothing. Signed-off-by: Max Reitz Message-id: 20180214204915.7980-4-mreitz@redhat.com Reviewed-by: Eric Blake Reviewed-by: Richard W.M. Jones Signed-off-by: Max Reitz --- block/ssh.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'block/ssh.c') diff --git a/block/ssh.c b/block/ssh.c index 4bcf10334f..80a8b40dfa 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -1220,6 +1220,29 @@ static int64_t ssh_getlength(BlockDriverState *bs) return length; } +static int ssh_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) +{ + BDRVSSHState *s = bs->opaque; + + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_str(prealloc)); + return -ENOTSUP; + } + + if (offset < s->attrs.filesize) { + error_setg(errp, "ssh driver does not support shrinking files"); + return -ENOTSUP; + } + + if (offset == s->attrs.filesize) { + return 0; + } + + return ssh_grow_file(s, offset, errp); +} + static BlockDriver bdrv_ssh = { .format_name = "ssh", .protocol_name = "ssh", @@ -1232,6 +1255,7 @@ static BlockDriver bdrv_ssh = { .bdrv_co_readv = ssh_co_readv, .bdrv_co_writev = ssh_co_writev, .bdrv_getlength = ssh_getlength, + .bdrv_truncate = ssh_truncate, .bdrv_co_flush_to_disk = ssh_co_flush, .create_opts = &ssh_create_opts, }; -- cgit v1.2.3