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"
21 #include "dm-generic.h"
23 struct adapter_group *
24 alloc_adaptergroup(void)
26 struct adapter_group *agp;
28 agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group));
33 agp->host_groups = vector_alloc();
34 if (!agp->host_groups) {
41 void free_adaptergroup(vector adapters)
44 struct adapter_group *agp;
46 vector_foreach_slot(adapters, agp, i) {
47 free_hostgroup(agp->host_groups);
50 vector_free(adapters);
53 void free_hostgroup(vector hostgroups)
56 struct host_group *hgp;
61 vector_foreach_slot(hostgroups, hgp, i) {
62 vector_free(hgp->paths);
65 vector_free(hostgroups);
71 struct host_group *hgp;
73 hgp = (struct host_group *)MALLOC(sizeof(struct host_group));
78 hgp->paths = vector_alloc();
92 pp = (struct path *)MALLOC(sizeof(struct path));
95 pp->sg_id.host_no = -1;
96 pp->sg_id.channel = -1;
97 pp->sg_id.scsi_id = -1;
99 pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
101 pp->tpgs = TPGS_UNDEF;
102 pp->priority = PRIO_UNDEF;
103 checker_clear(&pp->checker);
104 dm_path_to_gen(pp)->ops = &dm_gen_path_ops;
110 free_path (struct path * pp)
115 if (checker_selected(&pp->checker))
116 checker_put(&pp->checker);
118 if (prio_selected(&pp->prio))
125 udev_device_unref(pp->udev);
133 free_pathvec (vector vec, enum free_path_mode free_paths)
141 if (free_paths == FREE_PATHS)
142 vector_foreach_slot(vec, pp, i)
149 alloc_pathgroup (void)
151 struct pathgroup * pgp;
153 pgp = (struct pathgroup *)MALLOC(sizeof(struct pathgroup));
158 pgp->paths = vector_alloc();
165 dm_pathgroup_to_gen(pgp)->ops = &dm_gen_pathgroup_ops;
170 free_pathgroup (struct pathgroup * pgp, enum free_path_mode free_paths)
175 free_pathvec(pgp->paths, free_paths);
180 free_pgvec (vector pgvec, enum free_path_mode free_paths)
183 struct pathgroup * pgp;
188 vector_foreach_slot(pgvec, pgp, i)
189 free_pathgroup(pgp, free_paths);
195 alloc_multipath (void)
197 struct multipath * mpp;
199 mpp = (struct multipath *)MALLOC(sizeof(struct multipath));
203 mpp->mpcontext = NULL;
204 mpp->no_path_retry = NO_PATH_RETRY_UNDEF;
205 mpp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
206 dm_multipath_to_gen(mpp)->ops = &dm_gen_multipath_ops;
211 void free_multipath_attributes(struct multipath *mpp)
218 mpp->selector = NULL;
223 mpp->features = NULL;
226 if (mpp->hwhandler) {
227 FREE(mpp->hwhandler);
228 mpp->hwhandler = NULL;
233 free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
238 free_multipath_attributes(mpp);
250 free_pathvec(mpp->paths, free_paths);
251 free_pgvec(mpp->pg, free_paths);
252 FREE_PTR(mpp->mpcontext);
257 drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths)
260 struct multipath * mpp;
265 vector_foreach_slot (mpvec, mpp, i) {
266 if (!strncmp(mpp->wwid, wwid, WWID_SIZE)) {
267 free_multipath(mpp, free_paths);
268 vector_del_slot(mpvec, i);
275 free_multipathvec (vector mpvec, enum free_path_mode free_paths)
278 struct multipath * mpp;
283 vector_foreach_slot (mpvec, mpp, i)
284 free_multipath(mpp, free_paths);
290 store_path (vector pathvec, struct path * pp)
294 if (!strlen(pp->dev_t)) {
295 condlog(2, "%s: Empty device number", pp->dev);
298 if (!strlen(pp->dev)) {
299 condlog(2, "%s: Empty device name", pp->dev_t);
306 if (!vector_alloc_slot(pathvec))
309 vector_set_slot(pathvec, pp);
315 store_pathgroup (vector pgvec, struct pathgroup * pgp)
317 if (!vector_alloc_slot(pgvec))
320 vector_set_slot(pgvec, pgp);
325 int add_pathgroup(struct multipath *mpp, struct pathgroup *pgp)
327 int ret = store_pathgroup(mpp->pg, pgp);
336 store_hostgroup(vector hostgroupvec, struct host_group * hgp)
338 if (!vector_alloc_slot(hostgroupvec))
341 vector_set_slot(hostgroupvec, hgp);
346 store_adaptergroup(vector adapters, struct adapter_group * agp)
348 if (!vector_alloc_slot(adapters))
351 vector_set_slot(adapters, agp);
356 find_mp_by_minor (vector mpvec, int minor)
359 struct multipath * mpp;
364 vector_foreach_slot (mpvec, mpp, i) {
368 if (mpp->dmi->minor == minor)
375 find_mp_by_wwid (vector mpvec, char * wwid)
378 struct multipath * mpp;
383 vector_foreach_slot (mpvec, mpp, i)
384 if (!strncmp(mpp->wwid, wwid, WWID_SIZE))
391 find_mp_by_alias (vector mpvec, const char * alias)
395 struct multipath * mpp;
405 vector_foreach_slot (mpvec, mpp, i) {
406 if (strlen(mpp->alias) == len &&
407 !strncmp(mpp->alias, alias, len))
414 find_mp_by_str (vector mpvec, char * str)
418 if (sscanf(str, "dm-%d", &minor) == 1)
419 return find_mp_by_minor(mpvec, minor);
421 return find_mp_by_alias(mpvec, str);
425 find_path_by_dev (vector pathvec, const char * dev)
433 vector_foreach_slot (pathvec, pp, i)
434 if (!strcmp(pp->dev, dev))
437 condlog(4, "%s: dev not found in pathvec", dev);
442 find_path_by_devt (vector pathvec, const char * dev_t)
450 vector_foreach_slot (pathvec, pp, i)
451 if (!strcmp(pp->dev_t, dev_t))
454 condlog(4, "%s: dev_t not found in pathvec", dev_t);
458 int pathcountgr(struct pathgroup *pgp, int state)
464 vector_foreach_slot (pgp->paths, pp, i)
465 if ((pp->state == state) || (state == PATH_WILD))
471 int pathcount(struct multipath *mpp, int state)
473 struct pathgroup *pgp;
478 vector_foreach_slot (mpp->pg, pgp, i)
479 count += pathcountgr(pgp, state);
484 int pathcmp(struct pathgroup *pgp, struct pathgroup *cpgp)
487 struct path *pp, *cpp;
488 int pnum = 0, found = 0;
490 vector_foreach_slot(pgp->paths, pp, i) {
492 vector_foreach_slot(cpgp->paths, cpp, j) {
493 if ((long)pp == (long)cpp) {
504 first_path (struct multipath * mpp)
506 struct pathgroup * pgp;
509 pgp = VECTOR_SLOT(mpp->pg, 0);
511 return pgp?VECTOR_SLOT(pgp->paths, 0):NULL;
514 int add_feature(char **f, const char *n)
526 if (strchr(n, ' ') != NULL) {
527 condlog(0, "internal error: feature \"%s\" contains spaces", n);
531 /* default feature is null */
534 l = asprintf(&t, "1 %s", n);
542 /* Check if feature is already present */
546 /* Get feature count */
547 c = strtoul(*f, &e, 10);
548 if (*f == e || (*e != ' ' && *e != '\0')) {
549 condlog(0, "parse error in feature string \"%s\"", *f);
553 /* Add 1 digit and 1 space */
554 l = strlen(e) + strlen(n) + 2;
557 /* Check if we need more digits for feature count */
558 for (d = c; d >= 10; d /= 10)
565 /* e: old feature string with leading space, or "" */
567 while (*(e + 1) == ' ')
570 snprintf(t, l + 1, "%0d%s %s", c, e, n);
578 int remove_feature(char **f, const char *o)
588 if (!o || *o == '\0')
591 /* Check if not present */
595 /* Get feature count */
596 c = strtoul(*f, &e, 10);
601 /* Normalize features */
605 /* Just spaces, return */
613 /* Update feature count */
616 while (q[0] != '\0') {
617 if (q[0] == ' ' && q[1] != ' ' && q[1] != '\0')
622 /* Quick exit if all features have been removed */
631 /* Search feature to be removed */
634 /* Not found, return */
637 /* Update feature count space */
643 /* Copy the feature count */
644 sprintf(n, "%0d", c);
646 * Copy existing features up to the feature
647 * about to be removed
651 /* Internal error, feature string inconsistent */
664 strncat(n, p, (size_t)(e - p));
665 p += (size_t)(e - p);
667 /* Skip feature to be removed */
670 /* Copy remaining features */