nfs server: improve use of the VFS KPI

In particular, do not assume that vn_start_write() returns the same mp
as it was passed in, or never returns error.

Also be more accurate to return NULL vp and mp when error occured, to
catch wrong control flow easier.

Stop checking for NULL mp before calling vn_finished_write(), NULL mp
is handled transparently by the function.

Reviewed by:	rmacklem
Tested by:	pho
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D27881
This commit is contained in:
Konstantin Belousov 2021-01-01 17:35:44 +02:00
parent 8c45fe5d8e
commit 51a9b978e7
2 changed files with 23 additions and 18 deletions

View file

@ -3243,28 +3243,35 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
struct vnode **vpp, struct nfsexstuff *exp,
struct mount **mpp, int startwrite)
{
struct mount *mp;
struct mount *mp, *mpw;
struct ucred *credanon;
fhandle_t *fhp;
int error;
fhp = (fhandle_t *)nfp->nfsrvfh_data;
/*
* Check for the special case of the nfsv4root_fh.
*/
mp = vfs_busyfs(&fhp->fh_fsid);
if (mpp != NULL)
*mpp = mp;
*mpp = NULL;
*vpp = NULL;
fhp = (fhandle_t *)nfp->nfsrvfh_data;
mp = vfs_busyfs(&fhp->fh_fsid);
if (mp == NULL) {
*vpp = NULL;
nd->nd_repstat = ESTALE;
goto out;
}
if (startwrite) {
vn_start_write(NULL, mpp, V_WAIT);
mpw = mp;
error = vn_start_write(NULL, &mpw, V_WAIT);
if (error != 0) {
mpw = NULL;
vfs_unbusy(mp);
nd->nd_repstat = ESTALE;
goto out;
}
if (lktype == LK_SHARED && !(MNT_SHARED_WRITES(mp)))
lktype = LK_EXCLUSIVE;
}
} else
mpw = NULL;
nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp,
&credanon);
vfs_unbusy(mp);
@ -3276,6 +3283,7 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
if (!nd->nd_repstat && exp->nes_exflag == 0 &&
!(nd->nd_flag & ND_NFSV4)) {
vput(*vpp);
*vpp = NULL;
nd->nd_repstat = EACCES;
}
@ -3336,11 +3344,10 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
if (credanon != NULL)
crfree(credanon);
if (nd->nd_repstat) {
if (startwrite)
vn_finished_write(mp);
vn_finished_write(mpw);
*vpp = NULL;
if (mpp != NULL)
*mpp = NULL;
} else if (mpp != NULL) {
*mpp = mpw;
}
out:

View file

@ -612,8 +612,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
/*now*/ NULL, /*then*/ NULL);
if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
vn_finished_write(mp);
vn_finished_write(mp);
goto out;
}
@ -643,8 +642,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
vp, &nes);
}
if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
vn_finished_write(mp);
vn_finished_write(mp);
if (error == 0 && nd->nd_repstat == ERELOOKUP) {
/*