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
=== 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
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel