aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/inode_mark.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-05-21 17:01:54 -0400
committerEric Paris <eparis@redhat.com>2009-06-11 14:57:54 -0400
commit1ef5f13c6c8acd3fd10db9f1743f3b4cf30a4abb (patch)
treeb42f8aa8f74e598e47c114fc5141a8566a92d859 /fs/notify/inode_mark.c
parente4aff117368cfdd3567ee41844d216d079b55173 (diff)
fsnotify: fsnotify marks on inodes pin them in core
This patch pins any inodes with an fsnotify mark in core. The idea is that as soon as the mark is removed from the inode->fsnotify_mark_entries list the inode will be iput. In reality is doesn't quite work exactly this way. The igrab will happen when the mark is added to an inode, but the iput will happen when the inode pointer is NULL'd inside the mark. It's possible that 2 racing things will try to remove the mark from different directions. One may try to remove the mark because of an explicit request and one might try to remove it because the inode was deleted. It's possible that the removal because of inode deletion will remove the mark from the inode's list, but the removal by explicit request will actually set entry->inode == NULL; and call the iput. This is safe. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/notify/inode_mark.c')
-rw-r--r--fs/notify/inode_mark.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index a39534845b28..282150f74cfa 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -204,6 +204,8 @@ void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry)
204 */ 204 */
205 205
206 206
207 iput(inode);
208
207 /* 209 /*
208 * it's possible that this group tried to destroy itself, but this 210 * it's possible that this group tried to destroy itself, but this
209 * this mark was simultaneously being freed by inode. If that's the 211 * this mark was simultaneously being freed by inode. If that's the
@@ -306,6 +308,10 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
306 struct fsnotify_mark_entry *lentry; 308 struct fsnotify_mark_entry *lentry;
307 int ret = 0; 309 int ret = 0;
308 310
311 inode = igrab(inode);
312 if (unlikely(!inode))
313 return -EINVAL;
314
309 /* 315 /*
310 * LOCKING ORDER!!!! 316 * LOCKING ORDER!!!!
311 * entry->lock 317 * entry->lock
@@ -337,6 +343,7 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
337 343
338 if (lentry) { 344 if (lentry) {
339 ret = -EEXIST; 345 ret = -EEXIST;
346 iput(inode);
340 fsnotify_put_mark(lentry); 347 fsnotify_put_mark(lentry);
341 } else { 348 } else {
342 __fsnotify_update_child_dentry_flags(inode); 349 __fsnotify_update_child_dentry_flags(inode);