STRBUF_ON_STACK() uses the cleanup __attribute__, which doesn't get run if a thread is cancelled. condlog() will call fprintf() when run under systemd, which is a cancellation point. The snprint function for the generic mutipath and generic path operations both call cancellation points. Also, the keyword print functions can call cancellation points. Because of all this, I did not see any safe uses of STRBUF_ON_STACK() outside of the unit tests. Replace them all with pthread cleanup handlers. Signed-off-by: Benjamin Marzinski <bmarzins@xxxxxxxxxx> --- libmpathutil/parser.c | 5 +- libmpathutil/strbuf.h | 4 +- libmultipath/alias.c | 59 +++++++++++------- libmultipath/blacklist.c | 4 +- libmultipath/discovery.c | 34 +++++++---- libmultipath/dmparser.c | 21 +++---- libmultipath/foreign.c | 4 +- libmultipath/generic.c | 10 +++- libmultipath/print.c | 50 ++++++++++------ libmultipath/prioritizers/weightedpath.c | 16 ++--- libmultipath/propsel.c | 76 ++++++++++++++++++------ libmultipath/sysfs.h | 11 +--- libmultipath/uevent.c | 6 +- 13 files changed, 195 insertions(+), 105 deletions(-) diff --git a/libmpathutil/parser.c b/libmpathutil/parser.c index 8d3ac53a..04c65b51 100644 --- a/libmpathutil/parser.c +++ b/libmpathutil/parser.c @@ -25,6 +25,7 @@ #include "parser.h" #include "debug.h" #include "strbuf.h" +#include "util.h" /* local vars */ static int sublevel = 0; @@ -155,11 +156,12 @@ snprint_keyword(struct strbuf *buff, const char *fmt, struct keyword *kw, int r = 0; char *f; struct config *conf; - STRBUF_ON_STACK(sbuf); + struct strbuf sbuf = STRBUF_INIT; if (!kw || !kw->print) return 0; + pthread_cleanup_push_cast(reset_strbuf, &sbuf); do { f = strchr(fmt, '%'); if (f == NULL) { @@ -193,6 +195,7 @@ out: if (r >= 0) r = __append_strbuf_str(buff, get_strbuf_str(&sbuf), get_strbuf_len(&sbuf)); + pthread_cleanup_pop(1); return r; } diff --git a/libmpathutil/strbuf.h b/libmpathutil/strbuf.h index ae863417..5aa54677 100644 --- a/libmpathutil/strbuf.h +++ b/libmpathutil/strbuf.h @@ -42,7 +42,9 @@ void free_strbuf(struct strbuf *buf); * macro: STRBUF_ON_STACK * * Define and initialize a local struct @strbuf to be cleaned up when - * the current scope is left + * the current scope is left. This can only be used in non-threaded + * programs, or if there are no pthread cancellation points in the + * current scope, after the buffer could first be used. */ #define STRBUF_ON_STACK(__x) \ struct strbuf __attribute__((cleanup(reset_strbuf))) (__x) = STRBUF_INIT; diff --git a/libmultipath/alias.c b/libmultipath/alias.c index 05201224..3a81a7ad 100644 --- a/libmultipath/alias.c +++ b/libmultipath/alias.c @@ -112,12 +112,14 @@ scan_devname(const char *alias, const char *prefix) static int id_already_taken(int id, const char *prefix, const char *map_wwid) { - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; const char *alias; + int r = 0; + pthread_cleanup_push_cast(reset_strbuf, &buf); if (append_strbuf_str(&buf, prefix) < 0 || format_devname(&buf, id) < 0) - return 0; + goto out; alias = get_strbuf_str(&buf); if (dm_map_present(alias)) { @@ -126,11 +128,13 @@ id_already_taken(int id, const char *prefix, const char *map_wwid) /* If both the name and the wwid match, then it's fine.*/ if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && strncmp(map_wwid, wwid, sizeof(wwid)) == 0) - return 0; + goto out; condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", map_wwid, alias); - return 1; + r = 1; } - return 0; +out: + pthread_cleanup_pop(1); + return r; } @@ -277,10 +281,12 @@ rlookup_binding(FILE *f, char *buff, const char *map_alias) static char * allocate_binding(int fd, const char *wwid, int id, const char *prefix) { - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; off_t offset; ssize_t len; - char *alias, *c; + char *alias = NULL; + const char *str; + int end; if (id <= 0) { condlog(0, "%s: cannot allocate new binding for id %d", @@ -288,38 +294,41 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix) return NULL; } + pthread_cleanup_push_cast(reset_strbuf, &buf); if (append_strbuf_str(&buf, prefix) < 0 || format_devname(&buf, id) == -1) - return NULL; + goto out; if (print_strbuf(&buf, " %s\n", wwid) < 0) - return NULL; + goto out; offset = lseek(fd, 0, SEEK_END); if (offset < 0){ condlog(0, "Cannot seek to end of bindings file : %s", strerror(errno)); - return NULL; + goto out; } len = get_strbuf_len(&buf); - alias = steal_strbuf_str(&buf); + str = get_strbuf_str(&buf); - if (write(fd, alias, len) != len) { + if (write(fd, str, len) != len) { condlog(0, "Cannot write binding to bindings file : %s", strerror(errno)); /* clear partial write */ if (ftruncate(fd, offset)) condlog(0, "Cannot truncate the header : %s", strerror(errno)); - free(alias); - return NULL; + goto out; } - c = strchr(alias, ' '); - if (c) - *c = '\0'; + end = strcspn(str, " "); - condlog(3, "Created new binding [%s] for WWID [%s]", alias, wwid); + condlog(3, "Created new binding [%.*s] for WWID [%s]", end, str, wwid); + alias = steal_strbuf_str(&buf); + + alias[len] = '\0'; +out: + pthread_cleanup_pop(1); return alias; } @@ -549,24 +558,28 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) static int write_bindings_file(const Bindings *bindings, int fd) { struct binding *bnd; - STRBUF_ON_STACK(line); - int i; + struct strbuf line = STRBUF_INIT; + int i, r = -1; if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) != sizeof(BINDINGS_FILE_HEADER) - 1) return -1; + pthread_cleanup_push_cast(reset_strbuf, &line); vector_foreach_slot(bindings, bnd, i) { int len; if ((len = print_strbuf(&line, "%s %s\n", bnd->alias, bnd->wwid)) < 0) - return -1; + goto out; if (write(fd, get_strbuf_str(&line), len) != len) - return -1; + goto out; truncate_strbuf(&line, 0); } - return 0; + r = 0; +out: + pthread_cleanup_pop(1); + return r; } static int fix_bindings_file(const struct config *conf, diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c index 8d15d2ea..7e0b036a 100644 --- a/libmultipath/blacklist.c +++ b/libmultipath/blacklist.c @@ -341,11 +341,12 @@ int filter_protocol(const struct _vector *blist, const struct _vector *elist, const struct path *pp) { - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; const char *prot; int r = MATCH_NOTHING; if (pp) { + pthread_cleanup_push_cast(reset_strbuf, &buf); snprint_path_protocol(&buf, pp); prot = get_strbuf_str(&buf); @@ -354,6 +355,7 @@ filter_protocol(const struct _vector *blist, const struct _vector *elist, else if (match_reglist(blist, prot)) r = MATCH_PROTOCOL_BLIST; log_filter(pp->dev, NULL, NULL, NULL, NULL, prot, r, 3); + pthread_cleanup_pop(1); } return r; diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index f3fccedd..32181259 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -838,13 +838,15 @@ static void scsi_tmo_error_msg(struct path *pp) { STATIC_BITFIELD(bf, LAST_BUS_PROTOCOL_ID + 1); - STRBUF_ON_STACK(proto_buf); + struct strbuf proto_buf = STRBUF_INIT; unsigned int proto_id = bus_protocol_id(pp); + pthread_cleanup_push_cast(reset_strbuf, &proto_buf); snprint_path_protocol(&proto_buf, pp); condlog(2, "%s: setting scsi timeouts is unsupported for protocol %s", pp->dev, get_strbuf_str(&proto_buf)); set_bit_in_bitfield(proto_id, bf); + pthread_cleanup_pop(1); } int @@ -1142,12 +1144,13 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, size_t len, vpd_len, i; int vpd_type, prio = -1; int err = -ENODATA; - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; /* Need space at least for one digit */ if (out_len <= 1) return 0; + pthread_cleanup_push_cast(reset_strbuf, &buf); d = in + 4; while (d <= in + in_len - 4) { bool invalid = false; @@ -1241,8 +1244,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, } if (prio <= 0) - return err; + goto out; + err = 0; if (d != in + in_len) /* Should this be fatal? (overflow covered above) */ condlog(2, "%s: warning: last descriptor end %zd != VPD length %zu", @@ -1262,10 +1266,10 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, size_t i; if ((err = print_strbuf(&buf, "%d", vpd_type)) < 0) - return err; + goto out; for (i = 0; i < vpd_len; i++) if ((err = print_strbuf(&buf, "%02x", vpd[i])) < 0) - return err; + goto out; } else if (vpd_type == 0x8) { char type; @@ -1276,12 +1280,12 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, else type = '8'; if ((err = fill_strbuf(&buf, type, 1)) < 0) - return err; + goto out; vpd += 4; len = vpd_len - 4; if ((err = __append_strbuf_str(&buf, (const char *)vpd, len)) < 0) - return err; + goto out; /* The input is 0-padded, make sure the length is correct */ truncate_strbuf(&buf, strlen(get_strbuf_str(&buf))); @@ -1298,12 +1302,12 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, size_t p_len; if ((err = fill_strbuf(&buf, '1', 1)) < 0) - return err; + goto out; while (vpd && (p = memchr(vpd, ' ', vpd_len))) { p_len = p - vpd; if ((err = __append_strbuf_str(&buf, (const char *)vpd, p_len)) < 0) - return err; + goto out; vpd = p; vpd_len -= p_len; while (vpd && vpd_len > 0 && *vpd == ' ') { @@ -1311,12 +1315,12 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, vpd_len --; } if (vpd_len > 0 && (err = fill_strbuf(&buf, '_', 1)) < 0) - return err; + goto out; } if (vpd_len > 0) { if ((err = __append_strbuf_str(&buf, (const char *)vpd, vpd_len)) < 0) - return err; + goto out; } } @@ -1331,6 +1335,10 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, len = out_len - 1; } strlcpy(out, get_strbuf_str(&buf), len + 1); +out: + pthread_cleanup_pop(1); + if (err) + return err; return len; } @@ -2435,11 +2443,13 @@ int pathinfo(struct path *pp, struct config *conf, int mask) * It's likely that this path is not fit for * multipath use. */ - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; + pthread_cleanup_push_cast(reset_strbuf, &buf); snprint_path(&buf, "%T", pp, 0); condlog(1, "%s: no WWID in state \"%s\", giving up", pp->dev, get_strbuf_str(&buf)); + pthread_cleanup_pop(1); return PATHINFO_SKIPPED; } return PATHINFO_OK; diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c index 3b37a926..44650aaa 100644 --- a/libmultipath/dmparser.c +++ b/libmultipath/dmparser.c @@ -48,10 +48,10 @@ int assemble_map(struct multipath *mp, char **params) { static const char no_path_retry[] = "queue_if_no_path"; static const char retain_hwhandler[] = "retain_attached_hw_handler"; - int i, j; + int i, j, r = 1; int minio; int nr_priority_groups, initial_pg_nr; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; struct pathgroup * pgp; struct path * pp; @@ -68,15 +68,16 @@ int assemble_map(struct multipath *mp, char **params) get_linux_version_code() < KERNEL_VERSION(4, 3, 0)) add_feature(&mp->features, retain_hwhandler); + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_strbuf(&buff, "%s %s %i %i", mp->features, mp->hwhandler, nr_priority_groups, initial_pg_nr) < 0) - goto err; + goto out; vector_foreach_slot (mp->pg, pgp, i) { pgp = VECTOR_SLOT(mp->pg, i); if (print_strbuf(&buff, " %s %i 1", mp->selector, VECTOR_SIZE(pgp->paths)) < 0) - goto err; + goto out; vector_foreach_slot (pgp->paths, pp, j) { int tmp_minio = minio; @@ -86,19 +87,19 @@ int assemble_map(struct multipath *mp, char **params) tmp_minio = minio * pp->priority; if (!strlen(pp->dev_t) ) { condlog(0, "dev_t not set for '%s'", pp->dev); - goto err; + goto out; } if (print_strbuf(&buff, " %s %d", pp->dev_t, tmp_minio) < 0) - goto err; + goto out; } } *params = steal_strbuf_str(&buff); condlog(4, "%s: assembled map [%s]", mp->alias, *params); - return 0; - -err: - return 1; + r = 0; +out: + pthread_cleanup_pop(1); + return r; } /* diff --git a/libmultipath/foreign.c b/libmultipath/foreign.c index d01a5ef0..8981ff58 100644 --- a/libmultipath/foreign.c +++ b/libmultipath/foreign.c @@ -547,7 +547,7 @@ int snprint_foreign_topology(struct strbuf *buf, int verbosity, void print_foreign_topology(int verbosity) { - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; struct foreign *fgn; int i; fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL; @@ -559,6 +559,7 @@ void print_foreign_topology(int verbosity) unlock_foreigns(NULL); return; } + pthread_cleanup_push_cast(reset_strbuf, &buf); pthread_cleanup_push(unlock_foreigns, NULL); vector_foreach_slot(foreigns, fgn, i) { const struct _vector *vec; @@ -573,6 +574,7 @@ void print_foreign_topology(int verbosity) __snprint_foreign_topology(&buf, verbosity, width); pthread_cleanup_pop(1); printf("%s", get_strbuf_str(&buf)); + pthread_cleanup_pop(1); } int snprint_foreign_paths(struct strbuf *buf, const char *style, diff --git a/libmultipath/generic.c b/libmultipath/generic.c index e7cf2975..3e2268e6 100644 --- a/libmultipath/generic.c +++ b/libmultipath/generic.c @@ -23,15 +23,19 @@ int generic_style(const struct gen_multipath* gm, struct strbuf *buf, __attribute__((unused)) int verbosity) { - STRBUF_ON_STACK(tmp); + struct strbuf tmp = STRBUF_INIT; char *alias_buf __attribute__((cleanup(cleanup_charp))); const char *wwid_buf; + int ret; + pthread_cleanup_push_cast(reset_strbuf, &tmp); gm->ops->snprint(gm, &tmp, 'n'); alias_buf = steal_strbuf_str(&tmp); gm->ops->snprint(gm, &tmp, 'w'); wwid_buf = get_strbuf_str(&tmp); - return print_strbuf(buf, "%%n %s[%%G]:%%d %%s", - strcmp(alias_buf, wwid_buf) ? "(%w) " : ""); + ret = print_strbuf(buf, "%%n %s[%%G]:%%d %%s", + strcmp(alias_buf, wwid_buf) ? "(%w) " : ""); + pthread_cleanup_pop(1); + return ret; } diff --git a/libmultipath/print.c b/libmultipath/print.c index d7d522c8..97f9a177 100644 --- a/libmultipath/print.c +++ b/libmultipath/print.c @@ -911,19 +911,21 @@ void _get_path_layout (const struct _vector *gpvec, enum layout_reset reset, return; for (j = 0; j < ARRAY_SIZE(pd); j++) { - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; reset_width(&width[j], reset, pd[j].header); if (gpvec == NULL) continue; + pthread_cleanup_push_cast(reset_strbuf, &buff); vector_foreach_slot (gpvec, gp, i) { gp->ops->snprint(gp, &buff, pd[j].wildcard); width[j] = MAX(width[j], MIN(get_strbuf_len(&buff), MAX_FIELD_WIDTH)); truncate_strbuf(&buff, 0); } + pthread_cleanup_pop(1); } } @@ -951,19 +953,21 @@ _get_multipath_layout (const struct _vector *gmvec, enum layout_reset reset, if (width == NULL) return; for (j = 0; j < ARRAY_SIZE(mpd); j++) { - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; reset_width(&width[j], reset, mpd[j].header); if (gmvec == NULL) continue; + pthread_cleanup_push_cast(reset_strbuf, &buff); vector_foreach_slot (gmvec, gm, i) { gm->ops->snprint(gm, &buff, mpd[j].wildcard); width[j] = MAX(width[j], MIN(get_strbuf_len(&buff), MAX_FIELD_WIDTH)); truncate_strbuf(&buff, 0); } + pthread_cleanup_pop(1); condlog(4, "%s: width %d", mpd[j].header, width[j]); } } @@ -1182,7 +1186,7 @@ int _snprint_pathgroup(const struct gen_pathgroup *ggp, struct strbuf *line, void _print_multipath_topology(const struct gen_multipath *gmp, int verbosity) { - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; fieldwidth_t *p_width __attribute__((cleanup(cleanup_ucharp))) = NULL; const struct gen_pathgroup *gpg; const struct _vector *pgvec, *pathvec; @@ -1202,8 +1206,10 @@ void _print_multipath_topology(const struct gen_multipath *gmp, int verbosity) gmp->ops->rel_pathgroups(gmp, pgvec); } + pthread_cleanup_push_cast(reset_strbuf, &buff); _snprint_multipath_topology(gmp, &buff, verbosity, p_width); printf("%s", get_strbuf_str(&buff)); + pthread_cleanup_pop(1); } int snprint_multipath_style(const struct gen_multipath *gmp, @@ -1225,10 +1231,10 @@ int _snprint_multipath_topology(const struct gen_multipath *gmp, struct strbuf *buff, int verbosity, const fieldwidth_t *p_width) { - int j, i, rc; + int j, i, rc = 0; const struct _vector *pgvec; const struct gen_pathgroup *gpg; - STRBUF_ON_STACK(style); + struct strbuf style = STRBUF_INIT; size_t initial_len = get_strbuf_len(buff); fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL; @@ -1241,17 +1247,21 @@ int _snprint_multipath_topology(const struct gen_multipath *gmp, if (verbosity == 1) return _snprint_multipath(gmp, buff, "%n", width); + pthread_cleanup_push_cast(reset_strbuf, &style); if(isatty(1) && (rc = print_strbuf(&style, "%c[%dm", 0x1B, 1)) < 0) /* bold on */ - return rc; + goto err; if ((rc = gmp->ops->style(gmp, &style, verbosity)) < 0) - return rc; + goto err; if(isatty(1) && (rc = print_strbuf(&style, "%c[%dm", 0x1B, 0)) < 0) /* bold off */ - return rc; + goto err; - if ((rc = _snprint_multipath(gmp, buff, get_strbuf_str(&style), width)) < 0 - || (rc = _snprint_multipath(gmp, buff, PRINT_MAP_PROPS, width)) < 0) + if ((rc = _snprint_multipath(gmp, buff, get_strbuf_str(&style), width)) >= 0) + rc = _snprint_multipath(gmp, buff, PRINT_MAP_PROPS, width); +err: + pthread_cleanup_pop(1); + if (rc < 0) return rc; pgvec = gmp->ops->get_pathgroups(gmp); @@ -1868,7 +1878,7 @@ int __snprint_config(const struct config *conf, struct strbuf *buff, { int rc; - if ((rc = snprint_defaults(conf, buff)) < 0 || + if ((rc = snprint_defaults(conf, buff)) < 1 || (rc = snprint_blacklist(conf, buff)) < 0 || (rc = snprint_blacklist_except(conf, buff)) < 0 || (rc = snprint_hwtable(conf, buff, @@ -1887,17 +1897,21 @@ int __snprint_config(const struct config *conf, struct strbuf *buff, char *snprint_config(const struct config *conf, int *len, const struct _vector *hwtable, const struct _vector *mpvec) { - STRBUF_ON_STACK(buff); - char *reply; - int rc = __snprint_config(conf, &buff, hwtable, mpvec); + struct strbuf buff = STRBUF_INIT; + char *reply = NULL; + int rc; + + pthread_cleanup_push_cast(reset_strbuf, &buff); + rc = __snprint_config(conf, &buff, hwtable, mpvec); if (rc < 0) - return NULL; + goto out; if (len) *len = get_strbuf_len(&buff); reply = steal_strbuf_str(&buff); - +out: + pthread_cleanup_pop(1); return reply; } @@ -2012,7 +2026,7 @@ static void print_all_paths_custo(vector pathvec, int banner, const char *fmt) { int i; struct path * pp; - STRBUF_ON_STACK(line); + struct strbuf line = STRBUF_INIT; fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL; if (!VECTOR_SIZE(pathvec)) { @@ -2025,6 +2039,7 @@ static void print_all_paths_custo(vector pathvec, int banner, const char *fmt) return; get_path_layout(pathvec, 1, width); + pthread_cleanup_push_cast(reset_strbuf, &line); if (banner) append_strbuf_str(&line, "===== paths list =====\n"); @@ -2034,6 +2049,7 @@ static void print_all_paths_custo(vector pathvec, int banner, const char *fmt) snprint_path(&line, fmt, pp, width); printf("%s", get_strbuf_str(&line)); + pthread_cleanup_pop(1); } void print_all_paths(vector pathvec, int banner) diff --git a/libmultipath/prioritizers/weightedpath.c b/libmultipath/prioritizers/weightedpath.c index 561ebb48..df700bf3 100644 --- a/libmultipath/prioritizers/weightedpath.c +++ b/libmultipath/prioritizers/weightedpath.c @@ -63,7 +63,7 @@ build_wwn_path(struct path *pp, struct strbuf *buf) /* main priority routine */ int prio_path_weight(struct path *pp, char *prio_args) { - STRBUF_ON_STACK(path); + struct strbuf path = STRBUF_INIT; char *arg __attribute__((cleanup(cleanup_charp))) = NULL; char *temp, *regex, *prio; char split_char[] = " \t"; @@ -84,24 +84,25 @@ int prio_path_weight(struct path *pp, char *prio_args) return priority; } + pthread_cleanup_push_cast(reset_strbuf, &path); if (!strcmp(regex, HBTL)) { if (print_strbuf(&path, "%d:%d:%d:%" PRIu64, pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun) < 0) - return priority; + goto out; } else if (!strcmp(regex, DEV_NAME)) { if (append_strbuf_str(&path, pp->dev) < 0) - return priority; + goto out; } else if (!strcmp(regex, SERIAL)) { if (build_serial_path(pp, &path) != 0) - return priority; + goto out; } else if (!strcmp(regex, WWN)) { if (build_wwn_path(pp, &path) != 0) - return priority; + goto out; } else { condlog(0, "%s: %s - Invalid arguments", pp->dev, pp->prio.name); - return priority; + goto out; } while (!path_found) { @@ -121,7 +122,8 @@ int prio_path_weight(struct path *pp, char *prio_args) regfree(&pathe); } } - +out: + pthread_cleanup_pop(1); return priority; } diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index d4f19897..f35acdaa 100644 --- a/libmultipath/propsel.c +++ b/libmultipath/propsel.c @@ -217,7 +217,7 @@ out: int select_rr_weight(struct config *conf, struct multipath * mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; mp_set_mpe(rr_weight); mp_set_ovr(rr_weight); @@ -225,16 +225,18 @@ int select_rr_weight(struct config *conf, struct multipath * mp) mp_set_conf(rr_weight); mp_set_default(rr_weight, DEFAULT_RR_WEIGHT); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); print_rr_weight(&buff, mp->rr_weight); condlog(3, "%s: rr_weight = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } int select_pgfailback(struct config *conf, struct multipath * mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; mp_set_mpe(pgfailback); mp_set_ovr(pgfailback); @@ -242,9 +244,11 @@ int select_pgfailback(struct config *conf, struct multipath * mp) mp_set_conf(pgfailback); mp_set_default(pgfailback, DEFAULT_FAILBACK); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); print_pgfailback(&buff, mp->pgfailback); condlog(3, "%s: failback = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } @@ -367,7 +371,7 @@ void reconcile_features_with_options(const char *id, char **features, int* no_pa { static const char q_i_n_p[] = "queue_if_no_path"; static const char r_a_h_h[] = "retain_attached_hw_handler"; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (*features == NULL) return; @@ -382,6 +386,7 @@ void reconcile_features_with_options(const char *id, char **features, int* no_pa * For backward compatibility we allow 'features "1 queue_if_no_path"'; * it's translated into "no_path_retry queue" here. */ + pthread_cleanup_push_cast(reset_strbuf, &buff); if (strstr(*features, q_i_n_p)) { condlog(0, "%s: option 'features \"1 %s\"' is deprecated, " "please use 'no_path_retry queue' instead", @@ -400,6 +405,7 @@ void reconcile_features_with_options(const char *id, char **features, int* no_pa } remove_feature(features, q_i_n_p); } + pthread_cleanup_pop(1); if (strstr(*features, r_a_h_h)) { condlog(0, "%s: option 'features \"1 %s\"' is deprecated", id, r_a_h_h); @@ -779,7 +785,7 @@ out: int select_no_path_retry(struct config *conf, struct multipath *mp) { const char *origin = NULL; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (mp->disable_queueing) { condlog(0, "%s: queueing disabled", mp->alias); @@ -791,6 +797,7 @@ int select_no_path_retry(struct config *conf, struct multipath *mp) mp_set_hwe(no_path_retry); mp_set_conf(no_path_retry); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); print_no_path_retry(&buff, mp->no_path_retry); if (origin) condlog(3, "%s: no_path_retry = %s %s", mp->alias, @@ -798,6 +805,7 @@ out: else condlog(3, "%s: no_path_retry = undef %s", mp->alias, default_origin); + pthread_cleanup_pop(1); return 0; } @@ -845,23 +853,25 @@ int select_minio(struct config *conf, struct multipath *mp) int select_fast_io_fail(struct config *conf, struct path *pp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; pp_set_ovr_pce(fast_io_fail); pp_set_hwe(fast_io_fail); pp_set_conf(fast_io_fail); pp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); print_undef_off_zero(&buff, pp->fast_io_fail); condlog(3, "%s: fast_io_fail_tmo = %s %s", pp->dev, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } int select_dev_loss(struct config *conf, struct path *pp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; pp_set_ovr_pce(dev_loss); pp_set_hwe(dev_loss); @@ -869,16 +879,18 @@ int select_dev_loss(struct config *conf, struct path *pp) pp->dev_loss = DEV_LOSS_TMO_UNSET; return 0; out: + pthread_cleanup_push_cast(reset_strbuf, &buff); print_dev_loss(&buff, pp->dev_loss); condlog(3, "%s: dev_loss_tmo = %s %s", pp->dev, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } int select_eh_deadline(struct config *conf, struct path *pp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; pp_set_ovr_pce(eh_deadline); pp_set_hwe(eh_deadline); @@ -887,9 +899,11 @@ int select_eh_deadline(struct config *conf, struct path *pp) /* not changing sysfs in default cause, so don't print anything */ return 0; out: + pthread_cleanup_push_cast(reset_strbuf, &buff); print_undef_off_zero(&buff, pp->eh_deadline); condlog(3, "%s: eh_deadline = %s %s", pp->dev, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } @@ -911,7 +925,7 @@ out: int select_reservation_key(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; char *from_file = ""; uint64_t prkey = 0; @@ -929,10 +943,12 @@ out: else put_be64(mp->reservation_key, prkey); } + pthread_cleanup_push_cast(reset_strbuf, &buff); print_reservation_key(&buff, mp->reservation_key, mp->sa_flags, mp->prkey_source); condlog(3, "%s: reservation_key = %s %s%s", mp->alias, get_strbuf_str(&buff), origin, from_file); + pthread_cleanup_pop(1); return 0; } @@ -1029,16 +1045,18 @@ use_delay_watch_checks(struct config *conf, struct multipath *mp) { int value = NU_UNDEF; const char *origin = default_origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; do_set(delay_watch_checks, mp->mpe, value, multipaths_origin); do_set(delay_watch_checks, conf->overrides, value, overrides_origin); do_set_from_hwe(delay_watch_checks, mp, value, hwe_origin); do_set(delay_watch_checks, conf, value, conf_origin); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, value) > 0) condlog(3, "%s: delay_watch_checks = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return value; } @@ -1047,23 +1065,25 @@ use_delay_wait_checks(struct config *conf, struct multipath *mp) { int value = NU_UNDEF; const char *origin = default_origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; do_set(delay_wait_checks, mp->mpe, value, multipaths_origin); do_set(delay_wait_checks, conf->overrides, value, overrides_origin); do_set_from_hwe(delay_wait_checks, mp, value, hwe_origin); do_set(delay_wait_checks, conf, value, conf_origin); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, value) > 0) condlog(3, "%s: delay_wait_checks = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return value; } int select_delay_checks(struct config *conf, struct multipath *mp) { int watch_checks, wait_checks; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; watch_checks = use_delay_watch_checks(conf, mp); wait_checks = use_delay_wait_checks(conf, mp); @@ -1077,6 +1097,7 @@ int select_delay_checks(struct config *conf, struct multipath *mp) mp->san_path_err_threshold = 1; condlog(3, "%s: san_path_err_threshold = 1 %s", mp->alias, (watch_checks > 0)? delay_watch_origin : delay_wait_origin); + pthread_cleanup_push_cast(reset_strbuf, &buff); if (watch_checks > 0) { mp->san_path_err_forget_rate = watch_checks; print_off_int_undef(&buff, mp->san_path_err_forget_rate); @@ -1091,6 +1112,7 @@ int select_delay_checks(struct config *conf, struct multipath *mp) condlog(3, "%s: san_path_err_recovery_time = %s %s", mp->alias, get_strbuf_str(&buff), delay_wait_origin); } + pthread_cleanup_pop(1); return 0; } @@ -1108,7 +1130,7 @@ static int san_path_deprecated_warned; int select_san_path_err_threshold(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (marginal_path_check_enabled(mp) || (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) { mp->san_path_err_threshold = NU_NO; @@ -1124,17 +1146,19 @@ int select_san_path_err_threshold(struct config *conf, struct multipath *mp) mp_set_conf(san_path_err_threshold); mp_set_default(san_path_err_threshold, DEFAULT_ERR_CHECKS); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->san_path_err_threshold) > 0) condlog(3, "%s: san_path_err_threshold = %s %s", mp->alias, get_strbuf_str(&buff), origin); warn_san_path_deprecated(mp, san_path_err_threshold); + pthread_cleanup_pop(1); return 0; } int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (marginal_path_check_enabled(mp) || (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) { mp->san_path_err_forget_rate = NU_NO; @@ -1150,9 +1174,11 @@ int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp) mp_set_conf(san_path_err_forget_rate); mp_set_default(san_path_err_forget_rate, DEFAULT_ERR_CHECKS); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->san_path_err_forget_rate) > 0) condlog(3, "%s: san_path_err_forget_rate = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); warn_san_path_deprecated(mp, san_path_err_forget_rate); return 0; @@ -1161,7 +1187,7 @@ out: int select_san_path_err_recovery_time(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (marginal_path_check_enabled(mp) || (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) { mp->san_path_err_recovery_time = NU_NO; @@ -1177,9 +1203,11 @@ int select_san_path_err_recovery_time(struct config *conf, struct multipath *mp) mp_set_conf(san_path_err_recovery_time); mp_set_default(san_path_err_recovery_time, DEFAULT_ERR_CHECKS); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->san_path_err_recovery_time) != 0) condlog(3, "%s: san_path_err_recovery_time = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); warn_san_path_deprecated(mp, san_path_err_recovery_time); return 0; @@ -1188,7 +1216,7 @@ out: int select_marginal_path_err_sample_time(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) { mp->marginal_path_err_sample_time = NU_NO; @@ -1208,16 +1236,18 @@ out: mp->alias, 2 * IOTIMEOUT_SEC); mp->marginal_path_err_sample_time = 2 * IOTIMEOUT_SEC; } + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->marginal_path_err_sample_time) > 0) condlog(3, "%s: marginal_path_err_sample_time = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } int select_marginal_path_err_rate_threshold(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) { mp->marginal_path_err_rate_threshold = NU_NO; @@ -1231,16 +1261,18 @@ int select_marginal_path_err_rate_threshold(struct config *conf, struct multipat mp_set_conf(marginal_path_err_rate_threshold); mp_set_default(marginal_path_err_rate_threshold, DEFAULT_ERR_CHECKS); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->marginal_path_err_rate_threshold) > 0) condlog(3, "%s: marginal_path_err_rate_threshold = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } int select_marginal_path_err_recheck_gap_time(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) { mp->marginal_path_err_recheck_gap_time = NU_NO; @@ -1254,17 +1286,19 @@ int select_marginal_path_err_recheck_gap_time(struct config *conf, struct multip mp_set_conf(marginal_path_err_recheck_gap_time); mp_set_default(marginal_path_err_recheck_gap_time, DEFAULT_ERR_CHECKS); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->marginal_path_err_recheck_gap_time) > 0) condlog(3, "%s: marginal_path_err_recheck_gap_time = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } int select_marginal_path_double_failed_time(struct config *conf, struct multipath *mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) { mp->marginal_path_double_failed_time = NU_NO; @@ -1278,9 +1312,11 @@ int select_marginal_path_double_failed_time(struct config *conf, struct multipat mp_set_conf(marginal_path_double_failed_time); mp_set_default(marginal_path_double_failed_time, DEFAULT_ERR_CHECKS); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->marginal_path_double_failed_time) > 0) condlog(3, "%s: marginal_path_double_failed_time = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } @@ -1324,7 +1360,7 @@ out: int select_ghost_delay (struct config *conf, struct multipath * mp) { const char *origin; - STRBUF_ON_STACK(buff); + struct strbuf buff = STRBUF_INIT; mp_set_mpe(ghost_delay); mp_set_ovr(ghost_delay); @@ -1332,9 +1368,11 @@ int select_ghost_delay (struct config *conf, struct multipath * mp) mp_set_conf(ghost_delay); mp_set_default(ghost_delay, DEFAULT_GHOST_DELAY); out: + pthread_cleanup_push_cast(reset_strbuf, &buff); if (print_off_int_undef(&buff, mp->ghost_delay) != 0) condlog(3, "%s: ghost_delay = %s %s", mp->alias, get_strbuf_str(&buff), origin); + pthread_cleanup_pop(1); return 0; } diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h index 799f68e9..7e80b411 100644 --- a/libmultipath/sysfs.h +++ b/libmultipath/sysfs.h @@ -26,14 +26,9 @@ ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name, sysfs_attr_value_ok(__rc, __l); \ }) -#define log_sysfs_attr_set_value(prio, rc, fmt, __args...) \ -do { \ - STRBUF_ON_STACK(__buf); \ - if (print_strbuf(&__buf, fmt, ##__args) >= 0 && \ - print_strbuf(&__buf, ": %s", rc < 0 ? strerror(-rc) : \ - "write underflow") >= 0) \ - condlog(prio, "%s", get_strbuf_str(&__buf)); \ -} while(0) +#define log_sysfs_attr_set_value(prio, rc, fmt, __args...) \ + condlog(prio, fmt ": %s", ##__args , rc < 0 ? strerror(-rc) : \ + "write underflow") int sysfs_get_size (struct path *pp, unsigned long long * size); int sysfs_check_holders(char * check_devt, char * new_devt); diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c index 57447ca0..db6da984 100644 --- a/libmultipath/uevent.c +++ b/libmultipath/uevent.c @@ -460,11 +460,12 @@ static void print_uevq(const char *msg, struct list_head *uevq) { struct uevent *uev; int i = 0; - STRBUF_ON_STACK(buf); + struct strbuf buf = STRBUF_INIT; if (4 > MAX_VERBOSITY || 4 > libmp_verbosity) return; + pthread_cleanup_push_cast(reset_strbuf, &buf); if (list_empty(uevq)) append_strbuf_str(&buf, "*empty*"); else @@ -473,7 +474,8 @@ static void print_uevq(const char *msg, struct list_head *uevq) print_uev(&buf, uev); } - condlog(4, "uevent queue (%s): %s", msg, steal_strbuf_str(&buf)); + condlog(4, "uevent queue (%s): %s", msg, get_strbuf_str(&buf)); + pthread_cleanup_pop(1); } static void -- 2.17.2 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/dm-devel