summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2017-06-01 09:42:16 -0400
committerSteve Dickson <steved@redhat.com>2017-06-01 09:52:29 -0400
commitd406648690fa0fdf5333d7d54cf8210dab7f4d9c (patch)
tree7c8de5cb2b0e3a9921f490d87dfbd1d2218db106
parent0277815d9509ffc197c27973313f364616245704 (diff)
downloadnfs-utils-d406648690fa0fdf5333d7d54cf8210dab7f4d9c.tar.gz
nfs-utils-d406648690fa0fdf5333d7d54cf8210dab7f4d9c.tar.xz
nfs-utils-d406648690fa0fdf5333d7d54cf8210dab7f4d9c.zip
mount.nfs: improve version negotiation when vers=4 is specified.
If NFSv4, in general, is requested (possibly by -t nfs4 or -o v4 or -o vers=4 etc) then we need to negotiate the best minor version, but must not fallback to v3 or v2. Internally, this state is reflected in v_mode == V_GENERAL. This means that a major version was given, but the minor version still needs to be negotiated. This is handled by nfs_autonegotiate(). It currently does the right thing for EPROTONOSUPPORT and EINVAL, but not for other errors. In particular, ENOENT can cause problems as NFSv4 might export a different namespace than NFSv3 (e.g. by using fsid=0 in the Linux NFS server). Currently a mount request for NFSv4 and a particular path can result if an NFSv3 mount if the path is available with v3 but not v4. So move the special handling of V_GENERAL into the common fall_back: code, and add extra checking in the ENCONNREFUSED case, which does not use fall_back:. Tested-by: Steve Dickson <steved@redhat.com> Signed-off-by: NeilBrown <neilb@suse.com> Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r--utils/mount/stropts.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 0fbb375..c0266e5 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -315,9 +315,10 @@ static int nfs_set_version(struct nfsmount_info *mi)
if (!nfs_nfs_version(mi->options, &mi->version))
return 0;
- if (strncmp(mi->type, "nfs4", 4) == 0)
+ if (strncmp(mi->type, "nfs4", 4) == 0) {
mi->version.major = 4;
-
+ mi->version.v_mode = V_GENERAL;
+ }
/*
* Before 2.6.32, the kernel NFS client didn't
* support "-t nfs vers=4" mounts, so NFS version
@@ -838,9 +839,6 @@ check_result:
case EINVAL:
/* A less clear indication that our client
* does not support NFSv4 minor version. */
- if (mi->version.v_mode == V_GENERAL &&
- mi->version.minor == 0)
- return result;
if (mi->version.v_mode != V_SPECIFIC) {
if (mi->version.minor > 0) {
mi->version.minor--;
@@ -862,6 +860,9 @@ check_result:
/* UDP-Only servers won't support v4, but maybe it
* just isn't ready yet. So try v3, but double-check
* with rpcbind for v4. */
+ if (mi->version.v_mode == V_GENERAL)
+ /* Mustn't try v2,v3 */
+ return result;
result = nfs_try_mount_v3v2(mi, TRUE);
if (result == 0 && errno == EAGAIN) {
/* v4 server seems to be registered now. */
@@ -878,6 +879,9 @@ check_result:
}
fall_back:
+ if (mi->version.v_mode == V_GENERAL)
+ /* v2,3 fallback not allowed */
+ return result;
return nfs_try_mount_v3v2(mi, FALSE);
}