Remove all hand-crafted sysfs access code and replace it with libudev functions. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> --- libmultipath/discovery.c | 309 +++++++++++++-------------------------------- 1 files changed, 89 insertions(+), 220 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 452c709..7adda2a 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -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) @@ -484,72 +419,6 @@ get_serial (char * str, int maxlen, int fd) } 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) { if (pp->fd < 0) @@ -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", -- 1.7.3.4 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel