xfs: ensure log covering transactions are synchronous
To ensure the log is covered and the filesystem idles correctly, we need to ensure that dummy transactions hit the disk and do not stay pinned in memory. If the superblock is pinned in memory, it can't be flushed so the log covering cannot make progress. The result is dependent on timing - more oftent han not we continue to issues a log covering transaction every 36s rather than idling after ~90s. Fix this by making the log covering transaction synchronous. To avoid additional log force from xfssyncd, make the log covering transaction take the place of the existing log force in the xfssyncd background sync process. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
This commit is contained in:
parent
eda7798272
commit
c58efdb442
4 changed files with 13 additions and 12 deletions
|
@ -1413,7 +1413,7 @@ xfs_fs_freeze(
|
|||
|
||||
xfs_save_resvblks(mp);
|
||||
xfs_quiesce_attr(mp);
|
||||
return -xfs_fs_log_dummy(mp, SYNC_WAIT);
|
||||
return -xfs_fs_log_dummy(mp);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
|
|
@ -362,7 +362,7 @@ xfs_quiesce_data(
|
|||
|
||||
/* mark the log as covered if needed */
|
||||
if (xfs_log_need_covered(mp))
|
||||
error2 = xfs_fs_log_dummy(mp, SYNC_WAIT);
|
||||
error2 = xfs_fs_log_dummy(mp);
|
||||
|
||||
/* flush data-only devices */
|
||||
if (mp->m_rtdev_targp)
|
||||
|
@ -503,13 +503,14 @@ xfs_sync_worker(
|
|||
int error;
|
||||
|
||||
if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
|
||||
xfs_log_force(mp, 0);
|
||||
xfs_reclaim_inodes(mp, 0);
|
||||
/* dgc: errors ignored here */
|
||||
error = xfs_qm_sync(mp, SYNC_TRYLOCK);
|
||||
if (mp->m_super->s_frozen == SB_UNFROZEN &&
|
||||
xfs_log_need_covered(mp))
|
||||
error = xfs_fs_log_dummy(mp, 0);
|
||||
error = xfs_fs_log_dummy(mp);
|
||||
else
|
||||
xfs_log_force(mp, 0);
|
||||
xfs_reclaim_inodes(mp, 0);
|
||||
error = xfs_qm_sync(mp, SYNC_TRYLOCK);
|
||||
}
|
||||
mp->m_sync_seq++;
|
||||
wake_up(&mp->m_wait_single_sync_task);
|
||||
|
|
|
@ -612,12 +612,13 @@ xfs_reserve_blocks(
|
|||
*
|
||||
* We cannot use an inode here for this - that will push dirty state back up
|
||||
* into the VFS and then periodic inode flushing will prevent log covering from
|
||||
* making progress. Hence we log a field in the superblock instead.
|
||||
* making progress. Hence we log a field in the superblock instead and use a
|
||||
* synchronous transaction to ensure the superblock is immediately unpinned
|
||||
* and can be written back.
|
||||
*/
|
||||
int
|
||||
xfs_fs_log_dummy(
|
||||
xfs_mount_t *mp,
|
||||
int flags)
|
||||
xfs_mount_t *mp)
|
||||
{
|
||||
xfs_trans_t *tp;
|
||||
int error;
|
||||
|
@ -632,8 +633,7 @@ xfs_fs_log_dummy(
|
|||
|
||||
/* log the UUID because it is an unchanging field */
|
||||
xfs_mod_sb(tp, XFS_SB_UUID);
|
||||
if (flags & SYNC_WAIT)
|
||||
xfs_trans_set_sync(tp);
|
||||
xfs_trans_set_sync(tp);
|
||||
return xfs_trans_commit(tp, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,6 @@ extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt);
|
|||
extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval,
|
||||
xfs_fsop_resblks_t *outval);
|
||||
extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
|
||||
extern int xfs_fs_log_dummy(xfs_mount_t *mp, int flags);
|
||||
extern int xfs_fs_log_dummy(struct xfs_mount *mp);
|
||||
|
||||
#endif /* __XFS_FSOPS_H__ */
|
||||
|
|
Loading…
Reference in a new issue