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
|
@ -285,7 +285,6 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
|
||||
if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0)
|
||||
{
|
||||
batch = 65536;
|
||||
if (ata->dma)
|
||||
{
|
||||
cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT;
|
||||
|
@ -301,10 +300,6 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
{
|
||||
if (addressing == GRUB_ATA_LBA48)
|
||||
addressing = GRUB_ATA_LBA;
|
||||
if (addressing != GRUB_ATA_CHS)
|
||||
batch = 256;
|
||||
else
|
||||
batch = 1;
|
||||
if (ata->dma)
|
||||
{
|
||||
cmd = GRUB_ATA_CMD_READ_SECTORS_DMA;
|
||||
|
@ -317,8 +312,10 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
}
|
||||
}
|
||||
|
||||
if (batch > (ata->maxbuffer >> ata->log_sector_size))
|
||||
batch = (ata->maxbuffer >> ata->log_sector_size);
|
||||
if (addressing != GRUB_ATA_CHS)
|
||||
batch = 256;
|
||||
else
|
||||
batch = 1;
|
||||
|
||||
while (nsectors < size)
|
||||
{
|
||||
|
@ -464,6 +461,10 @@ grub_ata_open (const char *name, grub_disk_t disk)
|
|||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
|
||||
|
||||
disk->total_sectors = ata->size;
|
||||
disk->max_agglomerate = (ata->maxbuffer >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
|
||||
if (disk->max_agglomerate > (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size)))
|
||||
disk->max_agglomerate = (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size));
|
||||
|
||||
disk->log_sector_size = ata->log_sector_size;
|
||||
|
||||
disk->id = grub_make_scsi_id (id, bus, 0);
|
||||
|
|
|
@ -517,6 +517,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
|
|||
|
||||
disk->data = dev;
|
||||
disk->total_sectors = dev->total_length;
|
||||
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
|
||||
disk->id = dev->id;
|
||||
dev->ref++;
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -445,6 +445,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk)
|
|||
disk->data = lv;
|
||||
|
||||
disk->total_sectors = lv->size;
|
||||
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -518,6 +518,8 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
|
|||
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
|
||||
m, (unsigned long long) m->last_block, m->block_size);
|
||||
disk->total_sectors = m->last_block + 1;
|
||||
/* Don't increase this value due to bug in some EFI. */
|
||||
disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
|
||||
if (m->block_size & (m->block_size - 1) || !m->block_size)
|
||||
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
|
||||
m->block_size);
|
||||
|
@ -550,24 +552,11 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector,
|
|||
d = disk->data;
|
||||
bio = d->block_io;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
grub_size_t len;
|
||||
len = 0x500;
|
||||
if (len > size)
|
||||
len = size;
|
||||
status = efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
|
||||
bio->media->media_id,
|
||||
(grub_efi_uint64_t) sector,
|
||||
(grub_efi_uintn_t) len << disk->log_sector_size,
|
||||
buf);
|
||||
size -= len;
|
||||
buf += len << disk->log_sector_size;
|
||||
sector += len;
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
return GRUB_EFI_SUCCESS;
|
||||
return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
|
||||
bio->media->media_id,
|
||||
(grub_efi_uint64_t) sector,
|
||||
(grub_efi_uintn_t) size << disk->log_sector_size,
|
||||
buf);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -424,6 +424,9 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
}
|
||||
|
||||
disk->total_sectors = total_sectors;
|
||||
/* Limit the max to 0x7f because of Phoenix EDD. */
|
||||
disk->max_agglomerate = 0x7f >> GRUB_DISK_CACHE_BITS;
|
||||
|
||||
disk->data = data;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -548,10 +551,6 @@ get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
|
|||
|
||||
size = sectors - offset;
|
||||
|
||||
/* Limit the max to 0x7f because of Phoenix EDD. */
|
||||
if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
|
||||
size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,10 @@ grub_loopback_open (const char *name, grub_disk_t disk)
|
|||
/ GRUB_DISK_SECTOR_SIZE);
|
||||
else
|
||||
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
|
||||
/* Avoid reading more than 512M. */
|
||||
disk->max_agglomerate = 1 << (29 - GRUB_DISK_SECTOR_BITS
|
||||
- GRUB_DISK_CACHE_BITS);
|
||||
|
||||
disk->id = (unsigned long) dev;
|
||||
|
||||
disk->data = dev;
|
||||
|
|
|
@ -46,6 +46,7 @@ grub_memdisk_open (const char *name, grub_disk_t disk)
|
|||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk");
|
||||
|
||||
disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE;
|
||||
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
|
||||
disk->id = (unsigned long) "mdsk";
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -606,6 +606,13 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
|||
}
|
||||
|
||||
disk->total_sectors = scsi->last_block + 1;
|
||||
/* PATA doesn't support more than 32K reads.
|
||||
Not sure about AHCI and USB. If it's confirmed that either of
|
||||
them can do bigger reads reliably this value can be moved to 'scsi'
|
||||
structure. */
|
||||
disk->max_agglomerate = 32768 >> (GRUB_DISK_SECTOR_BITS
|
||||
+ GRUB_DISK_CACHE_BITS);
|
||||
|
||||
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
|
||||
{
|
||||
grub_free (scsi);
|
||||
|
@ -647,40 +654,27 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
|
||||
scsi = disk->data;
|
||||
|
||||
while (size)
|
||||
grub_err_t err;
|
||||
/* Depending on the type, select a read function. */
|
||||
switch (scsi->devtype)
|
||||
{
|
||||
/* PATA doesn't support more than 32K reads.
|
||||
Not sure about AHCI and USB. If it's confirmed that either of
|
||||
them can do bigger reads reliably this value can be moved to 'scsi'
|
||||
structure. */
|
||||
grub_size_t len = 32768 >> disk->log_sector_size;
|
||||
grub_err_t err;
|
||||
if (len > size)
|
||||
len = size;
|
||||
/* Depending on the type, select a read function. */
|
||||
switch (scsi->devtype)
|
||||
{
|
||||
case grub_scsi_devtype_direct:
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_read16 (disk, sector, len, buf);
|
||||
else
|
||||
err = grub_scsi_read10 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
case grub_scsi_devtype_direct:
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_read16 (disk, sector, size, buf);
|
||||
else
|
||||
err = grub_scsi_read10 (disk, sector, size, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case grub_scsi_devtype_cdrom:
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_read16 (disk, sector, len, buf);
|
||||
else
|
||||
err = grub_scsi_read12 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
size -= len;
|
||||
sector += len;
|
||||
buf += len << disk->log_sector_size;
|
||||
case grub_scsi_devtype_cdrom:
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_read16 (disk, sector, size, buf);
|
||||
else
|
||||
err = grub_scsi_read12 (disk, sector, size, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -718,10 +712,10 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_scsi_write (grub_disk_t disk __attribute((unused)),
|
||||
grub_disk_addr_t sector __attribute((unused)),
|
||||
grub_size_t size __attribute((unused)),
|
||||
const char *buf __attribute((unused)))
|
||||
grub_scsi_write (grub_disk_t disk,
|
||||
grub_disk_addr_t sector,
|
||||
grub_size_t size,
|
||||
const char *buf)
|
||||
{
|
||||
grub_scsi_t scsi;
|
||||
|
||||
|
@ -730,31 +724,18 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)),
|
|||
if (scsi->devtype == grub_scsi_devtype_cdrom)
|
||||
return grub_error (GRUB_ERR_IO, N_("cannot write to CD-ROM"));
|
||||
|
||||
while (size)
|
||||
grub_err_t err;
|
||||
/* Depending on the type, select a read function. */
|
||||
switch (scsi->devtype)
|
||||
{
|
||||
/* PATA doesn't support more than 32K reads.
|
||||
Not sure about AHCI and USB. If it's confirmed that either of
|
||||
them can do bigger reads reliably this value can be moved to 'scsi'
|
||||
structure. */
|
||||
grub_size_t len = 32768 >> disk->log_sector_size;
|
||||
grub_err_t err;
|
||||
if (len > size)
|
||||
len = size;
|
||||
/* Depending on the type, select a read function. */
|
||||
switch (scsi->devtype)
|
||||
{
|
||||
case grub_scsi_devtype_direct:
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_write16 (disk, sector, len, buf);
|
||||
else
|
||||
err = grub_scsi_write10 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
size -= len;
|
||||
sector += len;
|
||||
buf += len << disk->log_sector_size;
|
||||
case grub_scsi_devtype_direct:
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_write16 (disk, sector, size, buf);
|
||||
else
|
||||
err = grub_scsi_write10 (disk, sector, size, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue