3fd33a3e72148cdfb68a0232c581c40cf4052d51
[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 *targetid, *value;
209         struct udev_device *parent, *tgtdev;
210         int host, channel, rport_id = -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                 pp->sg_id.proto_id = SCSI_PROTOCOL_SAS;
219                 strncpy(node, value, NODE_NAME_SIZE);
220                 return 0;
221         }
222
223         parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi", "scsi_target");
224         if (!parent)
225                 return 1;
226         /* Check for FibreChannel */
227         tgtdev = udev_device_get_parent(parent);
228         value = udev_device_get_sysname(tgtdev);
229         if (sscanf(value, "rport-%d:%d-%d",
230                    &host, &channel, &rport_id) == 3) {
231                 tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
232                                 "fc_remote_ports", value);
233                 if (tgtdev) {
234                         condlog(3, "SCSI target %d:%d:%d -> "
235                                 "FC rport %d:%d-%d",
236                                 pp->sg_id.host_no, pp->sg_id.channel,
237                                 pp->sg_id.scsi_id, host, channel,
238                                 rport_id);
239                         value = udev_device_get_sysattr_value(tgtdev,
240                                                               "node_name");
241                         if (value) {
242                                 pp->sg_id.proto_id = SCSI_PROTOCOL_FCP;
243                                 pp->sg_id.transport_id = rport_id;
244                                 strncpy(node, value, NODE_NAME_SIZE);
245                                 udev_device_unref(tgtdev);
246                                 return 0;
247                         } else
248                                 udev_device_unref(tgtdev);
249                 }
250         }
251
252         /* Check for iSCSI */
253         parent = pp->udev;
254         targetid = NULL;
255         while (parent) {
256                 targetid = udev_device_get_sysname(parent);
257                 if (!strncmp(targetid , "session", 6))
258                         break;
259                 parent = udev_device_get_parent(parent);
260                 targetid = NULL;
261         }
262         if (parent) {
263                 tgtdev = udev_device_new_from_subsystem_sysname(conf->udev, "iscsi_session", targetid);
264                 if (tgtdev) {
265                         const char *value;
266
267                         value = udev_device_get_sysattr_value(tgtdev, "targetname");
268                         if (value) {
269                                 pp->sg_id.proto_id = SCSI_PROTOCOL_ISCSI;
270                                 strncpy(node, value, NODE_NAME_SIZE);
271                                 udev_device_unref(tgtdev);
272                                 return 0;
273                         }
274                         else
275                                 udev_device_unref(tgtdev);
276                 }
277         }
278         return 1;
279 }
280
281 static void
282 sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
283 {
284         struct udev_device *rport_dev = NULL;
285         char value[11];
286         char rport_id[32];
287
288         if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) {
289                 condlog(3, "%s: Not a FCP device", pp->dev);
290                 return;
291         }
292         sprintf(rport_id, "rport-%d:%d-%d",
293                 pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
294         rport_dev = udev_device_new_from_subsystem_sysname(conf->udev,
295                                 "fc_remote_ports", rport_id);
296         if (!rport_dev) {
297                 condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
298                         rport_id);
299                 return;
300         }
301         condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
302                 pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
303
304         snprintf(value, 11, "%u", mpp->dev_loss);
305         if (mpp->dev_loss &&
306             sysfs_attr_set_value(rport_dev, "dev_loss_tmo", value, 11) <= 0) {
307                 if ((mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET ||
308                      mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
309                     && mpp->dev_loss > 600) {
310                         condlog(3, "%s: limiting dev_loss_tmo to 600, since "
311                                 "fast_io_fail is not set", mpp->alias);
312                         snprintf(value, 11, "%u", 600);
313                         if (sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
314                                                  value, 11) <= 0)
315                                 condlog(0, "%s failed to set dev_loss_tmo",
316                                         mpp->alias);
317                         goto out;
318                 }
319         }
320         if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET){
321                 if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
322                         sprintf(value, "off");
323                 else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
324                         sprintf(value, "0");
325                 else
326                         snprintf(value, 11, "%u", mpp->fast_io_fail);
327                 if (sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
328                                          value, 11) <= 0) {
329                         condlog(0, "%s failed to set fast_io_fail_tmo",
330                                 mpp->alias);
331                 }
332         }
333 out:
334         udev_device_unref(rport_dev);
335 }
336
337 int
338 sysfs_set_scsi_tmo (struct multipath *mpp)
339 {
340         struct path *pp;
341         int i;
342         int dev_loss_tmo = mpp->dev_loss;
343
344         if (mpp->no_path_retry > 0) {
345                 int no_path_retry_tmo = mpp->no_path_retry * conf->checkint;
346
347                 if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
348                         no_path_retry_tmo = MAX_DEV_LOSS_TMO;
349                 if (no_path_retry_tmo > dev_loss_tmo)
350                         dev_loss_tmo = no_path_retry_tmo;
351                 condlog(3, "%s: update dev_loss_tmo to %d",
352                         mpp->alias, dev_loss_tmo);
353         } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) {
354                 dev_loss_tmo = MAX_DEV_LOSS_TMO;
355                 condlog(3, "%s: update dev_loss_tmo to %d",
356                         mpp->alias, dev_loss_tmo);
357         }
358         mpp->dev_loss = dev_loss_tmo;
359         if (mpp->dev_loss && mpp->fast_io_fail >= (int)mpp->dev_loss) {
360                 condlog(3, "%s: turning off fast_io_fail (%d is not smaller than dev_loss_tmo)",
361                         mpp->alias, mpp->fast_io_fail);
362                 mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
363         }
364         if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
365                 return 0;
366
367         vector_foreach_slot(mpp->paths, pp, i) {
368                 sysfs_set_rport_tmo(mpp, pp);
369         }
370         return 0;
371 }
372
373 int
374 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
375        void *resp, int mx_resp_len)
376 {
377         unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
378                 { INQUIRY_CMD, 0, 0, 0, 0, 0 };
379         unsigned char sense_b[SENSE_BUFF_LEN];
380         struct sg_io_hdr io_hdr;
381
382         if (cmddt)
383                 inqCmdBlk[1] |= 2;
384         if (evpd)
385                 inqCmdBlk[1] |= 1;
386         inqCmdBlk[2] = (unsigned char) pg_op;
387         inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
388         inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
389         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
390         memset(sense_b, 0, SENSE_BUFF_LEN);
391         io_hdr.interface_id = 'S';
392         io_hdr.cmd_len = sizeof (inqCmdBlk);
393         io_hdr.mx_sb_len = sizeof (sense_b);
394         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
395         io_hdr.dxfer_len = mx_resp_len;
396         io_hdr.dxferp = resp;
397         io_hdr.cmdp = inqCmdBlk;
398         io_hdr.sbp = sense_b;
399         io_hdr.timeout = DEF_TIMEOUT;
400
401         if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
402                 return -1;
403
404         /* treat SG_ERR here to get rid of sg_err.[ch] */
405         io_hdr.status &= 0x7e;
406         if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
407             (0 == io_hdr.driver_status))
408                 return 0;
409         if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
410             (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
411             (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
412                 if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
413                         int sense_key;
414                         unsigned char * sense_buffer = io_hdr.sbp;
415                         if (sense_buffer[0] & 0x2)
416                                 sense_key = sense_buffer[1] & 0xf;
417                         else
418                                 sense_key = sense_buffer[2] & 0xf;
419                         if(RECOVERED_ERROR == sense_key)
420                                 return 0;
421                 }
422         }
423         return -1;
424 }
425
426 static int
427 get_serial (char * str, int maxlen, int fd)
428 {
429         int len = 0;
430         char buff[MX_ALLOC_LEN + 1] = {0};
431
432         if (fd < 0)
433                 return 1;
434
435         if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN)) {
436                 len = buff[3];
437                 if (len >= maxlen)
438                         return 1;
439                 if (len > 0) {
440                         memcpy(str, buff + 4, len);
441                         str[len] = '\0';
442                 }
443                 return 0;
444         }
445         return 1;
446 }
447
448 static int
449 get_geometry(struct path *pp)
450 {
451         if (pp->fd < 0)
452                 return 1;
453
454         if (ioctl(pp->fd, HDIO_GETGEO, &pp->geom)) {
455                 condlog(2, "%s: HDIO_GETGEO failed with %d", pp->dev, errno);
456                 memset(&pp->geom, 0, sizeof(pp->geom));
457                 return 1;
458         }
459         condlog(3, "%s: %u cyl, %u heads, %u sectors/track, start at %lu",
460                 pp->dev, pp->geom.cylinders, pp->geom.heads,
461                 pp->geom.sectors, pp->geom.start);
462         return 0;
463 }
464
465 static int
466 scsi_sysfs_pathinfo (struct path * pp)
467 {
468         struct udev_device *parent;
469         const char *attr_path = NULL;
470
471         parent = pp->udev;
472         while (parent) {
473                 const char *subsys = udev_device_get_subsystem(parent);
474                 if (subsys && !strncmp(subsys, "scsi", 4)) {
475                         attr_path = udev_device_get_sysname(parent);
476                         if (!attr_path)
477                                 break;
478                         if (sscanf(attr_path, "%i:%i:%i:%i",
479                                    &pp->sg_id.host_no,
480                                    &pp->sg_id.channel,
481                                    &pp->sg_id.scsi_id,
482                                    &pp->sg_id.lun) == 4)
483                                 break;
484                 }
485                 parent = udev_device_get_parent(parent);
486         }
487         if (!attr_path || pp->sg_id.host_no == -1)
488                 return 1;
489
490         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE))
491                 return 1;
492
493         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
494
495         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE))
496                 return 1;
497
498         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
499
500         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE))
501                 return 1;
502
503         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
504
505         /*
506          * set the hwe configlet pointer
507          */
508         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
509
510         /*
511          * host / bus / target / lun
512          */
513         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
514                         pp->dev,
515                         pp->sg_id.host_no,
516                         pp->sg_id.channel,
517                         pp->sg_id.scsi_id,
518                         pp->sg_id.lun);
519
520         /*
521          * target node name
522          */
523         if(!sysfs_get_tgt_nodename(pp, pp->tgt_node_name)) {
524                 condlog(3, "%s: tgt_node_name = %s",
525                         pp->dev, pp->tgt_node_name);
526         }
527
528         return 0;
529 }
530
531 static int
532 ccw_sysfs_pathinfo (struct path * pp)
533 {
534         struct udev_device *parent;
535         char attr_buff[NAME_SIZE];
536         const char *attr_path;
537
538         parent = pp->udev;
539         while (parent) {
540                 const char *subsys = udev_device_get_subsystem(parent);
541                 if (subsys && !strncmp(subsys, "ccw", 3))
542                         break;
543                 parent = udev_device_get_parent(parent);
544         }
545         if (!parent)
546                 return 1;
547
548         sprintf(pp->vendor_id, "IBM");
549
550         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
551
552         if (sysfs_get_devtype(parent, attr_buff, FILE_NAME_SIZE))
553                 return 1;
554
555         if (!strncmp(attr_buff, "3370", 4)) {
556                 sprintf(pp->product_id,"S/390 DASD FBA");
557         } else if (!strncmp(attr_buff, "9336", 4)) {
558                 sprintf(pp->product_id,"S/390 DASD FBA");
559         } else {
560                 sprintf(pp->product_id,"S/390 DASD ECKD");
561         }
562
563         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
564
565         /*
566          * set the hwe configlet pointer
567          */
568         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
569
570         /*
571          * host / bus / target / lun
572          */
573         attr_path = udev_device_get_sysname(parent);
574         pp->sg_id.lun = 0;
575         sscanf(attr_path, "%i.%i.%x",
576                         &pp->sg_id.host_no,
577                         &pp->sg_id.channel,
578                         &pp->sg_id.scsi_id);
579         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
580                         pp->dev,
581                         pp->sg_id.host_no,
582                         pp->sg_id.channel,
583                         pp->sg_id.scsi_id,
584                         pp->sg_id.lun);
585
586         return 0;
587 }
588
589 static int
590 cciss_sysfs_pathinfo (struct path * pp)
591 {
592         const char * attr_path = NULL;
593         struct udev_device *parent;
594
595         parent = pp->udev;
596         while (parent) {
597                 const char *subsys = udev_device_get_subsystem(parent);
598                 if (subsys && !strncmp(subsys, "cciss", 5)) {
599                         attr_path = udev_device_get_sysname(parent);
600                         if (!attr_path)
601                                 break;
602                         if (sscanf(attr_path, "c%id%i",
603                                    &pp->sg_id.host_no,
604                                    &pp->sg_id.scsi_id) == 2)
605                                 break;
606                 }
607                 parent = udev_device_get_parent(parent);
608         }
609         if (!attr_path || pp->sg_id.host_no == -1)
610                 return 1;
611
612         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE))
613                 return 1;
614
615         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
616
617         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE))
618                 return 1;
619
620         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
621
622         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE))
623                 return 1;
624
625         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
626
627         /*
628          * set the hwe configlet pointer
629          */
630         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
631
632         /*
633          * host / bus / target / lun
634          */
635         pp->sg_id.lun = 0;
636         pp->sg_id.channel = 0;
637         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
638                 pp->dev,
639                 pp->sg_id.host_no,
640                 pp->sg_id.channel,
641                 pp->sg_id.scsi_id,
642                 pp->sg_id.lun);
643         return 0;
644 }
645
646 static int
647 common_sysfs_pathinfo (struct path * pp)
648 {
649         if (!pp->udev) {
650                 condlog(4, "%s: udev not initialised", pp->dev);
651                 return 1;
652         }
653         if (sysfs_get_dev(pp->udev, pp->dev_t, BLK_DEV_SIZE)) {
654                 condlog(3, "%s: no 'dev' attribute in sysfs", pp->dev);
655                 return 1;
656         }
657
658         condlog(3, "%s: dev_t = %s", pp->dev, pp->dev_t);
659
660         if (sysfs_get_size(pp, &pp->size))
661                 return 1;
662
663         condlog(3, "%s: size = %llu", pp->dev, pp->size);
664
665         return 0;
666 }
667
668 int
669 path_offline (struct path * pp)
670 {
671         struct udev_device * parent;
672         char buff[SCSI_STATE_SIZE];
673
674         if (pp->bus != SYSFS_BUS_SCSI)
675                 return PATH_UP;
676
677         parent = pp->udev;
678         while (parent) {
679                 const char *subsys = udev_device_get_subsystem(parent);
680                 if (subsys && !strncmp(subsys, "scsi", 4))
681                         break;
682                 parent = udev_device_get_parent(parent);
683         }
684
685         if (!parent) {
686                 condlog(1, "%s: failed to get sysfs information", pp->dev);
687                 return PATH_DOWN;
688         }
689
690         if (sysfs_get_state(parent, buff, SCSI_STATE_SIZE))
691                 return PATH_DOWN;
692
693         condlog(3, "%s: path state = %s", pp->dev, buff);
694
695         if (!strncmp(buff, "offline", 7)) {
696                 pp->offline = 1;
697                 return PATH_DOWN;
698         }
699         pp->offline = 0;
700         if (!strncmp(buff, "blocked", 7))
701                 return PATH_PENDING;
702         else if (!strncmp(buff, "running", 7))
703                 return PATH_UP;
704
705         return PATH_DOWN;
706 }
707
708 int
709 sysfs_pathinfo(struct path * pp)
710 {
711         if (common_sysfs_pathinfo(pp))
712                 return 1;
713
714         pp->bus = SYSFS_BUS_UNDEF;
715         if (!strncmp(pp->dev,"cciss",5))
716                 pp->bus = SYSFS_BUS_CCISS;
717         if (!strncmp(pp->dev,"dasd", 4))
718                 pp->bus = SYSFS_BUS_CCW;
719         if (!strncmp(pp->dev,"sd", 2))
720                 pp->bus = SYSFS_BUS_SCSI;
721
722         if (pp->bus == SYSFS_BUS_UNDEF)
723                 return 0;
724         else if (pp->bus == SYSFS_BUS_SCSI) {
725                 if (scsi_sysfs_pathinfo(pp))
726                         return 1;
727         } else if (pp->bus == SYSFS_BUS_CCW) {
728                 if (ccw_sysfs_pathinfo(pp))
729                         return 1;
730         } else if (pp->bus == SYSFS_BUS_CCISS) {
731                 if (cciss_sysfs_pathinfo(pp))
732                         return 1;
733         }
734         return 0;
735 }
736
737 static int
738 scsi_ioctl_pathinfo (struct path * pp, int mask)
739 {
740         if (mask & DI_SERIAL) {
741                 get_serial(pp->serial, SERIAL_SIZE, pp->fd);
742                 condlog(3, "%s: serial = %s", pp->dev, pp->serial);
743         }
744
745         return 0;
746 }
747
748 static int
749 cciss_ioctl_pathinfo (struct path * pp, int mask)
750 {
751         if (mask & DI_SERIAL) {
752                 get_serial(pp->serial, SERIAL_SIZE, pp->fd);
753                 condlog(3, "%s: serial = %s", pp->dev, pp->serial);
754         }
755         return 0;
756 }
757
758 int
759 get_state (struct path * pp, int daemon)
760 {
761         struct checker * c = &pp->checker;
762         int state;
763
764         condlog(3, "%s: get_state", pp->dev);
765
766         if (!checker_selected(c)) {
767                 if (daemon) {
768                         if (pathinfo(pp, conf->hwtable, DI_SYSFS) != 0) {
769                                 condlog(3, "%s: couldn't get sysfs pathinfo",
770                                         pp->dev);
771                                 return PATH_UNCHECKED;
772                         }
773                 }
774                 select_checker(pp);
775                 if (!checker_selected(c)) {
776                         condlog(3, "%s: No checker selected", pp->dev);
777                         return PATH_UNCHECKED;
778                 }
779                 checker_set_fd(c, pp->fd);
780                 if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) {
781                         memset(c, 0x0, sizeof(struct checker));
782                         condlog(3, "%s: checker init failed", pp->dev);
783                         return PATH_UNCHECKED;
784                 }
785         }
786         checker_clear_message(c);
787         if (daemon)
788                 checker_set_async(c);
789         if (!conf->checker_timeout &&
790             (pp->bus != SYSFS_BUS_SCSI ||
791              sysfs_get_timeout(pp, &(c->timeout))))
792                 c->timeout = DEF_TIMEOUT;
793         state = checker_check(c);
794         condlog(3, "%s: state = %s", pp->dev, checker_state_name(state));
795         if (state != PATH_UP && strlen(checker_message(c)))
796                 condlog(3, "%s: checker msg is \"%s\"",
797                         pp->dev, checker_message(c));
798         return state;
799 }
800
801 static int
802 get_prio (struct path * pp)
803 {
804         if (!pp)
805                 return 0;
806
807         struct prio * p = &pp->prio;
808
809         if (!prio_selected(p)) {
810                 select_detect_prio(pp);
811                 select_prio(pp);
812                 if (!prio_selected(p)) {
813                         condlog(3, "%s: no prio selected", pp->dev);
814                         return 1;
815                 }
816         }
817         pp->priority = prio_getprio(p, pp);
818         if (pp->priority < 0) {
819                 condlog(3, "%s: %s prio error", pp->dev, prio_name(p));
820                 pp->priority = PRIO_UNDEF;
821                 return 1;
822         }
823         condlog(3, "%s: %s prio = %u",
824                 pp->dev, prio_name(p), pp->priority);
825         return 0;
826 }
827
828 static int
829 get_uid (struct path * pp)
830 {
831         char *c;
832         const char *value;
833
834         if (!pp->uid_attribute)
835                 select_getuid(pp);
836
837         if (!pp->udev) {
838                 condlog(1, "%s: no udev information", pp->dev);
839                 return 1;
840         }
841
842         memset(pp->wwid, 0, WWID_SIZE);
843         value = udev_device_get_property_value(pp->udev, pp->uid_attribute);
844         if ((!value || strlen(value) == 0) && conf->dry_run == 2)
845                 value = getenv(pp->uid_attribute);
846         if (value && strlen(value)) {
847                 size_t len = WWID_SIZE;
848
849                 if (strlen(value) + 1 > WWID_SIZE) {
850                         condlog(0, "%s: wwid overflow", pp->dev);
851                 } else {
852                         len = strlen(value);
853                 }
854                 strncpy(pp->wwid, value, len);
855         } else {
856                 condlog(3, "%s: no %s attribute", pp->dev,
857                         pp->uid_attribute);
858         }
859
860         /* Strip any trailing blanks */
861         c = strchr(pp->wwid, '\0');
862         c--;
863         while (c && c >= pp->wwid && *c == ' ') {
864                 *c = '\0';
865                 c--;
866         }
867         condlog(3, "%s: uid = %s (udev)", pp->dev,
868                 *pp->wwid == '\0' ? "<empty>" : pp->wwid);
869         return 0;
870 }
871
872 extern int
873 pathinfo (struct path *pp, vector hwtable, int mask)
874 {
875         int path_state;
876
877         condlog(3, "%s: mask = 0x%x", pp->dev, mask);
878
879         /*
880          * fetch info available in sysfs
881          */
882         if (mask & DI_SYSFS && sysfs_pathinfo(pp))
883                 return 1;
884
885         if (mask & DI_BLACKLIST && mask & DI_SYSFS) {
886                 if (filter_device(conf->blist_device, conf->elist_device,
887                                   pp->vendor_id, pp->product_id) > 0) {
888                         return 2;
889                 }
890         }
891
892         path_state = path_offline(pp);
893
894         /*
895          * fetch info not available through sysfs
896          */
897         if (pp->fd < 0)
898                 pp->fd = open(udev_device_get_devnode(pp->udev), O_RDONLY);
899
900         if (pp->fd < 0) {
901                 condlog(4, "Couldn't open node for %s: %s",
902                         pp->dev, strerror(errno));
903                 goto blank;
904         }
905
906         if (mask & DI_SERIAL)
907                 get_geometry(pp);
908
909         if (path_state == PATH_UP && pp->bus == SYSFS_BUS_SCSI &&
910             scsi_ioctl_pathinfo(pp, mask))
911                 goto blank;
912
913         if (pp->bus == SYSFS_BUS_CCISS &&
914             cciss_ioctl_pathinfo(pp, mask))
915                 goto blank;
916
917         if (mask & DI_CHECKER) {
918                 if (path_state == PATH_UP) {
919                         pp->chkrstate = pp->state = get_state(pp, 0);
920                         if (pp->state == PATH_UNCHECKED ||
921                             pp->state == PATH_WILD)
922                                 goto blank;
923                 } else {
924                         condlog(3, "%s: path inaccessible", pp->dev);
925                         pp->chkrstate = pp->state = path_state;
926                 }
927         }
928
929         if (path_state == PATH_UP && (mask & DI_WWID) && !strlen(pp->wwid))
930                 get_uid(pp);
931         if (mask & DI_BLACKLIST && mask & DI_WWID) {
932                 if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
933                                 pp->wwid) > 0) {
934                         return 2;
935                 }
936         }
937
938          /*
939           * Retrieve path priority, even for PATH_DOWN paths if it has never
940           * been successfully obtained before.
941           */
942         if ((mask & DI_PRIO) && path_state == PATH_UP) {
943                 if (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF) {
944                         if (!strlen(pp->wwid))
945                                 get_uid(pp);
946                         get_prio(pp);
947                 } else {
948                         pp->priority = PRIO_UNDEF;
949                 }
950         }
951
952         return 0;
953
954 blank:
955         /*
956          * Recoverable error, for example faulty or offline path
957          */
958         memset(pp->wwid, 0, WWID_SIZE);
959         pp->chkrstate = pp->state = PATH_DOWN;
960
961         return 0;
962 }