Ejemplo n.º 1
0
/*
 * Return root of a filesystem
 */
static int
nfs_root(struct mount *mp, int flags, struct vnode **vpp)
{
	struct vnode *vp;
	struct nfsmount *nmp;
	struct nfsnode *np;
	int error;

	nmp = VFSTONFS(mp);
	error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
	if (error)
		return error;
	vp = NFSTOV(np);
	/*
	 * Get transfer parameters and attributes for root vnode once.
	 */
	mtx_lock(&nmp->nm_mtx);
	if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
	    (nmp->nm_flag & NFSMNT_NFSV3)) {
		mtx_unlock(&nmp->nm_mtx);
		nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
	} else 
		mtx_unlock(&nmp->nm_mtx);
	if (vp->v_type == VNON)
	    vp->v_type = VDIR;
	vp->v_vflag |= VV_ROOT;
	*vpp = vp;
	return (0);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
/*
 * 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);
}
Ejemplo n.º 4
0
/*
 * 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);
}
Ejemplo n.º 5
0
/*
 * Common code for mount and mountroot
 */
static int
mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
    char *hst, struct vnode **vpp, struct ucred *cred, int nametimeo,
    int negnametimeo)
{
	struct nfsmount *nmp;
	struct nfsnode *np;
	int error;
	struct vattr attrs;

	if (mp->mnt_flag & MNT_UPDATE) {
		nmp = VFSTONFS(mp);
		printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
		free(nam, M_SONAME);
		return (0);
	} else {
		nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
		bzero((caddr_t)nmp, sizeof (struct nfsmount));
		TAILQ_INIT(&nmp->nm_bufq);
		mp->mnt_data = nmp;
		nmp->nm_getinfo = nfs_getnlminfo;
		nmp->nm_vinvalbuf = nfs_vinvalbuf;
	}
	vfs_getnewfsid(mp);
	nmp->nm_mountp = mp;
	mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);			

	/*
	 * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
	 * high, depending on whether we end up with negative offsets in
	 * the client or server somewhere.  2GB-1 may be safer.
	 *
	 * For V3, nfs_fsinfo will adjust this as necessary.  Assume maximum
	 * that we can handle until we find out otherwise.
	 */
	if ((argp->flags & NFSMNT_NFSV3) == 0)
		nmp->nm_maxfilesize = 0xffffffffLL;
	else
		nmp->nm_maxfilesize = OFF_MAX;

	nmp->nm_timeo = NFS_TIMEO;
	nmp->nm_retry = NFS_RETRANS;
	if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
		nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
	} else {
		nmp->nm_wsize = NFS_WSIZE;
		nmp->nm_rsize = NFS_RSIZE;
	}
	nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
	nmp->nm_readdirsize = NFS_READDIRSIZE;
	nmp->nm_numgrps = NFS_MAXGRPS;
	nmp->nm_readahead = NFS_DEFRAHEAD;
	nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
	nmp->nm_nametimeo = nametimeo;
	nmp->nm_negnametimeo = negnametimeo;
	nmp->nm_tprintf_delay = nfs_tprintf_delay;
	if (nmp->nm_tprintf_delay < 0)
		nmp->nm_tprintf_delay = 0;
	nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
	if (nmp->nm_tprintf_initial_delay < 0)
		nmp->nm_tprintf_initial_delay = 0;
	nmp->nm_fhsize = argp->fhsize;
	bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
	nmp->nm_nam = nam;
	/* Set up the sockets and per-host congestion */
	nmp->nm_sotype = argp->sotype;
	nmp->nm_soproto = argp->proto;
	nmp->nm_rpcops = &nfs_rpcops;

	nfs_decode_args(mp, nmp, argp, hst);

	/*
	 * For Connection based sockets (TCP,...) defer the connect until
	 * the first request, in case the server is not responding.
	 */
	if (nmp->nm_sotype == SOCK_DGRAM &&
		(error = nfs_connect(nmp)))
		goto bad;

	/*
	 * This is silly, but it has to be set so that vinifod() works.
	 * We do not want to do an nfs_statfs() here since we can get
	 * stuck on a dead server and we are holding a lock on the mount
	 * point.
	 */
	mtx_lock(&nmp->nm_mtx);
	mp->mnt_stat.f_iosize = nfs_iosize(nmp);
	mtx_unlock(&nmp->nm_mtx);
	/*
	 * A reference count is needed on the nfsnode representing the
	 * remote root.  If this object is not persistent, then backward
	 * traversals of the mount point (i.e. "..") will not work if
	 * the nfsnode gets flushed out of the cache. Ufs does not have
	 * this problem, because one can identify root inodes by their
	 * number == ROOTINO (2).
	 */
	error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
	if (error)
		goto bad;
	*vpp = NFSTOV(np);

	/*
	 * Get file attributes and transfer parameters for the
	 * mountpoint.  This has the side effect of filling in
	 * (*vpp)->v_type with the correct value.
	 */
	if (argp->flags & NFSMNT_NFSV3)
		nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
	else
		VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);

	/*
	 * Lose the lock but keep the ref.
	 */
	VOP_UNLOCK(*vpp, 0);

	return (0);
bad:
	nfs_disconnect(nmp);
	mtx_destroy(&nmp->nm_mtx);
	uma_zfree(nfsmount_zone, nmp);
	free(nam, M_SONAME);
	return (error);
}