Date: Sat, 15 Nov 2003 06:46:26 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: Peter Edwards <peter.edwards@openet-telecom.com> Cc: current@freebsd.org Subject: Re: Who needs these silly statfs changes... Message-ID: <20031115054126.B9400@gamplex.bde.org> In-Reply-To: <3FB4E8A1.6090402@openet-telecom.com> References: <20031113020400.GA44619@xor.obsecurity.org> <20031113085418.GA47995@xor.obsecurity.org> <3FB4E8A1.6090402@openet-telecom.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 14 Nov 2003, Peter Edwards wrote: > Bernd Walter wrote: > > >On Thu, Nov 13, 2003 at 12:54:18AM -0800, Kris Kennaway wrote: > > > > > >>On Thu, Nov 13, 2003 at 06:44:25PM +1100, Peter Jeremy wrote: > >> > >> > >>>On Wed, Nov 12, 2003 at 06:04:00PM -0800, Kris Kennaway wrote: > >>> > >>> > >>>>...my sparc machine reports that my i386 nfs server has 15 exabytes of > >>>>free space! > >>>> > >>>>enigma# df -k > >>>>Filesystem 1K-blocks Used Avail Capacity Mounted on > >>>>rot13:/mnt2 56595176 54032286 18014398507517260 0% /rot13/mnt2 > >>>> > >>>> > >>>18014398507517260 = 2^54 - 1964724. and 2^54KB == 2^64 bytes. Is it > >>>possible that rot13:/mnt2 has negative free space? (ie it's into the > >>>8-10% reserved area). > >>> > >>> > >>Yes, that's precisely what it is..the bug is either in df or the > >>kernel (I suspect the latter, i.e. something in the nfs code). > >> > >> > > > >And it's nothing new - I'm seeing this since several years now. > > > > > > The NFS protocols have unsigned fields where statfs has signed > equivalents: NFS can't represent negative available disk space ( Without > the knowledge of the underlying filesystem on the server, negative free > space is a little nonsensical anyway, I suppose) > > The attached patch stops the NFS server assigning negative values to > unsigned fields in the statfs response, and works against my local > solaris box. Seem reasonable? The client attampts to fix this by pretending that the unsigned fields are signed. -current tries to do more to support file system sizes larger that 1TB, but the code for this is not even wrong except it may be wrong enough to break the negative values. See my reply to one of the PRs for more details. I just got around to testing the patch in that reply: %%% Index: nfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/nfsclient/nfs_vfsops.c,v retrieving revision 1.143 diff -u -2 -r1.143 nfs_vfsops.c --- nfs_vfsops.c 12 Nov 2003 02:54:46 -0000 1.143 +++ nfs_vfsops.c 12 Nov 2003 14:37:46 -0000 @@ -223,5 +223,5 @@ struct mbuf *mreq, *mrep, *md, *mb; struct nfsnode *np; - u_quad_t tquad; + quad_t tquad; int bsize; @@ -254,19 +254,19 @@ for (bsize = NFS_FABLKSIZE; ; bsize *= 2) { sbp->f_bsize = bsize; - tquad = fxdr_hyper(&sfp->sf_tbytes); - if (((long)(tquad / bsize) > LONG_MAX) || - ((long)(tquad / bsize) < LONG_MIN)) + tquad = (quad_t)fxdr_hyper(&sfp->sf_tbytes) / bsize; + if (bsize <= INT_MAX / 2 && + (tquad > LONG_MAX || tquad < LONG_MIN)) continue; - sbp->f_blocks = tquad / bsize; - tquad = fxdr_hyper(&sfp->sf_fbytes); - if (((long)(tquad / bsize) > LONG_MAX) || - ((long)(tquad / bsize) < LONG_MIN)) + sbp->f_blocks = tquad; + tquad = (quad_t)fxdr_hyper(&sfp->sf_fbytes) / bsize; + if (bsize <= INT_MAX / 2 && + (tquad > LONG_MAX || tquad < LONG_MIN)) continue; - sbp->f_bfree = tquad / bsize; - tquad = fxdr_hyper(&sfp->sf_abytes); - if (((long)(tquad / bsize) > LONG_MAX) || - ((long)(tquad / bsize) < LONG_MIN)) + sbp->f_bfree = tquad; + tquad = (quad_t)fxdr_hyper(&sfp->sf_abytes) / bsize; + if (bsize <= INT_MAX / 2 && + (tquad > LONG_MAX || tquad < LONG_MIN)) continue; - sbp->f_bavail = tquad / bsize; + sbp->f_bavail = tquad; sbp->f_files = (fxdr_unsigned(int32_t, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); %%% This seems to work. On a 2TB-epsilon ffs1 file system (*) on an md malloc disk (**): server: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/md0 2147416896 0 1975624000 0% /b client: Filesystem 1024-blocks Used Avail Capacity Mounted on besplex:/b 2147416896 0 1975624000 0% /b These are 1K-blocks so their count fits in an int32_t, but the count in 512-blocks is too large for an int32_t so the scaling must be helping. With newfs -m 100 (***) to get near negative free space: server: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/md0 2147416896 0 5696 0% /b client: Filesystem 1K-blocks Used Avail Capacity Mounted on besplex:/b 2147416896 0 5696 0% /b After using up all the free space by creating a 6MB file: server: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/md0 2147416896 6208 -512 109% /b client: Filesystem 1024-blocks Used Avail Capacity Mounted on besplex:/b 2147416896 6208 -512 109% /b (*) Overflow at 1TB in fs.h:fsbtodb() must be fixed for 2TB ffs1 file systems to be safe to use. (**) mdconfig and md have overflow bugs at 2^32 sectors but we only need 2^31+epsilon sectors to test file system overflow bugs at 1TB. (***) The off-by-1 error in newfs -m must be fixed for newfs -m 100 to work. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031115054126.B9400>