summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Berra <bluca@comedia.it>2011-06-17 14:41:01 +1000
committerNeilBrown <neilb@suse.de>2011-06-17 14:41:01 +1000
commit73e658d8ccf2ac73d795866e1b568f04cf8ee565 (patch)
treec58c09b113f68324ed1a9ed3954f7f57a55c7691
parent3b7e9d0cbeb91d8567a229f26326ec77053b90a2 (diff)
downloadmdadm-73e658d8ccf2ac73d795866e1b568f04cf8ee565.tar.gz
Improvements to GPT reading code.
looking at the gpt code in util.c i found i did not like it at all, a gpt partition entry is currently 128 bytes, but the spec does not say it is a fixed value, so the code that reads into a buffer with 512bytes chunk expecting this to be a multiplier of part_size is imho incorrect. my fix was to read each partition entry directly into a struct GPT_part_entry, the advantage is that the code is very simple to read, the disadvantage it is 128 reads of 128 bytes each, which is sub-optimal, but i believe readahead will mitigate this a lot. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--util.c27
1 files changed, 9 insertions, 18 deletions
diff --git a/util.c b/util.c
index e92be4f..10bbe56 100644
--- a/util.c
+++ b/util.c
@@ -1119,9 +1119,8 @@ int must_be_container(int fd)
static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
{
struct GPT gpt;
- unsigned char buf[512];
unsigned char empty_gpt_entry[16]= {0};
- struct GPT_part_entry *part;
+ struct GPT_part_entry part;
unsigned long long curr_part_end;
unsigned all_partitions, entry_size;
unsigned part_nr;
@@ -1129,8 +1128,9 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
*endofpart = 0;
BUILD_BUG_ON(sizeof(gpt) != 512);
- /* read GPT header */
+ /* skip protective MBR */
lseek(fd, 512, SEEK_SET);
+ /* read GPT header */
if (read(fd, &gpt, 512) != 512)
return 0;
@@ -1147,28 +1147,19 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
entry_size > 512)
return -1;
- /* read first GPT partition entries */
- if (read(fd, buf, 512) != 512)
- return 0;
-
- part = (struct GPT_part_entry*)buf;
-
for (part_nr=0; part_nr < all_partitions; part_nr++) {
+ /* read partition entry */
+ if (read(fd, &part, entry_size) != (ssize_t)entry_size)
+ return 0;
+
/* is this valid partition? */
- if (memcmp(part->type_guid, empty_gpt_entry, 16) != 0) {
+ if (memcmp(part.type_guid, empty_gpt_entry, 16) != 0) {
/* check the last lba for the current partition */
- curr_part_end = __le64_to_cpu(part->ending_lba);
+ curr_part_end = __le64_to_cpu(part.ending_lba);
if (curr_part_end > *endofpart)
*endofpart = curr_part_end;
}
- part = (struct GPT_part_entry*)((unsigned char*)part + entry_size);
-
- if ((unsigned char *)part >= buf + 512) {
- if (read(fd, buf, 512) != 512)
- return 0;
- part = (struct GPT_part_entry*)buf;
- }
}
return 1;
}