3292358a6587c58a45dca7dca7c6b83dc8968e2b
[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 <unistd.h>
8 #include <fcntl.h>
9 #include <sys/ioctl.h>
10 #include <sys/stat.h>
11 #include <dirent.h>
12 #include <errno.h>
13 #include <libgen.h>
14 #include <libudev.h>
15
16 #include "checkers.h"
17 #include "vector.h"
18 #include "memory.h"
19 #include "util.h"
20 #include "structs.h"
21 #include "config.h"
22 #include "blacklist.h"
23 #include "callout.h"
24 #include "debug.h"
25 #include "propsel.h"
26 #include "sg_include.h"
27 #include "sysfs.h"
28 #include "discovery.h"
29 #include "prio.h"
30 #include "defaults.h"
31
32 int
33 store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice,
34                 int flag, struct path **pp_ptr)
35 {
36         int err = 1;
37         struct path * pp;
38         const char * devname;
39
40         if (pp_ptr)
41                 *pp_ptr = NULL;
42
43         devname = udev_device_get_sysname(udevice);
44         if (!devname)
45                 return 1;
46
47         pp = alloc_path();
48
49         if (!pp)
50                 return 1;
51
52         if(safe_sprintf(pp->dev, "%s", devname)) {
53                 condlog(0, "pp->dev too small");
54                 goto out;
55         }
56         pp->udev = udev_device_ref(udevice);
57         err = pathinfo(pp, hwtable,
58                        (conf->dry_run == 3)? flag : (flag | DI_BLACKLIST));
59         if (err)
60                 goto out;
61
62         err = store_path(pathvec, pp);
63         if (err)
64                 goto out;
65
66 out:
67         if (err)
68                 free_path(pp);
69         else if (pp_ptr)
70                 *pp_ptr = pp;
71         return err;
72 }
73
74 static int
75 path_discover (vector pathvec, struct config * conf,
76                struct udev_device *udevice, int flag)
77 {
78         struct path * pp;
79         const char * devname;
80
81         devname = udev_device_get_sysname(udevice);
82         if (!devname)
83                 return 0;
84
85         if (filter_property(conf, udevice) > 0)
86                 return 0;
87
88         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
89                            (char *)devname) > 0)
90                 return 0;
91
92         pp = find_path_by_dev(pathvec, (char *)devname);
93         if (!pp) {
94                 if (store_pathinfo(pathvec, conf->hwtable,
95                                    udevice, flag, NULL) != 1)
96                         return 0;
97                 else
98                         return 1;
99         }
100         return pathinfo(pp, conf->hwtable, flag);
101 }
102
103 int
104 path_discovery (vector pathvec, struct config * conf, int flag)
105 {
106         struct udev_enumerate *udev_iter;
107         struct udev_list_entry *entry;
108         struct udev_device *udevice;
109         const char *devpath;
110         int r = 0;
111
112         udev_iter = udev_enumerate_new(conf->udev);
113         if (!udev_iter)
114                 return 1;
115
116         udev_enumerate_add_match_subsystem(udev_iter, "block");
117         udev_enumerate_scan_devices(udev_iter);
118
119         udev_list_entry_foreach(entry,
120                                 udev_enumerate_get_list_entry(udev_iter)) {
121                 const char *devtype;
122                 devpath = udev_list_entry_get_name(entry);
123                 condlog(4, "Discover device %s", devpath);
124                 udevice = udev_device_new_from_syspath(conf->udev, devpath);
125                 if (!udevice) {
126                         condlog(4, "%s: no udev information", devpath);
127                         r++;
128                         continue;
129                 }
130                 devtype = udev_device_get_devtype(udevice);
131                 if(devtype && !strncmp(devtype, "disk", 4)) {
132                         r += path_discover(pathvec, conf,
133                                                    udevice, flag);
134                 }
135                 udev_device_unref(udevice);
136         }
137         udev_enumerate_unref(udev_iter);
138         condlog(4, "Discovery status %d", r);
139         return r;
140 }
141
142 #define declare_sysfs_get_str(fname)                                    \
143 extern int                                                              \
144 sysfs_get_##fname (struct udev_device * udev, char * buff, size_t len)  \
145 {                                                                       \
146         const char * attr;                                              \
147         const char * devname;                                           \
148                                                                         \
149         devname = udev_device_get_sysname(udev);                        \
150                                                                         \
151         attr = udev_device_get_sysattr_value(udev, #fname);             \
152         if (!attr) {                                                    \
153                 condlog(3, "%s: attribute %s not found in sysfs",       \
154                         devname, #fname);                               \
155                 return 1;                                               \
156         }                                                               \
157         if (strlen(attr) > len) {                                       \
158                 condlog(3, "%s: overflow in attribute %s",              \
159                         devname, #fname);                               \
160                 return 2;                                               \
161         }                                                               \
162         strlcpy(buff, attr, len);                                       \
163         return 0;                                                       \
164 }
165
166 declare_sysfs_get_str(devtype);
167 declare_sysfs_get_str(cutype);
168 declare_sysfs_get_str(vendor);
169 declare_sysfs_get_str(model);
170 declare_sysfs_get_str(rev);
171 declare_sysfs_get_str(dev);
172
173 int
174 sysfs_get_timeout(struct path *pp, unsigned int *timeout)
175 {
176         const char *attr = NULL;
177         const char *subsys;
178         struct udev_device *parent;
179         int r;
180         unsigned int t;
181
182         if (!pp->udev || pp->bus != SYSFS_BUS_SCSI)
183                 return 1;
184
185         parent = pp->udev;
186         while (parent) {
187                 subsys = udev_device_get_subsystem(parent);
188                 attr = udev_device_get_sysattr_value(parent, "timeout");
189                 if (subsys && attr)
190                         break;
191                 parent = udev_device_get_parent(parent);
192         }
193         if (!attr) {
194                 condlog(3, "%s: No timeout value in sysfs", pp->dev);
195                 return 1;
196         }
197
198         r = sscanf(attr, "%u\n", &t);
199
200         if (r != 1) {
201                 condlog(3, "%s: Cannot parse timeout attribute '%s'",
202                         pp->dev, attr);
203                 return 1;
204         }
205
206         *timeout = t;
207
208         return 0;
209 }
210
211 int
212 sysfs_get_tgt_nodename (struct path *pp, char * node)
213 {
214         const char *tgtname, *value;
215         struct udev_device *parent, *tgtdev;
216         int host, channel, tgtid = -1;
217
218         parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_device");
219         if (!parent)
220                 return 1;
221         /* Check for SAS */
222         value = udev_device_get_sysattr_value(parent, "sas_address");
223         if (value) {
224                 tgtdev = udev_device_get_parent(parent);
225                 while (tgtdev) {
226                         tgtname = udev_device_get_sysname(tgtdev);
227                         if (sscanf(tgtname, "end_device-%d:%d",
228                                    &host, &tgtid) == 2)
229                                 break;
230                         tgtdev = udev_device_get_parent(tgtdev);
231                         tgtid = -1;
232                 }
233                 if (tgtid >= 0) {
234                         pp->sg_id.proto_id = SCSI_PROTOCOL_SAS;
235                         pp->sg_id.transport_id = tgtid;
236                         strncpy(node, value, NODE_NAME_SIZE);
237                         return 0;
238                 }
239         }
240
241         parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_target");
242         if (!parent)
243                 return 1;
244         /* Check for FibreChannel */
245         tgtdev = udev_device_get_parent(parent);
246         value = udev_device_get_sysname(tgtdev);
247         if (sscanf(value, "rport-%d:%d-%d",
248                    &host, &channel, &tgtid) == 3) {
249                 tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
250                                 "fc_remote_ports", value);
251                 if (tgtdev) {
252                         condlog(3, "SCSI target %d:%d:%d -> "
253                                 "FC rport %d:%d-%d",
254                                 pp->sg_id.host_no, pp->sg_id.channel,
255                                 pp->sg_id.scsi_id, host, channel,
256                                 tgtid);
257                         value = udev_device_get_sysattr_value(tgtdev,
258                                                               "node_name");
259                         if (value) {
260                                 pp->sg_id.proto_id = SCSI_PROTOCOL_FCP;
261                                 pp->sg_id.transport_id = tgtid;
262                                 strncpy(node, value, NODE_NAME_SIZE);
263                                 udev_device_unref(tgtdev);
264                                 return 0;
265                         } else
266                                 udev_device_unref(tgtdev);
267                 }
268         }
269
270         /* Check for iSCSI */
271         parent = pp->udev;
272         tgtname = NULL;
273         while (parent) {
274                 tgtname = udev_device_get_sysname(parent);
275                 if (tgtname && sscanf(tgtname , "session%d", &tgtid) == 1)
276                         break;
277                 parent = udev_device_get_parent(parent);
278                 tgtname = NULL;
279                 tgtid = -1;
280         }
281         if (parent && tgtname) {
282                 tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
283                                 "iscsi_session", tgtname);
284                 if (tgtdev) {
285                         const char *value;
286
287                         value = udev_device_get_sysattr_value(tgtdev, "tgtname");
288                         if (value) {
289                                 pp->sg_id.proto_id = SCSI_PROTOCOL_ISCSI;
290                                 pp->sg_id.transport_id = tgtid;
291                                 strncpy(node, value, NODE_NAME_SIZE);
292                                 udev_device_unref(tgtdev);
293                                 return 0;
294                         }
295                         else
296                                 udev_device_unref(tgtdev);
297                 }
298         }
299         /* Check for libata */
300         parent = pp->udev;
301         tgtname = NULL;
302         while (parent) {
303                 tgtname = udev_device_get_sysname(parent);
304                 if (tgtname && sscanf(tgtname, "ata%d", &tgtid) == 1)
305                         break;
306                 parent = udev_device_get_parent(parent);
307                 tgtname = NULL;
308         }
309         if (tgtname) {
310                 pp->sg_id.proto_id = SCSI_PROTOCOL_ATA;
311                 pp->sg_id.transport_id = tgtid;
312                 snprintf(node, NODE_NAME_SIZE, "ata-%d.00", tgtid);
313                 return 0;
314         }
315         pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
316         return 1;
317 }
318
319 static void
320 sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
321 {
322         struct udev_device *rport_dev = NULL;
323         char value[16];
324         char rport_id[32];
325         unsigned long long tmo = 0;
326         int ret;
327
328         sprintf(rport_id, "rport-%d:%d-%d",
329                 pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
330         rport_dev = udev_device_new_from_subsystem_sysname(conf->udev,
331                                 "fc_remote_ports", rport_id);
332         if (!rport_dev) {
333                 condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
334                         rport_id);
335                 return;
336         }
337         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
338                 pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
339
340         /*
341          * This is tricky.
342          * dev_loss_tmo will be limited to 600 if fast_io_fail
343          * is _not_ set.
344          * fast_io_fail will be limited by the current dev_loss_tmo
345          * setting.
346          * So to get everything right we first need to increase
347          * dev_loss_tmo to the fast_io_fail setting (if present),
348          * then set fast_io_fail, and _then_ set dev_loss_tmo
349          * to the correct value.
350          */
351         memset(value, 0, 16);
352         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET &&
353             mpp->fast_io_fail != MP_FAST_IO_FAIL_ZERO &&
354             mpp->fast_io_fail != MP_FAST_IO_FAIL_OFF) {
355                 /* Check if we need to temporarily increase dev_loss_tmo */
356                 ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo",
357                                            value, 16);
358                 if (ret <= 0) {
359                         condlog(0, "%s: failed to read dev_loss_tmo value, "
360                                 "error %d", rport_id, -ret);
361                         goto out;
362                 }
363                 if (sscanf(value, "%llu\n", &tmo) != 1) {
364                         condlog(0, "%s: Cannot parse dev_loss_tmo "
365                                 "attribute '%s'", rport_id, value);
366                         goto out;
367                 }
368                 if (mpp->fast_io_fail >= tmo) {
369                         snprintf(value, 16, "%u", mpp->fast_io_fail + 1);
370                 }
371         } else if (mpp->dev_loss > 600) {
372                 condlog(3, "%s: limiting dev_loss_tmo to 600, since "
373                         "fast_io_fail is not set", rport_id);
374                 snprintf(value, 16, "%u", 600);
375         } else {
376                 snprintf(value, 16, "%u", mpp->dev_loss);
377         }
378         if (strlen(value)) {
379                 ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
380                                            value, strlen(value));
381                 if (ret <= 0) {
382                         if (ret == -EBUSY)
383                                 condlog(3, "%s: rport blocked", rport_id);
384                         else
385                                 condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d",
386                                         rport_id, value, -ret);
387                         goto out;
388                 }
389         }
390         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
391                 if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
392                         sprintf(value, "off");
393                 else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
394                         sprintf(value, "0");
395                 else
396                         snprintf(value, 16, "%u", mpp->fast_io_fail);
397                 ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
398                                            value, strlen(value));
399                 if (ret <= 0) {
400                         if (ret == -EBUSY)
401                                 condlog(3, "%s: rport blocked", rport_id);
402                         else
403                                 condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d",
404                                         rport_id, value, -ret);
405                 }
406         }
407         if (tmo > 0) {
408                 snprintf(value, 16, "%u", mpp->dev_loss);
409                 ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
410                                            value, strlen(value));
411                 if (ret <= 0) {
412                         if (ret == -EBUSY)
413                                 condlog(3, "%s: rport blocked", rport_id);
414                         else
415                                 condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d",
416                                         rport_id, value, -ret);
417                 }
418         }
419 out:
420         udev_device_unref(rport_dev);
421 }
422
423 static void
424 sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
425 {
426         struct udev_device *session_dev = NULL;
427         char session_id[64];
428         char value[11];
429
430         sprintf(session_id, "session%d", pp->sg_id.transport_id);
431         session_dev = udev_device_new_from_subsystem_sysname(conf->udev,
432                                 "iscsi_session", session_id);
433         if (!session_dev) {
434                 condlog(1, "%s: No iscsi session for '%s'", pp->dev,
435                         session_id);
436                 return;
437         }
438         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
439                 pp->sg_id.channel, pp->sg_id.scsi_id, session_id);
440
441         if (mpp->dev_loss) {
442                 condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev);
443         }
444         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
445                 if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) {
446                         condlog(3, "%s: can't switch off fast_io_fail_tmo "
447                                 "on iSCSI", pp->dev);
448                 } else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) {
449                         condlog(3, "%s: can't set fast_io_fail_tmo to '0'"
450                                 "on iSCSI", pp->dev);
451                 } else {
452                         snprintf(value, 11, "%u", mpp->fast_io_fail);
453                         if (sysfs_attr_set_value(session_dev, "recovery_tmo",
454                                                  value, 11) <= 0) {
455                                 condlog(3, "%s: Failed to set recovery_tmo, "
456                                         " error %d", pp->dev, errno);
457                         }
458                 }
459         }
460         udev_device_unref(session_dev);
461         return;
462 }
463
464 static void
465 sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
466 {
467         struct udev_device *sas_dev = NULL;
468         char end_dev_id[64];
469         char value[11];
470
471         sprintf(end_dev_id, "end_device-%d:%d",
472                 pp->sg_id.host_no, pp->sg_id.transport_id);
473         sas_dev = udev_device_new_from_subsystem_sysname(conf->udev,
474                                 "sas_end_device", end_dev_id);
475         if (!sas_dev) {
476                 condlog(1, "%s: No SAS end device for '%s'", pp->dev,
477                         end_dev_id);
478                 return;
479         }
480         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
481                 pp->sg_id.channel, pp->sg_id.scsi_id, end_dev_id);
482
483         if (mpp->dev_loss) {
484                 snprintf(value, 11, "%u", mpp->dev_loss);
485                 if (sysfs_attr_set_value(sas_dev, "I_T_nexus_loss_timeout",
486                                          value, 11) <= 0)
487                         condlog(3, "%s: failed to update "
488                                 "I_T Nexus loss timeout, error %d",
489                                 pp->dev, errno);
490         }
491         udev_device_unref(sas_dev);
492         return;
493 }
494
495 int
496 sysfs_set_scsi_tmo (struct multipath *mpp)
497 {
498         struct path *pp;
499         int i;
500         int dev_loss_tmo = mpp->dev_loss;
501
502         if (mpp->no_path_retry > 0) {
503                 int no_path_retry_tmo = mpp->no_path_retry * conf->checkint;
504
505                 if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
506                         no_path_retry_tmo = MAX_DEV_LOSS_TMO;
507                 if (no_path_retry_tmo > dev_loss_tmo)
508                         dev_loss_tmo = no_path_retry_tmo;
509                 condlog(3, "%s: update dev_loss_tmo to %d",
510                         mpp->alias, dev_loss_tmo);
511         } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) {
512                 dev_loss_tmo = MAX_DEV_LOSS_TMO;
513                 condlog(3, "%s: update dev_loss_tmo to %d",
514                         mpp->alias, dev_loss_tmo);
515         }
516         mpp->dev_loss = dev_loss_tmo;
517         if (mpp->dev_loss && mpp->fast_io_fail >= (int)mpp->dev_loss) {
518                 condlog(3, "%s: turning off fast_io_fail (%d is not smaller than dev_loss_tmo)",
519                         mpp->alias, mpp->fast_io_fail);
520                 mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
521         }
522         if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
523                 return 0;
524
525         vector_foreach_slot(mpp->paths, pp, i) {
526                 if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
527                         sysfs_set_rport_tmo(mpp, pp);
528                 if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
529                         sysfs_set_session_tmo(mpp, pp);
530                 if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS)
531                         sysfs_set_nexus_loss_tmo(mpp, pp);
532         }
533         return 0;
534 }
535
536 int
537 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
538        void *resp, int mx_resp_len)
539 {
540         unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
541                 { INQUIRY_CMD, 0, 0, 0, 0, 0 };
542         unsigned char sense_b[SENSE_BUFF_LEN];
543         struct sg_io_hdr io_hdr;
544
545         if (cmddt)
546                 inqCmdBlk[1] |= 2;
547         if (evpd)
548                 inqCmdBlk[1] |= 1;
549         inqCmdBlk[2] = (unsigned char) pg_op;
550         inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
551         inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
552         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
553         memset(sense_b, 0, SENSE_BUFF_LEN);
554         io_hdr.interface_id = 'S';
555         io_hdr.cmd_len = sizeof (inqCmdBlk);
556         io_hdr.mx_sb_len = sizeof (sense_b);
557         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
558         io_hdr.dxfer_len = mx_resp_len;
559         io_hdr.dxferp = resp;
560         io_hdr.cmdp = inqCmdBlk;
561         io_hdr.sbp = sense_b;
562         io_hdr.timeout = DEF_TIMEOUT;
563
564         if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
565                 return -1;
566
567         /* treat SG_ERR here to get rid of sg_err.[ch] */
568         io_hdr.status &= 0x7e;
569         if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
570             (0 == io_hdr.driver_status))
571                 return 0;
572         if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
573             (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
574             (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
575                 if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
576                         int sense_key;
577                         unsigned char * sense_buffer = io_hdr.sbp;
578                         if (sense_buffer[0] & 0x2)
579                                 sense_key = sense_buffer[1] & 0xf;
580                         else
581                                 sense_key = sense_buffer[2] & 0xf;
582                         if(RECOVERED_ERROR == sense_key)
583                                 return 0;
584                 }
585         }
586         return -1;
587 }
588
589 static int
590 get_serial (char * str, int maxlen, int fd)
591 {
592         int len = 0;
593         char buff[MX_ALLOC_LEN + 1] = {0};
594
595         if (fd < 0)
596                 return 1;
597
598         if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN)) {
599                 len = buff[3];
600                 if (len >= maxlen)
601                         return 1;
602                 if (len > 0) {
603                         memcpy(str, buff + 4, len);
604                         str[len] = '\0';
605                 }
606                 return 0;
607         }
608         return 1;
609 }
610
611 static int
612 get_geometry(struct path *pp)
613 {
614         if (pp->fd < 0)
615                 return 1;
616
617         if (ioctl(pp->fd, HDIO_GETGEO, &pp->geom)) {
618                 condlog(2, "%s: HDIO_GETGEO failed with %d", pp->dev, errno);
619                 memset(&pp->geom, 0, sizeof(pp->geom));
620                 return 1;
621         }
622         condlog(3, "%s: %u cyl, %u heads, %u sectors/track, start at %lu",
623                 pp->dev, pp->geom.cylinders, pp->geom.heads,
624                 pp->geom.sectors, pp->geom.start);
625         return 0;
626 }
627
628 static int
629 scsi_sysfs_pathinfo (struct path * pp)
630 {
631         struct udev_device *parent;
632         const char *attr_path = NULL;
633
634         parent = pp->udev;
635         while (parent) {
636                 const char *subsys = udev_device_get_subsystem(parent);
637                 if (subsys && !strncmp(subsys, "scsi", 4)) {
638                         attr_path = udev_device_get_sysname(parent);
639                         if (!attr_path)
640                                 break;
641                         if (sscanf(attr_path, "%i:%i:%i:%i",
642                                    &pp->sg_id.host_no,
643                                    &pp->sg_id.channel,
644                                    &pp->sg_id.scsi_id,
645                                    &pp->sg_id.lun) == 4)
646                                 break;
647                 }
648                 parent = udev_device_get_parent(parent);
649         }
650         if (!attr_path || pp->sg_id.host_no == -1)
651                 return 1;
652
653         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE))
654                 return 1;
655
656         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
657
658         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE))
659                 return 1;
660
661         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
662
663         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE))
664                 return 1;
665
666         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
667
668         /*
669          * set the hwe configlet pointer
670          */
671         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
672
673         /*
674          * host / bus / target / lun
675          */
676         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
677                         pp->dev,
678                         pp->sg_id.host_no,
679                         pp->sg_id.channel,
680                         pp->sg_id.scsi_id,
681                         pp->sg_id.lun);
682
683         /*
684          * target node name
685          */
686         if(!sysfs_get_tgt_nodename(pp, pp->tgt_node_name)) {
687                 condlog(3, "%s: tgt_node_name = %s",
688                         pp->dev, pp->tgt_node_name);
689         }
690
691         return 0;
692 }
693
694 static int
695 ccw_sysfs_pathinfo (struct path * pp)
696 {
697         struct udev_device *parent;
698         char attr_buff[NAME_SIZE];
699         const char *attr_path;
700
701         parent = pp->udev;
702         while (parent) {
703                 const char *subsys = udev_device_get_subsystem(parent);
704                 if (subsys && !strncmp(subsys, "ccw", 3))
705                         break;
706                 parent = udev_device_get_parent(parent);
707         }
708         if (!parent)
709                 return 1;
710
711         sprintf(pp->vendor_id, "IBM");
712
713         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
714
715         if (sysfs_get_devtype(parent, attr_buff, FILE_NAME_SIZE))
716                 return 1;
717
718         if (!strncmp(attr_buff, "3370", 4)) {
719                 sprintf(pp->product_id,"S/390 DASD FBA");
720         } else if (!strncmp(attr_buff, "9336", 4)) {
721                 sprintf(pp->product_id,"S/390 DASD FBA");
722         } else {
723                 sprintf(pp->product_id,"S/390 DASD ECKD");
724         }
725
726         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
727
728         /*
729          * set the hwe configlet pointer
730          */
731         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
732
733         /*
734          * host / bus / target / lun
735          */
736         attr_path = udev_device_get_sysname(parent);
737         pp->sg_id.lun = 0;
738         sscanf(attr_path, "%i.%i.%x",
739                         &pp->sg_id.host_no,
740                         &pp->sg_id.channel,
741                         &pp->sg_id.scsi_id);
742         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
743                         pp->dev,
744                         pp->sg_id.host_no,
745                         pp->sg_id.channel,
746                         pp->sg_id.scsi_id,
747                         pp->sg_id.lun);
748
749         return 0;
750 }
751
752 static int
753 cciss_sysfs_pathinfo (struct path * pp)
754 {
755         const char * attr_path = NULL;
756         struct udev_device *parent;
757
758         parent = pp->udev;
759         while (parent) {
760                 const char *subsys = udev_device_get_subsystem(parent);
761                 if (subsys && !strncmp(subsys, "cciss", 5)) {
762                         attr_path = udev_device_get_sysname(parent);
763                         if (!attr_path)
764                                 break;
765                         if (sscanf(attr_path, "c%id%i",
766                                    &pp->sg_id.host_no,
767                                    &pp->sg_id.scsi_id) == 2)
768                                 break;
769                 }
770                 parent = udev_device_get_parent(parent);
771         }
772         if (!attr_path || pp->sg_id.host_no == -1)
773                 return 1;
774
775         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE))
776                 return 1;
777
778         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
779
780         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE))
781                 return 1;
782
783         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
784
785         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE))
786                 return 1;
787
788         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
789
790         /*
791          * set the hwe configlet pointer
792          */
793         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
794
795         /*
796          * host / bus / target / lun
797          */
798         pp->sg_id.lun = 0;
799         pp->sg_id.channel = 0;
800         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
801                 pp->dev,
802                 pp->sg_id.host_no,
803                 pp->sg_id.channel,
804                 pp->sg_id.scsi_id,
805                 pp->sg_id.lun);
806         return 0;
807 }
808
809 static int
810 common_sysfs_pathinfo (struct path * pp)
811 {
812         if (!pp)
813                 return 1;
814
815         if (!pp->udev) {
816                 condlog(4, "%s: udev not initialised", pp->dev);
817                 return 1;
818         }
819         if (sysfs_get_dev(pp->udev, pp->dev_t, BLK_DEV_SIZE)) {
820                 condlog(3, "%s: no 'dev' attribute in sysfs", pp->dev);
821                 return 1;
822         }
823
824         condlog(3, "%s: dev_t = %s", pp->dev, pp->dev_t);
825
826         if (sysfs_get_size(pp, &pp->size))
827                 return 1;
828
829         condlog(3, "%s: size = %llu", pp->dev, pp->size);
830
831         return 0;
832 }
833
834 int
835 path_offline (struct path * pp)
836 {
837         struct udev_device * parent;
838         char buff[SCSI_STATE_SIZE];
839
840         if (pp->bus != SYSFS_BUS_SCSI)
841                 return PATH_UP;
842
843         parent = pp->udev;
844         while (parent) {
845                 const char *subsys = udev_device_get_subsystem(parent);
846                 if (subsys && !strncmp(subsys, "scsi", 4))
847                         break;
848                 parent = udev_device_get_parent(parent);
849         }
850
851         if (!parent) {
852                 condlog(1, "%s: failed to get sysfs information", pp->dev);
853                 return PATH_DOWN;
854         }
855
856         memset(buff, 0x0, SCSI_STATE_SIZE);
857         if (sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE) <= 0)
858                 return PATH_DOWN;
859
860         condlog(3, "%s: path state = %s", pp->dev, buff);
861
862         if (!strncmp(buff, "offline", 7) ||
863             !strncmp(buff, "quiesce", 7) ||
864             !strncmp(buff, "transport-offline", 17)) {
865                 pp->offline = 1;
866                 return PATH_DOWN;
867         }
868         pp->offline = 0;
869         if (!strncmp(buff, "blocked", 7) || !strncmp(buff, "quiesce", 7))
870                 return PATH_PENDING;
871         else if (!strncmp(buff, "running", 7))
872                 return PATH_UP;
873
874         return PATH_DOWN;
875 }
876
877 int
878 sysfs_pathinfo(struct path * pp)
879 {
880         if (common_sysfs_pathinfo(pp))
881                 return 1;
882
883         pp->bus = SYSFS_BUS_UNDEF;
884         if (!strncmp(pp->dev,"cciss",5))
885                 pp->bus = SYSFS_BUS_CCISS;
886         if (!strncmp(pp->dev,"dasd", 4))
887                 pp->bus = SYSFS_BUS_CCW;
888         if (!strncmp(pp->dev,"sd", 2))
889                 pp->bus = SYSFS_BUS_SCSI;
890
891         if (pp->bus == SYSFS_BUS_UNDEF)
892                 return 0;
893         else if (pp->bus == SYSFS_BUS_SCSI) {
894                 if (scsi_sysfs_pathinfo(pp))
895                         return 1;
896         } else if (pp->bus == SYSFS_BUS_CCW) {
897                 if (ccw_sysfs_pathinfo(pp))
898                         return 1;
899         } else if (pp->bus == SYSFS_BUS_CCISS) {
900                 if (cciss_sysfs_pathinfo(pp))
901                         return 1;
902         }
903         return 0;
904 }
905
906 static int
907 scsi_ioctl_pathinfo (struct path * pp, int mask)
908 {
909         if (mask & DI_SERIAL) {
910                 get_serial(pp->serial, SERIAL_SIZE, pp->fd);
911                 condlog(3, "%s: serial = %s", pp->dev, pp->serial);
912         }
913
914         return 0;
915 }
916
917 static int
918 cciss_ioctl_pathinfo (struct path * pp, int mask)
919 {
920         if (mask & DI_SERIAL) {
921                 get_serial(pp->serial, SERIAL_SIZE, pp->fd);
922                 condlog(3, "%s: serial = %s", pp->dev, pp->serial);
923         }
924         return 0;
925 }
926
927 int
928 get_state (struct path * pp, int daemon)
929 {
930         struct checker * c = &pp->checker;
931         int state;
932
933         condlog(3, "%s: get_state", pp->dev);
934
935         if (!checker_selected(c)) {
936                 if (daemon) {
937                         if (pathinfo(pp, conf->hwtable, DI_SYSFS) != 0) {
938                                 condlog(3, "%s: couldn't get sysfs pathinfo",
939                                         pp->dev);
940                                 return PATH_UNCHECKED;
941                         }
942                 }
943                 select_checker(pp);
944                 if (!checker_selected(c)) {
945                         condlog(3, "%s: No checker selected", pp->dev);
946                         return PATH_UNCHECKED;
947                 }
948                 checker_set_fd(c, pp->fd);
949                 if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) {
950                         memset(c, 0x0, sizeof(struct checker));
951                         condlog(3, "%s: checker init failed", pp->dev);
952                         return PATH_UNCHECKED;
953                 }
954         }
955         checker_clear_message(c);
956         if (daemon)
957                 checker_set_async(c);
958         if (!conf->checker_timeout &&
959             (pp->bus != SYSFS_BUS_SCSI ||
960              sysfs_get_timeout(pp, &(c->timeout))))
961                 c->timeout = DEF_TIMEOUT;
962         state = checker_check(c);
963         condlog(3, "%s: state = %s", pp->dev, checker_state_name(state));
964         if (state != PATH_UP && state != PATH_GHOST &&
965             strlen(checker_message(c)))
966                 condlog(3, "%s: checker msg is \"%s\"",
967                         pp->dev, checker_message(c));
968         return state;
969 }
970
971 static int
972 get_prio (struct path * pp)
973 {
974         if (!pp)
975                 return 0;
976
977         struct prio * p = &pp->prio;
978
979         if (!prio_selected(p)) {
980                 select_detect_prio(pp);
981                 select_prio(pp);
982                 if (!prio_selected(p)) {
983                         condlog(3, "%s: no prio selected", pp->dev);
984                         pp->priority = PRIO_UNDEF;
985                         return 1;
986                 }
987         }
988         pp->priority = prio_getprio(p, pp);
989         if (pp->priority < 0) {
990                 condlog(3, "%s: %s prio error", pp->dev, prio_name(p));
991                 pp->priority = PRIO_UNDEF;
992                 return 1;
993         }
994         condlog(3, "%s: %s prio = %u",
995                 pp->dev, prio_name(p), pp->priority);
996         return 0;
997 }
998
999 static int
1000 get_uid (struct path * pp)
1001 {
1002         char *c;
1003         const char *origin;
1004
1005         if (!pp->uid_attribute && !pp->getuid)
1006                 select_getuid(pp);
1007
1008         if (!pp->udev) {
1009                 condlog(1, "%s: no udev information", pp->dev);
1010                 return 1;
1011         }
1012
1013         memset(pp->wwid, 0, WWID_SIZE);
1014         if (pp->getuid) {
1015                 char buff[CALLOUT_MAX_SIZE];
1016
1017                 /* Use 'getuid' callout, deprecated */
1018                 condlog(1, "%s: using deprecated getuid callout", pp->dev);
1019                 if (apply_format(pp->getuid, &buff[0], pp)) {
1020                         condlog(0, "error formatting uid callout command");
1021                         memset(pp->wwid, 0, WWID_SIZE);
1022                 } else if (execute_program(buff, pp->wwid, WWID_SIZE)) {
1023                         condlog(3, "error calling out %s", buff);
1024                         memset(pp->wwid, 0, WWID_SIZE);
1025                 }
1026                 origin = "callout";
1027         } else {
1028                 const char *value;
1029
1030                 value = udev_device_get_property_value(pp->udev,
1031                                                        pp->uid_attribute);
1032                 if ((!value || strlen(value) == 0) && conf->dry_run == 2)
1033                         value = getenv(pp->uid_attribute);
1034                 if (value && strlen(value)) {
1035                         size_t len = WWID_SIZE;
1036
1037                         if (strlen(value) + 1 > WWID_SIZE) {
1038                                 condlog(0, "%s: wwid overflow", pp->dev);
1039                         } else {
1040                                 len = strlen(value);
1041                         }
1042                         strncpy(pp->wwid, value, len);
1043                 } else {
1044                         condlog(3, "%s: no %s attribute", pp->dev,
1045                                 pp->uid_attribute);
1046                 }
1047                 origin = "udev";
1048         }
1049         /* Strip any trailing blanks */
1050         c = strchr(pp->wwid, '\0');
1051         c--;
1052         while (c && c >= pp->wwid && *c == ' ') {
1053                 *c = '\0';
1054                 c--;
1055         }
1056         condlog(3, "%s: uid = %s (%s)", pp->dev,
1057                 *pp->wwid == '\0' ? "<empty>" : pp->wwid, origin);
1058         return 0;
1059 }
1060
1061 extern int
1062 pathinfo (struct path *pp, vector hwtable, int mask)
1063 {
1064         int path_state;
1065
1066         if (!pp)
1067                 return 1;
1068
1069         condlog(3, "%s: mask = 0x%x", pp->dev, mask);
1070
1071         /*
1072          * fetch info available in sysfs
1073          */
1074         if (mask & DI_SYSFS && sysfs_pathinfo(pp))
1075                 return 1;
1076
1077         if (mask & DI_BLACKLIST && mask & DI_SYSFS) {
1078                 if (filter_device(conf->blist_device, conf->elist_device,
1079                                   pp->vendor_id, pp->product_id) > 0) {
1080                         return 2;
1081                 }
1082         }
1083
1084         path_state = path_offline(pp);
1085
1086         /*
1087          * fetch info not available through sysfs
1088          */
1089         if (pp->fd < 0)
1090                 pp->fd = open(udev_device_get_devnode(pp->udev), O_RDONLY);
1091
1092         if (pp->fd < 0) {
1093                 condlog(4, "Couldn't open node for %s: %s",
1094                         pp->dev, strerror(errno));
1095                 goto blank;
1096         }
1097
1098         if (mask & DI_SERIAL)
1099                 get_geometry(pp);
1100
1101         if (path_state == PATH_UP && pp->bus == SYSFS_BUS_SCSI &&
1102             scsi_ioctl_pathinfo(pp, mask))
1103                 goto blank;
1104
1105         if (pp->bus == SYSFS_BUS_CCISS &&
1106             cciss_ioctl_pathinfo(pp, mask))
1107                 goto blank;
1108
1109         if (mask & DI_CHECKER) {
1110                 if (path_state == PATH_UP) {
1111                         pp->chkrstate = pp->state = get_state(pp, 0);
1112                         if (pp->state == PATH_UNCHECKED ||
1113                             pp->state == PATH_WILD)
1114                                 goto blank;
1115                         if (pp->state == PATH_TIMEOUT)
1116                                 pp->state = PATH_DOWN;
1117                 } else {
1118                         condlog(3, "%s: path inaccessible", pp->dev);
1119                         pp->chkrstate = pp->state = path_state;
1120                         if (path_state == PATH_PENDING ||
1121                             path_state == PATH_DOWN)
1122                                 pp->priority = 0;
1123                 }
1124         }
1125
1126         if ((mask & DI_WWID) && !strlen(pp->wwid))
1127                 get_uid(pp);
1128         if (mask & DI_BLACKLIST && mask & DI_WWID) {
1129                 if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
1130                                 pp->wwid) > 0) {
1131                         return 2;
1132                 }
1133         }
1134
1135          /*
1136           * Retrieve path priority, even for PATH_DOWN paths if it has never
1137           * been successfully obtained before.
1138           */
1139         if ((mask & DI_PRIO) && path_state == PATH_UP) {
1140                 if (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF) {
1141                         if (!strlen(pp->wwid))
1142                                 get_uid(pp);
1143                         get_prio(pp);
1144                 }
1145         }
1146
1147         return 0;
1148
1149 blank:
1150         /*
1151          * Recoverable error, for example faulty or offline path
1152          */
1153         memset(pp->wwid, 0, WWID_SIZE);
1154         pp->chkrstate = pp->state = PATH_DOWN;
1155
1156         return 0;
1157 }