vfs: push dentry_unhash on rmdir into file systems
authorSage Weil <sage@newdream.net>
Tue, 24 May 2011 20:06:06 +0000 (13:06 -0700)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 26 May 2011 11:26:47 +0000 (07:26 -0400)
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>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
37 files changed:
fs/9p/vfs_inode.c
fs/affs/namei.c
fs/afs/dir.c
fs/autofs4/root.c
fs/btrfs/inode.c
fs/ceph/dir.c
fs/cifs/inode.c
fs/coda/dir.c
fs/configfs/dir.c
fs/ecryptfs/inode.c
fs/exofs/namei.c
fs/ext2/namei.c
fs/ext3/namei.c
fs/ext4/namei.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fuse/dir.c
fs/hfs/dir.c
fs/hfsplus/dir.c
fs/hostfs/hostfs_kern.c
fs/hpfs/namei.c
fs/jffs2/dir.c
fs/jfs/namei.c
fs/libfs.c
fs/logfs/dir.c
fs/minix/namei.c
fs/namei.c
fs/ncpfs/dir.c
fs/nfs/dir.c
fs/nilfs2/namei.c
fs/ocfs2/namei.c
fs/omfs/dir.c
fs/reiserfs/namei.c
fs/sysv/namei.c
fs/ubifs/dir.c
fs/udf/namei.c
fs/ufs/namei.c

index 7f6c6770319538c3094f7b26eb40fc18a398475d..ecd77172bf0391e9ff8d9a817fcdef0f60731a8b 100644 (file)
@@ -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);
 }
 
index e3e9efc1fdd8276b19eaccb02747afeb27172671..d087153d50523f7e79f13d599bffe4090234075c 100644 (file)
@@ -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);
 }
 
index 20c106f2492740f7de1615ee7712207b74a33828..9a7f4142153431c9ca003c2271f233824b816436 100644 (file)
@@ -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;
index f55ae23b137e2a21001948e1c4b6b17795abc1b0..87d95a8cddbc4223c77e9aa642292b784912b807 100644 (file)
@@ -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)
index 7cd8ab0ef04d5b3e95ccd572f96ca858457e8c18..c692dad3de18215cdd151bf10540ecb797cb2752 100644 (file)
@@ -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);
index 1a867a3601aea88ee25c9fadf399d4a2a3472498..d2e549023dedabb785985c25e3af5a2616bdd840 100644 (file)
@@ -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,
index 8852470b4fbb50b55907cbbd2f4d75357a9f0776..cee5896bcf56e414c72b586c1cd71ce9fd3dcdaf 100644 (file)
@@ -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);
index 2b8dae4d121ee5ad7d42ff879ce1a7c496d295f0..9f72b75a1defd68aa70e0fdf4881ac75e2823b38 100644 (file)
@@ -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 */
index 3313dd19f543841d7e4689cfd18da028e4522892..9908c20bb1a557d7d0a2976ea352c5c980c197f2 100644 (file)
@@ -1355,6 +1355,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;
 
index 4d4cc6a90cd57f18b330674f8e5320205cc2a5e6..c88612f0c1eb1304ce494debc5d3b7b7243f0fd6 100644 (file)
@@ -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);
index 4d70db110cfc4d8585bf77f1f02061f66fab4127..0697175d1a38dafc4b84aec0a792db0cc9fa9a2f 100644 (file)
@@ -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) {
index ed5c5d496ee914aacd5e0d3ea6c7dcd98d319794..7a5ad9762de9d262056222a93408e968a980ceb4 100644 (file)
@@ -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) {
index 32f3b869585927400a035259c0fee27e312b39c8..552f94d7cf3ddc7939de699e90ece9ef5679c785 100644 (file)
@@ -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);
index 67fd0b0258589ae64428d26530807b898e79854b..957580daad78f09da3061f9a664865a473fe017c 100644 (file)
@@ -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);
index 711499040eb615ebe66a263f3d99661e9698e0b5..0c25cea64d241845df3751e81543f7e17fd89770 100644 (file)
@@ -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
index adae3fb7451aa52670d07fdf34381defe133e73a..d7b9383bb9c2a4266c13fbfa41a4e719aac84bb5 100644 (file)
@@ -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);
index c6ba49bd95b34136d04bae30b83342933c35ce7a..40d5c2ae4e73c35908c02c92573a3f2bc00426b6 100644 (file)
@@ -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;
index b4d70b13be92548c6ac2cd72ae5e34f3ab53ec21..616cfe02b601d27f574f2622d17b017fa43b5a49 100644 (file)
@@ -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);
index 4df5059c25da67c4b1ddd2a868057951e6e54d60..23451a955aa0a7522e341d4ee33489d27b517007 100644 (file)
@@ -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;
 
index 2638c834ed281db783f6a7cd5ef24e2edb2047e4..73ea3ba3e6581c6e4eba65cf9770a8c59ec84b7c 100644 (file)
@@ -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);
index b1c72a92c14ea7a9aa5d61bf4a904a296bf1ae62..b9fe158fd7ba52fad6650b2cc22d763429e90c5e 100644 (file)
@@ -461,6 +461,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);
        mutex_lock(&hpfs_i(inode)->i_parent_mutex);
index 82faddd1f321b74e8efd4f11fe07449e409d7bbc..727d64439cd14bac3ede6486620082251ef00d49 100644 (file)
@@ -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;
index eaaf2b511e89a64613bd281f82029ee869358484..0569daca86ad6829d913ba360fb463dcc7cfa4cb 100644 (file)
@@ -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);
index c88eab55aec95f4ab26427da882fd88c8b3ef512..1e2ba5a96b10974d26c9e2dc23c46d9ddd59f277 100644 (file)
@@ -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);
index 9ed89d1663f839c86b84e133617a47f4d855ee25..2b32734cd31a3b3a5a3ab9ef5b7abbc7cb221c0f 100644 (file)
@@ -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;
 
index 6e6777f1b4b208eb5b2767ac4b215f781ad7385d..091626f5577de5ea0d82c43c5874fdd2cc494529 100644 (file)
@@ -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) {
index 8d11187a18d7ca3315a09c17ad8f47633df22fc5..596edb5094a4e2d232c8d365f8a46d258cfc9398 100644 (file)
@@ -2568,7 +2568,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;
index f6946bb5cb5530a655dba93d0aedb072ceb627cc..57336b7cb55e12ec5a556391ee1149431526a502 100644 (file)
@@ -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;
index 7237672216c804769b945c9b09b1e57e1b3de202..48483b562361526ffd5fb1f0664e3bd65355dcee 100644 (file)
@@ -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)
index 546849b3e88f1935585067628e158f4233631d17..78306e6462e3ae71558e3c122f58c7e9d28750df 100644 (file)
@@ -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;
index e5d738cd9cc0540d508873818bd0b6035f2c1f20..b017ebbaf3fab87e2709fbe74adb668eff12944f 100644 (file)
@@ -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);
index de4ff29f1e0595c549877d16144064dae9bcbb7a..95ef4433d1a3d1d6ba8efc92be81fed5902c41b6 100644 (file)
@@ -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)
index 118662690cdf7a88c88074a88fab26bff94fd3f3..43e94f0f60baf4dfb74d4c0cceb7e8becbdbc7f4 100644 (file)
@@ -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
index e474fbcf8bde991924da62e321d2be7eae8ac5f6..fac64ac31869a3656311bb81994dbcea15bedced 100644 (file)
@@ -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) {
index 7217d67a80a691a8114e4d7f04d2f98037d03997..6ca9176c8f59f135e2b4c9a6d67abaf399f38060 100644 (file)
@@ -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
index f1dce848ef966ea1853c9f50ce2d9cc997114a18..b70f026302a5f8dc9bf089997d33b22dfb42c9b5 100644 (file)
@@ -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)
index 29309e25417fdf30209f69d301ea55e4daaed401..3a769d56c6891e6e5d2e93a77269336ece7a3cac 100644 (file)
@@ -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);