changeset 10035:9c430ac1464a

6224897 NFSv4 and NFSv3 server support for maximum file size on a file system is incorrect and incomplete.
author Piyush Shivam <Piyush.Shivam@Sun.COM>
date Mon, 06 Jul 2009 00:38:36 -0500
parents 5a676578aeda
children d1aae351293e
files usr/src/uts/common/fs/nfs/nfs3_srv.c usr/src/uts/common/fs/nfs/nfs4_srv_attr.c usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
diffstat 3 files changed, 68 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/nfs/nfs3_srv.c	Fri Jul 03 12:07:36 2009 -0400
+++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c	Mon Jul 06 00:38:36 2009 -0500
@@ -4148,11 +4148,25 @@
 	 * underlying filesystem.  We can guess 2^31-1 if need be.
 	 */
 	error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
-
-	if (!error && l != 0 && l <= 64)
-		resp->resok.maxfilesize = (1LL << (l-1)) - 1;
-	else
+	if (error) {
+		resp->status = puterrno3(error);
+		goto out;
+	}
+
+	/*
+	 * If the underlying file system does not support _PC_FILESIZEBITS,
+	 * return a reasonable default. Note that error code on VOP_PATHCONF
+	 * will be 0, even if the underlying file system does not support
+	 * _PC_FILESIZEBITS.
+	 */
+	if (l == (ulong_t)-1) {
 		resp->resok.maxfilesize = MAXOFF32_T;
+	} else {
+		if (l >= (sizeof (uint64_t) * 8))
+			resp->resok.maxfilesize = INT64_MAX;
+		else
+			resp->resok.maxfilesize = (1LL << (l-1)) - 1;
+	}
 
 	resp->resok.time_delta.seconds = 0;
 	resp->resok.time_delta.nseconds = 1000;
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c	Fri Jul 03 12:07:36 2009 -0400
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c	Mon Jul 06 00:38:36 2009 -0500
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/systm.h>
 #include <sys/cmn_err.h>
 #include <nfs/nfs.h>
@@ -1574,10 +1572,21 @@
 		    sarg->cs->cr, NULL);
 		if (error)
 			break;
-		if (val >= (sizeof (uint64_t) * 8))
-			na->maxfilesize = UINT64_MAX;
-		else
-			na->maxfilesize = ((1LL << val) - 1);
+
+		/*
+		 * If the underlying file system does not support
+		 * _PC_FILESIZEBITS, return a reasonable default. Note that
+		 * error code on VOP_PATHCONF will be 0, even if the underlying
+		 * file system does not support _PC_FILESIZEBITS.
+		 */
+		if (val == (ulong_t)-1) {
+			na->maxfilesize = MAXOFF32_T;
+		} else {
+			if (val >= (sizeof (uint64_t) * 8))
+				na->maxfilesize = INT64_MAX;
+			else
+				na->maxfilesize = ((1LL << (val - 1)) - 1);
+		}
 		break;
 	case NFS4ATTR_SETIT:
 		/*
@@ -1591,10 +1600,20 @@
 		    sarg->cs->cr, NULL);
 		if (error)
 			break;
-		if (val >= (sizeof (uint64_t) * 8))
-			maxfilesize = UINT64_MAX;
-		else
-			maxfilesize = ((1LL << val) - 1);
+		/*
+		 * If the underlying file system does not support
+		 * _PC_FILESIZEBITS, return a reasonable default. Note that
+		 * error code on VOP_PATHCONF will be 0, even if the underlying
+		 * file system does not support _PC_FILESIZEBITS.
+		 */
+		if (val == (ulong_t)-1) {
+			maxfilesize = MAXOFF32_T;
+		} else {
+			if (val >= (sizeof (uint64_t) * 8))
+				maxfilesize = INT64_MAX;
+			else
+				maxfilesize = ((1LL << (val - 1)) - 1);
+		}
 		if (na->maxfilesize != maxfilesize)
 			error = -1;	/* no match */
 		break;
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c	Fri Jul 03 12:07:36 2009 -0400
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c	Mon Jul 06 00:38:36 2009 -0500
@@ -231,19 +231,30 @@
 
 	if (ar & FATTR4_MAXFILESIZE_MASK) {
 		/* Maximum File Size */
-		if (error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &pc_val, cr,
-		    NULL))
+		error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &pc_val, cr, NULL);
+		if (error)
 			return (error);
 
-		if (pc_val >= (sizeof (uint64_t) * 8))
-			pce->maxfilesize = UINT64_MAX;
-		else
-			pce->maxfilesize = ((1LL << pc_val) - 1);
+		/*
+		 * If the underlying file system does not support
+		 * _PC_FILESIZEBITS, return a reasonable default. Note that
+		 * error code on VOP_PATHCONF will be 0, even if the underlying
+		 * file system does not support _PC_FILESIZEBITS.
+		 */
+		if (pc_val == (ulong_t)-1) {
+			pce->maxfilesize = MAXOFF32_T;
+		} else {
+			if (pc_val >= (sizeof (uint64_t) * 8))
+				pce->maxfilesize = INT64_MAX;
+			else
+				pce->maxfilesize = ((1LL << (pc_val - 1)) - 1);
+		}
 	}
 
 	if (ar & FATTR4_MAXLINK_MASK) {
 		/* Maximum Link Count */
-		if (error = VOP_PATHCONF(vp, _PC_LINK_MAX, &pc_val, cr, NULL))
+		error = VOP_PATHCONF(vp, _PC_LINK_MAX, &pc_val, cr, NULL);
+		if (error)
 			return (error);
 
 		pce->maxlink = pc_val;
@@ -251,7 +262,8 @@
 
 	if (ar & FATTR4_MAXNAME_MASK) {
 		/* Maximum Name Length */
-		if (error = VOP_PATHCONF(vp, _PC_NAME_MAX, &pc_val, cr, NULL))
+		error = VOP_PATHCONF(vp, _PC_NAME_MAX, &pc_val, cr, NULL);
+		if (error)
 			return (error);
 
 		pce->maxname = pc_val;