* Grub2 EFI: Image loading from USB takes too long
@ 2011-04-05 5:33 Aravind Srinivasan
2011-04-05 6:32 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 6:32 ` Seth Goldberg
0 siblings, 2 replies; 21+ messages in thread
From: Aravind Srinivasan @ 2011-04-05 5:33 UTC (permalink / raw)
To: grub-devel
Hi,
I am trying Grub2 EFI - this is on a custom platform. On 1.99-rc1, compared to
Legacy grub, loading image, in particular initrd image from a USB takes a very
long. Our initrd image is about 160M and it is taking about 2 mins to load this
image. Turning on "set debug=all" in the grub.cfg file, I see that all the time
is being spent in reading the USB. Looking at the source, I think the issue is
the value set for GRUB_DISK_CACHE_SIZE in include/grub/disk.h
Currently this is what it is set to:
include/grub/disk.h
<snip>
/* The size of a disk cache in sector units. */
#define GRUB_DISK_CACHE_SIZE 8
#define GRUB_DISK_CACHE_BITS 3
<snip>
I tried changing this value to 8192 - and the time it took to load the same
image came down to 10 secs !
/* The size of a disk cache in sector units. */
#define GRUB_DISK_CACHE_SIZE 8192
#define GRUB_DISK_CACHE_BITS 13
I am not sure of the reason for setting the cache size to a low value and any
possible issues in increasing this size. Appreciate any input on this.
Thanks,
-Aravind
Insert mode
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 5:33 Aravind Srinivasan
@ 2011-04-05 6:32 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 7:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 6:32 ` Seth Goldberg
1 sibling, 1 reply; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-05 6:32 UTC (permalink / raw)
To: The development of GNU GRUB
On 05.04.2011 07:33, Aravind Srinivasan wrote:
> include/grub/disk.h
> <snip>
> /* The size of a disk cache in sector units. */
> #define GRUB_DISK_CACHE_SIZE 8
> #define GRUB_DISK_CACHE_BITS 3
> <snip>
>
> I tried changing this value to 8192 - and the time it took to load the same
> image came down to 10 secs !
> /* The size of a disk cache in sector units. */
> #define GRUB_DISK_CACHE_SIZE 8192
> #define GRUB_DISK_CACHE_BITS 13
>
> I am not sure of the reason for setting the cache size to a low value and any
> possible issues in increasing this size. Appreciate any input on this.
This value is a misnomer. It's not a cache size but a cache unit size.
As immediate effect it has that if one reads a single 512B, sector one
reads an entire block of 4K. Under normal conditions values of around
32K-128K (6-8/64-256) would be optimal. It seems that some EFI
implementations do a "buffering" only to discard the buffered data. Some
of the reports suggest that this braindamage is limited to disk io and
doesn't happen with Block IO. Values you propose would result in 4M
reads even when one needs just few sectors and so is suboptimal under
normal conditions.
I'll prepare few patches to investigate.
After 1.99 the GRUB_DISK_CACHE_BITS will be increased to 6-8 range
since, it's optimal and my AF support requires sector size to be smaller
than cache unit size.
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 5:33 Aravind Srinivasan
2011-04-05 6:32 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-05 6:32 ` Seth Goldberg
2011-04-05 7:17 ` KESHAV P.R.
1 sibling, 1 reply; 21+ messages in thread
From: Seth Goldberg @ 2011-04-05 6:32 UTC (permalink / raw)
To: The development of GNU GRUB; +Cc: grub-devel@gnu.org
It's not just USB. Loading large files via UEFI with GRUB2 takes an extremely long time. One of the things phcoder suggested was changing the cache size, which you've done. Od love to see a larger cache committed to the trunk so UEFI platforms can benefit when large files need to be read by GRUB2 (assuming no other side effects)!
--S
On Apr 4, 2011, at 10:33 PM, Aravind Srinivasan <aravind_s_873@yahoo.com> wrote:
>
> Hi,
>
> I am trying Grub2 EFI - this is on a custom platform. On 1.99-rc1, compared to
> Legacy grub, loading image, in particular initrd image from a USB takes a very
> long. Our initrd image is about 160M and it is taking about 2 mins to load this
> image. Turning on "set debug=all" in the grub.cfg file, I see that all the time
> is being spent in reading the USB. Looking at the source, I think the issue is
> the value set for GRUB_DISK_CACHE_SIZE in include/grub/disk.h
> Currently this is what it is set to:
>
> include/grub/disk.h
> <snip>
> /* The size of a disk cache in sector units. */
> #define GRUB_DISK_CACHE_SIZE 8
> #define GRUB_DISK_CACHE_BITS 3
> <snip>
>
> I tried changing this value to 8192 - and the time it took to load the same
> image came down to 10 secs !
> /* The size of a disk cache in sector units. */
> #define GRUB_DISK_CACHE_SIZE 8192
> #define GRUB_DISK_CACHE_BITS 13
>
> I am not sure of the reason for setting the cache size to a low value and any
> possible issues in increasing this size. Appreciate any input on this.
>
> Thanks,
> -Aravind
> Insert mode
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 6:32 ` Seth Goldberg
@ 2011-04-05 7:17 ` KESHAV P.R.
2011-04-05 7:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 21+ messages in thread
From: KESHAV P.R. @ 2011-04-05 7:17 UTC (permalink / raw)
To: The development of GNU GRUB
On Tue, Apr 5, 2011 at 12:02, Seth Goldberg <seth.goldberg@oracle.com> wrote:
> It's not just USB. Loading large files via UEFI with GRUB2 takes an extremely long time. One of the things phcoder suggested was changing the cache size, which you've done. Od love to see a larger cache committed to the trunk so UEFI platforms can benefit when large files need to be read by GRUB2 (assuming no other side effects)!
>
> --S
>
> On Apr 4, 2011, at 10:33 PM, Aravind Srinivasan <aravind_s_873@yahoo.com> wrote:
>
>>
>> Hi,
>>
>> I am trying Grub2 EFI - this is on a custom platform. On 1.99-rc1, compared to
>> Legacy grub, loading image, in particular initrd image from a USB takes a very
>> long. Our initrd image is about 160M and it is taking about 2 mins to load this
>> image. Turning on "set debug=all" in the grub.cfg file, I see that all the time
>> is being spent in reading the USB. Looking at the source, I think the issue is
>> the value set for GRUB_DISK_CACHE_SIZE in include/grub/disk.h
>> Currently this is what it is set to:
>>
>> include/grub/disk.h
>> <snip>
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8
>> #define GRUB_DISK_CACHE_BITS 3
>> <snip>
>>
>> I tried changing this value to 8192 - and the time it took to load the same
>> image came down to 10 secs !
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8192
>> #define GRUB_DISK_CACHE_BITS 13
>>
>> I am not sure of the reason for setting the cache size to a low value and any
>> possible issues in increasing this size. Appreciate any input on this.
>>
>> Thanks,
>> -Aravind
>> Insert mode
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
I can confirm that grub2 x86_64-efi is very slow in loading initramfs
files. I did my testing in VirtualBox 4.0.4 (VBox patched OVMF, quite
old compared to updated OVMF) using an iso mounted in a virtual SATA
AHCI CD drive and 1 GiB RAM alloted to the virtual machine. Intel VT
extension was enabled. In a crude benchmarking using s top watch, the
time between selection of menuentry to seeing the kernel boot messages
is approx 4 minutes (236 seconds) measured using a stop watch. I have
not yet tested with an updated ovmf in qemu or in duet. I guess
accessing from HDDs is faster in UEFI systems. Its the CDs and USB
which seem to take a lot of time.
The kernel loaded by grub2 during the test and the initramfs can be
downloaded from
ftp://ftp.archlinux.org/iso/archboot/2011.02/boot/vm64 - kernel (lzma
compressed)
ftp://ftp.archlinux.org/iso/archboot/2011.02/boot/initrd64.img -
initramfs (lzma -9 compressed cpio archive).
Regards.
Keshav
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 6:32 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-05 7:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 16:36 ` Aravind Srinivasan
0 siblings, 1 reply; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-05 7:36 UTC (permalink / raw)
To: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 1625 bytes --]
On 05.04.2011 08:32, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> On 05.04.2011 07:33, Aravind Srinivasan wrote:
>> include/grub/disk.h
>> <snip>
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8
>> #define GRUB_DISK_CACHE_BITS 3
>> <snip>
>>
>> I tried changing this value to 8192 - and the time it took to load
>> the same
>> image came down to 10 secs !
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8192
>> #define GRUB_DISK_CACHE_BITS 13
>>
>> I am not sure of the reason for setting the cache size to a low value
>> and any
>> possible issues in increasing this size. Appreciate any input on this.
> This value is a misnomer. It's not a cache size but a cache unit size.
> As immediate effect it has that if one reads a single 512B, sector one
> reads an entire block of 4K. Under normal conditions values of around
> 32K-128K (6-8/64-256) would be optimal. It seems that some EFI
> implementations do a "buffering" only to discard the buffered data.
> Some of the reports suggest that this braindamage is limited to disk
> io and doesn't happen with Block IO. Values you propose would result
> in 4M reads even when one needs just few sectors and so is suboptimal
> under normal conditions.
> I'll prepare few patches to investigate.
> After 1.99 the GRUB_DISK_CACHE_BITS will be increased to 6-8 range
> since, it's optimal and my AF support requires sector size to be
> smaller than cache unit size.
>
Attached a patch based on my AF patch which change to block IO.
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: blockio.diff --]
[-- Type: text/x-diff, Size: 22617 bytes --]
=== modified file 'grub-core/disk/efi/efidisk.c'
--- grub-core/disk/efi/efidisk.c 2010-09-21 12:41:23 +0000
+++ grub-core/disk/efi/efidisk.c 2011-04-05 07:35:10 +0000
@@ -33,12 +33,10 @@
grub_efi_device_path_t *device_path;
grub_efi_device_path_t *last_device_path;
grub_efi_block_io_t *block_io;
- grub_efi_disk_io_t *disk_io;
struct grub_efidisk_data *next;
};
-/* GUIDs. */
-static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
+/* GUID. */
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
static struct grub_efidisk_data *fd_devices;
@@ -143,7 +141,7 @@
struct grub_efidisk_data *devices = 0;
/* Find handles which support the disk io interface. */
- handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid,
+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid,
0, &num_handles);
if (! handles)
return 0;
@@ -155,7 +153,6 @@
grub_efi_device_path_t *ldp;
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
- grub_efi_disk_io_t *dio;
dp = grub_efi_get_device_path (*handle);
if (! dp)
@@ -168,9 +165,7 @@
bio = grub_efi_open_protocol (*handle, &block_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- dio = grub_efi_open_protocol (*handle, &disk_io_guid,
- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (! bio || ! dio)
+ if (! bio)
/* This should not happen... Why? */
continue;
@@ -186,7 +181,6 @@
d->device_path = dp;
d->last_device_path = ldp;
d->block_io = bio;
- d->disk_io = dio;
d->next = devices;
devices = d;
}
@@ -536,8 +530,13 @@
and total sectors should be replaced with total blocks. */
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
- * (m->block_size >> GRUB_DISK_SECTOR_BITS));
+ disk->total_sectors = m->last_block;
+ if (m->block_size & (m->block_size - 1) || !m->block_size)
+ return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+ m->block_size);
+ for (disk->log_sector_size = 0;
+ (1U << disk->log_sector_size) < m->block_size;
+ disk->log_sector_size++);
disk->data = d;
grub_dprintf ("efidisk", "opening %s succeeded\n", name);
@@ -558,22 +557,20 @@
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
- grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
- dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"reading 0x%lx sectors at the sector 0x%llx from %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
- status = efi_call_5 (dio->read, dio, bio->media->media_id,
- (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
- (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
- buf);
+ status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
+ buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
@@ -586,21 +583,19 @@
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
- grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
- dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"writing 0x%lx sectors at the sector 0x%llx to %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
- status = efi_call_5 (dio->write, dio, bio->media->media_id,
- (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
- (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
+ status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
(void *) buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");
=== modified file 'grub-core/disk/i386/pc/biosdisk.c'
--- grub-core/disk/i386/pc/biosdisk.c 2011-01-04 14:42:47 +0000
+++ grub-core/disk/i386/pc/biosdisk.c 2011-03-29 00:02:28 +0000
@@ -338,7 +338,8 @@
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
- data->sectors = 32;
+ data->sectors = 8;
+ disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
@@ -347,6 +348,8 @@
/* HDD */
int version;
+ disk->log_sector_size = 9;
+
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
@@ -367,6 +370,15 @@
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = drp->cylinders * drp->heads * drp->sectors;
+ if (drp->bytes_per_sector
+ && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
+ && drp->bytes_per_sector >= 512
+ && drp->bytes_per_sector <= 16384)
+ {
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < drp->bytes_per_sector;
+ disk->log_sector_size++);
+ }
}
}
}
@@ -429,7 +441,7 @@
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
- << GRUB_DISK_SECTOR_BITS));
+ << disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
@@ -443,9 +455,6 @@
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
- dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2;
- dap->block >>= 2;
-
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
@@ -501,10 +510,12 @@
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
-get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
+get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
grub_uint32_t offset;
+ struct grub_biosdisk_data *data = disk->data;
+ grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
@@ -512,8 +523,8 @@
size = sectors - offset;
/* Limit the max to 0x7f because of Phoenix EDD. */
- if (size > 0x7f)
- size = 0x7f;
+ if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
+ size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
return size;
}
@@ -522,21 +533,11 @@
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
- struct grub_biosdisk_data *data = disk->data;
-
while (size)
{
grub_size_t len;
- grub_size_t cdoff = 0;
-
- len = get_safe_sectors (sector, data->sectors);
-
- if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
- {
- cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS;
- len = ALIGN_UP (sector + len, 4) - (sector & ~3);
- sector &= ~3;
- }
+
+ len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
@@ -545,9 +546,10 @@
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
- grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff),
- len << GRUB_DISK_SECTOR_BITS);
- buf += len << GRUB_DISK_SECTOR_BITS;
+ grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+ len << disk->log_sector_size);
+
+ buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
@@ -568,18 +570,18 @@
{
grub_size_t len;
- len = get_safe_sectors (sector, data->sectors);
+ len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
- len << GRUB_DISK_SECTOR_BITS);
+ len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
- buf += len << GRUB_DISK_SECTOR_BITS;
+ buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
=== modified file 'grub-core/disk/scsi.c'
--- grub-core/disk/scsi.c 2011-01-22 12:22:46 +0000
+++ grub-core/disk/scsi.c 2011-03-29 00:02:28 +0000
@@ -463,15 +463,20 @@
return err;
}
- /* SCSI blocks can be something else than 512, although GRUB
- wants 512 byte blocks. */
- disk->total_sectors = ((grub_uint64_t)scsi->size
- * (grub_uint64_t)scsi->blocksize)
- >> GRUB_DISK_SECTOR_BITS;
+ disk->total_sectors = scsi->size;
+ if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
+ {
+ grub_free (scsi);
+ return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+ scsi->blocksize);
+ }
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < scsi->blocksize;
+ disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
- grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
+ grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
return GRUB_ERR_NONE;
@@ -501,25 +506,6 @@
scsi = disk->data;
- /* SCSI sectors are variable in size. GRUB uses 512 byte
- sectors. */
- if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
- {
- unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
- if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unsupported SCSI block size");
-
- grub_uint32_t sector_mod = 0;
- sector = grub_divmod64 (sector, spb, §or_mod);
-
- if (! (sector_mod == 0 && size % spb == 0))
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unaligned SCSI read not supported");
-
- size /= spb;
- }
-
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{
=== modified file 'grub-core/kern/disk.c'
--- grub-core/kern/disk.c 2010-09-20 19:45:06 +0000
+++ grub-core/kern/disk.c 2011-03-29 00:02:28 +0000
@@ -247,6 +247,7 @@
disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
if (! disk)
return 0;
+ disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
p = find_part_sep (name);
if (p)
@@ -266,7 +267,6 @@
if (! disk->name)
goto fail;
-
for (dev = grub_disk_dev_list; dev; dev = dev->next)
{
if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
@@ -282,6 +282,14 @@
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
goto fail;
}
+ if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
+ || disk->log_sector_size < GRUB_DISK_SECTOR_BITS)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "sector sizes of %d bytes aren't supported yet",
+ (1 << disk->log_sector_size));
+ goto fail;
+ }
disk->dev = dev;
@@ -373,14 +381,23 @@
*sector += start;
}
- if (disk->total_sectors <= *sector
- || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
+ if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
+ && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector
+ || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
+ >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors
+ << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) - *sector))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
return GRUB_ERR_NONE;
}
+static inline grub_disk_addr_t
+transform_sector (grub_disk_t disk, grub_disk_addr_t sector)
+{
+ return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+}
+
/* Read data from the disk. */
grub_err_t
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
@@ -433,27 +450,39 @@
else
{
/* Otherwise read data from the disk actually. */
- if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
- || (disk->dev->read) (disk, start_sector,
- GRUB_DISK_CACHE_SIZE, tmp_buf)
+ if ((disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
+ && start_sector + GRUB_DISK_CACHE_SIZE
+ > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+ || (disk->dev->read) (disk, transform_sector (disk, start_sector),
+ 1 << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size), tmp_buf)
!= GRUB_ERR_NONE)
{
/* Uggh... Failed. Instead, just read necessary data. */
unsigned num;
char *p;
+ grub_disk_addr_t aligned_sector;
grub_errno = GRUB_ERR_NONE;
- num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS);
+ aligned_sector = (sector & ~((1 << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS))
+ - 1));
+ real_offset += ((sector - aligned_sector)
+ << GRUB_DISK_SECTOR_BITS);
+ num = ((size + real_offset + (1 << (disk->log_sector_size))
+ - 1) >> (disk->log_sector_size));
- p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS);
+ p = grub_realloc (tmp_buf, num << disk->log_sector_size);
if (!p)
goto finish;
tmp_buf = p;
- if ((disk->dev->read) (disk, sector, num, tmp_buf))
+ if ((disk->dev->read) (disk, transform_sector (disk,
+ aligned_sector),
+ num, tmp_buf))
{
grub_error_push ();
grub_dprintf ("disk", "%s read failed\n", disk->name);
@@ -528,25 +557,31 @@
grub_off_t offset, grub_size_t size, const void *buf)
{
unsigned real_offset;
+ grub_disk_addr_t aligned_sector;
grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
return -1;
- real_offset = offset;
+ aligned_sector = (sector & ~((1 << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) - 1));
+ real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
+ sector = aligned_sector;
while (size)
{
- if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
+ if (real_offset != 0 || (size < (1U << disk->log_sector_size)
+ && size != 0))
{
- char tmp_buf[GRUB_DISK_SECTOR_SIZE];
+ char tmp_buf[1 << disk->log_sector_size];
grub_size_t len;
grub_partition_t part;
part = disk->partition;
disk->partition = 0;
- if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
+ if (grub_disk_read (disk, sector,
+ 0, (1 << disk->log_sector_size), tmp_buf)
!= GRUB_ERR_NONE)
{
disk->partition = part;
@@ -554,7 +589,7 @@
}
disk->partition = part;
- len = GRUB_DISK_SECTOR_SIZE - real_offset;
+ len = (1 << disk->log_sector_size) - real_offset;
if (len > size)
len = size;
@@ -565,7 +600,7 @@
if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
goto finish;
- sector++;
+ sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
buf = (char *) buf + len;
size -= len;
real_offset = 0;
@@ -575,8 +610,8 @@
grub_size_t len;
grub_size_t n;
- len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
- n = size >> GRUB_DISK_SECTOR_BITS;
+ len = size & ~((1 << disk->log_sector_size) - 1);
+ n = size >> disk->log_sector_size;
if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
goto finish;
@@ -599,6 +634,8 @@
{
if (disk->partition)
return grub_partition_get_len (disk->partition);
+ else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN)
+ return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
else
- return disk->total_sectors;
+ return GRUB_DISK_SIZE_UNKNOWN;
}
=== modified file 'grub-core/kern/emu/hostdisk.c'
--- grub-core/kern/emu/hostdisk.c 2011-03-26 11:59:02 +0000
+++ grub-core/kern/emu/hostdisk.c 2011-03-29 00:02:28 +0000
@@ -42,6 +42,7 @@
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
+# include <sys/mount.h>
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
@@ -264,6 +265,7 @@
# else
unsigned long long nr;
# endif
+ int sector_size;
int fd;
fd = open (map[drive].device, O_RDONLY);
@@ -295,16 +297,28 @@
goto fail;
}
+ if (ioctl (fd, BLKSSZGET, §or_size))
+ {
+ close (fd);
+ goto fail;
+ }
+
close (fd);
+ if (sector_size & (sector_size - 1) || !sector_size)
+ goto fail;
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < sector_size;
+ disk->log_sector_size++);
+
# if defined (__APPLE__)
disk->total_sectors = nr;
# elif defined(__NetBSD__)
disk->total_sectors = label.d_secperunit;
# else
- disk->total_sectors = nr / 512;
+ disk->total_sectors = nr >> disk->log_sector_size;
- if (nr % 512)
+ if (nr & ((1 << disk->log_sector_size) - 1))
grub_util_error ("unaligned device size");
# endif
@@ -321,7 +335,7 @@
if (stat (map[drive].device, &st) < 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
- disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
+ disk->total_sectors = st.st_size >> disk->log_sector_size;
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
@@ -760,7 +774,7 @@
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
- offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
+ offset = (loff_t) sector << disk->log_sector_size;
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
@@ -770,7 +784,7 @@
}
#else
{
- off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
+ off_t offset = (off_t) sector << disk->log_sector_size;
if (lseek (fd, offset, SEEK_SET) != offset)
{
@@ -870,20 +884,21 @@
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
- if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
+ if (nread (fd, buf, (1 << disk->log_sector_size))
+ != (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
close (fd);
return grub_errno;
}
- buf += GRUB_DISK_SECTOR_SIZE;
+ buf += (1 << disk->log_sector_size);
size--;
}
#endif /* __linux__ */
- if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
- != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+ if (nread (fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
return grub_errno;
@@ -916,8 +931,8 @@
if (fd < 0)
return grub_errno;
- if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
- != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+ if (nwrite (fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
return grub_errno;
=== modified file 'grub-core/partmap/msdos.c'
--- grub-core/partmap/msdos.c 2011-02-12 06:59:04 +0000
+++ grub-core/partmap/msdos.c 2011-03-29 00:02:28 +0000
@@ -90,8 +90,11 @@
{
e = mbr.entries + p.index;
- p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
- p.len = grub_le_to_cpu32 (e->length);
+ p.start = p.offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta;
+ p.len = grub_le_to_cpu32 (e->length)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
p.msdostype = e->type;
grub_dprintf ("partition",
@@ -126,7 +129,9 @@
if (grub_msdos_partition_is_extended (e->type))
{
- p.offset = ext_offset + grub_le_to_cpu32 (e->start);
+ p.offset = ext_offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = p.offset;
@@ -204,8 +209,11 @@
e = mbr.entries + i;
if (!grub_msdos_partition_is_empty (e->type)
- && end > offset + grub_le_to_cpu32 (e->start))
- end = offset + grub_le_to_cpu32 (e->start);
+ && end > offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+ end = offset + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
/* If this is a GPT partition, this MBR is just a dummy. */
if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
@@ -219,7 +227,9 @@
if (grub_msdos_partition_is_extended (e->type))
{
- offset = ext_offset + grub_le_to_cpu32 (e->start);
+ offset = ext_offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = offset;
=== modified file 'include/grub/disk.h'
--- include/grub/disk.h 2010-10-08 21:27:27 +0000
+++ include/grub/disk.h 2011-03-29 00:02:28 +0000
@@ -100,6 +100,9 @@
/* The total number of sectors. */
grub_uint64_t total_sectors;
+ /* Logarithm of sector size. */
+ unsigned int log_sector_size;
+
/* The id used by the disk cache manager. */
unsigned long id;
@@ -132,9 +135,10 @@
/* The maximum number of disk caches. */
#define GRUB_DISK_CACHE_NUM 1021
-/* The size of a disk cache in sector units. */
-#define GRUB_DISK_CACHE_SIZE 8
-#define GRUB_DISK_CACHE_BITS 3
+/* The size of a disk cache in 512B units. Must be at least as big as the
+ largest supported sector size, currently 16K. */
+#define GRUB_DISK_CACHE_BITS 6
+#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS)
/* Return value of grub_disk_get_size() in case disk size is unknown. */
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 7:17 ` KESHAV P.R.
@ 2011-04-05 7:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 8:06 ` KESHAV P.R.
0 siblings, 1 reply; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-05 7:43 UTC (permalink / raw)
To: The development of GNU GRUB
On 05.04.2011 09:17, KESHAV P.R. wrote:
> In a crude benchmarking using s top watch, the
> time between selection of menuentry to seeing the kernel boot messages
> is approx 4 minutes (236 seconds) measured using a stop watch. I have
> not yet tested with an updated ovmf in qemu or in duet.
You push for a potentially harming change, yet when asked to try with
smaller numbers to see which value is optimal/required suddenly you stop
answering.
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 7:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-05 8:06 ` KESHAV P.R.
0 siblings, 0 replies; 21+ messages in thread
From: KESHAV P.R. @ 2011-04-05 8:06 UTC (permalink / raw)
To: The development of GNU GRUB
2011/4/5 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> On 05.04.2011 09:17, KESHAV P.R. wrote:
>>
>> In a crude benchmarking using stop watch, the
>> time between selection of menuentry to seeing the kernel boot messages
>> is approx 4 minutes (236 seconds) measured using a stop watch. I have
>> not yet tested with an updated ovmf in qemu or in duet.
>
> You push for a potentially harming change, yet when asked to try with
> smaller numbers to see which value is optimal/required suddenly you stop
> answering.
>
I didn't request (or push) for any change in the first place because i
do not know what that change does in the first place. I simply tried
to benchmark it to see whether such a problem occurs. This testing was
done with 1.99~rc1 release (not bzr trunk and not with the 16 KiB
alignment patch) and I am not sure whether the same results might
occur bzr trunk. I do not know whether the proposed change will solve
the problem because i am not a programmer. Of course i will test any
patch you send to me if i have time and if i am able to obtain any
useful info.
The only info you (phcoder) mentioned is that you tried for dynamic
cache allocation
(http://www.mail-archive.com/grub-devel@gnu.org/msg15793.html). If you
can provide an updated patch i will test it (is the blockio patch same
as this?). Sorry but i don't mean to offend anyone in this mail.
- Keshav
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-05 7:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-05 16:36 ` Aravind Srinivasan
0 siblings, 0 replies; 21+ messages in thread
From: Aravind Srinivasan @ 2011-04-05 16:36 UTC (permalink / raw)
To: The development of GNU GRUB
Tried the block IO patch. It is much better than the current default performance
of 1.99. For the same initrd image (160M), loading from USB took approx 20 secs.
I also tried changing the value of GRUB_DISK_CACHE_BITS from 6 to 8, and load
time improved to approx 12 secs.
Just to note, on Legacy Grub, this gets loaded almost in 3 secs.
Thanks,
Aravind
----- Original Message ----
From: Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Sent: Tue, April 5, 2011 12:36:35 AM
Subject: Re: Grub2 EFI: Image loading from USB takes too long
On 05.04.2011 08:32, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> On 05.04.2011 07:33, Aravind Srinivasan wrote:
>> include/grub/disk.h
>> <snip>
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8
>> #define GRUB_DISK_CACHE_BITS 3
>> <snip>
>>
>> I tried changing this value to 8192 - and the time it took to load the same
>> image came down to 10 secs !
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8192
>> #define GRUB_DISK_CACHE_BITS 13
>>
>> I am not sure of the reason for setting the cache size to a low value and any
>> possible issues in increasing this size. Appreciate any input on this.
> This value is a misnomer. It's not a cache size but a cache unit size. As
>immediate effect it has that if one reads a single 512B, sector one reads an
>entire block of 4K. Under normal conditions values of around 32K-128K
>(6-8/64-256) would be optimal. It seems that some EFI implementations do a
>"buffering" only to discard the buffered data. Some of the reports suggest that
>this braindamage is limited to disk io and doesn't happen with Block IO. Values
>you propose would result in 4M reads even when one needs just few sectors and so
>is suboptimal under normal conditions.
> I'll prepare few patches to investigate.
> After 1.99 the GRUB_DISK_CACHE_BITS will be increased to 6-8 range since, it's
>optimal and my AF support requires sector size to be smaller than cache unit
>size.
>
Attached a patch based on my AF patch which change to block IO.
-- Regards
Vladimir 'φ-coder/phcoder' Serbinenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
@ 2011-04-06 16:12 Aravind Srinivasan
2011-04-07 9:24 ` KESHAV P.R.
2011-04-08 16:33 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 2 replies; 21+ messages in thread
From: Aravind Srinivasan @ 2011-04-06 16:12 UTC (permalink / raw)
To: grub-devel
Dint see any further response on this. So can I assume the block-io patch
provided will become part of some official release ? If so, which one ? Do I
need to log a bug for this ?
Thanks,
Aravind
----- Original Message ----
From: Aravind Srinivasan <aravind_s_873@yahoo.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Sent: Tue, April 5, 2011 9:36:52 AM
Subject: Re: Grub2 EFI: Image loading from USB takes too long
Tried the block IO patch. It is much better than the current default performance
of 1.99. For the same initrd image (160M), loading from USB took approx 20 secs.
I also tried changing the value of GRUB_DISK_CACHE_BITS from 6 to 8, and load
time improved to approx 12 secs.
Just to note, on Legacy Grub, this gets loaded almost in 3 secs.
Thanks,
Aravind
----- Original Message ----
From: Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Sent: Tue, April 5, 2011 12:36:35 AM
Subject: Re: Grub2 EFI: Image loading from USB takes too long
On 05.04.2011 08:32, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> On 05.04.2011 07:33, Aravind Srinivasan wrote:
>> include/grub/disk.h
>> <snip>
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8
>> #define GRUB_DISK_CACHE_BITS 3
>> <snip>
>>
>> I tried changing this value to 8192 - and the time it took to load the same
>> image came down to 10 secs !
>> /* The size of a disk cache in sector units. */
>> #define GRUB_DISK_CACHE_SIZE 8192
>> #define GRUB_DISK_CACHE_BITS 13
>>
>> I am not sure of the reason for setting the cache size to a low value and any
>> possible issues in increasing this size. Appreciate any input on this.
> This value is a misnomer. It's not a cache size but a cache unit size. As
>immediate effect it has that if one reads a single 512B, sector one reads an
>entire block of 4K. Under normal conditions values of around 32K-128K
>(6-8/64-256) would be optimal. It seems that some EFI implementations do a
>"buffering" only to discard the buffered data. Some of the reports suggest that
>this braindamage is limited to disk io and doesn't happen with Block IO. Values
>you propose would result in 4M reads even when one needs just few sectors and so
>
>is suboptimal under normal conditions.
> I'll prepare few patches to investigate.
> After 1.99 the GRUB_DISK_CACHE_BITS will be increased to 6-8 range since, it's
>optimal and my AF support requires sector size to be smaller than cache unit
>size.
>
Attached a patch based on my AF patch which change to block IO.
-- Regards
Vladimir 'φ-coder/phcoder' Serbinenko
Insert mode
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-06 16:12 Grub2 EFI: Image loading from USB takes too long Aravind Srinivasan
@ 2011-04-07 9:24 ` KESHAV P.R.
2011-04-08 16:33 ` Vladimir 'φ-coder/phcoder' Serbinenko
1 sibling, 0 replies; 21+ messages in thread
From: KESHAV P.R. @ 2011-04-07 9:24 UTC (permalink / raw)
To: The development of GNU GRUB
On Wed, Apr 6, 2011 at 21:42, Aravind Srinivasan
<aravind_s_873@yahoo.com> wrote:
>
>
> Dint see any further response on this. So can I assume the block-io patch
> provided will become part of some official release ? If so, which one ? Do I
> need to log a bug for this ?
>
> Thanks,
> Aravind
>
> ----- Original Message ----
> From: Aravind Srinivasan <aravind_s_873@yahoo.com>
> To: The development of GNU GRUB <grub-devel@gnu.org>
> Sent: Tue, April 5, 2011 9:36:52 AM
> Subject: Re: Grub2 EFI: Image loading from USB takes too long
>
>
>
> Tried the block IO patch. It is much better than the current default performance
>
> of 1.99. For the same initrd image (160M), loading from USB took approx 20 secs.
>
> I also tried changing the value of GRUB_DISK_CACHE_BITS from 6 to 8, and load
> time improved to approx 12 secs.
> Just to note, on Legacy Grub, this gets loaded almost in 3 secs.
>
Just FYI, in my VirtualBox 4.0.4 (EFI64 UEFI 2.1) test using archboot
iso, the x86_64 kernel (2,249,632 bytes) and iniramfs (55,628,934
bytes) (both lzma compressed) load time dropped from 240 seconds to
160 seconds with blockio patch and GRUB_DISK_CACHE_BITS set to 8 (bzr
mainline 3176). I don't know why there is still about 2 min load time
but since this occurs in a VM (and using virtual sata cd drive), i
guess it will be faster with a physical cd in real hardware.
I also tested the kernel and initramfs files (booting from HDD, not
CD) in DUET (UEFI 2.3 x86_64). Without the patch the load time was 63
seconds. With the patch (and GRUB_DISK_CACHE_BITS=8) the load time
dropped to 16 seconds. I did not check load time from an actual cd but
i guess it will be only slighly more due to cd access speeds. I have
not yet tested the same with Fedora grub-legacy efi.
Regards.
Keshav
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-06 16:12 Grub2 EFI: Image loading from USB takes too long Aravind Srinivasan
2011-04-07 9:24 ` KESHAV P.R.
@ 2011-04-08 16:33 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-15 2:45 ` Bean
1 sibling, 1 reply; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-08 16:33 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 472 bytes --]
On 06.04.2011 18:12, Aravind Srinivasan wrote:
>
> Dint see any further response on this.
Well I'm mostly puzzled as to why RedHat's grub-legacy is faster. Which
FS is it?
> So can I assume the block-io patch
> provided will become part of some official release ? If so, which one ?
It will be committed after 1.99 is released. So it will be in 2.00
> Do I
> need to log a bug for this ?
No need.
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-08 16:33 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-15 2:45 ` Bean
2011-04-15 6:55 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 21+ messages in thread
From: Bean @ 2011-04-15 2:45 UTC (permalink / raw)
To: The development of GNU GRUB
Hi,
I believe this is caused by the read algorithm of grub2. If the file
is continuous, grub legacy will read it in one pass, while grub2 will
break it up into small blocks, this will slow it down dramatically. I
haven't tested efi, but in bios mode, sometimes it takes twice as long
for grub2 to read the same file.
2011/4/9 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> On 06.04.2011 18:12, Aravind Srinivasan wrote:
>>
>> Dint see any further response on this.
> Well I'm mostly puzzled as to why RedHat's grub-legacy is faster. Which
> FS is it?
>> So can I assume the block-io patch
>> provided will become part of some official release ? If so, which one ?
> It will be committed after 1.99 is released. So it will be in 2.00
>> Do I
>> need to log a bug for this ?
> No need.
>
> --
> Regards
> Vladimir 'φ-coder/phcoder' Serbinenko
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>
--
Bean
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-15 2:45 ` Bean
@ 2011-04-15 6:55 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-15 8:18 ` Seth Goldberg
2011-04-25 4:14 ` Bean
0 siblings, 2 replies; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-15 6:55 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 991 bytes --]
On 15.04.2011 04:45, Bean wrote:
> Hi,
>
> I believe this is caused by the read algorithm of grub2. If the file
> is continuous, grub legacy will read it in one pass, while grub2 will
> break it up into small blocks, this will slow it down dramatically. I
> haven't tested efi, but in bios mode, sometimes it takes twice as long
> for grub2 to read the same file.
>
That's why I asked which fs it is. On an FS like ext2 or fat Both GRUBs
are limited by the need of rereading indirect blocks or FAT chain (sure
this can be aleviated by buffering and merging the nodes but neither
GRUB Legacy nor GRUB2 does it). Currently it makes difference only on
extent-based filesystems like ext, xfs or btrfs. I don't want to embark
on adding another code path in grub_disk_read before having enough info
to confirm this theory yet neither the original reporter nor the others
answered which FS they conducted experiments on.
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-15 6:55 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-15 8:18 ` Seth Goldberg
2011-04-15 19:54 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-25 4:14 ` Bean
1 sibling, 1 reply; 21+ messages in thread
From: Seth Goldberg @ 2011-04-15 8:18 UTC (permalink / raw)
To: The development of GNU GRUB
This problem is present, at least, on ZFS.
--S
On Apr 14, 2011, at 8:55 PM, Vladimir 'φ-coder/phcoder' Serbinenko<phcoder@gmail.com> wrote:
> On 15.04.2011 04:45, Bean wrote:
>> Hi,
>>
>> I believe this is caused by the read algorithm of grub2. If the file
>> is continuous, grub legacy will read it in one pass, while grub2 will
>> break it up into small blocks, this will slow it down dramatically. I
>> haven't tested efi, but in bios mode, sometimes it takes twice as long
>> for grub2 to read the same file.
>>
> That's why I asked which fs it is. On an FS like ext2 or fat Both GRUBs
> are limited by the need of rereading indirect blocks or FAT chain (sure
> this can be aleviated by buffering and merging the nodes but neither
> GRUB Legacy nor GRUB2 does it). Currently it makes difference only on
> extent-based filesystems like ext, xfs or btrfs. I don't want to embark
> on adding another code path in grub_disk_read before having enough info
> to confirm this theory yet neither the original reporter nor the others
> answered which FS they conducted experiments on.
>
> --
> Regards
> Vladimir 'φ-coder/phcoder' Serbinenko
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
@ 2011-04-15 16:07 Finnbarr P. Murphy
0 siblings, 0 replies; 21+ messages in thread
From: Finnbarr P. Murphy @ 2011-04-15 16:07 UTC (permalink / raw)
To: grub-devel
This problem is also present on ext3 and ext4
- F
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-15 8:18 ` Seth Goldberg
@ 2011-04-15 19:54 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-06-23 16:02 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-15 19:54 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 188 bytes --]
On 15.04.2011 10:18, Seth Goldberg wrote:
> This problem is present, at least, on ZFS.
Could you test the attached patch then?
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 4096.diff --]
[-- Type: text/x-diff; name="4096.diff", Size: 30578 bytes --]
=== modified file 'grub-core/disk/efi/efidisk.c'
--- grub-core/disk/efi/efidisk.c 2010-09-21 12:41:23 +0000
+++ grub-core/disk/efi/efidisk.c 2011-04-15 16:15:06 +0000
@@ -33,12 +33,10 @@
grub_efi_device_path_t *device_path;
grub_efi_device_path_t *last_device_path;
grub_efi_block_io_t *block_io;
- grub_efi_disk_io_t *disk_io;
struct grub_efidisk_data *next;
};
-/* GUIDs. */
-static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
+/* GUID. */
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
static struct grub_efidisk_data *fd_devices;
@@ -143,7 +141,7 @@
struct grub_efidisk_data *devices = 0;
/* Find handles which support the disk io interface. */
- handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid,
+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid,
0, &num_handles);
if (! handles)
return 0;
@@ -155,7 +153,6 @@
grub_efi_device_path_t *ldp;
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
- grub_efi_disk_io_t *dio;
dp = grub_efi_get_device_path (*handle);
if (! dp)
@@ -168,9 +165,7 @@
bio = grub_efi_open_protocol (*handle, &block_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- dio = grub_efi_open_protocol (*handle, &disk_io_guid,
- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (! bio || ! dio)
+ if (! bio)
/* This should not happen... Why? */
continue;
@@ -186,7 +181,6 @@
d->device_path = dp;
d->last_device_path = ldp;
d->block_io = bio;
- d->disk_io = dio;
d->next = devices;
devices = d;
}
@@ -536,8 +530,13 @@
and total sectors should be replaced with total blocks. */
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
- * (m->block_size >> GRUB_DISK_SECTOR_BITS));
+ disk->total_sectors = m->last_block;
+ if (m->block_size & (m->block_size - 1) || !m->block_size)
+ return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+ m->block_size);
+ for (disk->log_sector_size = 0;
+ (1U << disk->log_sector_size) < m->block_size;
+ disk->log_sector_size++);
disk->data = d;
grub_dprintf ("efidisk", "opening %s succeeded\n", name);
@@ -558,22 +557,20 @@
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
- grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
- dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"reading 0x%lx sectors at the sector 0x%llx from %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
- status = efi_call_5 (dio->read, dio, bio->media->media_id,
- (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
- (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
- buf);
+ status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
+ buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
@@ -586,21 +583,19 @@
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
- grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
- dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"writing 0x%lx sectors at the sector 0x%llx to %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
- status = efi_call_5 (dio->write, dio, bio->media->media_id,
- (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
- (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
+ status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
(void *) buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");
=== modified file 'grub-core/disk/i386/pc/biosdisk.c'
--- grub-core/disk/i386/pc/biosdisk.c 2011-01-04 14:42:47 +0000
+++ grub-core/disk/i386/pc/biosdisk.c 2011-03-29 00:02:55 +0000
@@ -338,7 +338,8 @@
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
- data->sectors = 32;
+ data->sectors = 8;
+ disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
@@ -347,6 +348,8 @@
/* HDD */
int version;
+ disk->log_sector_size = 9;
+
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
@@ -367,6 +370,15 @@
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = drp->cylinders * drp->heads * drp->sectors;
+ if (drp->bytes_per_sector
+ && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
+ && drp->bytes_per_sector >= 512
+ && drp->bytes_per_sector <= 16384)
+ {
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < drp->bytes_per_sector;
+ disk->log_sector_size++);
+ }
}
}
}
@@ -429,7 +441,7 @@
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
- << GRUB_DISK_SECTOR_BITS));
+ << disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
@@ -443,9 +455,6 @@
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
- dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2;
- dap->block >>= 2;
-
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
@@ -501,10 +510,12 @@
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
-get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
+get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
grub_uint32_t offset;
+ struct grub_biosdisk_data *data = disk->data;
+ grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
@@ -512,8 +523,8 @@
size = sectors - offset;
/* Limit the max to 0x7f because of Phoenix EDD. */
- if (size > 0x7f)
- size = 0x7f;
+ if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
+ size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
return size;
}
@@ -522,21 +533,11 @@
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
- struct grub_biosdisk_data *data = disk->data;
-
while (size)
{
grub_size_t len;
- grub_size_t cdoff = 0;
-
- len = get_safe_sectors (sector, data->sectors);
-
- if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
- {
- cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS;
- len = ALIGN_UP (sector + len, 4) - (sector & ~3);
- sector &= ~3;
- }
+
+ len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
@@ -545,9 +546,10 @@
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
- grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff),
- len << GRUB_DISK_SECTOR_BITS);
- buf += len << GRUB_DISK_SECTOR_BITS;
+ grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+ len << disk->log_sector_size);
+
+ buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
@@ -568,18 +570,18 @@
{
grub_size_t len;
- len = get_safe_sectors (sector, data->sectors);
+ len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
- len << GRUB_DISK_SECTOR_BITS);
+ len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
- buf += len << GRUB_DISK_SECTOR_BITS;
+ buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
=== modified file 'grub-core/disk/scsi.c'
--- grub-core/disk/scsi.c 2011-01-22 12:22:46 +0000
+++ grub-core/disk/scsi.c 2011-03-29 00:02:55 +0000
@@ -463,15 +463,20 @@
return err;
}
- /* SCSI blocks can be something else than 512, although GRUB
- wants 512 byte blocks. */
- disk->total_sectors = ((grub_uint64_t)scsi->size
- * (grub_uint64_t)scsi->blocksize)
- >> GRUB_DISK_SECTOR_BITS;
+ disk->total_sectors = scsi->size;
+ if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
+ {
+ grub_free (scsi);
+ return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+ scsi->blocksize);
+ }
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < scsi->blocksize;
+ disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
- grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
+ grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
return GRUB_ERR_NONE;
@@ -501,25 +506,6 @@
scsi = disk->data;
- /* SCSI sectors are variable in size. GRUB uses 512 byte
- sectors. */
- if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
- {
- unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
- if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unsupported SCSI block size");
-
- grub_uint32_t sector_mod = 0;
- sector = grub_divmod64 (sector, spb, §or_mod);
-
- if (! (sector_mod == 0 && size % spb == 0))
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unaligned SCSI read not supported");
-
- size /= spb;
- }
-
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{
=== modified file 'grub-core/kern/disk.c'
--- grub-core/kern/disk.c 2010-09-20 19:45:06 +0000
+++ grub-core/kern/disk.c 2011-04-15 19:42:29 +0000
@@ -247,6 +247,7 @@
disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
if (! disk)
return 0;
+ disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
p = find_part_sep (name);
if (p)
@@ -266,7 +267,6 @@
if (! disk->name)
goto fail;
-
for (dev = grub_disk_dev_list; dev; dev = dev->next)
{
if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
@@ -282,6 +282,14 @@
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
goto fail;
}
+ if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
+ || disk->log_sector_size < GRUB_DISK_SECTOR_BITS)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "sector sizes of %d bytes aren't supported yet",
+ (1 << disk->log_sector_size));
+ goto fail;
+ }
disk->dev = dev;
@@ -373,21 +381,110 @@
*sector += start;
}
- if (disk->total_sectors <= *sector
- || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
+ if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
+ && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector
+ || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
+ >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors
+ << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) - *sector))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
return GRUB_ERR_NONE;
}
+static inline grub_disk_addr_t
+transform_sector (grub_disk_t disk, grub_disk_addr_t sector)
+{
+ return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+}
+
+/* Small read (less than cache size and not pass across cache unit boundaries).
+ sector is already adjusted and is divisible by cache unit size.
+ */
+static grub_err_t
+grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_off_t offset, grub_size_t size, void *buf)
+{
+ char *data;
+ char *tmp_buf;
+
+ /* Fetch the cache. */
+ data = grub_disk_cache_fetch (disk->dev->id, disk->id, sector);
+ if (data)
+ {
+ /* Just copy it! */
+ grub_memcpy (buf, data + offset, size);
+ grub_disk_cache_unlock (disk->dev->id, disk->id, sector);
+ return GRUB_ERR_NONE;
+ }
+
+ /* Allocate a temporary buffer. */
+ tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
+ if (! tmp_buf)
+ return grub_errno;
+
+ /* Otherwise read data from the disk actually. */
+ if (disk->total_sectors == GRUB_DISK_SIZE_UNKNOWN
+ || sector + GRUB_DISK_CACHE_SIZE
+ < (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+ {
+ grub_err_t err;
+ err = (disk->dev->read) (disk, transform_sector (disk, sector),
+ 1 << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size), tmp_buf);
+ if (!err)
+ {
+ /* Copy it and store it in the disk cache. */
+ grub_memcpy (buf, tmp_buf + offset, size);
+ grub_disk_cache_store (disk->dev->id, disk->id,
+ sector, tmp_buf);
+ grub_free (tmp_buf);
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ grub_errno = GRUB_ERR_NONE;
+
+ {
+ /* Uggh... Failed. Instead, just read necessary data. */
+ unsigned num;
+ grub_disk_addr_t aligned_sector;
+
+ sector += (offset >> GRUB_DISK_SECTOR_BITS);
+ offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
+ aligned_sector = (sector & ~((1 << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS))
+ - 1));
+ offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
+ num = ((size + offset + (1 << (disk->log_sector_size))
+ - 1) >> (disk->log_sector_size));
+
+ tmp_buf = grub_malloc (num << disk->log_sector_size);
+ if (!tmp_buf)
+ return grub_errno;
+
+ if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector),
+ num, tmp_buf))
+ {
+ grub_error_push ();
+ grub_dprintf ("disk", "%s read failed\n", disk->name);
+ grub_error_pop ();
+ return grub_errno;
+ }
+ grub_memcpy (buf, tmp_buf + offset, size);
+ return GRUB_ERR_NONE;
+ }
+}
+
/* Read data from the disk. */
grub_err_t
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf)
{
- char *tmp_buf;
- unsigned real_offset;
+ grub_off_t real_offset;
+ grub_disk_addr_t real_sector;
+ grub_size_t real_size;
/* First of all, check if the region is within the disk. */
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
@@ -399,126 +496,118 @@
return grub_errno;
}
+ real_sector = sector;
real_offset = offset;
-
- /* Allocate a temporary buffer. */
- tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
- if (! tmp_buf)
- return grub_errno;
-
- /* Until SIZE is zero... */
- while (size)
+ real_size = size;
+
+ /* First read until first cache boundary. */
+ if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
{
- char *data;
grub_disk_addr_t start_sector;
+ grub_size_t pos;
+ grub_err_t err;
grub_size_t len;
- grub_size_t pos;
- /* For reading bulk data. */
start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1);
pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS;
len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS)
- - pos - real_offset);
+ - pos - offset);
if (len > size)
len = size;
-
- /* Fetch the cache. */
- data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector);
- if (data)
- {
- /* Just copy it! */
- grub_memcpy (buf, data + pos + real_offset, len);
- grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector);
- }
- else
- {
- /* Otherwise read data from the disk actually. */
- if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
- || (disk->dev->read) (disk, start_sector,
- GRUB_DISK_CACHE_SIZE, tmp_buf)
- != GRUB_ERR_NONE)
- {
- /* Uggh... Failed. Instead, just read necessary data. */
- unsigned num;
- char *p;
-
- grub_errno = GRUB_ERR_NONE;
-
- num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS);
-
- p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS);
- if (!p)
- goto finish;
-
- tmp_buf = p;
-
- if ((disk->dev->read) (disk, sector, num, tmp_buf))
- {
- grub_error_push ();
- grub_dprintf ("disk", "%s read failed\n", disk->name);
- grub_error_pop ();
- goto finish;
- }
-
- grub_memcpy (buf, tmp_buf + real_offset, size);
-
- /* Call the read hook, if any. */
- if (disk->read_hook)
- while (size)
- {
- grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size;
- (disk->read_hook) (sector, real_offset,
- to_read);
- if (grub_errno != GRUB_ERR_NONE)
- goto finish;
-
- sector++;
- size -= to_read - real_offset;
- real_offset = 0;
- }
-
- /* This must be the end. */
- goto finish;
- }
-
- /* Copy it and store it in the disk cache. */
- grub_memcpy (buf, tmp_buf + pos + real_offset, len);
- grub_disk_cache_store (disk->dev->id, disk->id,
- start_sector, tmp_buf);
- }
-
- /* Call the read hook, if any. */
- if (disk->read_hook)
- {
- grub_disk_addr_t s = sector;
- grub_size_t l = len;
-
- while (l)
- {
- (disk->read_hook) (s, real_offset,
- ((l > GRUB_DISK_SECTOR_SIZE)
- ? GRUB_DISK_SECTOR_SIZE
- : l));
-
- if (l < GRUB_DISK_SECTOR_SIZE - real_offset)
- break;
-
- s++;
- l -= GRUB_DISK_SECTOR_SIZE - real_offset;
- real_offset = 0;
- }
- }
-
- sector = start_sector + GRUB_DISK_CACHE_SIZE;
+ err = grub_disk_read_small (disk, start_sector,
+ offset + pos, len, buf);
+ if (err)
+ return err;
buf = (char *) buf + len;
size -= len;
- real_offset = 0;
- }
-
- finish:
-
- grub_free (tmp_buf);
+ offset += len;
+ sector += (offset >> GRUB_DISK_SECTOR_BITS);
+ offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
+ }
+
+ /* Until SIZE is zero... */
+ while (size >= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS))
+ {
+ char *data = NULL;
+ grub_disk_addr_t agglomerate;
+ grub_err_t err;
+
+ /* agglomerate read until we find a first cached entry. */
+ for (agglomerate = 0; agglomerate
+ < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS));
+ agglomerate++)
+ {
+ data = grub_disk_cache_fetch (disk->dev->id, disk->id,
+ sector + (agglomerate
+ << GRUB_DISK_CACHE_BITS));
+ if (data)
+ break;
+ }
+
+ if (agglomerate)
+ {
+ grub_disk_addr_t i;
+
+ err = (disk->dev->read) (disk, transform_sector (disk, sector),
+ agglomerate << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size),
+ buf);
+ if (err)
+ return err;
+
+ for (i = 0; i < agglomerate; i ++)
+ grub_disk_cache_store (disk->dev->id, disk->id,
+ sector + (i << GRUB_DISK_CACHE_BITS),
+ (char *) buf
+ + (i << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS)));
+
+ sector += agglomerate << GRUB_DISK_CACHE_BITS;
+ size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
+ buf = (char *) buf
+ + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
+ }
+
+ if (data)
+ {
+ grub_memcpy (buf, data, GRUB_DISK_CACHE_SIZE);
+ sector += GRUB_DISK_CACHE_SIZE;
+ buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
+ size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
+ grub_disk_cache_unlock (disk->dev->id, disk->id,
+ sector + (agglomerate
+ << GRUB_DISK_CACHE_BITS));
+ }
+ }
+
+ /* And now read the last part. */
+ if (size)
+ {
+ grub_err_t err;
+ err = grub_disk_read_small (disk, sector, 0, size, buf);
+ if (err)
+ return err;
+ }
+
+ /* Call the read hook, if any. */
+ if (disk->read_hook)
+ {
+ grub_disk_addr_t s = real_sector;
+ grub_size_t l = real_size;
+ grub_off_t o = real_offset;
+
+ while (l)
+ {
+ (disk->read_hook) (s, o,
+ ((l > GRUB_DISK_SECTOR_SIZE)
+ ? GRUB_DISK_SECTOR_SIZE
+ : l));
+ s++;
+ l -= GRUB_DISK_SECTOR_SIZE - o;
+ o = 0;
+ }
+ }
return grub_errno;
}
@@ -528,25 +617,31 @@
grub_off_t offset, grub_size_t size, const void *buf)
{
unsigned real_offset;
+ grub_disk_addr_t aligned_sector;
grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
return -1;
- real_offset = offset;
+ aligned_sector = (sector & ~((1 << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) - 1));
+ real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
+ sector = aligned_sector;
while (size)
{
- if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
+ if (real_offset != 0 || (size < (1U << disk->log_sector_size)
+ && size != 0))
{
- char tmp_buf[GRUB_DISK_SECTOR_SIZE];
+ char tmp_buf[1 << disk->log_sector_size];
grub_size_t len;
grub_partition_t part;
part = disk->partition;
disk->partition = 0;
- if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
+ if (grub_disk_read (disk, sector,
+ 0, (1 << disk->log_sector_size), tmp_buf)
!= GRUB_ERR_NONE)
{
disk->partition = part;
@@ -554,7 +649,7 @@
}
disk->partition = part;
- len = GRUB_DISK_SECTOR_SIZE - real_offset;
+ len = (1 << disk->log_sector_size) - real_offset;
if (len > size)
len = size;
@@ -565,7 +660,7 @@
if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
goto finish;
- sector++;
+ sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
buf = (char *) buf + len;
size -= len;
real_offset = 0;
@@ -575,8 +670,8 @@
grub_size_t len;
grub_size_t n;
- len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
- n = size >> GRUB_DISK_SECTOR_BITS;
+ len = size & ~((1 << disk->log_sector_size) - 1);
+ n = size >> disk->log_sector_size;
if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
goto finish;
@@ -599,6 +694,8 @@
{
if (disk->partition)
return grub_partition_get_len (disk->partition);
+ else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN)
+ return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
else
- return disk->total_sectors;
+ return GRUB_DISK_SIZE_UNKNOWN;
}
=== modified file 'grub-core/kern/emu/hostdisk.c'
--- grub-core/kern/emu/hostdisk.c 2011-03-26 11:59:02 +0000
+++ grub-core/kern/emu/hostdisk.c 2011-03-29 00:02:55 +0000
@@ -42,6 +42,7 @@
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
+# include <sys/mount.h>
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
@@ -264,6 +265,7 @@
# else
unsigned long long nr;
# endif
+ int sector_size;
int fd;
fd = open (map[drive].device, O_RDONLY);
@@ -295,16 +297,28 @@
goto fail;
}
+ if (ioctl (fd, BLKSSZGET, §or_size))
+ {
+ close (fd);
+ goto fail;
+ }
+
close (fd);
+ if (sector_size & (sector_size - 1) || !sector_size)
+ goto fail;
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < sector_size;
+ disk->log_sector_size++);
+
# if defined (__APPLE__)
disk->total_sectors = nr;
# elif defined(__NetBSD__)
disk->total_sectors = label.d_secperunit;
# else
- disk->total_sectors = nr / 512;
+ disk->total_sectors = nr >> disk->log_sector_size;
- if (nr % 512)
+ if (nr & ((1 << disk->log_sector_size) - 1))
grub_util_error ("unaligned device size");
# endif
@@ -321,7 +335,7 @@
if (stat (map[drive].device, &st) < 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
- disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
+ disk->total_sectors = st.st_size >> disk->log_sector_size;
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
@@ -760,7 +774,7 @@
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
- offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
+ offset = (loff_t) sector << disk->log_sector_size;
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
@@ -770,7 +784,7 @@
}
#else
{
- off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
+ off_t offset = (off_t) sector << disk->log_sector_size;
if (lseek (fd, offset, SEEK_SET) != offset)
{
@@ -870,20 +884,21 @@
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
- if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
+ if (nread (fd, buf, (1 << disk->log_sector_size))
+ != (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
close (fd);
return grub_errno;
}
- buf += GRUB_DISK_SECTOR_SIZE;
+ buf += (1 << disk->log_sector_size);
size--;
}
#endif /* __linux__ */
- if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
- != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+ if (nread (fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
return grub_errno;
@@ -916,8 +931,8 @@
if (fd < 0)
return grub_errno;
- if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
- != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+ if (nwrite (fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
return grub_errno;
=== modified file 'grub-core/partmap/msdos.c'
--- grub-core/partmap/msdos.c 2011-02-12 06:59:04 +0000
+++ grub-core/partmap/msdos.c 2011-03-29 00:02:55 +0000
@@ -90,8 +90,11 @@
{
e = mbr.entries + p.index;
- p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
- p.len = grub_le_to_cpu32 (e->length);
+ p.start = p.offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta;
+ p.len = grub_le_to_cpu32 (e->length)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
p.msdostype = e->type;
grub_dprintf ("partition",
@@ -126,7 +129,9 @@
if (grub_msdos_partition_is_extended (e->type))
{
- p.offset = ext_offset + grub_le_to_cpu32 (e->start);
+ p.offset = ext_offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = p.offset;
@@ -204,8 +209,11 @@
e = mbr.entries + i;
if (!grub_msdos_partition_is_empty (e->type)
- && end > offset + grub_le_to_cpu32 (e->start))
- end = offset + grub_le_to_cpu32 (e->start);
+ && end > offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+ end = offset + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
/* If this is a GPT partition, this MBR is just a dummy. */
if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
@@ -219,7 +227,9 @@
if (grub_msdos_partition_is_extended (e->type))
{
- offset = ext_offset + grub_le_to_cpu32 (e->start);
+ offset = ext_offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = offset;
=== modified file 'include/grub/disk.h'
--- include/grub/disk.h 2010-10-08 21:27:27 +0000
+++ include/grub/disk.h 2011-03-29 00:02:55 +0000
@@ -100,6 +100,9 @@
/* The total number of sectors. */
grub_uint64_t total_sectors;
+ /* Logarithm of sector size. */
+ unsigned int log_sector_size;
+
/* The id used by the disk cache manager. */
unsigned long id;
@@ -132,9 +135,10 @@
/* The maximum number of disk caches. */
#define GRUB_DISK_CACHE_NUM 1021
-/* The size of a disk cache in sector units. */
-#define GRUB_DISK_CACHE_SIZE 8
-#define GRUB_DISK_CACHE_BITS 3
+/* The size of a disk cache in 512B units. Must be at least as big as the
+ largest supported sector size, currently 16K. */
+#define GRUB_DISK_CACHE_BITS 6
+#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS)
/* Return value of grub_disk_get_size() in case disk size is unknown. */
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-15 6:55 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-15 8:18 ` Seth Goldberg
@ 2011-04-25 4:14 ` Bean
2011-04-25 10:58 ` Vladimir 'φ-coder/phcoder' Serbinenko
1 sibling, 1 reply; 21+ messages in thread
From: Bean @ 2011-04-25 4:14 UTC (permalink / raw)
To: The development of GNU GRUB
Hi,
This effects ALL fs since grub_disk_read will break it into 8192
blocks, regardless of what the upper fs asks. In burg, I add another
function to read the blocks directly and skip the cache, which results
in much faster reads for large continuous file.
2011/4/15 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> On 15.04.2011 04:45, Bean wrote:
>> Hi,
>>
>> I believe this is caused by the read algorithm of grub2. If the file
>> is continuous, grub legacy will read it in one pass, while grub2 will
>> break it up into small blocks, this will slow it down dramatically. I
>> haven't tested efi, but in bios mode, sometimes it takes twice as long
>> for grub2 to read the same file.
>>
> That's why I asked which fs it is. On an FS like ext2 or fat Both GRUBs
> are limited by the need of rereading indirect blocks or FAT chain (sure
> this can be aleviated by buffering and merging the nodes but neither
> GRUB Legacy nor GRUB2 does it). Currently it makes difference only on
> extent-based filesystems like ext, xfs or btrfs. I don't want to embark
> on adding another code path in grub_disk_read before having enough info
> to confirm this theory yet neither the original reporter nor the others
> answered which FS they conducted experiments on.
>
> --
> Regards
> Vladimir 'φ-coder/phcoder' Serbinenko
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>
--
Bean
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-25 4:14 ` Bean
@ 2011-04-25 10:58 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-26 3:03 ` Bean
0 siblings, 1 reply; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-25 10:58 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 2094 bytes --]
On 25.04.2011 06:14, Bean wrote:
> Hi,
>
> This effects ALL fs since grub_disk_read will break it into 8192
> blocks, regardless of what the upper fs asks.
Non-extent based FS simply don't do any direct reads bigger than that
unless they implement block pointer buffering and none of our fs does
> In burg, I add another
> function to read the blocks directly and skip the cache, which results
> in much faster reads for large continuous file.
Which is an example of bad design. Rather than improving the existing
function to do both caching and unbroken read (like in my 4096 branch)
you have 2 functions and force upper layers to do the tradeoffs and care
about matters which should be abstracted and invisible to them.
> 2011/4/15 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
>> On 15.04.2011 04:45, Bean wrote:
>>> Hi,
>>>
>>> I believe this is caused by the read algorithm of grub2. If the file
>>> is continuous, grub legacy will read it in one pass, while grub2 will
>>> break it up into small blocks, this will slow it down dramatically. I
>>> haven't tested efi, but in bios mode, sometimes it takes twice as long
>>> for grub2 to read the same file.
>>>
>> That's why I asked which fs it is. On an FS like ext2 or fat Both GRUBs
>> are limited by the need of rereading indirect blocks or FAT chain (sure
>> this can be aleviated by buffering and merging the nodes but neither
>> GRUB Legacy nor GRUB2 does it). Currently it makes difference only on
>> extent-based filesystems like ext, xfs or btrfs. I don't want to embark
>> on adding another code path in grub_disk_read before having enough info
>> to confirm this theory yet neither the original reporter nor the others
>> answered which FS they conducted experiments on.
>>
>> --
>> Regards
>> Vladimir 'φ-coder/phcoder' Serbinenko
>>
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>>
>
>
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-25 10:58 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-04-26 3:03 ` Bean
2011-04-26 10:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 21+ messages in thread
From: Bean @ 2011-04-26 3:03 UTC (permalink / raw)
To: The development of GNU GRUB
Hi,
It's not decided by fs driver, it's configured by a flag in
grub_file_open, which is passed to the disk driver. There is only a
few places where we can expect large file, such as linux/initrd
command. And in this case, caching is useless since we only use the
data once and caching would only flush out useful data unnecessarily.
By setting a flag to indicate direct read is required, we can optimize
access for such situation while keeping the cache for others. This is
similar to the pass through flag for linux/windows.
> Which is an example of bad design. Rather than improving the existing
> function to do both caching and unbroken read (like in my 4096 branch)
> you have 2 functions and force upper layers to do the tradeoffs and care
> about matters which should be abstracted and invisible to them.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-26 3:03 ` Bean
@ 2011-04-26 10:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 0 replies; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-04-26 10:36 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]
On 26.04.2011 05:03, Bean wrote:
> Hi,
>
> It's not decided by fs driver, it's configured by a flag in
> grub_file_open, which is passed to the disk driver. There is only a
> few places where we can expect large file, such as linux/initrd
> command.
Yet worse, such a high level shouldn't care about low-level at all.
> And in this case, caching is useless since we only use the
> data once and caching would only flush out useful data unnecessarily.
> By setting a flag to indicate direct read is required, we can optimize
> access for such situation while keeping the cache for others. This is
> similar to the pass through flag for linux/windows.
I don't think that the intent is the same. Under OS considerations are
more along transaction-safeness and barriers for databases and cache
disabling for system software. Normal application shouldn't use those flags.
>> Which is an example of bad design. Rather than improving the existing
>> function to do both caching and unbroken read (like in my 4096 branch)
>> you have 2 functions and force upper layers to do the tradeoffs and care
>> about matters which should be abstracted and invisible to them.
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Grub2 EFI: Image loading from USB takes too long
2011-04-15 19:54 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-06-23 16:02 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 0 replies; 21+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-06-23 16:02 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 322 bytes --]
On 15.04.2011 21:54, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> On 15.04.2011 10:18, Seth Goldberg wrote:
>> This problem is present, at least, on ZFS.
> Could you test the attached patch then?
>
The branch in question has been merged into mainline.
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2011-06-23 16:02 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-06 16:12 Grub2 EFI: Image loading from USB takes too long Aravind Srinivasan
2011-04-07 9:24 ` KESHAV P.R.
2011-04-08 16:33 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-15 2:45 ` Bean
2011-04-15 6:55 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-15 8:18 ` Seth Goldberg
2011-04-15 19:54 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-06-23 16:02 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-25 4:14 ` Bean
2011-04-25 10:58 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-26 3:03 ` Bean
2011-04-26 10:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
-- strict thread matches above, loose matches on Subject: below --
2011-04-15 16:07 Finnbarr P. Murphy
2011-04-05 5:33 Aravind Srinivasan
2011-04-05 6:32 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 7:36 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 16:36 ` Aravind Srinivasan
2011-04-05 6:32 ` Seth Goldberg
2011-04-05 7:17 ` KESHAV P.R.
2011-04-05 7:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-04-05 8:06 ` KESHAV P.R.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.