aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBen Myers <bpm@sgi.com>2012-05-15 15:26:55 -0400
committerBen Myers <bpm@sgi.com>2012-05-15 15:35:43 -0400
commit1307bbd2af67283131728637e9489002adb26f10 (patch)
tree76b3000b2cf8e7d101b8f4b4de20e6255d316b95 /fs/xfs
parent3fe3e6b18216c1247497dfd51c35484338856e1b (diff)
xfs: protect xfs_sync_worker with s_umount semaphore
xfs_sync_worker checks the MS_ACTIVE flag in s_flags to avoid doing work during mount and unmount. This flag can be cleared by unmount after the xfs_sync_worker checks it but before the work is completed. The has caused crashes in the completion handler for the dummy transaction commited by xfs_sync_worker: PID: 27544 TASK: ffff88013544e040 CPU: 3 COMMAND: "kworker/3:0" #0 [ffff88016fdff930] machine_kexec at ffffffff810244e9 #1 [ffff88016fdff9a0] crash_kexec at ffffffff8108d053 #2 [ffff88016fdffa70] oops_end at ffffffff813ad1b8 #3 [ffff88016fdffaa0] no_context at ffffffff8102bd48 #4 [ffff88016fdffaf0] __bad_area_nosemaphore at ffffffff8102c04d #5 [ffff88016fdffb40] bad_area_nosemaphore at ffffffff8102c12e #6 [ffff88016fdffb50] do_page_fault at ffffffff813afaee #7 [ffff88016fdffc60] page_fault at ffffffff813ac635 [exception RIP: xlog_get_lowest_lsn+0x30] RIP: ffffffffa04a9910 RSP: ffff88016fdffd10 RFLAGS: 00010246 RAX: ffffc90014e48000 RBX: ffff88014d879980 RCX: ffff88014d879980 RDX: ffff8802214ee4c0 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff88016fdffd10 R8: ffff88014d879a80 R9: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: ffff8802214ee400 R13: ffff88014d879980 R14: 0000000000000000 R15: ffff88022fd96605 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #8 [ffff88016fdffd18] xlog_state_do_callback at ffffffffa04aa186 [xfs] #9 [ffff88016fdffd98] xlog_state_done_syncing at ffffffffa04aa568 [xfs] Protect xfs_sync_worker by using the s_umount semaphore at the read level to provide exclusion with unmount while work is progressing. Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_sync.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c
index d2422683ed7..c9d3409c5ca 100644
--- a/fs/xfs/xfs_sync.c
+++ b/fs/xfs/xfs_sync.c
@@ -386,20 +386,23 @@ xfs_sync_worker(
386 * We shouldn't write/force the log if we are in the mount/unmount 386 * We shouldn't write/force the log if we are in the mount/unmount
387 * process or on a read only filesystem. The workqueue still needs to be 387 * process or on a read only filesystem. The workqueue still needs to be
388 * active in both cases, however, because it is used for inode reclaim 388 * active in both cases, however, because it is used for inode reclaim
389 * during these times. hence use the MS_ACTIVE flag to avoid doing 389 * during these times. Use the s_umount semaphore to provide exclusion
390 * anything in these periods. 390 * with unmount.
391 */ 391 */
392 if (!(mp->m_super->s_flags & MS_ACTIVE) && 392 if (down_read_trylock(&mp->m_super->s_umount)) {
393 !(mp->m_flags & XFS_MOUNT_RDONLY)) { 393 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
394 /* dgc: errors ignored here */ 394 /* dgc: errors ignored here */
395 if (mp->m_super->s_frozen == SB_UNFROZEN && 395 if (mp->m_super->s_frozen == SB_UNFROZEN &&
396 xfs_log_need_covered(mp)) 396 xfs_log_need_covered(mp))
397 error = xfs_fs_log_dummy(mp); 397 error = xfs_fs_log_dummy(mp);
398 else 398 else
399 xfs_log_force(mp, 0); 399 xfs_log_force(mp, 0);
400 400
401 /* start pushing all the metadata that is currently dirty */ 401 /* start pushing all the metadata that is currently
402 xfs_ail_push_all(mp->m_ail); 402 * dirty */
403 xfs_ail_push_all(mp->m_ail);
404 }
405 up_read(&mp->m_super->s_umount);
403 } 406 }
404 407
405 /* queue us up again */ 408 /* queue us up again */