/* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred, struct thread *td) { struct nfsv3_fsinfo *fsp; u_int32_t pref, max; caddr_t bpos, dpos; int error = 0, retattr; struct mbuf *mreq, *mrep, *md, *mb; u_int64_t maxfsize; nfsstats.rpccnt[NFSPROC_FSINFO]++; mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); mb = mreq; bpos = mtod(mb, caddr_t); nfsm_fhtom(vp, 1); nfsm_request(vp, NFSPROC_FSINFO, td, cred); nfsm_postop_attr(vp, retattr); if (!error) { fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO); pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref); mtx_lock(&nmp->nm_mtx); if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE) nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax); if (max < nmp->nm_wsize && max > 0) { nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = max; } pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref); if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE) nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax); if (max < nmp->nm_rsize && max > 0) { nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = max; } pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ) nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); if (max < nmp->nm_readdirsize && max > 0) { nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); if (nmp->nm_readdirsize == 0) nmp->nm_readdirsize = max; } maxfsize = fxdr_hyper(&fsp->fs_maxfilesize); if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize) nmp->nm_maxfilesize = maxfsize; nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp); nmp->nm_state |= NFSSTA_GOTFSINFO; mtx_unlock(&nmp->nm_mtx); }
/* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct thread *td) { struct nfsv3_fsinfo *fsp; u_int32_t pref, max; int error = 0, retattr; u_int64_t maxfsize; struct nfsm_info info; info.v3 = 1; nfsstats.rpccnt[NFSPROC_FSINFO]++; nfsm_reqhead(&info, vp, NFSPROC_FSINFO, NFSX_FH(1)); ERROROUT(nfsm_fhtom(&info, vp)); NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSINFO, td, nfs_vpcred(vp, ND_READ), &error)); ERROROUT(nfsm_postop_attr(&info, vp, &retattr, NFS_LATTR_NOSHRINK)); if (error == 0) { NULLOUT(fsp = nfsm_dissect(&info, NFSX_V3FSINFO)); pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref); if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE) nmp->nm_wsize = roundup2(pref, NFS_FABLKSIZE); max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax); if (max < nmp->nm_wsize && max > 0) { nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = max; } pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref); if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE) nmp->nm_rsize = roundup2(pref, NFS_FABLKSIZE); max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax); if (max < nmp->nm_rsize && max > 0) { nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = max; } pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ) nmp->nm_readdirsize = roundup2(pref, NFS_DIRBLKSIZ); if (max < nmp->nm_readdirsize && max > 0) { nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); if (nmp->nm_readdirsize == 0) nmp->nm_readdirsize = max; } maxfsize = fxdr_hyper(&fsp->fs_maxfilesize); if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize) nmp->nm_maxfilesize = maxfsize; nmp->nm_state |= NFSSTA_GOTFSINFO; /* * Use the smaller of rsize/wsize for the biosize. */ if (nmp->nm_rsize < nmp->nm_wsize) nmp->nm_mountp->mnt_stat.f_iosize = nmp->nm_rsize; else nmp->nm_mountp->mnt_stat.f_iosize = nmp->nm_wsize; } m_freem(info.mrep); info.mrep = NULL; nfsmout: return (error); }
static int nfs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred) { struct vnode *vp; struct nfs_statfs *sfp; struct nfsmount *nmp = VFSTONFS(mp); thread_t td = curthread; int error = 0, retattr; struct nfsnode *np; struct nfsm_info info; info.mrep = NULL; info.v3 = (nmp->nm_flag & NFSMNT_NFSV3); lwkt_gettoken(&nmp->nm_token); #ifndef nolint sfp = NULL; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, NULL); if (error) { lwkt_reltoken(&nmp->nm_token); return (error); } vp = NFSTOV(np); /* ignore the passed cred */ cred = crget(); cred->cr_ngroups = 1; if (info.v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, td); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(&info, vp, NFSPROC_FSSTAT, NFSX_FH(info.v3)); ERROROUT(nfsm_fhtom(&info, vp)); NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSSTAT, td, cred, &error)); if (info.v3) { ERROROUT(nfsm_postop_attr(&info, vp, &retattr, NFS_LATTR_NOSHRINK)); } if (error) { if (info.mrep != NULL) m_freem(info.mrep); goto nfsmout; } NULLOUT(sfp = nfsm_dissect(&info, NFSX_STATFS(info.v3))); sbp->f_flag = nmp->nm_flag; sbp->f_owner = nmp->nm_cred->cr_ruid; if (info.v3) { sbp->f_bsize = NFS_FABLKSIZE; sbp->f_frsize = NFS_FABLKSIZE; sbp->f_blocks = (fxdr_hyper(&sfp->sf_tbytes) / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_bfree = (fxdr_hyper(&sfp->sf_fbytes) / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_bavail = (fxdr_hyper(&sfp->sf_abytes) / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = fxdr_hyper(&sfp->sf_tfiles); sbp->f_ffree = fxdr_hyper(&sfp->sf_ffiles); sbp->f_favail = fxdr_hyper(&sfp->sf_afiles); } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; sbp->f_favail = 0; } sbp->f_syncreads = 0; sbp->f_syncwrites = 0; sbp->f_asyncreads = 0; sbp->f_asyncwrites = 0; sbp->f_type = mp->mnt_vfc->vfc_typenum; m_freem(info.mrep); info.mrep = NULL; nfsmout: vput(vp); crfree(cred); lwkt_reltoken(&nmp->nm_token); return (error); }
/* * nfs statfs call */ int nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) { struct vnode *vp; struct nfs_statfs *sfp; struct nfsmount *nmp = VFSTONFS(mp); thread_t td = curthread; int error = 0, retattr; struct nfsnode *np; u_quad_t tquad; struct nfsm_info info; info.mrep = NULL; info.v3 = (nmp->nm_flag & NFSMNT_NFSV3); lwkt_gettoken(&nmp->nm_token); #ifndef nolint sfp = NULL; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, NULL); if (error) { lwkt_reltoken(&nmp->nm_token); return (error); } vp = NFSTOV(np); /* ignore the passed cred */ cred = crget(); cred->cr_ngroups = 1; if (info.v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, td); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(&info, vp, NFSPROC_FSSTAT, NFSX_FH(info.v3)); ERROROUT(nfsm_fhtom(&info, vp)); NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSSTAT, td, cred, &error)); if (info.v3) { ERROROUT(nfsm_postop_attr(&info, vp, &retattr, NFS_LATTR_NOSHRINK)); } if (error) { if (info.mrep != NULL) m_freem(info.mrep); goto nfsmout; } NULLOUT(sfp = nfsm_dissect(&info, NFSX_STATFS(info.v3))); sbp->f_flags = nmp->nm_flag; if (info.v3) { sbp->f_bsize = NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tbytes); sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); tquad = fxdr_hyper(&sfp->sf_fbytes); sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); tquad = fxdr_hyper(&sfp->sf_abytes); sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = (fxdr_unsigned(int32_t, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); sbp->f_ffree = (fxdr_unsigned(int32_t, sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } /* * Some values are pre-set in mnt_stat. Note in particular f_iosize * cannot be changed once the filesystem is mounted as it is used * as the basis for BIOs. */ if (sbp != &mp->mnt_stat) { sbp->f_type = mp->mnt_vfc->vfc_typenum; bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); sbp->f_iosize = mp->mnt_stat.f_iosize; } m_freem(info.mrep); info.mrep = NULL; nfsmout: vput(vp); crfree(cred); lwkt_reltoken(&nmp->nm_token); return (error); }
/* * nfs statfs call */ static int nfs_statfs(struct mount *mp, struct statfs *sbp) { struct vnode *vp; struct thread *td; struct nfs_statfs *sfp; caddr_t bpos, dpos; struct nfsmount *nmp = VFSTONFS(mp); int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; struct mbuf *mreq, *mrep, *md, *mb; struct nfsnode *np; u_quad_t tquad; td = curthread; #ifndef nolint sfp = NULL; #endif error = vfs_busy(mp, MBF_NOWAIT); if (error) return (error); error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE); if (error) { vfs_unbusy(mp); return (error); } vp = NFSTOV(np); mtx_lock(&nmp->nm_mtx); if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) { mtx_unlock(&nmp->nm_mtx); (void)nfs_fsinfo(nmp, vp, td->td_ucred, td); } else mtx_unlock(&nmp->nm_mtx); nfsstats.rpccnt[NFSPROC_FSSTAT]++; mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); mb = mreq; bpos = mtod(mb, caddr_t); nfsm_fhtom(vp, v3); nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred); if (v3) nfsm_postop_attr(vp, retattr); if (error) { if (mrep != NULL) m_freem(mrep); goto nfsmout; } sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3)); mtx_lock(&nmp->nm_mtx); sbp->f_iosize = nfs_iosize(nmp); mtx_unlock(&nmp->nm_mtx); if (v3) { sbp->f_bsize = NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tbytes); sbp->f_blocks = tquad / NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_fbytes); sbp->f_bfree = tquad / NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_abytes); sbp->f_bavail = tquad / NFS_FABLKSIZE; sbp->f_files = (fxdr_unsigned(int32_t, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); sbp->f_ffree = (fxdr_unsigned(int32_t, sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } m_freem(mrep); nfsmout: vput(vp); vfs_unbusy(mp); return (error); }
/* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, kauth_cred_t cred, struct lwp *l) { struct nfsv3_fsinfo *fsp; char *cp; int32_t t1, t2; u_int32_t *tl, pref, xmax; char *bpos, *dpos, *cp2; int error = 0, retattr; struct mbuf *mreq, *mrep, *md, *mb; u_int64_t maxfsize; struct nfsnode *np = VTONFS(vp); nfsstats.rpccnt[NFSPROC_FSINFO]++; nfsm_reqhead(np, NFSPROC_FSINFO, NFSX_FH(1)); nfsm_fhtom(np, 1); nfsm_request(np, NFSPROC_FSINFO, l, cred); nfsm_postop_attr(vp, retattr, 0); if (!error) { nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref); if ((nmp->nm_flag & NFSMNT_WSIZE) == 0 && pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE) nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); xmax = fxdr_unsigned(u_int32_t, fsp->fs_wtmax); if (xmax < nmp->nm_wsize && xmax > 0) { nmp->nm_wsize = xmax & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = xmax; } pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref); if ((nmp->nm_flag & NFSMNT_RSIZE) == 0 && pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE) nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); xmax = fxdr_unsigned(u_int32_t, fsp->fs_rtmax); if (xmax < nmp->nm_rsize && xmax > 0) { nmp->nm_rsize = xmax & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = xmax; } pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize && pref >= NFS_DIRFRAGSIZ) nmp->nm_readdirsize = (pref + NFS_DIRFRAGSIZ - 1) & ~(NFS_DIRFRAGSIZ - 1); if (xmax < nmp->nm_readdirsize && xmax > 0) { nmp->nm_readdirsize = xmax & ~(NFS_DIRFRAGSIZ - 1); if (nmp->nm_readdirsize == 0) nmp->nm_readdirsize = xmax; } /* XXX */ nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1; maxfsize = fxdr_hyper(&fsp->fs_maxfilesize); if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize) nmp->nm_maxfilesize = maxfsize; nmp->nm_mountp->mnt_fs_bshift = ffs(MIN(nmp->nm_rsize, nmp->nm_wsize)) - 1; nmp->nm_iflag |= NFSMNT_GOTFSINFO; } nfsm_reqdone; return (error); }
/* * nfs statvfs call */ int nfs_statvfs(struct mount *mp, struct statvfs *sbp) { struct lwp *l = curlwp; struct vnode *vp; struct nfs_statfs *sfp; char *cp; u_int32_t *tl; int32_t t1, t2; char *bpos, *dpos, *cp2; struct nfsmount *nmp = VFSTONFS(mp); int error = 0, retattr; #ifdef NFS_V2_ONLY const int v3 = 0; #else int v3 = (nmp->nm_flag & NFSMNT_NFSV3); #endif struct mbuf *mreq, *mrep = NULL, *md, *mb; kauth_cred_t cred; u_quad_t tquad; struct nfsnode *np; #ifndef nolint sfp = (struct nfs_statfs *)0; #endif vp = nmp->nm_vnode; np = VTONFS(vp); cred = kauth_cred_alloc(); #ifndef NFS_V2_ONLY if (v3 && (nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, cred, l); #endif nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(np, NFSPROC_FSSTAT, NFSX_FH(v3)); nfsm_fhtom(np, v3); nfsm_request(np, NFSPROC_FSSTAT, l, cred); if (v3) nfsm_postop_attr(vp, retattr, 0); if (error) { if (mrep != NULL) { if (mrep->m_next != NULL) printf("nfs_vfsops: nfs_statvfs would lose buffers\n"); m_freem(mrep); } goto nfsmout; } nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); sbp->f_flag = nmp->nm_flag; sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize); if (v3) { sbp->f_frsize = sbp->f_bsize = NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tbytes); sbp->f_blocks = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE); tquad = fxdr_hyper(&sfp->sf_fbytes); sbp->f_bfree = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE); tquad = fxdr_hyper(&sfp->sf_abytes); tquad = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE); sbp->f_bresvd = sbp->f_bfree - tquad; sbp->f_bavail = tquad; /* Handle older NFS servers returning negative values */ if ((quad_t)sbp->f_bavail < 0) sbp->f_bavail = 0; tquad = fxdr_hyper(&sfp->sf_tfiles); sbp->f_files = tquad; tquad = fxdr_hyper(&sfp->sf_ffiles); sbp->f_ffree = tquad; sbp->f_favail = tquad; sbp->f_fresvd = 0; sbp->f_namemax = NFS_MAXNAMLEN; } else { sbp->f_bsize = NFS_FABLKSIZE; sbp->f_frsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_fresvd = 0; sbp->f_files = 0; sbp->f_ffree = 0; sbp->f_favail = 0; sbp->f_fresvd = 0; sbp->f_namemax = NFS_MAXNAMLEN; } copy_statvfs_info(sbp, mp); nfsm_reqdone; kauth_cred_free(cred); return (error); }