Avoid consuming lots of space and time if the first partition is not near the start of the disk (Debian bug #619458, Ubuntu bug #691569).

This commit is contained in:
Colin Watson 2011-03-25 17:22:12 +00:00
parent 7bdeb3987a
commit 58ed62d221
5 changed files with 27 additions and 7 deletions

View file

@ -1,7 +1,12 @@
2011-03-14 Colin Watson <cjwatson@ubuntu.com> 2011-03-14 Colin Watson <cjwatson@ubuntu.com>
* include/grub/partition.h (grub_partition_map): Change prototype of
embed to take a maximum value for nsectors.
* grub-core/partmap/msdos.c (embed_signatures): New array. * grub-core/partmap/msdos.c (embed_signatures): New array.
(pc_partition_map_embed): Check for and avoid sectors matching any (pc_partition_map_embed): Check for and avoid sectors matching any
of the signatures in embed_signatures. of the signatures in embed_signatures, up to max_nsectors.
* grub-core/partmap/gpt.c (gpt_partition_map_embed): Restrict
returned sector map to max_nsectors.
* util/grub-setup.c (setup): Allow for the embedding area being * util/grub-setup.c (setup): Allow for the embedding area being
split into multiple blocklists. split into multiple blocklists. Tell dest_partmap->embed the
maximum number of sectors we care about.

View file

@ -125,6 +125,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
static grub_err_t static grub_err_t
gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
unsigned int max_nsectors,
grub_embed_type_t embed_type, grub_embed_type_t embed_type,
grub_disk_addr_t **sectors) grub_disk_addr_t **sectors)
{ {
@ -174,6 +175,8 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
" embedding won't be possible!"); " embedding won't be possible!");
*nsectors = len; *nsectors = len;
if (*nsectors > max_nsectors)
*nsectors = max_nsectors;
*sectors = grub_malloc (*nsectors * sizeof (**sectors)); *sectors = grub_malloc (*nsectors * sizeof (**sectors));
if (!*sectors) if (!*sectors)
return grub_errno; return grub_errno;

View file

@ -185,6 +185,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
static grub_err_t static grub_err_t
pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
unsigned int max_nsectors,
grub_embed_type_t embed_type, grub_embed_type_t embed_type,
grub_disk_addr_t **sectors) grub_disk_addr_t **sectors)
{ {
@ -275,10 +276,13 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
{ {
unsigned i, j; unsigned i, j;
char *embed_signature_check; char *embed_signature_check;
unsigned int orig_nsectors; unsigned int orig_nsectors, avail_nsectors;
orig_nsectors = *nsectors; orig_nsectors = *nsectors;
*nsectors = end - 2; *nsectors = end - 2;
avail_nsectors = *nsectors;
if (*nsectors > max_nsectors)
*nsectors = max_nsectors;
*sectors = grub_malloc (*nsectors * sizeof (**sectors)); *sectors = grub_malloc (*nsectors * sizeof (**sectors));
if (!*sectors) if (!*sectors)
return grub_errno; return grub_errno;
@ -307,11 +311,20 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
"future. Please ask its authors not to store data " "future. Please ask its authors not to store data "
"in the boot track", "in the boot track",
(*sectors)[i], embed_signatures[j].name); (*sectors)[i], embed_signatures[j].name);
(*nsectors)--; avail_nsectors--;
if (avail_nsectors < *nsectors)
*nsectors = avail_nsectors;
/* Avoid this sector. */ /* Avoid this sector. */
for (j = i; j < *nsectors; j++) for (j = i; j < *nsectors; j++)
(*sectors)[j]++; (*sectors)[j]++;
/* Have we run out of space? */
if (avail_nsectors < orig_nsectors)
break;
/* Make sure to check the next sector. */
i--;
} }
grub_free (embed_signature_check); grub_free (embed_signature_check);

View file

@ -49,6 +49,7 @@ struct grub_partition_map
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
/* Determine sectors available for embedding. */ /* Determine sectors available for embedding. */
grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors, grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors,
unsigned int max_nsectors,
grub_embed_type_t embed_type, grub_embed_type_t embed_type,
grub_disk_addr_t **sectors); grub_disk_addr_t **sectors);
#endif #endif

View file

@ -426,10 +426,8 @@ setup (const char *dir,
} }
nsec = core_sectors; nsec = core_sectors;
err = dest_partmap->embed (dest_dev->disk, &nsec, err = dest_partmap->embed (dest_dev->disk, &nsec, 2 * core_sectors,
GRUB_EMBED_PCBIOS, &sectors); GRUB_EMBED_PCBIOS, &sectors);
if (nsec > 2 * core_sectors)
nsec = 2 * core_sectors;
if (err) if (err)
{ {