Chris Lalancette 08b914
--- a/src/storage_backend_iscsi.c	4 Mar 2008 20:02:34 -0000	1.3
Chris Lalancette 08b914
+++ b/src/storage_backend_iscsi.c	26 Mar 2008 22:07:05 -0000
Chris Lalancette 08b914
@@ -170,20 +170,91 @@
Chris Lalancette 08b914
 virStorageBackendISCSIMakeLUN(virConnectPtr conn,
Chris Lalancette 08b914
                               virStoragePoolObjPtr pool,
Chris Lalancette 08b914
                               char **const groups,
Chris Lalancette 08b914
-                              void *data ATTRIBUTE_UNUSED)
Chris Lalancette 08b914
+                              void *data)
Chris Lalancette 08b914
 {
Chris Lalancette 08b914
     virStorageVolDefPtr vol;
Chris Lalancette 08b914
     int fd = -1;
Chris Lalancette 08b914
+    unsigned int target, channel, id, lun;
Chris Lalancette 08b914
     char lunid[100];
Chris Lalancette 08b914
-    char *dev = groups[4];
Chris Lalancette 08b914
     int opentries = 0;
Chris Lalancette 08b914
     char *devpath = NULL;
Chris Lalancette 08b914
+    char *session = data;
Chris Lalancette 08b914
+    char sysfs_path[PATH_MAX];
Chris Lalancette 08b914
+    char *dev = NULL;
Chris Lalancette 08b914
+    DIR *sysdir;
Chris Lalancette 08b914
+    struct dirent *block_dirent;
Chris Lalancette 08b914
+    struct stat sbuf;
Chris Lalancette 08b914
+    int len;
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    if ((virStrToLong_ui(groups[0], NULL, 10, &target) < 0) ||
Chris Lalancette 08b914
+        (virStrToLong_ui(groups[1], NULL, 10, &channel) < 0) ||
Chris Lalancette 08b914
+        (virStrToLong_ui(groups[2], NULL, 10, &id) < 0) ||
Chris Lalancette 08b914
+        (virStrToLong_ui(groups[3], NULL, 10, &lun) < 0)) {
Chris Lalancette 08b914
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
Chris Lalancette 08b914
+                              _("Failed parsing iscsiadm commands"));
Chris Lalancette 08b914
+        return -1;
Chris Lalancette 08b914
+    }
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    if (lun == 0) {
Chris Lalancette 08b914
+        /* the 0'th LUN isn't a real LUN, it's just a control LUN; skip it */
Chris Lalancette 08b914
+        return 0;
Chris Lalancette 08b914
+    }
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    snprintf(sysfs_path, PATH_MAX,
Chris Lalancette 08b914
+             "/sys/class/iscsi_session/session%s/device/"
Chris Lalancette 08b914
+             "target%d:%d:%d/%d:%d:%d:%d/block",
Chris Lalancette 08b914
+             session, target, channel, id, target, channel, id, lun);
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    if (stat(sysfs_path, &sbuf) < 0) {
Chris Lalancette 08b914
+        /* block path in subdir didn't exist; this is unexpected, so fail */
Chris Lalancette 08b914
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
Chris Lalancette 08b914
+                              _("Failed to find the sysfs path for %d:%d:%d:%d: %s"),
Chris Lalancette 08b914
+                              target, channel, id, lun, strerror(errno));
Chris Lalancette 08b914
+        return -1;
Chris Lalancette 08b914
+    }
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    sysdir = opendir(sysfs_path);
Chris Lalancette 08b914
+    if (sysdir == NULL) {
Chris Lalancette 08b914
+        /* we failed for some reason; return an error */
Chris Lalancette 08b914
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
Chris Lalancette 08b914
+                              _("Failed to opendir sysfs path %s: %s"),
Chris Lalancette 08b914
+                              sysfs_path, strerror(errno));
Chris Lalancette 08b914
+        return -1;
Chris Lalancette 08b914
+    }
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    while ((block_dirent = readdir(sysdir)) != NULL) {
Chris Lalancette 08b914
+        len = strlen(block_dirent->d_name);
Chris Lalancette 08b914
+        if ((len == 1 && block_dirent->d_name[0] == '.') ||
Chris Lalancette 08b914
+            (len == 2 && block_dirent->d_name[0] == '.' && block_dirent->d_name[1] == '.')) {
Chris Lalancette 08b914
+            /* the . and .. directories; just skip them */
Chris Lalancette 08b914
+            continue;
Chris Lalancette 08b914
+        }
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+        /* OK, not . or ..; let's see if it is a SCSI device */
Chris Lalancette 08b914
+        if (len > 2 &&
Chris Lalancette 08b914
+            block_dirent->d_name[0] == 's' &&
Chris Lalancette 08b914
+            block_dirent->d_name[1] == 'd') {
Chris Lalancette 08b914
+            /* looks like a scsi device, smells like scsi device; it must be
Chris Lalancette 08b914
+               a scsi device */
Chris Lalancette 08b914
+            dev = strdup(block_dirent->d_name);
Chris Lalancette 08b914
+            break;
Chris Lalancette 08b914
+        }
Chris Lalancette 08b914
+    }
Chris Lalancette 08b914
+    closedir(sysdir);
Chris Lalancette 08b914
+
Chris Lalancette 08b914
+    if (dev == NULL) {
Chris Lalancette 08b914
+        /* we didn't find the sd? device we were looking for; fail */
Chris Lalancette 08b914
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
Chris Lalancette 08b914
+                              _("Failed to find SCSI device for %d:%d:%d:%d: %s"),
Chris Lalancette 08b914
+                              target, channel, id, lun, strerror(errno));
Chris Lalancette 08b914
+        return -1;
Chris Lalancette 08b914
+    }
Chris Lalancette 08b914
 
Chris Lalancette 08b914
     snprintf(lunid, sizeof(lunid)-1, "lun-%s", groups[3]);
Chris Lalancette 08b914
 
Chris Lalancette 08b914
     if ((vol = calloc(1, sizeof(virStorageVolDef))) == NULL) {
Chris Lalancette 08b914
         virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("volume"));
Chris Lalancette 08b914
-        return -1;
Chris Lalancette 08b914
+        goto cleanup;
Chris Lalancette 08b914
     }
Chris Lalancette 08b914
 
Chris Lalancette 08b914
     if ((vol->name = strdup(lunid)) == NULL) {
Chris Lalancette 08b914
@@ -197,6 +268,8 @@
Chris Lalancette 08b914
     }
Chris Lalancette 08b914
     strcpy(devpath, "/dev/");
Chris Lalancette 08b914
     strcat(devpath, dev);
Chris Lalancette 08b914
+    free(dev);
Chris Lalancette 08b914
+    dev = NULL;
Chris Lalancette 08b914
     /* It can take a little while between logging into the ISCSI
Chris Lalancette 08b914
      * server and udev creating the /dev nodes, so if we get ENOENT
Chris Lalancette 08b914
      * we must retry a few times - they should eventually appear.
Chris Lalancette 08b914
@@ -258,6 +331,7 @@
Chris Lalancette 08b914
     if (fd != -1) close(fd);
Chris Lalancette 08b914
     free(devpath);
Chris Lalancette 08b914
     virStorageVolDefFree(vol);
Chris Lalancette 08b914
+    free(dev);
Chris Lalancette 08b914
     return -1;
Chris Lalancette 08b914
 }
Chris Lalancette 08b914
 
Chris Lalancette 08b914
@@ -281,14 +355,13 @@
Chris Lalancette 08b914
      *           scsi1 Channel 00 Id 0 Lun: 5
Chris Lalancette 08b914
      *                   Attached scsi disk sdg          State: running
Chris Lalancette 08b914
      *
Chris Lalancette 08b914
-     * Need 2 regex to match alternating lines
Chris Lalancette 08b914
+     * Need a regex to match the Channel:Id:Lun lines
Chris Lalancette 08b914
      */
Chris Lalancette 08b914
     const char *regexes[] = {
Chris Lalancette 08b914
-        "^\\s*scsi(\\S+)\\s+Channel\\s+(\\S+)\\s+Id\\s+(\\S+)\\s+Lun:\\s+(\\S+)\\s*$",
Chris Lalancette 08b914
-        "^\\s*Attached\\s+scsi\\s+disk\\s+(\\S+)\\s+State:\\s+running\\s*$"
Chris Lalancette 08b914
+        "^\\s*scsi(\\S+)\\s+Channel\\s+(\\S+)\\s+Id\\s+(\\S+)\\s+Lun:\\s+(\\S+)\\s*$"
Chris Lalancette 08b914
     };
Chris Lalancette 08b914
     int vars[] = {
Chris Lalancette 08b914
-        4, 1
Chris Lalancette 08b914
+        4
Chris Lalancette 08b914
     };
Chris Lalancette 08b914
     const char *prog[] = {
Chris Lalancette 08b914
         ISCSIADM, "--mode", "session", "-r", session, "-P", "3", NULL,
Chris Lalancette 08b914
@@ -296,11 +369,11 @@
Chris Lalancette 08b914
 
Chris Lalancette 08b914
     return virStorageBackendRunProgRegex(conn, pool,
Chris Lalancette 08b914
                                          prog,
Chris Lalancette 08b914
-                                         2,
Chris Lalancette 08b914
+                                         1,
Chris Lalancette 08b914
                                          regexes,
Chris Lalancette 08b914
                                          vars,
Chris Lalancette 08b914
                                          virStorageBackendISCSIMakeLUN,
Chris Lalancette 08b914
-                                         NULL);
Chris Lalancette 08b914
+                                         (void *)session);
Chris Lalancette 08b914
 }
Chris Lalancette 08b914
 
Chris Lalancette 08b914