diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-28 16:03:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-28 16:03:41 -0400 |
commit | 36947a76826111e661a26cb0f668a5be6cc3ddb4 (patch) | |
tree | ed5d92c9d71f9ca68e6a3583a10ebf911c9c44dd | |
parent | a947e23a8ec04bccbfe98c5a2d64cd1f88b612d5 (diff) | |
parent | 69b4573296469fd3f70cf7044693074980517067 (diff) |
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: (36 commits)
Cache xattr security drop check for write v2
fs: block_page_mkwrite should wait for writeback to finish
mm: Wait for writeback when grabbing pages to begin a write
configfs: remove unnecessary dentry_unhash on rmdir, dir rename
fat: remove unnecessary dentry_unhash on rmdir, dir rename
hpfs: remove unnecessary dentry_unhash on rmdir, dir rename
minix: remove unnecessary dentry_unhash on rmdir, dir rename
fuse: remove unnecessary dentry_unhash on rmdir, dir rename
coda: remove unnecessary dentry_unhash on rmdir, dir rename
afs: remove unnecessary dentry_unhash on rmdir, dir rename
affs: remove unnecessary dentry_unhash on rmdir, dir rename
9p: remove unnecessary dentry_unhash on rmdir, dir rename
ncpfs: fix rename over directory with dangling references
ncpfs: document dentry_unhash usage
ecryptfs: remove unnecessary dentry_unhash on rmdir, dir rename
hostfs: remove unnecessary dentry_unhash on rmdir, dir rename
hfsplus: remove unnecessary dentry_unhash on rmdir, dir rename
hfs: remove unnecessary dentry_unhash on rmdir, dir rename
omfs: remove unnecessary dentry_unhash on rmdir, dir rneame
udf: remove unnecessary dentry_unhash from rmdir, dir rename
...
53 files changed, 127 insertions, 235 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 61b31acb9176..57d827d6071d 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -104,7 +104,7 @@ of the locking scheme for directory operations. | |||
104 | prototypes: | 104 | prototypes: |
105 | struct inode *(*alloc_inode)(struct super_block *sb); | 105 | struct inode *(*alloc_inode)(struct super_block *sb); |
106 | void (*destroy_inode)(struct inode *); | 106 | void (*destroy_inode)(struct inode *); |
107 | void (*dirty_inode) (struct inode *); | 107 | void (*dirty_inode) (struct inode *, int flags); |
108 | int (*write_inode) (struct inode *, struct writeback_control *wbc); | 108 | int (*write_inode) (struct inode *, struct writeback_control *wbc); |
109 | int (*drop_inode) (struct inode *); | 109 | int (*drop_inode) (struct inode *); |
110 | void (*evict_inode) (struct inode *); | 110 | void (*evict_inode) (struct inode *); |
@@ -126,7 +126,7 @@ locking rules: | |||
126 | s_umount | 126 | s_umount |
127 | alloc_inode: | 127 | alloc_inode: |
128 | destroy_inode: | 128 | destroy_inode: |
129 | dirty_inode: (must not sleep) | 129 | dirty_inode: |
130 | write_inode: | 130 | write_inode: |
131 | drop_inode: !!!inode->i_lock!!! | 131 | drop_inode: !!!inode->i_lock!!! |
132 | evict_inode: | 132 | evict_inode: |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 21a7dc467bba..88b9f5519af9 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -211,7 +211,7 @@ struct super_operations { | |||
211 | struct inode *(*alloc_inode)(struct super_block *sb); | 211 | struct inode *(*alloc_inode)(struct super_block *sb); |
212 | void (*destroy_inode)(struct inode *); | 212 | void (*destroy_inode)(struct inode *); |
213 | 213 | ||
214 | void (*dirty_inode) (struct inode *); | 214 | void (*dirty_inode) (struct inode *, int flags); |
215 | int (*write_inode) (struct inode *, int); | 215 | int (*write_inode) (struct inode *, int); |
216 | void (*drop_inode) (struct inode *); | 216 | void (*drop_inode) (struct inode *); |
217 | void (*delete_inode) (struct inode *); | 217 | void (*delete_inode) (struct inode *); |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 8d7f3e69ae29..7f6c67703195 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -814,7 +814,6 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d) | |||
814 | 814 | ||
815 | int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) | 815 | int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) |
816 | { | 816 | { |
817 | dentry_unhash(d); | ||
818 | return v9fs_remove(i, d, 1); | 817 | return v9fs_remove(i, d, 1); |
819 | } | 818 | } |
820 | 819 | ||
@@ -840,9 +839,6 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
840 | struct p9_fid *newdirfid; | 839 | struct p9_fid *newdirfid; |
841 | struct p9_wstat wstat; | 840 | struct p9_wstat wstat; |
842 | 841 | ||
843 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
844 | dentry_unhash(new_dentry); | ||
845 | |||
846 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); | 842 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); |
847 | retval = 0; | 843 | retval = 0; |
848 | old_inode = old_dentry->d_inode; | 844 | old_inode = old_dentry->d_inode; |
diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 03330e2e390c..e3e9efc1fdd8 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c | |||
@@ -320,8 +320,6 @@ affs_rmdir(struct inode *dir, struct dentry *dentry) | |||
320 | dentry->d_inode->i_ino, | 320 | dentry->d_inode->i_ino, |
321 | (int)dentry->d_name.len, dentry->d_name.name); | 321 | (int)dentry->d_name.len, dentry->d_name.name); |
322 | 322 | ||
323 | dentry_unhash(dentry); | ||
324 | |||
325 | return affs_remove_header(dentry); | 323 | return affs_remove_header(dentry); |
326 | } | 324 | } |
327 | 325 | ||
@@ -419,9 +417,6 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
419 | struct buffer_head *bh = NULL; | 417 | struct buffer_head *bh = NULL; |
420 | int retval; | 418 | int retval; |
421 | 419 | ||
422 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
423 | dentry_unhash(new_dentry); | ||
424 | |||
425 | pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", | 420 | pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", |
426 | (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, | 421 | (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, |
427 | (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); | 422 | (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 2c4e05160042..20c106f24927 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -845,8 +845,6 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) | |||
845 | _enter("{%x:%u},{%s}", | 845 | _enter("{%x:%u},{%s}", |
846 | dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); | 846 | dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); |
847 | 847 | ||
848 | dentry_unhash(dentry); | ||
849 | |||
850 | ret = -ENAMETOOLONG; | 848 | ret = -ENAMETOOLONG; |
851 | if (dentry->d_name.len >= AFSNAMEMAX) | 849 | if (dentry->d_name.len >= AFSNAMEMAX) |
852 | goto error; | 850 | goto error; |
@@ -1148,9 +1146,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1148 | struct key *key; | 1146 | struct key *key; |
1149 | int ret; | 1147 | int ret; |
1150 | 1148 | ||
1151 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
1152 | dentry_unhash(new_dentry); | ||
1153 | |||
1154 | vnode = AFS_FS_I(old_dentry->d_inode); | 1149 | vnode = AFS_FS_I(old_dentry->d_inode); |
1155 | orig_dvnode = AFS_FS_I(old_dir); | 1150 | orig_dvnode = AFS_FS_I(old_dir); |
1156 | new_dvnode = AFS_FS_I(new_dir); | 1151 | new_dvnode = AFS_FS_I(new_dir); |
@@ -175,6 +175,13 @@ int notify_change(struct dentry * dentry, struct iattr * attr) | |||
175 | return -EPERM; | 175 | return -EPERM; |
176 | } | 176 | } |
177 | 177 | ||
178 | if ((ia_valid & ATTR_MODE)) { | ||
179 | mode_t amode = attr->ia_mode; | ||
180 | /* Flag setting protected by i_mutex */ | ||
181 | if (is_sxid(amode)) | ||
182 | inode->i_flags &= ~S_NOSEC; | ||
183 | } | ||
184 | |||
178 | now = current_fs_time(inode->i_sb); | 185 | now = current_fs_time(inode->i_sb); |
179 | 186 | ||
180 | attr->ia_ctime = now; | 187 | attr->ia_ctime = now; |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index c7d1d06b0483..b14cebfd9047 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -224,9 +224,6 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
224 | struct bfs_sb_info *info; | 224 | struct bfs_sb_info *info; |
225 | int error = -ENOENT; | 225 | int error = -ENOENT; |
226 | 226 | ||
227 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
228 | dentry_unhash(new_dentry); | ||
229 | |||
230 | old_bh = new_bh = NULL; | 227 | old_bh = new_bh = NULL; |
231 | old_inode = old_dentry->d_inode; | 228 | old_inode = old_dentry->d_inode; |
232 | if (S_ISDIR(old_inode->i_mode)) | 229 | if (S_ISDIR(old_inode->i_mode)) |
@@ -638,10 +638,11 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
638 | * @offset: vec entry offset | 638 | * @offset: vec entry offset |
639 | * | 639 | * |
640 | * Attempt to add a page to the bio_vec maplist. This can fail for a | 640 | * Attempt to add a page to the bio_vec maplist. This can fail for a |
641 | * number of reasons, such as the bio being full or target block | 641 | * number of reasons, such as the bio being full or target block device |
642 | * device limitations. The target block device must allow bio's | 642 | * limitations. The target block device must allow bio's up to PAGE_SIZE, |
643 | * smaller than PAGE_SIZE, so it is always possible to add a single | 643 | * so it is always possible to add a single page to an empty bio. |
644 | * page to an empty bio. This should only be used by REQ_PC bios. | 644 | * |
645 | * This should only be used by REQ_PC bios. | ||
645 | */ | 646 | */ |
646 | int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page *page, | 647 | int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page *page, |
647 | unsigned int len, unsigned int offset) | 648 | unsigned int len, unsigned int offset) |
@@ -659,10 +660,9 @@ EXPORT_SYMBOL(bio_add_pc_page); | |||
659 | * @offset: vec entry offset | 660 | * @offset: vec entry offset |
660 | * | 661 | * |
661 | * Attempt to add a page to the bio_vec maplist. This can fail for a | 662 | * Attempt to add a page to the bio_vec maplist. This can fail for a |
662 | * number of reasons, such as the bio being full or target block | 663 | * number of reasons, such as the bio being full or target block device |
663 | * device limitations. The target block device must allow bio's | 664 | * limitations. The target block device must allow bio's up to PAGE_SIZE, |
664 | * smaller than PAGE_SIZE, so it is always possible to add a single | 665 | * so it is always possible to add a single page to an empty bio. |
665 | * page to an empty bio. | ||
666 | */ | 666 | */ |
667 | int bio_add_page(struct bio *bio, struct page *page, unsigned int len, | 667 | int bio_add_page(struct bio *bio, struct page *page, unsigned int len, |
668 | unsigned int offset) | 668 | unsigned int offset) |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 332323e19dd1..6c093fa98f61 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2524,7 +2524,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | |||
2524 | int btrfs_readpage(struct file *file, struct page *page); | 2524 | int btrfs_readpage(struct file *file, struct page *page); |
2525 | void btrfs_evict_inode(struct inode *inode); | 2525 | void btrfs_evict_inode(struct inode *inode); |
2526 | int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); | 2526 | int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); |
2527 | void btrfs_dirty_inode(struct inode *inode); | 2527 | void btrfs_dirty_inode(struct inode *inode, int flags); |
2528 | struct inode *btrfs_alloc_inode(struct super_block *sb); | 2528 | struct inode *btrfs_alloc_inode(struct super_block *sb); |
2529 | void btrfs_destroy_inode(struct inode *inode); | 2529 | void btrfs_destroy_inode(struct inode *inode); |
2530 | int btrfs_drop_inode(struct inode *inode); | 2530 | int btrfs_drop_inode(struct inode *inode); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bb51bb1fa44f..39a9d5750efd 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4294,7 +4294,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
4294 | * FIXME, needs more benchmarking...there are no reasons other than performance | 4294 | * FIXME, needs more benchmarking...there are no reasons other than performance |
4295 | * to keep or drop this code. | 4295 | * to keep or drop this code. |
4296 | */ | 4296 | */ |
4297 | void btrfs_dirty_inode(struct inode *inode) | 4297 | void btrfs_dirty_inode(struct inode *inode, int flags) |
4298 | { | 4298 | { |
4299 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4299 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4300 | struct btrfs_trans_handle *trans; | 4300 | struct btrfs_trans_handle *trans; |
diff --git a/fs/buffer.c b/fs/buffer.c index 698c6b2cc462..49c9aada0374 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2382,6 +2382,7 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, | |||
2382 | ret = -EAGAIN; | 2382 | ret = -EAGAIN; |
2383 | goto out_unlock; | 2383 | goto out_unlock; |
2384 | } | 2384 | } |
2385 | wait_on_page_writeback(page); | ||
2385 | return 0; | 2386 | return 0; |
2386 | out_unlock: | 2387 | out_unlock: |
2387 | unlock_page(page); | 2388 | unlock_page(page); |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index a46126fd5735..2b8dae4d121e 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -336,8 +336,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) | |||
336 | int len = de->d_name.len; | 336 | int len = de->d_name.len; |
337 | int error; | 337 | int error; |
338 | 338 | ||
339 | dentry_unhash(de); | ||
340 | |||
341 | error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); | 339 | error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); |
342 | if (!error) { | 340 | if (!error) { |
343 | /* VFS may delete the child */ | 341 | /* VFS may delete the child */ |
@@ -361,9 +359,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
361 | int new_length = new_dentry->d_name.len; | 359 | int new_length = new_dentry->d_name.len; |
362 | int error; | 360 | int error; |
363 | 361 | ||
364 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
365 | dentry_unhash(new_dentry); | ||
366 | |||
367 | error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), | 362 | error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), |
368 | coda_i2f(new_dir), old_length, new_length, | 363 | coda_i2f(new_dir), old_length, new_length, |
369 | (const char *) old_name, (const char *)new_name); | 364 | (const char *) old_name, (const char *)new_name); |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 9d17d350abc5..9a37a9b6de3a 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -1359,8 +1359,6 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1359 | struct module *subsys_owner = NULL, *dead_item_owner = NULL; | 1359 | struct module *subsys_owner = NULL, *dead_item_owner = NULL; |
1360 | int ret; | 1360 | int ret; |
1361 | 1361 | ||
1362 | dentry_unhash(dentry); | ||
1363 | |||
1364 | if (dentry->d_parent == configfs_sb->s_root) | 1362 | if (dentry->d_parent == configfs_sb->s_root) |
1365 | return -EPERM; | 1363 | return -EPERM; |
1366 | 1364 | ||
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index bc116b9ffcf2..94ab3c06317a 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -521,8 +521,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
521 | struct dentry *lower_dir_dentry; | 521 | struct dentry *lower_dir_dentry; |
522 | int rc; | 522 | int rc; |
523 | 523 | ||
524 | dentry_unhash(dentry); | ||
525 | |||
526 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 524 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
527 | dget(dentry); | 525 | dget(dentry); |
528 | lower_dir_dentry = lock_parent(lower_dentry); | 526 | lower_dir_dentry = lock_parent(lower_dentry); |
@@ -575,9 +573,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
575 | struct dentry *lower_new_dir_dentry; | 573 | struct dentry *lower_new_dir_dentry; |
576 | struct dentry *trap = NULL; | 574 | struct dentry *trap = NULL; |
577 | 575 | ||
578 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
579 | dentry_unhash(new_dentry); | ||
580 | |||
581 | lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); | 576 | lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); |
582 | lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); | 577 | lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); |
583 | dget(lower_old_dentry); | 578 | dget(lower_old_dentry); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 68b2e43d7c35..3451d23c3bae 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -3392,7 +3392,7 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode) | |||
3392 | * so would cause a commit on atime updates, which we don't bother doing. | 3392 | * so would cause a commit on atime updates, which we don't bother doing. |
3393 | * We handle synchronous inodes at the highest possible level. | 3393 | * We handle synchronous inodes at the highest possible level. |
3394 | */ | 3394 | */ |
3395 | void ext3_dirty_inode(struct inode *inode) | 3395 | void ext3_dirty_inode(struct inode *inode, int flags) |
3396 | { | 3396 | { |
3397 | handle_t *current_handle = ext3_journal_current_handle(); | 3397 | handle_t *current_handle = ext3_journal_current_handle(); |
3398 | handle_t *handle; | 3398 | handle_t *handle; |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index a74b89c09f90..1921392cd708 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1813,7 +1813,7 @@ extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1813 | extern void ext4_evict_inode(struct inode *); | 1813 | extern void ext4_evict_inode(struct inode *); |
1814 | extern void ext4_clear_inode(struct inode *); | 1814 | extern void ext4_clear_inode(struct inode *); |
1815 | extern int ext4_sync_inode(handle_t *, struct inode *); | 1815 | extern int ext4_sync_inode(handle_t *, struct inode *); |
1816 | extern void ext4_dirty_inode(struct inode *); | 1816 | extern void ext4_dirty_inode(struct inode *, int); |
1817 | extern int ext4_change_inode_journal_flag(struct inode *, int); | 1817 | extern int ext4_change_inode_journal_flag(struct inode *, int); |
1818 | extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); | 1818 | extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); |
1819 | extern int ext4_can_truncate(struct inode *inode); | 1819 | extern int ext4_can_truncate(struct inode *inode); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 50d0e9c64584..a5763e3505ba 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -5733,7 +5733,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | |||
5733 | * so would cause a commit on atime updates, which we don't bother doing. | 5733 | * so would cause a commit on atime updates, which we don't bother doing. |
5734 | * We handle synchronous inodes at the highest possible level. | 5734 | * We handle synchronous inodes at the highest possible level. |
5735 | */ | 5735 | */ |
5736 | void ext4_dirty_inode(struct inode *inode) | 5736 | void ext4_dirty_inode(struct inode *inode, int flags) |
5737 | { | 5737 | { |
5738 | handle_t *handle; | 5738 | handle_t *handle; |
5739 | 5739 | ||
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index be15437c272e..3b222dafd15b 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c | |||
@@ -326,8 +326,6 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) | |||
326 | struct fat_slot_info sinfo; | 326 | struct fat_slot_info sinfo; |
327 | int err; | 327 | int err; |
328 | 328 | ||
329 | dentry_unhash(dentry); | ||
330 | |||
331 | lock_super(sb); | 329 | lock_super(sb); |
332 | /* | 330 | /* |
333 | * Check whether the directory is not in use, then check | 331 | * Check whether the directory is not in use, then check |
@@ -459,9 +457,6 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, | |||
459 | old_inode = old_dentry->d_inode; | 457 | old_inode = old_dentry->d_inode; |
460 | new_inode = new_dentry->d_inode; | 458 | new_inode = new_dentry->d_inode; |
461 | 459 | ||
462 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
463 | dentry_unhash(new_dentry); | ||
464 | |||
465 | err = fat_scan(old_dir, old_name, &old_sinfo); | 460 | err = fat_scan(old_dir, old_name, &old_sinfo); |
466 | if (err) { | 461 | if (err) { |
467 | err = -EIO; | 462 | err = -EIO; |
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index c61a6789f36c..20b4ea53fdc4 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c | |||
@@ -824,8 +824,6 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) | |||
824 | struct fat_slot_info sinfo; | 824 | struct fat_slot_info sinfo; |
825 | int err; | 825 | int err; |
826 | 826 | ||
827 | dentry_unhash(dentry); | ||
828 | |||
829 | lock_super(sb); | 827 | lock_super(sb); |
830 | 828 | ||
831 | err = fat_dir_empty(inode); | 829 | err = fat_dir_empty(inode); |
@@ -933,9 +931,6 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
933 | int err, is_dir, update_dotdot, corrupt = 0; | 931 | int err, is_dir, update_dotdot, corrupt = 0; |
934 | struct super_block *sb = old_dir->i_sb; | 932 | struct super_block *sb = old_dir->i_sb; |
935 | 933 | ||
936 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
937 | dentry_unhash(new_dentry); | ||
938 | |||
939 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; | 934 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; |
940 | old_inode = old_dentry->d_inode; | 935 | old_inode = old_dentry->d_inode; |
941 | new_inode = new_dentry->d_inode; | 936 | new_inode = new_dentry->d_inode; |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 34591ee804b5..0f015a0468de 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -1007,9 +1007,6 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode) | |||
1007 | * In short, make sure you hash any inodes _before_ you start marking | 1007 | * In short, make sure you hash any inodes _before_ you start marking |
1008 | * them dirty. | 1008 | * them dirty. |
1009 | * | 1009 | * |
1010 | * This function *must* be atomic for the I_DIRTY_PAGES case - | ||
1011 | * set_page_dirty() is called under spinlock in several places. | ||
1012 | * | ||
1013 | * Note that for blockdevs, inode->dirtied_when represents the dirtying time of | 1010 | * Note that for blockdevs, inode->dirtied_when represents the dirtying time of |
1014 | * the block-special inode (/dev/hda1) itself. And the ->dirtied_when field of | 1011 | * the block-special inode (/dev/hda1) itself. And the ->dirtied_when field of |
1015 | * the kernel-internal blockdev inode represents the dirtying time of the | 1012 | * the kernel-internal blockdev inode represents the dirtying time of the |
@@ -1028,7 +1025,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
1028 | */ | 1025 | */ |
1029 | if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { | 1026 | if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { |
1030 | if (sb->s_op->dirty_inode) | 1027 | if (sb->s_op->dirty_inode) |
1031 | sb->s_op->dirty_inode(inode); | 1028 | sb->s_op->dirty_inode(inode, flags); |
1032 | } | 1029 | } |
1033 | 1030 | ||
1034 | /* | 1031 | /* |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 0d0e3faddcfa..d50160714595 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -667,8 +667,6 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) | |||
667 | if (IS_ERR(req)) | 667 | if (IS_ERR(req)) |
668 | return PTR_ERR(req); | 668 | return PTR_ERR(req); |
669 | 669 | ||
670 | dentry_unhash(entry); | ||
671 | |||
672 | req->in.h.opcode = FUSE_RMDIR; | 670 | req->in.h.opcode = FUSE_RMDIR; |
673 | req->in.h.nodeid = get_node_id(dir); | 671 | req->in.h.nodeid = get_node_id(dir); |
674 | req->in.numargs = 1; | 672 | req->in.numargs = 1; |
@@ -694,9 +692,6 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
694 | struct fuse_conn *fc = get_fuse_conn(olddir); | 692 | struct fuse_conn *fc = get_fuse_conn(olddir); |
695 | struct fuse_req *req = fuse_get_req(fc); | 693 | struct fuse_req *req = fuse_get_req(fc); |
696 | 694 | ||
697 | if (newent->d_inode && S_ISDIR(newent->d_inode->i_mode)) | ||
698 | dentry_unhash(newent); | ||
699 | |||
700 | if (IS_ERR(req)) | 695 | if (IS_ERR(req)) |
701 | return PTR_ERR(req); | 696 | return PTR_ERR(req); |
702 | 697 | ||
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 1cb70cdba2c1..b4d70b13be92 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
@@ -253,9 +253,6 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry) | |||
253 | struct inode *inode = dentry->d_inode; | 253 | struct inode *inode = dentry->d_inode; |
254 | int res; | 254 | int res; |
255 | 255 | ||
256 | if (S_ISDIR(inode->i_mode)) | ||
257 | dentry_unhash(dentry); | ||
258 | |||
259 | if (S_ISDIR(inode->i_mode) && inode->i_size != 2) | 256 | if (S_ISDIR(inode->i_mode) && inode->i_size != 2) |
260 | return -ENOTEMPTY; | 257 | return -ENOTEMPTY; |
261 | res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); | 258 | res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); |
@@ -286,9 +283,6 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
286 | 283 | ||
287 | /* Unlink destination if it already exists */ | 284 | /* Unlink destination if it already exists */ |
288 | if (new_dentry->d_inode) { | 285 | if (new_dentry->d_inode) { |
289 | if (S_ISDIR(new_dentry->d_inode->i_mode)) | ||
290 | dentry_unhash(new_dentry); | ||
291 | |||
292 | res = hfs_remove(new_dir, new_dentry); | 286 | res = hfs_remove(new_dir, new_dentry); |
293 | if (res) | 287 | if (res) |
294 | return res; | 288 | return res; |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index b28835091dd0..4df5059c25da 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -370,8 +370,6 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) | |||
370 | struct inode *inode = dentry->d_inode; | 370 | struct inode *inode = dentry->d_inode; |
371 | int res; | 371 | int res; |
372 | 372 | ||
373 | dentry_unhash(dentry); | ||
374 | |||
375 | if (inode->i_size != 2) | 373 | if (inode->i_size != 2) |
376 | return -ENOTEMPTY; | 374 | return -ENOTEMPTY; |
377 | 375 | ||
@@ -469,12 +467,10 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
469 | 467 | ||
470 | /* Unlink destination if it already exists */ | 468 | /* Unlink destination if it already exists */ |
471 | if (new_dentry->d_inode) { | 469 | if (new_dentry->d_inode) { |
472 | if (S_ISDIR(new_dentry->d_inode->i_mode)) { | 470 | if (S_ISDIR(new_dentry->d_inode->i_mode)) |
473 | dentry_unhash(new_dentry); | ||
474 | res = hfsplus_rmdir(new_dir, new_dentry); | 471 | res = hfsplus_rmdir(new_dir, new_dentry); |
475 | } else { | 472 | else |
476 | res = hfsplus_unlink(new_dir, new_dentry); | 473 | res = hfsplus_unlink(new_dir, new_dentry); |
477 | } | ||
478 | if (res) | 474 | if (res) |
479 | return res; | 475 | return res; |
480 | } | 476 | } |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index e6816b9e6903..2638c834ed28 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -683,8 +683,6 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry) | |||
683 | char *file; | 683 | char *file; |
684 | int err; | 684 | int err; |
685 | 685 | ||
686 | dentry_unhash(dentry); | ||
687 | |||
688 | if ((file = dentry_name(dentry)) == NULL) | 686 | if ((file = dentry_name(dentry)) == NULL) |
689 | return -ENOMEM; | 687 | return -ENOMEM; |
690 | err = do_rmdir(file); | 688 | err = do_rmdir(file); |
@@ -738,9 +736,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, | |||
738 | char *from_name, *to_name; | 736 | char *from_name, *to_name; |
739 | int err; | 737 | int err; |
740 | 738 | ||
741 | if (to->d_inode && S_ISDIR(to->d_inode->i_mode)) | ||
742 | dentry_unhash(to); | ||
743 | |||
744 | if ((from_name = dentry_name(from)) == NULL) | 739 | if ((from_name = dentry_name(from)) == NULL) |
745 | return -ENOMEM; | 740 | return -ENOMEM; |
746 | if ((to_name = dentry_name(to)) == NULL) { | 741 | if ((to_name = dentry_name(to)) == NULL) { |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index ff0ce21c0867..acf95dab2aac 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
@@ -439,8 +439,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
439 | int err; | 439 | int err; |
440 | int r; | 440 | int r; |
441 | 441 | ||
442 | dentry_unhash(dentry); | ||
443 | |||
444 | hpfs_adjust_length(name, &len); | 442 | hpfs_adjust_length(name, &len); |
445 | hpfs_lock(dir->i_sb); | 443 | hpfs_lock(dir->i_sb); |
446 | err = -ENOENT; | 444 | err = -ENOENT; |
@@ -535,9 +533,6 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
535 | struct fnode *fnode; | 533 | struct fnode *fnode; |
536 | int err; | 534 | int err; |
537 | 535 | ||
538 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
539 | dentry_unhash(new_dentry); | ||
540 | |||
541 | if ((err = hpfs_chk_name(new_name, &new_len))) return err; | 536 | if ((err = hpfs_chk_name(new_name, &new_len))) return err; |
542 | err = 0; | 537 | err = 0; |
543 | hpfs_adjust_length(old_name, &old_len); | 538 | hpfs_adjust_length(old_name, &old_len); |
diff --git a/fs/inode.c b/fs/inode.c index 990d284877a1..0f7e88a7803f 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1,9 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/fs/inode.c | ||
3 | * | ||
4 | * (C) 1997 Linus Torvalds | 2 | * (C) 1997 Linus Torvalds |
3 | * (C) 1999 Andrea Arcangeli <andrea@suse.de> (dynamic inode allocation) | ||
5 | */ | 4 | */ |
6 | |||
7 | #include <linux/fs.h> | 5 | #include <linux/fs.h> |
8 | #include <linux/mm.h> | 6 | #include <linux/mm.h> |
9 | #include <linux/dcache.h> | 7 | #include <linux/dcache.h> |
@@ -27,10 +25,11 @@ | |||
27 | #include <linux/prefetch.h> | 25 | #include <linux/prefetch.h> |
28 | #include <linux/ima.h> | 26 | #include <linux/ima.h> |
29 | #include <linux/cred.h> | 27 | #include <linux/cred.h> |
28 | #include <linux/buffer_head.h> /* for inode_has_buffers */ | ||
30 | #include "internal.h" | 29 | #include "internal.h" |
31 | 30 | ||
32 | /* | 31 | /* |
33 | * inode locking rules. | 32 | * Inode locking rules: |
34 | * | 33 | * |
35 | * inode->i_lock protects: | 34 | * inode->i_lock protects: |
36 | * inode->i_state, inode->i_hash, __iget() | 35 | * inode->i_state, inode->i_hash, __iget() |
@@ -60,54 +59,11 @@ | |||
60 | * inode_hash_lock | 59 | * inode_hash_lock |
61 | */ | 60 | */ |
62 | 61 | ||
63 | /* | ||
64 | * This is needed for the following functions: | ||
65 | * - inode_has_buffers | ||
66 | * - invalidate_bdev | ||
67 | * | ||
68 | * FIXME: remove all knowledge of the buffer layer from this file | ||
69 | */ | ||
70 | #include <linux/buffer_head.h> | ||
71 | |||
72 | /* | ||
73 | * New inode.c implementation. | ||
74 | * | ||
75 | * This implementation has the basic premise of trying | ||
76 | * to be extremely low-overhead and SMP-safe, yet be | ||
77 | * simple enough to be "obviously correct". | ||
78 | * | ||
79 | * Famous last words. | ||
80 | */ | ||
81 | |||
82 | /* inode dynamic allocation 1999, Andrea Arcangeli <andrea@suse.de> */ | ||
83 | |||
84 | /* #define INODE_PARANOIA 1 */ | ||
85 | /* #define INODE_DEBUG 1 */ | ||
86 | |||
87 | /* | ||
88 | * Inode lookup is no longer as critical as it used to be: | ||
89 | * most of the lookups are going to be through the dcache. | ||
90 | */ | ||
91 | #define I_HASHBITS i_hash_shift | ||
92 | #define I_HASHMASK i_hash_mask | ||
93 | |||
94 | static unsigned int i_hash_mask __read_mostly; | 62 | static unsigned int i_hash_mask __read_mostly; |
95 | static unsigned int i_hash_shift __read_mostly; | 63 | static unsigned int i_hash_shift __read_mostly; |
96 | static struct hlist_head *inode_hashtable __read_mostly; | 64 | static struct hlist_head *inode_hashtable __read_mostly; |
97 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock); | 65 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock); |
98 | 66 | ||
99 | /* | ||
100 | * Each inode can be on two separate lists. One is | ||
101 | * the hash list of the inode, used for lookups. The | ||
102 | * other linked list is the "type" list: | ||
103 | * "in_use" - valid inode, i_count > 0, i_nlink > 0 | ||
104 | * "dirty" - as "in_use" but also dirty | ||
105 | * "unused" - valid inode, i_count = 0 | ||
106 | * | ||
107 | * A "dirty" list is maintained for each super block, | ||
108 | * allowing for low-overhead inode sync() operations. | ||
109 | */ | ||
110 | |||
111 | static LIST_HEAD(inode_lru); | 67 | static LIST_HEAD(inode_lru); |
112 | static DEFINE_SPINLOCK(inode_lru_lock); | 68 | static DEFINE_SPINLOCK(inode_lru_lock); |
113 | 69 | ||
@@ -424,8 +380,8 @@ static unsigned long hash(struct super_block *sb, unsigned long hashval) | |||
424 | 380 | ||
425 | tmp = (hashval * (unsigned long)sb) ^ (GOLDEN_RATIO_PRIME + hashval) / | 381 | tmp = (hashval * (unsigned long)sb) ^ (GOLDEN_RATIO_PRIME + hashval) / |
426 | L1_CACHE_BYTES; | 382 | L1_CACHE_BYTES; |
427 | tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> I_HASHBITS); | 383 | tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> i_hash_shift); |
428 | return tmp & I_HASHMASK; | 384 | return tmp & i_hash_mask; |
429 | } | 385 | } |
430 | 386 | ||
431 | /** | 387 | /** |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 9a1e86fc1362..4bca6a2e5c07 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -605,8 +605,6 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) | |||
605 | int ret; | 605 | int ret; |
606 | uint32_t now = get_seconds(); | 606 | uint32_t now = get_seconds(); |
607 | 607 | ||
608 | dentry_unhash(dentry); | ||
609 | |||
610 | for (fd = f->dents ; fd; fd = fd->next) { | 608 | for (fd = f->dents ; fd; fd = fd->next) { |
611 | if (fd->ino) | 609 | if (fd->ino) |
612 | return -ENOTEMPTY; | 610 | return -ENOTEMPTY; |
@@ -782,9 +780,6 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
782 | uint8_t type; | 780 | uint8_t type; |
783 | uint32_t now; | 781 | uint32_t now; |
784 | 782 | ||
785 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
786 | dentry_unhash(new_dentry); | ||
787 | |||
788 | /* The VFS will check for us and prevent trying to rename a | 783 | /* The VFS will check for us and prevent trying to rename a |
789 | * file over a directory and vice versa, but if it's a directory, | 784 | * file over a directory and vice versa, but if it's a directory, |
790 | * the VFS can't check whether the victim is empty. The filesystem | 785 | * the VFS can't check whether the victim is empty. The filesystem |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index e896e67767eb..46ad619b6124 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -357,7 +357,7 @@ error: | |||
357 | return ERR_PTR(ret); | 357 | return ERR_PTR(ret); |
358 | } | 358 | } |
359 | 359 | ||
360 | void jffs2_dirty_inode(struct inode *inode) | 360 | void jffs2_dirty_inode(struct inode *inode, int flags) |
361 | { | 361 | { |
362 | struct iattr iattr; | 362 | struct iattr iattr; |
363 | 363 | ||
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 00bae7cc2e48..65c6c43ca482 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -172,7 +172,7 @@ int jffs2_setattr (struct dentry *, struct iattr *); | |||
172 | int jffs2_do_setattr (struct inode *, struct iattr *); | 172 | int jffs2_do_setattr (struct inode *, struct iattr *); |
173 | struct inode *jffs2_iget(struct super_block *, unsigned long); | 173 | struct inode *jffs2_iget(struct super_block *, unsigned long); |
174 | void jffs2_evict_inode (struct inode *); | 174 | void jffs2_evict_inode (struct inode *); |
175 | void jffs2_dirty_inode(struct inode *inode); | 175 | void jffs2_dirty_inode(struct inode *inode, int flags); |
176 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, | 176 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, |
177 | struct jffs2_raw_inode *ri); | 177 | struct jffs2_raw_inode *ri); |
178 | int jffs2_statfs (struct dentry *, struct kstatfs *); | 178 | int jffs2_statfs (struct dentry *, struct kstatfs *); |
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index eddbb373209e..109655904bbc 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c | |||
@@ -173,7 +173,7 @@ void jfs_evict_inode(struct inode *inode) | |||
173 | dquot_drop(inode); | 173 | dquot_drop(inode); |
174 | } | 174 | } |
175 | 175 | ||
176 | void jfs_dirty_inode(struct inode *inode) | 176 | void jfs_dirty_inode(struct inode *inode, int flags) |
177 | { | 177 | { |
178 | static int noisy = 5; | 178 | static int noisy = 5; |
179 | 179 | ||
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 155e91eff07d..ec2fb8b945fc 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
@@ -28,7 +28,7 @@ extern struct inode *jfs_iget(struct super_block *, unsigned long); | |||
28 | extern int jfs_commit_inode(struct inode *, int); | 28 | extern int jfs_commit_inode(struct inode *, int); |
29 | extern int jfs_write_inode(struct inode *, struct writeback_control *); | 29 | extern int jfs_write_inode(struct inode *, struct writeback_control *); |
30 | extern void jfs_evict_inode(struct inode *); | 30 | extern void jfs_evict_inode(struct inode *); |
31 | extern void jfs_dirty_inode(struct inode *); | 31 | extern void jfs_dirty_inode(struct inode *, int); |
32 | extern void jfs_truncate(struct inode *); | 32 | extern void jfs_truncate(struct inode *); |
33 | extern void jfs_truncate_nolock(struct inode *, loff_t); | 33 | extern void jfs_truncate_nolock(struct inode *, loff_t); |
34 | extern void jfs_free_zero_link(struct inode *); | 34 | extern void jfs_free_zero_link(struct inode *); |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 865df16a6cf3..eaaf2b511e89 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -360,8 +360,6 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) | |||
360 | 360 | ||
361 | jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); | 361 | jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); |
362 | 362 | ||
363 | dentry_unhash(dentry); | ||
364 | |||
365 | /* Init inode for quota operations. */ | 363 | /* Init inode for quota operations. */ |
366 | dquot_initialize(dip); | 364 | dquot_initialize(dip); |
367 | dquot_initialize(ip); | 365 | dquot_initialize(ip); |
@@ -1097,9 +1095,6 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1097 | jfs_info("jfs_rename: %s %s", old_dentry->d_name.name, | 1095 | jfs_info("jfs_rename: %s %s", old_dentry->d_name.name, |
1098 | new_dentry->d_name.name); | 1096 | new_dentry->d_name.name); |
1099 | 1097 | ||
1100 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
1101 | dentry_unhash(new_dentry); | ||
1102 | |||
1103 | dquot_initialize(old_dir); | 1098 | dquot_initialize(old_dir); |
1104 | dquot_initialize(new_dir); | 1099 | dquot_initialize(new_dir); |
1105 | 1100 | ||
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index f34c9cde9e94..9ed89d1663f8 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c | |||
@@ -273,8 +273,6 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
273 | { | 273 | { |
274 | struct inode *inode = dentry->d_inode; | 274 | struct inode *inode = dentry->d_inode; |
275 | 275 | ||
276 | dentry_unhash(dentry); | ||
277 | |||
278 | if (!logfs_empty_dir(inode)) | 276 | if (!logfs_empty_dir(inode)) |
279 | return -ENOTEMPTY; | 277 | return -ENOTEMPTY; |
280 | 278 | ||
@@ -624,9 +622,6 @@ static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry, | |||
624 | loff_t pos; | 622 | loff_t pos; |
625 | int err; | 623 | int err; |
626 | 624 | ||
627 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
628 | dentry_unhash(new_dentry); | ||
629 | |||
630 | /* 1. locate source dd */ | 625 | /* 1. locate source dd */ |
631 | err = logfs_get_dd(old_dir, old_dentry, &dd, &pos); | 626 | err = logfs_get_dd(old_dir, old_dentry, &dd, &pos); |
632 | if (err) | 627 | if (err) |
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index f60aed8db9c4..6e6777f1b4b2 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c | |||
@@ -168,8 +168,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry) | |||
168 | struct inode * inode = dentry->d_inode; | 168 | struct inode * inode = dentry->d_inode; |
169 | int err = -ENOTEMPTY; | 169 | int err = -ENOTEMPTY; |
170 | 170 | ||
171 | dentry_unhash(dentry); | ||
172 | |||
173 | if (minix_empty_dir(inode)) { | 171 | if (minix_empty_dir(inode)) { |
174 | err = minix_unlink(dir, dentry); | 172 | err = minix_unlink(dir, dentry); |
175 | if (!err) { | 173 | if (!err) { |
@@ -192,9 +190,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
192 | struct minix_dir_entry * old_de; | 190 | struct minix_dir_entry * old_de; |
193 | int err = -ENOENT; | 191 | int err = -ENOENT; |
194 | 192 | ||
195 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
196 | dentry_unhash(new_dentry); | ||
197 | |||
198 | old_de = minix_find_entry(old_dentry, &old_page); | 193 | old_de = minix_find_entry(old_dentry, &old_page); |
199 | if (!old_de) | 194 | if (!old_de) |
200 | goto out; | 195 | goto out; |
diff --git a/fs/namei.c b/fs/namei.c index 2358b326b221..1ab641f2e78e 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -919,12 +919,11 @@ static inline bool managed_dentry_might_block(struct dentry *dentry) | |||
919 | } | 919 | } |
920 | 920 | ||
921 | /* | 921 | /* |
922 | * Skip to top of mountpoint pile in rcuwalk mode. We abort the rcu-walk if we | 922 | * Try to skip to top of mountpoint pile in rcuwalk mode. Fail if |
923 | * meet a managed dentry and we're not walking to "..". True is returned to | 923 | * we meet a managed dentry that would need blocking. |
924 | * continue, false to abort. | ||
925 | */ | 924 | */ |
926 | static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | 925 | static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, |
927 | struct inode **inode, bool reverse_transit) | 926 | struct inode **inode) |
928 | { | 927 | { |
929 | for (;;) { | 928 | for (;;) { |
930 | struct vfsmount *mounted; | 929 | struct vfsmount *mounted; |
@@ -933,8 +932,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
933 | * that wants to block transit. | 932 | * that wants to block transit. |
934 | */ | 933 | */ |
935 | *inode = path->dentry->d_inode; | 934 | *inode = path->dentry->d_inode; |
936 | if (!reverse_transit && | 935 | if (unlikely(managed_dentry_might_block(path->dentry))) |
937 | unlikely(managed_dentry_might_block(path->dentry))) | ||
938 | return false; | 936 | return false; |
939 | 937 | ||
940 | if (!d_mountpoint(path->dentry)) | 938 | if (!d_mountpoint(path->dentry)) |
@@ -947,16 +945,24 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
947 | path->dentry = mounted->mnt_root; | 945 | path->dentry = mounted->mnt_root; |
948 | nd->seq = read_seqcount_begin(&path->dentry->d_seq); | 946 | nd->seq = read_seqcount_begin(&path->dentry->d_seq); |
949 | } | 947 | } |
950 | |||
951 | if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT)) | ||
952 | return reverse_transit; | ||
953 | return true; | 948 | return true; |
954 | } | 949 | } |
955 | 950 | ||
956 | static int follow_dotdot_rcu(struct nameidata *nd) | 951 | static void follow_mount_rcu(struct nameidata *nd) |
957 | { | 952 | { |
958 | struct inode *inode = nd->inode; | 953 | while (d_mountpoint(nd->path.dentry)) { |
954 | struct vfsmount *mounted; | ||
955 | mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1); | ||
956 | if (!mounted) | ||
957 | break; | ||
958 | nd->path.mnt = mounted; | ||
959 | nd->path.dentry = mounted->mnt_root; | ||
960 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | ||
961 | } | ||
962 | } | ||
959 | 963 | ||
964 | static int follow_dotdot_rcu(struct nameidata *nd) | ||
965 | { | ||
960 | set_root_rcu(nd); | 966 | set_root_rcu(nd); |
961 | 967 | ||
962 | while (1) { | 968 | while (1) { |
@@ -972,7 +978,6 @@ static int follow_dotdot_rcu(struct nameidata *nd) | |||
972 | seq = read_seqcount_begin(&parent->d_seq); | 978 | seq = read_seqcount_begin(&parent->d_seq); |
973 | if (read_seqcount_retry(&old->d_seq, nd->seq)) | 979 | if (read_seqcount_retry(&old->d_seq, nd->seq)) |
974 | goto failed; | 980 | goto failed; |
975 | inode = parent->d_inode; | ||
976 | nd->path.dentry = parent; | 981 | nd->path.dentry = parent; |
977 | nd->seq = seq; | 982 | nd->seq = seq; |
978 | break; | 983 | break; |
@@ -980,10 +985,9 @@ static int follow_dotdot_rcu(struct nameidata *nd) | |||
980 | if (!follow_up_rcu(&nd->path)) | 985 | if (!follow_up_rcu(&nd->path)) |
981 | break; | 986 | break; |
982 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | 987 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); |
983 | inode = nd->path.dentry->d_inode; | ||
984 | } | 988 | } |
985 | __follow_mount_rcu(nd, &nd->path, &inode, true); | 989 | follow_mount_rcu(nd); |
986 | nd->inode = inode; | 990 | nd->inode = nd->path.dentry->d_inode; |
987 | return 0; | 991 | return 0; |
988 | 992 | ||
989 | failed: | 993 | failed: |
@@ -1157,8 +1161,11 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
1157 | } | 1161 | } |
1158 | path->mnt = mnt; | 1162 | path->mnt = mnt; |
1159 | path->dentry = dentry; | 1163 | path->dentry = dentry; |
1160 | if (likely(__follow_mount_rcu(nd, path, inode, false))) | 1164 | if (unlikely(!__follow_mount_rcu(nd, path, inode))) |
1161 | return 0; | 1165 | goto unlazy; |
1166 | if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT)) | ||
1167 | goto unlazy; | ||
1168 | return 0; | ||
1162 | unlazy: | 1169 | unlazy: |
1163 | if (unlazy_walk(nd, dentry)) | 1170 | if (unlazy_walk(nd, dentry)) |
1164 | return -ECHILD; | 1171 | return -ECHILD; |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index e3e646b06404..9c51f621e901 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -1033,8 +1033,11 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) | |||
1033 | DPRINTK("ncp_rmdir: removing %s/%s\n", | 1033 | DPRINTK("ncp_rmdir: removing %s/%s\n", |
1034 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1034 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1035 | 1035 | ||
1036 | /* | ||
1037 | * fail with EBUSY if there are still references to this | ||
1038 | * directory. | ||
1039 | */ | ||
1036 | dentry_unhash(dentry); | 1040 | dentry_unhash(dentry); |
1037 | |||
1038 | error = -EBUSY; | 1041 | error = -EBUSY; |
1039 | if (!d_unhashed(dentry)) | 1042 | if (!d_unhashed(dentry)) |
1040 | goto out; | 1043 | goto out; |
@@ -1141,8 +1144,16 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1141 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1144 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1142 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name); | 1145 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name); |
1143 | 1146 | ||
1144 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | 1147 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) { |
1148 | /* | ||
1149 | * fail with EBUSY if there are still references to this | ||
1150 | * directory. | ||
1151 | */ | ||
1145 | dentry_unhash(new_dentry); | 1152 | dentry_unhash(new_dentry); |
1153 | error = -EBUSY; | ||
1154 | if (!d_unhashed(new_dentry)) | ||
1155 | goto out; | ||
1156 | } | ||
1146 | 1157 | ||
1147 | ncp_age_dentry(server, old_dentry); | 1158 | ncp_age_dentry(server, old_dentry); |
1148 | ncp_age_dentry(server, new_dentry); | 1159 | ncp_age_dentry(server, new_dentry); |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 587f18432832..b954878ad6ce 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -917,7 +917,7 @@ int nilfs_mark_inode_dirty(struct inode *inode) | |||
917 | * construction. This function can be called both as a single operation | 917 | * construction. This function can be called both as a single operation |
918 | * and as a part of indivisible file operations. | 918 | * and as a part of indivisible file operations. |
919 | */ | 919 | */ |
920 | void nilfs_dirty_inode(struct inode *inode) | 920 | void nilfs_dirty_inode(struct inode *inode, int flags) |
921 | { | 921 | { |
922 | struct nilfs_transaction_info ti; | 922 | struct nilfs_transaction_info ti; |
923 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | 923 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 1102a5fbb744..546849b3e88f 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
@@ -334,8 +334,6 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
334 | struct nilfs_transaction_info ti; | 334 | struct nilfs_transaction_info ti; |
335 | int err; | 335 | int err; |
336 | 336 | ||
337 | dentry_unhash(dentry); | ||
338 | |||
339 | err = nilfs_transaction_begin(dir->i_sb, &ti, 0); | 337 | err = nilfs_transaction_begin(dir->i_sb, &ti, 0); |
340 | if (err) | 338 | if (err) |
341 | return err; | 339 | return err; |
@@ -371,9 +369,6 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
371 | struct nilfs_transaction_info ti; | 369 | struct nilfs_transaction_info ti; |
372 | int err; | 370 | int err; |
373 | 371 | ||
374 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
375 | dentry_unhash(new_dentry); | ||
376 | |||
377 | err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1); | 372 | err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1); |
378 | if (unlikely(err)) | 373 | if (unlikely(err)) |
379 | return err; | 374 | return err; |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index a9c6a531f80c..f02b9ad43a21 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
@@ -269,7 +269,7 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh); | |||
269 | extern int nilfs_inode_dirty(struct inode *); | 269 | extern int nilfs_inode_dirty(struct inode *); |
270 | int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty); | 270 | int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty); |
271 | extern int nilfs_mark_inode_dirty(struct inode *); | 271 | extern int nilfs_mark_inode_dirty(struct inode *); |
272 | extern void nilfs_dirty_inode(struct inode *); | 272 | extern void nilfs_dirty_inode(struct inode *, int flags); |
273 | int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 273 | int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
274 | __u64 start, __u64 len); | 274 | __u64 start, __u64 len); |
275 | 275 | ||
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index c368360c35a1..3b8d3979e03b 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c | |||
@@ -241,11 +241,9 @@ static int omfs_remove(struct inode *dir, struct dentry *dentry) | |||
241 | int ret; | 241 | int ret; |
242 | 242 | ||
243 | 243 | ||
244 | if (S_ISDIR(inode->i_mode)) { | 244 | if (S_ISDIR(inode->i_mode) && |
245 | dentry_unhash(dentry); | 245 | !omfs_dir_is_empty(inode)) |
246 | if (!omfs_dir_is_empty(inode)) | 246 | return -ENOTEMPTY; |
247 | return -ENOTEMPTY; | ||
248 | } | ||
249 | 247 | ||
250 | ret = omfs_delete_entry(dentry); | 248 | ret = omfs_delete_entry(dentry); |
251 | if (ret) | 249 | if (ret) |
@@ -382,9 +380,6 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
382 | int err; | 380 | int err; |
383 | 381 | ||
384 | if (new_inode) { | 382 | if (new_inode) { |
385 | if (S_ISDIR(new_inode->i_mode)) | ||
386 | dentry_unhash(new_dentry); | ||
387 | |||
388 | /* overwriting existing file/dir */ | 383 | /* overwriting existing file/dir */ |
389 | err = omfs_remove(new_dir, new_dentry); | 384 | err = omfs_remove(new_dir, new_dentry); |
390 | if (err) | 385 | if (err) |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 76c8164d5651..118662690cdf 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -831,8 +831,6 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
831 | INITIALIZE_PATH(path); | 831 | INITIALIZE_PATH(path); |
832 | struct reiserfs_dir_entry de; | 832 | struct reiserfs_dir_entry de; |
833 | 833 | ||
834 | dentry_unhash(dentry); | ||
835 | |||
836 | /* we will be doing 2 balancings and update 2 stat data, we change quotas | 834 | /* we will be doing 2 balancings and update 2 stat data, we change quotas |
837 | * of the owner of the directory and of the owner of the parent directory. | 835 | * of the owner of the directory and of the owner of the parent directory. |
838 | * The quota structure is possibly deleted only on last iput => outside | 836 | * The quota structure is possibly deleted only on last iput => outside |
@@ -1227,9 +1225,6 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1227 | unsigned long savelink = 1; | 1225 | unsigned long savelink = 1; |
1228 | struct timespec ctime; | 1226 | struct timespec ctime; |
1229 | 1227 | ||
1230 | if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) | ||
1231 | dentry_unhash(new_dentry); | ||
1232 | |||
1233 | /* three balancings: (1) old name removal, (2) new name insertion | 1228 | /* three balancings: (1) old name removal, (2) new name insertion |
1234 | and (3) maybe "save" link insertion | 1229 | and (3) maybe "save" link insertion |
1235 | stat data updates: (1) old directory, | 1230 | stat data updates: (1) old directory, |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index b216ff6be1c9..aa91089162cb 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -568,7 +568,7 @@ static void destroy_inodecache(void) | |||
568 | } | 568 | } |
569 | 569 | ||
570 | /* we don't mark inodes dirty, we just log them */ | 570 | /* we don't mark inodes dirty, we just log them */ |
571 | static void reiserfs_dirty_inode(struct inode *inode) | 571 | static void reiserfs_dirty_inode(struct inode *inode, int flags) |
572 | { | 572 | { |
573 | struct reiserfs_transaction_handle th; | 573 | struct reiserfs_transaction_handle th; |
574 | 574 | ||
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 50f1abccd1cd..e8a62f41b458 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -98,7 +98,6 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) | |||
98 | 98 | ||
99 | reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, | 99 | reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, |
100 | I_MUTEX_CHILD, dir->i_sb); | 100 | I_MUTEX_CHILD, dir->i_sb); |
101 | dentry_unhash(dentry); | ||
102 | error = dir->i_op->rmdir(dir, dentry); | 101 | error = dir->i_op->rmdir(dir, dentry); |
103 | if (!error) | 102 | if (!error) |
104 | dentry->d_inode->i_flags |= S_DEAD; | 103 | dentry->d_inode->i_flags |= S_DEAD; |
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index e2cc6756f3b1..e474fbcf8bde 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c | |||
@@ -196,8 +196,6 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry) | |||
196 | struct inode *inode = dentry->d_inode; | 196 | struct inode *inode = dentry->d_inode; |
197 | int err = -ENOTEMPTY; | 197 | int err = -ENOTEMPTY; |
198 | 198 | ||
199 | dentry_unhash(dentry); | ||
200 | |||
201 | if (sysv_empty_dir(inode)) { | 199 | if (sysv_empty_dir(inode)) { |
202 | err = sysv_unlink(dir, dentry); | 200 | err = sysv_unlink(dir, dentry); |
203 | if (!err) { | 201 | if (!err) { |
@@ -224,9 +222,6 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, | |||
224 | struct sysv_dir_entry * old_de; | 222 | struct sysv_dir_entry * old_de; |
225 | int err = -ENOENT; | 223 | int err = -ENOENT; |
226 | 224 | ||
227 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
228 | dentry_unhash(new_dentry); | ||
229 | |||
230 | old_de = sysv_find_entry(old_dentry, &old_page); | 225 | old_de = sysv_find_entry(old_dentry, &old_page); |
231 | if (!old_de) | 226 | if (!old_de) |
232 | goto out; | 227 | goto out; |
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index c2b80943560d..ef5abd38f0bf 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -656,8 +656,6 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) | |||
656 | struct ubifs_inode *dir_ui = ubifs_inode(dir); | 656 | struct ubifs_inode *dir_ui = ubifs_inode(dir); |
657 | struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; | 657 | struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; |
658 | 658 | ||
659 | dentry_unhash(dentry); | ||
660 | |||
661 | /* | 659 | /* |
662 | * Budget request settings: deletion direntry, deletion inode and | 660 | * Budget request settings: deletion direntry, deletion inode and |
663 | * changing the parent inode. If budgeting fails, go ahead anyway | 661 | * changing the parent inode. If budgeting fails, go ahead anyway |
@@ -978,9 +976,6 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
978 | .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; | 976 | .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; |
979 | struct timespec time; | 977 | struct timespec time; |
980 | 978 | ||
981 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
982 | dentry_unhash(new_dentry); | ||
983 | |||
984 | /* | 979 | /* |
985 | * Budget request settings: deletion direntry, new direntry, removing | 980 | * Budget request settings: deletion direntry, new direntry, removing |
986 | * the old inode, and changing old and new parent directory inodes. | 981 | * the old inode, and changing old and new parent directory inodes. |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 6db0bdaa9f74..1ab0d22e4c94 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -382,7 +382,7 @@ done: | |||
382 | end_writeback(inode); | 382 | end_writeback(inode); |
383 | } | 383 | } |
384 | 384 | ||
385 | static void ubifs_dirty_inode(struct inode *inode) | 385 | static void ubifs_dirty_inode(struct inode *inode, int flags) |
386 | { | 386 | { |
387 | struct ubifs_inode *ui = ubifs_inode(inode); | 387 | struct ubifs_inode *ui = ubifs_inode(inode); |
388 | 388 | ||
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 4d76594c2a8f..f1dce848ef96 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -783,8 +783,6 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) | |||
783 | struct fileIdentDesc *fi, cfi; | 783 | struct fileIdentDesc *fi, cfi; |
784 | struct kernel_lb_addr tloc; | 784 | struct kernel_lb_addr tloc; |
785 | 785 | ||
786 | dentry_unhash(dentry); | ||
787 | |||
788 | retval = -ENOENT; | 786 | retval = -ENOENT; |
789 | fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); | 787 | fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); |
790 | if (!fi) | 788 | if (!fi) |
@@ -1083,9 +1081,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1083 | struct kernel_lb_addr tloc; | 1081 | struct kernel_lb_addr tloc; |
1084 | struct udf_inode_info *old_iinfo = UDF_I(old_inode); | 1082 | struct udf_inode_info *old_iinfo = UDF_I(old_inode); |
1085 | 1083 | ||
1086 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
1087 | dentry_unhash(new_dentry); | ||
1088 | |||
1089 | ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); | 1084 | ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); |
1090 | if (ofi) { | 1085 | if (ofi) { |
1091 | if (ofibh.sbh != ofibh.ebh) | 1086 | if (ofibh.sbh != ofibh.ebh) |
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 953ebdfc5bf7..29309e25417f 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c | |||
@@ -258,8 +258,6 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry) | |||
258 | struct inode * inode = dentry->d_inode; | 258 | struct inode * inode = dentry->d_inode; |
259 | int err= -ENOTEMPTY; | 259 | int err= -ENOTEMPTY; |
260 | 260 | ||
261 | dentry_unhash(dentry); | ||
262 | |||
263 | lock_ufs(dir->i_sb); | 261 | lock_ufs(dir->i_sb); |
264 | if (ufs_empty_dir (inode)) { | 262 | if (ufs_empty_dir (inode)) { |
265 | err = ufs_unlink(dir, dentry); | 263 | err = ufs_unlink(dir, dentry); |
@@ -284,9 +282,6 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
284 | struct ufs_dir_entry *old_de; | 282 | struct ufs_dir_entry *old_de; |
285 | int err = -ENOENT; | 283 | int err = -ENOENT; |
286 | 284 | ||
287 | if (new_inode && S_ISDIR(new_inode->i_mode)) | ||
288 | dentry_unhash(new_dentry); | ||
289 | |||
290 | old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page); | 285 | old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page); |
291 | if (!old_de) | 286 | if (!old_de) |
292 | goto out; | 287 | goto out; |
diff --git a/fs/xattr.c b/fs/xattr.c index f1ef94974dea..f060663ab70c 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -46,18 +46,22 @@ xattr_permission(struct inode *inode, const char *name, int mask) | |||
46 | return 0; | 46 | return 0; |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * The trusted.* namespace can only be accessed by a privileged user. | 49 | * The trusted.* namespace can only be accessed by privileged users. |
50 | */ | 50 | */ |
51 | if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) | 51 | if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) { |
52 | return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); | 52 | if (!capable(CAP_SYS_ADMIN)) |
53 | return (mask & MAY_WRITE) ? -EPERM : -ENODATA; | ||
54 | return 0; | ||
55 | } | ||
53 | 56 | ||
54 | /* In user.* namespace, only regular files and directories can have | 57 | /* |
58 | * In the user.* namespace, only regular files and directories can have | ||
55 | * extended attributes. For sticky directories, only the owner and | 59 | * extended attributes. For sticky directories, only the owner and |
56 | * privileged user can write attributes. | 60 | * privileged users can write attributes. |
57 | */ | 61 | */ |
58 | if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { | 62 | if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { |
59 | if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) | 63 | if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) |
60 | return -EPERM; | 64 | return (mask & MAY_WRITE) ? -EPERM : -ENODATA; |
61 | if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && | 65 | if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && |
62 | (mask & MAY_WRITE) && !inode_owner_or_capable(inode)) | 66 | (mask & MAY_WRITE) && !inode_owner_or_capable(inode)) |
63 | return -EPERM; | 67 | return -EPERM; |
@@ -87,7 +91,11 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, | |||
87 | { | 91 | { |
88 | struct inode *inode = dentry->d_inode; | 92 | struct inode *inode = dentry->d_inode; |
89 | int error = -EOPNOTSUPP; | 93 | int error = -EOPNOTSUPP; |
94 | int issec = !strncmp(name, XATTR_SECURITY_PREFIX, | ||
95 | XATTR_SECURITY_PREFIX_LEN); | ||
90 | 96 | ||
97 | if (issec) | ||
98 | inode->i_flags &= ~S_NOSEC; | ||
91 | if (inode->i_op->setxattr) { | 99 | if (inode->i_op->setxattr) { |
92 | error = inode->i_op->setxattr(dentry, name, value, size, flags); | 100 | error = inode->i_op->setxattr(dentry, name, value, size, flags); |
93 | if (!error) { | 101 | if (!error) { |
@@ -95,8 +103,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, | |||
95 | security_inode_post_setxattr(dentry, name, value, | 103 | security_inode_post_setxattr(dentry, name, value, |
96 | size, flags); | 104 | size, flags); |
97 | } | 105 | } |
98 | } else if (!strncmp(name, XATTR_SECURITY_PREFIX, | 106 | } else if (issec) { |
99 | XATTR_SECURITY_PREFIX_LEN)) { | ||
100 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; | 107 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; |
101 | error = security_inode_setsecurity(inode, suffix, value, | 108 | error = security_inode_setsecurity(inode, suffix, value, |
102 | size, flags); | 109 | size, flags); |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 98b9c91fcdf1..1e3a7ce804dc 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -925,7 +925,8 @@ xfs_fs_inode_init_once( | |||
925 | */ | 925 | */ |
926 | STATIC void | 926 | STATIC void |
927 | xfs_fs_dirty_inode( | 927 | xfs_fs_dirty_inode( |
928 | struct inode *inode) | 928 | struct inode *inode, |
929 | int flags) | ||
929 | { | 930 | { |
930 | barrier(); | 931 | barrier(); |
931 | XFS_I(inode)->i_update_core = 1; | 932 | XFS_I(inode)->i_update_core = 1; |
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 85c1d302c12e..5e06acf95d0f 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
@@ -909,7 +909,7 @@ extern int ext3_setattr (struct dentry *, struct iattr *); | |||
909 | extern void ext3_evict_inode (struct inode *); | 909 | extern void ext3_evict_inode (struct inode *); |
910 | extern int ext3_sync_inode (handle_t *, struct inode *); | 910 | extern int ext3_sync_inode (handle_t *, struct inode *); |
911 | extern void ext3_discard_reservation (struct inode *); | 911 | extern void ext3_discard_reservation (struct inode *); |
912 | extern void ext3_dirty_inode(struct inode *); | 912 | extern void ext3_dirty_inode(struct inode *, int); |
913 | extern int ext3_change_inode_journal_flag(struct inode *, int); | 913 | extern int ext3_change_inode_journal_flag(struct inode *, int); |
914 | extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *); | 914 | extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *); |
915 | extern int ext3_can_truncate(struct inode *inode); | 915 | extern int ext3_can_truncate(struct inode *inode); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 241609346dfb..c55d6b7cd5d6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -237,6 +237,7 @@ struct inodes_stat_t { | |||
237 | #define S_PRIVATE 512 /* Inode is fs-internal */ | 237 | #define S_PRIVATE 512 /* Inode is fs-internal */ |
238 | #define S_IMA 1024 /* Inode has an associated IMA struct */ | 238 | #define S_IMA 1024 /* Inode has an associated IMA struct */ |
239 | #define S_AUTOMOUNT 2048 /* Automount/referral quasi-directory */ | 239 | #define S_AUTOMOUNT 2048 /* Automount/referral quasi-directory */ |
240 | #define S_NOSEC 4096 /* no suid or xattr security attributes */ | ||
240 | 241 | ||
241 | /* | 242 | /* |
242 | * Note that nosuid etc flags are inode-specific: setting some file-system | 243 | * Note that nosuid etc flags are inode-specific: setting some file-system |
@@ -273,6 +274,7 @@ struct inodes_stat_t { | |||
273 | #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) | 274 | #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) |
274 | #define IS_IMA(inode) ((inode)->i_flags & S_IMA) | 275 | #define IS_IMA(inode) ((inode)->i_flags & S_IMA) |
275 | #define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT) | 276 | #define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT) |
277 | #define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC) | ||
276 | 278 | ||
277 | /* the read-only stuff doesn't really belong here, but any other place is | 279 | /* the read-only stuff doesn't really belong here, but any other place is |
278 | probably as bad and I don't want to create yet another include file. */ | 280 | probably as bad and I don't want to create yet another include file. */ |
@@ -1618,7 +1620,7 @@ struct super_operations { | |||
1618 | struct inode *(*alloc_inode)(struct super_block *sb); | 1620 | struct inode *(*alloc_inode)(struct super_block *sb); |
1619 | void (*destroy_inode)(struct inode *); | 1621 | void (*destroy_inode)(struct inode *); |
1620 | 1622 | ||
1621 | void (*dirty_inode) (struct inode *); | 1623 | void (*dirty_inode) (struct inode *, int flags); |
1622 | int (*write_inode) (struct inode *, struct writeback_control *wbc); | 1624 | int (*write_inode) (struct inode *, struct writeback_control *wbc); |
1623 | int (*drop_inode) (struct inode *); | 1625 | int (*drop_inode) (struct inode *); |
1624 | void (*evict_inode) (struct inode *); | 1626 | void (*evict_inode) (struct inode *); |
@@ -2582,5 +2584,16 @@ int __init get_filesystem_list(char *buf); | |||
2582 | #define OPEN_FMODE(flag) ((__force fmode_t)(((flag + 1) & O_ACCMODE) | \ | 2584 | #define OPEN_FMODE(flag) ((__force fmode_t)(((flag + 1) & O_ACCMODE) | \ |
2583 | (flag & __FMODE_NONOTIFY))) | 2585 | (flag & __FMODE_NONOTIFY))) |
2584 | 2586 | ||
2587 | static inline int is_sxid(mode_t mode) | ||
2588 | { | ||
2589 | return (mode & S_ISUID) || ((mode & S_ISGID) && (mode & S_IXGRP)); | ||
2590 | } | ||
2591 | |||
2592 | static inline void inode_has_no_xattr(struct inode *inode) | ||
2593 | { | ||
2594 | if (!is_sxid(inode->i_mode)) | ||
2595 | inode->i_flags |= S_NOSEC; | ||
2596 | } | ||
2597 | |||
2585 | #endif /* __KERNEL__ */ | 2598 | #endif /* __KERNEL__ */ |
2586 | #endif /* _LINUX_FS_H */ | 2599 | #endif /* _LINUX_FS_H */ |
diff --git a/mm/filemap.c b/mm/filemap.c index bcdc393b6580..d7b10578a64b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1982,16 +1982,26 @@ static int __remove_suid(struct dentry *dentry, int kill) | |||
1982 | int file_remove_suid(struct file *file) | 1982 | int file_remove_suid(struct file *file) |
1983 | { | 1983 | { |
1984 | struct dentry *dentry = file->f_path.dentry; | 1984 | struct dentry *dentry = file->f_path.dentry; |
1985 | int killsuid = should_remove_suid(dentry); | 1985 | struct inode *inode = dentry->d_inode; |
1986 | int killpriv = security_inode_need_killpriv(dentry); | 1986 | int killsuid; |
1987 | int killpriv; | ||
1987 | int error = 0; | 1988 | int error = 0; |
1988 | 1989 | ||
1990 | /* Fast path for nothing security related */ | ||
1991 | if (IS_NOSEC(inode)) | ||
1992 | return 0; | ||
1993 | |||
1994 | killsuid = should_remove_suid(dentry); | ||
1995 | killpriv = security_inode_need_killpriv(dentry); | ||
1996 | |||
1989 | if (killpriv < 0) | 1997 | if (killpriv < 0) |
1990 | return killpriv; | 1998 | return killpriv; |
1991 | if (killpriv) | 1999 | if (killpriv) |
1992 | error = security_inode_killpriv(dentry); | 2000 | error = security_inode_killpriv(dentry); |
1993 | if (!error && killsuid) | 2001 | if (!error && killsuid) |
1994 | error = __remove_suid(dentry, killsuid); | 2002 | error = __remove_suid(dentry, killsuid); |
2003 | if (!error) | ||
2004 | inode->i_flags |= S_NOSEC; | ||
1995 | 2005 | ||
1996 | return error; | 2006 | return error; |
1997 | } | 2007 | } |
@@ -2327,7 +2337,7 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping, | |||
2327 | repeat: | 2337 | repeat: |
2328 | page = find_lock_page(mapping, index); | 2338 | page = find_lock_page(mapping, index); |
2329 | if (page) | 2339 | if (page) |
2330 | return page; | 2340 | goto found; |
2331 | 2341 | ||
2332 | page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask); | 2342 | page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask); |
2333 | if (!page) | 2343 | if (!page) |
@@ -2340,6 +2350,8 @@ repeat: | |||
2340 | goto repeat; | 2350 | goto repeat; |
2341 | return NULL; | 2351 | return NULL; |
2342 | } | 2352 | } |
2353 | found: | ||
2354 | wait_on_page_writeback(page); | ||
2343 | return page; | 2355 | return page; |
2344 | } | 2356 | } |
2345 | EXPORT_SYMBOL(grab_cache_page_write_begin); | 2357 | EXPORT_SYMBOL(grab_cache_page_write_begin); |