Use udev devices during discovery
authorHannes Reinecke <hare@suse.de>
Thu, 19 Apr 2012 09:09:05 +0000 (11:09 +0200)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Fri, 20 Apr 2012 17:47:49 +0000 (19:47 +0200)
Remove all hand-crafted sysfs access code and replace it with
libudev functions.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/discovery.c

index 452c709..7adda2a 100644 (file)
@@ -192,127 +192,126 @@ sysfs_get_timeout(struct path *pp, unsigned int *timeout)
 }
 
 int
-sysfs_get_size (struct path *pp, unsigned long long * size)
+sysfs_get_tgt_nodename (struct path *pp, char * node)
 {
-       const char * attr;
-       int r;
-
-       if (!pp->udev)
-               return 1;
-
-       attr = udev_device_get_sysattr_value(pp->udev, "size");
-       if (!attr) {
-               condlog(3, "%s: No size attribute in sysfs", pp->dev);
-               return 1;
-       }
-
-       r = sscanf(attr, "%llu\n", size);
+       const char *targetid, *value;
+       struct udev_device *parent, *tgtdev;
 
-       if (r != 1) {
-               condlog(3, "%s: Cannot parse size attribute '%s'",
-                       pp->dev, attr);
+       parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_device");
+       if (!parent)
                return 1;
+       /* Check for SAS */
+       value = udev_device_get_sysattr_value(parent, "sas_address");
+       if (value) {
+               strncpy(node, value, NODE_NAME_SIZE);
+               return 0;
        }
 
-       return 0;
-}
-
-int
-sysfs_get_tgt_nodename (struct path *pp, char * node)
-{
-       const char * targetid;
-       struct udev_device *parent;
-       char attr_path[SYSFS_PATH_SIZE];
-       size_t len;
-
-       parent = pp->udev;
-       while (parent) {
-               targetid = udev_device_get_sysname(parent);
-               if (!strncmp(targetid , "target", 6))
-                       break;
-               parent = udev_device_get_parent(parent);
-       }
-       /* 'target' needs to exist */
-       if (!parent || !targetid)
+       parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_target");
+       if (!parent)
                return 1;
+       tgtdev = udev_device_new_from_subsystem_sysname(conf->udev, "fc_transport", udev_device_get_sysname(parent));
        /* Check if it's FibreChannel */
-       if (safe_sprintf(attr_path,
-                        "/class/fc_transport/%s", targetid)) {
-               condlog(0, "attr_path too small");
-               return 1;
-       }
+       if (tgtdev) {
+               const char *value;
 
-       len = sysfs_attr_get_value(attr_path, "node_name",
-                                  node, NODE_NAME_SIZE);
-       if (len)
-               return 0;
+               value = udev_device_get_sysattr_value(tgtdev, "node_name");
+               if (value) {
+                       strncpy(node, value, NODE_NAME_SIZE);
+                       return 0;
+               }
+               udev_device_unref(tgtdev);
+       }
 
        /* Check for iSCSI */
        parent = pp->udev;
+       targetid = NULL;
        while (parent) {
                targetid = udev_device_get_sysname(parent);
                if (!strncmp(targetid , "session", 6))
                        break;
                parent = udev_device_get_parent(parent);
+               targetid = NULL;
        }
        if (parent) {
-               if (safe_sprintf(attr_path, "/class/iscsi_session/%s",
-                                targetid)) {
-                       condlog(0, "attr_path too small");
-                       return 1;
+               tgtdev = udev_device_new_from_subsystem_sysname(conf->udev, "iscsi_session", targetid);
+               if (node) {
+                       const char *value;
+
+                       value = udev_device_get_sysattr_value(tgtdev, "targetname");
+                       if (value) {
+                               strncpy(node, value, NODE_NAME_SIZE);
+                               return 0;
+                       }
+                       udev_device_unref(tgtdev);
                }
-               len = sysfs_attr_get_value(attr_path, "targetname", node,
-                                          NODE_NAME_SIZE);
-               if (len)
-                       return 0;
        }
-
        return 1;
 }
 
-static int
-find_rport_id(struct path *pp)
+static void
+sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
 {
-       char attr_path[SYSFS_PATH_SIZE];
-       char *dir, *base;
-       int host, channel, rport_id = -1;
-
-       if (safe_sprintf(attr_path,
-                        "/class/fc_transport/target%i:%i:%i",
-                        pp->sg_id.host_no, pp->sg_id.channel,
-                        pp->sg_id.scsi_id)) {
-               condlog(0, "attr_path too small for target");
-               return 1;
-       }
-
-       if (sysfs_resolve_link(attr_path, SYSFS_PATH_SIZE))
-               return -1;
-
-       condlog(4, "target%d:%d:%d -> path %s", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id, attr_path);
-       dir = attr_path;
-       do {
-               base = basename(dir);
-               dir = dirname(dir);
+       struct udev_device *parent = pp->udev;
+       struct udev_device *rport_dev = NULL;
+       char value[11];
+       const char *rport_id = NULL;
 
-               if (sscanf((const char *)base, "rport-%d:%d-%d", &host, &channel, &rport_id) == 3)
+       while (parent) {
+               rport_id = udev_device_get_sysname(parent);
+               if (!strncmp(rport_id, "rport-", 6))
                        break;
-       } while (strcmp((const char *)dir, "/"));
-
-       if (rport_id < 0)
-               return -1;
-
-       condlog(4, "target%d:%d:%d -> rport_id %d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
-       return rport_id;
+               parent = udev_device_get_parent(parent);
+               rport_id = NULL;
+       }
+       if (!parent || !rport_id) {
+               condlog(0, "%s: rport id not found", pp->dev);
+               return;
+       }
+       rport_dev = udev_device_new_from_subsystem_sysname(conf->udev, "fc_remote_ports", rport_id);
+       if (!rport_dev) {
+               condlog(3, "%s: No fc_remote_port device for '%s'", pp->dev,
+                       rport_id);
+               return;
+       }
+       condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
+               pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
+
+       snprintf(value, 11, "%u", mpp->dev_loss);
+       if (sysfs_attr_set_value(rport_dev, "dev_loss_tmo", value, 11) < 0) {
+               if ((!mpp->fast_io_fail ||
+                    mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
+                   && mpp->dev_loss > 600) {
+                       condlog(3, "%s: limiting dev_loss_tmo to 600, since "
+                               "fast_io_fail is not set", mpp->alias);
+                       snprintf(value, 11, "%u", 600);
+                       if (sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
+                                                value, 11) < 0)
+                               condlog(0, "%s failed to set dev_loss_tmo",
+                                       mpp->alias);
+                       return;
+               }
+       }
+       if (mpp->fast_io_fail){
+               if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
+                       sprintf(value, "off");
+               else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
+                       sprintf(value, "0");
+               else
+                       snprintf(value, 11, "%u", mpp->fast_io_fail);
+               if (sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
+                                        value, 11) < 0) {
+                       condlog(0, "%s failed to set fast_io_fail_tmo",
+                               mpp->alias);
+               }
+       }
 }
 
 int
 sysfs_set_scsi_tmo (struct multipath *mpp)
 {
-       char attr_path[SYSFS_PATH_SIZE];
        struct path *pp;
        int i;
-       char value[11];
-       int rport_id;
        int dev_loss_tmo = mpp->dev_loss;
 
        if (mpp->no_path_retry > 0) {
@@ -339,75 +338,11 @@ sysfs_set_scsi_tmo (struct multipath *mpp)
                return 0;
 
        vector_foreach_slot(mpp->paths, pp, i) {
-               rport_id = find_rport_id(pp);
-               if (rport_id < 0) {
-                       condlog(3, "failed to find rport_id for target%d:%d:%d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id);
-                       return 1;
-               }
-
-               if (safe_snprintf(attr_path, SYSFS_PATH_SIZE,
-                                 "/class/fc_remote_ports/rport-%d:%d-%d",
-                                 pp->sg_id.host_no, pp->sg_id.channel,
-                                 rport_id)) {
-                       condlog(0, "attr_path '/class/fc_remote_ports/rport-%d:%d-%d' too large", pp->sg_id.host_no, pp->sg_id.channel, rport_id);
-                       return 1;
-               }
-               if (mpp->dev_loss){
-                       snprintf(value, 11, "%u", mpp->dev_loss);
-                       if (sysfs_attr_set_value(attr_path, "dev_loss_tmo",
-                                                value, 11) < 0) {
-                               int err = 1;
-                               if ((!mpp->fast_io_fail || mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) && mpp->dev_loss > 600) {
-                                       strncpy(value, "600", 4);
-                                       condlog(3, "%s: limiting dev_loss_tmo to 600, since fast_io_fail is not set", mpp->alias);
-                                       if (sysfs_attr_set_value(attr_path, "dev_loss_tmo", value, 11) >= 0)
-                                               err = 0;
-                               }
-                               if (err) {
-                                       condlog(0, "%s failed to set %s/dev_loss_tmo", mpp->alias, attr_path);
-                                       return 1;
-                               }
-                       }
-               }
-               if (mpp->fast_io_fail){
-                       if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
-                               sprintf(value, "off");
-                       else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
-                               sprintf(value, "0");
-                       else
-                               snprintf(value, 11, "%u", mpp->fast_io_fail);
-                       if (sysfs_attr_set_value(attr_path, "fast_io_fail_tmo",
-                                                value, 11) < 0) {
-                               condlog(0,
-                                       "%s failed to set %s/fast_io_fail_tmo", 
-                                       mpp->alias, attr_path);
-                               return 1;
-                       }
-               }
+               sysfs_set_rport_tmo(mpp, pp);
        }
        return 0;
 }
 
-static int
-opennode (char * dev, int mode)
-{
-       char devpath[FILE_NAME_SIZE], *ptr;
-
-       if (safe_sprintf(devpath, "%s/%s", conf->udev_dir, dev)) {
-               condlog(0, "devpath too small");
-               return -1;
-       }
-       /*
-        * Translate '!' into '/'
-        */
-       ptr = devpath;
-       while ((ptr = strchr(ptr, '!'))) {
-               *ptr = '/';
-               ptr++;
-       }
-       return open(devpath, mode);
-}
-
 int
 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
        void *resp, int mx_resp_len)
@@ -483,72 +418,6 @@ get_serial (char * str, int maxlen, int fd)
        return 1;
 }
 
-static int
-get_inq (char * dev, char * vendor, char * product, char * rev, int fd)
-{
-       unsigned char buff[MX_ALLOC_LEN + 1] = {0};
-       int len;
-
-       if (fd < 0)
-               return 1;
-
-       if (0 != do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN))
-               return 1;
-
-       /* Check peripheral qualifier */
-       if ((buff[0] >> 5) != 0) {
-               int pqual = (buff[0] >> 5);
-               switch (pqual) {
-               case 1:
-                       condlog(3, "%s: INQUIRY failed, LU not connected", dev);
-                       break;
-               case 3:
-                       condlog(3, "%s: INQUIRY failed, LU not supported", dev);
-                       break;
-               default:
-                       condlog(3, "%s: INQUIRY failed, Invalid PQ %x",
-                               dev, pqual);
-                       break;
-               }
-
-               return 1;
-       }
-
-       len = buff[4] + 4;
-
-       if (len < 8) {
-               condlog(3, "%s: INQUIRY response too short (len %d)",
-                       dev, len);
-               return 1;
-       }
-
-       len -= 8;
-       memset(vendor, 0x0, 8);
-       memcpy(vendor, buff + 8, len > 8 ? 8 : len);
-       vendor[8] = '\0';
-       strchop(vendor);
-       if (len <= 8)
-               return 0;
-
-       len -= 8;
-
-       memset(product, 0x0, 16);
-       memcpy(product, buff + 16, len > 16 ? 16 : len);
-       product[16] = '\0';
-       strchop(product);
-       if (len <= 16)
-               return 0;
-
-       len -= 16;
-
-       memset(rev, 0x0, 4);
-       memcpy(rev, buff + 32, 4);
-       rev[4] = '\0';
-       strchop(rev);
-
-       return 0;
-}
-
 static int
 get_geometry(struct path *pp)
 {
@@ -980,7 +849,7 @@ pathinfo (struct path *pp, vector hwtable, int mask)
         * fetch info not available through sysfs
         */
        if (pp->fd < 0)
-               pp->fd = opennode(pp->dev, O_RDWR);
+               pp->fd = open(udev_device_get_devnode(pp->udev), O_RDWR);
 
        if (pp->fd < 0) {
                condlog(4, "Couldn't open node for %s: %s",