Re: [PATCH 3/3] btrfs: disguise single-data-RAID56 as RAID1/RAID1C3

David Sterba <[email protected]>
Newsgroups gmane.linux.raid,gmane.comp.file-systems.btrfs
Message-ID <[email protected]>
On Sun, May 24, 2026 at 01:43:54PM +0930, Qu Wenruo wrote:
> I tried the idea, and it doesn't look elegant at all, we need a lot of 
> if () checks around every xor_gen()/raid6_call.
> 
> Sure the end result is not that huge (and I have only compile tested 
> it), but if we had some parameters passed wrongly, or some corner case 
> missed, it can be very hard to notice.
> 
> Just paste the adhoc fix for reference:

I ended up with something similar, but replaced the open coded ifs with
a helper so there's not that much churn at the call sites.

> diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
> index 08ee8f316d96..50fefe33bbe3 100644
> --- a/fs/btrfs/raid56.c
> +++ b/fs/btrfs/raid56.c
> @@ -1410,11 +1410,17 @@ static void generate_pq_vertical_step(struct 
> btrfs_raid_bio *rbio, unsigned int
>   				rbio_qstripe_paddr(rbio, sector_nr, step_nr));
> 
>   		assert_rbio(rbio);
> -		raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
> +		if (rbio->nr_data > 1) {
> +			raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
> +		} else {
> +			memcpy(pointers[1], pointers[0], step);
> +			memcpy(pointers[2], pointers[0], step);
> +		}
>   	} else {
>   		/* raid5 */
>   		memcpy(pointers[rbio->nr_data], pointers[0], step);
> -		xor_gen(pointers[rbio->nr_data], pointers + 1, rbio->nr_data - 1,
> +		if (rbio->nr_data > 1)
> +			xor_gen(pointers[rbio->nr_data], pointers + 1, rbio->nr_data - 1,
>   				step);
>   	}
>   	for (stripe = stripe - 1; stripe >= 0; stripe--)
> @@ -1987,11 +1993,17 @@ static void recover_vertical_step(struct 
> btrfs_raid_bio *rbio,
>   		}
> 
>   		if (failb == rbio->real_stripes - 2) {
> -			raid6_datap_recov(rbio->real_stripes, step,
> -					  faila, pointers);
> +			if (unlikely(rbio->nr_data == 1))
> +				memcpy(pointers[0], pointers[rbio->real_stripes - 1], step);
> +			else
> +				raid6_datap_recov(rbio->real_stripes, step,
> +						  faila, pointers);
>   		} else {
> -			raid6_2data_recov(rbio->real_stripes, step,
> -					  faila, failb, pointers);
> +			if (unlikely(rbio->nr_data == 1))
> +				memcpy(pointers[0], pointers[rbio->real_stripes - 2], step);

The 2data recovery needs to do 2 memcpy

> +			else
> +				raid6_2data_recov(rbio->real_stripes, step,
> +						  faila, failb, pointers);
>   		}
>   	} else {
>   		void *p;
> @@ -2002,6 +2014,9 @@ static void recover_vertical_step(struct 
> btrfs_raid_bio *rbio,
>   		/* Copy parity block into failed block to start with */
>   		memcpy(pointers[faila], pointers[rbio->nr_data], step);
> 
> +		if (rbio->nr_data == 1)
> +			goto cleanup;
> +
>   		/* Rearrange the pointer array */
>   		p = pointers[faila];
>   		for (stripe_nr = faila; stripe_nr < rbio->nr_data - 1;
> @@ -2644,11 +2659,17 @@ static bool verify_one_parity_step(struct 
> btrfs_raid_bio *rbio,
>   	if (has_qstripe) {
>   		assert_rbio(rbio);
>   		/* RAID6, call the library function to fill in our P/Q. */
> -		raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
> +		if (rbio->nr_data > 1) {
> +			raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
> +		} else {
> +			memcpy(pointers[1], pointers[0], step);
> +			memcpy(pointers[2], pointers[0], step);
> +		}
>   	} else {
>   		/* RAID5. */
>   		memcpy(pointers[nr_data], pointers[0], step);
> -		xor_gen(pointers[nr_data], pointers + 1, nr_data - 1, step);
> +		if (rbio->nr_data > 1)
> +			xor_gen(pointers[nr_data], pointers + 1, nr_data - 1, step);
>   	}
> 
>   	/* Check scrubbing parity and repair it. */
> --
> 2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.