Merge tag 'xfs-4.19-merge-7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Aug 2018 01:15:47 +0000 (18:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Aug 2018 01:15:47 +0000 (18:15 -0700)
Pull xfs fixes from Darrick Wong:

 - Fix an uninitialized variable

 - Don't use obviously garbage AG header counters to calculate
   transaction reservations

 - Trigger icount recalculation on bad icount when mounting

* tag 'xfs-4.19-merge-7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  iomap: fix WARN_ON_ONCE on uninitialized variable
  xfs: sanity check ag header values in xrep_calc_ag_resblks
  xfs: recalculate summary counters at mount time if icount is bad

fs/iomap.c
fs/xfs/scrub/repair.c
fs/xfs/xfs_mount.c

index 009071e73bc0bb46e368f792859d492a93cbd366..74762b1ec233f9e9ab1f5da47116271143a344db 100644 (file)
@@ -290,7 +290,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
        sector_t sector;
 
        if (iomap->type == IOMAP_INLINE) {
-               WARN_ON_ONCE(poff);
+               WARN_ON_ONCE(pos);
                iomap_read_inline_data(inode, page, iomap);
                return PAGE_SIZE;
        }
index 17cf4856439034450e5a83c1ca1e8cb6d421f1e3..9f08dd9bf1d553934bf2aa2f8a108ab8435bc19c 100644 (file)
@@ -195,8 +195,8 @@ xrep_calc_ag_resblks(
        struct xfs_scrub_metadata       *sm = sc->sm;
        struct xfs_perag                *pag;
        struct xfs_buf                  *bp;
-       xfs_agino_t                     icount = 0;
-       xfs_extlen_t                    aglen = 0;
+       xfs_agino_t                     icount = NULLAGINO;
+       xfs_extlen_t                    aglen = NULLAGBLOCK;
        xfs_extlen_t                    usedlen;
        xfs_extlen_t                    freelen;
        xfs_extlen_t                    bnobt_sz;
@@ -208,20 +208,14 @@ xrep_calc_ag_resblks(
        if (!(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
                return 0;
 
-       /* Use in-core counters if possible. */
        pag = xfs_perag_get(mp, sm->sm_agno);
-       if (pag->pagi_init)
+       if (pag->pagi_init) {
+               /* Use in-core icount if possible. */
                icount = pag->pagi_count;
-
-       /*
-        * Otherwise try to get the actual counters from disk; if not, make
-        * some worst case assumptions.
-        */
-       if (icount == 0) {
+       } else {
+               /* Try to get the actual counters from disk. */
                error = xfs_ialloc_read_agi(mp, NULL, sm->sm_agno, &bp);
-               if (error) {
-                       icount = mp->m_sb.sb_agblocks / mp->m_sb.sb_inopblock;
-               } else {
+               if (!error) {
                        icount = pag->pagi_count;
                        xfs_buf_relse(bp);
                }
@@ -229,18 +223,32 @@ xrep_calc_ag_resblks(
 
        /* Now grab the block counters from the AGF. */
        error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp);
-       if (error) {
-               aglen = mp->m_sb.sb_agblocks;
-               freelen = aglen;
-               usedlen = aglen;
-       } else {
+       if (!error) {
                aglen = be32_to_cpu(XFS_BUF_TO_AGF(bp)->agf_length);
-               freelen = pag->pagf_freeblks;
+               freelen = be32_to_cpu(XFS_BUF_TO_AGF(bp)->agf_freeblks);
                usedlen = aglen - freelen;
                xfs_buf_relse(bp);
        }
        xfs_perag_put(pag);
 
+       /* If the icount is impossible, make some worst-case assumptions. */
+       if (icount == NULLAGINO ||
+           !xfs_verify_agino(mp, sm->sm_agno, icount)) {
+               xfs_agino_t     first, last;
+
+               xfs_agino_range(mp, sm->sm_agno, &first, &last);
+               icount = last - first + 1;
+       }
+
+       /* If the block counts are impossible, make worst-case assumptions. */
+       if (aglen == NULLAGBLOCK ||
+           aglen != xfs_ag_block_count(mp, sm->sm_agno) ||
+           freelen >= aglen) {
+               aglen = xfs_ag_block_count(mp, sm->sm_agno);
+               freelen = aglen;
+               usedlen = aglen;
+       }
+
        trace_xrep_calc_ag_resblks(mp, sm->sm_agno, icount, aglen,
                        freelen, usedlen);
 
index 99db27d6ac8a4f25de6405d69a8952144b277847..02d15098dbee3f830101dbca3aef7cad04bb4ba8 100644 (file)
@@ -637,6 +637,7 @@ xfs_check_summary_counts(
         */
        if (XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
            (mp->m_sb.sb_fdblocks > mp->m_sb.sb_dblocks ||
+            !xfs_verify_icount(mp, mp->m_sb.sb_icount) ||
             mp->m_sb.sb_ifree > mp->m_sb.sb_icount))
                mp->m_flags |= XFS_MOUNT_BAD_SUMMARY;