Subject: Re: bug in NFS_V2_ONLY option
To: Ben Harris <bjh21@netbsd.org>
From: Christian Groessler <cpg@aladdin.de>
List: current-users
Date: 04/29/2001 02:18:35
On 04/28/2001 05:11:47 PM CET Ben Harris wrote:
>
>On 28 Apr 2001, Christian Groessler wrote:
>
>> Anyway, I think the cleaner approach would be if mount_nfs asks the
>> kernel what nfs it understands before contacting the nfs server.
>> How should this query be implemented? Additional syscall?
>
>sysctl().  vfs.nfs.max_version or similar.

OK, I've implemented this. This is my first excursion into this area so
please double-check it :-)

I've added code to sys/nfs/nfs_vfsops.c and
sbin/mount_nfs/mount_nfs.c.

Some things remain:

a,
If you look at my code in mount_nfs.c you'll see that I use an
immediate value for mib[1] (2 - VFS_NFS). I haven't found an existing
define for it...

b,
My patch as is works OK on i386, but when I tried it on alpha and
macppc, mount_nfs didn't compile because of mutiply defined "struct
pmap". This seems to happen because I include sysctl.h.

On alpha these 2 files are biting each other

/usr/include//rpc/pmap_prot.h:struct pmap {
/usr/include//alpha/pmap.h:struct pmap {

and on macppc these 2 files:

/usr/include//rpc/pmap_prot.h:struct pmap {
/usr/include//powerpc/pmap.h:struct pmap {

Hmm, I believe I'm innocent in this case...

regards,
chris



Index: sys/nfs/nfs.h
===================================================================
RCS file: /net/swamp/zeug/netbsd-rsync/main/syssrc/sys/nfs/nfs.h,v
retrieving revision 1.28
diff -u -r1.28 nfs.h
--- sys/nfs/nfs.h	2001/04/03 15:08:38	1.28
+++ sys/nfs/nfs.h	2001/04/28 21:49:24
@@ -259,12 +259,14 @@
  */
 #define NFS_NFSSTATS	1		/* struct: struct nfsstats */
 #define NFS_IOTHREADS	2		/* number of io threads */
-#define	NFS_MAXID	3
+#define	NFS_MAXVERSION	3		/* max. supported NFS version */
+#define	NFS_MAXID	4
 
 #define NFS_NAMES { \
 	{ 0, 0 }, \
 	{ "nfsstats", CTLTYPE_STRUCT }, \
 	{ "iothreads", CTLTYPE_INT }, \
+	{ "max_version", CTLTYPE_INT }, \
 }
 
 /*
Index: sys/nfs/nfs_vfsops.c
===================================================================
RCS file: /net/swamp/zeug/netbsd-rsync/main/syssrc/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.101
diff -u -r1.101 nfs_vfsops.c
--- sys/nfs/nfs_vfsops.c	2001/02/12 20:02:30	1.101
+++ sys/nfs/nfs_vfsops.c	2001/04/28 21:52:50
@@ -564,7 +564,9 @@
 	if (args.version != NFS_ARGSVERSION)
 		return (EPROGMISMATCH);
 #ifdef NFS_V2_ONLY
-	args.flags &= ~(NFSMNT_NFSV3 | NFSMNT_NQNFS);
+	if (args.flags & (NFSMNT_NFSV3 | NFSMNT_NQNFS)) {
+		return (EPROTONOSUPPORT);
+	}
 #endif
 	if (mp->mnt_flag & MNT_UPDATE) {
 		struct nfsmount *nmp = VFSTONFS(mp);
@@ -960,7 +962,14 @@
 			nfs_getset_niothreads(1);
 
 		return rv;
-                
+
+	case NFS_MAXVERSION:
+#ifndef NFS_V2_ONLY
+		return (sysctl_rdint(oldp, oldlenp, newp, 3));
+#else
+		return (sysctl_rdint(oldp, oldlenp, newp, 2));
+#endif
+
 	default:
 		return EOPNOTSUPP;
 	}
Index: sbin/mount_nfs/mount_nfs.c
===================================================================
RCS file: /net/swamp/zeug/netbsd-rsync/main/basesrc/sbin/mount_nfs/mount_nfs.c,v
retrieving revision 1.30
diff -u -r1.30 mount_nfs.c
--- sbin/mount_nfs/mount_nfs.c	2001/01/11 01:33:35	1.30
+++ sbin/mount_nfs/mount_nfs.c	2001/04/28 23:55:39
@@ -51,6 +51,7 @@
 #endif /* not lint */
 
 #include <sys/param.h>
+#include <sys/sysctl.h>
 #include <sys/mount.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -217,6 +218,8 @@
 	struct nfsd_cargs ncd;
 	int mntflags, altflags, i, nfssvc_flag, num;
 	char *name, *p, *spec, *ospec;
+	int ret, nfsver, len = sizeof(int);
+	int mib[3];
 #ifdef NFSKERB
 	uid_t last_ruid;
 
@@ -436,6 +439,29 @@
 		}
 	argc -= optind;
 	argv += optind;
+
+	/*
+	 * verify that kernel supports requested NFS version
+	 */
+	if (! force2) {
+		mib[0] = CTL_VFS;
+		mib[1] = 2; /* VFS_NFS */
+		mib[2] = NFS_MAXVERSION;
+
+		ret = sysctl(mib, 3, &nfsver, &len, NULL, 0);
+		if (ret == -1) {
+			fprintf(stderr, "cannot query NFS version from kernel (%s)\n", strerror(errno));
+			fprintf(stderr, "coninuing anyway...\n");
+		}
+		else {
+			if (nfsver < 3 && force3)
+				errx(1, "NFSv3 requested, but kernel doesn't support v3!");
+			if (nfsver < 3) {
+				nfsargsp->flags &= ~NFSMNT_NFSV3;
+				force2 = 1;   /* we don't support v3, so don't try to negotiate it. */
+			}
+		}
+	}
 
 	if (argc != 2)
 		usage();