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