Rewrite blocklist functions in order to get progress when
reading large extents and decrease amount of blocklist hook calls.
This commit is contained in:
parent
896f913571
commit
cb72aa1809
20 changed files with 220 additions and 181 deletions
|
@ -62,23 +62,47 @@ read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length,
|
|||
if (ctx->num_sectors > 0)
|
||||
{
|
||||
if (ctx->start_sector + ctx->num_sectors == sector
|
||||
&& offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
|
||||
&& offset == 0 && length >= GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
ctx->num_sectors++;
|
||||
return;
|
||||
ctx->num_sectors += length >> GRUB_DISK_SECTOR_BITS;
|
||||
sector += length >> GRUB_DISK_SECTOR_BITS;
|
||||
length &= (GRUB_DISK_SECTOR_SIZE - 1);
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
|
||||
ctx->num_sectors = 0;
|
||||
}
|
||||
|
||||
if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
|
||||
if (offset)
|
||||
{
|
||||
ctx->start_sector = sector;
|
||||
ctx->num_sectors++;
|
||||
unsigned l = length + offset;
|
||||
l &= (GRUB_DISK_SECTOR_SIZE - 1);
|
||||
l -= offset;
|
||||
print_blocklist (sector, 0, offset, l, ctx);
|
||||
length -= l;
|
||||
sector++;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
if (length & (GRUB_DISK_SECTOR_SIZE - 1))
|
||||
{
|
||||
if (length >> GRUB_DISK_SECTOR_BITS)
|
||||
{
|
||||
print_blocklist (sector, length >> GRUB_DISK_SECTOR_BITS, 0, 0, ctx);
|
||||
sector += length >> GRUB_DISK_SECTOR_BITS;
|
||||
}
|
||||
print_blocklist (sector, 0, 0, length & (GRUB_DISK_SECTOR_SIZE - 1), ctx);
|
||||
}
|
||||
else
|
||||
print_blocklist (sector, 0, offset, length, ctx);
|
||||
{
|
||||
ctx->start_sector = sector;
|
||||
ctx->num_sectors = length >> GRUB_DISK_SECTOR_BITS;
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -259,10 +259,28 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
|||
for (p = blocklists; p; p = p->next)
|
||||
{
|
||||
struct blocklist *q;
|
||||
/* Check if any pair of blocks overlap. */
|
||||
for (q = p->next; q; q = q->next)
|
||||
{
|
||||
/* Check if any pair of blocks overlap. */
|
||||
if (p->sector == q->sector)
|
||||
grub_disk_addr_t s1, s2;
|
||||
grub_disk_addr_t e1, e2, t;
|
||||
|
||||
s1 = p->sector;
|
||||
e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
s2 = q->sector;
|
||||
e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (s2 > s1)
|
||||
{
|
||||
t = s2;
|
||||
s2 = s1;
|
||||
s1 = t;
|
||||
t = e2;
|
||||
e2 = e1;
|
||||
e1 = t;
|
||||
}
|
||||
if (e1 > s2)
|
||||
{
|
||||
/* This might be actually valid, but it is unbelievable that
|
||||
any filesystem makes such a silly allocation. */
|
||||
|
@ -286,9 +304,18 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
|||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
char *blockbuf = NULL;
|
||||
grub_size_t blockbuf_len = 0;
|
||||
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
|
||||
{
|
||||
char blockbuf[GRUB_DISK_SECTOR_SIZE];
|
||||
if (p->length > blockbuf_len)
|
||||
{
|
||||
grub_free (blockbuf);
|
||||
blockbuf_len = 2 * p->length;
|
||||
blockbuf = grub_malloc (blockbuf_len);
|
||||
if (!blockbuf)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_disk_read (disk, p->sector - part_start,
|
||||
p->offset, p->length, blockbuf))
|
||||
|
@ -340,10 +367,6 @@ save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
|
|||
struct grub_cmd_save_env_ctx *ctx = data;
|
||||
struct blocklist *block;
|
||||
|
||||
if (offset + length > GRUB_DISK_SECTOR_SIZE)
|
||||
/* Seemingly a bug. */
|
||||
return;
|
||||
|
||||
block = grub_malloc (sizeof (*block));
|
||||
if (! block)
|
||||
return;
|
||||
|
|
|
@ -35,10 +35,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
static void
|
||||
read_progress (grub_disk_addr_t sector __attribute__ ((unused)),
|
||||
unsigned offset __attribute__ ((unused)),
|
||||
unsigned len __attribute__ ((unused)),
|
||||
unsigned len,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
grub_xputs (".");
|
||||
for (; len >= GRUB_DISK_SECTOR_SIZE; len -= GRUB_DISK_SECTOR_SIZE)
|
||||
grub_xputs (".");
|
||||
if (len)
|
||||
grub_xputs (".");
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue