Speed up consecutive hostdisk operations on the same device.
* util/hostdisk.c (struct grub_util_biosdisk_data): New structure. (grub_util_biosdisk_open): Initialise disk->data. (struct linux_partition_cache): New structure. (linux_find_partition): Cache partition start positions; these are expensive to compute on every read and write. (open_device): Cache open file descriptor in disk->data, so that we don't have to reopen it and flush the buffer cache for consecutive operations on the same device. (grub_util_biosdisk_close): New function. (grub_util_biosdisk_dev): Set `close' member. * conf/common.rmk (grub_probe_SOURCES): Add kern/list.c. * conf/i386-efi.rmk (grub_setup_SOURCES): Likewise. * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise. * conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Likewise. * conf/x86_64-efi.rmk (grub_setup_SOURCES): Likewise.
This commit is contained in:
commit
08e46ededa
7 changed files with 131 additions and 18 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
2010-03-14 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
Speed up consecutive hostdisk operations on the same device.
|
||||||
|
|
||||||
|
* util/hostdisk.c (struct grub_util_biosdisk_data): New structure.
|
||||||
|
(grub_util_biosdisk_open): Initialise disk->data.
|
||||||
|
(struct linux_partition_cache): New structure.
|
||||||
|
(linux_find_partition): Cache partition start positions; these are
|
||||||
|
expensive to compute on every read and write.
|
||||||
|
(open_device): Cache open file descriptor in disk->data, so that we
|
||||||
|
don't have to reopen it and flush the buffer cache for consecutive
|
||||||
|
operations on the same device.
|
||||||
|
(grub_util_biosdisk_close): New function.
|
||||||
|
(grub_util_biosdisk_dev): Set `close' member.
|
||||||
|
|
||||||
|
* conf/common.rmk (grub_probe_SOURCES): Add kern/list.c.
|
||||||
|
* conf/i386-efi.rmk (grub_setup_SOURCES): Likewise.
|
||||||
|
* conf/i386-pc.rmk (grub_setup_SOURCES): Likewise.
|
||||||
|
* conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Likewise.
|
||||||
|
* conf/x86_64-efi.rmk (grub_setup_SOURCES): Likewise.
|
||||||
|
|
||||||
2010-03-14 Vladimir Serbinenko <phcoder@gmail.com>
|
2010-03-14 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
Compile parts of grub-emu as modules.
|
Compile parts of grub-emu as modules.
|
||||||
|
|
|
@ -24,7 +24,7 @@ util/grub-probe.c_DEPENDENCIES = grub_probe_init.h
|
||||||
grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \
|
grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \
|
||||||
util/hostdisk.c util/misc.c util/getroot.c \
|
util/hostdisk.c util/misc.c util/getroot.c \
|
||||||
kern/device.c kern/disk.c kern/err.c kern/misc.c \
|
kern/device.c kern/disk.c kern/err.c kern/misc.c \
|
||||||
kern/parser.c kern/partition.c kern/file.c \
|
kern/parser.c kern/partition.c kern/file.c kern/list.c \
|
||||||
\
|
\
|
||||||
fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \
|
fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \
|
||||||
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
|
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
|
||||||
|
|
|
@ -21,7 +21,7 @@ util/i386/efi/grub-mkimage.c_DEPENDENCIES = Makefile
|
||||||
# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
|
# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
|
||||||
# fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c \
|
# fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c \
|
||||||
# fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
|
# fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
|
||||||
# kern/fs.c kern/env.c fs/fshelp.c
|
# kern/fs.c kern/env.c kern/list.c fs/fshelp.c
|
||||||
|
|
||||||
# Scripts.
|
# Scripts.
|
||||||
sbin_SCRIPTS = grub-install
|
sbin_SCRIPTS = grub-install
|
||||||
|
|
|
@ -96,7 +96,8 @@ grub_setup_SOURCES = gnulib/progname.c \
|
||||||
util/i386/pc/grub-setup.c util/hostdisk.c \
|
util/i386/pc/grub-setup.c util/hostdisk.c \
|
||||||
util/misc.c util/getroot.c kern/device.c kern/disk.c \
|
util/misc.c util/getroot.c kern/device.c kern/disk.c \
|
||||||
kern/err.c kern/misc.c kern/parser.c kern/partition.c \
|
kern/err.c kern/misc.c kern/parser.c kern/partition.c \
|
||||||
kern/file.c kern/fs.c kern/env.c fs/fshelp.c \
|
kern/file.c kern/fs.c kern/env.c kern/list.c \
|
||||||
|
fs/fshelp.c \
|
||||||
\
|
\
|
||||||
fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
|
fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
|
||||||
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
|
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
|
||||||
|
|
|
@ -70,7 +70,8 @@ util/sparc64/ieee1275/grub-setup.c_DEPENDENCIES = grub_setup_init.h
|
||||||
grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c \
|
grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c \
|
||||||
util/misc.c util/getroot.c kern/device.c kern/disk.c \
|
util/misc.c util/getroot.c kern/device.c kern/disk.c \
|
||||||
kern/err.c kern/misc.c kern/parser.c kern/partition.c \
|
kern/err.c kern/misc.c kern/parser.c kern/partition.c \
|
||||||
kern/file.c kern/fs.c kern/env.c fs/fshelp.c \
|
kern/file.c kern/fs.c kern/env.c kern/list.c \
|
||||||
|
fs/fshelp.c \
|
||||||
\
|
\
|
||||||
fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
|
fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
|
||||||
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
|
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
|
||||||
|
|
|
@ -20,7 +20,7 @@ grub_mkimage_SOURCES = gnulib/progname.c util/i386/efi/grub-mkimage.c \
|
||||||
# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
|
# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
|
||||||
# fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c \
|
# fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c \
|
||||||
# fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
|
# fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
|
||||||
# kern/fs.c kern/env.c fs/fshelp.c
|
# kern/fs.c kern/env.c kern/list.c fs/fshelp.c
|
||||||
|
|
||||||
# Scripts.
|
# Scripts.
|
||||||
sbin_SCRIPTS = grub-install
|
sbin_SCRIPTS = grub-install
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/util/hostdisk.h>
|
#include <grub/util/hostdisk.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/list.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -103,6 +104,13 @@ struct
|
||||||
char *device;
|
char *device;
|
||||||
} map[256];
|
} map[256];
|
||||||
|
|
||||||
|
struct grub_util_biosdisk_data
|
||||||
|
{
|
||||||
|
char *dev;
|
||||||
|
int access_mode;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* Check if we have devfs support. */
|
/* Check if we have devfs support. */
|
||||||
static int
|
static int
|
||||||
|
@ -165,6 +173,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
{
|
{
|
||||||
int drive;
|
int drive;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
struct grub_util_biosdisk_data *data;
|
||||||
|
|
||||||
drive = find_grub_drive (name);
|
drive = find_grub_drive (name);
|
||||||
if (drive < 0)
|
if (drive < 0)
|
||||||
|
@ -173,6 +182,10 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
|
|
||||||
disk->has_partitions = 1;
|
disk->has_partitions = 1;
|
||||||
disk->id = drive;
|
disk->id = drive;
|
||||||
|
disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data));
|
||||||
|
data->dev = NULL;
|
||||||
|
data->access_mode = 0;
|
||||||
|
data->fd = -1;
|
||||||
|
|
||||||
/* Get the size. */
|
/* Get the size. */
|
||||||
#if defined(__MINGW32__)
|
#if defined(__MINGW32__)
|
||||||
|
@ -254,6 +267,17 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
/* Cache of partition start sectors for each disk. */
|
||||||
|
struct linux_partition_cache
|
||||||
|
{
|
||||||
|
struct linux_partition_cache *next;
|
||||||
|
char *dev;
|
||||||
|
unsigned long start;
|
||||||
|
int partno;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct linux_partition_cache *linux_partition_cache_list;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
linux_find_partition (char *dev, unsigned long sector)
|
linux_find_partition (char *dev, unsigned long sector)
|
||||||
{
|
{
|
||||||
|
@ -262,6 +286,7 @@ linux_find_partition (char *dev, unsigned long sector)
|
||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
char real_dev[PATH_MAX];
|
char real_dev[PATH_MAX];
|
||||||
|
struct linux_partition_cache *cache;
|
||||||
|
|
||||||
strcpy(real_dev, dev);
|
strcpy(real_dev, dev);
|
||||||
|
|
||||||
|
@ -281,6 +306,16 @@ linux_find_partition (char *dev, unsigned long sector)
|
||||||
format = "%d";
|
format = "%d";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (cache = linux_partition_cache_list; cache; cache = cache->next)
|
||||||
|
{
|
||||||
|
if (strcmp (cache->dev, dev) == 0 && cache->start == sector)
|
||||||
|
{
|
||||||
|
sprintf (p, format, cache->partno);
|
||||||
|
strcpy (dev, real_dev);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 1; i < 10000; i++)
|
for (i = 1; i < 10000; i++)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -301,6 +336,15 @@ linux_find_partition (char *dev, unsigned long sector)
|
||||||
|
|
||||||
if (hdg.start == sector)
|
if (hdg.start == sector)
|
||||||
{
|
{
|
||||||
|
struct linux_partition_cache *new_cache_item;
|
||||||
|
|
||||||
|
new_cache_item = xmalloc (sizeof *new_cache_item);
|
||||||
|
new_cache_item->dev = xstrdup (dev);
|
||||||
|
new_cache_item->start = hdg.start;
|
||||||
|
new_cache_item->partno = i;
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list),
|
||||||
|
GRUB_AS_LIST (new_cache_item));
|
||||||
|
|
||||||
strcpy (dev, real_dev);
|
strcpy (dev, real_dev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -314,6 +358,7 @@ static int
|
||||||
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
struct grub_util_biosdisk_data *data = disk->data;
|
||||||
|
|
||||||
#ifdef O_LARGEFILE
|
#ifdef O_LARGEFILE
|
||||||
flags |= O_LARGEFILE;
|
flags |= O_LARGEFILE;
|
||||||
|
@ -340,6 +385,18 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
&& strncmp (map[disk->id].device, "/dev/", 5) == 0)
|
&& strncmp (map[disk->id].device, "/dev/", 5) == 0)
|
||||||
is_partition = linux_find_partition (dev, disk->partition->start);
|
is_partition = linux_find_partition (dev, disk->partition->start);
|
||||||
|
|
||||||
|
if (data->dev && strcmp (data->dev, dev) == 0 &&
|
||||||
|
data->access_mode == (flags & O_ACCMODE))
|
||||||
|
{
|
||||||
|
grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev);
|
||||||
|
fd = data->fd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free (data->dev);
|
||||||
|
if (data->fd != -1)
|
||||||
|
close (data->fd);
|
||||||
|
|
||||||
/* Open the partition. */
|
/* Open the partition. */
|
||||||
grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
|
grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
|
||||||
fd = open (dev, flags);
|
fd = open (dev, flags);
|
||||||
|
@ -353,6 +410,11 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
XXX: This also empties the buffer cache. */
|
XXX: This also empties the buffer cache. */
|
||||||
ioctl (fd, BLKFLSBUF, 0);
|
ioctl (fd, BLKFLSBUF, 0);
|
||||||
|
|
||||||
|
data->dev = xstrdup (dev);
|
||||||
|
data->access_mode = (flags & O_ACCMODE);
|
||||||
|
data->fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_partition)
|
if (is_partition)
|
||||||
sector -= disk->partition->start;
|
sector -= disk->partition->start;
|
||||||
}
|
}
|
||||||
|
@ -375,7 +437,26 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
|
||||||
|
data->access_mode == (flags & O_ACCMODE))
|
||||||
|
{
|
||||||
|
grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
|
||||||
|
fd = data->fd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free (data->dev);
|
||||||
|
if (data->fd != -1)
|
||||||
|
close (data->fd);
|
||||||
|
|
||||||
fd = open (map[disk->id].device, flags);
|
fd = open (map[disk->id].device, flags);
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
data->dev = xstrdup (map[disk->id].device);
|
||||||
|
data->access_mode = (flags & O_ACCMODE);
|
||||||
|
data->fd = fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
if (! (sysctl_oldflags & 0x10)
|
if (! (sysctl_oldflags & 0x10)
|
||||||
|
@ -535,7 +616,6 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
|
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
|
||||||
|
|
||||||
close (fd);
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,17 +650,27 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
|
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
|
||||||
|
|
||||||
close (fd);
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_util_biosdisk_close (struct grub_disk *disk)
|
||||||
|
{
|
||||||
|
struct grub_util_biosdisk_data *data = disk->data;
|
||||||
|
|
||||||
|
free (data->dev);
|
||||||
|
if (data->fd != -1)
|
||||||
|
close (data->fd);
|
||||||
|
free (data);
|
||||||
|
}
|
||||||
|
|
||||||
static struct grub_disk_dev grub_util_biosdisk_dev =
|
static struct grub_disk_dev grub_util_biosdisk_dev =
|
||||||
{
|
{
|
||||||
.name = "biosdisk",
|
.name = "biosdisk",
|
||||||
.id = GRUB_DISK_DEVICE_BIOSDISK_ID,
|
.id = GRUB_DISK_DEVICE_BIOSDISK_ID,
|
||||||
.iterate = grub_util_biosdisk_iterate,
|
.iterate = grub_util_biosdisk_iterate,
|
||||||
.open = grub_util_biosdisk_open,
|
.open = grub_util_biosdisk_open,
|
||||||
.close = 0,
|
.close = grub_util_biosdisk_close,
|
||||||
.read = grub_util_biosdisk_read,
|
.read = grub_util_biosdisk_read,
|
||||||
.write = grub_util_biosdisk_write,
|
.write = grub_util_biosdisk_write,
|
||||||
.next = 0
|
.next = 0
|
||||||
|
|
Loading…
Reference in a new issue