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