|
|
d18179 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
d18179 |
From: Vladimir Serbinenko <phcoder@gmail.com>
|
|
|
d18179 |
Date: Tue, 20 Jan 2015 17:36:29 +0100
|
|
|
d18179 |
Subject: [PATCH] * grub-core/fs/btrfs.c: Avoid divisions by zero.
|
|
|
d18179 |
|
|
|
d18179 |
(cherry picked from commit 9deb46e363a341d8c243e4c85754e673b4b68571)
|
|
|
d18179 |
[rharwood: drop ChangeLog]
|
|
|
d18179 |
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
|
|
|
d18179 |
---
|
|
|
d18179 |
grub-core/fs/btrfs.c | 35 +++++++++++++++++++++--------------
|
|
|
d18179 |
1 file changed, 21 insertions(+), 14 deletions(-)
|
|
|
d18179 |
|
|
|
d18179 |
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
|
|
d18179 |
index d8d71226ac..a401374690 100644
|
|
|
d18179 |
--- a/grub-core/fs/btrfs.c
|
|
|
d18179 |
+++ b/grub-core/fs/btrfs.c
|
|
|
d18179 |
@@ -701,6 +701,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
|
|
d18179 |
grub_uint64_t stripen;
|
|
|
d18179 |
grub_uint64_t stripe_offset;
|
|
|
d18179 |
grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset);
|
|
|
d18179 |
+ grub_uint64_t chunk_stripe_length;
|
|
|
d18179 |
+ grub_uint16_t nstripes;
|
|
|
d18179 |
unsigned redundancy = 1;
|
|
|
d18179 |
unsigned i, j;
|
|
|
d18179 |
|
|
|
d18179 |
@@ -711,15 +713,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
|
|
d18179 |
"couldn't find the chunk descriptor");
|
|
|
d18179 |
}
|
|
|
d18179 |
|
|
|
d18179 |
+ nstripes = grub_le_to_cpu16 (chunk->nstripes) ? : 1;
|
|
|
d18179 |
+ chunk_stripe_length = grub_le_to_cpu64 (chunk->stripe_length) ? : 512;
|
|
|
d18179 |
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
|
|
|
d18179 |
"+0x%" PRIxGRUB_UINT64_T
|
|
|
d18179 |
" (%d stripes (%d substripes) of %"
|
|
|
d18179 |
PRIxGRUB_UINT64_T ")\n",
|
|
|
d18179 |
grub_le_to_cpu64 (key->offset),
|
|
|
d18179 |
grub_le_to_cpu64 (chunk->size),
|
|
|
d18179 |
- grub_le_to_cpu16 (chunk->nstripes),
|
|
|
d18179 |
+ nstripes,
|
|
|
d18179 |
grub_le_to_cpu16 (chunk->nsubstripes),
|
|
|
d18179 |
- grub_le_to_cpu64 (chunk->stripe_length));
|
|
|
d18179 |
+ chunk_stripe_length);
|
|
|
d18179 |
|
|
|
d18179 |
switch (grub_le_to_cpu64 (chunk->type)
|
|
|
d18179 |
& ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE)
|
|
|
d18179 |
@@ -729,8 +733,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
|
|
d18179 |
grub_uint64_t stripe_length;
|
|
|
d18179 |
grub_dprintf ("btrfs", "single\n");
|
|
|
d18179 |
stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
|
|
|
d18179 |
- grub_le_to_cpu16 (chunk->nstripes),
|
|
|
d18179 |
+ nstripes,
|
|
|
d18179 |
NULL);
|
|
|
d18179 |
+ if (stripe_length == 0)
|
|
|
d18179 |
+ stripe_length = 512;
|
|
|
d18179 |
stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
|
|
|
d18179 |
csize = (stripen + 1) * stripe_length - off;
|
|
|
d18179 |
break;
|
|
|
d18179 |
@@ -751,33 +757,34 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
|
|
d18179 |
grub_uint64_t low;
|
|
|
d18179 |
grub_dprintf ("btrfs", "RAID0\n");
|
|
|
d18179 |
middle = grub_divmod64 (off,
|
|
|
d18179 |
- grub_le_to_cpu64 (chunk->stripe_length),
|
|
|
d18179 |
+ chunk_stripe_length,
|
|
|
d18179 |
&low);
|
|
|
d18179 |
|
|
|
d18179 |
- high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
|
|
|
d18179 |
+ high = grub_divmod64 (middle, nstripes,
|
|
|
d18179 |
&stripen);
|
|
|
d18179 |
stripe_offset =
|
|
|
d18179 |
- low + grub_le_to_cpu64 (chunk->stripe_length) * high;
|
|
|
d18179 |
- csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
|
|
d18179 |
+ low + chunk_stripe_length * high;
|
|
|
d18179 |
+ csize = chunk_stripe_length - low;
|
|
|
d18179 |
break;
|
|
|
d18179 |
}
|
|
|
d18179 |
case GRUB_BTRFS_CHUNK_TYPE_RAID10:
|
|
|
d18179 |
{
|
|
|
d18179 |
grub_uint64_t middle, high;
|
|
|
d18179 |
grub_uint64_t low;
|
|
|
d18179 |
+ grub_uint16_t nsubstripes;
|
|
|
d18179 |
+ nsubstripes = grub_le_to_cpu16 (chunk->nsubstripes) ? : 1;
|
|
|
d18179 |
middle = grub_divmod64 (off,
|
|
|
d18179 |
- grub_le_to_cpu64 (chunk->stripe_length),
|
|
|
d18179 |
+ chunk_stripe_length,
|
|
|
d18179 |
&low);
|
|
|
d18179 |
|
|
|
d18179 |
high = grub_divmod64 (middle,
|
|
|
d18179 |
- grub_le_to_cpu16 (chunk->nstripes)
|
|
|
d18179 |
- / grub_le_to_cpu16 (chunk->nsubstripes),
|
|
|
d18179 |
+ nstripes / nsubstripes ? : 1,
|
|
|
d18179 |
&stripen);
|
|
|
d18179 |
- stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
|
|
|
d18179 |
- redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
|
|
|
d18179 |
- stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
|
|
|
d18179 |
+ stripen *= nsubstripes;
|
|
|
d18179 |
+ redundancy = nsubstripes;
|
|
|
d18179 |
+ stripe_offset = low + chunk_stripe_length
|
|
|
d18179 |
* high;
|
|
|
d18179 |
- csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
|
|
d18179 |
+ csize = chunk_stripe_length - low;
|
|
|
d18179 |
break;
|
|
|
d18179 |
}
|
|
|
d18179 |
default:
|