2013-05-03 18:07:22 +00:00
|
|
|
/*
|
|
|
|
* virscsi.c: helper APIs for managing host SCSI devices
|
|
|
|
*
|
2014-01-29 17:22:42 +00:00
|
|
|
* Copyright (C) 2013-2014 Red Hat, Inc.
|
2013-05-03 18:07:22 +00:00
|
|
|
* Copyright (C) 2013 Fujitsu, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2017-01-23 17:54:42 +00:00
|
|
|
#include "virlog.h"
|
2013-05-03 18:07:22 +00:00
|
|
|
#include "virscsi.h"
|
|
|
|
#include "virfile.h"
|
|
|
|
#include "virutil.h"
|
|
|
|
#include "virstring.h"
|
|
|
|
#include "virerror.h"
|
2019-04-01 14:28:05 +00:00
|
|
|
#include "viralloc.h"
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
#define SYSFS_SCSI_DEVICES "/sys/bus/scsi/devices"
|
|
|
|
|
|
|
|
/* For virReportOOMError() and virReportSystemError() */
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
2017-01-23 17:54:42 +00:00
|
|
|
|
|
|
|
VIR_LOG_INIT("util.scsi");
|
|
|
|
|
2014-03-01 06:28:56 +00:00
|
|
|
struct _virUsedByInfo {
|
|
|
|
char *drvname; /* which driver */
|
|
|
|
char *domname; /* which domain */
|
|
|
|
};
|
2018-07-24 15:52:27 +00:00
|
|
|
typedef struct _virUsedByInfo virUsedByInfo;
|
|
|
|
typedef virUsedByInfo *virUsedByInfoPtr;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
struct _virSCSIDevice {
|
|
|
|
unsigned int adapter;
|
|
|
|
unsigned int bus;
|
|
|
|
unsigned int target;
|
2015-06-17 03:29:53 +00:00
|
|
|
unsigned long long unit;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
char *name; /* adapter:bus:target:unit */
|
|
|
|
char *id; /* model:vendor */
|
|
|
|
char *sg_path; /* e.g. /dev/sg2 */
|
2014-03-01 06:28:56 +00:00
|
|
|
virUsedByInfoPtr *used_by; /* driver:domain(s) using this dev */
|
2014-01-29 17:22:42 +00:00
|
|
|
size_t n_used_by; /* how many domains are using this dev */
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
bool readonly;
|
2014-01-08 14:51:29 +00:00
|
|
|
bool shareable;
|
2013-05-03 18:07:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _virSCSIDeviceList {
|
|
|
|
virObjectLockable parent;
|
2014-01-07 14:44:27 +00:00
|
|
|
size_t count;
|
2013-05-03 18:07:22 +00:00
|
|
|
virSCSIDevicePtr *devs;
|
|
|
|
};
|
|
|
|
|
|
|
|
static virClassPtr virSCSIDeviceListClass;
|
|
|
|
|
|
|
|
static void virSCSIDeviceListDispose(void *obj);
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSCSIOnceInit(void)
|
|
|
|
{
|
2018-04-17 15:42:33 +00:00
|
|
|
if (!VIR_CLASS_NEW(virSCSIDeviceList, virClassForObjectLockable()))
|
2013-05-03 18:07:22 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:23:29 +00:00
|
|
|
VIR_ONCE_GLOBAL_INIT(virSCSI);
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virSCSIDeviceGetAdapterId(const char *adapter,
|
|
|
|
unsigned int *adapter_id)
|
|
|
|
{
|
2013-09-30 12:23:17 +00:00
|
|
|
if (STRPREFIX(adapter, "scsi_host") &&
|
|
|
|
virStrToLong_ui(adapter + strlen("scsi_host"),
|
|
|
|
NULL, 0, adapter_id) == 0)
|
|
|
|
return 0;
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot parse adapter '%s'"), adapter);
|
|
|
|
return -1;
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2014-01-30 07:05:59 +00:00
|
|
|
virSCSIDeviceGetSgName(const char *sysfs_prefix,
|
|
|
|
const char *adapter,
|
2013-05-03 18:07:22 +00:00
|
|
|
unsigned int bus,
|
|
|
|
unsigned int target,
|
2015-06-17 03:29:53 +00:00
|
|
|
unsigned long long unit)
|
2013-05-03 18:07:22 +00:00
|
|
|
{
|
|
|
|
DIR *dir = NULL;
|
|
|
|
struct dirent *entry;
|
2018-07-24 15:52:28 +00:00
|
|
|
VIR_AUTOFREE(char *) path = NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
char *sg = NULL;
|
|
|
|
unsigned int adapter_id;
|
2014-01-30 07:05:59 +00:00
|
|
|
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_DEVICES;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
if (virSCSIDeviceGetAdapterId(adapter, &adapter_id) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virAsprintf(&path,
|
2015-06-17 03:29:53 +00:00
|
|
|
"%s/%d:%u:%u:%llu/scsi_generic",
|
2014-01-30 07:05:59 +00:00
|
|
|
prefix, adapter_id, bus, target, unit) < 0)
|
2013-05-03 18:07:22 +00:00
|
|
|
return NULL;
|
|
|
|
|
2016-06-21 14:34:08 +00:00
|
|
|
if (virDirOpen(&dir, path) < 0)
|
2013-05-03 18:07:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-04-25 20:45:49 +00:00
|
|
|
while (virDirRead(dir, &entry, path) > 0) {
|
|
|
|
/* Assume a single directory entry */
|
|
|
|
ignore_value(VIR_STRDUP(sg, entry->d_name));
|
|
|
|
break;
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2016-06-21 10:40:29 +00:00
|
|
|
VIR_DIR_CLOSE(dir);
|
2013-05-03 18:07:22 +00:00
|
|
|
return sg;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:36 +00:00
|
|
|
/* Returns device name (e.g. "sdc") on success, or NULL
|
|
|
|
* on failure.
|
|
|
|
*/
|
|
|
|
char *
|
2014-01-30 07:05:59 +00:00
|
|
|
virSCSIDeviceGetDevName(const char *sysfs_prefix,
|
|
|
|
const char *adapter,
|
2013-05-03 18:07:36 +00:00
|
|
|
unsigned int bus,
|
|
|
|
unsigned int target,
|
2015-06-17 03:29:53 +00:00
|
|
|
unsigned long long unit)
|
2013-05-03 18:07:36 +00:00
|
|
|
{
|
|
|
|
DIR *dir = NULL;
|
|
|
|
struct dirent *entry;
|
2018-07-24 15:52:28 +00:00
|
|
|
VIR_AUTOFREE(char *) path = NULL;
|
2013-05-03 18:07:36 +00:00
|
|
|
char *name = NULL;
|
|
|
|
unsigned int adapter_id;
|
2014-01-30 07:05:59 +00:00
|
|
|
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_DEVICES;
|
2013-05-03 18:07:36 +00:00
|
|
|
|
|
|
|
if (virSCSIDeviceGetAdapterId(adapter, &adapter_id) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virAsprintf(&path,
|
2015-06-17 03:29:53 +00:00
|
|
|
"%s/%d:%u:%u:%llu/block",
|
2014-01-30 07:05:59 +00:00
|
|
|
prefix, adapter_id, bus, target, unit) < 0)
|
2013-05-03 18:07:36 +00:00
|
|
|
return NULL;
|
|
|
|
|
2016-06-21 14:34:08 +00:00
|
|
|
if (virDirOpen(&dir, path) < 0)
|
2013-05-03 18:07:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-04-25 20:45:49 +00:00
|
|
|
while (virDirRead(dir, &entry, path) > 0) {
|
2013-05-24 07:19:51 +00:00
|
|
|
ignore_value(VIR_STRDUP(name, entry->d_name));
|
|
|
|
break;
|
2013-05-03 18:07:36 +00:00
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2016-06-21 10:40:29 +00:00
|
|
|
VIR_DIR_CLOSE(dir);
|
2013-05-03 18:07:36 +00:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:22 +00:00
|
|
|
virSCSIDevicePtr
|
2014-01-30 07:05:59 +00:00
|
|
|
virSCSIDeviceNew(const char *sysfs_prefix,
|
|
|
|
const char *adapter,
|
2013-05-03 18:07:22 +00:00
|
|
|
unsigned int bus,
|
|
|
|
unsigned int target,
|
2015-06-17 03:29:53 +00:00
|
|
|
unsigned long long unit,
|
2014-01-08 14:51:29 +00:00
|
|
|
bool readonly,
|
|
|
|
bool shareable)
|
2013-05-03 18:07:22 +00:00
|
|
|
{
|
2018-07-24 15:52:29 +00:00
|
|
|
VIR_AUTOPTR(virSCSIDevice) dev = NULL;
|
|
|
|
virSCSIDevicePtr ret = NULL;
|
2018-07-24 15:52:28 +00:00
|
|
|
VIR_AUTOFREE(char *) sg = NULL;
|
|
|
|
VIR_AUTOFREE(char *) vendor_path = NULL;
|
|
|
|
VIR_AUTOFREE(char *) model_path = NULL;
|
|
|
|
VIR_AUTOFREE(char *) vendor = NULL;
|
|
|
|
VIR_AUTOFREE(char *) model = NULL;
|
2014-01-30 07:05:59 +00:00
|
|
|
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_DEVICES;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
2013-07-04 10:17:18 +00:00
|
|
|
if (VIR_ALLOC(dev) < 0)
|
2013-05-03 18:07:22 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
dev->bus = bus;
|
|
|
|
dev->target = target;
|
|
|
|
dev->unit = unit;
|
|
|
|
dev->readonly = readonly;
|
2014-01-23 10:16:11 +00:00
|
|
|
dev->shareable = shareable;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
2014-01-30 07:05:59 +00:00
|
|
|
if (!(sg = virSCSIDeviceGetSgName(prefix, adapter, bus, target, unit)))
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
if (virSCSIDeviceGetAdapterId(adapter, &dev->adapter) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
2015-06-17 03:29:53 +00:00
|
|
|
if (virAsprintf(&dev->name, "%d:%u:%u:%llu", dev->adapter,
|
2013-07-08 16:57:58 +00:00
|
|
|
dev->bus, dev->target, dev->unit) < 0 ||
|
2014-01-30 11:48:22 +00:00
|
|
|
virAsprintf(&dev->sg_path, "%s/%s",
|
|
|
|
sysfs_prefix ? sysfs_prefix : "/dev", sg) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
2013-09-13 13:32:43 +00:00
|
|
|
if (!virFileExists(dev->sg_path)) {
|
2013-05-03 18:07:22 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("SCSI device '%s': could not access %s"),
|
|
|
|
dev->name, dev->sg_path);
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&vendor_path,
|
2014-01-30 07:05:59 +00:00
|
|
|
"%s/%s/vendor", prefix, dev->name) < 0 ||
|
2013-05-03 18:07:22 +00:00
|
|
|
virAsprintf(&model_path,
|
2014-01-30 07:05:59 +00:00
|
|
|
"%s/%s/model", prefix, dev->name) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
if (virFileReadAll(vendor_path, 1024, &vendor) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
if (virFileReadAll(model_path, 1024, &model) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
virTrimSpaces(vendor, NULL);
|
|
|
|
virTrimSpaces(model, NULL);
|
|
|
|
|
2013-07-04 10:17:18 +00:00
|
|
|
if (virAsprintf(&dev->id, "%s:%s", vendor, model) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return NULL;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
2018-07-24 15:52:29 +00:00
|
|
|
VIR_STEAL_PTR(ret, dev);
|
2013-05-03 18:07:22 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-07 14:46:21 +00:00
|
|
|
static void
|
|
|
|
virSCSIDeviceUsedByInfoFree(virUsedByInfoPtr used_by)
|
|
|
|
{
|
|
|
|
VIR_FREE(used_by->drvname);
|
|
|
|
VIR_FREE(used_by->domname);
|
|
|
|
VIR_FREE(used_by);
|
|
|
|
}
|
2019-02-07 17:18:52 +00:00
|
|
|
VIR_DEFINE_AUTOPTR_FUNC(virUsedByInfo, virSCSIDeviceUsedByInfoFree);
|
2014-03-07 14:46:21 +00:00
|
|
|
|
2013-05-03 18:07:22 +00:00
|
|
|
void
|
|
|
|
virSCSIDeviceFree(virSCSIDevicePtr dev)
|
|
|
|
{
|
2014-01-29 17:22:42 +00:00
|
|
|
size_t i;
|
|
|
|
|
2013-05-03 18:07:22 +00:00
|
|
|
if (!dev)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(dev->id);
|
|
|
|
VIR_FREE(dev->name);
|
|
|
|
VIR_FREE(dev->sg_path);
|
2014-03-07 14:46:21 +00:00
|
|
|
for (i = 0; i < dev->n_used_by; i++)
|
|
|
|
virSCSIDeviceUsedByInfoFree(dev->used_by[i]);
|
2014-01-29 17:22:42 +00:00
|
|
|
VIR_FREE(dev->used_by);
|
2013-05-03 18:07:22 +00:00
|
|
|
VIR_FREE(dev);
|
|
|
|
}
|
|
|
|
|
2014-01-29 17:22:42 +00:00
|
|
|
int
|
2013-05-03 18:07:22 +00:00
|
|
|
virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev,
|
2014-03-01 06:28:56 +00:00
|
|
|
const char *drvname,
|
|
|
|
const char *domname)
|
2013-05-03 18:07:22 +00:00
|
|
|
{
|
2018-07-24 15:52:29 +00:00
|
|
|
VIR_AUTOPTR(virUsedByInfo) copy = NULL;
|
|
|
|
|
2014-03-01 06:28:56 +00:00
|
|
|
if (VIR_ALLOC(copy) < 0)
|
|
|
|
return -1;
|
2014-03-07 14:46:21 +00:00
|
|
|
if (VIR_STRDUP(copy->drvname, drvname) < 0 ||
|
|
|
|
VIR_STRDUP(copy->domname, domname) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return -1;
|
2014-03-07 14:46:21 +00:00
|
|
|
|
|
|
|
if (VIR_APPEND_ELEMENT(dev->used_by, dev->n_used_by, copy) < 0)
|
2018-07-24 15:52:29 +00:00
|
|
|
return -1;
|
2014-01-29 17:22:42 +00:00
|
|
|
|
2014-03-07 14:46:21 +00:00
|
|
|
return 0;
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
2014-01-29 17:22:42 +00:00
|
|
|
bool
|
|
|
|
virSCSIDeviceIsAvailable(virSCSIDevicePtr dev)
|
2013-05-03 18:07:22 +00:00
|
|
|
{
|
2014-01-29 17:22:42 +00:00
|
|
|
return dev->n_used_by == 0;
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
virSCSIDeviceGetName(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->name;
|
|
|
|
}
|
|
|
|
|
2016-11-16 14:27:20 +00:00
|
|
|
const char *
|
|
|
|
virSCSIDeviceGetPath(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->sg_path;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:22 +00:00
|
|
|
unsigned int
|
|
|
|
virSCSIDeviceGetAdapter(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->adapter;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
virSCSIDeviceGetBus(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->bus;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
virSCSIDeviceGetTarget(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->target;
|
|
|
|
}
|
|
|
|
|
2015-06-17 03:29:53 +00:00
|
|
|
unsigned long long
|
2013-05-03 18:07:22 +00:00
|
|
|
virSCSIDeviceGetUnit(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
virSCSIDeviceGetReadonly(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->readonly;
|
|
|
|
}
|
|
|
|
|
2014-01-08 14:51:29 +00:00
|
|
|
bool
|
|
|
|
virSCSIDeviceGetShareable(virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
return dev->shareable;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:22 +00:00
|
|
|
int
|
|
|
|
virSCSIDeviceFileIterate(virSCSIDevicePtr dev,
|
|
|
|
virSCSIDeviceFileActor actor,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
return (actor)(dev, dev->sg_path, opaque);
|
|
|
|
}
|
|
|
|
|
|
|
|
virSCSIDeviceListPtr
|
|
|
|
virSCSIDeviceListNew(void)
|
|
|
|
{
|
|
|
|
virSCSIDeviceListPtr list;
|
|
|
|
|
|
|
|
if (virSCSIInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(list = virObjectLockableNew(virSCSIDeviceListClass)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virSCSIDeviceListDispose(void *obj)
|
|
|
|
{
|
|
|
|
virSCSIDeviceListPtr list = obj;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < list->count; i++)
|
|
|
|
virSCSIDeviceFree(list->devs[i]);
|
|
|
|
|
|
|
|
VIR_FREE(list->devs);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virSCSIDeviceListAdd(virSCSIDeviceListPtr list,
|
|
|
|
virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
if (virSCSIDeviceListFind(list, dev)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Device %s already exists"),
|
|
|
|
dev->name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-01-07 14:44:27 +00:00
|
|
|
return VIR_APPEND_ELEMENT(list->devs, list->count, dev);
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virSCSIDevicePtr
|
|
|
|
virSCSIDeviceListGet(virSCSIDeviceListPtr list, int idx)
|
|
|
|
{
|
|
|
|
if (idx >= list->count || idx < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return list->devs[idx];
|
|
|
|
}
|
|
|
|
|
2014-01-07 14:44:27 +00:00
|
|
|
size_t
|
2013-05-03 18:07:22 +00:00
|
|
|
virSCSIDeviceListCount(virSCSIDeviceListPtr list)
|
|
|
|
{
|
|
|
|
return list->count;
|
|
|
|
}
|
|
|
|
|
|
|
|
virSCSIDevicePtr
|
|
|
|
virSCSIDeviceListSteal(virSCSIDeviceListPtr list,
|
|
|
|
virSCSIDevicePtr dev)
|
|
|
|
{
|
|
|
|
virSCSIDevicePtr ret = NULL;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < list->count; i++) {
|
2014-01-07 14:44:27 +00:00
|
|
|
if (list->devs[i]->adapter == dev->adapter &&
|
|
|
|
list->devs[i]->bus == dev->bus &&
|
|
|
|
list->devs[i]->target == dev->target &&
|
|
|
|
list->devs[i]->unit == dev->unit) {
|
|
|
|
ret = list->devs[i];
|
|
|
|
VIR_DELETE_ELEMENT(list->devs, i, list->count);
|
|
|
|
break;
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
virSCSIDeviceListDel(virSCSIDeviceListPtr list,
|
2014-01-29 17:22:42 +00:00
|
|
|
virSCSIDevicePtr dev,
|
2014-03-01 06:28:56 +00:00
|
|
|
const char *drvname,
|
|
|
|
const char *domname)
|
2013-05-03 18:07:22 +00:00
|
|
|
{
|
2014-01-29 17:22:42 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < dev->n_used_by; i++) {
|
2014-03-01 06:28:56 +00:00
|
|
|
if (STREQ_NULLABLE(dev->used_by[i]->drvname, drvname) &&
|
|
|
|
STREQ_NULLABLE(dev->used_by[i]->domname, domname)) {
|
2014-01-29 17:22:42 +00:00
|
|
|
if (dev->n_used_by > 1) {
|
2014-03-07 14:46:21 +00:00
|
|
|
virSCSIDeviceUsedByInfoFree(dev->used_by[i]);
|
2014-01-29 17:22:42 +00:00
|
|
|
VIR_DELETE_ELEMENT(dev->used_by, i, dev->n_used_by);
|
|
|
|
} else {
|
2018-07-24 15:52:29 +00:00
|
|
|
VIR_AUTOPTR(virSCSIDevice) tmp = NULL;
|
2014-01-29 17:22:42 +00:00
|
|
|
tmp = virSCSIDeviceListSteal(list, dev);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-05-03 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virSCSIDevicePtr
|
|
|
|
virSCSIDeviceListFind(virSCSIDeviceListPtr list,
|
|
|
|
virSCSIDevicePtr dev)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-05-03 18:07:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < list->count; i++) {
|
|
|
|
if (list->devs[i]->adapter == dev->adapter &&
|
|
|
|
list->devs[i]->bus == dev->bus &&
|
|
|
|
list->devs[i]->target == dev->target &&
|
|
|
|
list->devs[i]->unit == dev->unit)
|
|
|
|
return list->devs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|