Commit 79bf7c73 authored by Sage Weil's avatar Sage Weil Committed by Al Viro

vfs: push dentry_unhash on rmdir into file systems

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 64252c75
...@@ -814,6 +814,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d) ...@@ -814,6 +814,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
int v9fs_vfs_rmdir(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); return v9fs_remove(i, d, 1);
} }
......
...@@ -320,6 +320,8 @@ affs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -320,6 +320,8 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_ino, dentry->d_inode->i_ino,
(int)dentry->d_name.len, dentry->d_name.name); (int)dentry->d_name.len, dentry->d_name.name);
dentry_unhash(dentry);
return affs_remove_header(dentry); return affs_remove_header(dentry);
} }
......
...@@ -845,6 +845,8 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -845,6 +845,8 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
_enter("{%x:%u},{%s}", _enter("{%x:%u},{%s}",
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
dentry_unhash(dentry);
ret = -ENAMETOOLONG; ret = -ENAMETOOLONG;
if (dentry->d_name.len >= AFSNAMEMAX) if (dentry->d_name.len >= AFSNAMEMAX)
goto error; goto error;
......
...@@ -583,6 +583,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) ...@@ -583,6 +583,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
dentry_unhash(dentry);
if (atomic_dec_and_test(&ino->count)) { if (atomic_dec_and_test(&ino->count)) {
p_ino = autofs4_dentry_ino(dentry->d_parent); p_ino = autofs4_dentry_ino(dentry->d_parent);
if (p_ino && dentry->d_parent != dentry) if (p_ino && dentry->d_parent != dentry)
......
...@@ -3062,6 +3062,8 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -3062,6 +3062,8 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
return -ENOTEMPTY; return -ENOTEMPTY;
dentry_unhash(dentry);
trans = __unlink_start_trans(dir, dentry); trans = __unlink_start_trans(dir, dentry);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
......
...@@ -827,6 +827,9 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry) ...@@ -827,6 +827,9 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
int err = -EROFS; int err = -EROFS;
int op; int op;
if ((dentry->d_inode->i_mode & S_IFMT) == S_IFDIR)
dentry_unhash(dentry);
if (ceph_snap(dir) == CEPH_SNAPDIR) { if (ceph_snap(dir) == CEPH_SNAPDIR) {
/* rmdir .snap/foo is RMSNAP */ /* rmdir .snap/foo is RMSNAP */
dout("rmsnap dir %p '%.*s' dn %p\n", dir, dentry->d_name.len, dout("rmsnap dir %p '%.*s' dn %p\n", dir, dentry->d_name.len,
......
...@@ -1461,6 +1461,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1461,6 +1461,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cFYI(1, "cifs_rmdir, inode = 0x%p", inode); cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
dentry_unhash(direntry);
xid = GetXid(); xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
......
...@@ -336,6 +336,8 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) ...@@ -336,6 +336,8 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
int len = de->d_name.len; int len = de->d_name.len;
int error; int error;
dentry_unhash(de);
error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
if (!error) { if (!error) {
/* VFS may delete the child */ /* VFS may delete the child */
......
...@@ -1355,6 +1355,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -1355,6 +1355,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
struct module *subsys_owner = NULL, *dead_item_owner = NULL; struct module *subsys_owner = NULL, *dead_item_owner = NULL;
int ret; int ret;
dentry_unhash(dentry);
if (dentry->d_parent == configfs_sb->s_root) if (dentry->d_parent == configfs_sb->s_root)
return -EPERM; return -EPERM;
......
...@@ -521,6 +521,8 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -521,6 +521,8 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
struct dentry *lower_dir_dentry; struct dentry *lower_dir_dentry;
int rc; int rc;
dentry_unhash(dentry);
lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_dentry = ecryptfs_dentry_to_lower(dentry);
dget(dentry); dget(dentry);
lower_dir_dentry = lock_parent(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry);
......
...@@ -227,6 +227,8 @@ static int exofs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -227,6 +227,8 @@ static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int err = -ENOTEMPTY; int err = -ENOTEMPTY;
dentry_unhash(dentry);
if (exofs_empty_dir(inode)) { if (exofs_empty_dir(inode)) {
err = exofs_unlink(dir, dentry); err = exofs_unlink(dir, dentry);
if (!err) { if (!err) {
......
...@@ -296,6 +296,8 @@ static int ext2_rmdir (struct inode * dir, struct dentry *dentry) ...@@ -296,6 +296,8 @@ static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
int err = -ENOTEMPTY; int err = -ENOTEMPTY;
dentry_unhash(dentry);
if (ext2_empty_dir(inode)) { if (ext2_empty_dir(inode)) {
err = ext2_unlink(dir, dentry); err = ext2_unlink(dir, dentry);
if (!err) { if (!err) {
......
...@@ -2074,6 +2074,8 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) ...@@ -2074,6 +2074,8 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
struct ext3_dir_entry_2 * de; struct ext3_dir_entry_2 * de;
handle_t *handle; handle_t *handle;
dentry_unhash(dentry);
/* Initialize quotas before so that eventual writes go in /* Initialize quotas before so that eventual writes go in
* separate transaction */ * separate transaction */
dquot_initialize(dir); dquot_initialize(dir);
......
...@@ -2123,6 +2123,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -2123,6 +2123,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
struct ext4_dir_entry_2 *de; struct ext4_dir_entry_2 *de;
handle_t *handle; handle_t *handle;
dentry_unhash(dentry);
/* Initialize quotas before so that eventual writes go in /* Initialize quotas before so that eventual writes go in
* separate transaction */ * separate transaction */
dquot_initialize(dir); dquot_initialize(dir);
......
...@@ -326,6 +326,8 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -326,6 +326,8 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
int err; int err;
dentry_unhash(dentry);
lock_super(sb); lock_super(sb);
/* /*
* Check whether the directory is not in use, then check * Check whether the directory is not in use, then check
......
...@@ -824,6 +824,8 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -824,6 +824,8 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
int err; int err;
dentry_unhash(dentry);
lock_super(sb); lock_super(sb);
err = fat_dir_empty(inode); err = fat_dir_empty(inode);
......
...@@ -667,6 +667,8 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) ...@@ -667,6 +667,8 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
if (IS_ERR(req)) if (IS_ERR(req))
return PTR_ERR(req); return PTR_ERR(req);
dentry_unhash(entry);
req->in.h.opcode = FUSE_RMDIR; req->in.h.opcode = FUSE_RMDIR;
req->in.h.nodeid = get_node_id(dir); req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 1; req->in.numargs = 1;
......
...@@ -253,6 +253,9 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry) ...@@ -253,6 +253,9 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int res; int res;
if (S_ISDIR(inode->i_mode))
dentry_unhash(dentry);
if (S_ISDIR(inode->i_mode) && inode->i_size != 2) if (S_ISDIR(inode->i_mode) && inode->i_size != 2)
return -ENOTEMPTY; return -ENOTEMPTY;
res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
......
...@@ -370,6 +370,8 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -370,6 +370,8 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int res; int res;
dentry_unhash(dentry);
if (inode->i_size != 2) if (inode->i_size != 2)
return -ENOTEMPTY; return -ENOTEMPTY;
......
...@@ -683,6 +683,8 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry) ...@@ -683,6 +683,8 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
char *file; char *file;
int err; int err;
dentry_unhash(dentry);
if ((file = dentry_name(dentry)) == NULL) if ((file = dentry_name(dentry)) == NULL)
return -ENOMEM; return -ENOMEM;
err = do_rmdir(file); err = do_rmdir(file);
......
...@@ -461,6 +461,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -461,6 +461,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
int err; int err;
int r; int r;
dentry_unhash(dentry);
hpfs_adjust_length(name, &len); hpfs_adjust_length(name, &len);
hpfs_lock(dir->i_sb); hpfs_lock(dir->i_sb);
mutex_lock(&hpfs_i(inode)->i_parent_mutex); mutex_lock(&hpfs_i(inode)->i_parent_mutex);
......
...@@ -609,6 +609,8 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) ...@@ -609,6 +609,8 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
int ret; int ret;
uint32_t now = get_seconds(); uint32_t now = get_seconds();
dentry_unhash(dentry);
for (fd = f->dents ; fd; fd = fd->next) { for (fd = f->dents ; fd; fd = fd->next) {
if (fd->ino) if (fd->ino)
return -ENOTEMPTY; return -ENOTEMPTY;
......
...@@ -360,6 +360,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) ...@@ -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); jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
dentry_unhash(dentry);
/* Init inode for quota operations. */ /* Init inode for quota operations. */
dquot_initialize(dip); dquot_initialize(dip);
dquot_initialize(ip); dquot_initialize(ip);
......
...@@ -311,6 +311,8 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -311,6 +311,8 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
if (!simple_empty(dentry)) if (!simple_empty(dentry))
return -ENOTEMPTY; return -ENOTEMPTY;
dentry_unhash(dentry);
drop_nlink(dentry->d_inode); drop_nlink(dentry->d_inode);
simple_unlink(dir, dentry); simple_unlink(dir, dentry);
drop_nlink(dir); drop_nlink(dir);
......
...@@ -273,6 +273,8 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -273,6 +273,8 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
dentry_unhash(dentry);
if (!logfs_empty_dir(inode)) if (!logfs_empty_dir(inode))
return -ENOTEMPTY; return -ENOTEMPTY;
......
...@@ -168,6 +168,8 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry) ...@@ -168,6 +168,8 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
int err = -ENOTEMPTY; int err = -ENOTEMPTY;
dentry_unhash(dentry);
if (minix_empty_dir(inode)) { if (minix_empty_dir(inode)) {
err = minix_unlink(dir, dentry); err = minix_unlink(dir, dentry);
if (!err) { if (!err) {
......
...@@ -2568,7 +2568,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -2568,7 +2568,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
else { else {
error = security_inode_rmdir(dir, dentry); error = security_inode_rmdir(dir, dentry);
if (!error) { if (!error) {
dentry_unhash(dentry);
error = dir->i_op->rmdir(dir, dentry); error = dir->i_op->rmdir(dir, dentry);
if (!error) { if (!error) {
dentry->d_inode->i_flags |= S_DEAD; dentry->d_inode->i_flags |= S_DEAD;
......
...@@ -1033,6 +1033,8 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -1033,6 +1033,8 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
DPRINTK("ncp_rmdir: removing %s/%s\n", DPRINTK("ncp_rmdir: removing %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
dentry_unhash(dentry);
error = -EBUSY; error = -EBUSY;
if (!d_unhashed(dentry)) if (!d_unhashed(dentry))
goto out; goto out;
......
...@@ -1748,6 +1748,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -1748,6 +1748,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
dentry_unhash(dentry);
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
/* Ensure the VFS deletes this inode */ /* Ensure the VFS deletes this inode */
if (error == 0 && dentry->d_inode != NULL) if (error == 0 && dentry->d_inode != NULL)
......
...@@ -334,6 +334,8 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -334,6 +334,8 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int err; int err;
dentry_unhash(dentry);
err = nilfs_transaction_begin(dir->i_sb, &ti, 0); err = nilfs_transaction_begin(dir->i_sb, &ti, 0);
if (err) if (err)
return err; return err;
......
...@@ -810,6 +810,9 @@ static int ocfs2_unlink(struct inode *dir, ...@@ -810,6 +810,9 @@ static int ocfs2_unlink(struct inode *dir,
(unsigned long long)OCFS2_I(dir)->ip_blkno, (unsigned long long)OCFS2_I(dir)->ip_blkno,
(unsigned long long)OCFS2_I(inode)->ip_blkno); (unsigned long long)OCFS2_I(inode)->ip_blkno);
if (S_ISDIR(inode->i_mode))
dentry_unhash(dentry);
dquot_initialize(dir); dquot_initialize(dir);
BUG_ON(dentry->d_parent->d_inode != dir); BUG_ON(dentry->d_parent->d_inode != dir);
......
...@@ -240,8 +240,12 @@ static int omfs_remove(struct inode *dir, struct dentry *dentry) ...@@ -240,8 +240,12 @@ static int omfs_remove(struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int ret; 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); ret = omfs_delete_entry(dentry);
if (ret) if (ret)
......
...@@ -831,6 +831,8 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -831,6 +831,8 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
INITIALIZE_PATH(path); INITIALIZE_PATH(path);
struct reiserfs_dir_entry de; struct reiserfs_dir_entry de;
dentry_unhash(dentry);
/* we will be doing 2 balancings and update 2 stat data, we change quotas /* 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. * 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 * The quota structure is possibly deleted only on last iput => outside
......
...@@ -196,6 +196,8 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry) ...@@ -196,6 +196,8 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int err = -ENOTEMPTY; int err = -ENOTEMPTY;
dentry_unhash(dentry);
if (sysv_empty_dir(inode)) { if (sysv_empty_dir(inode)) {
err = sysv_unlink(dir, dentry); err = sysv_unlink(dir, dentry);
if (!err) { if (!err) {
......
...@@ -656,6 +656,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -656,6 +656,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_inode *dir_ui = ubifs_inode(dir);
struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 };
dentry_unhash(dentry);
/* /*
* Budget request settings: deletion direntry, deletion inode and * Budget request settings: deletion direntry, deletion inode and
* changing the parent inode. If budgeting fails, go ahead anyway * changing the parent inode. If budgeting fails, go ahead anyway
......
...@@ -783,6 +783,8 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -783,6 +783,8 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
struct fileIdentDesc *fi, cfi; struct fileIdentDesc *fi, cfi;
struct kernel_lb_addr tloc; struct kernel_lb_addr tloc;
dentry_unhash(dentry);
retval = -ENOENT; retval = -ENOENT;
fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
if (!fi) if (!fi)
......
...@@ -258,6 +258,8 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry) ...@@ -258,6 +258,8 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
int err= -ENOTEMPTY; int err= -ENOTEMPTY;
dentry_unhash(dentry);
lock_ufs(dir->i_sb); lock_ufs(dir->i_sb);
if (ufs_empty_dir (inode)) { if (ufs_empty_dir (inode)) {
err = ufs_unlink(dir, dentry); err = ufs_unlink(dir, dentry);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment