On Wed, Sep 28, 2016 at 04:30:03PM +0800, Qu Wenruo wrote:
> Add a new function raid5_gen_result() to calculate raid5 parity or
> recover data stripe.
> 
> Since now that raid6.c handles both raid5 and raid6, rename it to
> raid56.c.

Please split changes in this patch to the following:
- rename the file
- error handling of memory allocation failures
- the actual fix

A test would be very velcome, for all the cases the code handles, 2
devices, and more. But I'm not sure if we have support for that in the
testing suite.

> @@ -107,3 +108,47 @@ void raid6_gen_syndrome(int disks, size_t bytes, void 
> **ptrs)
>       }
>  }
>  
> +static void xor_range(void *src, void *dst, size_t size)
> +{
> +     while (size) {
> +             *(unsigned long *) dst ^= *(unsigned long *) src;

This could lead to unaligned access, please update the types and
possibly add some sanity checks (alignemnt, length).

> +             src += sizeof(unsigned long);
> +             dst += sizeof(unsigned long);
> +             size -= sizeof(unsigned long);
> +     }
> +}
> +
> +/*
> + * Generate desired data/parity for RAID5
> + *
> + * @nr_devs: Total number of devices, including parity
> + * @stripe_len:      Stripe length
> + * @data:    Data, with special layout:
> + *           data[0]:         Data stripe 0
> + *           data[nr_devs-2]: Last data stripe
> + *           data[nr_devs-1]: RAID5 parity
> + * @dest:    To generate which data. should follow above data layout
> + */
> +int raid5_gen_result(int nr_devs, size_t stripe_len, int dest, void **data)
> +{
> +     int i;
> +     char *buf = data[dest];
> +
> +     if (dest >= nr_devs || nr_devs < 2) {
> +             error("invalid parameter for %s", __func__);
> +             return -EINVAL;
> +     }
> +     /* Quich hack, 2 devs RAID5 is just RAID1, no need to calculate */

This is not a hack IMO, it could be a shortcut, a special case, an
optimization.

> +     if (nr_devs == 2) {
> +             memcpy(data[dest], data[1 - dest], stripe_len);
> +             return 0;
> +     }
> +     /* Just in case */

Such comment is not very helpful.

> +     memset(buf, 0, stripe_len);
> +     for (i = 0; i < nr_devs; i++) {
> +             if (i == dest)
> +                     continue;
> +             xor_range(data[i], buf, stripe_len);
> +     }
> +     return 0;
> +}
> diff --git a/volumes.c b/volumes.c
> index da79751..718e67c 100644
> --- a/volumes.c
> +++ b/volumes.c
> @@ -2108,12 +2108,14 @@ int write_raid56_with_parity(struct btrfs_fs_info 
> *info,
>  {
>       struct extent_buffer **ebs, *p_eb = NULL, *q_eb = NULL;
>       int i;
> -     int j;
>       int ret;
>       int alloc_size = eb->len;
> +     void **pointers;

I see you're moving existing code, so if you're going to fix the types,
please do that in a separate patch as well.

> -     ebs = kmalloc(sizeof(*ebs) * multi->num_stripes, GFP_NOFS);
> -     BUG_ON(!ebs);
> +     ebs = malloc(sizeof(*ebs) * multi->num_stripes);
> +     pointers = malloc(sizeof(void *) * multi->num_stripes);
> +     if (!ebs || !pointers)
> +             return -ENOMEM;
>  
>       if (stripe_len > alloc_size)
>               alloc_size = stripe_len;
> @@ -2143,12 +2145,6 @@ int write_raid56_with_parity(struct btrfs_fs_info 
> *info,
>                       q_eb = new_eb;
>       }
>       if (q_eb) {
> -             void **pointers;
> -
> -             pointers = kmalloc(sizeof(*pointers) * multi->num_stripes,
> -                                GFP_NOFS);
> -             BUG_ON(!pointers);
> -
>               ebs[multi->num_stripes - 2] = p_eb;
>               ebs[multi->num_stripes - 1] = q_eb;
>  
> @@ -2159,17 +2155,14 @@ int write_raid56_with_parity(struct btrfs_fs_info 
> *info,
>               kfree(pointers);
>       } else {
>               ebs[multi->num_stripes - 1] = p_eb;
> -             memcpy(p_eb->data, ebs[0]->data, stripe_len);
> -             for (j = 1; j < multi->num_stripes - 1; j++) {
> -                     for (i = 0; i < stripe_len; i += sizeof(u64)) {
> -                             u64 p_eb_data;
> -                             u64 ebs_data;
> -
> -                             p_eb_data = get_unaligned_64(p_eb->data + i);
> -                             ebs_data = get_unaligned_64(ebs[j]->data + i);
> -                             p_eb_data ^= ebs_data;
> -                             put_unaligned_64(p_eb_data, p_eb->data + i);
> -                     }
> +             for (i = 0; i < multi->num_stripes; i++)
> +                     pointers[i] = ebs[i]->data;
> +             ret = raid5_gen_result(multi->num_stripes, stripe_len,
> +                             multi->num_stripes - 1, pointers);
> +             if (ret < 0) {
> +                     free(ebs);
> +                     free(pointers);
> +                     return ret;
>               }
>       }
>  
> @@ -2180,7 +2173,8 @@ int write_raid56_with_parity(struct btrfs_fs_info *info,
>                       kfree(ebs[i]);
>       }
>  
> -     kfree(ebs);
> +     free(ebs);
> +     free(pointers);
>  
>       return 0;
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to