From: Chandan Babu R <chandanrli...@gmail.com>

[ Upstream commit 72cc95132a93293dcd0b6f68353f4741591c9aeb ]

The following sequence of commands,

  mkfs.xfs -f -m reflink=0 -r rtdev=/dev/loop1,size=10M /dev/loop0
  mount -o rtdev=/dev/loop1 /dev/loop0 /mnt
  xfs_growfs  /mnt

... causes the following call trace to be printed on the console,

XFS: Assertion failed: (bip->bli_flags & XFS_BLI_STALE) || 
(xfs_blft_from_flags(&bip->__bli_format) > XFS_BLFT_UNKNOWN_BUF && 
xfs_blft_from_flags(&bip->__bli_format) < XFS_BLFT_MAX_BUF), file: 
fs/xfs/xfs_buf_item.c, line: 331
Call Trace:
 xfs_buf_item_format+0x632/0x680
 ? kmem_alloc_large+0x29/0x90
 ? kmem_alloc+0x70/0x120
 ? xfs_log_commit_cil+0x132/0x940
 xfs_log_commit_cil+0x26f/0x940
 ? xfs_buf_item_init+0x1ad/0x240
 ? xfs_growfs_rt_alloc+0x1fc/0x280
 __xfs_trans_commit+0xac/0x370
 xfs_growfs_rt_alloc+0x1fc/0x280
 xfs_growfs_rt+0x1a0/0x5e0
 xfs_file_ioctl+0x3fd/0xc70
 ? selinux_file_ioctl+0x174/0x220
 ksys_ioctl+0x87/0xc0
 __x64_sys_ioctl+0x16/0x20
 do_syscall_64+0x3e/0x70
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

This occurs because the buffer being formatted has the value of
XFS_BLFT_UNKNOWN_BUF assigned to the 'type' subfield of
bip->bli_formats->blf_flags.

This commit fixes the issue by assigning one of XFS_BLFT_RTSUMMARY_BUF
and XFS_BLFT_RTBITMAP_BUF to the 'type' subfield of
bip->bli_formats->blf_flags before committing the corresponding
transaction.

Reviewed-by: Darrick J. Wong <darrick.w...@oracle.com>
Reviewed-by: Christoph Hellwig <h...@lst.de>
Signed-off-by: Chandan Babu R <chandanrli...@gmail.com>
Signed-off-by: Darrick J. Wong <darrick.w...@oracle.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 fs/xfs/xfs_rtalloc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 86994d7f7cba3..912f96a248f25 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -778,8 +778,14 @@ xfs_growfs_rt_alloc(
        struct xfs_bmbt_irec    map;            /* block map output */
        int                     nmap;           /* number of block maps */
        int                     resblks;        /* space reservation */
+       enum xfs_blft           buf_type;
        struct xfs_trans        *tp;
 
+       if (ip == mp->m_rsumip)
+               buf_type = XFS_BLFT_RTSUMMARY_BUF;
+       else
+               buf_type = XFS_BLFT_RTBITMAP_BUF;
+
        /*
         * Allocate space to the file, as necessary.
         */
@@ -841,6 +847,8 @@ xfs_growfs_rt_alloc(
                                        mp->m_bsize, 0, &bp);
                        if (error)
                                goto out_trans_cancel;
+
+                       xfs_trans_buf_set_type(tp, bp, buf_type);
                        memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
                        xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
                        /*
-- 
2.27.0



Reply via email to