diff options
author | Mark Tinguely <tinguely@sgi.com> | 2012-07-24 11:59:19 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-07-29 17:34:19 -0400 |
commit | 9a57fa8ee7c29e11c2a29ce058573ba99157eda7 (patch) | |
tree | 3fc564a3ad53b16a6604aa89ae3d4d26e07e2d38 /fs/xfs | |
parent | 8375f922aaa6e7a880022529202fb486315568c3 (diff) |
xfs: wait for the write the superblock on unmount
v2: Add the xfs_buf_lock to xfs_quiesce_attr().
Add explaination why xfs_buf_lock() is used to wait for write.
xfs_wait_buftarg() does not wait for the completion of the write of the
uncached superblock. This write can race with the shutdown of the log
and causes a panic if the write does not win the race.
During the log write, xfsaild_push() will lock the buffer and set the
XBF_ASYNC flag. Because the XBF_FLAG is set, complete() is not performed
on the buffer's iowait entry, we cannot call xfs_buf_iowait() to wait
for the write to complete. The buffer's lock is held until the write is
complete, so we can block on a xfs_buf_lock() request to be notified
that the write is complete.
Signed-off-by: Mark Tinguely <tinguely@sgi.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_mount.c | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_sync.c | 9 |
2 files changed, 18 insertions, 0 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 9536fd190191..711ca51ca3d7 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1529,6 +1529,15 @@ xfs_unmountfs( | |||
1529 | xfs_ail_push_all_sync(mp->m_ail); | 1529 | xfs_ail_push_all_sync(mp->m_ail); |
1530 | xfs_wait_buftarg(mp->m_ddev_targp); | 1530 | xfs_wait_buftarg(mp->m_ddev_targp); |
1531 | 1531 | ||
1532 | /* | ||
1533 | * The superblock buffer is uncached and xfsaild_push() will lock and | ||
1534 | * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait() | ||
1535 | * here but a lock on the superblock buffer will block until iodone() | ||
1536 | * has completed. | ||
1537 | */ | ||
1538 | xfs_buf_lock(mp->m_sb_bp); | ||
1539 | xfs_buf_unlock(mp->m_sb_bp); | ||
1540 | |||
1532 | xfs_log_unmount_write(mp); | 1541 | xfs_log_unmount_write(mp); |
1533 | xfs_log_unmount(mp); | 1542 | xfs_log_unmount(mp); |
1534 | xfs_uuid_unmount(mp); | 1543 | xfs_uuid_unmount(mp); |
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index e61fc1519073..97304f10e78a 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c | |||
@@ -359,6 +359,15 @@ xfs_quiesce_attr( | |||
359 | * added an item to the AIL, thus flush it again. | 359 | * added an item to the AIL, thus flush it again. |
360 | */ | 360 | */ |
361 | xfs_ail_push_all_sync(mp->m_ail); | 361 | xfs_ail_push_all_sync(mp->m_ail); |
362 | |||
363 | /* | ||
364 | * The superblock buffer is uncached and xfsaild_push() will lock and | ||
365 | * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait() | ||
366 | * here but a lock on the superblock buffer will block until iodone() | ||
367 | * has completed. | ||
368 | */ | ||
369 | xfs_buf_lock(mp->m_sb_bp); | ||
370 | xfs_buf_unlock(mp->m_sb_bp); | ||
362 | } | 371 | } |
363 | 372 | ||
364 | static void | 373 | static void |