Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fix from Al Viro:
 "Off-by-one in d_walk()/__dentry_kill() race fix.

  It's very hard to hit; possible in the same conditions as the original
  bug, except that you need the skipped branch to contain all the
  remaining evictables, so that the d_walk()-calling loop in
  d_invalidate() decides there's nothing more to do and doesn't go for
  another pass - otherwise that next pass will sweep the sucker.

  So it's not too urgent, but seeing that the fix is obvious and the
  original commit has spread into all -stable branches..."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  d_walk() might skip too much
This commit is contained in:
Linus Torvalds 2015-05-31 16:00:34 -07:00
Родитель 36a8b9a774 2159184ea0
Коммит 8ba64dc338
1 изменённых файлов: 4 добавлений и 4 удалений

Просмотреть файл

@ -1239,13 +1239,13 @@ ascend:
/* might go back up the wrong parent if we have had a rename. */ /* might go back up the wrong parent if we have had a rename. */
if (need_seqretry(&rename_lock, seq)) if (need_seqretry(&rename_lock, seq))
goto rename_retry; goto rename_retry;
next = child->d_child.next; /* go into the first sibling still alive */
while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { do {
next = child->d_child.next;
if (next == &this_parent->d_subdirs) if (next == &this_parent->d_subdirs)
goto ascend; goto ascend;
child = list_entry(next, struct dentry, d_child); child = list_entry(next, struct dentry, d_child);
next = next->next; } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
}
rcu_read_unlock(); rcu_read_unlock();
goto resume; goto resume;
} }