Merge branch 'coverity' of https://github.com/hreinecke/multipath-tools
[multipath-tools/.git] / libmultipath / discovery.c
1 /*
2  * Copyright (c) 2004, 2005, 2006 Christophe Varoqui
3  * Copyright (c) 2005 Stefan Bader, IBM
4  * Copyright (c) 2005 Mike Anderson
5  */
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <unistd.h>
9 #include <limits.h>
10 #include <fcntl.h>
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include <dirent.h>
14 #include <errno.h>
15 #include <libgen.h>
16 #include <libudev.h>
17
18 #include "checkers.h"
19 #include "vector.h"
20 #include "memory.h"
21 #include "util.h"
22 #include "structs.h"
23 #include "config.h"
24 #include "blacklist.h"
25 #include "callout.h"
26 #include "debug.h"
27 #include "propsel.h"
28 #include "sg_include.h"
29 #include "sysfs.h"
30 #include "discovery.h"
31 #include "prio.h"
32 #include "defaults.h"
33
34 int
35 alloc_path_with_pathinfo (vector hwtable, struct udev_device *udevice,
36                           int flag, struct path **pp_ptr)
37 {
38         int err = PATHINFO_FAILED;
39         struct path * pp;
40         const char * devname;
41
42         if (pp_ptr)
43                 *pp_ptr = NULL;
44
45         devname = udev_device_get_sysname(udevice);
46         if (!devname)
47                 return PATHINFO_FAILED;
48
49         pp = alloc_path();
50
51         if (!pp)
52                 return PATHINFO_FAILED;
53
54         if (safe_sprintf(pp->dev, "%s", devname)) {
55                 condlog(0, "pp->dev too small");
56         } else {
57                 pp->udev = udev_device_ref(udevice);
58                 err = pathinfo(pp, hwtable, flag | DI_BLACKLIST);
59         }
60
61         if (err)
62                 free_path(pp);
63         else if (pp_ptr)
64                 *pp_ptr = pp;
65         return err;
66 }
67
68 int
69 store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice,
70                 int flag, struct path **pp_ptr)
71 {
72         int err = PATHINFO_FAILED;
73         struct path * pp;
74         const char * devname;
75
76         if (pp_ptr)
77                 *pp_ptr = NULL;
78
79         devname = udev_device_get_sysname(udevice);
80         if (!devname)
81                 return PATHINFO_FAILED;
82
83         pp = alloc_path();
84
85         if (!pp)
86                 return PATHINFO_FAILED;
87
88         if(safe_sprintf(pp->dev, "%s", devname)) {
89                 condlog(0, "pp->dev too small");
90                 goto out;
91         }
92         pp->udev = udev_device_ref(udevice);
93         err = pathinfo(pp, hwtable,
94                        (conf->cmd == CMD_REMOVE_WWID)? flag :
95                                                        (flag | DI_BLACKLIST));
96         if (err)
97                 goto out;
98
99         err = store_path(pathvec, pp);
100         if (err)
101                 goto out;
102
103 out:
104         if (err)
105                 free_path(pp);
106         else if (pp_ptr)
107                 *pp_ptr = pp;
108         return err;
109 }
110
111 static int
112 path_discover (vector pathvec, struct config * conf,
113                struct udev_device *udevice, int flag)
114 {
115         struct path * pp;
116         const char * devname;
117
118         devname = udev_device_get_sysname(udevice);
119         if (!devname)
120                 return PATHINFO_FAILED;
121
122         if (filter_property(conf, udevice) > 0)
123                 return PATHINFO_SKIPPED;
124
125         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
126                            (char *)devname) > 0)
127                 return PATHINFO_SKIPPED;
128
129         pp = find_path_by_dev(pathvec, (char *)devname);
130         if (!pp) {
131                 return store_pathinfo(pathvec, conf->hwtable,
132                                       udevice, flag, NULL);
133         }
134         return pathinfo(pp, conf->hwtable, flag);
135 }
136
137 int
138 path_discovery (vector pathvec, struct config * conf, int flag)
139 {
140         struct udev_enumerate *udev_iter;
141         struct udev_list_entry *entry;
142         struct udev_device *udevice;
143         const char *devpath;
144         int num_paths = 0, total_paths = 0;
145
146         udev_iter = udev_enumerate_new(conf->udev);
147         if (!udev_iter)
148                 return -ENOMEM;
149
150         udev_enumerate_add_match_subsystem(udev_iter, "block");
151         udev_enumerate_add_match_is_initialized(udev_iter);
152         udev_enumerate_scan_devices(udev_iter);
153
154         udev_list_entry_foreach(entry,
155                                 udev_enumerate_get_list_entry(udev_iter)) {
156                 const char *devtype;
157                 devpath = udev_list_entry_get_name(entry);
158                 condlog(4, "Discover device %s", devpath);
159                 udevice = udev_device_new_from_syspath(conf->udev, devpath);
160                 if (!udevice) {
161                         condlog(4, "%s: no udev information", devpath);
162                         continue;
163                 }
164                 devtype = udev_device_get_devtype(udevice);
165                 if(devtype && !strncmp(devtype, "disk", 4)) {
166                         total_paths++;
167                         if (path_discover(pathvec, conf,
168                                           udevice, flag) == PATHINFO_OK)
169                                 num_paths++;
170                 }
171                 udev_device_unref(udevice);
172         }
173         udev_enumerate_unref(udev_iter);
174         condlog(4, "Discovered %d/%d paths", num_paths, total_paths);
175         return (total_paths - num_paths);
176 }
177
178 #define declare_sysfs_get_str(fname)                                    \
179 extern ssize_t                                                          \
180 sysfs_get_##fname (struct udev_device * udev, char * buff, size_t len)  \
181 {                                                                       \
182         int l;                                                  \
183         const char * attr;                                              \
184         const char * devname;                                           \
185                                                                         \
186         if (!udev)                                                      \
187                 return -ENOSYS;                                         \
188                                                                         \
189         devname = udev_device_get_sysname(udev);                        \
190                                                                         \
191         attr = udev_device_get_sysattr_value(udev, #fname);             \
192         if (!attr) {                                                    \
193                 condlog(3, "%s: attribute %s not found in sysfs",       \
194                         devname, #fname);                               \
195                 return -ENXIO;                                          \
196         }                                                               \
197         for (l = strlen(attr); l >= 1 && isspace(attr[l-1]); l--);      \
198         if (l > len) {                                                  \
199                 condlog(3, "%s: overflow in attribute %s",              \
200                         devname, #fname);                               \
201                 return -EINVAL;                                         \
202         }                                                               \
203         strlcpy(buff, attr, len);                                       \
204         return strchop(buff);                                           \
205 }
206
207 declare_sysfs_get_str(devtype);
208 declare_sysfs_get_str(vendor);
209 declare_sysfs_get_str(model);
210 declare_sysfs_get_str(rev);
211
212 ssize_t
213 sysfs_get_vpd (struct udev_device * udev, int pg,
214                unsigned char * buff, size_t len)
215 {
216         ssize_t attr_len;
217         char attrname[9];
218         const char * devname;
219
220         if (!udev) {
221                 condlog(3, "No udev device given\n");
222                 return -ENOSYS;
223         }
224
225         devname = udev_device_get_sysname(udev);
226         sprintf(attrname, "vpd_pg%02x", pg);
227         attr_len = sysfs_bin_attr_get_value(udev, attrname, buff, len);
228         if (attr_len < 0) {
229                 condlog(3, "%s: attribute %s not found in sysfs",
230                         devname, attrname);
231                 return attr_len;
232         }
233         return attr_len;
234 }
235
236 int
237 sysfs_get_timeout(struct path *pp, unsigned int *timeout)
238 {
239         const char *attr = NULL;
240         const char *subsys;
241         struct udev_device *parent;
242         char *eptr;
243         unsigned long t;
244
245         if (!pp->udev || pp->bus != SYSFS_BUS_SCSI)
246                 return -ENOSYS;
247
248         parent = pp->udev;
249         while (parent) {
250                 subsys = udev_device_get_subsystem(parent);
251                 attr = udev_device_get_sysattr_value(parent, "timeout");
252                 if (subsys && attr)
253                         break;
254                 parent = udev_device_get_parent(parent);
255         }
256         if (!attr) {
257                 condlog(3, "%s: No timeout value in sysfs", pp->dev);
258                 return -ENXIO;
259         }
260
261         t = strtoul(attr, &eptr, 0);
262         if (attr == eptr || t == ULONG_MAX) {
263                 condlog(3, "%s: Cannot parse timeout attribute '%s'",
264                         pp->dev, attr);
265                 return -EINVAL;
266         }
267         if (t > UINT_MAX) {
268                 condlog(3, "%s: Overflow in timeout value '%s'",
269                         pp->dev, attr);
270                 return -ERANGE;
271         }
272         *timeout = t;
273
274         return 0;
275 }
276
277 int
278 sysfs_get_tgt_nodename (struct path *pp, char * node)
279 {
280         const char *tgtname, *value;
281         struct udev_device *parent, *tgtdev;
282         int host, channel, tgtid = -1;
283
284         parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_device");
285         if (!parent)
286                 return 1;
287         /* Check for SAS */
288         value = udev_device_get_sysattr_value(parent, "sas_address");
289         if (value) {
290                 tgtdev = udev_device_get_parent(parent);
291                 while (tgtdev) {
292                         tgtname = udev_device_get_sysname(tgtdev);
293                         if (sscanf(tgtname, "end_device-%d:%d",
294                                    &host, &tgtid) == 2)
295                                 break;
296                         tgtdev = udev_device_get_parent(tgtdev);
297                         tgtid = -1;
298                 }
299                 if (tgtid >= 0) {
300                         pp->sg_id.proto_id = SCSI_PROTOCOL_SAS;
301                         pp->sg_id.transport_id = tgtid;
302                         strncpy(node, value, NODE_NAME_SIZE);
303                         return 0;
304                 }
305         }
306
307         /* Check for USB */
308         tgtdev = udev_device_get_parent(parent);
309         while (tgtdev) {
310                 value = udev_device_get_subsystem(tgtdev);
311                 if (value && !strcmp(value, "usb")) {
312                         pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
313                         tgtname = udev_device_get_sysname(tgtdev);
314                         strncpy(node, tgtname, strlen(tgtname));
315                         condlog(3, "%s: skip USB device %s", pp->dev, node);
316                         return 1;
317                 }
318                 tgtdev = udev_device_get_parent(tgtdev);
319         }
320         parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_target");
321         if (!parent)
322                 return 1;
323         /* Check for FibreChannel */
324         tgtdev = udev_device_get_parent(parent);
325         value = udev_device_get_sysname(tgtdev);
326         if (sscanf(value, "rport-%d:%d-%d",
327                    &host, &channel, &tgtid) == 3) {
328                 tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
329                                 "fc_remote_ports", value);
330                 if (tgtdev) {
331                         condlog(3, "SCSI target %d:%d:%d -> "
332                                 "FC rport %d:%d-%d",
333                                 pp->sg_id.host_no, pp->sg_id.channel,
334                                 pp->sg_id.scsi_id, host, channel,
335                                 tgtid);
336                         value = udev_device_get_sysattr_value(tgtdev,
337                                                               "node_name");
338                         if (value) {
339                                 pp->sg_id.proto_id = SCSI_PROTOCOL_FCP;
340                                 pp->sg_id.transport_id = tgtid;
341                                 strncpy(node, value, NODE_NAME_SIZE);
342                                 udev_device_unref(tgtdev);
343                                 return 0;
344                         } else
345                                 udev_device_unref(tgtdev);
346                 }
347         }
348
349         /* Check for iSCSI */
350         parent = pp->udev;
351         tgtname = NULL;
352         while (parent) {
353                 tgtname = udev_device_get_sysname(parent);
354                 if (tgtname && sscanf(tgtname , "session%d", &tgtid) == 1)
355                         break;
356                 parent = udev_device_get_parent(parent);
357                 tgtname = NULL;
358                 tgtid = -1;
359         }
360         if (parent && tgtname) {
361                 tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
362                                 "iscsi_session", tgtname);
363                 if (tgtdev) {
364                         const char *value;
365
366                         value = udev_device_get_sysattr_value(tgtdev, "targetname");
367                         if (value) {
368                                 pp->sg_id.proto_id = SCSI_PROTOCOL_ISCSI;
369                                 pp->sg_id.transport_id = tgtid;
370                                 strncpy(node, value, NODE_NAME_SIZE);
371                                 udev_device_unref(tgtdev);
372                                 return 0;
373                         }
374                         else
375                                 udev_device_unref(tgtdev);
376                 }
377         }
378         /* Check for libata */
379         parent = pp->udev;
380         tgtname = NULL;
381         while (parent) {
382                 tgtname = udev_device_get_sysname(parent);
383                 if (tgtname && sscanf(tgtname, "ata%d", &tgtid) == 1)
384                         break;
385                 parent = udev_device_get_parent(parent);
386                 tgtname = NULL;
387         }
388         if (tgtname) {
389                 pp->sg_id.proto_id = SCSI_PROTOCOL_ATA;
390                 pp->sg_id.transport_id = tgtid;
391                 snprintf(node, NODE_NAME_SIZE, "ata-%d.00", tgtid);
392                 return 0;
393         }
394         /* Unknown SCSI transport. Keep fingers crossed */
395         pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
396         return 0;
397 }
398
399 int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name)
400 {
401         int proto_id;
402
403         if (!pp || !adapter_name)
404                 return 1;
405
406         proto_id = pp->sg_id.proto_id;
407
408         if (proto_id != SCSI_PROTOCOL_FCP &&
409             proto_id != SCSI_PROTOCOL_SAS &&
410             proto_id != SCSI_PROTOCOL_ISCSI &&
411             proto_id != SCSI_PROTOCOL_SRP) {
412                 return 1;
413         }
414         /* iscsi doesn't have adapter info in sysfs
415          * get ip_address for grouping paths
416          */
417         if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
418                 return sysfs_get_iscsi_ip_address(pp, adapter_name);
419
420         /* fetch adapter pci name for other protocols
421          */
422         return sysfs_get_host_pci_name(pp, adapter_name);
423 }
424
425 int sysfs_get_host_pci_name(struct path *pp, char *pci_name)
426 {
427         struct udev_device *hostdev, *parent;
428         char host_name[HOST_NAME_LEN];
429         const char *driver_name, *value;
430
431         if (!pp || !pci_name)
432                 return 1;
433
434         sprintf(host_name, "host%d", pp->sg_id.host_no);
435         hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
436                         "scsi_host", host_name);
437         if (!hostdev)
438                 return 1;
439
440         parent = udev_device_get_parent(hostdev);
441         while (parent) {
442                 driver_name = udev_device_get_driver(parent);
443                 if (!driver_name) {
444                         parent = udev_device_get_parent(parent);
445                         continue;
446                 }
447                 if (!strcmp(driver_name, "pcieport"))
448                         break;
449                 parent = udev_device_get_parent(parent);
450         }
451         if (parent) {
452                 /* pci_device found
453                  */
454                 value = udev_device_get_sysname(parent);
455
456                 strncpy(pci_name, value, SLOT_NAME_SIZE);
457                 udev_device_unref(hostdev);
458                 return 0;
459         }
460         udev_device_unref(hostdev);
461         return 1;
462 }
463
464 int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address)
465 {
466         struct udev_device *hostdev;
467         char host_name[HOST_NAME_LEN];
468         const char *value;
469
470         sprintf(host_name, "host%d", pp->sg_id.host_no);
471         hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
472                         "iscsi_host", host_name);
473         if (hostdev) {
474                 value = udev_device_get_sysattr_value(hostdev,
475                                 "ipaddress");
476                 if (value) {
477                         strncpy(ip_address, value, SLOT_NAME_SIZE);
478                         udev_device_unref(hostdev);
479                         return 0;
480                 } else
481                         udev_device_unref(hostdev);
482         }
483         return 1;
484 }
485
486 static void
487 sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
488 {
489         struct udev_device *rport_dev = NULL;
490         char value[16], *eptr;
491         char rport_id[32];
492         unsigned long long tmo = 0;
493         int ret;
494
495         sprintf(rport_id, "rport-%d:%d-%d",
496                 pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
497         rport_dev = udev_device_new_from_subsystem_sysname(conf->udev,
498                                 "fc_remote_ports", rport_id);
499         if (!rport_dev) {
500                 condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
501                         rport_id);
502                 return;
503         }
504         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
505                 pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
506
507         /*
508          * read the current dev_loss_tmo value from sysfs
509          */
510         ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo", value, 16);
511         if (ret <= 0) {
512                 condlog(0, "%s: failed to read dev_loss_tmo value, "
513                         "error %d", rport_id, -ret);
514                 goto out;
515         }
516         tmo = strtoull(value, &eptr, 0);
517         if (value == eptr || tmo == ULLONG_MAX) {
518                 condlog(0, "%s: Cannot parse dev_loss_tmo "
519                         "attribute '%s'", rport_id, value);
520                 goto out;
521         }
522
523         /*
524          * This is tricky.
525          * dev_loss_tmo will be limited to 600 if fast_io_fail
526          * is _not_ set.
527          * fast_io_fail will be limited by the current dev_loss_tmo
528          * setting.
529          * So to get everything right we first need to increase
530          * dev_loss_tmo to the fast_io_fail setting (if present),
531          * then set fast_io_fail, and _then_ set dev_loss_tmo
532          * to the correct value.
533          */
534         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET &&
535             mpp->fast_io_fail != MP_FAST_IO_FAIL_ZERO &&
536             mpp->fast_io_fail != MP_FAST_IO_FAIL_OFF) {
537                 /* Check if we need to temporarily increase dev_loss_tmo */
538                 if (mpp->fast_io_fail >= tmo) {
539                         /* Increase dev_loss_tmo temporarily */
540                         snprintf(value, 16, "%u", mpp->fast_io_fail + 1);
541                         ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
542                                                    value, strlen(value));
543                         if (ret <= 0) {
544                                 if (ret == -EBUSY)
545                                         condlog(3, "%s: rport blocked",
546                                                 rport_id);
547                                 else
548                                         condlog(0, "%s: failed to set "
549                                                 "dev_loss_tmo to %s, error %d",
550                                                 rport_id, value, -ret);
551                                 goto out;
552                         }
553                 }
554         } else if (mpp->dev_loss > DEFAULT_DEV_LOSS_TMO) {
555                 condlog(3, "%s: limiting dev_loss_tmo to %d, since "
556                         "fast_io_fail is not set",
557                         rport_id, DEFAULT_DEV_LOSS_TMO);
558                 mpp->dev_loss = DEFAULT_DEV_LOSS_TMO;
559         }
560         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
561                 if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
562                         sprintf(value, "off");
563                 else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
564                         sprintf(value, "0");
565                 else
566                         snprintf(value, 16, "%u", mpp->fast_io_fail);
567                 ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
568                                            value, strlen(value));
569                 if (ret <= 0) {
570                         if (ret == -EBUSY)
571                                 condlog(3, "%s: rport blocked", rport_id);
572                         else
573                                 condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d",
574                                         rport_id, value, -ret);
575                 }
576         }
577         if (mpp->dev_loss > 0) {
578                 snprintf(value, 16, "%u", mpp->dev_loss);
579                 ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
580                                            value, strlen(value));
581                 if (ret <= 0) {
582                         if (ret == -EBUSY)
583                                 condlog(3, "%s: rport blocked", rport_id);
584                         else
585                                 condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d",
586                                         rport_id, value, -ret);
587                 }
588         }
589 out:
590         udev_device_unref(rport_dev);
591 }
592
593 static void
594 sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
595 {
596         struct udev_device *session_dev = NULL;
597         char session_id[64];
598         char value[11];
599
600         sprintf(session_id, "session%d", pp->sg_id.transport_id);
601         session_dev = udev_device_new_from_subsystem_sysname(conf->udev,
602                                 "iscsi_session", session_id);
603         if (!session_dev) {
604                 condlog(1, "%s: No iscsi session for '%s'", pp->dev,
605                         session_id);
606                 return;
607         }
608         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
609                 pp->sg_id.channel, pp->sg_id.scsi_id, session_id);
610
611         if (mpp->dev_loss) {
612                 condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev);
613         }
614         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
615                 if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) {
616                         condlog(3, "%s: can't switch off fast_io_fail_tmo "
617                                 "on iSCSI", pp->dev);
618                 } else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) {
619                         condlog(3, "%s: can't set fast_io_fail_tmo to '0'"
620                                 "on iSCSI", pp->dev);
621                 } else {
622                         snprintf(value, 11, "%u", mpp->fast_io_fail);
623                         if (sysfs_attr_set_value(session_dev, "recovery_tmo",
624                                                  value, 11) <= 0) {
625                                 condlog(3, "%s: Failed to set recovery_tmo, "
626                                         " error %d", pp->dev, errno);
627                         }
628                 }
629         }
630         udev_device_unref(session_dev);
631         return;
632 }
633
634 static void
635 sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
636 {
637         struct udev_device *sas_dev = NULL;
638         char end_dev_id[64];
639         char value[11];
640
641         sprintf(end_dev_id, "end_device-%d:%d",
642                 pp->sg_id.host_no, pp->sg_id.transport_id);
643         sas_dev = udev_device_new_from_subsystem_sysname(conf->udev,
644                                 "sas_end_device", end_dev_id);
645         if (!sas_dev) {
646                 condlog(1, "%s: No SAS end device for '%s'", pp->dev,
647                         end_dev_id);
648                 return;
649         }
650         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
651                 pp->sg_id.channel, pp->sg_id.scsi_id, end_dev_id);
652
653         if (mpp->dev_loss) {
654                 snprintf(value, 11, "%u", mpp->dev_loss);
655                 if (sysfs_attr_set_value(sas_dev, "I_T_nexus_loss_timeout",
656                                          value, 11) <= 0)
657                         condlog(3, "%s: failed to update "
658                                 "I_T Nexus loss timeout, error %d",
659                                 pp->dev, errno);
660         }
661         udev_device_unref(sas_dev);
662         return;
663 }
664
665 int
666 sysfs_set_scsi_tmo (struct multipath *mpp)
667 {
668         struct path *pp;
669         int i;
670         int dev_loss_tmo = mpp->dev_loss;
671
672         if (mpp->no_path_retry > 0) {
673                 uint64_t no_path_retry_tmo = mpp->no_path_retry * conf->checkint;
674
675                 if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
676                         no_path_retry_tmo = MAX_DEV_LOSS_TMO;
677                 if (no_path_retry_tmo > dev_loss_tmo)
678                         dev_loss_tmo = no_path_retry_tmo;
679                 condlog(3, "%s: update dev_loss_tmo to %u",
680                         mpp->alias, dev_loss_tmo);
681         } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) {
682                 dev_loss_tmo = MAX_DEV_LOSS_TMO;
683                 condlog(3, "%s: update dev_loss_tmo to %u",
684                         mpp->alias, dev_loss_tmo);
685         }
686         mpp->dev_loss = dev_loss_tmo;
687         if (mpp->dev_loss && mpp->fast_io_fail >= (int)mpp->dev_loss) {
688                 condlog(3, "%s: turning off fast_io_fail (%d is not smaller than dev_loss_tmo)",
689                         mpp->alias, mpp->fast_io_fail);
690                 mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
691         }
692         if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
693                 return 0;
694
695         vector_foreach_slot(mpp->paths, pp, i) {
696                 if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
697                         sysfs_set_rport_tmo(mpp, pp);
698                 if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
699                         sysfs_set_session_tmo(mpp, pp);
700                 if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS)
701                         sysfs_set_nexus_loss_tmo(mpp, pp);
702         }
703         return 0;
704 }
705
706 int
707 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
708        void *resp, int mx_resp_len)
709 {
710         unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
711                 { INQUIRY_CMD, 0, 0, 0, 0, 0 };
712         unsigned char sense_b[SENSE_BUFF_LEN];
713         struct sg_io_hdr io_hdr;
714
715         if (cmddt)
716                 inqCmdBlk[1] |= 2;
717         if (evpd)
718                 inqCmdBlk[1] |= 1;
719         inqCmdBlk[2] = (unsigned char) pg_op;
720         inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
721         inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
722         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
723         memset(sense_b, 0, SENSE_BUFF_LEN);
724         io_hdr.interface_id = 'S';
725         io_hdr.cmd_len = sizeof (inqCmdBlk);
726         io_hdr.mx_sb_len = sizeof (sense_b);
727         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
728         io_hdr.dxfer_len = mx_resp_len;
729         io_hdr.dxferp = resp;
730         io_hdr.cmdp = inqCmdBlk;
731         io_hdr.sbp = sense_b;
732         io_hdr.timeout = DEF_TIMEOUT;
733
734         if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
735                 return -1;
736
737         /* treat SG_ERR here to get rid of sg_err.[ch] */
738         io_hdr.status &= 0x7e;
739         if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
740             (0 == io_hdr.driver_status))
741                 return 0;
742         if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
743             (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
744             (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
745                 if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
746                         int sense_key;
747                         unsigned char * sense_buffer = io_hdr.sbp;
748                         if (sense_buffer[0] & 0x2)
749                                 sense_key = sense_buffer[1] & 0xf;
750                         else
751                                 sense_key = sense_buffer[2] & 0xf;
752                         if(RECOVERED_ERROR == sense_key)
753                                 return 0;
754                 }
755         }
756         return -1;
757 }
758
759 static int
760 get_serial (char * str, int maxlen, int fd)
761 {
762         int len = 0;
763         char buff[MX_ALLOC_LEN + 1] = {0};
764
765         if (fd < 0)
766                 return 1;
767
768         if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN)) {
769                 len = buff[3];
770                 if (len >= maxlen)
771                         return 1;
772                 if (len > 0) {
773                         memcpy(str, buff + 4, len);
774                         str[len] = '\0';
775                 }
776                 return 0;
777         }
778         return 1;
779 }
780
781 #define DEFAULT_SGIO_LEN 254
782
783 static int
784 sgio_get_vpd (unsigned char * buff, int maxlen, int fd)
785 {
786         int len = DEFAULT_SGIO_LEN;
787
788         if (fd < 0) {
789                 errno = EBADF;
790                 return -1;
791         }
792 retry:
793         if (0 == do_inq(fd, 0, 1, 0x83, buff, len)) {
794                 len = buff[3] + (buff[2] << 8);
795                 if (len >= maxlen)
796                         return len;
797                 if (len > DEFAULT_SGIO_LEN)
798                         goto retry;
799                 return 0;
800         }
801         return -1;
802 }
803
804 static int
805 get_geometry(struct path *pp)
806 {
807         if (pp->fd < 0)
808                 return 1;
809
810         if (ioctl(pp->fd, HDIO_GETGEO, &pp->geom)) {
811                 condlog(2, "%s: HDIO_GETGEO failed with %d", pp->dev, errno);
812                 memset(&pp->geom, 0, sizeof(pp->geom));
813                 return 1;
814         }
815         condlog(3, "%s: %u cyl, %u heads, %u sectors/track, start at %lu",
816                 pp->dev, pp->geom.cylinders, pp->geom.heads,
817                 pp->geom.sectors, pp->geom.start);
818         return 0;
819 }
820
821 static int
822 parse_vpd_pg80(const unsigned char *in, char *out, size_t out_len)
823 {
824         char *p = NULL;
825         int len = in[3] + (in[2] << 8);
826
827         if (len >= out_len) {
828                 condlog(2, "vpd pg80 overflow, %d/%d bytes required",
829                         len, (int)out_len);
830                 len = out_len;
831         }
832         if (len > 0) {
833                 memcpy(out, in + 4, len);
834                 out[len] = '\0';
835         }
836         /*
837          * Strip trailing whitspaces
838          */
839         p = out + len - 1;
840         while (p > out && *p == ' ') {
841                 *p = '\0';
842                 p--;
843                 len --;
844         }
845         return len;
846 }
847
848 static int
849 parse_vpd_pg83(const unsigned char *in, size_t in_len,
850                char *out, size_t out_len)
851 {
852         unsigned char *d;
853         unsigned char *vpd = NULL;
854         int len = -ENODATA, vpd_type, vpd_len, prio = -1, i, naa_prio;
855
856         d = (unsigned char *)in + 4;
857         while (d < (unsigned char *)in + in_len) {
858                 /* Select 'association: LUN' */
859                 if ((d[1] & 0x30) != 0) {
860                         d += d[3] + 4;
861                         continue;
862                 }
863                 switch (d[1] & 0xf) {
864                 case 0x3:
865                         /* NAA: Prio 5 */
866                         switch (d[4] >> 4) {
867                         case 6:
868                                 /* IEEE Registered Extended: Prio 8 */
869                                 naa_prio = 8;
870                                 break;
871                         case 5:
872                                 /* IEEE Registered: Prio 7 */
873                                 naa_prio = 7;
874                                 break;
875                         case 2:
876                                 /* IEEE Extended: Prio 6 */
877                                 naa_prio = 6;
878                                 break;
879                         case 3:
880                                 /* IEEE Locally assigned: Prio 1 */
881                                 naa_prio = 1;
882                                 break;
883                         default:
884                                 /* Default: no priority */
885                                 naa_prio = -1;
886                                 break;
887                         }
888                         if (prio < naa_prio) {
889                                 prio = naa_prio;
890                                 vpd = d;
891                         }
892                         break;
893                 case 0x8:
894                         /* SCSI Name: Prio 4 */
895                         if (memcmp(d + 4, "eui.", 4) &&
896                             memcmp(d + 4, "naa.", 4) &&
897                             memcmp(d + 4, "iqn.", 4))
898                                 continue;
899                         if (prio < 4) {
900                                 prio = 4;
901                                 vpd = d;
902                         }
903                         break;
904                 case 0x2:
905                         /* EUI-64: Prio 3 */
906                         if (prio < 3) {
907                                 prio = 3;
908                                 vpd = d;
909                         }
910                         break;
911                 case 0x1:
912                         /* T-10 Vendor ID: Prio 2 */
913                         if (prio < 2) {
914                                 prio = 2;
915                                 vpd = d;
916                         }
917                         break;
918                 }
919                 d += d[3] + 4;
920         }
921         if (prio > 0) {
922                 vpd_type = vpd[1] & 0xf;
923                 vpd_len = vpd[3];
924                 vpd += 4;
925                 if (vpd_type == 0x2 || vpd_type == 0x3) {
926                         int i;
927
928                         len = sprintf(out, "%d", vpd_type);
929                         for (i = 0; i < vpd_len; i++) {
930                                 len += sprintf(out + len,
931                                                "%02x", vpd[i]);
932                                 if (len >= out_len)
933                                         break;
934                         }
935                 } else if (vpd_type == 0x8) {
936                         if (!memcmp("eui.", vpd, 4)) {
937                                 out[0] =  '2';
938                                 len = 1;
939                                 vpd += 4;
940                                 vpd_len -= 4;
941                                 for (i = 0; i < vpd_len; i++) {
942                                         len += sprintf(out + len, "%c",
943                                                        tolower(vpd[i]));
944                                         if (len >= out_len)
945                                                 break;
946                                 }
947                                 len = vpd_len + 1;
948                                 out[len] = '\0';
949                         } else if (!memcmp("naa.", vpd, 4)) {
950                                 out[0] = '3';
951                                 len = 1;
952                                 vpd += 4;
953                                 vpd_len -= 4;
954                                 for (i = 0; i < vpd_len; i++) {
955                                         len += sprintf(out + len, "%c",
956                                                        tolower(vpd[i]));
957                                         if (len >= out_len)
958                                                 break;
959                                 }
960                                 len = vpd_len + 1;
961                                 out[len] = '\0';
962                         } else {
963                                 out[0] = '8';
964                                 len = 1;
965                                 vpd += 4;
966                                 vpd_len -= 4;
967                                 if (vpd_len > out_len + 2)
968                                         vpd_len = out_len - 2;
969                                 memcpy(out, vpd, vpd_len);
970                                 len = vpd_len + 1;
971                                 out[len] = '\0';
972                         }
973                 } else if (vpd_type == 0x1) {
974                         unsigned char *p;
975                         int p_len;
976
977                         out[0] = '1';
978                         len = 1;
979                         p = vpd;
980                         while ((p = memchr(vpd, ' ', vpd_len))) {
981                                 p_len = p - vpd;
982                                 if (len + p_len > out_len - 1)
983                                         p_len = out_len - len - 2;
984                                 memcpy(out + len, vpd, p_len);
985                                 len += p_len;
986                                 if (len >= out_len - 1) {
987                                         out[len] = '\0';
988                                         break;
989                                 }
990                                 out[len] = '_';
991                                 len ++;
992                                 vpd = p;
993                                 vpd_len -= p_len;
994                                 while (vpd && *vpd == ' ') {
995                                         vpd++;
996                                         vpd_len --;
997                                 }
998                         }
999                         if (len > 1 && out[len - 1] == '_') {
1000                                 out[len - 1] = '\0';
1001                                 len--;
1002                         }
1003                 }
1004         }
1005         return len;
1006 }
1007
1008 static int
1009 get_vpd_sysfs (struct udev_device *parent, int pg, char * str, int maxlen)
1010 {
1011         int len, buff_len;
1012         unsigned char buff[4096];
1013
1014         memset(buff, 0x0, 4096);
1015         if (!parent || sysfs_get_vpd(parent, pg, buff, 4096) <= 0) {
1016                 condlog(3, "failed to read sysfs vpd pg%02x", pg);
1017                 return -EINVAL;
1018         }
1019
1020         if (buff[1] != pg) {
1021                 condlog(3, "vpd pg%02x error, invalid vpd page %02x",
1022                         pg, buff[1]);
1023                 return -ENODATA;
1024         }
1025         buff_len = (buff[2] << 8) + buff[3] + 4;
1026         if (buff_len > 4096)
1027                 condlog(3, "vpd pg%02x page truncated", pg);
1028
1029         if (pg == 0x80)
1030                 len = parse_vpd_pg80(buff, str, maxlen);
1031         else if (pg == 0x83)
1032                 len = parse_vpd_pg83(buff, buff_len, str, maxlen);
1033         else
1034                 len = -ENOSYS;
1035
1036         return len;
1037 }
1038
1039 static int
1040 get_vpd_sgio (int fd, int pg, char * str, int maxlen)
1041 {
1042         int len, buff_len;
1043         unsigned char buff[4096];
1044
1045         memset(buff, 0x0, 4096);
1046         if (sgio_get_vpd(buff, 4096, fd) <= 0) {
1047                 condlog(3, "failed to issue vpd inquiry for pg%02x",
1048                         pg);
1049                 return -errno;
1050         }
1051
1052         if (buff[1] != pg) {
1053                 condlog(3, "vpd pg%02x error, invalid vpd page %02x",
1054                         pg, buff[1]);
1055                 return -ENODATA;
1056         }
1057         buff_len = (buff[2] << 8) + buff[3] + 4;
1058         if (buff_len > 4096)
1059                 condlog(3, "vpd pg%02x page truncated", pg);
1060
1061         if (pg == 0x80)
1062                 len = parse_vpd_pg80(buff, str, maxlen);
1063         else if (pg == 0x83)
1064                 len = parse_vpd_pg83(buff, buff_len, str, maxlen);
1065         else
1066                 len = -ENOSYS;
1067
1068         return len;
1069 }
1070
1071 static int
1072 scsi_sysfs_pathinfo (struct path * pp)
1073 {
1074         struct udev_device *parent;
1075         const char *attr_path = NULL;
1076
1077         parent = pp->udev;
1078         while (parent) {
1079                 const char *subsys = udev_device_get_subsystem(parent);
1080                 if (subsys && !strncmp(subsys, "scsi", 4)) {
1081                         attr_path = udev_device_get_sysname(parent);
1082                         if (!attr_path)
1083                                 break;
1084                         if (sscanf(attr_path, "%i:%i:%i:%i",
1085                                    &pp->sg_id.host_no,
1086                                    &pp->sg_id.channel,
1087                                    &pp->sg_id.scsi_id,
1088                                    &pp->sg_id.lun) == 4)
1089                                 break;
1090                 }
1091                 parent = udev_device_get_parent(parent);
1092         }
1093         if (!attr_path || pp->sg_id.host_no == -1)
1094                 return 1;
1095
1096         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE) <= 0)
1097                 return 1;
1098
1099         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
1100
1101         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE) <= 0)
1102                 return 1;
1103
1104         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
1105
1106         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE) < 0)
1107                 return 1;
1108
1109         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
1110
1111         /*
1112          * set the hwe configlet pointer
1113          */
1114         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
1115
1116         /*
1117          * host / bus / target / lun
1118          */
1119         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
1120                         pp->dev,
1121                         pp->sg_id.host_no,
1122                         pp->sg_id.channel,
1123                         pp->sg_id.scsi_id,
1124                         pp->sg_id.lun);
1125
1126         /*
1127          * target node name
1128          */
1129         if(sysfs_get_tgt_nodename(pp, pp->tgt_node_name))
1130                 return 1;
1131
1132         condlog(3, "%s: tgt_node_name = %s",
1133                 pp->dev, pp->tgt_node_name);
1134
1135         return 0;
1136 }
1137
1138 static int
1139 ccw_sysfs_pathinfo (struct path * pp)
1140 {
1141         struct udev_device *parent;
1142         char attr_buff[NAME_SIZE];
1143         const char *attr_path;
1144
1145         parent = pp->udev;
1146         while (parent) {
1147                 const char *subsys = udev_device_get_subsystem(parent);
1148                 if (subsys && !strncmp(subsys, "ccw", 3))
1149                         break;
1150                 parent = udev_device_get_parent(parent);
1151         }
1152         if (!parent)
1153                 return 1;
1154
1155         sprintf(pp->vendor_id, "IBM");
1156
1157         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
1158
1159         if (sysfs_get_devtype(parent, attr_buff, FILE_NAME_SIZE) <= 0)
1160                 return 1;
1161
1162         if (!strncmp(attr_buff, "3370", 4)) {
1163                 sprintf(pp->product_id,"S/390 DASD FBA");
1164         } else if (!strncmp(attr_buff, "9336", 4)) {
1165                 sprintf(pp->product_id,"S/390 DASD FBA");
1166         } else {
1167                 sprintf(pp->product_id,"S/390 DASD ECKD");
1168         }
1169
1170         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
1171
1172         /*
1173          * set the hwe configlet pointer
1174          */
1175         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
1176
1177         /*
1178          * host / bus / target / lun
1179          */
1180         attr_path = udev_device_get_sysname(parent);
1181         pp->sg_id.lun = 0;
1182         if (sscanf(attr_path, "%i.%i.%x",
1183                    &pp->sg_id.host_no,
1184                    &pp->sg_id.channel,
1185                    &pp->sg_id.scsi_id) == 3) {
1186                 condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
1187                         pp->dev,
1188                         pp->sg_id.host_no,
1189                         pp->sg_id.channel,
1190                         pp->sg_id.scsi_id,
1191                         pp->sg_id.lun);
1192         }
1193
1194         return 0;
1195 }
1196
1197 static int
1198 cciss_sysfs_pathinfo (struct path * pp)
1199 {
1200         const char * attr_path = NULL;
1201         struct udev_device *parent;
1202
1203         parent = pp->udev;
1204         while (parent) {
1205                 const char *subsys = udev_device_get_subsystem(parent);
1206                 if (subsys && !strncmp(subsys, "cciss", 5)) {
1207                         attr_path = udev_device_get_sysname(parent);
1208                         if (!attr_path)
1209                                 break;
1210                         if (sscanf(attr_path, "c%id%i",
1211                                    &pp->sg_id.host_no,
1212                                    &pp->sg_id.scsi_id) == 2)
1213                                 break;
1214                 }
1215                 parent = udev_device_get_parent(parent);
1216         }
1217         if (!attr_path || pp->sg_id.host_no == -1)
1218                 return 1;
1219
1220         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE) <= 0)
1221                 return 1;
1222
1223         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
1224
1225         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE) <= 0)
1226                 return 1;
1227
1228         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
1229
1230         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE) <= 0)
1231                 return 1;
1232
1233         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
1234
1235         /*
1236          * set the hwe configlet pointer
1237          */
1238         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
1239
1240         /*
1241          * host / bus / target / lun
1242          */
1243         pp->sg_id.lun = 0;
1244         pp->sg_id.channel = 0;
1245         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
1246                 pp->dev,
1247                 pp->sg_id.host_no,
1248                 pp->sg_id.channel,
1249                 pp->sg_id.scsi_id,
1250                 pp->sg_id.lun);
1251         return 0;
1252 }
1253
1254 static int
1255 common_sysfs_pathinfo (struct path * pp)
1256 {
1257         dev_t devt;
1258
1259         if (!pp)
1260                 return 1;
1261
1262         if (!pp->udev) {
1263                 condlog(4, "%s: udev not initialised", pp->dev);
1264                 return 1;
1265         }
1266         devt = udev_device_get_devnum(pp->udev);
1267         snprintf(pp->dev_t, BLK_DEV_SIZE, "%d:%d", major(devt), minor(devt));
1268
1269         condlog(3, "%s: dev_t = %s", pp->dev, pp->dev_t);
1270
1271         if (sysfs_get_size(pp, &pp->size))
1272                 return 1;
1273
1274         condlog(3, "%s: size = %llu", pp->dev, pp->size);
1275
1276         return 0;
1277 }
1278
1279 int
1280 path_offline (struct path * pp)
1281 {
1282         struct udev_device * parent;
1283         char buff[SCSI_STATE_SIZE];
1284         int err;
1285
1286         if (pp->bus != SYSFS_BUS_SCSI)
1287                 return PATH_UP;
1288
1289         parent = pp->udev;
1290         while (parent) {
1291                 const char *subsys = udev_device_get_subsystem(parent);
1292                 if (subsys && !strncmp(subsys, "scsi", 4))
1293                         break;
1294                 parent = udev_device_get_parent(parent);
1295         }
1296
1297         if (!parent) {
1298                 condlog(1, "%s: failed to get sysfs information", pp->dev);
1299                 return PATH_REMOVED;
1300         }
1301
1302         memset(buff, 0x0, SCSI_STATE_SIZE);
1303         err = sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE);
1304         if (err <= 0) {
1305                 if (err == -ENXIO)
1306                         return PATH_REMOVED;
1307                 else
1308                         return PATH_DOWN;
1309         }
1310
1311
1312         condlog(3, "%s: path state = %s", pp->dev, buff);
1313
1314         if (!strncmp(buff, "offline", 7)) {
1315                 pp->offline = 1;
1316                 return PATH_DOWN;
1317         }
1318         pp->offline = 0;
1319         if (!strncmp(buff, "blocked", 7) || !strncmp(buff, "quiesce", 7))
1320                 return PATH_PENDING;
1321         else if (!strncmp(buff, "running", 7))
1322                 return PATH_UP;
1323
1324         return PATH_DOWN;
1325 }
1326
1327 int
1328 sysfs_pathinfo(struct path * pp)
1329 {
1330         if (common_sysfs_pathinfo(pp))
1331                 return 1;
1332
1333         pp->bus = SYSFS_BUS_UNDEF;
1334         if (!strncmp(pp->dev,"cciss",5))
1335                 pp->bus = SYSFS_BUS_CCISS;
1336         if (!strncmp(pp->dev,"dasd", 4))
1337                 pp->bus = SYSFS_BUS_CCW;
1338         if (!strncmp(pp->dev,"sd", 2))
1339                 pp->bus = SYSFS_BUS_SCSI;
1340
1341         if (pp->bus == SYSFS_BUS_UNDEF)
1342                 return 0;
1343         else if (pp->bus == SYSFS_BUS_SCSI) {
1344                 if (scsi_sysfs_pathinfo(pp))
1345                         return 1;
1346         } else if (pp->bus == SYSFS_BUS_CCW) {
1347                 if (ccw_sysfs_pathinfo(pp))
1348                         return 1;
1349         } else if (pp->bus == SYSFS_BUS_CCISS) {
1350                 if (cciss_sysfs_pathinfo(pp))
1351                         return 1;
1352         }
1353         return 0;
1354 }
1355
1356 static int
1357 scsi_ioctl_pathinfo (struct path * pp, int mask)
1358 {
1359         struct udev_device *parent;
1360         const char *attr_path = NULL;
1361
1362         if (!(mask & DI_SERIAL))
1363                 return 0;
1364
1365         parent = pp->udev;
1366         while (parent) {
1367                 const char *subsys = udev_device_get_subsystem(parent);
1368                 if (subsys && !strncmp(subsys, "scsi", 4)) {
1369                         attr_path = udev_device_get_sysname(parent);
1370                         if (!attr_path)
1371                                 break;
1372                         if (sscanf(attr_path, "%i:%i:%i:%i",
1373                                    &pp->sg_id.host_no,
1374                                    &pp->sg_id.channel,
1375                                    &pp->sg_id.scsi_id,
1376                                    &pp->sg_id.lun) == 4)
1377                                 break;
1378                 }
1379                 parent = udev_device_get_parent(parent);
1380         }
1381         if (!attr_path || pp->sg_id.host_no == -1)
1382                 return 0;
1383
1384         if (get_vpd_sysfs(parent, 0x80, pp->serial, SERIAL_SIZE) > 0)
1385                 condlog(3, "%s: serial = %s",
1386                         pp->dev, pp->serial);
1387
1388         return 0;
1389 }
1390
1391 static int
1392 cciss_ioctl_pathinfo (struct path * pp, int mask)
1393 {
1394         if (mask & DI_SERIAL) {
1395                 get_serial(pp->serial, SERIAL_SIZE, pp->fd);
1396                 condlog(3, "%s: serial = %s", pp->dev, pp->serial);
1397         }
1398         return 0;
1399 }
1400
1401 int
1402 get_state (struct path * pp, int daemon)
1403 {
1404         struct checker * c = &pp->checker;
1405         int state;
1406
1407         condlog(3, "%s: get_state", pp->dev);
1408
1409         if (!checker_selected(c)) {
1410                 if (daemon) {
1411                         if (pathinfo(pp, conf->hwtable, DI_SYSFS) != PATHINFO_OK) {
1412                                 condlog(3, "%s: couldn't get sysfs pathinfo",
1413                                         pp->dev);
1414                                 return PATH_UNCHECKED;
1415                         }
1416                 }
1417                 select_checker(pp);
1418                 if (!checker_selected(c)) {
1419                         condlog(3, "%s: No checker selected", pp->dev);
1420                         return PATH_UNCHECKED;
1421                 }
1422                 checker_set_fd(c, pp->fd);
1423                 if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) {
1424                         memset(c, 0x0, sizeof(struct checker));
1425                         condlog(3, "%s: checker init failed", pp->dev);
1426                         return PATH_UNCHECKED;
1427                 }
1428         }
1429         checker_clear_message(c);
1430         if (daemon) {
1431                 if (conf->force_sync == 0)
1432                         checker_set_async(c);
1433                 else
1434                         checker_set_sync(c);
1435         }
1436         if (!conf->checker_timeout &&
1437             sysfs_get_timeout(pp, &(c->timeout)) <= 0)
1438                 c->timeout = DEF_TIMEOUT;
1439         state = checker_check(c);
1440         condlog(3, "%s: state = %s", pp->dev, checker_state_name(state));
1441         if (state != PATH_UP && state != PATH_GHOST &&
1442             strlen(checker_message(c)))
1443                 condlog(3, "%s: checker msg is \"%s\"",
1444                         pp->dev, checker_message(c));
1445         return state;
1446 }
1447
1448 static int
1449 get_prio (struct path * pp)
1450 {
1451         if (!pp)
1452                 return 0;
1453
1454         struct prio * p = &pp->prio;
1455
1456         if (!prio_selected(p)) {
1457                 select_detect_prio(pp);
1458                 select_prio(pp);
1459                 if (!prio_selected(p)) {
1460                         condlog(3, "%s: no prio selected", pp->dev);
1461                         pp->priority = PRIO_UNDEF;
1462                         return 1;
1463                 }
1464         }
1465         pp->priority = prio_getprio(p, pp);
1466         if (pp->priority < 0) {
1467                 condlog(3, "%s: %s prio error", pp->dev, prio_name(p));
1468                 pp->priority = PRIO_UNDEF;
1469                 return 1;
1470         }
1471         condlog(3, "%s: %s prio = %u",
1472                 pp->dev, prio_name(p), pp->priority);
1473         return 0;
1474 }
1475
1476 static int
1477 get_udev_uid(struct path * pp, char *uid_attribute)
1478 {
1479         ssize_t len;
1480         const char *value;
1481
1482         value = udev_device_get_property_value(pp->udev,
1483                                                uid_attribute);
1484         if ((!value || strlen(value) == 0) && conf->cmd == CMD_VALID_PATH)
1485                 value = getenv(uid_attribute);
1486         if (value && strlen(value)) {
1487                 if (strlen(value) + 1 > WWID_SIZE) {
1488                         condlog(0, "%s: wwid overflow", pp->dev);
1489                         len = WWID_SIZE;
1490                 } else {
1491                         len = strlen(value);
1492                 }
1493                 strncpy(pp->wwid, value, len);
1494         } else {
1495                 condlog(3, "%s: no %s attribute", pp->dev,
1496                         uid_attribute);
1497                 len = -EINVAL;
1498         }
1499         return len;
1500 }
1501
1502 static int
1503 get_vpd_uid(struct path * pp)
1504 {
1505         struct udev_device *parent = pp->udev;
1506
1507         while (parent) {
1508                 const char *subsys = udev_device_get_subsystem(parent);
1509                 if (subsys && !strncmp(subsys, "scsi", 4))
1510                         break;
1511                 parent = udev_device_get_parent(parent);
1512         }
1513
1514         return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE);
1515 }
1516
1517 static int
1518 get_uid (struct path * pp, int path_state)
1519 {
1520         char *c;
1521         const char *origin = "unknown";
1522         ssize_t len = 0;
1523
1524         if (!pp->uid_attribute && !pp->getuid)
1525                 select_getuid(pp);
1526
1527         if (!pp->udev) {
1528                 condlog(1, "%s: no udev information", pp->dev);
1529                 return 1;
1530         }
1531
1532         memset(pp->wwid, 0, WWID_SIZE);
1533         if (pp->getuid) {
1534                 char buff[CALLOUT_MAX_SIZE];
1535
1536                 /* Use 'getuid' callout, deprecated */
1537                 condlog(1, "%s: using deprecated getuid callout", pp->dev);
1538                 if (path_state != PATH_UP) {
1539                         condlog(3, "%s: path inaccessible", pp->dev);
1540                         len = -EWOULDBLOCK;
1541                 } else if (apply_format(pp->getuid, &buff[0], pp)) {
1542                         condlog(0, "error formatting uid callout command");
1543                         len = -EINVAL;
1544                 } else if (execute_program(buff, pp->wwid, WWID_SIZE)) {
1545                         condlog(3, "error calling out %s", buff);
1546                         len = -EIO;
1547                 } else
1548                         len = strlen(pp->wwid);
1549                 origin = "callout";
1550         } else {
1551                 if (pp->uid_attribute) {
1552                         len = get_udev_uid(pp, pp->uid_attribute);
1553                         origin = "udev";
1554                         if (len <= 0)
1555                                 condlog(1,
1556                                         "%s: failed to get udev uid: %s",
1557                                         pp->dev, strerror(-len));
1558
1559                 }
1560                 if (len <= 0 && pp->retriggers >= conf->retrigger_tries &&
1561                     !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
1562                         len = get_vpd_uid(pp);
1563                         origin = "sysfs";
1564                         pp->uid_attribute = NULL;
1565                         if (len < 0 && path_state == PATH_UP) {
1566                                 condlog(1, "%s: failed to get sysfs uid: %s",
1567                                         pp->dev, strerror(-len));
1568                                 len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
1569                                                    WWID_SIZE);
1570                                 origin = "sgio";
1571                         }
1572                 }
1573         }
1574         if ( len < 0 ) {
1575                 condlog(1, "%s: failed to get %s uid: %s",
1576                         pp->dev, origin, strerror(-len));
1577                 memset(pp->wwid, 0x0, WWID_SIZE);
1578         } else {
1579                 /* Strip any trailing blanks */
1580                 c = strchr(pp->wwid, '\0');
1581                 c--;
1582                 while (c && c >= pp->wwid && *c == ' ') {
1583                         *c = '\0';
1584                         c--;
1585                 }
1586         }
1587         condlog(3, "%s: uid = %s (%s)", pp->dev,
1588                 *pp->wwid == '\0' ? "<empty>" : pp->wwid, origin);
1589         return 0;
1590 }
1591
1592 extern int
1593 pathinfo (struct path *pp, vector hwtable, int mask)
1594 {
1595         int path_state;
1596
1597         if (!pp)
1598                 return PATHINFO_FAILED;
1599
1600         condlog(3, "%s: mask = 0x%x", pp->dev, mask);
1601
1602         /*
1603          * Sanity check: we need the device number to
1604          * avoid inconsistent information in
1605          * find_path_by_dev()/find_path_by_devt()
1606          */
1607         if (!strlen(pp->dev_t) && !(mask & DI_SYSFS)) {
1608                 condlog(1, "%s: empty device number", pp->dev);
1609                 mask |= DI_SYSFS;
1610         }
1611
1612         /*
1613          * fetch info available in sysfs
1614          */
1615         if (mask & DI_SYSFS && sysfs_pathinfo(pp))
1616                 return PATHINFO_FAILED;
1617
1618         if (mask & DI_BLACKLIST && mask & DI_SYSFS) {
1619                 if (filter_device(conf->blist_device, conf->elist_device,
1620                                   pp->vendor_id, pp->product_id) > 0) {
1621                         return PATHINFO_SKIPPED;
1622                 }
1623         }
1624
1625         path_state = path_offline(pp);
1626         if (path_state == PATH_REMOVED)
1627                 goto blank;
1628
1629         /*
1630          * fetch info not available through sysfs
1631          */
1632         if (pp->fd < 0)
1633                 pp->fd = open(udev_device_get_devnode(pp->udev), O_RDONLY);
1634
1635         if (pp->fd < 0) {
1636                 condlog(4, "Couldn't open node for %s: %s",
1637                         pp->dev, strerror(errno));
1638                 goto blank;
1639         }
1640
1641         if (mask & DI_SERIAL)
1642                 get_geometry(pp);
1643
1644         if (path_state == PATH_UP && pp->bus == SYSFS_BUS_SCSI &&
1645             scsi_ioctl_pathinfo(pp, mask))
1646                 goto blank;
1647
1648         if (pp->bus == SYSFS_BUS_CCISS &&
1649             cciss_ioctl_pathinfo(pp, mask))
1650                 goto blank;
1651
1652         if (mask & DI_CHECKER) {
1653                 if (path_state == PATH_UP) {
1654                         pp->chkrstate = pp->state = get_state(pp, 0);
1655                         if (pp->state == PATH_UNCHECKED ||
1656                             pp->state == PATH_WILD)
1657                                 goto blank;
1658                         if (pp->state == PATH_TIMEOUT)
1659                                 pp->state = PATH_DOWN;
1660                         if (pp->state == PATH_UP && !pp->size) {
1661                                 condlog(3, "%s: device size is 0, "
1662                                         "path unuseable", pp->dev);
1663                                 pp->state = PATH_GHOST;
1664                         }
1665                 } else {
1666                         condlog(3, "%s: path inaccessible", pp->dev);
1667                         pp->chkrstate = pp->state = path_state;
1668                         if (path_state == PATH_PENDING ||
1669                             path_state == PATH_DOWN)
1670                                 pp->priority = 0;
1671                 }
1672         }
1673
1674         if ((mask & DI_WWID) && !strlen(pp->wwid)) {
1675                 get_uid(pp, path_state);
1676                 if (!strlen(pp->wwid)) {
1677                         pp->initialized = INIT_MISSING_UDEV;
1678                         pp->tick = conf->retrigger_delay;
1679                         return PATHINFO_OK;
1680                 }
1681                 else
1682                         pp->tick = 1;
1683         }
1684
1685         if (mask & DI_BLACKLIST && mask & DI_WWID) {
1686                 if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
1687                                 pp->wwid, pp->dev) > 0) {
1688                         return PATHINFO_SKIPPED;
1689                 }
1690         }
1691
1692          /*
1693           * Retrieve path priority, even for PATH_DOWN paths if it has never
1694           * been successfully obtained before.
1695           */
1696         if ((mask & DI_PRIO) && path_state == PATH_UP && strlen(pp->wwid)) {
1697                 if (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF) {
1698                         get_prio(pp);
1699                 }
1700         }
1701
1702         pp->initialized = INIT_OK;
1703         return PATHINFO_OK;
1704
1705 blank:
1706         /*
1707          * Recoverable error, for example faulty or offline path
1708          */
1709         memset(pp->wwid, 0, WWID_SIZE);
1710         pp->chkrstate = pp->state = PATH_DOWN;
1711         pp->initialized = INIT_FAILED;
1712
1713         return PATHINFO_OK;
1714 }