block: Add driver methods to probe blocksizes and geometry
Introduce driver methods of defining disk blocksizes (physical and logical) and hard drive geometry. Methods are only implemented for "host_device". For "raw" devices driver calls child's method. For now geometry detection will only work for DASD devices. To check that a local check_for_dasd function was introduced. It calls BIODASDINFO2 ioctl and returns its rc. Blocksizes detection function will probe sizes for DASD devices. Signed-off-by: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 1424087278-49393-4-git-send-email-tumanova@linux.vnet.ibm.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
8a4ed0d1b1
commit
1a9335e4a9
@ -56,6 +56,10 @@
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/fd.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hdreg.h>
|
||||
#ifdef __s390__
|
||||
#include <asm/dasd.h>
|
||||
#endif
|
||||
#ifndef FS_NOCOW_FL
|
||||
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
|
||||
#endif
|
||||
@ -251,6 +255,23 @@ static int probe_logical_blocksize(int fd, unsigned int *sector_size_p)
|
||||
return success ? 0 : -errno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get physical block size of @fd.
|
||||
* On success, store it in @blk_size and return 0.
|
||||
* On failure, return -errno.
|
||||
*/
|
||||
static int probe_physical_blocksize(int fd, unsigned int *blk_size)
|
||||
{
|
||||
#ifdef BLKPBSZGET
|
||||
if (ioctl(fd, BLKPBSZGET, blk_size) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
@ -674,6 +695,86 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
bs->bl.opt_mem_alignment = s->buf_align;
|
||||
}
|
||||
|
||||
static int check_for_dasd(int fd)
|
||||
{
|
||||
#ifdef BIODASDINFO2
|
||||
struct dasd_information2_t info = {0};
|
||||
|
||||
return ioctl(fd, BIODASDINFO2, &info);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get @bs's logical and physical block size.
|
||||
* On success, store them in @bsz and return zero.
|
||||
* On failure, return negative errno.
|
||||
*/
|
||||
static int hdev_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
int ret;
|
||||
|
||||
/* If DASD, get blocksizes */
|
||||
if (check_for_dasd(s->fd) < 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
ret = probe_logical_blocksize(s->fd, &bsz->log);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return probe_physical_blocksize(s->fd, &bsz->phys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get @bs's geometry: cyls, heads, sectors.
|
||||
* On success, store them in @geo and return 0.
|
||||
* On failure return -errno.
|
||||
* (Allows block driver to assign default geometry values that guest sees)
|
||||
*/
|
||||
#ifdef __linux__
|
||||
static int hdev_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
struct hd_geometry ioctl_geo = {0};
|
||||
uint32_t blksize;
|
||||
|
||||
/* If DASD, get its geometry */
|
||||
if (check_for_dasd(s->fd) < 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (ioctl(s->fd, HDIO_GETGEO, &ioctl_geo) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
/* HDIO_GETGEO may return success even though geo contains zeros
|
||||
(e.g. certain multipath setups) */
|
||||
if (!ioctl_geo.heads || !ioctl_geo.sectors || !ioctl_geo.cylinders) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
/* Do not return a geometry for partition */
|
||||
if (ioctl_geo.start != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
geo->heads = ioctl_geo.heads;
|
||||
geo->sectors = ioctl_geo.sectors;
|
||||
if (!probe_physical_blocksize(s->fd, &blksize)) {
|
||||
/* overwrite cyls: HDIO_GETGEO result is incorrect for big drives */
|
||||
geo->cylinders = bdrv_nb_sectors(bs) / (blksize / BDRV_SECTOR_SIZE)
|
||||
/ (geo->heads * geo->sectors);
|
||||
return 0;
|
||||
}
|
||||
geo->cylinders = ioctl_geo.cylinders;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* __linux__ */
|
||||
static int hdev_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
|
||||
{
|
||||
int ret;
|
||||
@ -2215,6 +2316,8 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_get_info = raw_get_info,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
.bdrv_probe_blocksizes = hdev_probe_blocksizes,
|
||||
.bdrv_probe_geometry = hdev_probe_geometry,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
@ -235,6 +235,16 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int raw_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
|
||||
{
|
||||
return bdrv_probe_blocksizes(bs->file, bsz);
|
||||
}
|
||||
|
||||
static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
|
||||
{
|
||||
return bdrv_probe_geometry(bs->file, geo);
|
||||
}
|
||||
|
||||
BlockDriver bdrv_raw = {
|
||||
.format_name = "raw",
|
||||
.bdrv_probe = &raw_probe,
|
||||
@ -252,6 +262,8 @@ BlockDriver bdrv_raw = {
|
||||
.has_variable_length = true,
|
||||
.bdrv_get_info = &raw_get_info,
|
||||
.bdrv_refresh_limits = &raw_refresh_limits,
|
||||
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
|
||||
.bdrv_probe_geometry = &raw_probe_geometry,
|
||||
.bdrv_is_inserted = &raw_is_inserted,
|
||||
.bdrv_media_changed = &raw_media_changed,
|
||||
.bdrv_eject = &raw_eject,
|
||||
|
Loading…
Reference in New Issue
Block a user