2 * Copyright (c) 2004, 2005 Christophe Varoqui
3 * Copyright (c) 2005 Stefan Bader, IBM
4 * Copyright (c) 2005 Edward Goggin, EMC
22 merge_words(char **dst, const char *word)
27 dstlen = strlen(*dst);
28 len = dstlen + strlen(word) + 2;
29 *dst = realloc(*dst, len);
39 strncpy(p, word, len - dstlen - 1);
45 * Transforms the path group vector into a proper device map string
47 int assemble_map(struct multipath *mp, char **params)
49 static const char no_path_retry[] = "queue_if_no_path";
50 static const char retain_hwhandler[] = "retain_attached_hw_handler";
53 int nr_priority_groups, initial_pg_nr;
54 STRBUF_ON_STACK(buff);
55 struct pathgroup * pgp;
60 nr_priority_groups = VECTOR_SIZE(mp->pg);
61 initial_pg_nr = (nr_priority_groups ? mp->bestpg : 0);
63 if (mp->no_path_retry != NO_PATH_RETRY_UNDEF &&
64 mp->no_path_retry != NO_PATH_RETRY_FAIL) {
65 add_feature(&mp->features, no_path_retry);
67 if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON &&
68 get_linux_version_code() < KERNEL_VERSION(4, 3, 0))
69 add_feature(&mp->features, retain_hwhandler);
71 if (print_strbuf(&buff, "%s %s %i %i", mp->features, mp->hwhandler,
72 nr_priority_groups, initial_pg_nr) < 0)
75 vector_foreach_slot (mp->pg, pgp, i) {
76 pgp = VECTOR_SLOT(mp->pg, i);
77 if (print_strbuf(&buff, " %s %i 1", mp->selector,
78 VECTOR_SIZE(pgp->paths)) < 0)
81 vector_foreach_slot (pgp->paths, pp, j) {
82 int tmp_minio = minio;
84 if (mp->rr_weight == RR_WEIGHT_PRIO
86 tmp_minio = minio * pp->priority;
87 if (!strlen(pp->dev_t) ) {
88 condlog(0, "dev_t not set for '%s'", pp->dev);
91 if (print_strbuf(&buff, " %s %d", pp->dev_t, tmp_minio) < 0)
96 *params = steal_strbuf_str(&buff);
97 condlog(4, "%s: assembled map [%s]", mp->alias, *params);
105 * Caution callers: If this function encounters yet unkown path devices, it
106 * adds them uninitialized to the mpp.
107 * Call update_pathvec_from_dm() after this function to make sure
108 * all data structures are in a sane state.
110 int disassemble_map(const struct _vector *pathvec,
111 const char *params, struct multipath *mpp)
116 int num_features = 0;
117 int num_hwhandler = 0;
121 int num_paths_args = 0;
124 struct pathgroup * pgp;
126 assert(pathvec != NULL);
129 condlog(4, "%s: disassemble map [%s]", mpp->alias, params);
134 p += get_word(p, &mpp->features);
139 num_features = atoi(mpp->features);
141 for (i = 0; i < num_features; i++) {
142 p += get_word(p, &word);
147 if (merge_words(&mpp->features, word)) {
158 p += get_word(p, &mpp->hwhandler);
163 num_hwhandler = atoi(mpp->hwhandler);
165 for (i = 0; i < num_hwhandler; i++) {
166 p += get_word(p, &word);
171 if (merge_words(&mpp->hwhandler, word)) {
181 p += get_word(p, &word);
191 mpp->pg = vector_alloc();
196 free_pgvec(mpp->pg, KEEP_PATHS);
203 p += get_word(p, &word);
208 mpp->nextpg = atoi(word);
211 for (i = 0; i < num_pg; i++) {
216 if (!mpp->selector) {
217 p += get_word(p, &mpp->selector);
225 p += get_word(p, &word);
230 num_pg_args = atoi(word);
232 if (merge_words(&mpp->selector, word))
236 p += get_word(p, NULL);
237 p += get_word(p, NULL);
240 for (j = 0; j < num_pg_args; j++)
241 p += get_word(p, NULL);
246 pgp = alloc_pathgroup();
251 if (add_pathgroup(mpp, pgp)) {
252 free_pathgroup(pgp, KEEP_PATHS);
256 p += get_word(p, &word);
261 num_paths = atoi(word);
264 p += get_word(p, &word);
269 num_paths_args = atoi(word);
272 for (j = 0; j < num_paths; j++) {
274 p += get_word(p, &word);
279 pp = find_path_by_devt(pathvec, word);
287 strlcpy(pp->dev_t, word, BLK_DEV_SIZE);
289 if (store_path(pgp->paths, pp)) {
293 } else if (store_path(pgp->paths, pp))
301 for (k = 0; k < num_paths_args; k++)
303 p += get_word(p, &word);
304 def_minio = atoi(word);
307 if (!strncmp(mpp->selector,
308 "round-robin", 11)) {
310 if (mpp->rr_weight == RR_WEIGHT_PRIO
312 def_minio /= pp->priority;
316 if (def_minio != mpp->minio)
317 mpp->minio = def_minio;
320 p += get_word(p, NULL);
328 free_pgvec(mpp->pg, KEEP_PATHS);
333 int disassemble_status(const char *params, struct multipath *mpp)
338 int num_feature_args;
339 int num_hwhandler_args;
345 struct pathgroup * pgp;
349 condlog(4, "%s: disassemble status [%s]", mpp->alias, params);
354 p += get_word(p, &word);
359 num_feature_args = atoi(word);
362 for (i = 0; i < num_feature_args; i++) {
364 p += get_word(p, &word);
369 mpp->queuedio = atoi(word);
374 p += get_word(p, NULL);
379 p += get_word(p, &word);
384 num_hwhandler_args = atoi(word);
387 for (i = 0; i < num_hwhandler_args; i++)
388 p += get_word(p, NULL);
393 p += get_word(p, &word);
407 p += get_word(p, NULL);
409 if (VECTOR_SIZE(mpp->pg) < num_pg)
412 for (i = 0; i < num_pg; i++) {
413 pgp = VECTOR_SLOT(mpp->pg, i);
417 p += get_word(p, &word);
424 pgp->status = PGSTATE_DISABLED;
427 pgp->status = PGSTATE_ACTIVE;
430 pgp->status = PGSTATE_ENABLED;
433 pgp->status = PGSTATE_UNDEF;
439 * PG Status (discarded, would be '0' anyway)
441 p += get_word(p, NULL);
443 p += get_word(p, &word);
448 num_paths = atoi(word);
451 p += get_word(p, &word);
456 num_pg_args = atoi(word);
459 if (VECTOR_SIZE(pgp->paths) < num_paths)
462 for (j = 0; j < num_paths; j++) {
463 pp = VECTOR_SLOT(pgp->paths, j);
467 p += get_word(p, NULL);
472 p += get_word(p, &word);
479 pp->dmstate = PSTATE_FAILED;
482 pp->dmstate = PSTATE_ACTIVE;
491 p += get_word(p, &word);
496 pp->failcount = atoi(word);
502 for (k = 0; k < num_pg_args; k++) {
503 if (!strncmp(mpp->selector,
504 "least-pending", 13)) {
505 p += get_word(p, &word);
506 if (sscanf(word,"%d:*d",
508 def_minio != mpp->minio)
509 mpp->minio = def_minio;
512 p += get_word(p, NULL);