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