xfs: prevent xfs_bmapi_write() to exceed maximum extent size. When trying to do preallocation that exceed the the maximum size of an extent, the extsize alignment can exceed the MAXEXTLEN. We are already solving this issue for delay allocation but we have the same with prealloc. So the Solution is to limit the bma.length we send to xfs_bmapi_allocate() in xfs_bmapi_write(). We do have a simple test case to confirm that the problem exist. # mkfs.xfs -f -b size=512 -d agcount=1,size=4294967296 /dev/sdb1 meta-data="" isize=256 agcount=1, agsize=8388608 blks = sectsz=512 attr=2, projid32bit=0 data = "" blocks=8388608, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 log =internal log bsize=512 blocks=20480, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # mount /dev/sdb1 /xfs_dir # cd /xfs_dir/ # xfs_io -c 'extsize 4m' . # xfs_io -f -c 'resvsp 0 1g' test_file XFS_IOC_RESVSP64: No space left on device Signed-off-by: Alain Renaud <arenaud@xxxxxxx> --- This is the 3rd version of the patch. In the previous version we were making the change in xfs_bmap_extsize_align() but like Dave mention we were breaking the function definition. Limiting the length in xfs_bmapi_write() seem more logical and should avoid any unexpected side effect. fs/xfs/xfs_bmap.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) Index: b/fs/xfs/xfs_bmap.c =================================================================== --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4915,22 +4915,27 @@ xfs_bmapi_write( * that we found, if any. */ if (inhole || wasdelay) { + xfs_extlen_t extsz; bma.eof = eof; bma.conv = !!(flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.offset = bno; - /* - * There's a 32/64 bit type mismatch between the - * allocation length request (which can be 64 bits in - * length) and the bma length request, which is - * xfs_extlen_t and therefore 32 bits. Hence we have to - * check for 32-bit overflows and handle them here. - */ - if (len > (xfs_filblks_t)MAXEXTLEN) - bma.length = MAXEXTLEN; - else - bma.length = len; + /* Figure out the extent size, set bma.length */ + extsz = xfs_get_extsz_hint(ip); + if (extsz) { + /* + * Make sure we don't exceed the maximum extent + * length when we align the extent. Reduce the + * length we are going to allocate by the + * maximum adjustment extent size aligment may + * require. + */ + bma.length = XFS_FILBLKS_MIN(len, + MAXEXTLEN - (2 * extsz - 1)); + } else { + bma.length = XFS_FILBLKS_MIN(len, MAXEXTLEN); + } ASSERT(len > 0); ASSERT(bma.length > 0); Alain Renaud |
When trying to do preallocation that exceed the the maximum size of an extent, the extsize alignment can exceed the MAXEXTLEN. We are already solving this issue for delay allocation but we have the same with prealloc. So the Solution is to limit the bma.length we send to xfs_bmapi_allocate() in xfs_bmapi_write(). We do have a simple test case to confirm that the problem exist. # mkfs.xfs -f -b size=512 -d agcount=1,size=4294967296 /dev/sdb1 meta-data=/dev/sdb1 isize=256 agcount=1, agsize=8388608 blks = sectsz=512 attr=2, projid32bit=0 data = bsize=512 blocks=8388608, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 log =internal log bsize=512 blocks=20480, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # mount /dev/sdb1 /xfs_dir # cd /xfs_dir/ # xfs_io -c 'extsize 4m' . # xfs_io -f -c 'resvsp 0 1g' test_file XFS_IOC_RESVSP64: No space left on device Signed-off-by: Alain Renaud <arenaud@xxxxxxx> --- This is the 3rd version of the patch. In the previous version we were making the change in xfs_bmap_extsize_align() but like Dave mention we were breaking the function definition. Limiting the length in xfs_bmapi_write() seem more logical and should avoid any unexpected side effect. fs/xfs/xfs_bmap.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) Index: b/fs/xfs/xfs_bmap.c =================================================================== --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4915,22 +4915,27 @@ xfs_bmapi_write( * that we found, if any. */ if (inhole || wasdelay) { + xfs_extlen_t extsz; bma.eof = eof; bma.conv = !!(flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.offset = bno; - /* - * There's a 32/64 bit type mismatch between the - * allocation length request (which can be 64 bits in - * length) and the bma length request, which is - * xfs_extlen_t and therefore 32 bits. Hence we have to - * check for 32-bit overflows and handle them here. - */ - if (len > (xfs_filblks_t)MAXEXTLEN) - bma.length = MAXEXTLEN; - else - bma.length = len; + /* Figure out the extent size, set bma.length */ + extsz = xfs_get_extsz_hint(ip); + if (extsz) { + /* + * Make sure we don't exceed the maximum extent + * length when we align the extent. Reduce the + * length we are going to allocate by the + * maximum adjustment extent size aligment may + * require. + */ + bma.length = XFS_FILBLKS_MIN(len, + MAXEXTLEN - (2 * extsz - 1)); + } else { + bma.length = XFS_FILBLKS_MIN(len, MAXEXTLEN); + } ASSERT(len > 0); ASSERT(bma.length > 0);
_______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs