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); |
