Remove DAEMON defines
[platform/upstream/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
14 #include "checkers.h"
15 #include "vector.h"
16 #include "memory.h"
17 #include "util.h"
18 #include "structs.h"
19 #include "config.h"
20 #include "blacklist.h"
21 #include "callout.h"
22 #include "debug.h"
23 #include "propsel.h"
24 #include "sg_include.h"
25 #include "sysfs.h"
26 #include "discovery.h"
27 #include "prio.h"
28
29 struct path *
30 store_pathinfo (vector pathvec, vector hwtable, char * devname, int flag)
31 {
32         struct path * pp;
33
34         pp = alloc_path();
35
36         if (!pp)
37                 return NULL;
38
39         if(safe_sprintf(pp->dev, "%s", devname)) {
40                 condlog(0, "pp->dev too small");
41                 goto out;
42         }
43         if (pathinfo(pp, hwtable, flag))
44                 goto out;
45
46         if (store_path(pathvec, pp))
47                 goto out;
48
49         return pp;
50 out:
51         free_path(pp);
52         return NULL;
53 }
54
55 static int
56 path_discover (vector pathvec, struct config * conf, char * devname, int flag)
57 {
58         char path[FILE_NAME_SIZE];
59         struct path * pp;
60
61         if (!devname)
62                 return 0;
63
64         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
65                            devname) > 0)
66                 return 0;
67
68         if(safe_sprintf(path, "%s/block/%s/device", sysfs_path,
69                         devname)) {
70                 condlog(0, "path too small");
71                 return 1;
72         }
73                         
74         if (strncmp(devname,"cciss",5) && !filepresent(path)) {
75                 condlog(4, "path %s not present", path);
76                 return 0;
77         }
78
79         pp = find_path_by_dev(pathvec, devname);
80
81         if (!pp) {
82                 pp = store_pathinfo(pathvec, conf->hwtable,
83                                     devname, flag);
84                 return (pp ? 0 : 1);
85         }
86         return pathinfo(pp, conf->hwtable, flag);
87 }
88
89 int
90 path_discovery (vector pathvec, struct config * conf, int flag)
91 {
92         DIR *blkdir;
93         struct dirent *blkdev;
94         struct stat statbuf;
95         char devpath[PATH_MAX];
96         char *devptr;
97         int r = 0;
98
99         if (!(blkdir = opendir("/sys/block")))
100                 return 1;
101
102         strcpy(devpath,"/sys/block");
103         while ((blkdev = readdir(blkdir)) != NULL) {
104                 if ((strcmp(blkdev->d_name,".") == 0) ||
105                     (strcmp(blkdev->d_name,"..") == 0))
106                         continue;
107
108                 devptr = devpath + 10;
109                 *devptr = '\0';
110                 strcat(devptr,"/");
111                 strcat(devptr,blkdev->d_name);
112                 if (stat(devpath, &statbuf) < 0)
113                         continue;
114
115                 if (S_ISDIR(statbuf.st_mode) == 0)
116                         continue;
117
118                 condlog(4, "Discover device %s", devpath);
119
120                 r += path_discover(pathvec, conf, blkdev->d_name, flag);
121         }
122         closedir(blkdir);
123         condlog(4, "Discovery status %d", r);
124         return r;
125 }
126
127 #define declare_sysfs_get_str(fname) \
128 extern int \
129 sysfs_get_##fname (struct sysfs_device * dev, char * buff, size_t len) \
130 { \
131         char *attr; \
132 \
133         attr = sysfs_attr_get_value(dev->devpath, #fname); \
134         if (!attr) \
135                 return 1; \
136         if (strlcpy(buff, attr, len) != strlen(attr)) \
137                 return 2; \
138         strchop(buff); \
139         return 0; \
140 }
141
142 declare_sysfs_get_str(devtype);
143 declare_sysfs_get_str(cutype);
144 declare_sysfs_get_str(vendor);
145 declare_sysfs_get_str(model);
146 declare_sysfs_get_str(rev);
147
148 int
149 sysfs_get_dev (struct sysfs_device * dev, char * buff, size_t len)
150 {
151         char *attr;
152
153         attr = sysfs_attr_get_value(dev->devpath, "dev");
154         if (!attr) {
155                 condlog(3, "%s: no 'dev' attribute in sysfs", dev->kernel);
156                 return 1;
157         }
158         if (strlcpy(buff, attr, len) != strlen(attr)) {
159                 condlog(3, "%s: overflow in 'dev' attribute", dev->kernel);
160                 return 2;
161         }
162         return 0;
163 }
164
165 int
166 sysfs_get_size (struct sysfs_device * dev, unsigned long long * size)
167 {
168         char *attr;
169         int r;
170
171         attr = sysfs_attr_get_value(dev->devpath, "size");
172         if (!attr)
173                 return 1;
174
175         r = sscanf(attr, "%llu\n", size);
176
177         if (r != 1)
178                 return 1;
179
180         return 0;
181 }
182         
183 int
184 sysfs_get_fc_nodename (struct sysfs_device * dev, char * node,
185                        unsigned int host, unsigned int channel,
186                        unsigned int target)
187 {
188         char attr_path[SYSFS_PATH_SIZE], *attr;
189
190         if (safe_sprintf(attr_path, 
191                          "/class/fc_transport/target%i:%i:%i",
192                          host, channel, target)) {
193                 condlog(0, "attr_path too small");
194                 return 1;
195         }
196
197         attr = sysfs_attr_get_value(attr_path, "node_name");
198         if (attr) {
199                 strlcpy(node, attr, strlen(attr));
200                 return 0;
201         }
202
203         return 1;
204 }
205         
206 /*
207  * udev might be slow creating node files : wait
208  */
209 static int
210 opennode (char * dev, int mode)
211 {
212         char devpath[FILE_NAME_SIZE], *ptr;
213
214         if (safe_sprintf(devpath, "%s/%s", conf->udev_dir, dev)) {
215                 condlog(0, "devpath too small");
216                 return -1;
217         }
218         /*
219          * Translate '!' into '/'
220          */
221         ptr = devpath;
222         while ((ptr = strchr(ptr, '!'))) {
223                 *ptr = '/';
224                 ptr++;
225         }
226         return open(devpath, mode);
227 }
228
229 extern int
230 devt2devname (char *devname, char *devt)
231 {
232         FILE *fd;
233         unsigned int tmpmaj, tmpmin, major, minor;
234         char dev[FILE_NAME_SIZE];
235         char block_path[FILE_NAME_SIZE];
236         struct stat statbuf;
237
238         if (sscanf(devt, "%u:%u", &major, &minor) != 2) {
239                 condlog(0, "Invalid device number %s", devt);
240                 return 1;
241         }
242
243         if ((fd = fopen("/proc/partitions", "r")) < 0) {
244                 condlog(0, "Cannot open /proc/partitions");
245                 return 1;
246         }
247         
248         while (!feof(fd)) {
249                 int r = fscanf(fd,"%u %u %*d %s",&tmpmaj, &tmpmin, dev);
250                 if (!r) {
251                         fscanf(fd,"%*s\n");
252                         continue;
253                 }
254                 if (r != 3)
255                         continue;
256
257                 if ((major == tmpmaj) && (minor == tmpmin)) {
258                         sprintf(block_path, "/sys/block/%s", dev);
259                         break;
260                 }
261         }
262         fclose(fd);
263
264         if (strncmp(block_path,"/sys/block", 10))
265                 return 1;
266
267         if (stat(block_path, &statbuf) < 0) {
268                 condlog(0, "No sysfs entry for %s\n", block_path);
269                 return 1;
270         }
271
272         if (S_ISDIR(statbuf.st_mode) == 0) {
273                 condlog(0, "sysfs entry %s is not a directory\n", block_path);
274                 return 1;
275         }
276         return 0;
277 }
278
279 int
280 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
281        void *resp, int mx_resp_len, int noisy)
282 {
283         unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
284             { INQUIRY_CMD, 0, 0, 0, 0, 0 };
285         unsigned char sense_b[SENSE_BUFF_LEN];
286         struct sg_io_hdr io_hdr;
287
288         if (cmddt)
289                 inqCmdBlk[1] |= 2;
290         if (evpd)
291                 inqCmdBlk[1] |= 1;
292         inqCmdBlk[2] = (unsigned char) pg_op;
293         inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
294         inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
295         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
296         io_hdr.interface_id = 'S';
297         io_hdr.cmd_len = sizeof (inqCmdBlk);
298         io_hdr.mx_sb_len = sizeof (sense_b);
299         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
300         io_hdr.dxfer_len = mx_resp_len;
301         io_hdr.dxferp = resp;
302         io_hdr.cmdp = inqCmdBlk;
303         io_hdr.sbp = sense_b;
304         io_hdr.timeout = DEF_TIMEOUT;
305
306         if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
307                 return -1;
308
309         /* treat SG_ERR here to get rid of sg_err.[ch] */
310         io_hdr.status &= 0x7e;
311         if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
312             (0 == io_hdr.driver_status))
313                 return 0;
314         if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
315             (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
316             (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
317                 if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
318                         int sense_key;
319                         unsigned char * sense_buffer = io_hdr.sbp;
320                         if (sense_buffer[0] & 0x2)
321                                 sense_key = sense_buffer[1] & 0xf;
322                         else
323                                 sense_key = sense_buffer[2] & 0xf;
324                         if(RECOVERED_ERROR == sense_key)
325                                 return 0;
326                 }
327         }
328         return -1;
329 }
330
331 static int
332 get_serial (char * str, int maxlen, int fd)
333 {
334         int len = 0;
335         char buff[MX_ALLOC_LEN + 1] = {0};
336
337         if (fd < 0)
338                 return 1;
339
340         if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
341                 len = buff[3];
342                 if (len >= maxlen)
343                         return 1;
344                 if (len > 0) {
345                         memcpy(str, buff + 4, len);
346                         str[len] = '\0';
347                 }
348                 return 0;
349         }
350         return 1;
351 }
352
353 static int
354 get_inq (char * vendor, char * product, char * rev, int fd)
355 {
356         char buff[MX_ALLOC_LEN + 1] = {0};
357
358         if (fd < 0)
359                 return 1;
360
361         if (0 == do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN, 0)) {
362                 memcpy(vendor, buff + 8, 8);
363                 vendor[8] = '\0';
364                 strchop(vendor);
365                 memcpy(product, buff + 16, 16);
366                 product[16] = '\0';
367                 strchop(product);
368                 memcpy(rev, buff + 32, 4);
369                 rev[4] = '\0';
370                 strchop(rev);
371                 return 0;
372         }
373         return 1;
374 }
375
376 static int
377 scsi_sysfs_pathinfo (struct path * pp, struct sysfs_device * parent)
378 {
379         char attr_path[FILE_NAME_SIZE];
380
381         if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE))
382                 return 1;
383
384         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
385
386         if (sysfs_get_model(parent, pp->product_id, SCSI_PRODUCT_SIZE))
387                 return 1;
388
389         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
390
391         if (sysfs_get_rev(parent, pp->rev, SCSI_REV_SIZE))
392                 return 1;
393
394         condlog(3, "%s: rev = %s", pp->dev, pp->rev);
395
396         /*
397          * set the hwe configlet pointer
398          */
399         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
400
401         /*
402          * host / bus / target / lun
403          */
404         basename(parent->devpath, attr_path);
405
406         sscanf(attr_path, "%i:%i:%i:%i",
407                         &pp->sg_id.host_no,
408                         &pp->sg_id.channel,
409                         &pp->sg_id.scsi_id,
410                         &pp->sg_id.lun);
411         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
412                         pp->dev,
413                         pp->sg_id.host_no,
414                         pp->sg_id.channel,
415                         pp->sg_id.scsi_id,
416                         pp->sg_id.lun);
417
418         /*
419          * target node name
420          */
421         if(!sysfs_get_fc_nodename(parent, pp->tgt_node_name,
422                                  pp->sg_id.host_no,
423                                  pp->sg_id.channel,
424                                  pp->sg_id.scsi_id)) {
425                 condlog(3, "%s: tgt_node_name = %s",
426                         pp->dev, pp->tgt_node_name);
427         }
428
429         return 0;
430 }
431
432 static int
433 ccw_sysfs_pathinfo (struct path * pp, struct sysfs_device * parent)
434 {
435         char attr_path[FILE_NAME_SIZE];
436         char attr_buff[FILE_NAME_SIZE];
437
438         sprintf(pp->vendor_id, "IBM");
439
440         condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
441
442         if (sysfs_get_devtype(parent, attr_buff, FILE_NAME_SIZE))
443                 return 1;
444
445         if (!strncmp(attr_buff, "3370", 4)) {
446                 sprintf(pp->product_id,"S/390 DASD FBA");
447         } else if (!strncmp(attr_buff, "9336", 4)) {
448                 sprintf(pp->product_id,"S/390 DASD FBA");
449         } else {
450                 sprintf(pp->product_id,"S/390 DASD ECKD");
451         }
452
453         condlog(3, "%s: product = %s", pp->dev, pp->product_id);
454
455         /*
456          * set the hwe configlet pointer
457          */
458         pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
459
460         /*
461          * host / bus / target / lun
462          */     
463         basename(parent->devpath, attr_path);
464         pp->sg_id.lun = 0;
465         sscanf(attr_path, "%i.%i.%x",
466                         &pp->sg_id.host_no,
467                         &pp->sg_id.channel,
468                         &pp->sg_id.scsi_id);
469         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
470                         pp->dev,
471                         pp->sg_id.host_no,
472                         pp->sg_id.channel,
473                         pp->sg_id.scsi_id,
474                         pp->sg_id.lun);
475
476         return 0;
477 }
478
479 static int
480 cciss_sysfs_pathinfo (struct path * pp, struct sysfs_device * dev)
481 {
482         char attr_path[FILE_NAME_SIZE];
483
484         /*
485          * host / bus / target / lun
486          */
487         basename(dev->devpath, attr_path);
488         pp->sg_id.lun = 0;
489         pp->sg_id.channel = 0;
490         sscanf(attr_path, "cciss!c%id%i",
491                         &pp->sg_id.host_no,
492                         &pp->sg_id.scsi_id);
493         condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
494                         pp->dev,
495                         pp->sg_id.host_no,
496                         pp->sg_id.channel,
497                         pp->sg_id.scsi_id,
498                         pp->sg_id.lun);
499         return 0;
500 }
501
502 static int
503 common_sysfs_pathinfo (struct path * pp, struct sysfs_device *dev)
504 {
505         char *attr;
506
507         attr = sysfs_attr_get_value(dev->devpath, "dev");
508         if (!attr) {
509                 condlog(3, "%s: no 'dev' attribute in sysfs", pp->dev);
510                 return 1;
511         }
512         strlcpy(pp->dev_t, attr, BLK_DEV_SIZE);
513
514         condlog(3, "%s: dev_t = %s", pp->dev, pp->dev_t);
515
516         if (sysfs_get_size(dev, &pp->size))
517                 return 1;
518
519         condlog(3, "%s: size = %llu", pp->dev, pp->size);
520
521         return 0;
522 }
523
524 struct sysfs_device *sysfs_device_from_path(struct path *pp)
525 {
526         char sysdev[FILE_NAME_SIZE];
527
528         strlcpy(sysdev,"/block/", FILE_NAME_SIZE);
529         strlcat(sysdev,pp->dev, FILE_NAME_SIZE);
530
531         return sysfs_device_get(sysdev);
532 }
533
534 extern int
535 sysfs_pathinfo(struct path * pp)
536 {
537         struct sysfs_device *parent;
538
539         pp->sysdev = sysfs_device_from_path(pp);
540         if (!pp->sysdev) {
541                 condlog(1, "%s: failed to get sysfs information", pp->dev);
542                 return 1;
543         }
544
545         if (common_sysfs_pathinfo(pp, pp->sysdev))
546                 return 1;
547
548         parent = sysfs_device_get_parent(pp->sysdev);
549         if (!parent)
550                 parent = pp->sysdev;
551
552         if (!strncmp(parent->kernel, "block",5))
553                 parent = sysfs_device_get_parent(parent);
554
555         condlog(3, "%s: subsystem = %s", pp->dev, parent->subsystem);
556
557         if (!strncmp(parent->subsystem, "scsi",4))
558                 pp->bus = SYSFS_BUS_SCSI;
559         if (!strncmp(parent->subsystem, "ccw",3))
560                 pp->bus = SYSFS_BUS_CCW;
561         if (!strncmp(pp->dev,"cciss",5))
562                 pp->bus = SYSFS_BUS_CCISS;
563
564         if (pp->bus == SYSFS_BUS_UNDEF)
565                 return 0;
566         else if (pp->bus == SYSFS_BUS_SCSI) {
567                 if (scsi_sysfs_pathinfo(pp, parent))
568                         return 1;
569         } else if (pp->bus == SYSFS_BUS_CCW) {
570                 if (ccw_sysfs_pathinfo(pp, parent))
571                         return 1;
572         } else if (pp->bus == SYSFS_BUS_CCISS) {
573                 if (cciss_sysfs_pathinfo(pp, pp->sysdev))
574                         return 1;
575         }
576         return 0;
577 }
578
579 static int
580 scsi_ioctl_pathinfo (struct path * pp, int mask)
581 {
582         if (mask & DI_SERIAL) {
583                 get_serial(pp->serial, SERIAL_SIZE, pp->fd);
584                 condlog(3, "%s: serial = %s", pp->dev, pp->serial);
585         }
586
587         return 0;
588 }
589
590 static int
591 cciss_ioctl_pathinfo (struct path * pp, int mask)
592 {
593         if (mask & DI_SYSFS) {
594                 get_inq(pp->vendor_id, pp->product_id, pp->rev, pp->fd);
595                 condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
596                 condlog(3, "%s: product = %s", pp->dev, pp->product_id);
597                 condlog(3, "%s: revision = %s", pp->dev, pp->rev);
598                 /*
599                  * set the hwe configlet pointer
600                  */
601                 pp->hwe = find_hwe(conf->hwtable, pp->vendor_id,
602                                    pp->product_id, pp->rev);
603
604         }
605         return 0;
606 }
607
608 static int
609 get_state (struct path * pp)
610 {
611         struct checker * c = &pp->checker;
612
613         if (!pp->mpp)
614                 return 0;
615
616         if (!checker_selected(c)) {
617                 select_checker(pp);
618                 if (!checker_selected(c))
619                         return 1;
620                 checker_set_fd(c, pp->fd);
621                 if (checker_init(c, &pp->mpp->mpcontext))
622                         return 1;
623         }
624         pp->state = checker_check(c);
625         condlog(3, "%s: state = %i", pp->dev, pp->state);
626         if (pp->state == PATH_DOWN && strlen(checker_message(c)))
627                 condlog(3, "%s: checker msg is \"%s\"",
628                         pp->dev, checker_message(c));
629         return 0;
630 }
631
632 static int
633 get_prio (struct path * pp)
634 {
635         if (!pp)
636                 return 0;
637
638         if (!pp->prio) {
639                 select_prio(pp);
640                 if (!pp->prio)
641                         return 1;
642         }
643         pp->priority = prio_getprio(pp->prio, pp);
644         if (pp->priority < 0) {
645                 condlog(3, "%s: %s prio error", pp->dev, prio_name(pp->prio));
646                 pp->priority = PRIO_UNDEF;
647                 return 1;
648         }
649         condlog(3, "%s: %s prio = %u",
650                 pp->dev, prio_name(pp->prio), pp->priority);
651         return 0;
652 }
653
654 static int
655 get_uid (struct path * pp)
656 {
657         char buff[CALLOUT_MAX_SIZE];
658
659         if (!pp->getuid)
660                 select_getuid(pp);
661
662         if (apply_format(pp->getuid, &buff[0], pp)) {
663                 condlog(0, "error formatting uid callout command");
664                 memset(pp->wwid, 0, WWID_SIZE);
665         } else if (execute_program(buff, pp->wwid, WWID_SIZE)) {
666                 condlog(3, "error calling out %s", buff);
667                 memset(pp->wwid, 0, WWID_SIZE);
668                 return 1;
669         }
670         condlog(3, "%s: uid = %s (callout)", pp->dev ,pp->wwid);
671         return 0;
672 }
673
674 extern int
675 pathinfo (struct path *pp, vector hwtable, int mask)
676 {
677         condlog(3, "%s: mask = 0x%x", pp->dev, mask);
678
679         /*
680          * fetch info available in sysfs
681          */
682         if (mask & DI_SYSFS && sysfs_pathinfo(pp))
683                 return 1;
684
685         /*
686          * fetch info not available through sysfs
687          */
688         if (pp->fd < 0)
689                 pp->fd = opennode(pp->dev, O_RDONLY);
690
691         if (pp->fd < 0) {
692                 condlog(4, "Couldn't open node for %s: %s",
693                         pp->dev, strerror(errno));
694                 goto blank;
695         }
696
697         if (pp->bus == SYSFS_BUS_SCSI &&
698             scsi_ioctl_pathinfo(pp, mask))
699                 goto blank;
700
701         if (pp->bus == SYSFS_BUS_CCISS &&
702             cciss_ioctl_pathinfo(pp, mask))
703                 goto blank;
704
705         if (mask & DI_CHECKER && get_state(pp))
706                 goto blank;
707
708          /*
709           * Retrieve path priority, even for PATH_DOWN paths if it has never
710           * been successfully obtained before.
711           */
712         if (mask & DI_PRIO &&
713             (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF))
714                 get_prio(pp);
715
716         if (mask & DI_WWID && !strlen(pp->wwid))
717                 get_uid(pp);
718
719         return 0;
720
721 blank:
722         /*
723          * Recoverable error, for example faulty or offline path
724          */
725         memset(pp->wwid, 0, WWID_SIZE);
726         pp->state = PATH_DOWN;
727
728         return 0;
729 }