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