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