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