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