On 05/09/2018 06:46 PM, Daniel Kiper wrote: > On Tue, Apr 24, 2018 at 09:13:15PM +0200, Goffredo Baroncelli wrote: >> Signed-off-by: Goffredo Baroncelli <kreij...@inwind.it> >> --- >> grub-core/fs/btrfs.c | 206 +++++++++++++++++++++++++++++++++++++++++-- >> 1 file changed, 199 insertions(+), 7 deletions(-) >> >> diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c >> index 697322125..5c76a68f3 100644 >> --- a/grub-core/fs/btrfs.c >> +++ b/grub-core/fs/btrfs.c >> @@ -29,6 +29,7 @@ >> #include <minilzo.h> >> #include <grub/i18n.h> >> #include <grub/btrfs.h> >> +#include <grub/crypto.h> >> >> GRUB_MOD_LICENSE ("GPLv3+"); >> >> @@ -661,9 +662,180 @@ btrfs_read_from_chunk (struct grub_btrfs_data *data, >> err = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS, >> paddr & (GRUB_DISK_SECTOR_SIZE - 1), >> csize, buf); >> + grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T "\n", >> paddr); >> return err; >> } >> >> +struct raid56_buffer { >> + void *buf; >> + int ok; > > What ok is? in the next series I renamed it as "data_is_valid" > >> +}; >> + >> +static void >> +rebuild_raid5 (struct raid56_buffer *buffers, grub_uint64_t nstripes, >> + grub_uint64_t csize) >> +{ >> + grub_uint64_t target, i; > > grub_uint64_t target = 0, i; > >> + target = 0; > > ...then you can drop this. ok > >> + while (buffers[target].ok && target < nstripes) >> + ++target; >> + >> + if (target == nstripes) >> + { >> + grub_dprintf ("btrfs", "called rebuild_raid5(), but all disks are >> OK\n"); >> + return; >> + } >> + >> + grub_dprintf ("btrfs", "rebuilding raid5 stripe #%" PRIuGRUB_UINT64_T >> "\n", >> + target); >> + for (i = 0; i < nstripes ; i++) >> + if (i != target) >> + grub_crypto_xor (buffers[target].buf, buffers[target].buf, >> buffers[i].buf, >> + csize); >> +} >> + >> +static void >> +rebuild_raid6 (struct raid56_buffer *buffers, grub_uint64_t nstripes, >> + grub_uint64_t csize, grub_uint64_t parities_pos, void *dest, >> + grub_uint64_t stripen) >> + >> +{ >> + (void)buffers; >> + (void)nstripes; >> + (void)csize; >> + (void)parities_pos; >> + (void)dest; >> + (void)stripen; >> + grub_dprintf ("btrfs", "called rebuild_raid6(), NOT IMPLEMENTED\n"); > > Could you add this function in next patch and print the relevant message > below directly instead from rebuild_raid6()? Ok > >> +} >> + >> +static grub_err_t >> +raid56_read_retry (struct grub_btrfs_data *data, >> + struct grub_btrfs_chunk_item *chunk, >> + grub_uint64_t stripe_offset, grub_uint64_t stripen, >> + grub_uint64_t csize, void *buf, grub_uint64_t parities_pos) >> +{ >> + >> + struct raid56_buffer *buffers = NULL; >> + grub_uint64_t nstripes = grub_le_to_cpu16 (chunk->nstripes); >> + grub_uint64_t chunk_type = grub_le_to_cpu64 (chunk->type); >> + grub_err_t ret = GRUB_ERR_NONE; >> + grub_uint64_t i, failed_devices; >> + >> + buffers = grub_zalloc (sizeof(struct raid56_buffer)* nstripes); > > ... sizeof (*buffers) * nstripes ... ok > >> + if (!buffers) >> + { >> + ret = GRUB_ERR_OUT_OF_MEMORY; >> + goto cleanup; >> + } >> + >> + for (i = 0 ; i < nstripes ; i++) > > for (i = 0; i < nstripes; i++) ok > >> + { >> + buffers[i].buf = grub_zalloc(csize); > > ... grub_zalloc (csize); ok > >> + if (!buffers[i].buf) >> + { >> + ret = GRUB_ERR_OUT_OF_MEMORY; >> + goto cleanup; >> + } >> + } >> + >> + for (i = 0 ; i < nstripes ; i++) > > Ditto. ok >> + { >> + struct grub_btrfs_chunk_stripe *stripe; >> + grub_disk_addr_t paddr; >> + grub_device_t dev; >> + grub_err_t err2; >> + >> + stripe = (struct grub_btrfs_chunk_stripe *) (chunk + 1); >> + stripe += i; >> + >> + paddr = grub_le_to_cpu64 (stripe->offset) + stripe_offset; >> + grub_dprintf ("btrfs", "reading paddr %" PRIxGRUB_UINT64_T >> + " from stripe ID %" PRIxGRUB_UINT64_T "\n", paddr, >> + stripe->device_id); >> + >> + /* FIXME: rescan the devices */ >> + dev = find_device (data, stripe->device_id); >> + if (!dev) >> + { >> + buffers[i].ok = 0; >> + grub_dprintf ("btrfs", "stripe %" PRIuGRUB_UINT64_T " FAILED (dev ID >> %" >> + PRIxGRUB_UINT64_T ")\n", i, stripe->device_id); >> + continue; >> + } > > Something is wrong with aligment. ok > >> + err2 = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS, >> + paddr & (GRUB_DISK_SECTOR_SIZE - 1), >> + csize, buffers[i].buf); >> + if (err2 == GRUB_ERR_NONE) >> + { >> + buffers[i].ok = 1; >> + grub_dprintf ("btrfs", "stripe %" PRIuGRUB_UINT64_T " Ok (dev ID %" >> + PRIxGRUB_UINT64_T ")\n", i, stripe->device_id); >> + } >> + else >> + { >> + buffers[i].ok = 0; >> + grub_dprintf ("btrfs", "stripe %" PRIuGRUB_UINT64_T >> + " FAILED (dev ID %" PRIxGRUB_UINT64_T ")\n", i, >> + stripe->device_id); >> + } >> + } >> + >> + failed_devices = 0; >> + for (i = 0 ; i < nstripes ; i++) > > Ditto. Ok > >> + if (!buffers[i].ok) >> + ++failed_devices; >> + if (failed_devices > 1 && (chunk_type & GRUB_BTRFS_CHUNK_TYPE_RAID5)) >> + { >> + grub_dprintf ("btrfs", >> + "not enough disks for raid5: total %" PRIuGRUB_UINT64_T >> + ", missing %" PRIuGRUB_UINT64_T "\n", >> + nstripes, failed_devices); >> + ret = GRUB_ERR_READ_ERROR; >> + goto cleanup; >> + } >> + else if (failed_devices > 2 && (chunk_type & GRUB_BTRFS_CHUNK_TYPE_RAID6)) >> + { >> + grub_dprintf ("btrfs", >> + "not enough disks for raid6: total %" PRIuGRUB_UINT64_T >> + ", missing %" PRIuGRUB_UINT64_T "\n", >> + nstripes, failed_devices); >> + ret = GRUB_ERR_READ_ERROR; >> + goto cleanup; >> + } > > This piece of code should be introduced in next patch. ok > >> + else >> + { >> + grub_dprintf ("btrfs", >> + "enough disks for raid5/6 rebuilding: total %" >> + PRIuGRUB_UINT64_T ", missing %" PRIuGRUB_UINT64_T "\n", >> + nstripes, failed_devices); >> + } >> + >> + /* if these are enough, try to rebuild the data */ >> + if (chunk_type & GRUB_BTRFS_CHUNK_TYPE_RAID5) >> + { >> + rebuild_raid5 (buffers, nstripes, csize); >> + grub_memcpy (buf, buffers[stripen].buf, csize); >> + } >> + else >> + { >> + rebuild_raid6 (buffers, nstripes, csize, parities_pos, buf, stripen); > > Please print not implemented messaged here instead of rebuild_raid6() call. ok > >> + } >> + >> +cleanup: > > Please add one space before the label. ok > >> + if (buffers) >> + { >> + for (i = 0 ; i < nstripes ; i++) > > Ditto. ok > >> + if (buffers[i].buf) >> + grub_free(buffers[i].buf); >> + grub_free(buffers); >> + } >> + >> + return ret; >> +} >> + >> static grub_err_t >> grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t >> addr, >> void *buf, grub_size_t size, int recursion_depth) >> @@ -741,6 +913,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, >> grub_disk_addr_t addr, >> grub_uint16_t nstripes; >> unsigned redundancy = 1; >> unsigned i, j; >> + int is_raid56; ok > > Incorrect aligment. > >> + grub_uint64_t parities_pos = 0; >> + >> + is_raid56 = !!(grub_le_to_cpu64 (chunk->type) & >> + (GRUB_BTRFS_CHUNK_TYPE_RAID5|GRUB_BTRFS_CHUNK_TYPE_RAID6)); > > Do we need GRUB_BTRFS_CHUNK_TYPE_RAID6 here? Or maybe this > should be introduced by next patch? ok > >> if (grub_le_to_cpu64 (chunk->size) <= off) >> { >> @@ -844,9 +1021,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, >> grub_disk_addr_t addr, >> } >> >> stripe_nr = grub_divmod64 (off, chunk_stripe_length, &low); >> - >> high = grub_divmod64 (stripe_nr, nstripes - nparities, &stripen); >> grub_divmod64 (high + stripen, nstripes, &stripen); >> + grub_divmod64 (high + nstripes - nparities, nstripes, >> + &parities_pos); >> >> stripe_offset = low + chunk_stripe_length * high; >> csize = chunk_stripe_length - low; >> @@ -881,12 +1059,26 @@ grub_btrfs_read_logical (struct grub_btrfs_data >> *data, grub_disk_addr_t addr, >> grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n", >> addr); >> >> - err = GRUB_ERR_NONE + 1; >> - for (i = 0; i < redundancy && err != GRUB_ERR_NONE; i++) >> - err = btrfs_read_from_chunk (data, chunk, stripen, >> - stripe_offset, >> - i, /* redundancy */ >> - csize, buf); >> + if (!is_raid56) >> + { >> + err = GRUB_ERR_NONE+1; > > What? Ok, I correct it > > Daniel >
-- gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it> Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel