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