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 cause a panic if the write does not win the race. Per Dave's suggestion, turn the final write of the superblock into a syncronous write. Signed-off-by: Mark Tinguely <tinguely@xxxxxxx> --- fs/xfs/xfs_mount.c | 43 +++++++++++++++++++------------------------ fs/xfs/xfs_mount.h | 4 +++- fs/xfs/xfs_sync.c | 8 +------- 3 files changed, 23 insertions(+), 32 deletions(-) Index: b/fs/xfs/xfs_mount.c =================================================================== --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1517,11 +1517,6 @@ xfs_unmountfs( xfs_warn(mp, "Unable to free reserved block pool. " "Freespace may not be correct on next mount."); - error = xfs_log_sbcount(mp); - if (error) - xfs_warn(mp, "Unable to update superblock counters. " - "Freespace may not be correct on next mount."); - /* * At this point we might have modified the superblock again and thus * added an item to the AIL, thus flush it again. @@ -1529,6 +1524,11 @@ xfs_unmountfs( xfs_ail_push_all_sync(mp->m_ail); xfs_wait_buftarg(mp->m_ddev_targp); + error = xfs_write_sbcount(mp); + if (error) + xfs_warn(mp, "Unable to update superblock counters. " + "Freespace may not be correct on next mount."); + xfs_log_unmount_write(mp); xfs_log_unmount(mp); xfs_uuid_unmount(mp); @@ -1547,19 +1547,17 @@ xfs_fs_writable(xfs_mount_t *mp) } /* - * xfs_log_sbcount + * xfs_write_sbcount * * Sync the superblock counters to disk. * - * Note this code can be called during the process of freezing, so - * we may need to use the transaction allocator which does not - * block when the transaction subsystem is in its frozen state. */ int -xfs_log_sbcount(xfs_mount_t *mp) +xfs_write_sbcount( + struct xfs_mount *mp) { - xfs_trans_t *tp; - int error; + struct xfs_buf *bp; + int error; if (!xfs_fs_writable(mp)) return 0; @@ -1571,19 +1569,16 @@ xfs_log_sbcount(xfs_mount_t *mp) * counters on every modification. */ if (!xfs_sb_version_haslazysbcount(&mp->m_sb)) - return 0; + return 0; - tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP); - error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, - XFS_DEFAULT_LOG_COUNT); - if (error) { - xfs_trans_cancel(tp, 0); - return error; - } - - xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS); - xfs_trans_set_sync(tp); - error = xfs_trans_commit(tp, 0); + bp = xfs_getsb(mp, 0); + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, + XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS); + + if (xfs_buf_ispinned(bp)) + xfs_log_force(mp, 0); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); return error; } Index: b/fs/xfs/xfs_mount.h =================================================================== --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -371,7 +371,9 @@ typedef struct xfs_mod_sb { int64_t msb_delta; /* Change to make to specified field */ } xfs_mod_sb_t; -extern int xfs_log_sbcount(xfs_mount_t *); +extern int +xfs_write_sbcount( + struct xfs_mount *mp); extern __uint64_t xfs_default_resblks(xfs_mount_t *mp); extern int xfs_mountfs(xfs_mount_t *mp); Index: b/fs/xfs/xfs_sync.c =================================================================== --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -348,17 +348,11 @@ xfs_quiesce_attr( WARN_ON(atomic_read(&mp->m_active_trans) != 0); /* Push the superblock and write an unmount record */ - error = xfs_log_sbcount(mp); + error = xfs_write_sbcount(mp); if (error) xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. " "Frozen image may not be consistent."); xfs_log_unmount_write(mp); - - /* - * At this point we might have modified the superblock again and thus - * added an item to the AIL, thus flush it again. - */ - xfs_ail_push_all_sync(mp->m_ail); } static void _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs