DF-3056 / fix.diff
diff --git a/sys/vfs/dirfs/dirfs_vnops.c b/sys/vfs/dirfs/dirfs_vnops.c index a9acfbb5..3ce2d52e 100644 --- a/sys/vfs/dirfs/dirfs_vnops.c +++ b/sys/vfs/dirfs/dirfs_vnops.c @@ -984,6 +984,21 @@ dirfs_nrename(struct vop_nrename_args *ap) if (error == 0) { vp = fncp->nc_vp; /* file being renamed */ dnp = VP_TO_NODE(vp); + /* + * If the file moved to a different directory the parent + * pointer must follow: dirfs_findfd() and + * dirfs_node_absolute_path() build every host path by + * walking dn_parent, and a stale parent makes later + * setattr/getattr/unlink operations act on whatever file + * occupies the OLD path. + */ + if (dnp->dn_parent != tdnp) { + dirfs_node_t opnp = dnp->dn_parent; + dnp->dn_parent = tdnp; + dirfs_node_ref(tdnp); + if (opnp) + dirfs_node_drop(dmp, opnp); + } dirfs_node_setname(dnp, tncp->nc_name, tncp->nc_nlen); dirfs_knote(fdvp, NOTE_RENAME); /* |