diff mbox

ext4: Try to initialize all groups we can in case of failure on ppc64

Message ID 1432722326-25574-1-git-send-email-lczerner@redhat.com
State Superseded, archived
Headers show

Commit Message

Lukas Czerner May 27, 2015, 10:25 a.m. UTC
Currently on the machines with page size > block size when initializing
block group buddy cache we initialize it for all the block group bitmaps
in the page. However in the case of read error, checksum error, or if
a single bitmap is in any way corrupted we would fail to initialize all
of the bitmaps. This is problematic because we will not have access to
the other allocation groups even though those might be perfectly fine
and usable.

Fix this by reading all the bitmaps instead of error out on the first
problem and simply skip the bitmaps which were either not read properly,
or are not valid.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
---
 fs/ext4/mballoc.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Comments

Eric Sandeen May 27, 2015, 3:44 p.m. UTC | #1
On 5/27/15 5:25 AM, Lukas Czerner wrote:
> Currently on the machines with page size > block size when initializing
> block group buddy cache we initialize it for all the block group bitmaps
> in the page. However in the case of read error, checksum error, or if
> a single bitmap is in any way corrupted we would fail to initialize all
> of the bitmaps. This is problematic because we will not have access to
> the other allocation groups even though those might be perfectly fine
> and usable.
> 
> Fix this by reading all the bitmaps instead of error out on the first
> problem and simply skip the bitmaps which were either not read properly,
> or are not valid.
> 
> Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> ---
>  fs/ext4/mballoc.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index 8d1e602..7e28007 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -882,10 +882,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
>  
>  	/* wait for I/O completion */
>  	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
> -		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i])) {
> +		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i]))
>  			err = -EIO;
> -			goto out;
> -		}
>  	}
>  
>  	first_block = page->index * blocks_per_page;
> @@ -898,6 +896,13 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
>  			/* skip initialized uptodate buddy */
>  			continue;
>  
> +		if (!buffer_verified(bh[group - first_group]) ||
> +		    !buffer_uptodate(bh[group - first_group]))
> +			/* Skip faulty bitmaps */
> +			continue;
> +		else
> +			err = 0;
> +

Hm, ext4_wait_block_bitmap() can fail 3 ways (buffer not update, or not verified,
but also if ext4_get_group_desc fails), but this only checks 2 of those, right?

If ext4_get_group_desc fails, we'll have a bh which is new, may or may not be
uptodate, and ... I guess it won't be verified in that case either, will it.  So
that's probably ok.

In fact, is the (!verified) test enough, here? (IOWs, could it possibly be verified,
but not uptodate?) 


In the bigger picture - if the filesystem is corrupt (or the device is bad) in this
way, do we really *want* to continue?  What are the consequences of doing so,
and have you tested with a filesystem partially-initialized like this?

Thinking more about it ... (sorry for the stream of consciousness here) - if validation
fails, encountering this sort of error will trigger remount,ro or panic unless
errors=continue, right?  But I guess that's still the default, so maybe we do expect
to continue.  So I go back to the question of: have you tested with partial init
like this, to be sure we don't fall off some cliff later?

Thanks,
-Eric
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andreas Dilger May 27, 2015, 8:07 p.m. UTC | #2
On May 27, 2015, at 9:44 AM, Eric Sandeen <sandeen@redhat.com> wrote:
> 
> On 5/27/15 5:25 AM, Lukas Czerner wrote:
>> Currently on the machines with page size > block size when initializing
>> block group buddy cache we initialize it for all the block group bitmaps
>> in the page. However in the case of read error, checksum error, or if
>> a single bitmap is in any way corrupted we would fail to initialize all
>> of the bitmaps. This is problematic because we will not have access to
>> the other allocation groups even though those might be perfectly fine
>> and usable.
>> 
>> Fix this by reading all the bitmaps instead of error out on the first
>> problem and simply skip the bitmaps which were either not read properly,
>> or are not valid.
>> 
>> Signed-off-by: Lukas Czerner <lczerner@redhat.com>
>> ---
>> fs/ext4/mballoc.c | 11 ++++++++---
>> 1 file changed, 8 insertions(+), 3 deletions(-)
>> 
>> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
>> index 8d1e602..7e28007 100644
>> --- a/fs/ext4/mballoc.c
>> +++ b/fs/ext4/mballoc.c
>> @@ -882,10 +882,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
>> 
>> 	/* wait for I/O completion */
>> 	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
>> -		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i])) {
>> +		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i]))
>> 			err = -EIO;
>> -			goto out;
>> -		}
>> 	}
>> 
>> 	first_block = page->index * blocks_per_page;
>> @@ -898,6 +896,13 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
>> 			/* skip initialized uptodate buddy */
>> 			continue;
>> 
>> +		if (!buffer_verified(bh[group - first_group]) ||
>> +		    !buffer_uptodate(bh[group - first_group]))
>> +			/* Skip faulty bitmaps */
>> +			continue;
>> +		else
>> +			err = 0;
>> +
> 
> Hm, ext4_wait_block_bitmap() can fail 3 ways (buffer not update, or
> not verified, but also if ext4_get_group_desc fails), but this only
> checks 2 of those, right?
> 
> If ext4_get_group_desc fails, we'll have a bh which is new, may or
> may not be uptodate, and ... I guess it won't be verified in that
> case either, will it.  So that's probably ok.
> 
> In fact, is the (!verified) test enough, here? (IOWs, could it
> possibly be verified, but not uptodate?) 
> 
> 
> In the bigger picture - if the filesystem is corrupt (or the device
> is bad) in this way, do we really *want* to continue?  What are the
> consequences of doing so, and have you tested with a filesystem
> partially-initialized like this?
> 
> Thinking more about it ... (sorry for the stream of consciousness
> here) - if validation fails, encountering this sort of error will
> trigger remount,ro or panic unless errors=continue, right?  But I
> guess that's still the default, so maybe we do expect to continue.
> So I go back to the question of: have you tested with partial init
> like this, to be sure we don't fall off some cliff later?

There is also the check in ext4_validate_block_bitmap() that will
fail if the bitmap is bad in some way.  At least that is marking
the bitmap bad in the group descriptor so that it is skipped for
later allocations.  Probably the same needs to be done here.

It also makes sense to fail the mount outright if too many of the
bitmaps are bad, or only mount it read-only, since it will otherwise
be unusable.

Cheers, Andreas





--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 8d1e602..7e28007 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -882,10 +882,8 @@  static int ext4_mb_init_cache(struct page *page, char *incore)
 
 	/* wait for I/O completion */
 	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
-		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i])) {
+		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i]))
 			err = -EIO;
-			goto out;
-		}
 	}
 
 	first_block = page->index * blocks_per_page;
@@ -898,6 +896,13 @@  static int ext4_mb_init_cache(struct page *page, char *incore)
 			/* skip initialized uptodate buddy */
 			continue;
 
+		if (!buffer_verified(bh[group - first_group]) ||
+		    !buffer_uptodate(bh[group - first_group]))
+			/* Skip faulty bitmaps */
+			continue;
+		else
+			err = 0;
+
 		/*
 		 * data carry information regarding this
 		 * particular group in the format specified