diff mbox series

[RFC,1/1] libocfs2: fix non-zero value in Next Leaf field in the rightmost leaf metadata block

Message ID 20241015161109.156497-1-gautham.ananthakrishna@oracle.com (mailing list archive)
State New
Headers show
Series [RFC,1/1] libocfs2: fix non-zero value in Next Leaf field in the rightmost leaf metadata block | expand

Commit Message

Gautham Ananthakrishna Oct. 15, 2024, 4:11 p.m. UTC
One of our customers reported read-only filesystem. fsck.ocfs2 -ny showed the
following issue:
Pass 1: Checking inodes and blocks
[EXTENT_LIST_FREE] Extent list in owner 658435 claims 231 as the next free chain record, but fsck believes the largest valid value is 227.  Clamp the next record value? n

debugfs.ocfs2 also showed the corruption:

        Inode: 658435   Mode: 0644   Generation: 974589382 (0x3a170dc6)
        FS Generation: 432631804 (0x19c96ffc)
        CRC32: 00000000   ECC: 0000
        Type: Regular   Attr: 0x0   Flags: Valid
        Dynamic Features: (0x0)
        User: 0 (root)   Group: 0 (root)   Size: 121633767424
        Links: 1   Clusters: 14848000
        ctime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
        atime: 0x66fa5e5d 0x34514ed8 -- Mon Sep 30 08:16:29.877743832 2024
        mtime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
        dtime: 0x0 -- Thu Jan  1 00:00:00 1970
        Refcount Block: 0
        Last Extblk: 539186   Orphan Slot: 0
        Sub Alloc Slot: 0   Sub Alloc Bit: 2
        Tree Depth: 1   Count: 227   Next Free Rec: 231
        ## Offset        Clusters       Block#
        0  0             129024         525859
        1  129024        129024         526883

The "Next Free Rec" had overshoot the "Count".

Upon running fsck.ocfs2 -fy, the fsck managed to fix only the
root metadata block and updated it with a new "Last Extblk"

        Inode: 658435   Mode: 0644   Generation: 974589382 (0x3a170dc6)
        FS Generation: 432631804 (0x19c96ffc)
        CRC32: 00000000   ECC: 0000
        Type: Regular   Attr: 0x0   Flags: Valid
        Dynamic Features: (0x0)
        User: 0 (root)   Group: 0 (root)   Size: 121633767424
        Links: 1   Clusters: 14644224
        ctime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
        atime: 0x66fa5e5d 0x34514ed8 -- Mon Sep 30 08:16:29.877743832 2024
        mtime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
        dtime: 0x0 -- Thu Jan  1 00:00:00 1970
        Refcount Block: 0
        Last Extblk: 535090   Orphan Slot: 0
        Sub Alloc Slot: 0   Sub Alloc Bit: 2
        Tree Depth: 1   Count: 227   Next Free Rec: 227
        ## Offset        Clusters       Block#
        0  0             129024         525859
        1  129024        129024         526883
        2  258048        129024         536099

However fsck.ocfs2 did not set "Next Leaf" to zero in the updated "Last Extblk".

        SubAlloc Bit: 16   SubAlloc Slot: 0
        Blknum: 535090   Next Leaf: 536114
        CRC32: 00000000   ECC: 0000
        Tree Depth: 0   Count: 252   Next Free Rec: 252
        ## Offset        Clusters       Block#          Flags
        0  29159424      256            7845889         0x0
        1  29159936      256            7846145         0x0

This patch addresses this issue by checking the last leaf metadata block
and setting "Next Leaf" to zero if not done.

Signed-off-by: Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com>
---
 libocfs2/extents.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Comments

Joseph Qi Oct. 16, 2024, 1:51 a.m. UTC | #1
Hi,

This is patch for ocfs2-tools, so please submit a pull request in
ocfs2-tools github repo.

Thanks,
Joseph

On 10/16/24 12:11 AM, Gautham Ananthakrishna wrote:
> One of our customers reported read-only filesystem. fsck.ocfs2 -ny showed the
> following issue:
> Pass 1: Checking inodes and blocks
> [EXTENT_LIST_FREE] Extent list in owner 658435 claims 231 as the next free chain record, but fsck believes the largest valid value is 227.  Clamp the next record value? n
> 
> debugfs.ocfs2 also showed the corruption:
> 
>         Inode: 658435   Mode: 0644   Generation: 974589382 (0x3a170dc6)
>         FS Generation: 432631804 (0x19c96ffc)
>         CRC32: 00000000   ECC: 0000
>         Type: Regular   Attr: 0x0   Flags: Valid
>         Dynamic Features: (0x0)
>         User: 0 (root)   Group: 0 (root)   Size: 121633767424
>         Links: 1   Clusters: 14848000
>         ctime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         atime: 0x66fa5e5d 0x34514ed8 -- Mon Sep 30 08:16:29.877743832 2024
>         mtime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         dtime: 0x0 -- Thu Jan  1 00:00:00 1970
>         Refcount Block: 0
>         Last Extblk: 539186   Orphan Slot: 0
>         Sub Alloc Slot: 0   Sub Alloc Bit: 2
>         Tree Depth: 1   Count: 227   Next Free Rec: 231
>         ## Offset        Clusters       Block#
>         0  0             129024         525859
>         1  129024        129024         526883
> 
> The "Next Free Rec" had overshoot the "Count".
> 
> Upon running fsck.ocfs2 -fy, the fsck managed to fix only the
> root metadata block and updated it with a new "Last Extblk"
> 
>         Inode: 658435   Mode: 0644   Generation: 974589382 (0x3a170dc6)
>         FS Generation: 432631804 (0x19c96ffc)
>         CRC32: 00000000   ECC: 0000
>         Type: Regular   Attr: 0x0   Flags: Valid
>         Dynamic Features: (0x0)
>         User: 0 (root)   Group: 0 (root)   Size: 121633767424
>         Links: 1   Clusters: 14644224
>         ctime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         atime: 0x66fa5e5d 0x34514ed8 -- Mon Sep 30 08:16:29.877743832 2024
>         mtime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         dtime: 0x0 -- Thu Jan  1 00:00:00 1970
>         Refcount Block: 0
>         Last Extblk: 535090   Orphan Slot: 0
>         Sub Alloc Slot: 0   Sub Alloc Bit: 2
>         Tree Depth: 1   Count: 227   Next Free Rec: 227
>         ## Offset        Clusters       Block#
>         0  0             129024         525859
>         1  129024        129024         526883
>         2  258048        129024         536099
> 
> However fsck.ocfs2 did not set "Next Leaf" to zero in the updated "Last Extblk".
> 
>         SubAlloc Bit: 16   SubAlloc Slot: 0
>         Blknum: 535090   Next Leaf: 536114
>         CRC32: 00000000   ECC: 0000
>         Tree Depth: 0   Count: 252   Next Free Rec: 252
>         ## Offset        Clusters       Block#          Flags
>         0  29159424      256            7845889         0x0
>         1  29159936      256            7846145         0x0
> 
> This patch addresses this issue by checking the last leaf metadata block
> and setting "Next Leaf" to zero if not done.
> 
> Signed-off-by: Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com>
> ---
>  libocfs2/extents.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/libocfs2/extents.c b/libocfs2/extents.c
> index d72ae66..c2a3a88 100644
> --- a/libocfs2/extents.c
> +++ b/libocfs2/extents.c
> @@ -277,6 +277,7 @@ static int extent_iterate_el(struct ocfs2_extent_list *el,
>  				if (el->l_tree_depth == 1)
>  					ctxt->last_eb_blkno =
>  							el->l_recs[i].e_blkno;
> +
>  				ctxt->last_eb_cpos = el->l_recs[i].e_cpos;
>  			}
>  
> @@ -478,6 +479,7 @@ errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
>  	struct ocfs2_extent_list *el;
>  	errcode_t ret;
>  	struct extent_context ctxt;
> +	struct ocfs2_extent_block *eb;
>  
>  	ret = OCFS2_ET_INODE_NOT_VALID;
>  	if (!(inode->i_flags & OCFS2_VALID_FL))
> @@ -543,6 +545,26 @@ out_abort:
>  	if (!ret && (iret & OCFS2_EXTENT_CHANGED))
>  		ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);
>  
> +	/*
> +	 * Check i_last_eb_blk and set
> +	 * its next leaf to zero.
> +	 */
> +	if (!ret && el->l_tree_depth) {
> +		ctxt.errcode = ocfs2_read_extent_block(fs,
> +					inode->i_last_eb_blk,
> +					ctxt.eb_bufs[0]);
> +
> +		eb = (struct ocfs2_extent_block *)ctxt.eb_bufs[0];
> +
> +		if (!ctxt.errcode && eb->h_next_leaf_blk != 0) {
> +			eb->h_next_leaf_blk = 0;
> +			ctxt.errcode = ocfs2_write_extent_block(fs,
> +						inode->i_last_eb_blk,
> +						ctxt.eb_bufs[0]);
> +		}
> +		ret = ctxt.errcode;
> +	}
> +
>  out_eb_bufs:
>  	if (ctxt.eb_bufs) {
>  		if (!block_buf && ctxt.eb_bufs[0])
Gautham Ananthakrishna Oct. 16, 2024, 5:57 a.m. UTC | #2
Thank you.

I have created a pull request https://github.com/markfasheh/ocfs2-tools/pull/68

Could you please review there.

Thanks,
Gautham.


-----Original Message-----
From: Joseph Qi <joseph.qi@linux.alibaba.com> 
Sent: Wednesday, October 16, 2024 7:22 AM
To: Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com>; ocfs2-devel@lists.linux.dev
Cc: ghe@suse.com; mark@fasheh.com
Subject: Re: [PATCH RFC 1/1] libocfs2: fix non-zero value in Next Leaf field in the rightmost leaf metadata block

Hi,

This is patch for ocfs2-tools, so please submit a pull request in ocfs2-tools github repo.

Thanks,
Joseph

On 10/16/24 12:11 AM, Gautham Ananthakrishna wrote:
> One of our customers reported read-only filesystem. fsck.ocfs2 -ny 
> showed the following issue:
> Pass 1: Checking inodes and blocks
> [EXTENT_LIST_FREE] Extent list in owner 658435 claims 231 as the next 
> free chain record, but fsck believes the largest valid value is 227.  
> Clamp the next record value? n
> 
> debugfs.ocfs2 also showed the corruption:
> 
>         Inode: 658435   Mode: 0644   Generation: 974589382 (0x3a170dc6)
>         FS Generation: 432631804 (0x19c96ffc)
>         CRC32: 00000000   ECC: 0000
>         Type: Regular   Attr: 0x0   Flags: Valid
>         Dynamic Features: (0x0)
>         User: 0 (root)   Group: 0 (root)   Size: 121633767424
>         Links: 1   Clusters: 14848000
>         ctime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         atime: 0x66fa5e5d 0x34514ed8 -- Mon Sep 30 08:16:29.877743832 2024
>         mtime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         dtime: 0x0 -- Thu Jan  1 00:00:00 1970
>         Refcount Block: 0
>         Last Extblk: 539186   Orphan Slot: 0
>         Sub Alloc Slot: 0   Sub Alloc Bit: 2
>         Tree Depth: 1   Count: 227   Next Free Rec: 231
>         ## Offset        Clusters       Block#
>         0  0             129024         525859
>         1  129024        129024         526883
> 
> The "Next Free Rec" had overshoot the "Count".
> 
> Upon running fsck.ocfs2 -fy, the fsck managed to fix only the root 
> metadata block and updated it with a new "Last Extblk"
> 
>         Inode: 658435   Mode: 0644   Generation: 974589382 (0x3a170dc6)
>         FS Generation: 432631804 (0x19c96ffc)
>         CRC32: 00000000   ECC: 0000
>         Type: Regular   Attr: 0x0   Flags: Valid
>         Dynamic Features: (0x0)
>         User: 0 (root)   Group: 0 (root)   Size: 121633767424
>         Links: 1   Clusters: 14644224
>         ctime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         atime: 0x66fa5e5d 0x34514ed8 -- Mon Sep 30 08:16:29.877743832 2024
>         mtime: 0x66fa60d8 0x343acc43 -- Mon Sep 30 08:27:04.876268611 2024
>         dtime: 0x0 -- Thu Jan  1 00:00:00 1970
>         Refcount Block: 0
>         Last Extblk: 535090   Orphan Slot: 0
>         Sub Alloc Slot: 0   Sub Alloc Bit: 2
>         Tree Depth: 1   Count: 227   Next Free Rec: 227
>         ## Offset        Clusters       Block#
>         0  0             129024         525859
>         1  129024        129024         526883
>         2  258048        129024         536099
> 
> However fsck.ocfs2 did not set "Next Leaf" to zero in the updated "Last Extblk".
> 
>         SubAlloc Bit: 16   SubAlloc Slot: 0
>         Blknum: 535090   Next Leaf: 536114
>         CRC32: 00000000   ECC: 0000
>         Tree Depth: 0   Count: 252   Next Free Rec: 252
>         ## Offset        Clusters       Block#          Flags
>         0  29159424      256            7845889         0x0
>         1  29159936      256            7846145         0x0
> 
> This patch addresses this issue by checking the last leaf metadata 
> block and setting "Next Leaf" to zero if not done.
> 
> Signed-off-by: Gautham Ananthakrishna 
> <gautham.ananthakrishna@oracle.com>
> ---
>  libocfs2/extents.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/libocfs2/extents.c b/libocfs2/extents.c index 
> d72ae66..c2a3a88 100644
> --- a/libocfs2/extents.c
> +++ b/libocfs2/extents.c
> @@ -277,6 +277,7 @@ static int extent_iterate_el(struct ocfs2_extent_list *el,
>  				if (el->l_tree_depth == 1)
>  					ctxt->last_eb_blkno =
>  							el->l_recs[i].e_blkno;
> +
>  				ctxt->last_eb_cpos = el->l_recs[i].e_cpos;
>  			}
>  
> @@ -478,6 +479,7 @@ errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
>  	struct ocfs2_extent_list *el;
>  	errcode_t ret;
>  	struct extent_context ctxt;
> +	struct ocfs2_extent_block *eb;
>  
>  	ret = OCFS2_ET_INODE_NOT_VALID;
>  	if (!(inode->i_flags & OCFS2_VALID_FL)) @@ -543,6 +545,26 @@ 
> out_abort:
>  	if (!ret && (iret & OCFS2_EXTENT_CHANGED))
>  		ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);
>  
> +	/*
> +	 * Check i_last_eb_blk and set
> +	 * its next leaf to zero.
> +	 */
> +	if (!ret && el->l_tree_depth) {
> +		ctxt.errcode = ocfs2_read_extent_block(fs,
> +					inode->i_last_eb_blk,
> +					ctxt.eb_bufs[0]);
> +
> +		eb = (struct ocfs2_extent_block *)ctxt.eb_bufs[0];
> +
> +		if (!ctxt.errcode && eb->h_next_leaf_blk != 0) {
> +			eb->h_next_leaf_blk = 0;
> +			ctxt.errcode = ocfs2_write_extent_block(fs,
> +						inode->i_last_eb_blk,
> +						ctxt.eb_bufs[0]);
> +		}
> +		ret = ctxt.errcode;
> +	}
> +
>  out_eb_bufs:
>  	if (ctxt.eb_bufs) {
>  		if (!block_buf && ctxt.eb_bufs[0])
diff mbox series

Patch

diff --git a/libocfs2/extents.c b/libocfs2/extents.c
index d72ae66..c2a3a88 100644
--- a/libocfs2/extents.c
+++ b/libocfs2/extents.c
@@ -277,6 +277,7 @@  static int extent_iterate_el(struct ocfs2_extent_list *el,
 				if (el->l_tree_depth == 1)
 					ctxt->last_eb_blkno =
 							el->l_recs[i].e_blkno;
+
 				ctxt->last_eb_cpos = el->l_recs[i].e_cpos;
 			}
 
@@ -478,6 +479,7 @@  errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
 	struct ocfs2_extent_list *el;
 	errcode_t ret;
 	struct extent_context ctxt;
+	struct ocfs2_extent_block *eb;
 
 	ret = OCFS2_ET_INODE_NOT_VALID;
 	if (!(inode->i_flags & OCFS2_VALID_FL))
@@ -543,6 +545,26 @@  out_abort:
 	if (!ret && (iret & OCFS2_EXTENT_CHANGED))
 		ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);
 
+	/*
+	 * Check i_last_eb_blk and set
+	 * its next leaf to zero.
+	 */
+	if (!ret && el->l_tree_depth) {
+		ctxt.errcode = ocfs2_read_extent_block(fs,
+					inode->i_last_eb_blk,
+					ctxt.eb_bufs[0]);
+
+		eb = (struct ocfs2_extent_block *)ctxt.eb_bufs[0];
+
+		if (!ctxt.errcode && eb->h_next_leaf_blk != 0) {
+			eb->h_next_leaf_blk = 0;
+			ctxt.errcode = ocfs2_write_extent_block(fs,
+						inode->i_last_eb_blk,
+						ctxt.eb_bufs[0]);
+		}
+		ret = ctxt.errcode;
+	}
+
 out_eb_bufs:
 	if (ctxt.eb_bufs) {
 		if (!block_buf && ctxt.eb_bufs[0])