diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/fs/inode.c b/fs/inode.c index 0571983755dc..a88baebf77cf 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/cdev.h> | 22 | #include <linux/cdev.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/inotify.h> | 24 | #include <linux/inotify.h> |
25 | #include <linux/fsnotify.h> | ||
25 | #include <linux/mount.h> | 26 | #include <linux/mount.h> |
26 | #include <linux/async.h> | 27 | #include <linux/async.h> |
27 | 28 | ||
@@ -189,6 +190,10 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
189 | inode->i_private = NULL; | 190 | inode->i_private = NULL; |
190 | inode->i_mapping = mapping; | 191 | inode->i_mapping = mapping; |
191 | 192 | ||
193 | #ifdef CONFIG_FSNOTIFY | ||
194 | inode->i_fsnotify_mask = 0; | ||
195 | #endif | ||
196 | |||
192 | return inode; | 197 | return inode; |
193 | 198 | ||
194 | out_free_security: | 199 | out_free_security: |
@@ -219,7 +224,9 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
219 | void destroy_inode(struct inode *inode) | 224 | void destroy_inode(struct inode *inode) |
220 | { | 225 | { |
221 | BUG_ON(inode_has_buffers(inode)); | 226 | BUG_ON(inode_has_buffers(inode)); |
227 | ima_inode_free(inode); | ||
222 | security_inode_free(inode); | 228 | security_inode_free(inode); |
229 | fsnotify_inode_delete(inode); | ||
223 | if (inode->i_sb->s_op->destroy_inode) | 230 | if (inode->i_sb->s_op->destroy_inode) |
224 | inode->i_sb->s_op->destroy_inode(inode); | 231 | inode->i_sb->s_op->destroy_inode(inode); |
225 | else | 232 | else |
@@ -251,6 +258,9 @@ void inode_init_once(struct inode *inode) | |||
251 | INIT_LIST_HEAD(&inode->inotify_watches); | 258 | INIT_LIST_HEAD(&inode->inotify_watches); |
252 | mutex_init(&inode->inotify_mutex); | 259 | mutex_init(&inode->inotify_mutex); |
253 | #endif | 260 | #endif |
261 | #ifdef CONFIG_FSNOTIFY | ||
262 | INIT_HLIST_HEAD(&inode->i_fsnotify_mark_entries); | ||
263 | #endif | ||
254 | } | 264 | } |
255 | EXPORT_SYMBOL(inode_init_once); | 265 | EXPORT_SYMBOL(inode_init_once); |
256 | 266 | ||
@@ -397,6 +407,7 @@ int invalidate_inodes(struct super_block *sb) | |||
397 | mutex_lock(&iprune_mutex); | 407 | mutex_lock(&iprune_mutex); |
398 | spin_lock(&inode_lock); | 408 | spin_lock(&inode_lock); |
399 | inotify_unmount_inodes(&sb->s_inodes); | 409 | inotify_unmount_inodes(&sb->s_inodes); |
410 | fsnotify_unmount_inodes(&sb->s_inodes); | ||
400 | busy = invalidate_list(&sb->s_inodes, &throw_away); | 411 | busy = invalidate_list(&sb->s_inodes, &throw_away); |
401 | spin_unlock(&inode_lock); | 412 | spin_unlock(&inode_lock); |
402 | 413 | ||
@@ -1053,13 +1064,22 @@ int insert_inode_locked(struct inode *inode) | |||
1053 | struct super_block *sb = inode->i_sb; | 1064 | struct super_block *sb = inode->i_sb; |
1054 | ino_t ino = inode->i_ino; | 1065 | ino_t ino = inode->i_ino; |
1055 | struct hlist_head *head = inode_hashtable + hash(sb, ino); | 1066 | struct hlist_head *head = inode_hashtable + hash(sb, ino); |
1056 | struct inode *old; | ||
1057 | 1067 | ||
1058 | inode->i_state |= I_LOCK|I_NEW; | 1068 | inode->i_state |= I_LOCK|I_NEW; |
1059 | while (1) { | 1069 | while (1) { |
1070 | struct hlist_node *node; | ||
1071 | struct inode *old = NULL; | ||
1060 | spin_lock(&inode_lock); | 1072 | spin_lock(&inode_lock); |
1061 | old = find_inode_fast(sb, head, ino); | 1073 | hlist_for_each_entry(old, node, head, i_hash) { |
1062 | if (likely(!old)) { | 1074 | if (old->i_ino != ino) |
1075 | continue; | ||
1076 | if (old->i_sb != sb) | ||
1077 | continue; | ||
1078 | if (old->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) | ||
1079 | continue; | ||
1080 | break; | ||
1081 | } | ||
1082 | if (likely(!node)) { | ||
1063 | hlist_add_head(&inode->i_hash, head); | 1083 | hlist_add_head(&inode->i_hash, head); |
1064 | spin_unlock(&inode_lock); | 1084 | spin_unlock(&inode_lock); |
1065 | return 0; | 1085 | return 0; |
@@ -1081,14 +1101,24 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, | |||
1081 | { | 1101 | { |
1082 | struct super_block *sb = inode->i_sb; | 1102 | struct super_block *sb = inode->i_sb; |
1083 | struct hlist_head *head = inode_hashtable + hash(sb, hashval); | 1103 | struct hlist_head *head = inode_hashtable + hash(sb, hashval); |
1084 | struct inode *old; | ||
1085 | 1104 | ||
1086 | inode->i_state |= I_LOCK|I_NEW; | 1105 | inode->i_state |= I_LOCK|I_NEW; |
1087 | 1106 | ||
1088 | while (1) { | 1107 | while (1) { |
1108 | struct hlist_node *node; | ||
1109 | struct inode *old = NULL; | ||
1110 | |||
1089 | spin_lock(&inode_lock); | 1111 | spin_lock(&inode_lock); |
1090 | old = find_inode(sb, head, test, data); | 1112 | hlist_for_each_entry(old, node, head, i_hash) { |
1091 | if (likely(!old)) { | 1113 | if (old->i_sb != sb) |
1114 | continue; | ||
1115 | if (!test(old, data)) | ||
1116 | continue; | ||
1117 | if (old->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) | ||
1118 | continue; | ||
1119 | break; | ||
1120 | } | ||
1121 | if (likely(!node)) { | ||
1092 | hlist_add_head(&inode->i_hash, head); | 1122 | hlist_add_head(&inode->i_hash, head); |
1093 | spin_unlock(&inode_lock); | 1123 | spin_unlock(&inode_lock); |
1094 | return 0; | 1124 | return 0; |
@@ -1392,7 +1422,7 @@ void file_update_time(struct file *file) | |||
1392 | if (IS_NOCMTIME(inode)) | 1422 | if (IS_NOCMTIME(inode)) |
1393 | return; | 1423 | return; |
1394 | 1424 | ||
1395 | err = mnt_want_write(file->f_path.mnt); | 1425 | err = mnt_want_write_file(file); |
1396 | if (err) | 1426 | if (err) |
1397 | return; | 1427 | return; |
1398 | 1428 | ||