Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Feb 2015 19:57:23 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r279401 - head/sys/fs/fdescfs
Message-ID:  <201502281957.t1SJvNUU053116@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Feb 28 19:57:22 2015
New Revision: 279401
URL: https://svnweb.freebsd.org/changeset/base/279401

Log:
  Some fixes for fdescfs lookup code.
  
  Do not ever return doomed vnode from lookup.  This could happen, if
  not checked, since dvp is relocked in the 'looking up ourselves' case.
  
  In the other case, since dvp is relocked, mount point might go away
  while fdesc_allocvp() is called.  Prevent the situation by doing
  vfs_busy() before unlocking dvp.  Reuse the vn_vget_ino_gen() helper.
  
  Reported and tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/fs/fdescfs/fdesc_vnops.c

Modified: head/sys/fs/fdescfs/fdesc_vnops.c
==============================================================================
--- head/sys/fs/fdescfs/fdesc_vnops.c	Sat Feb 28 19:11:37 2015	(r279400)
+++ head/sys/fs/fdescfs/fdesc_vnops.c	Sat Feb 28 19:57:22 2015	(r279401)
@@ -247,6 +247,28 @@ loop:
 	return (0);
 }
 
+struct fdesc_get_ino_args {
+	fdntype ftype;
+	unsigned fd_fd;
+	int ix;
+	struct file *fp;
+	struct thread *td;
+};
+
+static int
+fdesc_get_ino_alloc(struct mount *mp, void *arg, int lkflags,
+    struct vnode **rvp)
+{
+	struct fdesc_get_ino_args *a;
+	int error;
+
+	a = arg;
+	error = fdesc_allocvp(a->ftype, a->fd_fd, a->ix, mp, rvp);
+	fdrop(a->fp, a->td);
+	return (error);
+}
+
+
 /*
  * vp is the current namei directory
  * ndp is the name to locate in that directory...
@@ -265,6 +287,7 @@ fdesc_lookup(ap)
 	char *pname = cnp->cn_nameptr;
 	struct thread *td = cnp->cn_thread;
 	struct file *fp;
+	struct fdesc_get_ino_args arg;
 	int nlen = cnp->cn_namelen;
 	u_int fd, fd1;
 	int error;
@@ -326,6 +349,8 @@ fdesc_lookup(ap)
 		vn_lock(dvp, LK_RETRY | LK_EXCLUSIVE);
 		vdrop(dvp);
 		fvp = dvp;
+		if ((dvp->v_iflag & VI_DOOMED) != 0)
+			error = ENOENT;
 	} else {
 		/*
 		 * Unlock our root node (dvp) when doing this, since we might
@@ -335,16 +360,13 @@ fdesc_lookup(ap)
 		 * opposite lock order. Vhold the root vnode first so we don't
 		 * lose it.
 		 */
-		vhold(dvp);
-		VOP_UNLOCK(dvp, 0);
-		error = fdesc_allocvp(Fdesc, fd, FD_DESC + fd, dvp->v_mount,
-		    &fvp);
-		fdrop(fp, td);
-		/*
-		 * The root vnode must be locked last to prevent deadlock condition.
-		 */
-		vn_lock(dvp, LK_RETRY | LK_EXCLUSIVE);
-		vdrop(dvp);
+		arg.ftype = Fdesc;
+		arg.fd_fd = fd;
+		arg.ix = FD_DESC + fd;
+		arg.fp = fp;
+		arg.td = td;
+		error = vn_vget_ino_gen(dvp, fdesc_get_ino_alloc, &arg,
+		    LK_EXCLUSIVE, &fvp);
 	}
 	
 	if (error)



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