summaryrefslogtreecommitdiff
path: root/include/linux/raid
diff options
context:
space:
mode:
authorKirill Korotaev <dev@sw.ru>2004-09-22 04:21:31 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-09-22 04:21:31 -0700
commit4e56755a7d65add91da1ab50b56ea77cf61bd599 (patch)
tree3d71af42839806673bcedce8cf37f4ea9a38936f /include/linux/raid
parenta5b51d79817282ee3790271d99914266715fa479 (diff)
[PATCH] Fix of race in writeback_inodes()
This patch fixes race in writeback_inodes() described below: writeback_inodes() { .... sb->s_count++; spin_unlock(&sb_lock); .... spin_lock(&sb_lock); if (__put_super(sb)) <<< X goto restart; } } deactivate_super() { fs->kill_sb(s); kill_block_super(sb) generic_shutdown_super(sb) spin_lock(&sb_lock); list_del(&sb->s_list); <<< Y spin_unlock(&sb_lock); .... put_super(s); spin_lock(&sb_lock); __put_super(sb); <<< Z spin_unlock(&sb_lock); } The problem with it is that writeback_inodes() supposes that if __put_super() returns 0 then no super block was deleted from the list and we can safely traverse sb list further. But as it is obvious from the deactivate_super() it's not actually true. because at point Y we delete super block from the list and drop the lock. We do __put_super() very much later... So we can find sb with poisoned sb->s_list at point X and we won't be the last sb reference holders. The last reference will be dropped in point Z. So in case of the following sequence of execution Y -> X -> Z we'll get an oops after point X in writeback_inodes(). This patch introduces __put_super_and_need_restart() function which allows safe traversing of sb list. I'll send a couple of patches later which remove O(n^2) algos and using this function. Signed-Off-By: Kirill Korotaev <dev@sw.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux/raid')
0 files changed, 0 insertions, 0 deletions