David Allan wrote:
Last March, DanPB posted code to create pools from SCSI HBAs. This
patch is simply bringing that code into the current tree.
* src/storage_backend_scsi.[ch] contain the pool implementataion
* There are small changes to several other source files to integrate the new pool type.
[hmm... I wrote this a couple days ago and nearly forgot to send it. ]
This looks fine, overall.
a few suggestions below.
...
diff --git a/src/storage_backend_scsi.c b/src/storage_backend_scsi.c
...
+ /*
+ * First get the class based path eg
+ *
+ * /sys/class/scsi_host/host1/device
+ */
+ if ((dev = malloc(sizeof(LINUX_SYSFS_SCSI_HOST_PREFIX) +
+ strlen(pool->def->source.adapter) +
+ sizeof(LINUX_SYSFS_SCSI_HOST_POSTFIX) +
+ 1)) == NULL) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
+ strcpy(dev, LINUX_SYSFS_SCSI_HOST_PREFIX);
+ strcat(dev, pool->def->source.adapter);
+ strcat(dev, LINUX_SYSFS_SCSI_HOST_POSTFIX);
use virAsprintf in place of the above malloc/strcpy/strcat calls
+ /*
+ * Now resolve the class based path symlink to the real
+ * device path, which is likely under PCI bus hierarchy
+ * and is the path tracked by HAL
+ */
+ /* Readlink does not null terminate, so we reserve one byte */
+ if ((len = readlink(dev, relLink, sizeof(relLink)-1)) < 0) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot find SCSI host adapter '%s' at
'%s'"),
+ pool->def->source.adapter, dev);
+ free(dev);
+ return -1;
+ }
+ relLink[len] = '\0';
+
+
+ /*
+ * The symlink is relative, so now we have to turn it
+ * into a absolute path
+ */
+ if ((tmp = realloc(dev,
+ sizeof(LINUX_SYSFS_SCSI_HOST_PREFIX) +
+ strlen(pool->def->source.adapter) +
+ 1 +
+ strlen(relLink) +
+ 1)) == NULL) {
+ virReportOOMError(conn);
+ free(dev);
+ return -1;
+ }
+ dev = tmp;
+
+ strcpy(dev, LINUX_SYSFS_SCSI_HOST_PREFIX);
+ strcat(dev, pool->def->source.adapter);
+ strcat(dev, "/");
+ strcat(dev, relLink);
use virAsprintf here, too.
+ /*
+ * And finally canonicalize the absolute path to remove the
+ * copious .. components
+ */
+ if (!realpath(dev, absLink)) {
Don't use realpath. e.g. mingw lacks it.
Instead, use canonicalize_file_name, which should be
portable thanks to gnulib's canonicalize-lgpl module --
which you can include by adding that to the list of module
names in bootstrap.
+ char ebuf[1024];
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot canonicalize link: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ free(dev);
+ return -1;
+ }
+ free(dev);
+
+ if (strlen(absLink) >= buflen) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("link too long for buffer"));
+ return -1;
+ }
+ strcpy(buf, absLink);
+
+ return 0;
+}
...
+/**
+ * virStorageBackendSCSIAddLUN:
+ *
+ * @conn: connection to report errors against
+ * @pool: pool to register volume with
+ * @ctx: HAL context
+ * @devname: HAL device name for LUN
+ *
+ * Given a HAL device supported 'block' and 'storage' capabilities
+ * register it as a volume in the pool
+ *
+ * Returns 0 on success, -1 on error
+ */
+static int
+virStorageBackendSCSIAddLUN(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ LibHalContext *ctx,
+ const char *devname)
+{
+ char **strdevs = NULL;
+ int numstrdevs = 0;
+ char *dev = NULL, *key = NULL;
+ unsigned long long size;
How about uint64_t instead, since it's the value
returned by libhal_device_get_property_uint64?
+ int host, bus, target, lun;
+ int n = -1, i;
+ int ret = -1;
+ char name[100];
...
+ HAL_GET_PROPERTY(strdevs[0], "storage.serial",
&derr, string, key);
+ HAL_GET_PROPERTY(strdevs[0], "storage.size", &derr, uint64, size);
...