[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