2 * Copyright (c) 2004, 2005 Christophe Varoqui
3 * Copyright (c) 2004 Stefan Bader, IBM
7 #include <libdevmapper.h>
17 #include "structs_vec.h"
18 #include "blacklist.h"
20 #include "prioritizers/alua_spc3.h"
22 struct adapter_group *
23 alloc_adaptergroup(void)
25 struct adapter_group *agp;
27 agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group));
32 agp->host_groups = vector_alloc();
33 if (!agp->host_groups) {
40 void free_adaptergroup(vector adapters)
43 struct adapter_group *agp;
45 vector_foreach_slot(adapters, agp, i) {
46 free_hostgroup(agp->host_groups);
49 vector_free(adapters);
52 void free_hostgroup(vector hostgroups)
55 struct host_group *hgp;
60 vector_foreach_slot(hostgroups, hgp, i) {
61 vector_free(hgp->paths);
64 vector_free(hostgroups);
70 struct host_group *hgp;
72 hgp = (struct host_group *)MALLOC(sizeof(struct host_group));
77 hgp->paths = vector_alloc();
91 pp = (struct path *)MALLOC(sizeof(struct path));
94 pp->sg_id.host_no = -1;
95 pp->sg_id.channel = -1;
96 pp->sg_id.scsi_id = -1;
98 pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
100 pp->tpgs = TPGS_UNDEF;
101 pp->priority = PRIO_UNDEF;
102 checker_clear(&pp->checker);
108 free_path (struct path * pp)
113 if (checker_selected(&pp->checker))
114 checker_put(&pp->checker);
116 if (prio_selected(&pp->prio))
123 udev_device_unref(pp->udev);
131 free_pathvec (vector vec, enum free_path_mode free_paths)
139 if (free_paths == FREE_PATHS)
140 vector_foreach_slot(vec, pp, i)
147 alloc_pathgroup (void)
149 struct pathgroup * pgp;
151 pgp = (struct pathgroup *)MALLOC(sizeof(struct pathgroup));
156 pgp->paths = vector_alloc();
167 free_pathgroup (struct pathgroup * pgp, enum free_path_mode free_paths)
172 free_pathvec(pgp->paths, free_paths);
177 free_pgvec (vector pgvec, enum free_path_mode free_paths)
180 struct pathgroup * pgp;
185 vector_foreach_slot(pgvec, pgp, i)
186 free_pathgroup(pgp, free_paths);
192 alloc_multipath (void)
194 struct multipath * mpp;
196 mpp = (struct multipath *)MALLOC(sizeof(struct multipath));
200 mpp->mpcontext = NULL;
201 mpp->no_path_retry = NO_PATH_RETRY_UNDEF;
202 mpp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
207 void free_multipath_attributes(struct multipath *mpp)
214 mpp->selector = NULL;
219 mpp->features = NULL;
222 if (mpp->hwhandler) {
223 FREE(mpp->hwhandler);
224 mpp->hwhandler = NULL;
229 free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
234 free_multipath_attributes(mpp);
246 free_pathvec(mpp->paths, free_paths);
247 free_pgvec(mpp->pg, free_paths);
248 FREE_PTR(mpp->mpcontext);
253 drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths)
256 struct multipath * mpp;
261 vector_foreach_slot (mpvec, mpp, i) {
262 if (!strncmp(mpp->wwid, wwid, WWID_SIZE)) {
263 free_multipath(mpp, free_paths);
264 vector_del_slot(mpvec, i);
271 free_multipathvec (vector mpvec, enum free_path_mode free_paths)
274 struct multipath * mpp;
279 vector_foreach_slot (mpvec, mpp, i)
280 free_multipath(mpp, free_paths);
286 store_path (vector pathvec, struct path * pp)
290 if (!strlen(pp->dev_t)) {
291 condlog(2, "%s: Empty device number", pp->dev);
294 if (!strlen(pp->dev)) {
295 condlog(2, "%s: Empty device name", pp->dev_t);
302 if (!vector_alloc_slot(pathvec))
305 vector_set_slot(pathvec, pp);
311 store_pathgroup (vector pgvec, struct pathgroup * pgp)
313 if (!vector_alloc_slot(pgvec))
316 vector_set_slot(pgvec, pgp);
322 store_hostgroup(vector hostgroupvec, struct host_group * hgp)
324 if (!vector_alloc_slot(hostgroupvec))
327 vector_set_slot(hostgroupvec, hgp);
332 store_adaptergroup(vector adapters, struct adapter_group * agp)
334 if (!vector_alloc_slot(adapters))
337 vector_set_slot(adapters, agp);
342 find_mp_by_minor (vector mpvec, int minor)
345 struct multipath * mpp;
350 vector_foreach_slot (mpvec, mpp, i) {
354 if (mpp->dmi->minor == minor)
361 find_mp_by_wwid (vector mpvec, char * wwid)
364 struct multipath * mpp;
369 vector_foreach_slot (mpvec, mpp, i)
370 if (!strncmp(mpp->wwid, wwid, WWID_SIZE))
377 find_mp_by_alias (vector mpvec, char * alias)
381 struct multipath * mpp;
391 vector_foreach_slot (mpvec, mpp, i) {
392 if (strlen(mpp->alias) == len &&
393 !strncmp(mpp->alias, alias, len))
400 find_mp_by_str (vector mpvec, char * str)
404 if (sscanf(str, "dm-%d", &minor) == 1)
405 return find_mp_by_minor(mpvec, minor);
407 return find_mp_by_alias(mpvec, str);
411 find_path_by_dev (vector pathvec, char * dev)
419 vector_foreach_slot (pathvec, pp, i)
420 if (!strcmp(pp->dev, dev))
423 condlog(4, "%s: dev not found in pathvec", dev);
428 find_path_by_devt (vector pathvec, char * dev_t)
436 vector_foreach_slot (pathvec, pp, i)
437 if (!strcmp(pp->dev_t, dev_t))
440 condlog(4, "%s: dev_t not found in pathvec", dev_t);
444 int pathcountgr(struct pathgroup *pgp, int state)
450 vector_foreach_slot (pgp->paths, pp, i)
451 if ((pp->state == state) || (state == PATH_WILD))
457 int pathcount(struct multipath *mpp, int state)
459 struct pathgroup *pgp;
464 vector_foreach_slot (mpp->pg, pgp, i)
465 count += pathcountgr(pgp, state);
470 int pathcmp(struct pathgroup *pgp, struct pathgroup *cpgp)
473 struct path *pp, *cpp;
474 int pnum = 0, found = 0;
476 vector_foreach_slot(pgp->paths, pp, i) {
478 vector_foreach_slot(cpgp->paths, cpp, j) {
479 if ((long)pp == (long)cpp) {
490 first_path (struct multipath * mpp)
492 struct pathgroup * pgp;
495 pgp = VECTOR_SLOT(mpp->pg, 0);
497 return pgp?VECTOR_SLOT(pgp->paths, 0):NULL;
500 void setup_feature(struct multipath *mpp, char *feature)
502 if (!strncmp(feature, "queue_if_no_path", 16)) {
503 if (mpp->no_path_retry <= NO_PATH_RETRY_UNDEF)
504 mpp->no_path_retry = NO_PATH_RETRY_QUEUE;
506 condlog(1, "%s: ignoring feature queue_if_no_path because no_path_retry = %d",
507 mpp->alias, mpp->no_path_retry);
508 } else if (!strcmp(feature, "retain_attached_hw_handler")) {
509 if (mpp->retain_hwhandler != RETAIN_HWHANDLER_OFF)
510 mpp->retain_hwhandler = RETAIN_HWHANDLER_ON;
512 condlog(1, "%s: ignoring feature 'retain_attached_hw_handler'",
517 int add_feature(char **f, const char *n)
529 if (strchr(n, ' ') != NULL) {
530 condlog(0, "internal error: feature \"%s\" contains spaces", n);
534 /* default feature is null */
537 l = asprintf(&t, "1 %s", n);
545 /* Check if feature is already present */
549 /* Get feature count */
550 c = strtoul(*f, &e, 10);
551 if (*f == e || (*e != ' ' && *e != '\0')) {
552 condlog(0, "parse error in feature string \"%s\"", *f);
556 /* Add 1 digit and 1 space */
557 l = strlen(e) + strlen(n) + 2;
560 /* Check if we need more digits for feature count */
561 for (d = c; d >= 10; d /= 10)
568 /* e: old feature string with leading space, or "" */
570 while (*(e + 1) == ' ')
573 snprintf(t, l + 1, "%0d%s %s", c, e, n);
581 int remove_feature(char **f, const char *o)
591 if (!o || *o == '\0')
594 /* Check if not present */
598 /* Get feature count */
599 c = strtoul(*f, &e, 10);
604 /* Normalize features */
608 /* Just spaces, return */
616 /* Update feature count */
619 while (q[0] != '\0') {
620 if (q[0] == ' ' && q[1] != ' ' && q[1] != '\0')
625 /* Quick exit if all features have been removed */
634 /* Search feature to be removed */
637 /* Not found, return */
640 /* Update feature count space */
646 /* Copy the feature count */
647 sprintf(n, "%0d", c);
649 * Copy existing features up to the feature
650 * about to be removed
654 /* Internal error, feature string inconsistent */
667 strncat(n, p, (size_t)(e - p));
668 p += (size_t)(e - p);
670 /* Skip feature to be removed */
673 /* Copy remaining features */