[libvirt] [PATCH] storage: add wipeVol to iscsi-direct storage backend
Michal Privoznik
mprivozn at redhat.com
Fri Aug 10 11:58:46 UTC 2018
On 08/10/2018 01:12 PM, clem at lse.epita.fr wrote:
> From: Clementine Hayat <clem at lse.epita.fr>
>
> Change set volume capacity to get volume capacity to avoid code
> duplicate.
>
> Signed-off-by: Clementine Hayat <clem at lse.epita.fr>
> ---
>
> Set BLOCK_PER_PACKET to 128. Not sure about this value. Should be
> potentially tuned.
>
> src/storage/storage_backend_iscsi_direct.c | 152 +++++++++++++++++++--
> 1 file changed, 143 insertions(+), 9 deletions(-)
This fails 'make syntax-check'. You should see an automated e-mail in a while (hopefully patchew is up and running).
>
> diff --git a/src/storage/storage_backend_iscsi_direct.c b/src/storage/storage_backend_iscsi_direct.c
> index 0764356b62..094425c101 100644
> --- a/src/storage/storage_backend_iscsi_direct.c
> +++ b/src/storage/storage_backend_iscsi_direct.c
> @@ -41,6 +41,7 @@
>
> #define ISCSI_DEFAULT_TARGET_PORT 3260
> #define VIR_ISCSI_TEST_UNIT_TIMEOUT 30 * 1000
> +#define BLOCK_PER_PACKET 128
>
> VIR_LOG_INIT("storage.storage_backend_iscsi_direct");
>
> @@ -237,13 +238,13 @@ virISCSIDirectSetVolumeAttributes(virStoragePoolObjPtr pool,
> }
>
> static int
> -virISCSIDirectSetVolumeCapacity(struct iscsi_context *iscsi,
> - virStorageVolDefPtr vol,
> - int lun)
> +virISCSIDirectGetVolumeCapacity(struct iscsi_context *iscsi,
> + int lun,
> + uint32_t *block_size,
> + uint32_t *nb_block)
> {
> struct scsi_task *task = NULL;
> struct scsi_inquiry_standard *inq = NULL;
> - long long size = 0;
> int ret = -1;
>
> if (!(task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 64)) ||
> @@ -282,10 +283,8 @@ virISCSIDirectSetVolumeCapacity(struct iscsi_context *iscsi,
> goto cleanup;
> }
>
> - size = rc10->block_size;
> - size *= rc10->lba;
> - vol->target.capacity = size;
> - vol->target.allocation = size;
> + *block_size = rc10->block_size;
This is one problem that syntax-check raises. We use spaces, not TABs.
> + *nb_block = rc10->lba;
>
> }
>
> @@ -303,6 +302,8 @@ virISCSIDirectRefreshVol(virStoragePoolObjPtr pool,
> {
> virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
> virStorageVolDefPtr vol = NULL;
> + uint32_t block_size;
> + uint32_t nb_block;
> int ret = -1;
>
> virStoragePoolObjClearVols(pool);
> @@ -314,9 +315,12 @@ virISCSIDirectRefreshVol(virStoragePoolObjPtr pool,
>
> vol->type = VIR_STORAGE_VOL_NETWORK;
>
> - if (virISCSIDirectSetVolumeCapacity(iscsi, vol, lun) < 0)
> + if (virISCSIDirectGetVolumeCapacity(iscsi, lun,
> + &block_size, &nb_block) < 0)
> goto cleanup;
>
> + vol->target.capacity = block_size * nb_block;
> + vol->target.allocation = block_size * nb_block;
> def->capacity += vol->target.capacity;
> def->allocation += vol->target.allocation;
>
> @@ -584,12 +588,142 @@ virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool)
> return ret;
> }
>
> +static int
> +virStorageBackendISCSIDirectGetLun(virStorageVolDefPtr vol,
> + int *lun)
> +{
> + char *name = NULL;
> + char **name_split = NULL;
> + int ret = -1;
> +
> + if (VIR_STRDUP(name, vol->name) < 0)
> + return -1;
> + if (!(name_split = virStringSplit(name, ":", 4)))
> + goto cleanup;
> + if (!name_split[3])
This is unsafe. What if name is "a:b"? Then there is not going to be name_split[3] and the code crashes.
I think we are just safe with something like this:
diff --git i/src/storage/storage_backend_iscsi_direct.c w/src/storage/storage_backend_iscsi_direct.c
index 094425c101..d473366382 100644
--- i/src/storage/storage_backend_iscsi_direct.c
+++ w/src/storage/storage_backend_iscsi_direct.c
@@ -218,6 +218,9 @@ virISCSIDirectTestUnitReady(struct iscsi_context *iscsi,
return ret;
}
+
+#define VOL_NAME_PREFIX "unit:0:0:"
+
static int
virISCSIDirectSetVolumeAttributes(virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
@@ -226,7 +229,7 @@ virISCSIDirectSetVolumeAttributes(virStoragePoolObjPtr pool,
{
virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
- if (virAsprintf(&vol->name, "unit:0:0:%u", lun) < 0)
+ if (virAsprintf(&vol->name, VOL_NAME_PREFIX "%u", lun) < 0)
return -1;
if (virAsprintf(&vol->key, "ip-%s-iscsi-%s-lun-%u", portal,
def->source.devices[0].path, lun) < 0)
And then:
const char *name = vol->name;
int ret = -1;
if (!STRPREFIX(name, VOL_NAME_PREFIX)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid volume name %s"), name);
goto cleanup;
}
name += strlen(VOL_NAME_PREFIX);
if (virStrToLong_i(name, NULL, 10, lun) < 0)
goto cleanup;
ret = 0;
cleanup:
return ret;
> + goto cleanup;
> + if (virStrToLong_i(name_split[3], NULL, 10, lun) < 0)
> + goto cleanup;
> +
> + ret = 0;
> + cleanup:
> + VIR_FREE(name);
> + virStringListFree(name_split);
> + printf("\n");
Oops ;-)
> + return ret;
> +}
> +
> +static int
> +virStorageBackendISCSIDirectVolWipeZero(virStorageVolDefPtr vol,
> + struct iscsi_context *iscsi)
> +{
> + uint32_t lba = 0;
> + uint32_t block_size;
> + uint32_t nb_block;
> + struct scsi_task *task = NULL;
> + int lun = 0;
> + int ret = -1;
> + unsigned char *data;
> +
> + if (virStorageBackendISCSIDirectGetLun(vol, &lun) < 0)
> + return ret;
> + if (virISCSIDirectTestUnitReady(iscsi, lun) < 0)
> + return ret;
> + if (virISCSIDirectGetVolumeCapacity(iscsi, lun, &block_size, &nb_block))
> + return ret;
> + if (VIR_ALLOC_N(data, block_size * BLOCK_PER_PACKET))
> + return ret;
> +
> + while (lba < nb_block) {
> + if (nb_block - lba > block_size * BLOCK_PER_PACKET) {
> + if (!(task = iscsi_write10_sync(iscsi, lun, lba, data,
> + block_size * BLOCK_PER_PACKET,
> + block_size, 0, 0, 0, 0, 0)))
> + goto cleanup;
> + scsi_free_scsi_task(task);
> + lba += BLOCK_PER_PACKET;
> + }
> + else {
> + if (!(task = iscsi_write10_sync(iscsi, lun, lba, data, block_size,
> + block_size, 0, 0, 0, 0, 0)))
> + goto cleanup;
> + scsi_free_scsi_task(task);
> + lba++;
> + }
> + }
> +
> + ret = 0;
> + cleanup:
> + VIR_FREE(data);
> + return ret;
> +}
> +
> +static int
> +virStorageBackenISCSIDirectWipeVol(virStoragePoolObjPtr pool,
> + virStorageVolDefPtr vol,
> + unsigned int algorithm,
> + unsigned int flags)
> +{
> + virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
> + struct iscsi_context *iscsi = NULL;
> + char *portal = NULL;
> + int ret = -1;
> +
> + virCheckFlags(0, -1);
> +
Starting from here ...
> + if (!(iscsi = virISCSIDirectCreateContext(def->source.initiator.iqn)))
> + goto cleanup;
> + if (!(portal = virStorageBackendISCSIDirectPortal(&def->source)))
> + goto cleanup;
> + if (virStorageBackendISCSIDirectSetAuth(iscsi, &def->source) < 0)
> + goto cleanup;
> + if (virISCSIDirectSetContext(iscsi, def->source.devices[0].path, ISCSI_SESSION_NORMAL) < 0)
> + goto cleanup;
> + if (virISCSIDirectConnect(iscsi, portal) < 0)
> + goto cleanup;
... to here, the code looks exactly the same as in virStorageBackendISCSIDirectRefreshPool(). I suspect it is going to be copied over to another methods that will be implemented. Therefore I think it should be moved to a separate function.
> +
> +
> + switch ((virStorageVolWipeAlgorithm) algorithm) {
> + case VIR_STORAGE_VOL_WIPE_ALG_ZERO:
> + if (virStorageBackendISCSIDirectVolWipeZero(vol, iscsi) < 0) {
> + virReportSystemError(VIR_ERR_INTERNAL_ERROR,
> + _("failed to wipe volume %s"),
> + vol->name);
> + goto disconnect;
> + }
> + break;
> + case VIR_STORAGE_VOL_WIPE_ALG_TRIM:
> + case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
> + case VIR_STORAGE_VOL_WIPE_ALG_DOD:
> + case VIR_STORAGE_VOL_WIPE_ALG_BSI:
> + case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
> + case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
> + case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
> + case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
> + case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
> + case VIR_STORAGE_VOL_WIPE_ALG_LAST:
> + virReportError(VIR_ERR_INVALID_ARG, _("unsupported algorithm %d"),
> + algorithm);
> + goto disconnect;
> + }
> +
> + ret = 0;
> + disconnect:
> + virISCSIDirectDisconnect(iscsi);
> + cleanup:
> + VIR_FREE(portal);
> + iscsi_destroy_context(iscsi);
> + return ret;
> +}
> +
> +
> virStorageBackend virStorageBackendISCSIDirect = {
> .type = VIR_STORAGE_POOL_ISCSI_DIRECT,
>
> .checkPool = virStorageBackendISCSIDirectCheckPool,
> .findPoolSources = virStorageBackendISCSIDirectFindPoolSources,
> .refreshPool = virStorageBackendISCSIDirectRefreshPool,
> + .wipeVol = virStorageBackenISCSIDirectWipeVol,
> };
>
> int
>
Otherwise looking good.
Michal
More information about the libvir-list
mailing list