Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Jul 2015 17:40:21 +0200
From:      Mateusz Guzik <mjguzik@gmail.com>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        rwatson@FreeBSD.org, freebsd-fs@freebsd.org
Subject:   Re: [PATCH 3/4] vfs: simplify error handling in namei
Message-ID:  <20150709154021.GC1718@dft-labs.eu>
In-Reply-To: <20150709102533.GO2080@kib.kiev.ua>
References:  <20150707085857.GZ2080@kib.kiev.ua> <1436393231-5831-1-git-send-email-mjguzik@gmail.com> <1436393231-5831-4-git-send-email-mjguzik@gmail.com> <20150709102533.GO2080@kib.kiev.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Jul 09, 2015 at 01:25:33PM +0300, Konstantin Belousov wrote:
> On Thu, Jul 09, 2015 at 12:07:10AM +0200, Mateusz Guzik wrote:
> > From: Mateusz Guzik <mjg@freebsd.org>
> > 
> > The logic is reorganised so that there is one exit point prior to the
> > lookup loop. This is an intermediate step to making audit logging
> > functions use found vnode instead of translating ni_dirfd on their own.
> > 
> > ni_startdir validation is removed. The only in-tree consumer is nfs
> > which already makes sure it is a directory.
> > ---
> >  sys/kern/vfs_lookup.c | 50 +++++++++++++++++++++-----------------------------
> >  1 file changed, 21 insertions(+), 29 deletions(-)
> > 
> > diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
> > index e434464..d48fcff 100644
> > --- a/sys/kern/vfs_lookup.c
> > +++ b/sys/kern/vfs_lookup.c
> > @@ -158,7 +158,7 @@ namei(struct nameidata *ndp)
> >  	struct vnode *dp;	/* the directory we are searching */
> >  	struct iovec aiov;		/* uio for reading symbolic links */
> >  	struct uio auio;
> > -	int error, linklen;
> > +	int error, linklen, startdir_used;
> >  	struct componentname *cnp = &ndp->ni_cnd;
> >  	struct thread *td = cnp->cn_thread;
> >  	struct proc *p = td->td_proc;
> > @@ -169,6 +169,9 @@ namei(struct nameidata *ndp)
> >  	    ("namei: nameiop contaminated with flags"));
> >  	KASSERT((cnp->cn_flags & OPMASK) == 0,
> >  	    ("namei: flags contaminated with nameiops"));
> > +	if (ndp->ni_startdir != NULL)
> > +		MPASS(ndp->ni_startdir->v_type == VDIR ||
> > +		    ndp->ni_startdir->v_type == VBAD);
> Write this as
> 	MPASS(ndp->ni_startdir == NULL || ... == VDIR || ... == VBAD);
> ?
> 
Done.

> I think that the two previous patches are self-contained ?
> Please commit them, after that I think review of this patch can
> be finished.
> 

Committed.

diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index e434464..a93314e 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -158,7 +158,7 @@ namei(struct nameidata *ndp)
 	struct vnode *dp;	/* the directory we are searching */
 	struct iovec aiov;		/* uio for reading symbolic links */
 	struct uio auio;
-	int error, linklen;
+	int error, linklen, startdir_used;
 	struct componentname *cnp = &ndp->ni_cnd;
 	struct thread *td = cnp->cn_thread;
 	struct proc *p = td->td_proc;
@@ -169,6 +169,8 @@ namei(struct nameidata *ndp)
 	    ("namei: nameiop contaminated with flags"));
 	KASSERT((cnp->cn_flags & OPMASK) == 0,
 	    ("namei: flags contaminated with nameiops"));
+	MPASS(ndp->ni_startdir == NULL || ndp->ni_startdir->v_type == VDIR ||
+	    ndp->ni_startdir->v_type == VBAD);
 	if (!lookup_shared)
 		cnp->cn_flags &= ~LOCKSHARED;
 	fdp = p->p_fd;
@@ -242,23 +244,19 @@ namei(struct nameidata *ndp)
 	if (cnp->cn_flags & AUDITVNODE2)
 		AUDIT_ARG_UPATH2(td, ndp->ni_dirfd, cnp->cn_pnbuf);
 
+	startdir_used = 0;
 	dp = NULL;
 	cnp->cn_nameptr = cnp->cn_pnbuf;
 	if (cnp->cn_pnbuf[0] == '/') {
 		error = namei_handle_root(ndp, &dp);
-		FILEDESC_SUNLOCK(fdp);
-		if (error != 0) {
-			vrele(ndp->ni_rootdir);
-			if (ndp->ni_startdir != NULL)
-				vrele(ndp->ni_startdir);
-			namei_cleanup_cnp(cnp);
-			return (error);
-		}
 	} else {
 		if (ndp->ni_startdir != NULL) {
 			dp = ndp->ni_startdir;
-			error = 0;
-		} else if (ndp->ni_dirfd != AT_FDCWD) {
+			startdir_used = 1;
+		} else if (ndp->ni_dirfd == AT_FDCWD) {
+			dp = fdp->fd_cdir;
+			VREF(dp);
+		} else {
 			cap_rights_t rights;
 
 			rights = ndp->ni_rightsneeded;
@@ -285,25 +283,18 @@ namei(struct nameidata *ndp)
 			}
 #endif
 		}
-		if (error != 0 || dp != NULL) {
-			FILEDESC_SUNLOCK(fdp);
-			if (error == 0 && dp->v_type != VDIR) {
-				vrele(dp);
-				error = ENOTDIR;
-			}
-		}
-		if (error) {
-			vrele(ndp->ni_rootdir);
-			namei_cleanup_cnp(cnp);
-			return (error);
-		}
+		if (error == 0 && dp->v_type != VDIR)
+			error = ENOTDIR;
 	}
-	if (dp == NULL) {
-		dp = fdp->fd_cdir;
-		VREF(dp);
-		FILEDESC_SUNLOCK(fdp);
-		if (ndp->ni_startdir != NULL)
-			vrele(ndp->ni_startdir);
+	FILEDESC_SUNLOCK(fdp);
+	if (ndp->ni_startdir != NULL && !startdir_used)
+		vrele(ndp->ni_startdir);
+	if (error != 0) {
+		if (dp != NULL)
+			vrele(dp);
+		vrele(ndp->ni_rootdir);
+		namei_cleanup_cnp(cnp);
+		return (error);
 	}
 	SDT_PROBE(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf,
 	    cnp->cn_flags, 0, 0);
-- 
Mateusz Guzik <mjguzik gmail.com>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20150709154021.GC1718>