Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Dave Chinner and committed by
Alex Elder
c58efdb4 eda77982

+13 -12
+1 -1
fs/xfs/linux-2.6/xfs_super.c
··· 1413 1413 1414 1414 xfs_save_resvblks(mp); 1415 1415 xfs_quiesce_attr(mp); 1416 - return -xfs_fs_log_dummy(mp, SYNC_WAIT); 1416 + return -xfs_fs_log_dummy(mp); 1417 1417 } 1418 1418 1419 1419 STATIC int
+6 -5
fs/xfs/linux-2.6/xfs_sync.c
··· 362 362 363 363 /* mark the log as covered if needed */ 364 364 if (xfs_log_need_covered(mp)) 365 - error2 = xfs_fs_log_dummy(mp, SYNC_WAIT); 365 + error2 = xfs_fs_log_dummy(mp); 366 366 367 367 /* flush data-only devices */ 368 368 if (mp->m_rtdev_targp) ··· 503 503 int error; 504 504 505 505 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { 506 - xfs_log_force(mp, 0); 507 - xfs_reclaim_inodes(mp, 0); 508 506 /* dgc: errors ignored here */ 509 - error = xfs_qm_sync(mp, SYNC_TRYLOCK); 510 507 if (mp->m_super->s_frozen == SB_UNFROZEN && 511 508 xfs_log_need_covered(mp)) 512 - error = xfs_fs_log_dummy(mp, 0); 509 + error = xfs_fs_log_dummy(mp); 510 + else 511 + xfs_log_force(mp, 0); 512 + xfs_reclaim_inodes(mp, 0); 513 + error = xfs_qm_sync(mp, SYNC_TRYLOCK); 513 514 } 514 515 mp->m_sync_seq++; 515 516 wake_up(&mp->m_wait_single_sync_task);
+5 -5
fs/xfs/xfs_fsops.c
··· 612 612 * 613 613 * We cannot use an inode here for this - that will push dirty state back up 614 614 * into the VFS and then periodic inode flushing will prevent log covering from 615 - * making progress. Hence we log a field in the superblock instead. 615 + * making progress. Hence we log a field in the superblock instead and use a 616 + * synchronous transaction to ensure the superblock is immediately unpinned 617 + * and can be written back. 616 618 */ 617 619 int 618 620 xfs_fs_log_dummy( 619 - xfs_mount_t *mp, 620 - int flags) 621 + xfs_mount_t *mp) 621 622 { 622 623 xfs_trans_t *tp; 623 624 int error; ··· 633 632 634 633 /* log the UUID because it is an unchanging field */ 635 634 xfs_mod_sb(tp, XFS_SB_UUID); 636 - if (flags & SYNC_WAIT) 637 - xfs_trans_set_sync(tp); 635 + xfs_trans_set_sync(tp); 638 636 return xfs_trans_commit(tp, 0); 639 637 } 640 638
+1 -1
fs/xfs/xfs_fsops.h
··· 25 25 extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval, 26 26 xfs_fsop_resblks_t *outval); 27 27 extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags); 28 - extern int xfs_fs_log_dummy(xfs_mount_t *mp, int flags); 28 + extern int xfs_fs_log_dummy(struct xfs_mount *mp); 29 29 30 30 #endif /* __XFS_FSOPS_H__ */