fs/super.c: don't fool lockdep in freeze_super() and thaw_super() paths
sb_wait_write()->percpu_rwsem_release() fools lockdep to avoid the
false-positives. Now that xfs was fixed by Dave's commit dbad7c9930
("xfs: stop holding ILOCK over filldir callbacks") we can remove it and
change freeze_super() and thaw_super() to run with s_writers.rw_sem locks
held; we add two trivial helpers for that, lockdep_sb_freeze_release()
and lockdep_sb_freeze_acquire().
xfstests-dev/check `grep -il freeze tests/*/???` does not trigger any
warning from lockdep.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
89f39af129
commit
f1a9622037
37
fs/super.c
37
fs/super.c
@ -1269,25 +1269,34 @@ EXPORT_SYMBOL(__sb_start_write);
|
||||
static void sb_wait_write(struct super_block *sb, int level)
|
||||
{
|
||||
percpu_down_write(sb->s_writers.rw_sem + level-1);
|
||||
/*
|
||||
* We are going to return to userspace and forget about this lock, the
|
||||
* ownership goes to the caller of thaw_super() which does unlock.
|
||||
*
|
||||
* FIXME: we should do this before return from freeze_super() after we
|
||||
* called sync_filesystem(sb) and s_op->freeze_fs(sb), and thaw_super()
|
||||
* should re-acquire these locks before s_op->unfreeze_fs(sb). However
|
||||
* this leads to lockdep false-positives, so currently we do the early
|
||||
* release right after acquire.
|
||||
*/
|
||||
percpu_rwsem_release(sb->s_writers.rw_sem + level-1, 0, _THIS_IP_);
|
||||
}
|
||||
|
||||
static void sb_freeze_unlock(struct super_block *sb)
|
||||
/*
|
||||
* We are going to return to userspace and forget about these locks, the
|
||||
* ownership goes to the caller of thaw_super() which does unlock().
|
||||
*/
|
||||
static void lockdep_sb_freeze_release(struct super_block *sb)
|
||||
{
|
||||
int level;
|
||||
|
||||
for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--)
|
||||
percpu_rwsem_release(sb->s_writers.rw_sem + level, 0, _THIS_IP_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell lockdep we are holding these locks before we call ->unfreeze_fs(sb).
|
||||
*/
|
||||
static void lockdep_sb_freeze_acquire(struct super_block *sb)
|
||||
{
|
||||
int level;
|
||||
|
||||
for (level = 0; level < SB_FREEZE_LEVELS; ++level)
|
||||
percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_);
|
||||
}
|
||||
|
||||
static void sb_freeze_unlock(struct super_block *sb)
|
||||
{
|
||||
int level;
|
||||
|
||||
for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--)
|
||||
percpu_up_write(sb->s_writers.rw_sem + level);
|
||||
@ -1383,6 +1392,7 @@ int freeze_super(struct super_block *sb)
|
||||
* when frozen is set to SB_FREEZE_COMPLETE, and for thaw_super().
|
||||
*/
|
||||
sb->s_writers.frozen = SB_FREEZE_COMPLETE;
|
||||
lockdep_sb_freeze_release(sb);
|
||||
up_write(&sb->s_umount);
|
||||
return 0;
|
||||
}
|
||||
@ -1409,11 +1419,14 @@ int thaw_super(struct super_block *sb)
|
||||
goto out;
|
||||
}
|
||||
|
||||
lockdep_sb_freeze_acquire(sb);
|
||||
|
||||
if (sb->s_op->unfreeze_fs) {
|
||||
error = sb->s_op->unfreeze_fs(sb);
|
||||
if (error) {
|
||||
printk(KERN_ERR
|
||||
"VFS:Filesystem thaw failed\n");
|
||||
lockdep_sb_freeze_release(sb);
|
||||
up_write(&sb->s_umount);
|
||||
return error;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user