diff options
author | julian <julian@FreeBSD.org> | 1998-08-12 20:46:47 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1998-08-12 20:46:47 +0000 |
commit | 4c11bd9897e055091c31d225100831676b915dd4 (patch) | |
tree | d1b8a9724102b36859cf6ff6a37d4d6f3a95768b | |
parent | 3a1c25125ab1bb81d181b5f5b565afc299d837d9 (diff) | |
download | FreeBSD-src-4c11bd9897e055091c31d225100831676b915dd4.zip FreeBSD-src-4c11bd9897e055091c31d225100831676b915dd4.tar.gz |
Handle the case of moving a directory onto the top of a sibling's
child of the same name.
Submitted by: Kirk Mckusick with fixes from luoqi Chen
Obtained from: Whistle test tree.
-rw-r--r-- | contrib/sys/softupdates/ffs_softdep.c | 29 | ||||
-rw-r--r-- | sys/contrib/softupdates/ffs_softdep.c | 29 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 29 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 7 |
4 files changed, 85 insertions, 9 deletions
diff --git a/contrib/sys/softupdates/ffs_softdep.c b/contrib/sys/softupdates/ffs_softdep.c index 64b0c9f..72104c7 100644 --- a/contrib/sys/softupdates/ffs_softdep.c +++ b/contrib/sys/softupdates/ffs_softdep.c @@ -53,8 +53,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)ffs_softdep.c 9.27 (McKusick) 6/12/98 - * $Id: ffs_softdep.c,v 1.11 1998/06/12 20:48:30 julian Exp $ + * from: @(#)ffs_softdep.c 9.28 (McKusick) 8/8/98 + * $Id: ffs_softdep.c,v 1.12 1998/06/12 21:21:26 julian Exp $ */ /* @@ -2258,6 +2258,7 @@ free_diradd(dap) } else { dirrem = dap->da_previous; pagedep = dirrem->dm_pagedep; + dirrem->dm_dirinum = pagedep->pd_ino; add_to_worklist(&dirrem->dm_list); } if (inodedep_lookup(VFSTOUFS(pagedep->pd_mnt)->um_fs, dap->da_newinum, @@ -2437,6 +2438,20 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir) */ dirrem = newdirrem(bp, dp, ip, isrmdir); pagedep = dirrem->dm_pagedep; + /* + * The possible values for isrmdir: + * 0 - non-directory file rename + * 1 - directory rename within same directory + * inum - directory rename to new directory of given inode number + * When renaming to a new directory, we are both deleting and + * creating a new directory entry, so the link count on the new + * directory should not change. Thus we do not need the followup + * dirrem which is usually done in handle_workitem_remove. We set + * the DIRCHG flag to tell handle_workitem_remove to skip the + * followup dirrem. + */ + if (isrmdir > 1) + dirrem->dm_state |= DIRCHG; /* * Whiteouts have no additional dependencies, @@ -2546,6 +2561,16 @@ handle_workitem_remove(dirrem) ip->i_flag |= IN_CHANGE; if ((error = UFS_TRUNCATE(vp, (off_t)0, 0, p->p_ucred, p)) != 0) softdep_error("handle_workitem_remove: truncate", error); + /* + * Rename a directory to a new parent. Since, we are both deleting + * and creating a new directory entry, the link count on the new + * directory should not change. Thus we skip the followup dirrem. + */ + if (dirrem->dm_state & DIRCHG) { + vput(vp); + WORKITEM_FREE(dirrem, D_DIRREM); + return; + } ACQUIRE_LOCK(&lk); (void) inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, DEPALLOC, &inodedep); diff --git a/sys/contrib/softupdates/ffs_softdep.c b/sys/contrib/softupdates/ffs_softdep.c index 64b0c9f..72104c7 100644 --- a/sys/contrib/softupdates/ffs_softdep.c +++ b/sys/contrib/softupdates/ffs_softdep.c @@ -53,8 +53,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)ffs_softdep.c 9.27 (McKusick) 6/12/98 - * $Id: ffs_softdep.c,v 1.11 1998/06/12 20:48:30 julian Exp $ + * from: @(#)ffs_softdep.c 9.28 (McKusick) 8/8/98 + * $Id: ffs_softdep.c,v 1.12 1998/06/12 21:21:26 julian Exp $ */ /* @@ -2258,6 +2258,7 @@ free_diradd(dap) } else { dirrem = dap->da_previous; pagedep = dirrem->dm_pagedep; + dirrem->dm_dirinum = pagedep->pd_ino; add_to_worklist(&dirrem->dm_list); } if (inodedep_lookup(VFSTOUFS(pagedep->pd_mnt)->um_fs, dap->da_newinum, @@ -2437,6 +2438,20 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir) */ dirrem = newdirrem(bp, dp, ip, isrmdir); pagedep = dirrem->dm_pagedep; + /* + * The possible values for isrmdir: + * 0 - non-directory file rename + * 1 - directory rename within same directory + * inum - directory rename to new directory of given inode number + * When renaming to a new directory, we are both deleting and + * creating a new directory entry, so the link count on the new + * directory should not change. Thus we do not need the followup + * dirrem which is usually done in handle_workitem_remove. We set + * the DIRCHG flag to tell handle_workitem_remove to skip the + * followup dirrem. + */ + if (isrmdir > 1) + dirrem->dm_state |= DIRCHG; /* * Whiteouts have no additional dependencies, @@ -2546,6 +2561,16 @@ handle_workitem_remove(dirrem) ip->i_flag |= IN_CHANGE; if ((error = UFS_TRUNCATE(vp, (off_t)0, 0, p->p_ucred, p)) != 0) softdep_error("handle_workitem_remove: truncate", error); + /* + * Rename a directory to a new parent. Since, we are both deleting + * and creating a new directory entry, the link count on the new + * directory should not change. Thus we skip the followup dirrem. + */ + if (dirrem->dm_state & DIRCHG) { + vput(vp); + WORKITEM_FREE(dirrem, D_DIRREM); + return; + } ACQUIRE_LOCK(&lk); (void) inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, DEPALLOC, &inodedep); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 64b0c9f..72104c7 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -53,8 +53,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)ffs_softdep.c 9.27 (McKusick) 6/12/98 - * $Id: ffs_softdep.c,v 1.11 1998/06/12 20:48:30 julian Exp $ + * from: @(#)ffs_softdep.c 9.28 (McKusick) 8/8/98 + * $Id: ffs_softdep.c,v 1.12 1998/06/12 21:21:26 julian Exp $ */ /* @@ -2258,6 +2258,7 @@ free_diradd(dap) } else { dirrem = dap->da_previous; pagedep = dirrem->dm_pagedep; + dirrem->dm_dirinum = pagedep->pd_ino; add_to_worklist(&dirrem->dm_list); } if (inodedep_lookup(VFSTOUFS(pagedep->pd_mnt)->um_fs, dap->da_newinum, @@ -2437,6 +2438,20 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir) */ dirrem = newdirrem(bp, dp, ip, isrmdir); pagedep = dirrem->dm_pagedep; + /* + * The possible values for isrmdir: + * 0 - non-directory file rename + * 1 - directory rename within same directory + * inum - directory rename to new directory of given inode number + * When renaming to a new directory, we are both deleting and + * creating a new directory entry, so the link count on the new + * directory should not change. Thus we do not need the followup + * dirrem which is usually done in handle_workitem_remove. We set + * the DIRCHG flag to tell handle_workitem_remove to skip the + * followup dirrem. + */ + if (isrmdir > 1) + dirrem->dm_state |= DIRCHG; /* * Whiteouts have no additional dependencies, @@ -2546,6 +2561,16 @@ handle_workitem_remove(dirrem) ip->i_flag |= IN_CHANGE; if ((error = UFS_TRUNCATE(vp, (off_t)0, 0, p->p_ucred, p)) != 0) softdep_error("handle_workitem_remove: truncate", error); + /* + * Rename a directory to a new parent. Since, we are both deleting + * and creating a new directory entry, the link count on the new + * directory should not change. Thus we skip the followup dirrem. + */ + if (dirrem->dm_state & DIRCHG) { + vput(vp); + WORKITEM_FREE(dirrem, D_DIRREM); + return; + } ACQUIRE_LOCK(&lk); (void) inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, DEPALLOC, &inodedep); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 28d2634..ea3b0b3 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 - * $Id: ufs_vnops.c,v 1.96 1998/07/11 07:46:08 bde Exp $ + * $Id: ufs_vnops.c,v 1.97 1998/07/27 15:37:00 bde Exp $ */ #include "opt_quota.h" @@ -995,7 +995,7 @@ abortit: } ip->i_flag |= IN_RENAME; oldparent = dp->i_number; - doingdirectory++; + doingdirectory = 1; } VN_POLLEVENT(fdvp, POLLWRITE); vrele(fdvp); @@ -1143,7 +1143,8 @@ abortit: goto bad; } error = ufs_dirrewrite(dp, xp, ip->i_number, - IFTODT(ip->i_mode), doingdirectory); + IFTODT(ip->i_mode), + (doingdirectory && newparent) ? newparent : doingdirectory); if (error) goto bad; if (doingdirectory) { |