qemu: block: Use 'auto-read-only' instead of 'read-only' for backing chain

To allow using -blockdev with blockjobs QEMU needs to reopen files in
read-write mode when modifying the backing chain. To achieve this we
need to use 'auto-read-only' for the backing files rather than the
normal 'read-only' property. That way qemu knows that the files need to
be reopened.

Note that the format drivers (e.g. qcow2) are still opened with the
read-only property enabled when being a member of the backing chain
since they are supposed to be immutable unless a block job is started.

QEMU v4.0 (since commit 23dece19da4) allows also dynamic behaviour for
auto-read-only which allows us to use sVirt as we only grant write
permissions to files when doing a blockjob.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2018-09-04 19:29:10 +02:00
parent 8e0b1f8a9e
commit 2c4c347c4b
39 changed files with 115 additions and 92 deletions

View File

@ -1027,6 +1027,7 @@ qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSourcePtr src,
* @src: disk source
* @legacy: use legacy formatting of attributes (for -drive / old qemus)
* @onlytarget: omit any data which does not identify the image itself
* @autoreadonly: use the auto-read-only feature of qemu
*
* Creates a JSON object describing the underlying storage or protocol of a
* storage source. Returns NULL on error and reports an appropriate error message.
@ -1034,11 +1035,23 @@ qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSourcePtr src,
virJSONValuePtr
qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src,
bool legacy,
bool onlytarget)
bool onlytarget,
bool autoreadonly)
{
int actualType = virStorageSourceGetActualType(src);
VIR_AUTOPTR(virJSONValue) fileprops = NULL;
const char *driver = NULL;
virTristateBool aro = VIR_TRISTATE_BOOL_ABSENT;
virTristateBool ro = VIR_TRISTATE_BOOL_ABSENT;
if (autoreadonly) {
aro = VIR_TRISTATE_BOOL_YES;
} else {
if (src->readonly)
ro = VIR_TRISTATE_BOOL_YES;
else
ro = VIR_TRISTATE_BOOL_NO;
}
switch ((virStorageType)actualType) {
case VIR_STORAGE_TYPE_BLOCK:
@ -1142,7 +1155,8 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src,
return NULL;
if (virJSONValueObjectAdd(fileprops,
"b:read-only", src->readonly,
"T:read-only", ro,
"T:auto-read-only", aro,
"s:discard", "unmap",
NULL) < 0)
return NULL;
@ -1447,6 +1461,7 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
/**
* qemuBlockStorageSourceAttachPrepareBlockdev:
* @src: storage source to prepare data from
* @autoreadonly: use 'auto-read-only' feature of qemu
*
* Creates a qemuBlockStorageSourceAttachData structure containing data to attach
* @src to a VM using the blockdev-add approach. Note that this function only
@ -1459,7 +1474,8 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
* error is reported
*/
qemuBlockStorageSourceAttachDataPtr
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src)
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src,
bool autoreadonly)
{
VIR_AUTOPTR(qemuBlockStorageSourceAttachData) data = NULL;
@ -1467,7 +1483,9 @@ qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src)
return NULL;
if (!(data->formatProps = qemuBlockStorageSourceGetBlockdevProps(src)) ||
!(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false, false)))
!(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false,
false,
autoreadonly)))
return NULL;
data->storageNodeName = src->nodestorage;

View File

@ -59,7 +59,8 @@ qemuBlockStorageSourceSupportsConcurrentAccess(virStorageSourcePtr src);
virJSONValuePtr
qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src,
bool legacy,
bool onlytarget);
bool onlytarget,
bool autoreadonly);
virURIPtr
qemuBlockStorageSourceGetURI(virStorageSourcePtr src);
@ -106,7 +107,8 @@ VIR_DEFINE_AUTOPTR_FUNC(qemuBlockStorageSourceAttachData,
qemuBlockStorageSourceAttachDataFree);
qemuBlockStorageSourceAttachDataPtr
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src);
qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src,
bool autoreadonly);
qemuBlockStorageSourceAttachDataPtr
qemuBlockStorageSourceDetachPrepare(virStorageSourcePtr src,

View File

@ -1602,7 +1602,7 @@ qemuDiskSourceGetProps(virStorageSourcePtr src)
virJSONValuePtr props;
virJSONValuePtr ret;
if (!(props = qemuBlockStorageSourceGetBackendProps(src, true, false)))
if (!(props = qemuBlockStorageSourceGetBackendProps(src, true, false, false)))
return NULL;
if (virJSONValueObjectCreate(&ret, "a:file", &props, NULL) < 0) {
@ -11178,7 +11178,7 @@ qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSourcePtr top,
return NULL;
for (n = top; virStorageSourceIsBacking(n); n = n->backingStore) {
if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(n)))
if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(n, true)))
return NULL;
if (qemuBuildStorageSourceAttachPrepareCommon(n, elem, qemuCaps) < 0)

View File

@ -830,7 +830,9 @@ qemuMigrationSrcNBDStorageCopyBlockdev(virQEMUDriverPtr driver,
virAsprintf(&copysrc->nodeformat, "migration-%s-format", disk->dst) < 0)
goto cleanup;
if (!(data = qemuBlockStorageSourceAttachPrepareBlockdev(copysrc)))
/* Migration via blockdev-mirror was supported sooner than the auto-read-only
* feature was added to qemu */
if (!(data = qemuBlockStorageSourceAttachPrepareBlockdev(copysrc, false)))
goto cleanup;
if (qemuDomainObjEnterMonitorAsync(driver, vm,

View File

@ -67,7 +67,8 @@ testBackingXMLjsonXML(const void *args)
return -1;
}
if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true, false))) {
if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true, false,
false))) {
fprintf(stderr, "failed to format disk source json\n");
return -1;
}
@ -222,8 +223,8 @@ testQemuDiskXMLToProps(const void *opaque)
goto cleanup;
if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n)) ||
!(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, false, true)) ||
!(storageProps = qemuBlockStorageSourceGetBackendProps(n, false, false))) {
!(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, false, true, true)) ||
!(storageProps = qemuBlockStorageSourceGetBackendProps(n, false, false, true))) {
if (!data->fail) {
VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n");
goto cleanup;

View File

@ -8,6 +8,6 @@
"driver": "host_device",
"filename": "/dev/blah",
"node-name": "0123456789ABCDEF0123456789ABCDE",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -9,6 +9,6 @@
"filename": "/dev/blah",
"pr-manager": "node-a-st-pr-alias",
"node-name": "node-a-st",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -18,6 +18,6 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -10,6 +10,6 @@
"floppy": true,
"rw": false,
"node-name": "node-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -10,6 +10,6 @@
"floppy": false,
"rw": false,
"node-name": "node-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -10,7 +10,7 @@
"filename": "/var/lib/libvirt/images/a",
"aio": "threads",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -25,7 +25,7 @@
"filename": "/var/lib/libvirt/images/b",
"aio": "threads",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -47,7 +47,7 @@
}
],
"node-name": "node-c-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -61,6 +61,6 @@
"filename": "/var/lib/libvirt/images/d",
"aio": "threads",
"node-name": "node-d-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -17,7 +17,7 @@
"direct": true,
"no-flush": false
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -39,7 +39,7 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -69,7 +69,7 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -90,6 +90,6 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -17,7 +17,7 @@
"direct": true,
"no-flush": false
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -39,7 +39,7 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -69,7 +69,7 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -90,6 +90,6 @@
"direct": true,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -17,7 +17,7 @@
"direct": false,
"no-flush": true
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -39,7 +39,7 @@
"direct": false,
"no-flush": true
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -69,7 +69,7 @@
"direct": false,
"no-flush": true
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -90,6 +90,6 @@
"direct": false,
"no-flush": true
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -17,7 +17,7 @@
"direct": false,
"no-flush": false
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -39,7 +39,7 @@
"direct": false,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -69,7 +69,7 @@
"direct": false,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -90,6 +90,6 @@
"direct": false,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -17,7 +17,7 @@
"direct": false,
"no-flush": false
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -39,7 +39,7 @@
"direct": false,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -69,7 +69,7 @@
"direct": false,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -90,6 +90,6 @@
"direct": false,
"no-flush": false
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -10,7 +10,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/a",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -24,7 +24,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/b",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -46,7 +46,7 @@
}
],
"node-name": "node-c-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -59,6 +59,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/d",
"node-name": "node-d-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -9,7 +9,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/a",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -23,7 +23,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/b",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -37,7 +37,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/c",
"node-name": "node-c-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -50,6 +50,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/d",
"node-name": "node-d-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -11,7 +11,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/a",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -26,7 +26,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/b",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -49,7 +49,7 @@
}
],
"node-name": "node-c-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -63,6 +63,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/d",
"node-name": "node-d-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -11,7 +11,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/a",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -26,7 +26,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/b",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -49,7 +49,7 @@
}
],
"node-name": "node-c-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -63,6 +63,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/d",
"node-name": "node-d-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -10,7 +10,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/a",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -25,7 +25,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/b",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -48,7 +48,7 @@
}
],
"node-name": "node-c-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -62,6 +62,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/d",
"node-name": "node-d-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -13,7 +13,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/a",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -31,6 +31,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/b",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -9,7 +9,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1507297895",
"node-name": "#block004",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -23,7 +23,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1484071872",
"node-name": "#block256",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -37,7 +37,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483615252",
"node-name": "#block418",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -51,7 +51,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483605924",
"node-name": "#block624",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -65,7 +65,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483605920",
"node-name": "#block869",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -79,7 +79,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483546244",
"node-name": "#block1047",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -93,7 +93,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483545901",
"node-name": "#block1279",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -107,7 +107,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483545313",
"node-name": "#block1444",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -121,7 +121,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1483536402",
"node-name": "#block1602",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -135,6 +135,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.qcow2",
"node-name": "#block1864",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -9,7 +9,7 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1507297895",
"node-name": "#block004",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -22,6 +22,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/rhel7.3.1484071872",
"node-name": "#block256",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -17,6 +17,6 @@
"direct": true,
"no-flush": false
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -9,6 +9,6 @@
"driver": "file",
"filename": "/path/luks.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/var/lib/libvirt/images/i.img",
"node-name": "0123456789ABCDEF0123456789ABCDE",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -8,6 +8,6 @@
"driver": "file",
"filename": "/path/to/i.img",
"node-name": "test2",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -14,6 +14,6 @@
},
"tls-creds": "node-a-s-tls0",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -34,7 +34,7 @@
"direct": false,
"no-flush": true
},
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -59,6 +59,6 @@
"direct": false,
"no-flush": true
},
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -30,7 +30,7 @@
],
"key-secret": "node-a-s-secalias",
"node-name": "node-a-s",
"read-only": false,
"auto-read-only": true,
"discard": "unmap"
}
{
@ -53,6 +53,6 @@
"user": "testuser-iscsi",
"password-secret": "node-b-s-secalias",
"node-name": "node-b-s",
"read-only": true,
"auto-read-only": true,
"discard": "unmap"
}

View File

@ -30,7 +30,7 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
-boot strict=on \
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1",\
"node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \
"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw",\
"file":"libvirt-1-storage"}' \
-device ide-hd,bus=ide.0,unit=0,drive=libvirt-1-format,id=ide0-0-0,bootindex=1 \

View File

@ -30,7 +30,7 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
-boot strict=on \
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1",\
"node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \
"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw",\
"file":"libvirt-1-storage"}' \
-device ide-hd,bus=ide.0,unit=0,drive=libvirt-1-format,id=ide0-0-0,bootindex=1 \