]> git.baikalelectronics.ru Git - kernel.git/commitdiff
xfs: on failed mount, force-reclaim inodes after unmounting quota controls
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 9 Nov 2017 00:26:49 +0000 (16:26 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Fri, 10 Nov 2017 03:27:33 +0000 (19:27 -0800)
When mounting fails, we must force-reclaim inodes (and disable delayed
reclaim) /after/ the realtime and quota control have let go of the
realtime and quota inodes.  Without this, we corrupt the timer list and
cause other weird problems.

Found by xfs/376 fuzzing u3.bmbt[0].lastoff on an rmap filesystem to
force a bogus post-eof extent reclaim that causes the fs to go down.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/xfs_mount.c

index e9727d0a541a109329c2c9072b24c7c0d3b6ed23..c879b517cc94482e5a51506f3da1448e2404a6c1 100644 (file)
@@ -1022,10 +1022,21 @@ xfs_mountfs(
        xfs_rtunmount_inodes(mp);
  out_rele_rip:
        IRELE(rip);
-       cancel_delayed_work_sync(&mp->m_reclaim_work);
-       xfs_reclaim_inodes(mp, SYNC_WAIT);
        /* Clean out dquots that might be in memory after quotacheck. */
        xfs_qm_unmount(mp);
+       /*
+        * Cancel all delayed reclaim work and reclaim the inodes directly.
+        * We have to do this /after/ rtunmount and qm_unmount because those
+        * two will have scheduled delayed reclaim for the rt/quota inodes.
+        *
+        * This is slightly different from the unmountfs call sequence
+        * because we could be tearing down a partially set up mount.  In
+        * particular, if log_mount_finish fails we bail out without calling
+        * qm_unmount_quotas and therefore rely on qm_unmount to release the
+        * quota inodes.
+        */
+       cancel_delayed_work_sync(&mp->m_reclaim_work);
+       xfs_reclaim_inodes(mp, SYNC_WAIT);
  out_log_dealloc:
        mp->m_flags |= XFS_MOUNT_UNMOUNTING;
        xfs_log_mount_cancel(mp);