[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] [RFC][PATCH]: Make the iscsi storage backend mostly use sysfs



Hello,
     The newer version of iscsi-initiator-utils (6.2.0.865-0.2),
available in the f8-updates repository, is required as part of the fix
for a hang when doing iscsi logout (the other fix is in the 2.6.25
kernel).  Unfortunately, this version also changes the output of the
iscsiadm -m session -P 3 command; this output was being used to gather
the scsi devices available in a pool and present them as volumes.
Consequently, when starting an iSCSI pool on a machine with these newer
versions of the iscsi tools, the pool will be successfully created but
you won't be able to see any of the LUNs presented.

The attached patch *lessens* our dependency on the iscsiadm output by
using sysfs to gather the /dev devices.  Note that this patch is not to
be applied; I'm just putting it out there so people can take a look at
it.  DanB has suggested getting rid of our dependency on the iscsiadm
output altogether is the way to go, and I agree with him there; this is
mostly just a short-term solution, to possibly base future work on.

Chris Lalancette
--- libvirt-0.4.0/src/storage_backend_iscsi.c.orig	2008-02-22 15:56:03.000000000 -0500
+++ libvirt-0.4.0/src/storage_backend_iscsi.c	2008-02-22 15:57:38.000000000 -0500
@@ -161,24 +161,59 @@ static int virStorageBackendISCSIConnect
 static int virStorageBackendISCSIMakeLUN(virConnectPtr conn,
                                          virStoragePoolObjPtr pool,
                                          char **const groups,
-                                         void *data ATTRIBUTE_UNUSED)
+                                         void *data)
 {
     virStorageVolDefPtr vol;
     int fd = -1;
-    char scsiid[100];
-    char *dev = groups[4];
+    unsigned int channel;
+    char lunid[100];
     int opentries = 0;
     char *devpath = NULL;
+    char *session = (char *) data;
+    char sysfs_path[PATH_MAX];
+    char *dev = NULL;
+    DIR *sysdir;
+    struct dirent *block_dirent;
+    struct stat sbuf;
+    int len;
+
+    channel = strtoul(groups[1],NULL,10);
+
+    snprintf(sysfs_path, PATH_MAX, "/sys/class/iscsi_session/session%s/device/target%s:%.1d:%s/%s:%.1d:%s:%s/block",session,groups[0],channel,groups[2],groups[0],channel,groups[2],groups[3]);
+
+    if (stat(sysfs_path, &sbuf) < 0) {
+        // OK, block path in subdir didn't exist.  This is probably the 0'th
+        // LUN that isn't really a block device.  Just return 0 so we go on
+        return 0;
+    }
+    sysdir = opendir(sysfs_path);
+    if (sysdir == NULL) {
+        // we failed for some reason; return an error
+        return -1;
+    }
+    while ( (block_dirent = readdir(sysdir)) != NULL) {
+        len = strlen(block_dirent->d_name);
+        if ((len == 1 && block_dirent->d_name[0] == '.') ||
+            (len == 2 && block_dirent->d_name[0] == '.' && block_dirent->d_name[1] == '.')) {
+            // the . and .. directories; just skip them
+            continue;
+        }
+        // OK, not . or ..; must be our block device
+        dev = strdup(block_dirent->d_name);
+        break;
+    }
+    closedir(sysdir);
+
+    // FIXME: if dev is still NULL, it is an error here
 
-    snprintf(scsiid, sizeof(scsiid)-1, "%s:%s:%s:%s",
-             groups[0], groups[1], groups[2], groups[3]);
+    snprintf(lunid, sizeof(lunid)-1, "lun-%s", groups[3]);
 
     if ((vol = calloc(1, sizeof(virStorageVolDef))) == NULL) {
         virStorageReportError(conn, VIR_ERR_NO_MEMORY, "volume");
         return -1;
     }
 
-    if ((vol->name = strdup(scsiid)) == NULL) {
+    if ((vol->name = strdup(lunid)) == NULL) {
         virStorageReportError(conn, VIR_ERR_NO_MEMORY, "name");
         goto cleanup;
     }
@@ -189,6 +224,8 @@ static int virStorageBackendISCSIMakeLUN
     }
     strcpy(devpath, "/dev/");
     strcat(devpath, dev);
+    free(dev);
+    dev = NULL;
     /* It can take a little while between logging into the ISCSI
      * server and udev creating the /dev nodes, so if we get ENOENT
      * we must retry a few times - they should eventually appear.
@@ -248,6 +285,7 @@ static int virStorageBackendISCSIMakeLUN
     if (fd != -1) close(fd);
     free(devpath);
     virStorageVolDefFree(vol);
+    free(dev);
     return -1;
 }
 
@@ -273,11 +311,10 @@ static int virStorageBackendISCSIFindLUN
      * Need 2 regex to match alternating lines
      */
     const char *regexes[] = {
-        "^\\s*scsi(\\S+)\\s+Channel\\s+(\\S+)\\s+Id\\s+(\\S+)\\s+Lun:\\s+(\\S+)\\s*$",
-        "^\\s*Attached\\s+scsi\\s+disk\\s+(\\S+)\\s+State:\\s+running\\s*$"
+        "^\\s*scsi(\\S+)\\s+Channel\\s+(\\S+)\\s+Id\\s+(\\S+)\\s+Lun:\\s+(\\S+)\\s*$"
     };
     int vars[] = {
-        4, 1
+        4
     };
     const char *prog[] = {
         ISCSIADM, "--mode", "session", "-r", session, "-P", "3", NULL,
@@ -285,11 +322,11 @@ static int virStorageBackendISCSIFindLUN
 
     return virStorageBackendRunProgRegex(conn, pool,
                                          prog,
-                                         2,
+                                         1,
                                          regexes,
                                          vars,
                                          virStorageBackendISCSIMakeLUN,
-                                         NULL);
+                                         (void *)session);
 }
 
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]