commit 5a6c59a6a8ccb63ae1b124fb6b5b611b19528ea9 Author: Mateusz Guzik Date: Tue Oct 27 17:17:13 2020 -0400 vfs: NDREINIT diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 85f54e0ecfc9..6b110f78925d 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -508,11 +508,15 @@ namei(struct nameidata *ndp) * While NDINIT may seem like a more natural place to do it, there are * callers which directly modify flags past invoking init. */ - cnp->cn_origflags = cnp->cn_flags; + KASSERT(cnp->cn_flags != 0, ("%s: passed in cn_flags are 0\n", __func__)); + KASSERT(cnp->cn_debugflags == 0, + ("%s: ndp already has debugflags != 0 (%" PRIx64 "), missed NDREINIT?\n", + __func__, cnp->cn_debugflags)); + cnp->cn_debugflags = cnp->cn_flags; + if (ndp->ni_startdir != NULL) + cnp->cn_debugflags |= DBG_HADSTARTDIR; #endif ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; - KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x\n", - __func__, ndp->ni_resflags)); KASSERT(cnp->cn_cred && td->td_proc, ("namei: bad cred/proc")); KASSERT((cnp->cn_flags & NAMEI_INTERNAL_FLAGS) == 0, ("namei: unexpected flags: %" PRIx64 "\n", @@ -523,6 +527,7 @@ namei(struct nameidata *ndp) MPASS(ndp->ni_startdir == NULL || ndp->ni_startdir->v_type == VDIR || ndp->ni_startdir->v_type == VBAD); + ndp->ni_resflags = 0; ndp->ni_lcf = 0; ndp->ni_vp = NULL; @@ -1509,7 +1514,7 @@ NDVALIDATE(struct nameidata *ndp) u_int64_t used, orig; cnp = &ndp->ni_cnd; - orig = cnp->cn_origflags; + orig = cnp->cn_debugflags & ~(DBG_HADSTARTDIR); used = cnp->cn_flags; switch (cnp->cn_nameiop) { case LOOKUP: @@ -1546,7 +1551,7 @@ NDVALIDATE(struct nameidata *ndp) panic("%s: mismatched flags for op %d: added %" PRIx64 ", " "removed %" PRIx64" (%" PRIx64" != %" PRIx64"; stored %" PRIx64" != %" PRIx64")", __func__, cnp->cn_nameiop, used & ~orig, orig &~ used, - orig, used, cnp->cn_origflags, cnp->cn_flags); + orig, used, cnp->cn_debugflags, cnp->cn_flags); } #endif diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 5c07afcc02e7..34d00d23806c 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -256,6 +256,7 @@ vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags, if (vn_start_write(ndp->ni_dvp, &mp, V_NOWAIT) != 0) { NDFREE(ndp, NDF_ONLY_PNBUF); vput(ndp->ni_dvp); + NDREINIT(ndp); if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) return (error); diff --git a/sys/sys/namei.h b/sys/sys/namei.h index 09b95510443a..59bc5c1b58cd 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -46,7 +46,7 @@ struct componentname { /* * Arguments to lookup. */ - u_int64_t cn_origflags; /* flags to namei */ + u_int64_t cn_debugflags;/* debug flags used by namei */ u_int64_t cn_flags; /* flags to namei */ struct thread *cn_thread;/* thread requesting lookup */ struct ucred *cn_cred; /* credentials */ @@ -166,7 +166,7 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, #define NOCAPCHECK 0x00100000 /* do not perform capability checks */ /* UNUSED 0x00200000 */ /* UNUSED 0x00400000 */ -/* UNUSED 0x00800000 */ +#define DBG_HADSTARTDIR 0x00800000 /* DEBUG: caller passed ni_startdir != NULL */ #define HASBUF 0x01000000 /* has allocated pathname buffer */ #define NOEXECCHECK 0x02000000 /* do not perform exec check on dir */ #define MAKEENTRY 0x04000000 /* entry is to be added to name cache */ @@ -180,8 +180,8 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, * Flags which must not be passed in by callers. */ #define NAMEI_INTERNAL_FLAGS \ - (HASBUF | NOEXECCHECK | MAKEENTRY | ISSYMLINK | ISLASTCN | ISDOTDOT | \ - TRAILINGSLASH) + (DBG_HADSTARTDIR | HASBUF | NOEXECCHECK | MAKEENTRY | ISSYMLINK | \ + ISLASTCN | ISDOTDOT | TRAILINGSLASH) /* * Namei results flags @@ -215,8 +215,16 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, */ #ifdef INVARIANTS #define NDINIT_PREFILL(arg) memset(arg, 0xff, sizeof(*arg)) +#define NDINIT_DEBUG(arg) { (arg)->ni_cnd.cn_debugflags = 0; } +#define NDREINIT_DEBUG(arg) { \ + if ((arg)->ni_cnd.cn_debugflags & DBG_HADSTARTDIR) \ + panic("NDREINIT on ndp with DBG_HADSTARTDIR"); \ + (arg)->ni_cnd.cn_debugflags = 0; \ +} #else #define NDINIT_PREFILL(arg) do { } while (0) +#define NDINIT_DEBUG(arg) do { } while (0) +#define NDREINIT_DEBUG(arg) do { } while (0) #endif #define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp, td) \ @@ -225,18 +233,25 @@ do { \ cap_rights_t *_rightsp = (rightsp); \ MPASS(_rightsp != NULL); \ NDINIT_PREFILL(_ndp); \ + NDINIT_DEBUG(_ndp); \ _ndp->ni_cnd.cn_nameiop = op; \ _ndp->ni_cnd.cn_flags = flags; \ _ndp->ni_segflg = segflg; \ _ndp->ni_dirp = namep; \ _ndp->ni_dirfd = dirfd; \ _ndp->ni_startdir = startdir; \ - _ndp->ni_resflags = 0; \ filecaps_init(&_ndp->ni_filecaps); \ _ndp->ni_cnd.cn_thread = td; \ _ndp->ni_rightsneeded = _rightsp; \ } while (0) +#define NDREINIT(ndp) \ +do { \ + struct nameidata *_ndp = (ndp); \ + NDREINIT_DEBUG(_ndp); \ + _ndp->ni_startdir = NULL; \ +} while (0) + #define NDF_NO_DVP_RELE 0x00000001 #define NDF_NO_DVP_UNLOCK 0x00000002 #define NDF_NO_DVP_PUT 0x00000003