xfs: bump INUMBERS cursor correctly in xfs_inumbers_walk
PATCH 1/1 xfs: bump INUMBERS cursor correctly in xfs_inumbers_walk
From: Darrick J. Wong <[email protected]>
There's a subtle unit conversion error when we increment the INUMBERS cursor at the end of xfs_inumbers_walk. If there's an inode chunk at the very end of the AG /and/ the AG size is a perfect power of two, that means we can have inodes, that means that the startino of that last chunk (which is in units of AG inodes) will be 63 less than (1 << agino_log). If we add XFS_INODES_PER_CHUNK to the startino, we end up with a startino that's larger than (1 << agino_log) and when we convert that back to fs inode units we'll rip off that upper bit and wind up back at the start of the AG.
Fix this by converting to units of fs inodes before adding XFS_INODES_PER_CHUNK so that we'll harmlessly end up pointing to the next AG.
--- fs/xfs/xfs_itable.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
fs/xfs/xfs_itable.c +2 -3
@@ -338,15 +338,14 @@ xfs_inumbers_walk( .xi_version = XFS_INUMBERS_VERSION_V5, };struct xfs_inumbers_chunk *ic = data; -xfs_agino_t agino;int error; error = ic->formatter (ic->breq, &inogrp);if (error && error !=XFS_IBULK_ABORT )return error; - agino = irec->ir_startino +XFS_INODES_PER_CHUNK ; - ic->breq->startino =XFS_AGINO_TO_INO (mp, agno, agino); + ic->breq->startino =XFS_AGINO_TO_INO (mp, agno, irec->ir_startino) + +XFS_INODES_PER_CHUNK ;return error; }
Quoted 6 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
There's a subtle unit conversion error when we increment the INUMBERS cursor at the end of
xfs_inumbers_walk. If there's an inode chunk at the very end of the AG /and/ the AG size is a perfect power of two, that means we can have inodes, that means that the startino of that last
"...is a perfect power of two, the startino of that last chunk..."
--D
Quoted 37 lines
chunk (which is in units of AG inodes) will be 63 less than (1 <<
agino_log). If we addXFS_INODES_PER_CHUNKto the startino, we end up with a startino that's larger than (1 <<agino_log) and when we convert that back to fs inode units we'll rip off that upper bit and wind up back at the start of the AG.Fix this by converting to units of fs inodes before adding
XFS_INODES_PER_CHUNKso that we'll harmlessly end up pointing to the next AG.Signed-off-by Darrick J. Wong <[email protected]>--- fs/xfs/xfs_itable.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)fs/xfs/xfs_itable.c +2
-3@@ -338,15 +338,14 @@ xfs_inumbers_walk( .xi_version = XFS_INUMBERS_VERSION_V5, };struct xfs_inumbers_chunk *ic = data; -xfs_agino_t agino;int error; error = ic->formatter (ic->breq, &inogrp);if (error && error !=XFS_IBULK_ABORT )return error; - agino = irec->ir_startino +XFS_INODES_PER_CHUNK ; - ic->breq->startino =XFS_AGINO_TO_INO (mp, agno, agino); + ic->breq->startino =XFS_AGINO_TO_INO (mp, agno, irec->ir_startino) + +XFS_INODES_PER_CHUNK ;return error; }
Brian Foster
Reviewed-byQuoted 10 lines · Darrick J. Wong
Quoted 6 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
There's a subtle unit conversion error when we increment the INUMBERS cursor at the end of
xfs_inumbers_walk. If there's an inode chunk at the very end of the AG /and/ the AG size is a perfect power of two, that means we can have inodes, that means that the startino of that last"...is a perfect power of two, the startino of that last chunk..."
Yeah, was going to point out this looked like some stale/spurious text... :P
Quoted 14 lines
--D
Quoted 12 lines
chunk (which is in units of AG inodes) will be 63 less than (1 <<
agino_log). If we addXFS_INODES_PER_CHUNKto the startino, we end up with a startino that's larger than (1 <<agino_log) and when we convert that back to fs inode units we'll rip off that upper bit and wind up back at the start of the AG.Fix this by converting to units of fs inodes before adding
XFS_INODES_PER_CHUNKso that we'll harmlessly end up pointing to the next AG.Signed-off-by Darrick J. Wong <[email protected]>---
Otherwise looks good:
Quoted 25 lines
Quoted 25 lines
fs/xfs/xfs_itable.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)fs/xfs/xfs_itable.c +2
-3@@ -338,15 +338,14 @@ xfs_inumbers_walk( .xi_version = XFS_INUMBERS_VERSION_V5, };struct xfs_inumbers_chunk *ic = data; -xfs_agino_t agino;int error; error = ic->formatter (ic->breq, &inogrp);if (error && error !=XFS_IBULK_ABORT )return error; - agino = irec->ir_startino +XFS_INODES_PER_CHUNK ; - ic->breq->startino =XFS_AGINO_TO_INO (mp, agno, agino); + ic->breq->startino =XFS_AGINO_TO_INO (mp, agno, irec->ir_startino) + +XFS_INODES_PER_CHUNK ;return error; }