All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] Do not dentry_unhash in VFS (v3)
@ 2011-05-24 20:06 Sage Weil
  2011-05-24 20:06 ` [PATCH 01/19] vfs: dentry_unhash immediately prior to rmdir Sage Weil
                   ` (19 more replies)
  0 siblings, 20 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Hi Al,

Here's the latest version of my dentry_unhash series, with Christoph's 
ack on the push-down patches, some additional cleanup he suggested, xfs 
and gfs2 removed from the push-down (at maintainers' request), and acks 
for ocfs2 and exofs.  Is this suitable for this merge window?

The series can also be pulled from git at

        git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git dentry_unhash

Summary:

For the most part the VFS does not hash or unhash dentries outside of 
dcache pruning.  This is left to the file system namespace methods.  The 
only exception is on rmdir and directory rename, where we call 
dentry_unhash() for the benefit of a few file systems that can't handle 
lingering references to the empty and unlinked directory.

This patchset aims to clean this up by pushing the dentry_unhash calls 
into each fs where they can be safely removed on a per-fs basis.  We 
also take this opportunity to finally fix a longstanding bug in 
vfs_rename_dir() which rehashes new_dentry (Miklos' patch, see
        http://marc.info/?l=linux-fsdevel&m=121666695328987&w=2
        http://marc.info/?t=121580579500004&r=1&w=2
).

On a per-fs basis, the dentry_unhash calls can be replaced with 
shrink_dcache_parent (or dropped entirely) if it is safe to do so.  I 
expect that this is safe for most of them.

My hope is that this will move us closer to being able to introduce a 
->d_prune d_op.  Independent of that, however, I think this is a 
worthwhile dcache cleanup.

Thanks!
sage


v3:
 * drop xfs from push-down at Christoph's request
 * rebased against Linus' master
 * fixed Miklos' email address

v2:
 * clean up vfs_rmdir flow
 * clean up vfs_rename_dir flow
 * clean up vfs_rename_other flow to match vfs_rename_dir
 * drop gfs2 from push-down at Steve's request


Miklos Szeredi (1):
  vfs: fix vfs_rename_dir for FS_RENAME_DOES_D_MOVE filesystems

Sage Weil (18):
  vfs: dentry_unhash immediately prior to rmdir
  vfs: remove dget() from dentry_unhash()
  vfs: push dentry_unhash on rmdir into file systems
  vfs: push dentry_unhash on rename_dir into file systems
  vfs: update dentry_unhash() comment
  libfs: drop unneeded dentry_unhash
  vfs: clean up vfs_rmdir
  vfs: clean up vfs_rename_dir
  vfs: clean up vfs_rename_other
  ceph: remove unnecessary dentry_unhash calls
  btrfs: remove unnecessary dentry_unhash in rmdir/rename_dir
  ext4: remove unnecessary dentry_unhash on rmdir/rename_dir
  ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  ext2: remove unnecessary dentry_unhash on rmdir/rename_dir
  nfs: remove unnecessary dentry_unhash on rmdir/rename_dir
  exofs: remove unnecessary dentry_unhash on rmdir/rename_dir
  ocfs2: remove unnecessary dentry_unhash on rmdir/rename_dir
  cifs: remove unnecessary dentry_unhash on rmdir/rename_dir

 fs/9p/vfs_inode.c       |    4 ++
 fs/affs/namei.c         |    5 ++
 fs/afs/dir.c            |    5 ++
 fs/autofs4/root.c       |    2 +
 fs/bfs/dir.c            |    3 +
 fs/coda/dir.c           |    5 ++
 fs/configfs/dir.c       |    2 +
 fs/ecryptfs/inode.c     |    5 ++
 fs/fat/namei_msdos.c    |    5 ++
 fs/fat/namei_vfat.c     |    5 ++
 fs/fuse/dir.c           |    6 +++
 fs/hfs/dir.c            |    6 +++
 fs/hfsplus/dir.c        |    8 +++-
 fs/hostfs/hostfs_kern.c |    5 ++
 fs/hpfs/namei.c         |    9 +++-
 fs/jffs2/dir.c          |    5 ++
 fs/jfs/namei.c          |    5 ++
 fs/logfs/dir.c          |    5 ++
 fs/minix/namei.c        |    5 ++
 fs/namei.c              |  108 ++++++++++++++++++++++------------------------
 fs/ncpfs/dir.c          |    5 ++
 fs/nilfs2/namei.c       |    5 ++
 fs/omfs/dir.c           |   11 ++++-
 fs/reiserfs/namei.c     |    5 ++
 fs/reiserfs/xattr.c     |    1 -
 fs/sysv/namei.c         |    5 ++
 fs/ubifs/dir.c          |    5 ++
 fs/udf/namei.c          |    5 ++
 fs/ufs/namei.c          |    5 ++
 29 files changed, 186 insertions(+), 64 deletions(-)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 01/19] vfs: dentry_unhash immediately prior to rmdir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 02/19] vfs: remove dget() from dentry_unhash() Sage Weil
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

This presumes that there is no reason to unhash a dentry if we fail because
it is a mountpoint or the LSM check fails, and that the LSM checks do not
depend on the dentry being unhashed.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/namei.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 6ff858c..1df3361 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2664,24 +2664,24 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 		return -EPERM;
 
 	mutex_lock(&dentry->d_inode->i_mutex);
-	dentry_unhash(dentry);
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
 		error = security_inode_rmdir(dir, dentry);
 		if (!error) {
+			dentry_unhash(dentry);
 			error = dir->i_op->rmdir(dir, dentry);
 			if (!error) {
 				dentry->d_inode->i_flags |= S_DEAD;
 				dont_mount(dentry);
 			}
+			dput(dentry);
 		}
 	}
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	if (!error) {
 		d_delete(dentry);
 	}
-	dput(dentry);
 
 	return error;
 }
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 02/19] vfs: remove dget() from dentry_unhash()
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
  2011-05-24 20:06 ` [PATCH 01/19] vfs: dentry_unhash immediately prior to rmdir Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 03/19] vfs: push dentry_unhash on rmdir into file systems Sage Weil
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

This serves no useful purpose that I can discern.  All callers (rename,
rmdir) hold their own reference to the dentry.

A quick audit of all file systems showed no relevant checks on the value
of d_count in vfs_rmdir/vfs_rename_dir paths.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/hpfs/namei.c     |    3 ---
 fs/namei.c          |    5 +----
 fs/reiserfs/xattr.c |    1 -
 3 files changed, 1 insertions(+), 8 deletions(-)

diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 1f05839..0f89a64 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -395,7 +395,6 @@ again:
 
 		dentry_unhash(dentry);
 		if (!d_unhashed(dentry)) {
-			dput(dentry);
 			hpfs_unlock(dir->i_sb);
 			return -ENOSPC;
 		}
@@ -403,7 +402,6 @@ again:
 		    !S_ISREG(inode->i_mode) ||
 		    get_write_access(inode)) {
 			d_rehash(dentry);
-			dput(dentry);
 		} else {
 			struct iattr newattrs;
 			/*printk("HPFS: truncating file before delete.\n");*/
@@ -411,7 +409,6 @@ again:
 			newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 			err = notify_change(dentry, &newattrs);
 			put_write_access(inode);
-			dput(dentry);
 			if (!err)
 				goto again;
 		}
diff --git a/fs/namei.c b/fs/namei.c
index 1df3361..4866bff 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2645,10 +2645,9 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
  */
 void dentry_unhash(struct dentry *dentry)
 {
-	dget(dentry);
 	shrink_dcache_parent(dentry);
 	spin_lock(&dentry->d_lock);
-	if (dentry->d_count == 2)
+	if (dentry->d_count == 1)
 		__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
 }
@@ -2675,7 +2674,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 				dentry->d_inode->i_flags |= S_DEAD;
 				dont_mount(dentry);
 			}
-			dput(dentry);
 		}
 	}
 	mutex_unlock(&dentry->d_inode->i_mutex);
@@ -3102,7 +3100,6 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 		mutex_unlock(&target->i_mutex);
 		if (d_unhashed(new_dentry))
 			d_rehash(new_dentry);
-		dput(new_dentry);
 	}
 	if (!error)
 		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 47d2a44..50f1abc 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -105,7 +105,6 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	if (!error)
 		d_delete(dentry);
-	dput(dentry);
 
 	return error;
 }
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 03/19] vfs: push dentry_unhash on rmdir into file systems
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
  2011-05-24 20:06 ` [PATCH 01/19] vfs: dentry_unhash immediately prior to rmdir Sage Weil
  2011-05-24 20:06 ` [PATCH 02/19] vfs: remove dget() from dentry_unhash() Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 04/19] vfs: push dentry_unhash on rename_dir " Sage Weil
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Only a few file systems need this.  Start by pushing it down into each
fs rmdir method (except gfs2 and xfs) so it can be dealt with on a per-fs
basis.

This does not change behavior for any in-tree file systems.

Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/9p/vfs_inode.c       |    1 +
 fs/affs/namei.c         |    2 ++
 fs/afs/dir.c            |    2 ++
 fs/autofs4/root.c       |    2 ++
 fs/btrfs/inode.c        |    2 ++
 fs/ceph/dir.c           |    3 +++
 fs/cifs/inode.c         |    2 ++
 fs/coda/dir.c           |    2 ++
 fs/configfs/dir.c       |    2 ++
 fs/ecryptfs/inode.c     |    2 ++
 fs/exofs/namei.c        |    2 ++
 fs/ext2/namei.c         |    2 ++
 fs/ext3/namei.c         |    2 ++
 fs/ext4/namei.c         |    2 ++
 fs/fat/namei_msdos.c    |    2 ++
 fs/fat/namei_vfat.c     |    2 ++
 fs/fuse/dir.c           |    2 ++
 fs/hfs/dir.c            |    3 +++
 fs/hfsplus/dir.c        |    2 ++
 fs/hostfs/hostfs_kern.c |    2 ++
 fs/hpfs/namei.c         |    2 ++
 fs/jffs2/dir.c          |    2 ++
 fs/jfs/namei.c          |    2 ++
 fs/libfs.c              |    2 ++
 fs/logfs/dir.c          |    2 ++
 fs/minix/namei.c        |    2 ++
 fs/namei.c              |    1 -
 fs/ncpfs/dir.c          |    2 ++
 fs/nfs/dir.c            |    2 ++
 fs/nilfs2/namei.c       |    2 ++
 fs/ocfs2/namei.c        |    3 +++
 fs/omfs/dir.c           |    8 ++++++--
 fs/reiserfs/namei.c     |    2 ++
 fs/sysv/namei.c         |    2 ++
 fs/ubifs/dir.c          |    2 ++
 fs/udf/namei.c          |    2 ++
 fs/ufs/namei.c          |    2 ++
 37 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 7f6c677..ecd7717 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -814,6 +814,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
 
 int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
 {
+	dentry_unhash(d);
 	return v9fs_remove(i, d, 1);
 }
 
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index e3e9efc..d087153 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -320,6 +320,8 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
 		 dentry->d_inode->i_ino,
 		 (int)dentry->d_name.len, dentry->d_name.name);
 
+	dentry_unhash(dentry);
+
 	return affs_remove_header(dentry);
 }
 
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 20c106f..9a7f414 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -845,6 +845,8 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 	_enter("{%x:%u},{%s}",
 	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
+	dentry_unhash(dentry);
+
 	ret = -ENAMETOOLONG;
 	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index f55ae23..87d95a8 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -583,6 +583,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
 	if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
+	dentry_unhash(dentry);
+
 	if (atomic_dec_and_test(&ino->count)) {
 		p_ino = autofs4_dentry_ino(dentry->d_parent);
 		if (p_ino && dentry->d_parent != dentry)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7cd8ab0..c692dad 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3062,6 +3062,8 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 	    inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
 		return -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	trans = __unlink_start_trans(dir, dentry);
 	if (IS_ERR(trans))
 		return PTR_ERR(trans);
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 1a867a3..d2e5490 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -827,6 +827,9 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
 	int err = -EROFS;
 	int op;
 
+	if ((dentry->d_inode->i_mode & S_IFMT) == S_IFDIR)
+		dentry_unhash(dentry);
+
 	if (ceph_snap(dir) == CEPH_SNAPDIR) {
 		/* rmdir .snap/foo is RMSNAP */
 		dout("rmsnap dir %p '%.*s' dn %p\n", dir, dentry->d_name.len,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index de02ed5..b2bff7e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1461,6 +1461,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
 
 	cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
 
+	dentry_unhash(direntry);
+
 	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 2b8dae4..9f72b75 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -336,6 +336,8 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
 	int len = de->d_name.len;
 	int error;
 
+	dentry_unhash(de);
+
 	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
 	if (!error) {
 		/* VFS may delete the child */
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 9a37a9b..9d17d35 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1359,6 +1359,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
 	struct module *subsys_owner = NULL, *dead_item_owner = NULL;
 	int ret;
 
+	dentry_unhash(dentry);
+
 	if (dentry->d_parent == configfs_sb->s_root)
 		return -EPERM;
 
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 4d4cc6a..c88612f 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -521,6 +521,8 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
 	struct dentry *lower_dir_dentry;
 	int rc;
 
+	dentry_unhash(dentry);
+
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
 	dget(dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c
index 4d70db1..0697175 100644
--- a/fs/exofs/namei.c
+++ b/fs/exofs/namei.c
@@ -227,6 +227,8 @@ static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = dentry->d_inode;
 	int err = -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	if (exofs_empty_dir(inode)) {
 		err = exofs_unlink(dir, dentry);
 		if (!err) {
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index ed5c5d4..7a5ad97 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -296,6 +296,8 @@ static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
 	struct inode * inode = dentry->d_inode;
 	int err = -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	if (ext2_empty_dir(inode)) {
 		err = ext2_unlink(dir, dentry);
 		if (!err) {
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 32f3b86..552f94d 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2074,6 +2074,8 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
 	struct ext3_dir_entry_2 * de;
 	handle_t *handle;
 
+	dentry_unhash(dentry);
+
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
 	dquot_initialize(dir);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 67fd0b0..957580d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2123,6 +2123,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
 	struct ext4_dir_entry_2 *de;
 	handle_t *handle;
 
+	dentry_unhash(dentry);
+
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
 	dquot_initialize(dir);
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 3b222da..4d147f6 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -326,6 +326,8 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
 	struct fat_slot_info sinfo;
 	int err;
 
+	dentry_unhash(dentry);
+
 	lock_super(sb);
 	/*
 	 * Check whether the directory is not in use, then check
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 20b4ea5..740bb78 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -824,6 +824,8 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
 	struct fat_slot_info sinfo;
 	int err;
 
+	dentry_unhash(dentry);
+
 	lock_super(sb);
 
 	err = fat_dir_empty(inode);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index b32eb29..0d84ce6 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -667,6 +667,8 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
+	dentry_unhash(entry);
+
 	req->in.h.opcode = FUSE_RMDIR;
 	req->in.h.nodeid = get_node_id(dir);
 	req->in.numargs = 1;
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index b4d70b1..616cfe0 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -253,6 +253,9 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = dentry->d_inode;
 	int res;
 
+	if (S_ISDIR(inode->i_mode))
+		dentry_unhash(dentry);
+
 	if (S_ISDIR(inode->i_mode) && inode->i_size != 2)
 		return -ENOTEMPTY;
 	res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 4df5059..23451a9 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -370,6 +370,8 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = dentry->d_inode;
 	int res;
 
+	dentry_unhash(dentry);
+
 	if (inode->i_size != 2)
 		return -ENOTEMPTY;
 
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 2638c83..73ea3ba 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -683,6 +683,8 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
 	char *file;
 	int err;
 
+	dentry_unhash(dentry);
+
 	if ((file = dentry_name(dentry)) == NULL)
 		return -ENOMEM;
 	err = do_rmdir(file);
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 0f89a64..e3e03fa 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -439,6 +439,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 	int err;
 	int r;
 
+	dentry_unhash(dentry);
+
 	hpfs_adjust_length(name, &len);
 	hpfs_lock(dir->i_sb);
 	err = -ENOENT;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 82faddd..727d644 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -609,6 +609,8 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
 	int ret;
 	uint32_t now = get_seconds();
 
+	dentry_unhash(dentry);
+
 	for (fd = f->dents ; fd; fd = fd->next) {
 		if (fd->ino)
 			return -ENOTEMPTY;
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index eaaf2b5..0569dac 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -360,6 +360,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
 
 	jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	dentry_unhash(dentry);
+
 	/* Init inode for quota operations. */
 	dquot_initialize(dip);
 	dquot_initialize(ip);
diff --git a/fs/libfs.c b/fs/libfs.c
index c88eab5..1e2ba5a 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -311,6 +311,8 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
 	if (!simple_empty(dentry))
 		return -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	drop_nlink(dentry->d_inode);
 	simple_unlink(dir, dentry);
 	drop_nlink(dir);
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 9ed89d1..2b32734 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -273,6 +273,8 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 
+	dentry_unhash(dentry);
+
 	if (!logfs_empty_dir(inode))
 		return -ENOTEMPTY;
 
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 6e6777f..091626f 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -168,6 +168,8 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
 	struct inode * inode = dentry->d_inode;
 	int err = -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	if (minix_empty_dir(inode)) {
 		err = minix_unlink(dir, dentry);
 		if (!err) {
diff --git a/fs/namei.c b/fs/namei.c
index 4866bff..57f3693 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2668,7 +2668,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 	else {
 		error = security_inode_rmdir(dir, dentry);
 		if (!error) {
-			dentry_unhash(dentry);
 			error = dir->i_op->rmdir(dir, dentry);
 			if (!error) {
 				dentry->d_inode->i_flags |= S_DEAD;
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index f6946bb..57336b7 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -1033,6 +1033,8 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
 	DPRINTK("ncp_rmdir: removing %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
+	dentry_unhash(dentry);
+
 	error = -EBUSY;
 	if (!d_unhashed(dentry))
 		goto out;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 7237672..48483b5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1748,6 +1748,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 	dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
+	dentry_unhash(dentry);
+
 	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
 	/* Ensure the VFS deletes this inode */
 	if (error == 0 && dentry->d_inode != NULL)
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 546849b..78306e6 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -334,6 +334,8 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
 	struct nilfs_transaction_info ti;
 	int err;
 
+	dentry_unhash(dentry);
+
 	err = nilfs_transaction_begin(dir->i_sb, &ti, 0);
 	if (err)
 		return err;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index e5d738c..b017ebb 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -810,6 +810,9 @@ static int ocfs2_unlink(struct inode *dir,
 			   (unsigned long long)OCFS2_I(dir)->ip_blkno,
 			   (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
+	if (S_ISDIR(inode->i_mode))
+		dentry_unhash(dentry);
+
 	dquot_initialize(dir);
 
 	BUG_ON(dentry->d_parent->d_inode != dir);
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
index de4ff29..95ef443 100644
--- a/fs/omfs/dir.c
+++ b/fs/omfs/dir.c
@@ -240,8 +240,12 @@ static int omfs_remove(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = dentry->d_inode;
 	int ret;
 
-	if (S_ISDIR(inode->i_mode) && !omfs_dir_is_empty(inode))
-		return -ENOTEMPTY;
+
+	if (S_ISDIR(inode->i_mode)) {
+		dentry_unhash(dentry);
+		if (!omfs_dir_is_empty(inode))
+			return -ENOTEMPTY;
+	}
 
 	ret = omfs_delete_entry(dentry);
 	if (ret)
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 1186626..43e94f0 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -831,6 +831,8 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
 	INITIALIZE_PATH(path);
 	struct reiserfs_dir_entry de;
 
+	dentry_unhash(dentry);
+
 	/* we will be doing 2 balancings and update 2 stat data, we change quotas
 	 * of the owner of the directory and of the owner of the parent directory.
 	 * The quota structure is possibly deleted only on last iput => outside
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index e474fbc..fac64ac 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -196,6 +196,8 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
 	struct inode *inode = dentry->d_inode;
 	int err = -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	if (sysv_empty_dir(inode)) {
 		err = sysv_unlink(dir, dentry);
 		if (!err) {
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 7217d67..6ca9176 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -656,6 +656,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
 	struct ubifs_inode *dir_ui = ubifs_inode(dir);
 	struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 };
 
+	dentry_unhash(dentry);
+
 	/*
 	 * Budget request settings: deletion direntry, deletion inode and
 	 * changing the parent inode. If budgeting fails, go ahead anyway
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index f1dce84..b70f026 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -783,6 +783,8 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
 	struct fileIdentDesc *fi, cfi;
 	struct kernel_lb_addr tloc;
 
+	dentry_unhash(dentry);
+
 	retval = -ENOENT;
 	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
 	if (!fi)
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 29309e2..3a769d5 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -258,6 +258,8 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 	struct inode * inode = dentry->d_inode;
 	int err= -ENOTEMPTY;
 
+	dentry_unhash(dentry);
+
 	lock_ufs(dir->i_sb);
 	if (ufs_empty_dir (inode)) {
 		err = ufs_unlink(dir, dentry);
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 04/19] vfs: push dentry_unhash on rename_dir into file systems
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (2 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 03/19] vfs: push dentry_unhash on rmdir into file systems Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 05/19] vfs: update dentry_unhash() comment Sage Weil
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Only a few file systems need this.  Start by pushing it down into each
rename method (except gfs2 and xfs) so that it can be dealt with on a
per-fs basis.

Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/9p/vfs_inode.c       |    3 +++
 fs/affs/namei.c         |    3 +++
 fs/afs/dir.c            |    3 +++
 fs/bfs/dir.c            |    3 +++
 fs/btrfs/inode.c        |    3 +++
 fs/ceph/dir.c           |    3 +++
 fs/cifs/inode.c         |    3 +++
 fs/coda/dir.c           |    3 +++
 fs/ecryptfs/inode.c     |    3 +++
 fs/exofs/namei.c        |    3 +++
 fs/ext2/namei.c         |    3 +++
 fs/ext3/namei.c         |    3 +++
 fs/ext4/namei.c         |    3 +++
 fs/fat/namei_msdos.c    |    3 +++
 fs/fat/namei_vfat.c     |    3 +++
 fs/fuse/dir.c           |    4 ++++
 fs/hfs/dir.c            |    3 +++
 fs/hfsplus/dir.c        |    6 ++++--
 fs/hostfs/hostfs_kern.c |    3 +++
 fs/hpfs/namei.c         |    4 ++++
 fs/jffs2/dir.c          |    3 +++
 fs/jfs/namei.c          |    3 +++
 fs/libfs.c              |    3 +++
 fs/logfs/dir.c          |    3 +++
 fs/minix/namei.c        |    3 +++
 fs/namei.c              |   12 ++----------
 fs/ncpfs/dir.c          |    3 +++
 fs/nfs/dir.c            |    3 +++
 fs/nilfs2/namei.c       |    3 +++
 fs/ocfs2/namei.c        |    3 +++
 fs/omfs/dir.c           |    3 +++
 fs/reiserfs/namei.c     |    3 +++
 fs/sysv/namei.c         |    3 +++
 fs/ubifs/dir.c          |    3 +++
 fs/udf/namei.c          |    3 +++
 fs/ufs/namei.c          |    3 +++
 36 files changed, 110 insertions(+), 12 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index ecd7717..8d7f3e6 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -840,6 +840,9 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct p9_fid *newdirfid;
 	struct p9_wstat wstat;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	P9_DPRINTK(P9_DEBUG_VFS, "\n");
 	retval = 0;
 	old_inode = old_dentry->d_inode;
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index d087153..03330e2 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -419,6 +419,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct buffer_head *bh = NULL;
 	int retval;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
 		 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
 		 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 9a7f414..2c4e051 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -1148,6 +1148,9 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct key *key;
 	int ret;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	vnode = AFS_FS_I(old_dentry->d_inode);
 	orig_dvnode = AFS_FS_I(old_dir);
 	new_dvnode = AFS_FS_I(new_dir);
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index b14cebf..c7d1d06 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -224,6 +224,9 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct bfs_sb_info *info;
 	int error = -ENOENT;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	old_bh = new_bh = NULL;
 	old_inode = old_dentry->d_inode;
 	if (S_ISDIR(old_inode->i_mode))
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c692dad..3a33ae3 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6994,6 +6994,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	u64 root_objectid;
 	int ret;
 
+	if (new_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	if (new_dir->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
 		return -EPERM;
 
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index d2e5490..377b964 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -869,6 +869,9 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct ceph_mds_request *req;
 	int err;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	if (ceph_snap(old_dir) != ceph_snap(new_dir))
 		return -EXDEV;
 	if (ceph_snap(old_dir) != CEPH_NOSNAP ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index b2bff7e..9ac2290 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1571,6 +1571,9 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 	FILE_UNIX_BASIC_INFO *info_buf_target;
 	int xid, rc, tmprc;
 
+	if (target_dentry->d_inode && S_ISDIR(target_dentry->d_inode->i_mode))
+		dentry_unhash(target_dentry);
+
 	cifs_sb = CIFS_SB(source_dir->i_sb);
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 9f72b75..a46126f 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -361,6 +361,9 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
 	int new_length = new_dentry->d_name.len;
 	int error;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
 			     coda_i2f(new_dir), old_length, new_length,
 			     (const char *) old_name, (const char *)new_name);
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index c88612f..227b409 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -573,6 +573,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct dentry *lower_new_dir_dentry;
 	struct dentry *trap = NULL;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
 	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
 	dget(lower_old_dentry);
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c
index 0697175..de252e5 100644
--- a/fs/exofs/namei.c
+++ b/fs/exofs/namei.c
@@ -251,6 +251,9 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct exofs_dir_entry *old_de;
 	int err = -ENOENT;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	old_de = exofs_find_entry(old_dir, old_dentry, &old_page);
 	if (!old_de)
 		goto out;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 7a5ad97..516c31d 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -320,6 +320,9 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
 	struct ext2_dir_entry_2 * old_de;
 	int err = -ENOENT;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 552f94d..f89b1d4 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2298,6 +2298,9 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 	struct ext3_dir_entry_2 * old_de, * new_de;
 	int retval, flush_file = 0;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 957580d..792d06e 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2352,6 +2352,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct ext4_dir_entry_2 *old_de, *new_de;
 	int retval, force_da_alloc = 0;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 4d147f6..be15437 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -459,6 +459,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 	old_inode = old_dentry->d_inode;
 	new_inode = new_dentry->d_inode;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	err = fat_scan(old_dir, old_name, &old_sinfo);
 	if (err) {
 		err = -EIO;
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 740bb78..c61a678 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -933,6 +933,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 	int err, is_dir, update_dotdot, corrupt = 0;
 	struct super_block *sb = old_dir->i_sb;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
 	old_inode = old_dentry->d_inode;
 	new_inode = new_dentry->d_inode;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 0d84ce6..0d0e3fa 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -693,6 +693,10 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
 	struct fuse_rename_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(olddir);
 	struct fuse_req *req = fuse_get_req(fc);
+
+	if (newent->d_inode && S_ISDIR(newent->d_inode->i_mode))
+		dentry_unhash(newent);
+
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 616cfe0..1cb70cd 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -286,6 +286,9 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	/* Unlink destination if it already exists */
 	if (new_dentry->d_inode) {
+		if (S_ISDIR(new_dentry->d_inode->i_mode))
+			dentry_unhash(new_dentry);
+
 		res = hfs_remove(new_dir, new_dentry);
 		if (res)
 			return res;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 23451a9..b288350 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -469,10 +469,12 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	/* Unlink destination if it already exists */
 	if (new_dentry->d_inode) {
-		if (S_ISDIR(new_dentry->d_inode->i_mode))
+		if (S_ISDIR(new_dentry->d_inode->i_mode)) {
+			dentry_unhash(new_dentry);
 			res = hfsplus_rmdir(new_dir, new_dentry);
-		else
+		} else {
 			res = hfsplus_unlink(new_dir, new_dentry);
+		}
 		if (res)
 			return res;
 	}
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 73ea3ba..e6816b9 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -738,6 +738,9 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
 	char *from_name, *to_name;
 	int err;
 
+	if (to->d_inode && S_ISDIR(to->d_inode->i_mode))
+		dentry_unhash(to);
+
 	if ((from_name = dentry_name(from)) == NULL)
 		return -ENOMEM;
 	if ((to_name = dentry_name(to)) == NULL) {
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index e3e03fa..ff0ce21 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -534,6 +534,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct buffer_head *bh;
 	struct fnode *fnode;
 	int err;
+
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	if ((err = hpfs_chk_name(new_name, &new_len))) return err;
 	err = 0;
 	hpfs_adjust_length(old_name, &old_len);
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 727d644..05f7332 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -786,6 +786,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 	uint8_t type;
 	uint32_t now;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	/* The VFS will check for us and prevent trying to rename a
 	 * file over a directory and vice versa, but if it's a directory,
 	 * the VFS can't check whether the victim is empty. The filesystem
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 0569dac..865df16 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1097,6 +1097,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,
 		 new_dentry->d_name.name);
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
diff --git a/fs/libfs.c b/fs/libfs.c
index 1e2ba5a..91a3710 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -325,6 +325,9 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	if (!simple_empty(new_dentry))
 		return -ENOTEMPTY;
 
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 2b32734..f34c9cd 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -624,6 +624,9 @@ static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry,
 	loff_t pos;
 	int err;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	/* 1. locate source dd */
 	err = logfs_get_dd(old_dir, old_dentry, &dd, &pos);
 	if (err)
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 091626f..f60aed8 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -192,6 +192,9 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
 	struct minix_dir_entry * old_de;
 	int err = -ENOENT;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	old_de = minix_find_entry(old_dentry, &old_page);
 	if (!old_de)
 		goto out;
diff --git a/fs/namei.c b/fs/namei.c
index 57f3693..9a29c7b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3050,12 +3050,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname
  *	   HOWEVER, it relies on the assumption that any object with ->lookup()
  *	   has no more than 1 dentry.  If "hybrid" objects will ever appear,
  *	   we'd better make sure that there's no link(2) for them.
- *	d) some filesystems don't support opened-but-unlinked directories,
- *	   either because of layout or because they are not ready to deal with
- *	   all cases correctly. The latter will be fixed (taking this sort of
- *	   stuff into VFS), but the former is not going away. Solution: the same
- *	   trick as in rmdir().
- *	e) conversion from fhandle to dentry may come in the wrong moment - when
+ *	d) conversion from fhandle to dentry may come in the wrong moment - when
  *	   we are removing the target. Solution: we will have to grab ->i_mutex
  *	   in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
  *	   ->i_mutex on parents, which works but leads to some truly excessive
@@ -3086,11 +3081,8 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 		mutex_lock(&target->i_mutex);
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
-	else {
-		if (target)
-			dentry_unhash(new_dentry);
+	else
 		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-	}
 	if (target) {
 		if (!error) {
 			target->i_flags |= S_DEAD;
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 57336b7..e3e646b 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -1141,6 +1141,9 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
 		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	ncp_age_dentry(server, old_dentry);
 	ncp_age_dentry(server, new_dentry);
 
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 48483b5..87daf79 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1959,6 +1959,9 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
 		 new_dentry->d_count);
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	/*
 	 * For non-directories, check whether the target is busy and if so,
 	 * make a copy of the dentry and then do a silly-rename. If the
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 78306e6..1102a5f 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -371,6 +371,9 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct nilfs_transaction_info ti;
 	int err;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1);
 	if (unlikely(err))
 		return err;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index b017ebb..f3582a6 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1066,6 +1066,9 @@ static int ocfs2_rename(struct inode *old_dir,
 	struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
 	struct ocfs2_dir_lookup_result target_insert = { NULL, };
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	/* At some point it might be nice to break this function up a
 	 * bit. */
 
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
index 95ef443..c368360 100644
--- a/fs/omfs/dir.c
+++ b/fs/omfs/dir.c
@@ -382,6 +382,9 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	int err;
 
 	if (new_inode) {
+		if (S_ISDIR(new_inode->i_mode))
+			dentry_unhash(new_dentry);
+
 		/* overwriting existing file/dir */
 		err = omfs_remove(new_dir, new_dentry);
 		if (err)
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 43e94f0..76c8164 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1227,6 +1227,9 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	unsigned long savelink = 1;
 	struct timespec ctime;
 
+	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	/* three balancings: (1) old name removal, (2) new name insertion
 	   and (3) maybe "save" link insertion
 	   stat data updates: (1) old directory,
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index fac64ac..e2cc675 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -224,6 +224,9 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
 	struct sysv_dir_entry * old_de;
 	int err = -ENOENT;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	old_de = sysv_find_entry(old_dentry, &old_page);
 	if (!old_de)
 		goto out;
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6ca9176..d80810b 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -978,6 +978,9 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
 	struct timespec time;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	/*
 	 * Budget request settings: deletion direntry, new direntry, removing
 	 * the old inode, and changing old and new parent directory inodes.
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index b70f026..4d76594 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1083,6 +1083,9 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct kernel_lb_addr tloc;
 	struct udf_inode_info *old_iinfo = UDF_I(old_inode);
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
 	if (ofi) {
 		if (ofibh.sbh != ofibh.ebh)
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 3a769d5..953ebdf 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -284,6 +284,9 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct ufs_dir_entry *old_de;
 	int err = -ENOENT;
 
+	if (new_inode && S_ISDIR(new_inode->i_mode))
+		dentry_unhash(new_dentry);
+
 	old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
 	if (!old_de)
 		goto out;
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 05/19] vfs: update dentry_unhash() comment
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (3 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 04/19] vfs: push dentry_unhash on rename_dir " Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 06/19] libfs: drop unneeded dentry_unhash Sage Weil
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

The helper is now only called by file systems, not the VFS.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/namei.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 9a29c7b..fe9e305 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2629,10 +2629,10 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
 }
 
 /*
- * We try to drop the dentry early: we should have
- * a usage count of 2 if we're the only user of this
- * dentry, and if that is true (possibly after pruning
- * the dcache), then we drop the dentry now.
+ * The dentry_unhash() helper will try to drop the dentry early: we
+ * should have a usage count of 2 if we're the only user of this
+ * dentry, and if that is true (possibly after pruning the dcache),
+ * then we drop the dentry now.
  *
  * A low-level filesystem can, if it choses, legally
  * do a
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 06/19] libfs: drop unneeded dentry_unhash
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (4 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 05/19] vfs: update dentry_unhash() comment Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 07/19] vfs: fix vfs_rename_dir for FS_RENAME_DOES_D_MOVE filesystems Sage Weil
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

There are no libfs issues with dangling references to empty directories.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/libfs.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/libfs.c b/fs/libfs.c
index 91a3710..c88eab5 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -311,8 +311,6 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
 	if (!simple_empty(dentry))
 		return -ENOTEMPTY;
 
-	dentry_unhash(dentry);
-
 	drop_nlink(dentry->d_inode);
 	simple_unlink(dir, dentry);
 	drop_nlink(dir);
@@ -325,9 +323,6 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
 
-	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	if (!simple_empty(new_dentry))
 		return -ENOTEMPTY;
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 07/19] vfs: fix vfs_rename_dir for FS_RENAME_DOES_D_MOVE filesystems
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (5 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 06/19] libfs: drop unneeded dentry_unhash Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 08/19] vfs: clean up vfs_rmdir Sage Weil
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Miklos Szeredi, Miklos Szeredi

From: Miklos Szeredi <mszeredi@suse.cz>

vfs_rename_dir() doesn't properly account for filesystems with
FS_RENAME_DOES_D_MOVE.  If new_dentry has a target inode attached, it
unhashes the new_dentry prior to the rename() iop and rehashes it after,
but doesn't account for the possibility that rename() may have swapped
{old,new}_dentry.  For FS_RENAME_DOES_D_MOVE filesystems, it rehashes
new_dentry (now the old renamed-from name, which d_move() expected to go
away), such that a subsequent lookup will find it.  Currently all
FS_RENAME_DOES_D_MOVE filesystems compensate for this by failing in
d_revalidate.

The bug was introduced by: commit 349457ccf2592c14bdf13b6706170ae2e94931b1
"[PATCH] Allow file systems to manually d_move() inside of ->rename()"

Fix by not rehashing the new dentry.  Rehashing used to be needed by
d_move() but isn't anymore.

Reported-by: Sage Weil <sage@newdream.net>
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
 fs/namei.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index fe9e305..7a8d45c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3089,8 +3089,6 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 			dont_mount(new_dentry);
 		}
 		mutex_unlock(&target->i_mutex);
-		if (d_unhashed(new_dentry))
-			d_rehash(new_dentry);
 	}
 	if (!error)
 		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 08/19] vfs: clean up vfs_rmdir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (6 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 07/19] vfs: fix vfs_rename_dir for FS_RENAME_DOES_D_MOVE filesystems Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 09/19] vfs: clean up vfs_rename_dir Sage Weil
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Simplify the control flow with an out label.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/namei.c |   31 +++++++++++++++++--------------
 1 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 7a8d45c..6b42e19 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2663,23 +2663,26 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 		return -EPERM;
 
 	mutex_lock(&dentry->d_inode->i_mutex);
+
+	error = -EBUSY;
 	if (d_mountpoint(dentry))
-		error = -EBUSY;
-	else {
-		error = security_inode_rmdir(dir, dentry);
-		if (!error) {
-			error = dir->i_op->rmdir(dir, dentry);
-			if (!error) {
-				dentry->d_inode->i_flags |= S_DEAD;
-				dont_mount(dentry);
-			}
-		}
-	}
+		goto out;
+
+	error = security_inode_rmdir(dir, dentry);
+	if (error)
+		goto out;
+
+	error = dir->i_op->rmdir(dir, dentry);
+	if (error)
+		goto out;
+
+	dentry->d_inode->i_flags |= S_DEAD;
+	dont_mount(dentry);
+
+out:
 	mutex_unlock(&dentry->d_inode->i_mutex);
-	if (!error) {
+	if (!error)
 		d_delete(dentry);
-	}
-
 	return error;
 }
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 09/19] vfs: clean up vfs_rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (7 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 08/19] vfs: clean up vfs_rmdir Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 10/19] vfs: clean up vfs_rename_other Sage Weil
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Simplify control flow through vfs_rename_dir.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/namei.c |   26 +++++++++++++++-----------
 1 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 6b42e19..2601216 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3063,7 +3063,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 			  struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error = 0;
-	struct inode *target;
+	struct inode *target = new_dentry->d_inode;
 
 	/*
 	 * If we are going to change the parent - check write permissions,
@@ -3079,20 +3079,24 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 	if (error)
 		return error;
 
-	target = new_dentry->d_inode;
 	if (target)
 		mutex_lock(&target->i_mutex);
-	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
-		error = -EBUSY;
-	else
-		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+
+	error = -EBUSY;
+	if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry))
+		goto out;
+
+	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+	if (error)
+		goto out;
+
 	if (target) {
-		if (!error) {
-			target->i_flags |= S_DEAD;
-			dont_mount(new_dentry);
-		}
-		mutex_unlock(&target->i_mutex);
+		target->i_flags |= S_DEAD;
+		dont_mount(new_dentry);
 	}
+out:
+	if (target)
+		mutex_unlock(&target->i_mutex);
 	if (!error)
 		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
 			d_move(old_dentry,new_dentry);
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 10/19] vfs: clean up vfs_rename_other
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (8 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 09/19] vfs: clean up vfs_rename_dir Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 11/19] ceph: remove unnecessary dentry_unhash calls Sage Weil
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Simplify control flow to match vfs_rename_dir.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/namei.c |   25 ++++++++++++++-----------
 1 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 2601216..90b0846 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3106,7 +3106,7 @@ out:
 static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
 			    struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct inode *target;
+	struct inode *target = new_dentry->d_inode;
 	int error;
 
 	error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
@@ -3114,19 +3114,22 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
 		return error;
 
 	dget(new_dentry);
-	target = new_dentry->d_inode;
 	if (target)
 		mutex_lock(&target->i_mutex);
+
+	error = -EBUSY;
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
-		error = -EBUSY;
-	else
-		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-	if (!error) {
-		if (target)
-			dont_mount(new_dentry);
-		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
-			d_move(old_dentry, new_dentry);
-	}
+		goto out;
+
+	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+	if (error)
+		goto out;
+
+	if (target)
+		dont_mount(new_dentry);
+	if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
+		d_move(old_dentry, new_dentry);
+out:
 	if (target)
 		mutex_unlock(&target->i_mutex);
 	dput(new_dentry);
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 11/19] ceph: remove unnecessary dentry_unhash calls
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (9 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 10/19] vfs: clean up vfs_rename_other Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 12/19] btrfs: remove unnecessary dentry_unhash in rmdir/rename_dir Sage Weil
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil

Ceph does not need these, and they screw up our use of the dcache as a
consistent cache.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ceph/dir.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 377b964..1a867a3 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -827,9 +827,6 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
 	int err = -EROFS;
 	int op;
 
-	if ((dentry->d_inode->i_mode & S_IFMT) == S_IFDIR)
-		dentry_unhash(dentry);
-
 	if (ceph_snap(dir) == CEPH_SNAPDIR) {
 		/* rmdir .snap/foo is RMSNAP */
 		dout("rmsnap dir %p '%.*s' dn %p\n", dir, dentry->d_name.len,
@@ -869,9 +866,6 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct ceph_mds_request *req;
 	int err;
 
-	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	if (ceph_snap(old_dir) != ceph_snap(new_dir))
 		return -EXDEV;
 	if (ceph_snap(old_dir) != CEPH_NOSNAP ||
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 12/19] btrfs: remove unnecessary dentry_unhash in rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (10 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 11/19] ceph: remove unnecessary dentry_unhash calls Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 13/19] ext4: remove unnecessary dentry_unhash on rmdir/rename_dir Sage Weil
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Chris Mason, linux-btrfs

Btrfs has no problems with lingering references to unlinked directory
inodes.

CC: Chris Mason <chris.mason@oracle.com>
CC: linux-btrfs@vger.kernel.org
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/btrfs/inode.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3a33ae3..7cd8ab0 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3062,8 +3062,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 	    inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
 		return -ENOTEMPTY;
 
-	dentry_unhash(dentry);
-
 	trans = __unlink_start_trans(dir, dentry);
 	if (IS_ERR(trans))
 		return PTR_ERR(trans);
@@ -6994,9 +6992,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	u64 root_objectid;
 	int ret;
 
-	if (new_inode && S_ISDIR(new_dentry->d_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	if (new_dir->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
 		return -EPERM;
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 13/19] ext4: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (11 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 12/19] btrfs: remove unnecessary dentry_unhash in rmdir/rename_dir Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06 ` [PATCH 14/19] ext3: " Sage Weil
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro
  Cc: linux-fsdevel, hch, Sage Weil, Theodore Ts'o, Andreas Dilger,
	linux-ext4

ext4 has no problems with lingering references to unlinked directory
inodes.

CC: "Theodore Ts'o" <tytso@mit.edu>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: linux-ext4@vger.kernel.org
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ext4/namei.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 792d06e..67fd0b0 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2123,8 +2123,6 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
 	struct ext4_dir_entry_2 *de;
 	handle_t *handle;
 
-	dentry_unhash(dentry);
-
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
 	dquot_initialize(dir);
@@ -2352,9 +2350,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct ext4_dir_entry_2 *old_de, *new_de;
 	int retval, force_da_alloc = 0;
 
-	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 14/19] ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (12 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 13/19] ext4: remove unnecessary dentry_unhash on rmdir/rename_dir Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:38   ` Jan Kara
  2011-05-25  2:44   ` Yongqiang Yang
  2011-05-24 20:06 ` [PATCH 15/19] ext2: " Sage Weil
                   ` (5 subsequent siblings)
  19 siblings, 2 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro
  Cc: linux-fsdevel, hch, Sage Weil, Jan Kara, Andrew Morton,
	Andreas Dilger, linux-ext4

ext3 has no problems with lingering references to unlinked directory
inodes.

CC: Jan Kara <jack@suse.cz>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: linux-ext4@vger.kernel.org
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ext3/namei.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index f89b1d4..32f3b86 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2074,8 +2074,6 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
 	struct ext3_dir_entry_2 * de;
 	handle_t *handle;
 
-	dentry_unhash(dentry);
-
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
 	dquot_initialize(dir);
@@ -2298,9 +2296,6 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 	struct ext3_dir_entry_2 * old_de, * new_de;
 	int retval, flush_file = 0;
 
-	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 15/19] ext2: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (13 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 14/19] ext3: " Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
       [not found] ` <1306267582-5347-1-git-send-email-sage-BnTBU8nroG7k1uMJSBkQmQ@public.gmane.org>
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Jan Kara, linux-ext4

ext2 has no problems with lingering references to unlinked directory
inodes.

CC: Jan Kara <jack@suse.cz>
CC: linux-ext4@vger.kernel.org
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ext2/namei.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 516c31d..ed5c5d4 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -296,8 +296,6 @@ static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
 	struct inode * inode = dentry->d_inode;
 	int err = -ENOTEMPTY;
 
-	dentry_unhash(dentry);
-
 	if (ext2_empty_dir(inode)) {
 		err = ext2_unlink(dir, dentry);
 		if (!err) {
@@ -320,9 +318,6 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
 	struct ext2_dir_entry_2 * old_de;
 	int err = -ENOENT;
 
-	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	dquot_initialize(old_dir);
 	dquot_initialize(new_dir);
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 16/19] nfs: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
@ 2011-05-24 20:06     ` Sage Weil
  2011-05-24 20:06 ` [PATCH 02/19] vfs: remove dget() from dentry_unhash() Sage Weil
                       ` (18 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA, hch-jcswGhMUV9g, Sage Weil,
	Trond Myklebust, linux-nfs-u79uwXL29TY76Z2rM5mHXA

NFS has no problems with lingering references to unlinked directory
inodes.

CC: Trond Myklebust <Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org>
CC: linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Sage Weil <sage-BnTBU8nroG7k1uMJSBkQmQ@public.gmane.org>
---
 fs/nfs/dir.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 87daf79..7237672 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1748,8 +1748,6 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 	dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
-	dentry_unhash(dentry);
-
 	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
 	/* Ensure the VFS deletes this inode */
 	if (error == 0 && dentry->d_inode != NULL)
@@ -1959,9 +1957,6 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
 		 new_dentry->d_count);
 
-	if (new_inode && S_ISDIR(new_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	/*
 	 * For non-directories, check whether the target is busy and if so,
 	 * make a copy of the dentry and then do a silly-rename. If the
-- 
1.7.0

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 16/19] nfs: remove unnecessary dentry_unhash on rmdir/rename_dir
@ 2011-05-24 20:06     ` Sage Weil
  0 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Trond Myklebust, linux-nfs

NFS has no problems with lingering references to unlinked directory
inodes.

CC: Trond Myklebust <Trond.Myklebust@netapp.com>
CC: linux-nfs@vger.kernel.org
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/nfs/dir.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 87daf79..7237672 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1748,8 +1748,6 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 	dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
-	dentry_unhash(dentry);
-
 	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
 	/* Ensure the VFS deletes this inode */
 	if (error == 0 && dentry->d_inode != NULL)
@@ -1959,9 +1957,6 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
 		 new_dentry->d_count);
 
-	if (new_inode && S_ISDIR(new_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	/*
 	 * For non-directories, check whether the target is busy and if so,
 	 * make a copy of the dentry and then do a silly-rename. If the
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 17/19] exofs: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (15 preceding siblings ...)
       [not found] ` <1306267582-5347-1-git-send-email-sage-BnTBU8nroG7k1uMJSBkQmQ@public.gmane.org>
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-24 20:06   ` [Ocfs2-devel] " Sage Weil
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Benny Halevy, osd-dev

Exofs has no problems with lingering references to unlinked directory
inodes.

CC: Benny Halevy <bhalevy@panasas.com>
CC: osd-dev@open-osd.org
Acked-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/exofs/namei.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c
index de252e5..4d70db1 100644
--- a/fs/exofs/namei.c
+++ b/fs/exofs/namei.c
@@ -227,8 +227,6 @@ static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = dentry->d_inode;
 	int err = -ENOTEMPTY;
 
-	dentry_unhash(dentry);
-
 	if (exofs_empty_dir(inode)) {
 		err = exofs_unlink(dir, dentry);
 		if (!err) {
@@ -251,9 +249,6 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct exofs_dir_entry *old_de;
 	int err = -ENOENT;
 
-	if (new_inode && S_ISDIR(new_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	old_de = exofs_find_entry(old_dir, old_dentry, &old_page);
 	if (!old_de)
 		goto out;
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 18/19] ocfs2: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
@ 2011-05-24 20:06   ` Sage Weil
  2011-05-24 20:06 ` [PATCH 02/19] vfs: remove dget() from dentry_unhash() Sage Weil
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Mark Fasheh, ocfs2-devel

Ocfs2 has no issues with lingering references to unlinked directory inodes.

CC: Mark Fasheh <mfasheh@suse.com>
CC: ocfs2-devel@oss.oracle.com
Acked-by: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ocfs2/namei.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f3582a6..e5d738c 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -810,9 +810,6 @@ static int ocfs2_unlink(struct inode *dir,
 			   (unsigned long long)OCFS2_I(dir)->ip_blkno,
 			   (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-	if (S_ISDIR(inode->i_mode))
-		dentry_unhash(dentry);
-
 	dquot_initialize(dir);
 
 	BUG_ON(dentry->d_parent->d_inode != dir);
@@ -1066,9 +1063,6 @@ static int ocfs2_rename(struct inode *old_dir,
 	struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
 	struct ocfs2_dir_lookup_result target_insert = { NULL, };
 
-	if (new_inode && S_ISDIR(new_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	/* At some point it might be nice to break this function up a
 	 * bit. */
 
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Ocfs2-devel] [PATCH 18/19] ocfs2: remove unnecessary dentry_unhash on rmdir/rename_dir
@ 2011-05-24 20:06   ` Sage Weil
  0 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Mark Fasheh, ocfs2-devel

Ocfs2 has no issues with lingering references to unlinked directory inodes.

CC: Mark Fasheh <mfasheh@suse.com>
CC: ocfs2-devel at oss.oracle.com
Acked-by: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ocfs2/namei.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f3582a6..e5d738c 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -810,9 +810,6 @@ static int ocfs2_unlink(struct inode *dir,
 			   (unsigned long long)OCFS2_I(dir)->ip_blkno,
 			   (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-	if (S_ISDIR(inode->i_mode))
-		dentry_unhash(dentry);
-
 	dquot_initialize(dir);
 
 	BUG_ON(dentry->d_parent->d_inode != dir);
@@ -1066,9 +1063,6 @@ static int ocfs2_rename(struct inode *old_dir,
 	struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
 	struct ocfs2_dir_lookup_result target_insert = { NULL, };
 
-	if (new_inode && S_ISDIR(new_inode->i_mode))
-		dentry_unhash(new_dentry);
-
 	/* At some point it might be nice to break this function up a
 	 * bit. */
 
-- 
1.7.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 19/19] cifs: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (17 preceding siblings ...)
  2011-05-24 20:06   ` [Ocfs2-devel] " Sage Weil
@ 2011-05-24 20:06 ` Sage Weil
  2011-05-27  9:46 ` [PATCH 00/19] Do not dentry_unhash in VFS (v3) Christoph Hellwig
  19 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 20:06 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, hch, Sage Weil, Steve French, linux-cifs

Cifs has no problems with lingering references to unlinked directory
inodes.

CC: Steve French <sfrench@samba.org>
CC: linux-cifs@vger.kernel.org
Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/cifs/inode.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 9ac2290..de02ed5 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1461,8 +1461,6 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
 
 	cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
 
-	dentry_unhash(direntry);
-
 	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
@@ -1571,9 +1569,6 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 	FILE_UNIX_BASIC_INFO *info_buf_target;
 	int xid, rc, tmprc;
 
-	if (target_dentry->d_inode && S_ISDIR(target_dentry->d_inode->i_mode))
-		dentry_unhash(target_dentry);
-
 	cifs_sb = CIFS_SB(source_dir->i_sb);
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
-- 
1.7.0


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH 14/19] ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 ` [PATCH 14/19] ext3: " Sage Weil
@ 2011-05-24 20:38   ` Jan Kara
  2011-05-24 23:57     ` Sage Weil
  2011-05-25  2:44   ` Yongqiang Yang
  1 sibling, 1 reply; 29+ messages in thread
From: Jan Kara @ 2011-05-24 20:38 UTC (permalink / raw)
  To: Sage Weil
  Cc: viro, linux-fsdevel, hch, Jan Kara, Andrew Morton,
	Andreas Dilger, linux-ext4

On Tue 24-05-11 13:06:17, Sage Weil wrote:
> ext3 has no problems with lingering references to unlinked directory
> inodes.
  OK, so if I understand right, dentry_unhash() has been there only so that
filesystem can detect whether (something under) removed directory is in
use? So filesystems which can happily handle unlinked but open directories
don't need it, right? If that's the case, you can add:
  Acked-by: Jan Kara <jack@suse.cz>
to this patch and also the ext2 version.

								Honza
> 
> CC: Jan Kara <jack@suse.cz>
> CC: Andrew Morton <akpm@linux-foundation.org>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: linux-ext4@vger.kernel.org
> Signed-off-by: Sage Weil <sage@newdream.net>
> ---
>  fs/ext3/namei.c |    5 -----
>  1 files changed, 0 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
> index f89b1d4..32f3b86 100644
> --- a/fs/ext3/namei.c
> +++ b/fs/ext3/namei.c
> @@ -2074,8 +2074,6 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
>  	struct ext3_dir_entry_2 * de;
>  	handle_t *handle;
>  
> -	dentry_unhash(dentry);
> -
>  	/* Initialize quotas before so that eventual writes go in
>  	 * separate transaction */
>  	dquot_initialize(dir);
> @@ -2298,9 +2296,6 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
>  	struct ext3_dir_entry_2 * old_de, * new_de;
>  	int retval, flush_file = 0;
>  
> -	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
> -		dentry_unhash(new_dentry);
> -
>  	dquot_initialize(old_dir);
>  	dquot_initialize(new_dir);
>  
> -- 
> 1.7.0
> 
-- 
Jan Kara <jack@suse.cz>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 14/19] ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:38   ` Jan Kara
@ 2011-05-24 23:57     ` Sage Weil
  0 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-24 23:57 UTC (permalink / raw)
  To: Jan Kara
  Cc: viro, linux-fsdevel, hch, Andrew Morton, Andreas Dilger, linux-ext4

On Tue, 24 May 2011, Jan Kara wrote:
> On Tue 24-05-11 13:06:17, Sage Weil wrote:
> > ext3 has no problems with lingering references to unlinked directory
> > inodes.
>   OK, so if I understand right, dentry_unhash() has been there only so that
> filesystem can detect whether (something under) removed directory is in
> use? So filesystems which can happily handle unlinked but open directories
> don't need it, right? If that's the case, you can add:
>   Acked-by: Jan Kara <jack@suse.cz>
> to this patch and also the ext2 version.

Right.  Basically, a simple fs can return EBUSY if the dentry is hashed 
(implying there are still references) and not worry about a racing process 
traversing into the directory while rmdir is running.  A sane fs can 
handle references and doesn't care if a racing process traverses into the 
dir before the ->rmdir method completes.

Thanks!
sage

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 14/19] ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-24 20:06 ` [PATCH 14/19] ext3: " Sage Weil
  2011-05-24 20:38   ` Jan Kara
@ 2011-05-25  2:44   ` Yongqiang Yang
  2011-05-25  3:44     ` Sage Weil
  1 sibling, 1 reply; 29+ messages in thread
From: Yongqiang Yang @ 2011-05-25  2:44 UTC (permalink / raw)
  To: Sage Weil
  Cc: viro, linux-fsdevel, hch, Jan Kara, Andrew Morton,
	Andreas Dilger, linux-ext4

Hi,

Which kernel version is this patch based on?
Code in my working tree which is 2.6.39-rc3 is already same as the
code after the patch applied.

Thx!

Yongqiang.
On Wed, May 25, 2011 at 4:06 AM, Sage Weil <sage@newdream.net> wrote:
> ext3 has no problems with lingering references to unlinked directory
> inodes.
>
> CC: Jan Kara <jack@suse.cz>
> CC: Andrew Morton <akpm@linux-foundation.org>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: linux-ext4@vger.kernel.org
> Signed-off-by: Sage Weil <sage@newdream.net>
> ---
>  fs/ext3/namei.c |    5 -----
>  1 files changed, 0 insertions(+), 5 deletions(-)
>
> diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
> index f89b1d4..32f3b86 100644
> --- a/fs/ext3/namei.c
> +++ b/fs/ext3/namei.c
> @@ -2074,8 +2074,6 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
>        struct ext3_dir_entry_2 * de;
>        handle_t *handle;
>
> -       dentry_unhash(dentry);
> -
>        /* Initialize quotas before so that eventual writes go in
>         * separate transaction */
>        dquot_initialize(dir);
> @@ -2298,9 +2296,6 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
>        struct ext3_dir_entry_2 * old_de, * new_de;
>        int retval, flush_file = 0;
>
> -       if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
> -               dentry_unhash(new_dentry);
> -
>        dquot_initialize(old_dir);
>        dquot_initialize(new_dir);
>
> --
> 1.7.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



-- 
Best Wishes
Yongqiang Yang
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 14/19] ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  2011-05-25  2:44   ` Yongqiang Yang
@ 2011-05-25  3:44     ` Sage Weil
  0 siblings, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-25  3:44 UTC (permalink / raw)
  To: Yongqiang Yang
  Cc: viro, linux-fsdevel, hch, Jan Kara, Andrew Morton,
	Andreas Dilger, linux-ext4

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2300 bytes --]

On Wed, 25 May 2011, Yongqiang Yang wrote:
> Hi,
> 
> Which kernel version is this patch based on?
> Code in my working tree which is 2.6.39-rc3 is already same as the
> code after the patch applied.

An earlier patch in the series pushes the dentry_unhash call in fs/namei.c 
down into each file system (on change in behavior).  This patch then
removes the call because it shouldn't be necessary for extN, or any other 
file system that doesn't have problems with racing processes getting
references to the just-removed directory inode.

sage


> 
> Thx!
> 
> Yongqiang.
> On Wed, May 25, 2011 at 4:06 AM, Sage Weil <sage@newdream.net> wrote:
> > ext3 has no problems with lingering references to unlinked directory
> > inodes.
> >
> > CC: Jan Kara <jack@suse.cz>
> > CC: Andrew Morton <akpm@linux-foundation.org>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: linux-ext4@vger.kernel.org
> > Signed-off-by: Sage Weil <sage@newdream.net>
> > ---
> >  fs/ext3/namei.c |    5 -----
> >  1 files changed, 0 insertions(+), 5 deletions(-)
> >
> > diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
> > index f89b1d4..32f3b86 100644
> > --- a/fs/ext3/namei.c
> > +++ b/fs/ext3/namei.c
> > @@ -2074,8 +2074,6 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
> >        struct ext3_dir_entry_2 * de;
> >        handle_t *handle;
> >
> > -       dentry_unhash(dentry);
> > -
> >        /* Initialize quotas before so that eventual writes go in
> >         * separate transaction */
> >        dquot_initialize(dir);
> > @@ -2298,9 +2296,6 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
> >        struct ext3_dir_entry_2 * old_de, * new_de;
> >        int retval, flush_file = 0;
> >
> > -       if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
> > -               dentry_unhash(new_dentry);
> > -
> >        dquot_initialize(old_dir);
> >        dquot_initialize(new_dir);
> >
> > --
> > 1.7.0
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> 
> 
> 
> -- 
> Best Wishes
> Yongqiang Yang
> 
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 00/19] Do not dentry_unhash in VFS (v3)
  2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
                   ` (18 preceding siblings ...)
  2011-05-24 20:06 ` [PATCH 19/19] cifs: " Sage Weil
@ 2011-05-27  9:46 ` Christoph Hellwig
  2011-05-27 14:15   ` Jan Kara
  2011-05-27 19:11   ` Sage Weil
  19 siblings, 2 replies; 29+ messages in thread
From: Christoph Hellwig @ 2011-05-27  9:46 UTC (permalink / raw)
  To: Sage Weil; +Cc: viro, linux-fsdevel, jeffm, jack, me, tyhicks

Sage,

this series still leaves a lot of dentry_unhash callsites around,
can you submit some more patches to clan up after it?

 - bfs, sysv, jffs2, jfs, logfs, nilfs2, ubifs and ufs are plain old
   unix filesystems and should not have a problem.
 - reiserfs is a bit special but really shouldn't need it,  also it has
   a local copy of vfs_rmdir that needs the call removed as well.
 - udf also seems to have normal unix semantics
 - same for omfs
 - ecryptfs just passed down requests to the lower fs and thus almost
   certainly doesn't need it.
 - hfs and hfsplus don't care
 - hostsfs doesn't really either

Cced some more maintainers.  In the end each callsite of dentry_unhash
really should have a comment why it's needed or at least why we're
unsure about it.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 00/19] Do not dentry_unhash in VFS (v3)
  2011-05-27  9:46 ` [PATCH 00/19] Do not dentry_unhash in VFS (v3) Christoph Hellwig
@ 2011-05-27 14:15   ` Jan Kara
  2011-05-27 19:11   ` Sage Weil
  1 sibling, 0 replies; 29+ messages in thread
From: Jan Kara @ 2011-05-27 14:15 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Sage Weil, viro, linux-fsdevel, jeffm, jack, me, tyhicks

On Fri 27-05-11 05:46:31, Christoph Hellwig wrote:
> this series still leaves a lot of dentry_unhash callsites around,
> can you submit some more patches to clan up after it?
> 
>  - bfs, sysv, jffs2, jfs, logfs, nilfs2, ubifs and ufs are plain old
>    unix filesystems and should not have a problem.
>  - reiserfs is a bit special but really shouldn't need it,  also it has
>    a local copy of vfs_rmdir that needs the call removed as well.
  I've checked reiserfs code and it handles open-but-deleted directories
just fine - it removes directory from parent in rmdir and removes it only
in evict_inode - so dentry_unhash() isn't needed AFAIU.

>  - udf also seems to have normal unix semantics
  Yes, UDF has standard unix semantics.

								Honza

>  - same for omfs
>  - ecryptfs just passed down requests to the lower fs and thus almost
>    certainly doesn't need it.
>  - hfs and hfsplus don't care
>  - hostsfs doesn't really either
> 
> Cced some more maintainers.  In the end each callsite of dentry_unhash
> really should have a comment why it's needed or at least why we're
> unsure about it.
-- 
Jan Kara <jack@suse.cz>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 00/19] Do not dentry_unhash in VFS (v3)
  2011-05-27  9:46 ` [PATCH 00/19] Do not dentry_unhash in VFS (v3) Christoph Hellwig
  2011-05-27 14:15   ` Jan Kara
@ 2011-05-27 19:11   ` Sage Weil
  1 sibling, 0 replies; 29+ messages in thread
From: Sage Weil @ 2011-05-27 19:11 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: viro, linux-fsdevel, jeffm, jack, me, tyhicks

Hi Christoph,

On Fri, 27 May 2011, Christoph Hellwig wrote:
> Sage,
> 
> this series still leaves a lot of dentry_unhash callsites around,
> can you submit some more patches to clan up after it?
> 
>  - bfs, sysv, jffs2, jfs, logfs, nilfs2, ubifs and ufs are plain old
>    unix filesystems and should not have a problem.
>  - reiserfs is a bit special but really shouldn't need it,  also it has
>    a local copy of vfs_rmdir that needs the call removed as well.
>  - udf also seems to have normal unix semantics
>  - same for omfs
>  - ecryptfs just passed down requests to the lower fs and thus almost
>    certainly doesn't need it.
>  - hfs and hfsplus don't care
>  - hostsfs doesn't really either
> 
> Cced some more maintainers.  In the end each callsite of dentry_unhash
> really should have a comment why it's needed or at least why we're
> unsure about it.

I'm going through and looking at all the remaining callers now.  I just 
want to verify one thing with you to make sure my understanding is 100% 
correct: as long as the file system isn't looking at whether the dentry is 
hashed or unhashed after the dentry_unhash() call, that implies that there 
are no issues with lingering directory references, right?  Because a 
racing lookup getting into the directory (which dentry_unhash would 
prevent) isn't any different from a prior reference if the fs isn't 
checking the hashed status.

If that's the case, it looks like ncpfs is the main one that needs it.  
hpfs does something really weird when close to ENOSPC and needs it for 
that, but doesn't appear to for rmdir and dir rename.  autofs4 I'm scared 
to touch.  Everyone else (9p, affs, afs, coda, configfs, fat, fuse, and 
minix) I think I can remove.

Does that mesh with your understanding?

Thanks!
sage

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2011-05-27 19:09 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-24 20:06 [PATCH 00/19] Do not dentry_unhash in VFS (v3) Sage Weil
2011-05-24 20:06 ` [PATCH 01/19] vfs: dentry_unhash immediately prior to rmdir Sage Weil
2011-05-24 20:06 ` [PATCH 02/19] vfs: remove dget() from dentry_unhash() Sage Weil
2011-05-24 20:06 ` [PATCH 03/19] vfs: push dentry_unhash on rmdir into file systems Sage Weil
2011-05-24 20:06 ` [PATCH 04/19] vfs: push dentry_unhash on rename_dir " Sage Weil
2011-05-24 20:06 ` [PATCH 05/19] vfs: update dentry_unhash() comment Sage Weil
2011-05-24 20:06 ` [PATCH 06/19] libfs: drop unneeded dentry_unhash Sage Weil
2011-05-24 20:06 ` [PATCH 07/19] vfs: fix vfs_rename_dir for FS_RENAME_DOES_D_MOVE filesystems Sage Weil
2011-05-24 20:06 ` [PATCH 08/19] vfs: clean up vfs_rmdir Sage Weil
2011-05-24 20:06 ` [PATCH 09/19] vfs: clean up vfs_rename_dir Sage Weil
2011-05-24 20:06 ` [PATCH 10/19] vfs: clean up vfs_rename_other Sage Weil
2011-05-24 20:06 ` [PATCH 11/19] ceph: remove unnecessary dentry_unhash calls Sage Weil
2011-05-24 20:06 ` [PATCH 12/19] btrfs: remove unnecessary dentry_unhash in rmdir/rename_dir Sage Weil
2011-05-24 20:06 ` [PATCH 13/19] ext4: remove unnecessary dentry_unhash on rmdir/rename_dir Sage Weil
2011-05-24 20:06 ` [PATCH 14/19] ext3: " Sage Weil
2011-05-24 20:38   ` Jan Kara
2011-05-24 23:57     ` Sage Weil
2011-05-25  2:44   ` Yongqiang Yang
2011-05-25  3:44     ` Sage Weil
2011-05-24 20:06 ` [PATCH 15/19] ext2: " Sage Weil
     [not found] ` <1306267582-5347-1-git-send-email-sage-BnTBU8nroG7k1uMJSBkQmQ@public.gmane.org>
2011-05-24 20:06   ` [PATCH 16/19] nfs: " Sage Weil
2011-05-24 20:06     ` Sage Weil
2011-05-24 20:06 ` [PATCH 17/19] exofs: " Sage Weil
2011-05-24 20:06 ` [PATCH 18/19] ocfs2: " Sage Weil
2011-05-24 20:06   ` [Ocfs2-devel] " Sage Weil
2011-05-24 20:06 ` [PATCH 19/19] cifs: " Sage Weil
2011-05-27  9:46 ` [PATCH 00/19] Do not dentry_unhash in VFS (v3) Christoph Hellwig
2011-05-27 14:15   ` Jan Kara
2011-05-27 19:11   ` Sage Weil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.