]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - fs/xfs/xfs_fsops.c
xfs: make buffer read verication an IO completion function
[mirror_ubuntu-jammy-kernel.git] / fs / xfs / xfs_fsops.c
index c25b094efbf715186f39a9b7a44466eb0a910374..5440768ec41c1e17bad3961de9c935a40ed61a2e 100644 (file)
@@ -97,7 +97,9 @@ xfs_fs_geometry(
                        (xfs_sb_version_haslazysbcount(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
                        (xfs_sb_version_hasattr2(&mp->m_sb) ?
-                               XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
+                               XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) |
+                       (xfs_sb_version_hasprojid32bit(&mp->m_sb) ?
+                               XFS_FSOP_GEOM_FLAGS_PROJID32 : 0);
                geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ?
                                mp->m_sb.sb_logsectsize : BBSIZE;
                geo->rtsectsize = mp->m_sb.sb_blocksize;
@@ -112,18 +114,38 @@ xfs_fs_geometry(
        return 0;
 }
 
+static struct xfs_buf *
+xfs_growfs_get_hdr_buf(
+       struct xfs_mount        *mp,
+       xfs_daddr_t             blkno,
+       size_t                  numblks,
+       int                     flags)
+{
+       struct xfs_buf          *bp;
+
+       bp = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, flags);
+       if (!bp)
+               return NULL;
+
+       xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
+       bp->b_bn = blkno;
+       bp->b_maps[0].bm_bn = blkno;
+
+       return bp;
+}
+
 static int
 xfs_growfs_data_private(
        xfs_mount_t             *mp,            /* mount point for filesystem */
        xfs_growfs_data_t       *in)            /* growfs data input struct */
 {
        xfs_agf_t               *agf;
+       struct xfs_agfl         *agfl;
        xfs_agi_t               *agi;
        xfs_agnumber_t          agno;
        xfs_extlen_t            agsize;
        xfs_extlen_t            tmpsize;
        xfs_alloc_rec_t         *arec;
-       struct xfs_btree_block  *block;
        xfs_buf_t               *bp;
        int                     bucket;
        int                     dpct;
@@ -146,7 +168,7 @@ xfs_growfs_data_private(
        dpct = pct - mp->m_sb.sb_imax_pct;
        bp = xfs_buf_read_uncached(mp->m_ddev_targp,
                                XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
-                               XFS_FSS_TO_BB(mp, 1), 0);
+                               XFS_FSS_TO_BB(mp, 1), 0, NULL);
        if (!bp)
                return EIO;
        xfs_buf_relse(bp);
@@ -186,17 +208,17 @@ xfs_growfs_data_private(
        nfree = 0;
        for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
                /*
-                * AG freelist header block
+                * AG freespace header block
                 */
-               bp = xfs_buf_get(mp->m_ddev_targp,
-                                XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
-                                XFS_FSS_TO_BB(mp, 1), 0);
+               bp = xfs_growfs_get_hdr_buf(mp,
+                               XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
+                               XFS_FSS_TO_BB(mp, 1), 0);
                if (!bp) {
                        error = ENOMEM;
                        goto error0;
                }
+
                agf = XFS_BUF_TO_AGF(bp);
-               memset(agf, 0, mp->m_sb.sb_sectsize);
                agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
                agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
                agf->agf_seqno = cpu_to_be32(agno);
@@ -222,18 +244,38 @@ xfs_growfs_data_private(
                if (error)
                        goto error0;
 
+               /*
+                * AG freelist header block
+                */
+               bp = xfs_growfs_get_hdr_buf(mp,
+                               XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
+                               XFS_FSS_TO_BB(mp, 1), 0);
+               if (!bp) {
+                       error = ENOMEM;
+                       goto error0;
+               }
+
+               agfl = XFS_BUF_TO_AGFL(bp);
+               for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
+                       agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
+
+               error = xfs_bwrite(bp);
+               xfs_buf_relse(bp);
+               if (error)
+                       goto error0;
+
                /*
                 * AG inode header block
                 */
-               bp = xfs_buf_get(mp->m_ddev_targp,
-                                XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-                                XFS_FSS_TO_BB(mp, 1), 0);
+               bp = xfs_growfs_get_hdr_buf(mp,
+                               XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
+                               XFS_FSS_TO_BB(mp, 1), 0);
                if (!bp) {
                        error = ENOMEM;
                        goto error0;
                }
+
                agi = XFS_BUF_TO_AGI(bp);
-               memset(agi, 0, mp->m_sb.sb_sectsize);
                agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
                agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
                agi->agi_seqno = cpu_to_be32(agno);
@@ -254,24 +296,21 @@ xfs_growfs_data_private(
                /*
                 * BNO btree root block
                 */
-               bp = xfs_buf_get(mp->m_ddev_targp,
-                                XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
-                                BTOBB(mp->m_sb.sb_blocksize), 0);
+               bp = xfs_growfs_get_hdr_buf(mp,
+                               XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
+                               BTOBB(mp->m_sb.sb_blocksize), 0);
+
                if (!bp) {
                        error = ENOMEM;
                        goto error0;
                }
-               block = XFS_BUF_TO_BLOCK(bp);
-               memset(block, 0, mp->m_sb.sb_blocksize);
-               block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
-               block->bb_level = 0;
-               block->bb_numrecs = cpu_to_be16(1);
-               block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-               block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-               arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
+
+               xfs_btree_init_block(mp, bp, XFS_ABTB_MAGIC, 0, 1, 0);
+               arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
                arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
                arec->ar_blockcount = cpu_to_be32(
                        agsize - be32_to_cpu(arec->ar_startblock));
+
                error = xfs_bwrite(bp);
                xfs_buf_relse(bp);
                if (error)
@@ -280,25 +319,21 @@ xfs_growfs_data_private(
                /*
                 * CNT btree root block
                 */
-               bp = xfs_buf_get(mp->m_ddev_targp,
-                                XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
-                                BTOBB(mp->m_sb.sb_blocksize), 0);
+               bp = xfs_growfs_get_hdr_buf(mp,
+                               XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
+                               BTOBB(mp->m_sb.sb_blocksize), 0);
                if (!bp) {
                        error = ENOMEM;
                        goto error0;
                }
-               block = XFS_BUF_TO_BLOCK(bp);
-               memset(block, 0, mp->m_sb.sb_blocksize);
-               block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
-               block->bb_level = 0;
-               block->bb_numrecs = cpu_to_be16(1);
-               block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-               block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-               arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
+
+               xfs_btree_init_block(mp, bp, XFS_ABTC_MAGIC, 0, 1, 0);
+               arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
                arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
                arec->ar_blockcount = cpu_to_be32(
                        agsize - be32_to_cpu(arec->ar_startblock));
                nfree += be32_to_cpu(arec->ar_blockcount);
+
                error = xfs_bwrite(bp);
                xfs_buf_relse(bp);
                if (error)
@@ -307,20 +342,16 @@ xfs_growfs_data_private(
                /*
                 * INO btree root block
                 */
-               bp = xfs_buf_get(mp->m_ddev_targp,
-                                XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
-                                BTOBB(mp->m_sb.sb_blocksize), 0);
+               bp = xfs_growfs_get_hdr_buf(mp,
+                               XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
+                               BTOBB(mp->m_sb.sb_blocksize), 0);
                if (!bp) {
                        error = ENOMEM;
                        goto error0;
                }
-               block = XFS_BUF_TO_BLOCK(bp);
-               memset(block, 0, mp->m_sb.sb_blocksize);
-               block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
-               block->bb_level = 0;
-               block->bb_numrecs = 0;
-               block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-               block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+
+               xfs_btree_init_block(mp, bp, XFS_IBT_MAGIC, 0, 0, 0);
+
                error = xfs_bwrite(bp);
                xfs_buf_relse(bp);
                if (error)
@@ -399,9 +430,26 @@ xfs_growfs_data_private(
 
        /* update secondary superblocks. */
        for (agno = 1; agno < nagcount; agno++) {
-               error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
+               error = 0;
+               /*
+                * new secondary superblocks need to be zeroed, not read from
+                * disk as the contents of the new area we are growing into is
+                * completely unknown.
+                */
+               if (agno < oagcount) {
+                       error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
+                                 XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
+                                 XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
+               } else {
+                       bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp,
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
-                                 XFS_FSS_TO_BB(mp, 1), 0, &bp);
+                                 XFS_FSS_TO_BB(mp, 1), 0);
+                       if (bp)
+                               xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
+                       else
+                               error = ENOMEM;
+               }
+
                if (error) {
                        xfs_warn(mp,
                "error %d reading secondary superblock for ag %d",
@@ -423,7 +471,7 @@ xfs_growfs_data_private(
                        break; /* no point in continuing */
                }
        }
-       return 0;
+       return error;
 
  error0:
        xfs_trans_cancel(tp, XFS_TRANS_ABORT);