From: Chuck Lever Date: Tue, 29 Sep 2009 14:38:52 +0000 (-0400) Subject: mount: Support negotiation between v4, v3, and v2 X-Git-Tag: nfs-utils-1-2-1-rc6 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=0e0526cce8127f1c18063ff700f5e4d5c77dc108;p=nfs-utils.git mount: Support negotiation between v4, v3, and v2 When negotiating between v3 and v2, mount.nfs first tries v3, then v2. Take the same approach for v4: try v4 first, then v3, then v2, in order to get the highest NFS version both the client and server support. No MNT request is needed for v4. Since we want to avoid an rpcbind query for the v4 attempt, just go straight for mount(2) without a MNT request or rpcbind negotiation first. If the server reports that v4 is not supported, try lower versions. The decisions made by the fg/bg retry loop have nothing to do with version negotation. To avoid a layering violation, mount.nfs's multi-version negotiation strategy is wholly encapsulated within nfs_try_mount(). Thus, code duplication between nfsmount_fg(), nfsmount_parent(), and nfsmount_child() is avoided. For now, negotiating version 4 is supported only on kernels that can handle the vers=4 option on type "nfs" file systems. At some point we could also allow mount.nfs to switch to an "nfs4" file system in this case. Since mi->version == 0 can now mean v2, v3, or v4, limit the versions tried for RDMA mounts. Today, only version 3 supports RDMA. Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 25b206f..069bdc1 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -278,6 +278,11 @@ static int nfs_validate_options(struct nfsmount_info *mi) return 0; if (strncmp(mi->type, "nfs4", 4) == 0) mi->version = 4; + else { + char *option = po_get(mi->options, "proto"); + if (option && strcmp(option, "rdma") == 0) + mi->version = 3; + } if (!nfs_append_sloppy_option(mi->options)) return 0; @@ -558,11 +563,17 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi) return result; } + if (mi->version == 0) { + if (po_append(options, "vers=4") == PO_FAILED) { + errno = EINVAL; + goto out_fail; + } + } + if (!nfs_append_clientaddr_option(sap, mi->salen, options)) { errno = EINVAL; goto out_fail; } - /* * Update option string to be recorded in /etc/mtab. */ @@ -590,6 +601,12 @@ static int nfs_try_mount(struct nfsmount_info *mi) switch (mi->version) { case 0: + if (linux_version_code() > MAKE_VERSION(2, 6, 31)) { + errno = 0; + result = nfs_try_mount_v4(mi); + if (errno != EPROTONOSUPPORT) + break; + } case 2: case 3: result = nfs_try_mount_v3v2(mi);