From: Peter Lieven <pl@kamp.de>
To: Stefan Hajnoczi <stefanha@gmail.com>
Cc: kwolf@redhat.com, pbonzini@redhat.com, famz@redhat.com,
qemu-devel@nongnu.org, stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCHv2] block: add native support for NFS
Date: Tue, 17 Dec 2013 18:03:48 +0100 [thread overview]
Message-ID: <52B083F4.9030204@kamp.de> (raw)
In-Reply-To: <20131217164730.GD2708@stefanha-thinkpad.redhat.com>
On 17.12.2013 17:47, Stefan Hajnoczi wrote:
> On Tue, Dec 17, 2013 at 10:15:25AM +0100, Peter Lieven wrote:
>> This patch adds native support for accessing images on NFS shares without
>> the requirement to actually mount the entire NFS share on the host.
>>
>> NFS Images can simply be specified by an url of the form:
>> nfs://<host>/<export>/<filename>
>>
>> For example:
>> qemu-img create -f qcow2 nfs://10.0.0.1/qemu-images/test.qcow2
>>
>> You need libnfs from Ronnie Sahlberg available at:
>> git://github.com/sahlberg/libnfs.git
>> for this to work.
>>
>> During configure it is automatically probed for libnfs and support
>> is enabled on-the-fly. You can forbid or enforce libnfs support
>> with --disable-libnfs or --enable-libnfs respectively.
>>
>> Due to NFS restrictions you might need to execute your binaries
>> as root, allow them to open priviledged ports (<1024) or specify
>> insecure option on the NFS server.
>>
>> Signed-off-by: Peter Lieven <pl@kamp.de>
>> ---
>> v1->v2:
>> - fixed block/Makefile.objs [Ronnie]
>> - do not always register a read handler [Ronnie]
>> - add support for reading beyond EOF [Fam]
>> - fixed struct and paramter naming [Fam]
>> - fixed overlong lines and whitespace errors [Fam]
>> - return return status from libnfs whereever possible [Fam]
>> - added comment why we set allocated_file_size to -ENOTSUP after write [Fam]
>> - avoid segfault when parsing filname [Fam]
>> - remove unused close_bh from NFSClient [Fam]
>> - avoid dividing and mutliplying total_size by BDRV_SECTOR_SIZE in nfs_file_create [Fam]
>>
>> MAINTAINERS | 5 +
>> block/Makefile.objs | 1 +
>> block/nfs.c | 419 +++++++++++++++++++++++++++++++++++++++++++++++++++
>> configure | 38 +++++
>> 4 files changed, 463 insertions(+)
>> create mode 100644 block/nfs.c
> Which NFS protocol versions are supported by current libnfs?
Will check that out. Ronnie?
>
>> +#include <poll.h>
> Why is this header included?
leftover.
>
>> +typedef struct nfsclient {
> Please either drop the struct tag or use "NFSClient".
ok
>
>> +static void
>> +nfs_co_generic_cb(int status, struct nfs_context *nfs, void *data,
>> + void *private_data)
>> +{
>> + NFSTask *Task = private_data;
> lowercase "task" local variable name please.
ok
>
>> +static int coroutine_fn nfs_co_writev(BlockDriverState *bs,
>> + int64_t sector_num, int nb_sectors,
>> + QEMUIOVector *iov)
>> +{
>> + NFSClient *client = bs->opaque;
>> + NFSTask task;
>> + char *buf = NULL;
>> +
>> + nfs_co_init_task(client, &task);
>> +
>> + buf = g_malloc(nb_sectors * BDRV_SECTOR_SIZE);
>> + qemu_iovec_to_buf(iov, 0, buf, nb_sectors * BDRV_SECTOR_SIZE);
>> +
>> + if (nfs_pwrite_async(client->context, client->fh,
>> + sector_num * BDRV_SECTOR_SIZE,
>> + nb_sectors * BDRV_SECTOR_SIZE,
>> + buf, nfs_co_generic_cb, &task) != 0) {
>> + g_free(buf);
>> + return -EIO;
> Can we get a more detailed errno here? (e.g. ENOSPC)
libnfs only returns 0 or -1 if the setup of the call
fails. the status code from the RPC is more detailed
and available in task.status.
>
>> + }
>> +
>> + while (!task.complete) {
>> + nfs_set_events(client);
>> + qemu_coroutine_yield();
>> + }
>> +
>> + g_free(buf);
>> +
>> + if (task.status != nb_sectors * BDRV_SECTOR_SIZE) {
>> + return task.status < 0 ? task.status : -EIO;
>> + }
>> +
>> + bs->total_sectors = MAX(bs->total_sectors, sector_num + nb_sectors);
> Why is this necessary? block.c will update bs->total_sectors if the
> file is growable.
Ok, didn't know ;-)
>
>> + /* set to -ENOTSUP since bdrv_allocated_file_size is only used
>> + * in qemu-img open. So we can use the cached value for allocate
>> + * filesize obtained from fstat at open time */
>> + client->allocated_file_size = -ENOTSUP;
> Can you implement this fully? By stubbing it out like this we won't be
> able to call get_allocated_file_size() at runtime in the future without
> updating the nfs block driver code. It's just an fstat call, shouldn't
> be too hard to implement properly :).
Will do. I will also add bdrv_truncate as its needed for VMDK Create.
>
>> + if (client->context == NULL) {
>> + error_setg(errp, "Failed to init NFS context");
>> + ret = -EINVAL;
>> + goto fail;
>> + }
>> +
>> + if (strlen(filename) <= 6) {
>> + error_setg(errp, "Invalid server in URL");
>> + ret = -EINVAL;
>> + goto fail;
>> + }
>> +
>> + server = g_strdup(filename + 6);
>> + if (server[0] == '/' || server[0] == '\0') {
>> + error_setg(errp, "Invalid server in URL");
>> + ret = -EINVAL;
>> + goto fail;
>> + }
>> + strp = strchr(server, '/');
>> + if (strp == NULL) {
>> + error_setg(errp, "Invalid URL specified.\n");
>> + ret = -EINVAL;
>> + goto fail;
>> + }
>> + path = g_strdup(strp);
>> + *strp = 0;
>> + strp = strrchr(path, '/');
>> + if (strp == NULL) {
>> + error_setg(errp, "Invalid URL specified.\n");
>> + ret = -EINVAL;
>> + goto fail;
>> + }
>> + file = g_strdup(strp);
>> + *strp = 0;
> Can you use util/uri.c to avoid the string manipulation? It can extract
> the different parts for validation: scheme, server, port, and path.
Thanks for the pointer. This is actually the parsing code from
libnfs examples.
>
>> +static int nfs_file_create(const char *filename, QEMUOptionParameter *options,
>> + Error **errp)
>> +{
>> + int ret = 0;
>> + int64_t total_size = 0;
>> + BlockDriverState *bs;
>> + NFSClient *client = NULL;
>> + QDict *bs_options;
>> +
>> + bs = bdrv_new("");
> This approach seems a little risky to me. bs is a fake
> BlockDriverState with many fields not initialized. bdrv_*() calls would
> crash.
>
> How about a static nfs_open() function that operates on NFSClient and is
> shared by nfs_file_create() and nfs_file_open()?
Good idea, will look into this.
>
>> +##########################################
>> +# Do we have libnfs
>> +if test "$libnfs" != "no" ; then
>> + cat > $TMPC << EOF
>> +#include <nfsc/libnfs-zdr.h>
>> +#include <nfsc/libnfs.h>
>> +#include <nfsc/libnfs-raw.h>
>> +#include <nfsc/libnfs-raw-mount.h>
>> +int main(void) {
>> + nfs_init_context();
>> + nfs_pread_async(0,0,0,0,0,0);
>> + nfs_pwrite_async(0,0,0,0,0,0,0);
>> + nfs_fstat(0,0,0);
>> + return 0;
>> + }
>> +EOF
>> + if compile_prog "-Werror" "-lnfs" ; then
>> + libnfs="yes"
>> + LIBS="$LIBS -lnfs"
> pkg-config is usually better than hardcoding names. Is pkg-config
> available for libnfs?
it is, but until today it was buggy. we can use it from libnfs 1.9.0
onwards.
Thanks for reviewing.
Peter
next prev parent reply other threads:[~2013-12-17 17:03 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-17 9:15 [Qemu-devel] [PATCHv2] block: add native support for NFS Peter Lieven
2013-12-17 16:47 ` Stefan Hajnoczi
2013-12-17 17:03 ` Peter Lieven [this message]
2013-12-17 17:13 ` ronnie sahlberg
2013-12-17 22:36 ` Peter Lieven
2013-12-17 22:44 ` Eric Blake
2013-12-17 22:51 ` ronnie sahlberg
2013-12-17 22:56 ` Peter Lieven
2013-12-17 17:28 ` ronnie sahlberg
2013-12-17 23:00 ` Peter Lieven
2013-12-20 9:48 ` Peter Lieven
2013-12-20 12:19 ` Stefan Hajnoczi
2013-12-20 12:53 ` Peter Lieven
2013-12-20 13:57 ` Stefan Hajnoczi
2013-12-20 14:07 ` Peter Lieven
2013-12-20 14:38 ` Stefan Hajnoczi
2013-12-20 14:43 ` Peter Lieven
2013-12-20 15:03 ` ronnie sahlberg
2013-12-20 15:30 ` Stefan Hajnoczi
2013-12-20 15:49 ` Peter Lieven
2013-12-20 15:54 ` Stefan Hajnoczi
2013-12-20 15:57 ` Peter Lieven
2013-12-20 16:27 ` Stefan Hajnoczi
2014-01-03 10:35 ` Peter Lieven
2013-12-17 16:53 ` ronnie sahlberg
2013-12-17 22:57 ` Peter Lieven
2013-12-17 17:32 ` Daniel P. Berrange
2013-12-17 23:03 ` Peter Lieven
2013-12-18 9:30 ` Daniel P. Berrange
2013-12-18 10:00 ` Orit Wasserman
2013-12-18 10:18 ` Daniel P. Berrange
2013-12-18 10:24 ` Orit Wasserman
2013-12-18 10:38 ` Paolo Bonzini
2013-12-18 17:21 ` Peter Lieven
2013-12-19 14:31 ` Paolo Bonzini
2013-12-18 11:11 ` Peter Lieven
2013-12-18 11:23 ` Orit Wasserman
2013-12-18 14:42 ` ronnie sahlberg
2013-12-18 16:59 ` Peter Lieven
2013-12-18 17:33 ` ronnie sahlberg
2013-12-18 17:42 ` Peter Lieven
2013-12-18 17:50 ` ronnie sahlberg
2013-12-18 17:55 ` Peter Lieven
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52B083F4.9030204@kamp.de \
--to=pl@kamp.de \
--cc=famz@redhat.com \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@gmail.com \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.