[Midnightbsd-cvs] src [9120] trunk/sys: When renaming a directory from one parent to another, call ufs_checkpath() to walk from our new location to the root of the file system.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Oct 1 20:35:31 EDT 2016


Revision: 9120
          http://svnweb.midnightbsd.org/src/?rev=9120
Author:   laffer1
Date:     2016-10-01 20:35:31 -0400 (Sat, 01 Oct 2016)
Log Message:
-----------
When renaming a directory from one parent to another, call ufs_checkpath() to walk from our new location to the root of the file system.

Modified Paths:
--------------
    trunk/sys/kern/vfs_cache.c
    trunk/sys/sys/vnode.h
    trunk/sys/ufs/ufs/ufs_lookup.c

Modified: trunk/sys/kern/vfs_cache.c
===================================================================
--- trunk/sys/kern/vfs_cache.c	2016-10-02 00:34:47 UTC (rev 9119)
+++ trunk/sys/kern/vfs_cache.c	2016-10-02 00:35:31 UTC (rev 9120)
@@ -1387,6 +1387,28 @@
 	return (0);
 }
 
+struct vnode *
+vn_dir_dd_ino(struct vnode *vp)
+{
+	struct namecache *ncp;
+	struct vnode *ddvp;
+
+	ASSERT_VOP_LOCKED(vp, "vn_dir_dd_ino");
+	CACHE_RLOCK();
+	TAILQ_FOREACH(ncp, &(vp->v_cache_dst), nc_dst) {
+		if ((ncp->nc_flag & NCF_ISDOTDOT) != 0)
+			continue;
+		ddvp = ncp->nc_dvp;
+		VI_LOCK(ddvp);
+		CACHE_RUNLOCK();
+		if (vget(ddvp, LK_INTERLOCK | LK_SHARED | LK_NOWAIT, curthread))
+			return (NULL);
+		return (ddvp);
+	}
+	CACHE_RUNLOCK();
+	return (NULL);
+}
+
 int
 vn_commname(struct vnode *vp, char *buf, u_int buflen)
 {

Modified: trunk/sys/sys/vnode.h
===================================================================
--- trunk/sys/sys/vnode.h	2016-10-02 00:34:47 UTC (rev 9119)
+++ trunk/sys/sys/vnode.h	2016-10-02 00:35:31 UTC (rev 9120)
@@ -621,6 +621,8 @@
 	    char **retbuf, char **freebuf);
 int	vn_fullpath_global(struct thread *td, struct vnode *vn,
 	    char **retbuf, char **freebuf);
+struct vnode *
+	vn_dir_dd_ino(struct vnode *vp);
 int	vn_commname(struct vnode *vn, char *buf, u_int buflen);
 int	vn_path_to_global_path(struct thread *td, struct vnode *vp,
 	    char *path, u_int pathlen);

Modified: trunk/sys/ufs/ufs/ufs_lookup.c
===================================================================
--- trunk/sys/ufs/ufs/ufs_lookup.c	2016-10-02 00:34:47 UTC (rev 9119)
+++ trunk/sys/ufs/ufs/ufs_lookup.c	2016-10-02 00:35:31 UTC (rev 9120)
@@ -1385,13 +1385,29 @@
 }
 
 static int
-ufs_dir_dd_ino(struct vnode *vp, struct ucred *cred, ino_t *dd_ino)
+ufs_dir_dd_ino(struct vnode *vp, struct ucred *cred, ino_t *dd_ino,
+    struct vnode **dd_vp)
 {
 	struct dirtemplate dirbuf;
+	struct vnode *ddvp;
 	int error, namlen;
 
+	ASSERT_VOP_LOCKED(vp, "ufs_dir_dd_ino");
 	if (vp->v_type != VDIR)
 		return (ENOTDIR);
+	/*
+	 * First check to see if we have it in the name cache.
+	 */
+	if ((ddvp = vn_dir_dd_ino(vp)) != NULL) {
+		KASSERT(ddvp->v_mount == vp->v_mount,
+		    ("ufs_dir_dd_ino: Unexpected mount point crossing"));
+		*dd_ino = VTOI(ddvp)->i_number;
+		*dd_vp = ddvp;
+		return (0);
+	}
+	/*
+	 * Have to read the directory.
+	 */
 	error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf,
 	    sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE,
 	    IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, NULL, NULL);
@@ -1409,6 +1425,7 @@
 	    dirbuf.dotdot_name[1] != '.')
 		return (ENOTDIR);
 	*dd_ino = dirbuf.dotdot_ino;
+	*dd_vp = NULL;
 	return (0);
 }
 
@@ -1433,7 +1450,7 @@
 	if (target->i_number == ROOTINO)
 		return (0);
 	for (;;) {
-		error = ufs_dir_dd_ino(vp, cred, &dd_ino);
+		error = ufs_dir_dd_ino(vp, cred, &dd_ino, &vp1);
 		if (error != 0)
 			break;
 		if (dd_ino == source_ino) {
@@ -1444,22 +1461,16 @@
 			break;
 		if (dd_ino == parent_ino)
 			break;
-		error = VFS_VGET(mp, dd_ino, LK_SHARED | LK_NOWAIT, &vp1);
-		if (error != 0) {
-			*wait_ino = dd_ino;
-			break;
+		if (vp1 == NULL) {
+			error = VFS_VGET(mp, dd_ino, LK_SHARED | LK_NOWAIT,
+			    &vp1);
+			if (error != 0) {
+				*wait_ino = dd_ino;
+				break;
+			}
 		}
-		/* Recheck that ".." still points to vp1 after relock of vp */
-		error = ufs_dir_dd_ino(vp, cred, &dd_ino);
-		if (error != 0) {
-			vput(vp1);
-			break;
-		}
-		/* Redo the check of ".." if directory was reparented */
-		if (dd_ino != VTOI(vp1)->i_number) {
-			vput(vp1);
-			continue;
-		}
+		KASSERT(dd_ino == VTOI(vp1)->i_number,
+		    ("directory %d reparented\n", VTOI(vp1)->i_number));
 		if (vp != tvp)
 			vput(vp);
 		vp = vp1;
@@ -1467,6 +1478,8 @@
 
 	if (error == ENOTDIR)
 		panic("checkpath: .. not a directory\n");
+	if (vp1 != NULL)
+		vput(vp1);
 	if (vp != tvp)
 		vput(vp);
 	return (error);



More information about the Midnightbsd-cvs mailing list