aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1998-05-30 16:33:58 +0000
committerPeter Wemm <peter@FreeBSD.org>1998-05-30 16:33:58 +0000
commit7c1c33a7dd16e123fb836b48b7318eca0026d75e (patch)
tree4f808c23626fbcbe2da4ab45af795e14b7e43829
parent6edfc50c8e9d5097a2f5e82cc8a6d7b1de5f9bd3 (diff)
downloadsrc-7c1c33a7dd16e123fb836b48b7318eca0026d75e.tar.gz
src-7c1c33a7dd16e123fb836b48b7318eca0026d75e.zip
When using NFSv3, use the remote server's idea of the maximum file size
rather than assuming 2^64. It may not like files that big. :-) On the nfs server, calculate and report the max file size as the point that the block numbers in the cache would turn negative. (ie: 1099511627775 bytes (1TB)). One of the things I'm worried about however, is that directory offsets are really cookies on a NFSv3 server and can be rather large, especially when/if the server generates the opaque directory cookies by using a local filesystem offset in what comes out as the upper 32 bits of the 64 bit cookie. (a server is free to do this, it could save byte swapping depending on the native 64 bit byte order) Obtained from: NetBSD
Notes
Notes: svn path=/head/; revision=36473
-rw-r--r--sys/nfs/nfs_bio.c9
-rw-r--r--sys/nfs/nfs_serv.c18
-rw-r--r--sys/nfs/nfs_vfsops.c15
-rw-r--r--sys/nfs/nfs_vnops.c6
-rw-r--r--sys/nfs/nfsmount.h3
-rw-r--r--sys/nfsclient/nfs_bio.c9
-rw-r--r--sys/nfsclient/nfs_vfsops.c15
-rw-r--r--sys/nfsclient/nfs_vnops.c6
-rw-r--r--sys/nfsclient/nfsmount.h3
-rw-r--r--sys/nfsserver/nfs_serv.c18
10 files changed, 76 insertions, 26 deletions
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c
index d16bf1afc0fe..d98bc7f97d42 100644
--- a/sys/nfs/nfs_bio.c
+++ b/sys/nfs/nfs_bio.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- * $Id: nfs_bio.c,v 1.55 1998/05/19 07:11:22 peter Exp $
+ * $Id: nfs_bio.c,v 1.56 1998/05/20 08:02:23 peter Exp $
*/
@@ -254,12 +254,15 @@ nfs_bioread(vp, uio, ioflag, cred, getpages)
#endif
if (uio->uio_resid == 0)
return (0);
- if (uio->uio_offset < 0)
+ if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */
return (EINVAL);
p = uio->uio_procp;
if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
(nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
(void)nfs_fsinfo(nmp, vp, cred, p);
+ if (vp->v_type != VDIR &&
+ (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
+ return (EFBIG);
biosize = vp->v_mount->mnt_stat.f_iosize;
/*
* For nfs, cache consistency can only be maintained approximately.
@@ -657,6 +660,8 @@ nfs_write(ap)
}
if (uio->uio_offset < 0)
return (EINVAL);
+ if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
+ return (EFBIG);
if (uio->uio_resid == 0)
return (0);
/*
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
index bfae28d5ebc1..4b08bc699afd 100644
--- a/sys/nfs/nfs_serv.c
+++ b/sys/nfs/nfs_serv.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
- * $Id: nfs_serv.c,v 1.60 1998/05/07 04:58:51 msmith Exp $
+ * $Id: nfs_serv.c,v 1.61 1998/05/20 09:05:48 peter Exp $
*/
/*
@@ -3256,19 +3256,26 @@ nfsrv_fsinfo(nfsd, slp, procp, mrq)
struct vattr at;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
+ u_quad_t frev, maxfsize;
+ struct statfs sb;
#ifndef nolint
cache = 0;
#endif
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
+ &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ if (error) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
}
+
+ /* XXX Try to make a guess on the max file size. */
+ VFS_STATFS(vp->v_mount, &sb, procp);
+ maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
+
getret = VOP_GETATTR(vp, &at, cred, procp);
vput(vp);
nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
@@ -3291,8 +3298,7 @@ nfsrv_fsinfo(nfsd, slp, procp, mrq)
sip->fs_wtpref = txdr_unsigned(pref);
sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
sip->fs_dtpref = txdr_unsigned(pref);
- sip->fs_maxfilesize.nfsuquad[0] = 0xffffffff;
- sip->fs_maxfilesize.nfsuquad[1] = 0xffffffff;
+ txdr_hyper(&maxfsize, &sip->fs_maxfilesize);
sip->fs_timedelta.nfsv3_sec = 0;
sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c
index 729ccbac00b3..554b0ef9a9ba 100644
--- a/sys/nfs/nfs_vfsops.c
+++ b/sys/nfs/nfs_vfsops.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
- * $Id: nfs_vfsops.c,v 1.62 1998/05/20 08:05:45 peter Exp $
+ * $Id: nfs_vfsops.c,v 1.63 1998/05/24 14:41:56 peter Exp $
*/
#include <sys/param.h>
@@ -333,6 +333,7 @@ nfs_fsinfo(nmp, vp, cred, p)
caddr_t bpos, dpos, cp2;
int error = 0, retattr;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ u_int64_t maxfsize;
nfsstats.rpccnt[NFSPROC_FSINFO]++;
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
@@ -367,6 +368,11 @@ nfs_fsinfo(nmp, vp, cred, p)
if (max < nmp->nm_readdirsize) {
nmp->nm_readdirsize = max;
}
+ /* XXX */
+ nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
+ fxdr_hyper(&fsp->fs_maxfilesize, &maxfsize);
+ if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
+ nmp->nm_maxfilesize = maxfsize;
nmp->nm_state |= NFSSTA_GOTFSINFO;
}
nfsm_reqdone;
@@ -690,6 +696,13 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
* unsuspecting binaries).
*/
mp->mnt_maxsymlinklen = 1;
+ if ((argp->flags & NFSMNT_NFSV3) == 0)
+ /*
+ * V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
+ * will fill this in.
+ */
+ nmp->nm_maxfilesize = 0xffffffffLL;
+
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index 246757f2d2ab..dc8629d20358 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/nfs_vnops.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
- * $Id: nfs_vnops.c,v 1.88 1998/05/16 16:20:50 bde Exp $
+ * $Id: nfs_vnops.c,v 1.89 1998/05/19 07:11:26 peter Exp $
*/
@@ -1029,7 +1029,7 @@ nfs_readrpc(vp, uiop, cred)
#endif
nmp = VFSTONFS(vp->v_mount);
tsiz = uiop->uio_resid;
- if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
+ if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
return (EFBIG);
while (tsiz > 0) {
nfsstats.rpccnt[NFSPROC_READ]++;
@@ -1095,7 +1095,7 @@ nfs_writerpc(vp, uiop, cred, iomode, must_commit)
#endif
*must_commit = 0;
tsiz = uiop->uio_resid;
- if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
+ if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
return (EFBIG);
while (tsiz > 0) {
nfsstats.rpccnt[NFSPROC_WRITE]++;
diff --git a/sys/nfs/nfsmount.h b/sys/nfs/nfsmount.h
index 2d502bdd4ace..ecb4f058d52a 100644
--- a/sys/nfs/nfsmount.h
+++ b/sys/nfs/nfsmount.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsmount.h 8.3 (Berkeley) 3/30/95
- * $Id: nfsmount.h,v 1.13 1997/08/16 19:16:05 wollman Exp $
+ * $Id: nfsmount.h,v 1.14 1998/05/19 07:11:27 peter Exp $
*/
@@ -92,6 +92,7 @@ struct nfsmount {
short nm_bufqlen; /* number of buffers in queue */
short nm_bufqwant; /* process wants to add to the queue */
int nm_bufqiods; /* number of iods processing queue */
+ u_int64_t nm_maxfilesize; /* maximum file size */
};
#if defined(KERNEL) || defined(_KERNEL)
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index d16bf1afc0fe..d98bc7f97d42 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- * $Id: nfs_bio.c,v 1.55 1998/05/19 07:11:22 peter Exp $
+ * $Id: nfs_bio.c,v 1.56 1998/05/20 08:02:23 peter Exp $
*/
@@ -254,12 +254,15 @@ nfs_bioread(vp, uio, ioflag, cred, getpages)
#endif
if (uio->uio_resid == 0)
return (0);
- if (uio->uio_offset < 0)
+ if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */
return (EINVAL);
p = uio->uio_procp;
if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
(nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
(void)nfs_fsinfo(nmp, vp, cred, p);
+ if (vp->v_type != VDIR &&
+ (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
+ return (EFBIG);
biosize = vp->v_mount->mnt_stat.f_iosize;
/*
* For nfs, cache consistency can only be maintained approximately.
@@ -657,6 +660,8 @@ nfs_write(ap)
}
if (uio->uio_offset < 0)
return (EINVAL);
+ if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
+ return (EFBIG);
if (uio->uio_resid == 0)
return (0);
/*
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 729ccbac00b3..554b0ef9a9ba 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
- * $Id: nfs_vfsops.c,v 1.62 1998/05/20 08:05:45 peter Exp $
+ * $Id: nfs_vfsops.c,v 1.63 1998/05/24 14:41:56 peter Exp $
*/
#include <sys/param.h>
@@ -333,6 +333,7 @@ nfs_fsinfo(nmp, vp, cred, p)
caddr_t bpos, dpos, cp2;
int error = 0, retattr;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ u_int64_t maxfsize;
nfsstats.rpccnt[NFSPROC_FSINFO]++;
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
@@ -367,6 +368,11 @@ nfs_fsinfo(nmp, vp, cred, p)
if (max < nmp->nm_readdirsize) {
nmp->nm_readdirsize = max;
}
+ /* XXX */
+ nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
+ fxdr_hyper(&fsp->fs_maxfilesize, &maxfsize);
+ if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
+ nmp->nm_maxfilesize = maxfsize;
nmp->nm_state |= NFSSTA_GOTFSINFO;
}
nfsm_reqdone;
@@ -690,6 +696,13 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
* unsuspecting binaries).
*/
mp->mnt_maxsymlinklen = 1;
+ if ((argp->flags & NFSMNT_NFSV3) == 0)
+ /*
+ * V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
+ * will fill this in.
+ */
+ nmp->nm_maxfilesize = 0xffffffffLL;
+
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 246757f2d2ab..dc8629d20358 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
- * $Id: nfs_vnops.c,v 1.88 1998/05/16 16:20:50 bde Exp $
+ * $Id: nfs_vnops.c,v 1.89 1998/05/19 07:11:26 peter Exp $
*/
@@ -1029,7 +1029,7 @@ nfs_readrpc(vp, uiop, cred)
#endif
nmp = VFSTONFS(vp->v_mount);
tsiz = uiop->uio_resid;
- if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
+ if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
return (EFBIG);
while (tsiz > 0) {
nfsstats.rpccnt[NFSPROC_READ]++;
@@ -1095,7 +1095,7 @@ nfs_writerpc(vp, uiop, cred, iomode, must_commit)
#endif
*must_commit = 0;
tsiz = uiop->uio_resid;
- if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
+ if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
return (EFBIG);
while (tsiz > 0) {
nfsstats.rpccnt[NFSPROC_WRITE]++;
diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h
index 2d502bdd4ace..ecb4f058d52a 100644
--- a/sys/nfsclient/nfsmount.h
+++ b/sys/nfsclient/nfsmount.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsmount.h 8.3 (Berkeley) 3/30/95
- * $Id: nfsmount.h,v 1.13 1997/08/16 19:16:05 wollman Exp $
+ * $Id: nfsmount.h,v 1.14 1998/05/19 07:11:27 peter Exp $
*/
@@ -92,6 +92,7 @@ struct nfsmount {
short nm_bufqlen; /* number of buffers in queue */
short nm_bufqwant; /* process wants to add to the queue */
int nm_bufqiods; /* number of iods processing queue */
+ u_int64_t nm_maxfilesize; /* maximum file size */
};
#if defined(KERNEL) || defined(_KERNEL)
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index bfae28d5ebc1..4b08bc699afd 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
- * $Id: nfs_serv.c,v 1.60 1998/05/07 04:58:51 msmith Exp $
+ * $Id: nfs_serv.c,v 1.61 1998/05/20 09:05:48 peter Exp $
*/
/*
@@ -3256,19 +3256,26 @@ nfsrv_fsinfo(nfsd, slp, procp, mrq)
struct vattr at;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
+ u_quad_t frev, maxfsize;
+ struct statfs sb;
#ifndef nolint
cache = 0;
#endif
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE)) {
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
+ &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ if (error) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
return (0);
}
+
+ /* XXX Try to make a guess on the max file size. */
+ VFS_STATFS(vp->v_mount, &sb, procp);
+ maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
+
getret = VOP_GETATTR(vp, &at, cred, procp);
vput(vp);
nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
@@ -3291,8 +3298,7 @@ nfsrv_fsinfo(nfsd, slp, procp, mrq)
sip->fs_wtpref = txdr_unsigned(pref);
sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
sip->fs_dtpref = txdr_unsigned(pref);
- sip->fs_maxfilesize.nfsuquad[0] = 0xffffffff;
- sip->fs_maxfilesize.nfsuquad[1] = 0xffffffff;
+ txdr_hyper(&maxfsize, &sip->fs_maxfilesize);
sip->fs_timedelta.nfsv3_sec = 0;
sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |