diff options
Diffstat (limited to 'fs/notify/inode_mark.c')
-rw-r--r-- | fs/notify/inode_mark.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 9ce062218de9..dfbf5447eea4 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -194,6 +194,7 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | |||
194 | { | 194 | { |
195 | struct fsnotify_mark *lmark, *last = NULL; | 195 | struct fsnotify_mark *lmark, *last = NULL; |
196 | int ret = 0; | 196 | int ret = 0; |
197 | int cmp; | ||
197 | 198 | ||
198 | mark->flags |= FSNOTIFY_MARK_FLAG_INODE; | 199 | mark->flags |= FSNOTIFY_MARK_FLAG_INODE; |
199 | 200 | ||
@@ -219,11 +220,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | |||
219 | goto out; | 220 | goto out; |
220 | } | 221 | } |
221 | 222 | ||
222 | if (mark->group->priority < lmark->group->priority) | 223 | cmp = fsnotify_compare_groups(lmark->group, mark->group); |
223 | continue; | 224 | if (cmp < 0) |
224 | |||
225 | if ((mark->group->priority == lmark->group->priority) && | ||
226 | (mark->group < lmark->group)) | ||
227 | continue; | 225 | continue; |
228 | 226 | ||
229 | hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list); | 227 | hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list); |
@@ -288,20 +286,25 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
288 | spin_unlock(&inode->i_lock); | 286 | spin_unlock(&inode->i_lock); |
289 | 287 | ||
290 | /* In case the dropping of a reference would nuke next_i. */ | 288 | /* In case the dropping of a reference would nuke next_i. */ |
291 | if ((&next_i->i_sb_list != list) && | 289 | while (&next_i->i_sb_list != list) { |
292 | atomic_read(&next_i->i_count)) { | ||
293 | spin_lock(&next_i->i_lock); | 290 | spin_lock(&next_i->i_lock); |
294 | if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) { | 291 | if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) && |
292 | atomic_read(&next_i->i_count)) { | ||
295 | __iget(next_i); | 293 | __iget(next_i); |
296 | need_iput = next_i; | 294 | need_iput = next_i; |
295 | spin_unlock(&next_i->i_lock); | ||
296 | break; | ||
297 | } | 297 | } |
298 | spin_unlock(&next_i->i_lock); | 298 | spin_unlock(&next_i->i_lock); |
299 | next_i = list_entry(next_i->i_sb_list.next, | ||
300 | struct inode, i_sb_list); | ||
299 | } | 301 | } |
300 | 302 | ||
301 | /* | 303 | /* |
302 | * We can safely drop inode_sb_list_lock here because we hold | 304 | * We can safely drop inode_sb_list_lock here because either |
303 | * references on both inode and next_i. Also no new inodes | 305 | * we actually hold references on both inode and next_i or |
304 | * will be added since the umount has begun. | 306 | * end of list. Also no new inodes will be added since the |
307 | * umount has begun. | ||
305 | */ | 308 | */ |
306 | spin_unlock(&inode_sb_list_lock); | 309 | spin_unlock(&inode_sb_list_lock); |
307 | 310 | ||