From patchwork Wed Sep 13 10:26:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 9950925 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7773F60360 for ; Wed, 13 Sep 2017 10:27:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6761E22299 for ; Wed, 13 Sep 2017 10:27:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5C482223A5; Wed, 13 Sep 2017 10:27:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA88622299 for ; Wed, 13 Sep 2017 10:27:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752029AbdIMK1Y (ORCPT ); Wed, 13 Sep 2017 06:27:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40476 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751678AbdIMK1X (ORCPT ); Wed, 13 Sep 2017 06:27:23 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6402580F94; Wed, 13 Sep 2017 10:27:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6402580F94 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=stefanha@redhat.com Received: from localhost (ovpn-116-110.ams2.redhat.com [10.36.116.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id 016B75F935; Wed, 13 Sep 2017 10:27:22 +0000 (UTC) From: Stefan Hajnoczi To: linux-nfs@vger.kernel.org Cc: NeilBrown , Matt Benjamin , Jeff Layton , "J . Bruce Fields" , Chuck Lever , Steve Dickson , Stefan Hajnoczi Subject: [PATCH nfs-utils v3 08/14] mount: AF_VSOCK address parsing Date: Wed, 13 Sep 2017 11:26:44 +0100 Message-Id: <20170913102650.10377-9-stefanha@redhat.com> In-Reply-To: <20170913102650.10377-1-stefanha@redhat.com> References: <20170913102650.10377-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 13 Sep 2017 10:27:23 +0000 (UTC) Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP getaddrinfo(3) does not have AF_VSOCK support. Parse the CID in the hostname option and build a struct sockaddr_vm. There is one tricky thing here: struct addrinfo is normally allocated by getaddrinfo(3) and freed by freeaddrinfo(3). The memory allocation of the struct addrinfo and struct sockaddr are an implementation detail of libc. Therefore we must avoid freeaddrinfo(3) calls when the addrinfo details were filled out by us for AF_VSOCK instead of by getaddrinfo(3). It is now possible to mount a file system from the host (hypervisor) over AF_VSOCK like this: (guest)$ mount.nfs 2:/export /mnt -v -o proto=vsock The hypervisor is CID 2. Signed-off-by: Stefan Hajnoczi --- utils/mount/stropts.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++----- utils/mount/nfs.man | 20 ++++++++++++++---- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 033f254..be72e1e 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -908,6 +908,40 @@ fall_back: return nfs_try_mount_v3v2(mi, FALSE); } +/* There are no guarantees on how getaddrinfo(3) allocates struct addrinfo so + * be sure to call free(3) on *address instead of freeaddrinfo(3). + */ +static int vsock_getaddrinfo(struct nfsmount_info *mi, + struct addrinfo **address) +{ + struct { + struct addrinfo ai; + struct sockaddr_vm svm; + } *vai; + long cid; + char *endptr; + + errno = 0; + cid = strtol(mi->hostname, &endptr, 10); + if (errno != 0 || *endptr != '\0' || + cid < 0 || cid > UINT_MAX) + return EAI_NONAME; + + vai = calloc(1, sizeof(*vai)); + if (!vai) + return EAI_MEMORY; + + vai->ai.ai_family = AF_VSOCK; + vai->ai.ai_socktype = SOCK_STREAM; + vai->ai.ai_addrlen = sizeof(vai->svm); + vai->ai.ai_addr = (struct sockaddr *)&vai->svm; + vai->svm.svm_family = AF_VSOCK; + vai->svm.svm_cid = cid; + + *address = &vai->ai; + return 0; +} + /* * This is a single pass through the fg/bg loop. * @@ -919,12 +953,19 @@ static int nfs_try_mount(struct nfsmount_info *mi) int result = 0; if (mi->address == NULL) { - struct addrinfo hint = {}; - int error; - struct addrinfo *address; + int error = 0; + struct addrinfo *address = NULL; + + if (mi->family == AF_VSOCK) + error = vsock_getaddrinfo(mi, &address); + + if (error == 0 && !address) { + struct addrinfo hint = {}; + + hint.ai_family = (int)mi->family; + error = getaddrinfo(mi->hostname, NULL, &hint, &address); + } - hint.ai_family = (int)mi->family; - error = getaddrinfo(mi->hostname, NULL, &hint, &address); if (error != 0) { if (error == EAI_AGAIN) errno = EAGAIN; @@ -1219,6 +1260,12 @@ int nfsmount_string(const char *spec, const char *node, char *type, } else nfs_error(_("%s: internal option parsing error"), progname); + /* See vsock_getaddrinfo() for why we cannot use freeaddrinfo(3) */ + if (mi.address && mi.address->ai_family == AF_VSOCK) { + free(mi.address); + mi.address = NULL; + } + freeaddrinfo(mi.address); free(mi.hostname); return retval; diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man index cc6e992..4651826 100644 --- a/utils/mount/nfs.man +++ b/utils/mount/nfs.man @@ -58,8 +58,10 @@ are separated by blanks or tabs. .P The server's hostname can be an unqualified hostname, a fully qualified domain name, -a dotted quad IPv4 address, or -an IPv6 address enclosed in square brackets. +a dotted quad IPv4 address, +an IPv6 address enclosed in square brackets, +or a vsock address prefixed with +.BR vsock: . Link-local and site-local IPv6 addresses must be accompanied by an interface identifier. See @@ -769,7 +771,7 @@ The .I netid determines the transport that is used to communicate with the NFS server. Supported options are -.BR tcp ", " tcp6 ", and " rdma . +.BR tcp ", " tcp6 ", " rdma ", and " vsock . .B tcp6 use IPv6 addresses and is only available if support for TI-RPC is built in. Both others use IPv4 addresses. @@ -815,8 +817,11 @@ the behavior of this option in more detail. .BI clientaddr= n.n.n.n .TP 1.5i .BI clientaddr= n:n: ... :n +.TP 1.5i +.BI clientaddr= n Specifies a single IPv4 address (in dotted-quad form), -or a non-link-local IPv6 address, +a non-link-local IPv6 address, +or a vsock address, that the NFS client advertises to allow servers to perform NFS version 4 callback requests against files on this mount point. If the server is unable to @@ -934,6 +939,13 @@ using a raw IPv6 link-local address. .ta 8n +40n +5n +4n +9n [fe80::215:c5ff:fb3e:e2b1%eth0]:/export /mnt nfs defaults 0 0 .fi +.P +This example shows how to mount using NFS version 4 over vsock. +.P +.nf +.ta 8n +16n +6n +6n +30n + vsock:2:/export /mnt nfs4 defaults 0 0 +.fi .SH "TRANSPORT METHODS" NFS clients send requests to NFS servers via Remote Procedure Calls, or