ocfs2: Add validate function for slot map blocks
Subsystems (2)
PATCH v3 1/1 ocfs2: Add validate function for slot map blocks
When the filesystem is being mounted, the kernel panics while the data regarding slot map allocation to the local node, is being written to the disk. This occurs because the value of slot map buffer head block number, which should have been greater than or equal to OCFS2_SUPER_BLOCK_BLKNO (evaluating to 2) is less than it, indicative of disk metadata corruption. This triggers BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO) in ocfs2_write_block(), causing the kernel to panic.
This is fixed by introducing function ocfs2_validate_slot_map_block() to validate slot map blocks. It first checks if the buffer head passed to it is up to date and valid, else it panics the kernel at that point itself. Further, it contains an if condition block, which checks if bh->b_blocknr is lesser than OCFS2_SUPER_BLOCK_BLKNO; if yes, then ocfs2_error is called, which prints the error log, for debugging purposes, and the return value of ocfs2_error() is returned. If the return value is zero. then error code EIO is returned.
This function is used as validate function in calls to ocfs2_read_blocks() in ocfs2_refresh_slot_info() and ocfs2_map_slot_buffers().
In addition, the function also contains
---v2->v3:
- Create new function ocfs2_validate_slot_map_block() to validate block number of slot map blocks, to be greater then or equal to OCFS2_SUPER_BLOCK_BLKNO
- Use ocfs2_validate_slot_map_block() in calls to ocfs2_read_blocks() in ocfs2_refresh_slot_info() and ocfs2_map_slot_buffers()
- In addition to using previously formulated if block in ocfs2_validate_slot_map_block(), also check if the buffer head passed in this function is up to date; if not, then kernel panics at that point
- Change title of patch to 'ocfs2: Add validate function for slot map blocks'
v1->v2:
- Remove usage of le16_to_cpu() from ocfs2_error()
- Cast bh->b_blocknr to unsigned long long
- Remove type casting for OCFS2_SUPER_BLOCK_BLKNO
- Fix Sparse warnings reported in v1 by kernel test robot
- Update title from 'ocfs2: Fix kernel BUG in ocfs2_write_block' to 'ocfs2: fix kernel BUG in ocfs2_write_block'
v1 link: https://lore.kernel.org/all/[email protected]/T/
fs/ocfs2/slot_map.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
fs/ocfs2/slot_map.c +27 -2
@@ -44,6 +44,9 @@ struct ocfs2_slot_info {static int __ocfs2_node_num_to_slot (struct ocfs2_slot_info *si,unsigned int node_num); +static int ocfs2_validate_slot_map_block (struct super_block *sb, +struct buffer_head *bh); +static void ocfs2_invalidate_slot (struct ocfs2_slot_info *si,int slot_num) {
@@ -132,7 +135,8 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)* this is not true, the read of -1 (UINT64_MAX) will fail. */ ret =ocfs2_read_blocks (INODE_CACHE (si->si_inode),-1 , si->si_blocks, - si->si_bh,OCFS2_BH_IGNORE_CACHE ,NULL ); + si->si_bh,OCFS2_BH_IGNORE_CACHE , + ocfs2_validate_slot_map_block);if (ret ==0 ) {spin_lock (&osb->osb_lock);ocfs2_update_slot_info (si);
@@ -332,6 +336,26 @@ int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)return ocfs2_update_disk_slot (osb, osb->slot_info, slot_num); } +static int ocfs2_validate_slot_map_block (struct super_block *sb, +struct buffer_head *bh) +{ +int rc; + +BUG_ON (!buffer_uptodate (bh)); + +if (bh->b_blocknr <OCFS2_SUPER_BLOCK_BLKNO ) { + rc =ocfs2_error (sb, +"Invalid Slot Map Buffer Head " +"Block Number : %llu, Should be >= %d" , + (unsigned long long )bh->b_blocknr, +OCFS2_SUPER_BLOCK_BLKNO ); +if (!rc) +return -EIO ; +return rc; + } +return 0 ; +} +static int ocfs2_map_slot_buffers (struct ocfs2_super *osb,struct ocfs2_slot_info *si) {
@@ -383,7 +407,8 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, bh =NULL ;/* Acquire a fresh bh */ status =ocfs2_read_blocks (INODE_CACHE (si->si_inode), blkno, -1 , &bh,OCFS2_BH_IGNORE_CACHE ,NULL ); +1 , &bh,OCFS2_BH_IGNORE_CACHE , + ocfs2_validate_slot_map_block);if (status <0 ) {mlog_errno (status); goto bail;
base-commit: 24172e0d79900908cf5ebf366600616d29c9b417
Signature · 1 line
2.43.0
Heming Zhao
reviewerQuoted 18 lines · Prithvi Tambewagh
When the filesystem is being mounted, the kernel panics while the data regarding slot map allocation to the local node, is being written to the disk. This occurs because the value of slot map buffer head block number, which should have been greater than or equal to
OCFS2_SUPER_BLOCK_BLKNO(evaluating to 2) is less than it, indicative of disk metadata corruption. This triggersBUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO)inocfs2_write_block(), causing the kernel to panic.This is fixed by introducing function
ocfs2_validate_slot_map_block()to validate slot map blocks. It first checks if the buffer head passed to it is up to date and valid, else it panics the kernel at that point itself. Further, it contains an if condition block, which checks ifbh->b_blocknris lesser thanOCFS2_SUPER_BLOCK_BLKNO; if yes, thenocfs2_erroris called, which prints the error log, for debugging purposes, and the return value ofocfs2_error()is returned. If the return value is zero. then error code EIO is returned.
Quoted 3 lines
This function is used as validate function in calls to
ocfs2_read_blocks()inocfs2_refresh_slot_info()andocfs2_map_slot_buffers().
In addition, the function also contains
The last sentence seems incomplete.
Quoted 65 lines
Reported-by [email protected]Tested-by [email protected]Signed-off-by Prithvi Tambewagh <[email protected]>---
v2->v3:
- Create new functionocfs2_validate_slot_map_block()to validate block number of slot map blocks, to be greater then or equal toOCFS2_SUPER_BLOCK_BLKNO
- Useocfs2_validate_slot_map_block()in calls toocfs2_read_blocks()inocfs2_refresh_slot_info()andocfs2_map_slot_buffers()
- In addition to using previously formulated if block inocfs2_validate_slot_map_block(), also check if the buffer head passed in this function is up to date; if not, then kernel panics at that point
- Change title of patch to 'ocfs2: Add validate function for slot map blocks'
v1->v2:
- Remove usage ofle16_to_cpu()fromocfs2_error()
- Castbh->b_blocknrto unsigned long long
- Remove type casting forOCFS2_SUPER_BLOCK_BLKNO
- Fix Sparse warnings reported in v1 by kernel test robot
- Update title from 'ocfs2: Fix kernel BUG inocfs2_write_block' to 'ocfs2: fix kernel BUG inocfs2_write_block'v1 link: https://lore.kernel.org/all/[email protected]/T/
fs/ocfs2/slot_map.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)fs/ocfs2/slot_map.c +10
-1@@ -44,6 +44,9 @@ struct ocfs2_slot_info {static int __ocfs2_node_num_to_slot (struct ocfs2_slot_info *si,unsigned int node_num); +static int ocfs2_validate_slot_map_block (struct super_block *sb, +struct buffer_head *bh); +static void ocfs2_invalidate_slot (struct ocfs2_slot_info *si,int slot_num) {@@ -132,7 +135,8 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)* this is not true, the read of -1 (UINT64_MAX) will fail. */ ret =ocfs2_read_blocks (INODE_CACHE (si->si_inode),-1 , si->si_blocks, - si->si_bh,OCFS2_BH_IGNORE_CACHE ,NULL ); + si->si_bh,OCFS2_BH_IGNORE_CACHE , + ocfs2_validate_slot_map_block);if (ret ==0 ) {spin_lock (&osb->osb_lock);ocfs2_update_slot_info (si);@@ -332,6 +336,26 @@ int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)return ocfs2_update_disk_slot (osb, osb->slot_info, slot_num); } +static int ocfs2_validate_slot_map_block (struct super_block *sb, +struct buffer_head *bh) +{ +int rc; +
fs/ocfs2/slot_map.c int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) · line 353
Quoted 10 lines
fs/ocfs2/slot_map.c +10
-0+BUG_ON (!buffer_uptodate (bh)); + +if (bh->b_blocknr <OCFS2_SUPER_BLOCK_BLKNO ) { + rc =ocfs2_error (sb, +"Invalid Slot Map Buffer Head " +"Block Number : %llu, Should be >= %d" , + (unsigned long long )bh->b_blocknr, +OCFS2_SUPER_BLOCK_BLKNO ); +if (!rc) +return -EIO ;
Since ocfs2_error() never returns 0, please remove the above if condition.
Thanks,
Heming
Quoted 23 lines
fs/ocfs2/slot_map.c +7
-1+return rc; + } +return 0 ; +} +static int ocfs2_map_slot_buffers (struct ocfs2_super *osb,struct ocfs2_slot_info *si) {@@ -383,7 +407,8 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, bh =NULL ;/* Acquire a fresh bh */ status =ocfs2_read_blocks (INODE_CACHE (si->si_inode), blkno, -1 , &bh,OCFS2_BH_IGNORE_CACHE ,NULL ); +1 , &bh,OCFS2_BH_IGNORE_CACHE , + ocfs2_validate_slot_map_block);if (status <0 ) {mlog_errno (status); goto bail;base-commit:
24172e0d79900908cf5ebf366600616d29c9b417Signature · 1 line
2.43.0
Quoted 124 lines · Heming Zhao
Quoted 18 lines · Prithvi Tambewagh
When the filesystem is being mounted, the kernel panics while the data regarding slot map allocation to the local node, is being written to the disk. This occurs because the value of slot map buffer head block number, which should have been greater than or equal to
OCFS2_SUPER_BLOCK_BLKNO(evaluating to 2) is less than it, indicative of disk metadata corruption. This triggersBUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO)inocfs2_write_block(), causing the kernel to panic.This is fixed by introducing function
ocfs2_validate_slot_map_block()to validate slot map blocks. It first checks if the buffer head passed to it is up to date and valid, else it panics the kernel at that point itself. Further, it contains an if condition block, which checks ifbh->b_blocknris lesser thanOCFS2_SUPER_BLOCK_BLKNO; if yes, thenocfs2_erroris called, which prints the error log, for debugging purposes, and the return value ofocfs2_error()is returned. If the return value is zero. then error code EIO is returned.Quoted 3 lines
This function is used as validate function in calls to
ocfs2_read_blocks()inocfs2_refresh_slot_info()andocfs2_map_slot_buffers().
In addition, the function also containsThe last sentence seems incomplete.
Quoted 65 lines
Reported-by [email protected]Tested-by [email protected]Signed-off-by Prithvi Tambewagh <[email protected]>---
v2->v3:
- Create new functionocfs2_validate_slot_map_block()to validate block number of slot map blocks, to be greater then or equal toOCFS2_SUPER_BLOCK_BLKNO
- Useocfs2_validate_slot_map_block()in calls toocfs2_read_blocks()inocfs2_refresh_slot_info()andocfs2_map_slot_buffers()
- In addition to using previously formulated if block inocfs2_validate_slot_map_block(), also check if the buffer head passed in this function is up to date; if not, then kernel panics at that point
- Change title of patch to 'ocfs2: Add validate function for slot map blocks'
v1->v2:
- Remove usage ofle16_to_cpu()fromocfs2_error()
- Castbh->b_blocknrto unsigned long long
- Remove type casting forOCFS2_SUPER_BLOCK_BLKNO
- Fix Sparse warnings reported in v1 by kernel test robot
- Update title from 'ocfs2: Fix kernel BUG inocfs2_write_block' to 'ocfs2: fix kernel BUG inocfs2_write_block'v1 link: https://lore.kernel.org/all/[email protected]/T/
fs/ocfs2/slot_map.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)fs/ocfs2/slot_map.c +10
-1@@ -44,6 +44,9 @@ struct ocfs2_slot_info {static int __ocfs2_node_num_to_slot (struct ocfs2_slot_info *si,unsigned int node_num); +static int ocfs2_validate_slot_map_block (struct super_block *sb, +struct buffer_head *bh); +static void ocfs2_invalidate_slot (struct ocfs2_slot_info *si,int slot_num) {@@ -132,7 +135,8 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)* this is not true, the read of -1 (UINT64_MAX) will fail. */ ret =ocfs2_read_blocks (INODE_CACHE (si->si_inode),-1 , si->si_blocks, - si->si_bh,OCFS2_BH_IGNORE_CACHE ,NULL ); + si->si_bh,OCFS2_BH_IGNORE_CACHE , + ocfs2_validate_slot_map_block);if (ret ==0 ) {spin_lock (&osb->osb_lock);ocfs2_update_slot_info (si);@@ -332,6 +336,26 @@ int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)return ocfs2_update_disk_slot (osb, osb->slot_info, slot_num); } +static int ocfs2_validate_slot_map_block (struct super_block *sb, +struct buffer_head *bh) +{ +int rc; +fs/ocfs2/slot_map.c int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) · line 353
Quoted 10 lines
fs/ocfs2/slot_map.c +10
-0+BUG_ON (!buffer_uptodate (bh)); + +if (bh->b_blocknr <OCFS2_SUPER_BLOCK_BLKNO ) { + rc =ocfs2_error (sb, +"Invalid Slot Map Buffer Head " +"Block Number : %llu, Should be >= %d" , + (unsigned long long )bh->b_blocknr, +OCFS2_SUPER_BLOCK_BLKNO ); +if (!rc) +return -EIO ;Since
ocfs2_error()never returns 0, please remove the above if condition.Thanks,
HemingQuoted 19 lines
fs/ocfs2/slot_map.c +7
-1+return rc; + } +return 0 ; +} +static int ocfs2_map_slot_buffers (struct ocfs2_super *osb,struct ocfs2_slot_info *si) {@@ -383,7 +407,8 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, bh =NULL ;/* Acquire a fresh bh */ status =ocfs2_read_blocks (INODE_CACHE (si->si_inode), blkno, -1 , &bh,OCFS2_BH_IGNORE_CACHE ,NULL ); +1 , &bh,OCFS2_BH_IGNORE_CACHE , + ocfs2_validate_slot_map_block);if (status <0 ) {mlog_errno (status); goto bail;
Quoted 4 lines
Quoted 4 lines
base-commit:
24172e0d79900908cf5ebf366600616d29c9b417Signature · 1 line
2.43.0
Sure, I will make the corrections and send a v4 patch.
Thanks,
Prithvi