xfsprogs/repair: fix crash on zero record finobt reconstruction
PATCH 1/1 xfsprogs/repair: fix crash on zero record finobt reconstruction
The inode btrees are reconstructed in phase 5. init_ino_cursor() helps determine the block requirements of the tree based on the number of records. If the finobt is empty, we can crash in the btree blocks calculation code due to a divide-by-zero error in the following line:
lptr->modulo = num_recs % lptr->num_blocks;
This occurs if num_recs and in-turn lptr->num_blocks evaluate to zero.
We already have an execution path for the zero record btree scenario. However, it is only invoked when no records are found in the in-core tree. The finobt zero-record scenario can occur with a populated in-core tree provided that none of the existing records contain free inodes.
Move the zero-record handling code after the loop and use the record count to trigger it. This is safe because the loop iterator checks for ino_rec != NULL. This allows reuse of the same code regardless of whether the in-core tree is empty or non-empty but contains no records that meet the requirements for the particular on-disk tree under reconstruction (e.g., finobt).
--- repair/phase5.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
repair/phase5.c +18 -17
@@ -914,26 +914,10 @@ init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, lptr = &btree_curs->level[0 ]; btree_curs->init =1 ; -if ((ino_rec =findfirst_inode_rec (agno)) ==NULL ) { -/* -* easy corner-case -- no inode records -*/ - lptr->num_blocks =1 ; - lptr->modulo =0 ; - lptr->num_recs_pb =0 ; - lptr->num_recs_tot =0 ; - - btree_curs->num_levels =1 ; - btree_curs->num_tot_blocks = btree_curs->num_free_blocks =1 ; - -setup_cursor (mp, agno, btree_curs); - -return ; - } -/* * build up statistics */ + ino_rec =findfirst_inode_rec (agno);for (num_recs =0 ; ino_rec !=NULL ; ino_rec =next_ino_rec (ino_rec)) { rec_nfinos =0 ;for (i =0 ; i <XFS_INODES_PER_CHUNK ; i++) {
@@ -953,6 +937,23 @@ init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, num_recs++; } +if (num_recs ==0 ) { +/* +* easy corner-case -- no inode records +*/ + lptr->num_blocks =1 ; + lptr->modulo =0 ; + lptr->num_recs_pb =0 ; + lptr->num_recs_tot =0 ; + + btree_curs->num_levels =1 ; + btree_curs->num_tot_blocks = btree_curs->num_free_blocks =1 ; + +setup_cursor (mp, agno, btree_curs); + +return ; + } + blocks_allocated = lptr->num_blocks =howmany (num_recs,XR_INOBT_BLOCK_MAXRECS (mp,0 ));
Signature · 6 lines
1.8.3.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs