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