merge mainline into 4096

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-06-23 04:08:37 +02:00
commit a5edbcb3a1
393 changed files with 15834 additions and 2186 deletions

View file

@ -24,6 +24,7 @@
#include <grub/err.h>
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
#include <grub/emu/getroot.h>
#include <grub/misc.h>
#include <grub/i18n.h>
#include <grub/list.h>
@ -139,6 +140,7 @@ struct grub_util_biosdisk_data
char *dev;
int access_mode;
int fd;
int is_disk;
};
#ifdef __linux__
@ -240,6 +242,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
data->dev = NULL;
data->access_mode = 0;
data->fd = -1;
data->is_disk = 0;
/* Get the size. */
#if defined(__MINGW32__)
@ -281,6 +284,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
close (fd);
goto fail;
}
data->is_disk = 1;
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (ioctl (fd, DIOCGMEDIASIZE, &nr))
@ -342,18 +346,23 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
return GRUB_ERR_NONE;
}
#ifdef HAVE_DEVICE_MAPPER
static int
device_is_mapped (const char *dev)
int
grub_util_device_is_mapped (const char *dev)
{
#ifdef HAVE_DEVICE_MAPPER
struct stat st;
if (!grub_device_mapper_supported ())
return 0;
if (stat (dev, &st) < 0)
return 0;
return dm_is_dm_major (major (st.st_rdev));
}
#else
return 0;
#endif /* HAVE_DEVICE_MAPPER */
}
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
/* FIXME: geom actually gives us the whole container hierarchy.
@ -429,7 +438,7 @@ find_partition_start (const char *dev)
# endif /* !defined(HAVE_DIOCGDINFO) */
# ifdef HAVE_DEVICE_MAPPER
if (grub_device_mapper_supported () && device_is_mapped (dev)) {
if (grub_util_device_is_mapped (dev)) {
struct dm_task *task = NULL;
grub_uint64_t start, length;
char *target_type, *params, *space;
@ -532,9 +541,12 @@ devmapper_fail:
# if !defined(HAVE_DIOCGDINFO)
return hdg.start;
# else /* defined(HAVE_DIOCGDINFO) */
p_index = dev[strlen(dev) - 1] - 'a';
if (p_index >= label.d_npartitions)
if (dev[0])
p_index = dev[strlen(dev) - 1] - 'a';
else
p_index = -1;
if (p_index >= label.d_npartitions || p_index < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE,
"no disk label entry for `%s'", dev);
@ -558,7 +570,7 @@ struct linux_partition_cache
struct linux_partition_cache *linux_partition_cache_list;
static int
linux_find_partition (char *dev, unsigned long sector)
linux_find_partition (char *dev, grub_disk_addr_t sector)
{
size_t len = strlen (dev);
const char *format;
@ -566,6 +578,7 @@ linux_find_partition (char *dev, unsigned long sector)
int i;
char real_dev[PATH_MAX];
struct linux_partition_cache *cache;
int missing = 0;
strcpy(real_dev, dev);
@ -574,6 +587,12 @@ linux_find_partition (char *dev, unsigned long sector)
p = real_dev + len - 4;
format = "part%d";
}
else if (strncmp (real_dev, "/dev/disk/by-id/",
sizeof ("/dev/disk/by-id/") - 1) == 0)
{
p = real_dev + len;
format = "-part%d";
}
else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
{
p = real_dev + len;
@ -604,7 +623,13 @@ linux_find_partition (char *dev, unsigned long sector)
fd = open (real_dev, O_RDONLY);
if (fd == -1)
return 0;
{
if (missing++ < 10)
continue;
else
return 0;
}
missing = 0;
close (fd);
start = find_partition_start (real_dev);
@ -675,7 +700,19 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
{
free (data->dev);
if (data->fd != -1)
close (data->fd);
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
{
fsync (data->fd);
#ifdef __linux__
if (data->is_disk)
ioctl (data->fd, BLKFLSBUF, 0);
#endif
}
close (data->fd);
data->fd = -1;
}
/* Open the partition. */
grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
@ -686,10 +723,6 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
return -1;
}
/* Flush the buffer cache to the physical disk.
XXX: This also empties the buffer cache. */
ioctl (fd, BLKFLSBUF, 0);
data->dev = xstrdup (dev);
data->access_mode = (flags & O_ACCMODE);
data->fd = fd;
@ -727,7 +760,18 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
{
free (data->dev);
if (data->fd != -1)
close (data->fd);
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
{
fsync (data->fd);
#ifdef __linux__
if (data->is_disk)
ioctl (data->fd, BLKFLSBUF, 0);
#endif
}
close (data->fd);
data->fd = -1;
}
fd = open (map[disk->id].device, flags);
if (fd >= 0)
@ -888,7 +932,6 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
!= (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
close (fd);
return grub_errno;
}
@ -938,6 +981,27 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
return grub_errno;
}
grub_err_t
grub_util_biosdisk_flush (struct grub_disk *disk)
{
struct grub_util_biosdisk_data *data = disk->data;
if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
return GRUB_ERR_NONE;
if (data->fd == -1)
{
data->fd = open_device (disk, 0, O_RDONLY);
if (data->fd < 0)
return grub_errno;
}
fsync (data->fd);
#ifdef __linux__
if (data->is_disk)
ioctl (data->fd, BLKFLSBUF, 0);
#endif
return GRUB_ERR_NONE;
}
static void
grub_util_biosdisk_close (struct grub_disk *disk)
{
@ -945,7 +1009,11 @@ grub_util_biosdisk_close (struct grub_disk *disk)
free (data->dev);
if (data->fd != -1)
close (data->fd);
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
grub_util_biosdisk_flush (disk);
close (data->fd);
}
free (data);
}
@ -1115,6 +1183,54 @@ make_device_name (int drive, int dos_part, int bsd_part)
return ret;
}
#ifdef HAVE_DEVICE_MAPPER
static int
grub_util_get_dm_node_linear_info (const char *dev,
int *maj, int *min)
{
struct dm_task *dmt;
void *next = NULL;
uint64_t length, start;
char *target, *params;
char *ptr;
int major, minor;
dmt = dm_task_create(DM_DEVICE_TABLE);
if (!dmt)
return 0;
if (!dm_task_set_name(dmt, dev))
return 0;
dm_task_no_open_count(dmt);
if (!dm_task_run(dmt))
return 0;
next = dm_get_next_target(dmt, next, &start, &length,
&target, &params);
if (grub_strcmp (target, "linear") != 0)
return 0;
major = grub_strtoul (params, &ptr, 10);
if (grub_errno)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (*ptr != ':')
return 0;
ptr++;
minor = grub_strtoul (ptr, 0, 10);
if (grub_errno)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (maj)
*maj = major;
if (min)
*min = minor;
return 1;
}
#endif
static char *
convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
{
@ -1291,9 +1407,40 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
node = NULL;
goto devmapper_out;
}
else if (strncmp (node_uuid, "DMRAID-", 7) != 0)
if (strncmp (node_uuid, "LVM-", 4) == 0)
{
grub_dprintf ("hostdisk", "%s is an LVM\n", path);
node = NULL;
goto devmapper_out;
}
if (strncmp (node_uuid, "mpath-", 6) == 0)
{
/* Multipath partitions have partN-mpath-* UUIDs, and are
linear mappings so are handled by
grub_util_get_dm_node_linear_info. Multipath disks are not
linear mappings and must be handled specially. */
grub_dprintf ("hostdisk", "%s is a multipath disk\n", path);
mapper_name = dm_tree_node_get_name (node);
goto devmapper_out;
}
if (strncmp (node_uuid, "DMRAID-", 7) != 0)
{
int major, minor;
const char *node_name;
grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path);
if ((node_name = dm_tree_node_get_name (node))
&& grub_util_get_dm_node_linear_info (node_name,
&major, &minor))
{
if (tree)
dm_tree_free (tree);
free (path);
char *ret = grub_find_device ("/dev/mapper",
(major << 8) | minor);
return ret;
}
node = NULL;
goto devmapper_out;
}
@ -1530,6 +1677,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
if (stat (os_dev, &st) < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
grub_util_info ("cannot stat `%s'", os_dev);
return 0;
}
@ -1538,6 +1686,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"no mapping exists for `%s'", os_dev);
grub_util_info ("no mapping exists for `%s'", os_dev);
return 0;
}