Commit 32e51f14 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (25 commits)
  cifs: remove unnecessary dentry_unhash on rmdir/rename_dir
  ocfs2: remove unnecessary dentry_unhash on rmdir/rename_dir
  exofs: remove unnecessary dentry_unhash on rmdir/rename_dir
  nfs: remove unnecessary dentry_unhash on rmdir/rename_dir
  ext2: remove unnecessary dentry_unhash on rmdir/rename_dir
  ext3: remove unnecessary dentry_unhash on rmdir/rename_dir
  ext4: remove unnecessary dentry_unhash on rmdir/rename_dir
  btrfs: remove unnecessary dentry_unhash in rmdir/rename_dir
  ceph: remove unnecessary dentry_unhash calls
  vfs: clean up vfs_rename_other
  vfs: clean up vfs_rename_dir
  vfs: clean up vfs_rmdir
  vfs: fix vfs_rename_dir for FS_RENAME_DOES_D_MOVE filesystems
  libfs: drop unneeded dentry_unhash
  vfs: update dentry_unhash() comment
  vfs: push dentry_unhash on rename_dir into file systems
  vfs: push dentry_unhash on rmdir into file systems
  vfs: remove dget() from dentry_unhash()
  vfs: dentry_unhash immediately prior to rmdir
  vfs: Block mmapped writes while the fs is frozen
  ...
parents ca16d140 b6ff24a3
...@@ -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);
} }
...@@ -839,6 +840,9 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -839,6 +840,9 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct p9_fid *newdirfid; struct p9_fid *newdirfid;
struct p9_wstat wstat; 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"); P9_DPRINTK(P9_DEBUG_VFS, "\n");
retval = 0; retval = 0;
old_inode = old_dentry->d_inode; old_inode = old_dentry->d_inode;
......
...@@ -47,7 +47,7 @@ config FS_POSIX_ACL ...@@ -47,7 +47,7 @@ config FS_POSIX_ACL
def_bool n def_bool n
config EXPORTFS config EXPORTFS
bool tristate
config FILE_LOCKING config FILE_LOCKING
bool "Enable POSIX file locking API" if EXPERT bool "Enable POSIX file locking API" if EXPERT
......
...@@ -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);
} }
...@@ -417,6 +419,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -417,6 +419,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
int retval; 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", 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)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); (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
......
...@@ -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;
...@@ -1146,6 +1148,9 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1146,6 +1148,9 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct key *key; struct key *key;
int ret; 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); vnode = AFS_FS_I(old_dentry->d_inode);
orig_dvnode = AFS_FS_I(old_dir); orig_dvnode = AFS_FS_I(old_dir);
new_dvnode = AFS_FS_I(new_dir); new_dvnode = AFS_FS_I(new_dir);
......
...@@ -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)
......
...@@ -224,6 +224,9 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -224,6 +224,9 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct bfs_sb_info *info; struct bfs_sb_info *info;
int error = -ENOENT; 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_bh = new_bh = NULL;
old_inode = old_dentry->d_inode; old_inode = old_dentry->d_inode;
if (S_ISDIR(old_inode->i_mode)) if (S_ISDIR(old_inode->i_mode))
......
...@@ -2331,24 +2331,26 @@ EXPORT_SYMBOL(block_commit_write); ...@@ -2331,24 +2331,26 @@ EXPORT_SYMBOL(block_commit_write);
* page lock we can determine safely if the page is beyond EOF. If it is not * page lock we can determine safely if the page is beyond EOF. If it is not
* beyond EOF, then the page is guaranteed safe against truncation until we * beyond EOF, then the page is guaranteed safe against truncation until we
* unlock the page. * unlock the page.
*
* Direct callers of this function should call vfs_check_frozen() so that page
* fault does not busyloop until the fs is thawed.
*/ */
int int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, get_block_t get_block)
get_block_t get_block)
{ {
struct page *page = vmf->page; struct page *page = vmf->page;
struct inode *inode = vma->vm_file->f_path.dentry->d_inode; struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
unsigned long end; unsigned long end;
loff_t size; loff_t size;
int ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ int ret;
lock_page(page); lock_page(page);
size = i_size_read(inode); size = i_size_read(inode);
if ((page->mapping != inode->i_mapping) || if ((page->mapping != inode->i_mapping) ||
(page_offset(page) > size)) { (page_offset(page) > size)) {
/* page got truncated out from underneath us */ /* We overload EFAULT to mean page got truncated */
unlock_page(page); ret = -EFAULT;
goto out; goto out_unlock;
} }
/* page is wholly or partially inside EOF */ /* page is wholly or partially inside EOF */
...@@ -2361,18 +2363,41 @@ block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, ...@@ -2361,18 +2363,41 @@ block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
if (!ret) if (!ret)
ret = block_commit_write(page, 0, end); ret = block_commit_write(page, 0, end);
if (unlikely(ret)) { if (unlikely(ret < 0))
unlock_page(page); goto out_unlock;
if (ret == -ENOMEM) /*
ret = VM_FAULT_OOM; * Freezing in progress? We check after the page is marked dirty and
else /* -ENOSPC, -EIO, etc */ * with page lock held so if the test here fails, we are sure freezing
ret = VM_FAULT_SIGBUS; * code will wait during syncing until the page fault is done - at that
} else * point page will be dirty and unlocked so freezing code will write it
ret = VM_FAULT_LOCKED; * and writeprotect it again.
*/
out: set_page_dirty(page);
if (inode->i_sb->s_frozen != SB_UNFROZEN) {
ret = -EAGAIN;
goto out_unlock;
}
return 0;
out_unlock:
unlock_page(page);
return ret; return ret;
} }
EXPORT_SYMBOL(__block_page_mkwrite);
int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block)
{
int ret;
struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb;
/*
* This check is racy but catches the common case. The check in
* __block_page_mkwrite() is reliable.
*/
vfs_check_frozen(sb, SB_FREEZE_WRITE);
ret = __block_page_mkwrite(vma, vmf, get_block);
return block_page_mkwrite_return(ret);
}
EXPORT_SYMBOL(block_page_mkwrite); EXPORT_SYMBOL(block_page_mkwrite);
/* /*
......
...@@ -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 */
...@@ -359,6 +361,9 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -359,6 +361,9 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
int new_length = new_dentry->d_name.len; int new_length = new_dentry->d_name.len;
int error; 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), error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
coda_i2f(new_dir), old_length, new_length, coda_i2f(new_dir), old_length, new_length,
(const char *) old_name, (const char *)new_name); (const char *) old_name, (const char *)new_name);
......
...@@ -1359,6 +1359,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -1359,6 +1359,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);
...@@ -571,6 +573,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -571,6 +573,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *lower_new_dir_dentry; struct dentry *lower_new_dir_dentry;
struct dentry *trap = NULL; 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_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
dget(lower_old_dentry); dget(lower_old_dentry);
......
...@@ -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
...@@ -457,6 +459,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -457,6 +459,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
old_inode = old_dentry->d_inode; old_inode = old_dentry->d_inode;
new_inode = new_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); err = fat_scan(old_dir, old_name, &old_sinfo);
if (err) { if (err) {
err = -EIO; err = -EIO;
......
...@@ -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);
...@@ -931,6 +933,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -931,6 +933,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
int err, is_dir, update_dotdot, corrupt = 0; int err, is_dir, update_dotdot, corrupt = 0;
struct super_block *sb = old_dir->i_sb; 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_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
old_inode = old_dentry->d_inode; old_inode = old_dentry->d_inode;
new_inode = new_dentry->d_inode; new_inode = new_dentry->d_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;
...@@ -691,6 +693,10 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, ...@@ -691,6 +693,10 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
struct fuse_rename_in inarg; struct fuse_rename_in inarg;
struct fuse_conn *fc = get_fuse_conn(olddir); struct fuse_conn *fc = get_fuse_conn(olddir);
struct fuse_req *req = fuse_get_req(fc); 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)) if (IS_ERR(req))
return PTR_ERR(req); return PTR_ERR(req);
......
...@@ -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);
...@@ -283,6 +286,9 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -283,6 +286,9 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* Unlink destination if it already exists */ /* Unlink destination if it already exists */
if (new_dentry->d_inode) { 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); res = hfs_remove(new_dir, new_dentry);
if (res) if (res)
return res; return res;
......
...@@ -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;
...@@ -467,10 +469,12 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -467,10 +469,12 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
/* Unlink destination if it already exists */ /* Unlink destination if it already exists */
if (new_dentry->d_inode) { 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); res = hfsplus_rmdir(new_dir, new_dentry);
else } else {
res = hfsplus_unlink(new_dir, new_dentry); res = hfsplus_unlink(new_dir, new_dentry);
}
if (res) if (res)
return res; return res;
} }
......
...@@ -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);
...@@ -736,6 +738,9 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, ...@@ -736,6 +738,9 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
char *from_name, *to_name; char *from_name, *to_name;
int err; int err;
if (to->d_inode && S_ISDIR(to->d_inode->i_mode))
dentry_unhash(to);
if ((from_name = dentry_name(from)) == NULL) if ((from_name = dentry_name(from)) == NULL)
return -ENOMEM; return -ENOMEM;
if ((to_name = dentry_name(to)) == NULL) { if ((to_name = dentry_name(to)) == NULL) {
......
...@@ -395,7 +395,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -395,7 +395,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
dentry_unhash(dentry); dentry_unhash(dentry);
if (!d_unhashed(dentry)) { if (!d_unhashed(dentry)) {
dput(dentry);
hpfs_unlock(dir->i_sb); hpfs_unlock(dir->i_sb);
return -ENOSPC; return -ENOSPC;
} }
...@@ -403,7 +402,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -403,7 +402,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
!S_ISREG(inode->i_mode) || !S_ISREG(inode->i_mode) ||
get_write_access(inode)) { get_write_access(inode)) {
d_rehash(dentry); d_rehash(dentry);
dput(dentry);
} else { } else {
struct iattr newattrs; struct iattr newattrs;
/*printk("HPFS: truncating file before delete.\n");*/ /*printk("HPFS: truncating file before delete.\n");*/
...@@ -411,7 +409,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -411,7 +409,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
err = notify_change(dentry, &newattrs); err = notify_change(dentry, &newattrs);
put_write_access(inode); put_write_access(inode);
dput(dentry);
if (!err) if (!err)
goto again; goto again;
} }
...@@ -442,6 +439,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -442,6 +439,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);
err = -ENOENT; err = -ENOENT;
...@@ -535,6 +534,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -535,6 +534,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct buffer_head *bh; struct buffer_head *bh;
struct fnode *fnode; struct fnode *fnode;
int err; 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; if ((err = hpfs_chk_name(new_name, &new_len))) return err;
err = 0; err = 0;
hpfs_adjust_length(old_name, &old_len); hpfs_adjust_length(old_name, &old_len);
......
...@@ -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;
...@@ -784,6 +786,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ...@@ -784,6 +786,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
uint8_t type; uint8_t type;
uint32_t now; 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 /* 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, * 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 * the VFS can't check whether the victim is empty. The filesystem
......
...@@ -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);
...@@ -1095,6 +1097,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1095,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, jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,
new_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(old_dir);
dquot_initialize(new_dir); dquot_initialize(new_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;
...@@ -622,6 +624,9 @@ static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry, ...@@ -622,6 +624,9 @@ static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry,
loff_t pos; loff_t pos;
int err; int err;
if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
dentry_unhash(new_dentry);
/* 1. locate source dd */ /* 1. locate source dd */
err = logfs_get_dd(old_dir, old_dentry, &dd, &pos); err = logfs_get_dd(old_dir, old_dentry, &dd, &pos);
if (err) if (err)
......
...@@ -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) {
...@@ -190,6 +192,9 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -190,6 +192,9 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
struct minix_dir_entry * old_de; struct minix_dir_entry * old_de;
int err = -ENOENT; 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); old_de = minix_find_entry(old_dentry, &old_page);
if (!old_de) if (!old_de)
goto out; goto out;
......
This diff is collapsed.
...@@ -1695,7 +1695,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) ...@@ -1695,7 +1695,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path)
static int flags_to_propagation_type(int flags) static int flags_to_propagation_type(int flags)
{ {
int type = flags & ~MS_REC; int type = flags & ~(MS_REC | MS_SILENT);
/* Fail if any non-propagation flags are set */ /* Fail if any non-propagation flags are set */
if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
......
...@@ -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;
...@@ -1139,6 +1141,9 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1139,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, old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
new_dentry->d_parent->d_name.name, new_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, old_dentry);
ncp_age_dentry(server, new_dentry); ncp_age_dentry(server, new_dentry);
......
...@@ -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;
...@@ -369,6 +371,9 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -369,6 +371,9 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int err; 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); err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1);
if (unlikely(err)) if (unlikely(err))
return err; return err;
......
...@@ -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)
...@@ -378,6 +382,9 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -378,6 +382,9 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
int err; int err;
if (new_inode) { if (new_inode) {
if (S_ISDIR(new_inode->i_mode))
dentry_unhash(new_dentry);
/* overwriting existing file/dir */ /* overwriting existing file/dir */
err = omfs_remove(new_dir, new_dentry); err = omfs_remove(new_dir, new_dentry);
if (err) if (err)
......
...@@ -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
...@@ -1225,6 +1227,9 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1225,6 +1227,9 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
unsigned long savelink = 1; unsigned long savelink = 1;
struct timespec ctime; 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 /* three balancings: (1) old name removal, (2) new name insertion
and (3) maybe "save" link insertion and (3) maybe "save" link insertion
stat data updates: (1) old directory, stat data updates: (1) old directory,
......
...@@ -105,7 +105,6 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -105,7 +105,6 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
if (!error) if (!error)
d_delete(dentry); d_delete(dentry);
dput(dentry);
return error; return error;
} }
......
...@@ -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) {
...@@ -222,6 +224,9 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, ...@@ -222,6 +224,9 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
struct sysv_dir_entry * old_de; struct sysv_dir_entry * old_de;
int err = -ENOENT; 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); old_de = sysv_find_entry(old_dentry, &old_page);
if (!old_de) if (!old_de)
goto out; goto out;
......
...@@ -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
...@@ -976,6 +978,9 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -976,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) }; .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
struct timespec time; struct timespec time;
if (new_inode && S_ISDIR(new_inode->i_mode))
dentry_unhash(new_dentry);
/* /*
* Budget request settings: deletion direntry, new direntry, removing * Budget request settings: deletion direntry, new direntry, removing
* the old inode, and changing old and new parent directory inodes. * the old inode, and changing old and new parent directory inodes.
......
...@@ -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)
...@@ -1081,6 +1083,9 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1081,6 +1083,9 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
struct kernel_lb_addr tloc; struct kernel_lb_addr tloc;
struct udf_inode_info *old_iinfo = UDF_I(old_inode); 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); ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
if (ofi) { if (ofi) {
if (ofibh.sbh != ofibh.ebh) if (ofibh.sbh != ofibh.ebh)
......
...@@ -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);
...@@ -282,6 +284,9 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -282,6 +284,9 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct ufs_dir_entry *old_de; struct ufs_dir_entry *old_de;
int err = -ENOENT; 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); old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
if (!old_de) if (!old_de)
goto out; goto out;
......
...@@ -217,8 +217,24 @@ int cont_write_begin(struct file *, struct address_space *, loff_t, ...@@ -217,8 +217,24 @@ int cont_write_begin(struct file *, struct address_space *, loff_t,
get_block_t *, loff_t *); get_block_t *, loff_t *);
int generic_cont_expand_simple(struct inode *inode, loff_t size); int generic_cont_expand_simple(struct inode *inode, loff_t size);
int block_commit_write(struct page *page, unsigned from, unsigned to); int block_commit_write(struct page *page, unsigned from, unsigned to);
int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block);
int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block); get_block_t get_block);
/* Convert errno to return value from ->page_mkwrite() call */
static inline int block_page_mkwrite_return(int err)
{
if (err == 0)
return VM_FAULT_LOCKED;
if (err == -EFAULT)
return VM_FAULT_NOPAGE;
if (err == -ENOMEM)
return VM_FAULT_OOM;
if (err == -EAGAIN)
return VM_FAULT_RETRY;
/* -ENOSPC, -EDQUOT, -EIO ... */
return VM_FAULT_SIGBUS;
}
sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
int block_truncate_page(struct address_space *, loff_t, get_block_t *); int block_truncate_page(struct address_space *, loff_t, get_block_t *);
int nobh_write_begin(struct address_space *, loff_t, unsigned, unsigned, int nobh_write_begin(struct address_space *, loff_t, unsigned, unsigned,
......
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