On Sat, Feb 08, 2020 at 01:25:28AM +0200, Mykola Ivanets wrote:
From: Nikolay Ivanets <stenavin(a)gmail.com>
I faced with situation where libguestfs cannot recognize partitions on a
disk image which was partitioned on a system with "4K native" sector
size support.
In order to fix the issue we need to allow users to specify desired
physical and/or logical block size per drive basis.
It is definitely not a complete patch but rather a way to request for a
comments. Nevertheless it is already working patch. I've added an
optional parameters to add_drive API method which allow specifying
physical and logical block size for a drive separetely.
There are no documentation and tests yet. Input parameters are not
validated for correctness.
The patch is generally fine, but ...
Here are my questions:
- Am I move in the right direction adding support for physical/logical
block size?
I'm fairly sure we only need one of these. I'm just not
sure which one we need. I think we need to ask an expert
or look at the qemu / kernel code to find out exactly what
each setting really does.
- I'm not sure I've made a good choise for parameter names:
'pblocksize'
and 'lblocksize' respectively. I've tried to avoid long names like
'physicalblocksize' while keeping readability and semantic.
If we only have one, we can use "blocksize". But it does
require us to answer the previous one.
- Do we want to add the same optional parameters to
'add_drive_scratch'
API method? I think it would be nice but it is up to you.
It should also be added to add_domain and add_libvirt_dom (note all
the APIs which have 'discard' and 'copyonread' already).
It could be added to add_drive_scratch, I guess. However it doesn't
seem very useful for scratch drives (why create a scratch drive with
4K sectors which will be thrown away in the end?)
- What about 'add_dom', 'add_libvirt_dom' API
methods? Should they also
handle 'blokio' tag in domain XML and act respectively?
Yes.
- Anything else I didn't spot yet?
- Do we want guestfish to accept physical/logical block size per drive
from command line?
If you can be bothered, but best to put it in a second patch.
- What about other virt tools like virt-df, virt-cat and so on?
If you change the command line handling, then it should apply to other
tools mostly automatically. Have a look at how the --format option
works.
Thanks,
Rich.
Sorry for a long list of questions.
---
generator/actions_core.ml | 2 +-
lib/drives.c | 14 ++++++++++++++
lib/guestfs-internal.h | 2 ++
lib/launch-direct.c | 24 ++++++++++++++++++++++++
lib/launch-libvirt.c | 21 +++++++++++++++++++++
lib/launch-uml.c | 10 ++++++++++
6 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index cb7e8dcd0..9de3a6484 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -210,7 +210,7 @@ this function fails and the C<errno> is set to
C<EINVAL>." };
{ defaults with
name = "add_drive"; added = (0, 0, 3);
- style = RErr, [String (PlainString, "filename")], [OBool
"readonly"; OString "format"; OString "iface"; OString
"name"; OString "label"; OString "protocol"; OStringList
"server"; OString "username"; OString "secret"; OString
"cachemode"; OString "discard"; OBool "copyonread"];
+ style = RErr, [String (PlainString, "filename")], [OBool
"readonly"; OString "format"; OString "iface"; OString
"name"; OString "label"; OString "protocol"; OStringList
"server"; OString "username"; OString "secret"; OString
"cachemode"; OString "discard"; OBool "copyonread"; OInt
"pblocksize"; OInt "lblocksize"];
once_had_no_optargs = true;
blocking = false;
fish_alias = ["add"];
diff --git a/lib/drives.c b/lib/drives.c
index 5a8d29ab4..bb160cc34 100644
--- a/lib/drives.c
+++ b/lib/drives.c
@@ -58,6 +58,8 @@ struct drive_create_data {
const char *cachemode;
enum discard discard;
bool copyonread;
+ int pblocksize;
+ int lblocksize;
};
COMPILE_REGEXP (re_hostname_port, "(.*):(\\d+)$", 0)
@@ -114,6 +116,8 @@ create_drive_file (guestfs_h *g,
drv->cachemode = data->cachemode ? safe_strdup (g, data->cachemode) : NULL;
drv->discard = data->discard;
drv->copyonread = data->copyonread;
+ drv->pblocksize = data->pblocksize;
+ drv->lblocksize = data->lblocksize;
if (data->readonly) {
if (create_overlay (g, drv) == -1) {
@@ -150,6 +154,8 @@ create_drive_non_file (guestfs_h *g,
drv->cachemode = data->cachemode ? safe_strdup (g, data->cachemode) : NULL;
drv->discard = data->discard;
drv->copyonread = data->copyonread;
+ drv->pblocksize = data->pblocksize;
+ drv->lblocksize = data->lblocksize;
if (data->readonly) {
if (create_overlay (g, drv) == -1) {
@@ -767,6 +773,14 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename,
optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_COPYONREAD_BITMASK
? optargs->copyonread : false;
+ data.pblocksize =
+ optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_PBLOCKSIZE_BITMASK
+ ? optargs->pblocksize : 0;
+
+ data.lblocksize =
+ optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_LBLOCKSIZE_BITMASK
+ ? optargs->lblocksize : 0;
+
if (data.readonly && data.discard == discard_enable) {
error (g, _("discard support cannot be enabled on read-only drives"));
free_drive_servers (data.servers, data.nr_servers);
diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h
index 6799c265d..20f22a674 100644
--- a/lib/guestfs-internal.h
+++ b/lib/guestfs-internal.h
@@ -261,6 +261,8 @@ struct drive {
char *cachemode;
enum discard discard;
bool copyonread;
+ int pblocksize;
+ int lblocksize;
};
/* Extra hv parameters (from guestfs_config). */
diff --git a/lib/launch-direct.c b/lib/launch-direct.c
index ae6ca093b..518bd24fc 100644
--- a/lib/launch-direct.c
+++ b/lib/launch-direct.c
@@ -273,6 +273,26 @@ add_drive_standard_params (guestfs_h *g, struct backend_direct_data
*data,
return -1;
}
+/**
+ * Add the blockio elements of the C<-device> parameter.
+ */
+static int
+add_device_blockio_params (guestfs_h *g, struct qemuopts *qopts,
+ struct drive *drv)
+{
+ if (drv->pblocksize)
+ append_list_format ("physical_block_size=%d", drv->pblocksize);
+ if (drv->lblocksize)
+ append_list_format ("logical_block_size=%d", drv->lblocksize);
+
+ return 0;
+
+ /* This label is called implicitly from the qemuopts macros on error. */
+ qemuopts_error:
+ perrorf (g, "qemuopts");
+ return -1;
+}
+
static int
add_drive (guestfs_h *g, struct backend_direct_data *data,
struct qemuopts *qopts, size_t i, struct drive *drv)
@@ -291,6 +311,8 @@ add_drive (guestfs_h *g, struct backend_direct_data *data,
append_list_format ("drive=hd%zu", i);
if (drv->disk_label)
append_list_format ("serial=%s", drv->disk_label);
+ if (add_device_blockio_params (g, qopts, drv) == -1)
+ return -1;
} end_list ();
}
#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__)
@@ -317,6 +339,8 @@ add_drive (guestfs_h *g, struct backend_direct_data *data,
append_list_format ("drive=hd%zu", i);
if (drv->disk_label)
append_list_format ("serial=%s", drv->disk_label);
+ if (add_device_blockio_params (g, qopts, drv) == -1)
+ return -1;
} end_list ();
}
diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c
index f2cad9300..4ce2fa683 100644
--- a/lib/launch-libvirt.c
+++ b/lib/launch-libvirt.c
@@ -1043,6 +1043,7 @@ static int construct_libvirt_xml_disk (guestfs_h *g, const struct
backend_libvir
static int construct_libvirt_xml_disk_target (guestfs_h *g, xmlTextWriterPtr xo, size_t
drv_index);
static int construct_libvirt_xml_disk_driver_qemu (guestfs_h *g, const struct
backend_libvirt_data *data, struct drive *drv, xmlTextWriterPtr xo, const char *format,
const char *cachemode, enum discard discard, bool copyonread);
static int construct_libvirt_xml_disk_address (guestfs_h *g, xmlTextWriterPtr xo, size_t
drv_index);
+static int construct_libvirt_xml_disk_blockio (guestfs_h *g, xmlTextWriterPtr xo, int
pblocksize, int lblocksize);
static int construct_libvirt_xml_disk_source_hosts (guestfs_h *g, xmlTextWriterPtr xo,
const struct drive_source *src);
static int construct_libvirt_xml_disk_source_seclabel (guestfs_h *g, const struct
backend_libvirt_data *data, xmlTextWriterPtr xo);
static int construct_libvirt_xml_appliance (guestfs_h *g, const struct
libvirt_xml_params *params, xmlTextWriterPtr xo);
@@ -1578,6 +1579,10 @@ construct_libvirt_xml_disk (guestfs_h *g,
if (construct_libvirt_xml_disk_address (g, xo, drv_index) == -1)
return -1;
+ if (construct_libvirt_xml_disk_blockio (g, xo, drv->pblocksize,
+ drv->lblocksize) == -1)
+ return -1;
+
} end_element (); /* </disk> */
return 0;
@@ -1685,6 +1690,22 @@ construct_libvirt_xml_disk_address (guestfs_h *g, xmlTextWriterPtr
xo,
return 0;
}
+static int construct_libvirt_xml_disk_blockio (guestfs_h *g,
+ xmlTextWriterPtr xo,
+ int pblocksize, int lblocksize)
+{
+ if (pblocksize || lblocksize) {
+ start_element ("blockio") {
+ if (pblocksize)
+ attribute_format ("physical_block_size", "%d", pblocksize);
+ if (lblocksize)
+ attribute_format ("logical_block_size", "%d", lblocksize);
+ } end_element ();
+ }
+
+ return 0;
+}
+
static int
construct_libvirt_xml_disk_source_hosts (guestfs_h *g,
xmlTextWriterPtr xo,
diff --git a/lib/launch-uml.c b/lib/launch-uml.c
index da20c17d9..274287b58 100644
--- a/lib/launch-uml.c
+++ b/lib/launch-uml.c
@@ -124,6 +124,16 @@ uml_supported (guestfs_h *g)
_("uml backend does not support drives with ‘discard’ parameter set to
‘enable’"));
return false;
}
+ if (drv->pblocksize) {
+ error (g,
+ _("uml backend does not support drives with ‘physical_block_size’
parameter"));
+ return false;
+ }
+ if (drv->lblocksize) {
+ error (g,
+ _("uml backend does not support drives with ‘logical_block_size’
parameter"));
+ return false;
+ }
}
return true;
--
2.17.2
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages.
http://libguestfs.org