* [PATCH v2 00/39] multipath-tools series part I: minor changes
@ 2020-08-12 11:32 mwilck
2020-08-12 11:32 ` [PATCH v2 08/35] libmultipath: create bitfield abstraction mwilck
2020-08-12 11:32 ` [PATCH v2 12/35] libmultipath: strlcpy()/strlcat(): use restrict qualifier mwilck
0 siblings, 2 replies; 7+ messages in thread
From: mwilck @ 2020-08-12 11:32 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
From: Martin Wilck <mwilck@suse.com>
Hi Christophe, hi Ben,
This is part I of a larger patch series for multpath-tools I've been preparing.
It contains self-contained fixes and cleanups, and unit test additions.
This is v2 of the series I posted on 2020-07-09. To avoid spamming, I will
resend only the patches that have changed (including context changes).
I took care to make sure the numbering is preserved. The full series will
be available here:
https://github.com/mwilck/multipath-tools/tree/ups/submit-2008
There are tags in that repo for each part of the series.
This part is tagged "submit-200812-1".
It's based on 0.8.4, plus the following set of previously
submitted and reviewed patches (latest first):
- [PATCH v2 0/8] multipath cleanups (v2 8-part series from Ben,
without 7/8 "multipathd: unset mpp->hwe when removing map")
- [PATCH v3] vector: return false if realloc fails in vector_alloc_slot func (Zhiqiang Liu)
- libmultipath: free pgp if add_pathgroup fails in disassemble_map func (Zhiqiang Liu)
- checker: add input check of state in checker_state_name func (Zhiqiang Liu)
- libmultipath: fix null dereference in add (lixiaokeng)
- tests/hwtable: fix a memory free in replicate_config (Zhiqiang Liu)
- vector: fix upper boundary check of vector size in vector_del_slot (Zhiqiang Liu)
- vector: add lower bound check of E in VECTOR_SLOT (Zhiqiang Liu)
- devmapper: remove useless using of memset in dm_get_info func (Zhiqiang Liu)
- libmultipath: fix a memory leak in dm_get_maps (lixiaokeng)
- libmultipath: fix a memory leak in disassemble_status func (Zhiqiang Liu)
- [PATCH 0/4] Fix segfault on access to mpp->hwe (4-part series, me)
(below is where the v1 series was based on)
- libmultipath: add device to hwtable.c (Steve Schremmer)
- [PATCH v3 0/7] Fix muitpath/multipathd flush issue (v3 7-part series, Ben)
- [PATCH v2 0/4] misc patches (v2 4-part series, Ben)
- multipath: Fix compiler warnings when built without systemd. (Marius Bakke)
- [PATCH v2 0/3] multipath: change default devnode blacklist
(v2 3-part series, Ben)
- multipath: add "-e" option to enable foreign libraries (me)
- libmultipath: set "enable_foreign" to NONE by default (me)
- libmultipath: fix condlog NULL argument in uevent_get_env_var (Ben)
- fix boolean value with json-c 0.14 (Christian Hesse)
- [PATCH v3 0/6] multipath: path validation library prep work
(v3 6-part series, me)
- [PATCH 0/2] More minor libmultipath fixes (2-part series, me)
- [PATCH 00/11] Minor fixes for multipath-tools (11-part series, me)
- libmpathpersist: depend on libmultipath (Christian Hesse)
- [PATCH v2 0/2] multipath-tools: fixes for kpartx.rules and skip_kpartx
(v2 2-part series, me)
- libmultipath: allow force reload with no active paths (Ben)
- libmutipath: don't close fd on dm_lib_release (Ben)-
- libmultipath: assign variable to make gcc happy (Ben)
- [PATCH v2 0/4] libmpathpersist allocation size fixes (v2 4-part series, me)
You can find a full tree of the code this is based on here:
https://github.com/openSUSE/multipath-tools/tree/upstream-queue
Regards, Martin
Changes v1 -> v2, as suggested by Ben Marzinski:
* 8/35 "libmultipath: create bitfield abstraction"
- return NULL for 0 bitfield size
- fixed error handling for bf == NULL
- removed unused find_first_set() and related tests
* 12/35 "libmultipath: strlcpy()/strlcat(): use restrict qualifier"
- unchanged, but resubmitting as it has no Reviewed-by: tag yet
(corner case of unterminated "dst" still unresolved, but if at
all, it should be changed in a separate patch).
Martin Wilck (35):
multipath-tools tests/util: separate group for bitmask tests
multipath-tools tests/directio: fix missing initializers
tests: __wrap_dlog: use check_expected()
multipath tools tests: add strchop() test
libmultipath: improve strchop()
multipath-tools tests: add test for devt2devname
libmultipath: devt2devname(): simplify using libudev
libmultipath: create bitfield abstraction
libmultipath: use bitfields in group_by_match()
libmultipath: util: constify function arguments
multipath-tools tests: add unit tests for strlcat
libmultipath: strlcpy()/strlcat(): use restrict qualifier
libmultipath: constify blacklist code
libmultipath: rlookup_binding(): remove newline in log message
libmultipath: fix missing initializer warning from clang 3.9
libmultipath: fix gcc -Wstringop-overflow warning
libmultipath: remove uevent listener failback
libmultipath: uevent: use static linkage where possible
libmultipath: uevent: inline trivial functions
libmultipath: decrease log level of "SCSI target" log message
libmultipath: get_udev_uid(): more appropriate error code
libmultipath: get_uid(): improve log message on udev failure
libmultipath: make sysfs_pathinfo() static and use const
libmultipath: pathinfo(): improve a log message
libmultipath: pathinfo(): don't filter emtpy devnode names
libmultipath: io_err_stat_handle_pathfail(): less error conditions
libmultipath: improve libdm logging
libmultipath: snprint_devices(): use udev_enumerate
libmultipath: snprint_devices(): print hidden/foreign status
libmultipath: alloc_path(): initialize pp->initialized
libmultipath: alloc_path_with_pathinfo(): treat devname overflow as
error
libmultipath: log table params in addmap()
multipathd: remove set_multipath_wwid()
kpartx: print an error message if removing a partition fails
kpartx: add missing newline
kpartx/devmapper.c | 2 +-
kpartx/kpartx.c | 2 +
libmultipath/alias.c | 2 +-
libmultipath/blacklist.c | 34 +-
libmultipath/blacklist.h | 17 +-
libmultipath/checkers/directio.c | 2 +-
libmultipath/configure.c | 11 +-
libmultipath/defaults.h | 2 +
libmultipath/devmapper.c | 27 +-
libmultipath/discovery.c | 30 +-
libmultipath/dmparser.c | 2 +-
libmultipath/io_err_stat.c | 25 +-
libmultipath/parser.c | 2 +-
libmultipath/pgpolicies.c | 12 +-
libmultipath/print.c | 90 ++---
libmultipath/print.h | 2 +-
libmultipath/propsel.c | 6 +
libmultipath/structs.c | 1 +
libmultipath/uevent.c | 324 ++---------------
libmultipath/uevent.h | 47 ++-
libmultipath/util.c | 168 ++++-----
libmultipath/util.h | 73 +++-
multipathd/main.c | 14 +-
tests/Makefile | 3 +-
tests/alias.c | 4 +-
tests/devt.c | 192 ++++++++++
tests/directio.c | 28 +-
tests/test-log.c | 5 +-
tests/uevent.c | 4 -
tests/util.c | 586 ++++++++++++++++++++++++++++---
30 files changed, 1081 insertions(+), 636 deletions(-)
create mode 100644 tests/devt.c
--
2.26.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 08/35] libmultipath: create bitfield abstraction
2020-08-12 11:32 [PATCH v2 00/39] multipath-tools series part I: minor changes mwilck
@ 2020-08-12 11:32 ` mwilck
2020-08-12 17:28 ` Benjamin Marzinski
2020-10-27 11:41 ` [dm-devel] " Xose Vazquez Perez
2020-08-12 11:32 ` [PATCH v2 12/35] libmultipath: strlcpy()/strlcat(): use restrict qualifier mwilck
1 sibling, 2 replies; 7+ messages in thread
From: mwilck @ 2020-08-12 11:32 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
From: Martin Wilck <mwilck@suse.com>
In e32d521d ("libmultipath: coalesce_paths: fix size mismatch handling"),
we introduced simple bitmap handling functions. We can do better. This
patch introduces a bitfield type with overflow detection and a
find_first_set() method.
Use this in coalesce_paths(), and adapt the unit tests. Also, add
unit tests for "odd" bitfield sizes; so far we tested only multiples
of 64.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 9 +-
libmultipath/util.c | 22 ++++
libmultipath/util.h | 56 +++++++++-
tests/util.c | 231 ++++++++++++++++++++++++++++++++++-----
4 files changed, 281 insertions(+), 37 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 96c7961..fe590f4 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1092,7 +1092,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
vector pathvec = vecs->pathvec;
struct config *conf;
int allow_queueing;
- uint64_t *size_mismatch_seen;
+ struct bitfield *size_mismatch_seen;
/* ignore refwwid if it's empty */
if (refwwid && !strlen(refwwid))
@@ -1106,8 +1106,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
if (VECTOR_SIZE(pathvec) == 0)
return CP_OK;
- size_mismatch_seen = calloc((VECTOR_SIZE(pathvec) - 1) / 64 + 1,
- sizeof(uint64_t));
+ size_mismatch_seen = alloc_bitfield(VECTOR_SIZE(pathvec));
if (size_mismatch_seen == NULL)
return CP_FAIL;
@@ -1131,7 +1130,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
}
/* 2. if path already coalesced, or seen and discarded */
- if (pp1->mpp || is_bit_set_in_array(k, size_mismatch_seen))
+ if (pp1->mpp || is_bit_set_in_bitfield(k, size_mismatch_seen))
continue;
/* 3. if path has disappeared */
@@ -1183,7 +1182,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
"Discard", pp2->dev, pp2->size,
mpp->size);
mpp->action = ACT_REJECT;
- set_bit_in_array(i, size_mismatch_seen);
+ set_bit_in_bitfield(i, size_mismatch_seen);
}
}
verify_paths(mpp, vecs);
diff --git a/libmultipath/util.c b/libmultipath/util.c
index 3c43f28..3e2708a 100644
--- a/libmultipath/util.c
+++ b/libmultipath/util.c
@@ -404,3 +404,25 @@ void close_fd(void *arg)
{
close((long)arg);
}
+
+struct bitfield *alloc_bitfield(unsigned int maxbit)
+{
+ unsigned int n;
+ struct bitfield *bf;
+
+ if (maxbit == 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ n = (maxbit - 1) / bits_per_slot + 1;
+ bf = calloc(1, sizeof(struct bitfield) + n * sizeof(bitfield_t));
+ if (bf)
+ bf->len = maxbit;
+ return bf;
+}
+
+void _log_bitfield_overflow(const char *f, unsigned int bit, unsigned int len)
+{
+ condlog(0, "%s: bitfield overflow: %u >= %u", f, bit, len);
+}
diff --git a/libmultipath/util.h b/libmultipath/util.h
index df75c4f..7ed30c7 100644
--- a/libmultipath/util.h
+++ b/libmultipath/util.h
@@ -1,6 +1,9 @@
#ifndef _UTIL_H
#define _UTIL_H
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
#include <sys/types.h>
/* for rlim_t */
#include <sys/resource.h>
@@ -51,19 +54,60 @@ struct scandir_result {
};
void free_scandir_result(struct scandir_result *);
-static inline bool is_bit_set_in_array(unsigned int bit, const uint64_t *arr)
+/*
+ * ffsll() is also available on glibc < 2.27 if _GNU_SOURCE is defined.
+ * But relying on that would require that every program using this header file
+ * set _GNU_SOURCE during compilation, because otherwise the library and the
+ * program would use different types for bitfield_t, causing errors.
+ * That's too error prone, so if in doubt, use ffs().
+ */
+#if __GLIBC_PREREQ(2, 27)
+typedef unsigned long long int bitfield_t;
+#define _ffs(x) ffsll(x)
+#else
+typedef unsigned int bitfield_t;
+#define _ffs(x) ffs(x)
+#endif
+#define bits_per_slot (sizeof(bitfield_t) * CHAR_BIT)
+
+struct bitfield {
+ unsigned int len;
+ bitfield_t bits[];
+};
+
+struct bitfield *alloc_bitfield(unsigned int maxbit);
+
+void _log_bitfield_overflow(const char *f, unsigned int bit, unsigned int len);
+#define log_bitfield_overflow(bit, len) \
+ _log_bitfield_overflow(__func__, bit, len)
+
+static inline bool is_bit_set_in_bitfield(unsigned int bit,
+ const struct bitfield *bf)
{
- return arr[bit / 64] & (1ULL << (bit % 64)) ? 1 : 0;
+ if (bit >= bf->len) {
+ log_bitfield_overflow(bit, bf->len);
+ return false;
+ }
+ return !!(bf->bits[bit / bits_per_slot] &
+ (1ULL << (bit % bits_per_slot)));
}
-static inline void set_bit_in_array(unsigned int bit, uint64_t *arr)
+static inline void set_bit_in_bitfield(unsigned int bit, struct bitfield *bf)
{
- arr[bit / 64] |= (1ULL << (bit % 64));
+ if (bit >= bf->len) {
+ log_bitfield_overflow(bit, bf->len);
+ return;
+ }
+ bf->bits[bit / bits_per_slot] |= (1ULL << (bit % bits_per_slot));
}
-static inline void clear_bit_in_array(unsigned int bit, uint64_t *arr)
+static inline void clear_bit_in_bitfield(unsigned int bit, struct bitfield *bf)
{
- arr[bit / 64] &= ~(1ULL << (bit % 64));
+ if (bit >= bf->len) {
+ log_bitfield_overflow(bit, bf->len);
+ return;
+ }
+ bf->bits[bit / bits_per_slot] &= ~(1ULL << (bit % bits_per_slot));
}
#endif /* _UTIL_H */
diff --git a/tests/util.c b/tests/util.c
index 6d12fda..fa869cd 100644
--- a/tests/util.c
+++ b/tests/util.c
@@ -164,19 +164,25 @@ static int test_basenamecpy(void)
static void test_bitmask_1(void **state)
{
- uint64_t arr[BITARR_SZ];
+ struct bitfield *bf;
+ uint64_t *arr;
int i, j, k, m, b;
- memset(arr, 0, sizeof(arr));
+ bf = alloc_bitfield(BITARR_SZ * 64);
+ assert_non_null(bf);
+ assert_int_equal(bf->len, BITARR_SZ * 64);
+ arr = (uint64_t *)bf->bits;
for (j = 0; j < BITARR_SZ; j++) {
for (i = 0; i < 64; i++) {
b = 64 * j + i;
- assert(!is_bit_set_in_array(b, arr));
- set_bit_in_array(b, arr);
+ assert(!is_bit_set_in_bitfield(b, bf));
+ set_bit_in_bitfield(b, bf);
for (k = 0; k < BITARR_SZ; k++) {
+#if 0
printf("b = %d j = %d k = %d a = %"PRIx64"\n",
b, j, k, arr[k]);
+#endif
if (k == j)
assert_int_equal(arr[j], 1ULL << i);
else
@@ -184,39 +190,44 @@ static void test_bitmask_1(void **state)
}
for (m = 0; m < 64; m++)
if (i == m)
- assert(is_bit_set_in_array(64 * j + m,
- arr));
+ assert(is_bit_set_in_bitfield(64 * j + m,
+ bf));
else
- assert(!is_bit_set_in_array(64 * j + m,
- arr));
- clear_bit_in_array(b, arr);
- assert(!is_bit_set_in_array(b, arr));
+ assert(!is_bit_set_in_bitfield(64 * j + m,
+ bf));
+ clear_bit_in_bitfield(b, bf);
+ assert(!is_bit_set_in_bitfield(b, bf));
for (k = 0; k < BITARR_SZ; k++)
assert_int_equal(arr[k], 0ULL);
}
}
+ free(bf);
}
static void test_bitmask_2(void **state)
{
- uint64_t arr[BITARR_SZ];
+ struct bitfield *bf;
+ uint64_t *arr;
int i, j, k, m, b;
- memset(arr, 0, sizeof(arr));
+ bf = alloc_bitfield(BITARR_SZ * 64);
+ assert_non_null(bf);
+ assert_int_equal(bf->len, BITARR_SZ * 64);
+ arr = (uint64_t *)bf->bits;
for (j = 0; j < BITARR_SZ; j++) {
for (i = 0; i < 64; i++) {
b = 64 * j + i;
- assert(!is_bit_set_in_array(b, arr));
- set_bit_in_array(b, arr);
+ assert(!is_bit_set_in_bitfield(b, bf));
+ set_bit_in_bitfield(b, bf);
for (m = 0; m < 64; m++)
if (m <= i)
- assert(is_bit_set_in_array(64 * j + m,
- arr));
+ assert(is_bit_set_in_bitfield(64 * j + m,
+ bf));
else
- assert(!is_bit_set_in_array(64 * j + m,
- arr));
- assert(is_bit_set_in_array(b, arr));
+ assert(!is_bit_set_in_bitfield(64 * j + m,
+ bf));
+ assert(is_bit_set_in_bitfield(b, bf));
for (k = 0; k < BITARR_SZ; k++) {
if (k < j || (k == j && i == 63))
assert_int_equal(arr[k], ~0ULL);
@@ -232,16 +243,16 @@ static void test_bitmask_2(void **state)
for (j = 0; j < BITARR_SZ; j++) {
for (i = 0; i < 64; i++) {
b = 64 * j + i;
- assert(is_bit_set_in_array(b, arr));
- clear_bit_in_array(b, arr);
+ assert(is_bit_set_in_bitfield(b, bf));
+ clear_bit_in_bitfield(b, bf);
for (m = 0; m < 64; m++)
if (m <= i)
- assert(!is_bit_set_in_array(64 * j + m,
- arr));
+ assert(!is_bit_set_in_bitfield(64 * j + m,
+ bf));
else
- assert(is_bit_set_in_array(64 * j + m,
- arr));
- assert(!is_bit_set_in_array(b, arr));
+ assert(is_bit_set_in_bitfield(64 * j + m,
+ bf));
+ assert(!is_bit_set_in_bitfield(b, bf));
for (k = 0; k < BITARR_SZ; k++) {
if (k < j || (k == j && i == 63))
assert_int_equal(arr[k], 0ULL);
@@ -254,13 +265,181 @@ static void test_bitmask_2(void **state)
}
}
}
+ free(bf);
}
+/*
+ * Test operations on a 0-length bitfield
+ */
+static void test_bitmask_len_0(void **state)
+{
+ struct bitfield *bf;
+
+ bf = alloc_bitfield(0);
+ assert_null(bf);
+}
+
+static void _test_bitmask_small(unsigned int n)
+{
+ struct bitfield *bf;
+ uint64_t *arr;
+
+ assert(n <= 64);
+ assert(n >= 1);
+
+ bf = alloc_bitfield(n);
+ assert_non_null(bf);
+ assert_int_equal(bf->len, n);
+ arr = (uint64_t *)bf->bits;
+
+ assert_int_equal(*arr, 0);
+
+ set_bit_in_bitfield(n + 1, bf);
+ assert_int_equal(*arr, 0);
+
+ set_bit_in_bitfield(n, bf);
+ assert_int_equal(*arr, 0);
+
+ set_bit_in_bitfield(n - 1, bf);
+ assert_int_equal(*arr, 1ULL << (n - 1));
+
+ clear_bit_in_bitfield(n - 1, bf);
+ assert_int_equal(*arr, 0);
+
+ set_bit_in_bitfield(0, bf);
+ assert_int_equal(*arr, 1);
+
+ free(bf);
+}
+
+static void _test_bitmask_small_2(unsigned int n)
+{
+ struct bitfield *bf;
+ uint64_t *arr;
+
+ assert(n <= 128);
+ assert(n >= 65);
+
+ bf = alloc_bitfield(n);
+ assert_non_null(bf);
+ assert_int_equal(bf->len, n);
+ arr = (uint64_t *)bf->bits;
+
+ assert_int_equal(arr[0], 0);
+ assert_int_equal(arr[1], 0);
+
+ set_bit_in_bitfield(n + 1, bf);
+ assert_int_equal(arr[0], 0);
+ assert_int_equal(arr[1], 0);
+
+ set_bit_in_bitfield(n, bf);
+ assert_int_equal(arr[0], 0);
+ assert_int_equal(arr[1], 0);
+
+ set_bit_in_bitfield(n - 1, bf);
+ assert_int_equal(arr[0], 0);
+ assert_int_equal(arr[1], 1ULL << (n - 65));
+
+ set_bit_in_bitfield(0, bf);
+ assert_int_equal(arr[0], 1);
+ assert_int_equal(arr[1], 1ULL << (n - 65));
+
+ set_bit_in_bitfield(64, bf);
+ assert_int_equal(arr[0], 1);
+ assert_int_equal(arr[1], (1ULL << (n - 65)) | 1);
+
+ clear_bit_in_bitfield(0, bf);
+ assert_int_equal(arr[0], 0);
+ assert_int_equal(arr[1], (1ULL << (n - 65)) | 1);
+
+ free(bf);
+}
+
+static void test_bitmask_len_1(void **state)
+{
+ _test_bitmask_small(1);
+}
+
+static void test_bitmask_len_2(void **state)
+{
+ _test_bitmask_small(2);
+}
+
+static void test_bitmask_len_3(void **state)
+{
+ _test_bitmask_small(3);
+}
+
+static void test_bitmask_len_23(void **state)
+{
+ _test_bitmask_small(23);
+}
+
+static void test_bitmask_len_63(void **state)
+{
+ _test_bitmask_small(63);
+}
+
+static void test_bitmask_len_64(void **state)
+{
+ _test_bitmask_small(63);
+}
+
+static void test_bitmask_len_65(void **state)
+{
+ _test_bitmask_small_2(65);
+}
+
+static void test_bitmask_len_66(void **state)
+{
+ _test_bitmask_small_2(66);
+}
+
+static void test_bitmask_len_67(void **state)
+{
+ _test_bitmask_small_2(67);
+}
+
+static void test_bitmask_len_103(void **state)
+{
+ _test_bitmask_small_2(103);
+}
+
+static void test_bitmask_len_126(void **state)
+{
+ _test_bitmask_small_2(126);
+}
+
+static void test_bitmask_len_127(void **state)
+{
+ _test_bitmask_small_2(127);
+}
+
+static void test_bitmask_len_128(void **state)
+{
+ _test_bitmask_small_2(128);
+}
+
+
static int test_bitmasks(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_bitmask_1),
cmocka_unit_test(test_bitmask_2),
+ cmocka_unit_test(test_bitmask_len_0),
+ cmocka_unit_test(test_bitmask_len_1),
+ cmocka_unit_test(test_bitmask_len_2),
+ cmocka_unit_test(test_bitmask_len_3),
+ cmocka_unit_test(test_bitmask_len_23),
+ cmocka_unit_test(test_bitmask_len_63),
+ cmocka_unit_test(test_bitmask_len_64),
+ cmocka_unit_test(test_bitmask_len_65),
+ cmocka_unit_test(test_bitmask_len_66),
+ cmocka_unit_test(test_bitmask_len_67),
+ cmocka_unit_test(test_bitmask_len_103),
+ cmocka_unit_test(test_bitmask_len_126),
+ cmocka_unit_test(test_bitmask_len_127),
+ cmocka_unit_test(test_bitmask_len_128),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
--
2.28.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 12/35] libmultipath: strlcpy()/strlcat(): use restrict qualifier
2020-08-12 11:32 [PATCH v2 00/39] multipath-tools series part I: minor changes mwilck
2020-08-12 11:32 ` [PATCH v2 08/35] libmultipath: create bitfield abstraction mwilck
@ 2020-08-12 11:32 ` mwilck
2020-08-12 18:01 ` Benjamin Marzinski
1 sibling, 1 reply; 7+ messages in thread
From: mwilck @ 2020-08-12 11:32 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
From: Martin Wilck <mwilck@suse.com>
Also remove the redundant local variables. It's not necessary to
make "restrict" work, but it makes the intention more clear.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/util.c | 28 ++++++++++++----------------
libmultipath/util.h | 4 ++--
2 files changed, 14 insertions(+), 18 deletions(-)
diff --git a/libmultipath/util.c b/libmultipath/util.c
index 526869e..207e63c 100644
--- a/libmultipath/util.c
+++ b/libmultipath/util.c
@@ -113,46 +113,42 @@ get_word (const char *sentence, char **word)
return skip + len;
}
-size_t strlcpy(char *dst, const char *src, size_t size)
+size_t strlcpy(char * restrict dst, const char * restrict src, size_t size)
{
size_t bytes = 0;
- char *q = dst;
- const char *p = src;
char ch;
- while ((ch = *p++)) {
- if (bytes+1 < size)
- *q++ = ch;
+ while ((ch = *src++)) {
+ if (bytes + 1 < size)
+ *dst++ = ch;
bytes++;
}
/* If size == 0 there is no space for a final null... */
if (size)
- *q = '\0';
+ *dst = '\0';
return bytes;
}
-size_t strlcat(char *dst, const char *src, size_t size)
+size_t strlcat(char * restrict dst, const char * restrict src, size_t size)
{
size_t bytes = 0;
- char *q = dst;
- const char *p = src;
char ch;
- while (bytes < size && *q) {
- q++;
+ while (bytes < size && *dst) {
+ dst++;
bytes++;
}
if (bytes == size)
return (bytes + strlen(src));
- while ((ch = *p++)) {
- if (bytes+1 < size)
- *q++ = ch;
+ while ((ch = *src++)) {
+ if (bytes + 1 < size)
+ *dst++ = ch;
bytes++;
}
- *q = '\0';
+ *dst = '\0';
return bytes;
}
diff --git a/libmultipath/util.h b/libmultipath/util.h
index a4f7c0a..52aa559 100644
--- a/libmultipath/util.h
+++ b/libmultipath/util.h
@@ -15,8 +15,8 @@ int basenamecpy (const char *src, char *dst, size_t size);
int filepresent (const char *run);
char *get_next_string(char **temp, const char *split_char);
int get_word (const char * sentence, char ** word);
-size_t strlcpy(char *dst, const char *src, size_t size);
-size_t strlcat(char *dst, const char *src, size_t size);
+size_t strlcpy(char * restrict dst, const char * restrict src, size_t size);
+size_t strlcat(char * restrict dst, const char * restrict src, size_t size);
int devt2devname (char *, int, const char *);
dev_t parse_devt(const char *dev_t);
char *convert_dev(char *dev, int is_path_device);
--
2.28.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 08/35] libmultipath: create bitfield abstraction
2020-08-12 11:32 ` [PATCH v2 08/35] libmultipath: create bitfield abstraction mwilck
@ 2020-08-12 17:28 ` Benjamin Marzinski
2020-10-27 11:41 ` [dm-devel] " Xose Vazquez Perez
1 sibling, 0 replies; 7+ messages in thread
From: Benjamin Marzinski @ 2020-08-12 17:28 UTC (permalink / raw)
To: mwilck; +Cc: dm-devel
On Wed, Aug 12, 2020 at 01:32:31PM +0200, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
>
> In e32d521d ("libmultipath: coalesce_paths: fix size mismatch handling"),
> we introduced simple bitmap handling functions. We can do better. This
> patch introduces a bitfield type with overflow detection and a
> find_first_set() method.
>
> Use this in coalesce_paths(), and adapt the unit tests. Also, add
> unit tests for "odd" bitfield sizes; so far we tested only multiples
> of 64.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/configure.c | 9 +-
> libmultipath/util.c | 22 ++++
> libmultipath/util.h | 56 +++++++++-
> tests/util.c | 231 ++++++++++++++++++++++++++++++++++-----
> 4 files changed, 281 insertions(+), 37 deletions(-)
>
> diff --git a/libmultipath/configure.c b/libmultipath/configure.c
> index 96c7961..fe590f4 100644
> --- a/libmultipath/configure.c
> +++ b/libmultipath/configure.c
> @@ -1092,7 +1092,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
> vector pathvec = vecs->pathvec;
> struct config *conf;
> int allow_queueing;
> - uint64_t *size_mismatch_seen;
> + struct bitfield *size_mismatch_seen;
>
> /* ignore refwwid if it's empty */
> if (refwwid && !strlen(refwwid))
> @@ -1106,8 +1106,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
>
> if (VECTOR_SIZE(pathvec) == 0)
> return CP_OK;
> - size_mismatch_seen = calloc((VECTOR_SIZE(pathvec) - 1) / 64 + 1,
> - sizeof(uint64_t));
> + size_mismatch_seen = alloc_bitfield(VECTOR_SIZE(pathvec));
> if (size_mismatch_seen == NULL)
> return CP_FAIL;
>
> @@ -1131,7 +1130,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
> }
>
> /* 2. if path already coalesced, or seen and discarded */
> - if (pp1->mpp || is_bit_set_in_array(k, size_mismatch_seen))
> + if (pp1->mpp || is_bit_set_in_bitfield(k, size_mismatch_seen))
> continue;
>
> /* 3. if path has disappeared */
> @@ -1183,7 +1182,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
> "Discard", pp2->dev, pp2->size,
> mpp->size);
> mpp->action = ACT_REJECT;
> - set_bit_in_array(i, size_mismatch_seen);
> + set_bit_in_bitfield(i, size_mismatch_seen);
> }
> }
> verify_paths(mpp, vecs);
> diff --git a/libmultipath/util.c b/libmultipath/util.c
> index 3c43f28..3e2708a 100644
> --- a/libmultipath/util.c
> +++ b/libmultipath/util.c
> @@ -404,3 +404,25 @@ void close_fd(void *arg)
> {
> close((long)arg);
> }
> +
> +struct bitfield *alloc_bitfield(unsigned int maxbit)
> +{
> + unsigned int n;
> + struct bitfield *bf;
> +
> + if (maxbit == 0) {
> + errno = EINVAL;
> + return NULL;
> + }
> +
> + n = (maxbit - 1) / bits_per_slot + 1;
> + bf = calloc(1, sizeof(struct bitfield) + n * sizeof(bitfield_t));
> + if (bf)
> + bf->len = maxbit;
> + return bf;
> +}
> +
> +void _log_bitfield_overflow(const char *f, unsigned int bit, unsigned int len)
> +{
> + condlog(0, "%s: bitfield overflow: %u >= %u", f, bit, len);
> +}
> diff --git a/libmultipath/util.h b/libmultipath/util.h
> index df75c4f..7ed30c7 100644
> --- a/libmultipath/util.h
> +++ b/libmultipath/util.h
> @@ -1,6 +1,9 @@
> #ifndef _UTIL_H
> #define _UTIL_H
>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <limits.h>
> #include <sys/types.h>
> /* for rlim_t */
> #include <sys/resource.h>
> @@ -51,19 +54,60 @@ struct scandir_result {
> };
> void free_scandir_result(struct scandir_result *);
>
> -static inline bool is_bit_set_in_array(unsigned int bit, const uint64_t *arr)
> +/*
> + * ffsll() is also available on glibc < 2.27 if _GNU_SOURCE is defined.
> + * But relying on that would require that every program using this header file
> + * set _GNU_SOURCE during compilation, because otherwise the library and the
> + * program would use different types for bitfield_t, causing errors.
> + * That's too error prone, so if in doubt, use ffs().
> + */
> +#if __GLIBC_PREREQ(2, 27)
> +typedef unsigned long long int bitfield_t;
> +#define _ffs(x) ffsll(x)
> +#else
> +typedef unsigned int bitfield_t;
> +#define _ffs(x) ffs(x)
> +#endif
> +#define bits_per_slot (sizeof(bitfield_t) * CHAR_BIT)
> +
> +struct bitfield {
> + unsigned int len;
> + bitfield_t bits[];
> +};
> +
> +struct bitfield *alloc_bitfield(unsigned int maxbit);
> +
> +void _log_bitfield_overflow(const char *f, unsigned int bit, unsigned int len);
> +#define log_bitfield_overflow(bit, len) \
> + _log_bitfield_overflow(__func__, bit, len)
> +
> +static inline bool is_bit_set_in_bitfield(unsigned int bit,
> + const struct bitfield *bf)
> {
> - return arr[bit / 64] & (1ULL << (bit % 64)) ? 1 : 0;
> + if (bit >= bf->len) {
> + log_bitfield_overflow(bit, bf->len);
> + return false;
> + }
> + return !!(bf->bits[bit / bits_per_slot] &
> + (1ULL << (bit % bits_per_slot)));
> }
>
> -static inline void set_bit_in_array(unsigned int bit, uint64_t *arr)
> +static inline void set_bit_in_bitfield(unsigned int bit, struct bitfield *bf)
> {
> - arr[bit / 64] |= (1ULL << (bit % 64));
> + if (bit >= bf->len) {
> + log_bitfield_overflow(bit, bf->len);
> + return;
> + }
> + bf->bits[bit / bits_per_slot] |= (1ULL << (bit % bits_per_slot));
> }
>
> -static inline void clear_bit_in_array(unsigned int bit, uint64_t *arr)
> +static inline void clear_bit_in_bitfield(unsigned int bit, struct bitfield *bf)
> {
> - arr[bit / 64] &= ~(1ULL << (bit % 64));
> + if (bit >= bf->len) {
> + log_bitfield_overflow(bit, bf->len);
> + return;
> + }
> + bf->bits[bit / bits_per_slot] &= ~(1ULL << (bit % bits_per_slot));
> }
>
> #endif /* _UTIL_H */
> diff --git a/tests/util.c b/tests/util.c
> index 6d12fda..fa869cd 100644
> --- a/tests/util.c
> +++ b/tests/util.c
> @@ -164,19 +164,25 @@ static int test_basenamecpy(void)
>
> static void test_bitmask_1(void **state)
> {
> - uint64_t arr[BITARR_SZ];
> + struct bitfield *bf;
> + uint64_t *arr;
> int i, j, k, m, b;
>
> - memset(arr, 0, sizeof(arr));
> + bf = alloc_bitfield(BITARR_SZ * 64);
> + assert_non_null(bf);
> + assert_int_equal(bf->len, BITARR_SZ * 64);
> + arr = (uint64_t *)bf->bits;
>
> for (j = 0; j < BITARR_SZ; j++) {
> for (i = 0; i < 64; i++) {
> b = 64 * j + i;
> - assert(!is_bit_set_in_array(b, arr));
> - set_bit_in_array(b, arr);
> + assert(!is_bit_set_in_bitfield(b, bf));
> + set_bit_in_bitfield(b, bf);
> for (k = 0; k < BITARR_SZ; k++) {
> +#if 0
> printf("b = %d j = %d k = %d a = %"PRIx64"\n",
> b, j, k, arr[k]);
> +#endif
> if (k == j)
> assert_int_equal(arr[j], 1ULL << i);
> else
> @@ -184,39 +190,44 @@ static void test_bitmask_1(void **state)
> }
> for (m = 0; m < 64; m++)
> if (i == m)
> - assert(is_bit_set_in_array(64 * j + m,
> - arr));
> + assert(is_bit_set_in_bitfield(64 * j + m,
> + bf));
> else
> - assert(!is_bit_set_in_array(64 * j + m,
> - arr));
> - clear_bit_in_array(b, arr);
> - assert(!is_bit_set_in_array(b, arr));
> + assert(!is_bit_set_in_bitfield(64 * j + m,
> + bf));
> + clear_bit_in_bitfield(b, bf);
> + assert(!is_bit_set_in_bitfield(b, bf));
> for (k = 0; k < BITARR_SZ; k++)
> assert_int_equal(arr[k], 0ULL);
> }
> }
> + free(bf);
> }
>
> static void test_bitmask_2(void **state)
> {
> - uint64_t arr[BITARR_SZ];
> + struct bitfield *bf;
> + uint64_t *arr;
> int i, j, k, m, b;
>
> - memset(arr, 0, sizeof(arr));
> + bf = alloc_bitfield(BITARR_SZ * 64);
> + assert_non_null(bf);
> + assert_int_equal(bf->len, BITARR_SZ * 64);
> + arr = (uint64_t *)bf->bits;
>
> for (j = 0; j < BITARR_SZ; j++) {
> for (i = 0; i < 64; i++) {
> b = 64 * j + i;
> - assert(!is_bit_set_in_array(b, arr));
> - set_bit_in_array(b, arr);
> + assert(!is_bit_set_in_bitfield(b, bf));
> + set_bit_in_bitfield(b, bf);
> for (m = 0; m < 64; m++)
> if (m <= i)
> - assert(is_bit_set_in_array(64 * j + m,
> - arr));
> + assert(is_bit_set_in_bitfield(64 * j + m,
> + bf));
> else
> - assert(!is_bit_set_in_array(64 * j + m,
> - arr));
> - assert(is_bit_set_in_array(b, arr));
> + assert(!is_bit_set_in_bitfield(64 * j + m,
> + bf));
> + assert(is_bit_set_in_bitfield(b, bf));
> for (k = 0; k < BITARR_SZ; k++) {
> if (k < j || (k == j && i == 63))
> assert_int_equal(arr[k], ~0ULL);
> @@ -232,16 +243,16 @@ static void test_bitmask_2(void **state)
> for (j = 0; j < BITARR_SZ; j++) {
> for (i = 0; i < 64; i++) {
> b = 64 * j + i;
> - assert(is_bit_set_in_array(b, arr));
> - clear_bit_in_array(b, arr);
> + assert(is_bit_set_in_bitfield(b, bf));
> + clear_bit_in_bitfield(b, bf);
> for (m = 0; m < 64; m++)
> if (m <= i)
> - assert(!is_bit_set_in_array(64 * j + m,
> - arr));
> + assert(!is_bit_set_in_bitfield(64 * j + m,
> + bf));
> else
> - assert(is_bit_set_in_array(64 * j + m,
> - arr));
> - assert(!is_bit_set_in_array(b, arr));
> + assert(is_bit_set_in_bitfield(64 * j + m,
> + bf));
> + assert(!is_bit_set_in_bitfield(b, bf));
> for (k = 0; k < BITARR_SZ; k++) {
> if (k < j || (k == j && i == 63))
> assert_int_equal(arr[k], 0ULL);
> @@ -254,13 +265,181 @@ static void test_bitmask_2(void **state)
> }
> }
> }
> + free(bf);
> }
>
> +/*
> + * Test operations on a 0-length bitfield
> + */
> +static void test_bitmask_len_0(void **state)
> +{
> + struct bitfield *bf;
> +
> + bf = alloc_bitfield(0);
> + assert_null(bf);
> +}
> +
> +static void _test_bitmask_small(unsigned int n)
> +{
> + struct bitfield *bf;
> + uint64_t *arr;
> +
> + assert(n <= 64);
> + assert(n >= 1);
> +
> + bf = alloc_bitfield(n);
> + assert_non_null(bf);
> + assert_int_equal(bf->len, n);
> + arr = (uint64_t *)bf->bits;
> +
> + assert_int_equal(*arr, 0);
> +
> + set_bit_in_bitfield(n + 1, bf);
> + assert_int_equal(*arr, 0);
> +
> + set_bit_in_bitfield(n, bf);
> + assert_int_equal(*arr, 0);
> +
> + set_bit_in_bitfield(n - 1, bf);
> + assert_int_equal(*arr, 1ULL << (n - 1));
> +
> + clear_bit_in_bitfield(n - 1, bf);
> + assert_int_equal(*arr, 0);
> +
> + set_bit_in_bitfield(0, bf);
> + assert_int_equal(*arr, 1);
> +
> + free(bf);
> +}
> +
> +static void _test_bitmask_small_2(unsigned int n)
> +{
> + struct bitfield *bf;
> + uint64_t *arr;
> +
> + assert(n <= 128);
> + assert(n >= 65);
> +
> + bf = alloc_bitfield(n);
> + assert_non_null(bf);
> + assert_int_equal(bf->len, n);
> + arr = (uint64_t *)bf->bits;
> +
> + assert_int_equal(arr[0], 0);
> + assert_int_equal(arr[1], 0);
> +
> + set_bit_in_bitfield(n + 1, bf);
> + assert_int_equal(arr[0], 0);
> + assert_int_equal(arr[1], 0);
> +
> + set_bit_in_bitfield(n, bf);
> + assert_int_equal(arr[0], 0);
> + assert_int_equal(arr[1], 0);
> +
> + set_bit_in_bitfield(n - 1, bf);
> + assert_int_equal(arr[0], 0);
> + assert_int_equal(arr[1], 1ULL << (n - 65));
> +
> + set_bit_in_bitfield(0, bf);
> + assert_int_equal(arr[0], 1);
> + assert_int_equal(arr[1], 1ULL << (n - 65));
> +
> + set_bit_in_bitfield(64, bf);
> + assert_int_equal(arr[0], 1);
> + assert_int_equal(arr[1], (1ULL << (n - 65)) | 1);
> +
> + clear_bit_in_bitfield(0, bf);
> + assert_int_equal(arr[0], 0);
> + assert_int_equal(arr[1], (1ULL << (n - 65)) | 1);
> +
> + free(bf);
> +}
> +
> +static void test_bitmask_len_1(void **state)
> +{
> + _test_bitmask_small(1);
> +}
> +
> +static void test_bitmask_len_2(void **state)
> +{
> + _test_bitmask_small(2);
> +}
> +
> +static void test_bitmask_len_3(void **state)
> +{
> + _test_bitmask_small(3);
> +}
> +
> +static void test_bitmask_len_23(void **state)
> +{
> + _test_bitmask_small(23);
> +}
> +
> +static void test_bitmask_len_63(void **state)
> +{
> + _test_bitmask_small(63);
> +}
> +
> +static void test_bitmask_len_64(void **state)
> +{
> + _test_bitmask_small(63);
> +}
> +
> +static void test_bitmask_len_65(void **state)
> +{
> + _test_bitmask_small_2(65);
> +}
> +
> +static void test_bitmask_len_66(void **state)
> +{
> + _test_bitmask_small_2(66);
> +}
> +
> +static void test_bitmask_len_67(void **state)
> +{
> + _test_bitmask_small_2(67);
> +}
> +
> +static void test_bitmask_len_103(void **state)
> +{
> + _test_bitmask_small_2(103);
> +}
> +
> +static void test_bitmask_len_126(void **state)
> +{
> + _test_bitmask_small_2(126);
> +}
> +
> +static void test_bitmask_len_127(void **state)
> +{
> + _test_bitmask_small_2(127);
> +}
> +
> +static void test_bitmask_len_128(void **state)
> +{
> + _test_bitmask_small_2(128);
> +}
> +
> +
> static int test_bitmasks(void)
> {
> const struct CMUnitTest tests[] = {
> cmocka_unit_test(test_bitmask_1),
> cmocka_unit_test(test_bitmask_2),
> + cmocka_unit_test(test_bitmask_len_0),
> + cmocka_unit_test(test_bitmask_len_1),
> + cmocka_unit_test(test_bitmask_len_2),
> + cmocka_unit_test(test_bitmask_len_3),
> + cmocka_unit_test(test_bitmask_len_23),
> + cmocka_unit_test(test_bitmask_len_63),
> + cmocka_unit_test(test_bitmask_len_64),
> + cmocka_unit_test(test_bitmask_len_65),
> + cmocka_unit_test(test_bitmask_len_66),
> + cmocka_unit_test(test_bitmask_len_67),
> + cmocka_unit_test(test_bitmask_len_103),
> + cmocka_unit_test(test_bitmask_len_126),
> + cmocka_unit_test(test_bitmask_len_127),
> + cmocka_unit_test(test_bitmask_len_128),
> };
> return cmocka_run_group_tests(tests, NULL, NULL);
> }
> --
> 2.28.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 12/35] libmultipath: strlcpy()/strlcat(): use restrict qualifier
2020-08-12 11:32 ` [PATCH v2 12/35] libmultipath: strlcpy()/strlcat(): use restrict qualifier mwilck
@ 2020-08-12 18:01 ` Benjamin Marzinski
0 siblings, 0 replies; 7+ messages in thread
From: Benjamin Marzinski @ 2020-08-12 18:01 UTC (permalink / raw)
To: mwilck; +Cc: dm-devel
On Wed, Aug 12, 2020 at 01:32:32PM +0200, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
>
> Also remove the redundant local variables. It's not necessary to
> make "restrict" work, but it makes the intention more clear.
>
Clearly, the way you wrote strlcat agrees with other implementations,
so it's fine.
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/util.c | 28 ++++++++++++----------------
> libmultipath/util.h | 4 ++--
> 2 files changed, 14 insertions(+), 18 deletions(-)
>
> diff --git a/libmultipath/util.c b/libmultipath/util.c
> index 526869e..207e63c 100644
> --- a/libmultipath/util.c
> +++ b/libmultipath/util.c
> @@ -113,46 +113,42 @@ get_word (const char *sentence, char **word)
> return skip + len;
> }
>
> -size_t strlcpy(char *dst, const char *src, size_t size)
> +size_t strlcpy(char * restrict dst, const char * restrict src, size_t size)
> {
> size_t bytes = 0;
> - char *q = dst;
> - const char *p = src;
> char ch;
>
> - while ((ch = *p++)) {
> - if (bytes+1 < size)
> - *q++ = ch;
> + while ((ch = *src++)) {
> + if (bytes + 1 < size)
> + *dst++ = ch;
> bytes++;
> }
>
> /* If size == 0 there is no space for a final null... */
> if (size)
> - *q = '\0';
> + *dst = '\0';
> return bytes;
> }
>
> -size_t strlcat(char *dst, const char *src, size_t size)
> +size_t strlcat(char * restrict dst, const char * restrict src, size_t size)
> {
> size_t bytes = 0;
> - char *q = dst;
> - const char *p = src;
> char ch;
>
> - while (bytes < size && *q) {
> - q++;
> + while (bytes < size && *dst) {
> + dst++;
> bytes++;
> }
> if (bytes == size)
> return (bytes + strlen(src));
>
> - while ((ch = *p++)) {
> - if (bytes+1 < size)
> - *q++ = ch;
> + while ((ch = *src++)) {
> + if (bytes + 1 < size)
> + *dst++ = ch;
> bytes++;
> }
>
> - *q = '\0';
> + *dst = '\0';
> return bytes;
> }
>
> diff --git a/libmultipath/util.h b/libmultipath/util.h
> index a4f7c0a..52aa559 100644
> --- a/libmultipath/util.h
> +++ b/libmultipath/util.h
> @@ -15,8 +15,8 @@ int basenamecpy (const char *src, char *dst, size_t size);
> int filepresent (const char *run);
> char *get_next_string(char **temp, const char *split_char);
> int get_word (const char * sentence, char ** word);
> -size_t strlcpy(char *dst, const char *src, size_t size);
> -size_t strlcat(char *dst, const char *src, size_t size);
> +size_t strlcpy(char * restrict dst, const char * restrict src, size_t size);
> +size_t strlcat(char * restrict dst, const char * restrict src, size_t size);
> int devt2devname (char *, int, const char *);
> dev_t parse_devt(const char *dev_t);
> char *convert_dev(char *dev, int is_path_device);
> --
> 2.28.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [dm-devel] [PATCH v2 08/35] libmultipath: create bitfield abstraction
2020-08-12 11:32 ` [PATCH v2 08/35] libmultipath: create bitfield abstraction mwilck
2020-08-12 17:28 ` Benjamin Marzinski
@ 2020-10-27 11:41 ` Xose Vazquez Perez
2020-10-27 16:06 ` Martin Wilck
1 sibling, 1 reply; 7+ messages in thread
From: Xose Vazquez Perez @ 2020-10-27 11:41 UTC (permalink / raw)
To: mwilck, Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel
On 8/12/20 1:32 PM, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
>
> In e32d521d ("libmultipath: coalesce_paths: fix size mismatch handling"),
> we introduced simple bitmap handling functions. We can do better. This
> patch introduces a bitfield type with overflow detection and a
> find_first_set() method.
>
> Use this in coalesce_paths(), and adapt the unit tests. Also, add
> unit tests for "odd" bitfield sizes; so far we tested only multiples
> of 64.
>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/configure.c | 9 +-
> libmultipath/util.c | 22 ++++
> libmultipath/util.h | 56 +++++++++-
> tests/util.c | 231 ++++++++++++++++++++++++++++++++++-----
> 4 files changed, 281 insertions(+), 37 deletions(-)
> [...]
> diff --git a/libmultipath/util.h b/libmultipath/util.h
> index df75c4f..7ed30c7 100644
> --- a/libmultipath/util.h
> +++ b/libmultipath/util.h
> [...]
> -static inline bool is_bit_set_in_array(unsigned int bit, const uint64_t *arr)
> +/*
> + * ffsll() is also available on glibc < 2.27 if _GNU_SOURCE is defined.
> + * But relying on that would require that every program using this header file
> + * set _GNU_SOURCE during compilation, because otherwise the library and the
> + * program would use different types for bitfield_t, causing errors.
> + * That's too error prone, so if in doubt, use ffs().
> + */
> +#if __GLIBC_PREREQ(2, 27)
> +typedef unsigned long long int bitfield_t;
> +#define _ffs(x) ffsll(x)
> +#else
> +typedef unsigned int bitfield_t;
> +#define _ffs(x) ffs(x)
> +#endif
> [...]
musl-libc shows a warning(missing binary operator):
make[1]: Entering directory 'multipath-tools/libmultipath'
[...]
musl-gcc --std=gnu99 -O2 -g -fstack-protector-strong --param=ssp-buffer-size=4 -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int -Werror=implicit-function-declaration -Werror=format-security
-Wno-clobbered -Wno-error=clobbered -Werror=cast-qual -Werror=discarded-qualifiers -pipe -DBIN_DIR=\"/sbin\" -DLIB_STRING=\"lib64\" -DRUN_DIR=\"run\" -MMD -MP -fPIC -I../libmpathcmd
-I../libmpathpersist -I../libmultipath/nvme -DUSE_SYSTEMD=246 -DLIBDM_API_FLUSH -D_GNU_SOURCE -DLIBDM_API_COOKIE -DLIBUDEV_API_RECVBUF -DLIBDM_API_DEFERRED -DLIBDM_API_HOLD_CONTROL
-Wp,-D_FORTIFY_SOURCE=2 -c -o devmapper.o devmapper.c
In file included from devmapper.c:19:
util.h:65:19: error: missing binary operator before token "("
65 | #if __GLIBC_PREREQ(2, 27)
| ^
make[1]: *** [../Makefile.inc:138: devmapper.o] Error 1
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [dm-devel] [PATCH v2 08/35] libmultipath: create bitfield abstraction
2020-10-27 11:41 ` [dm-devel] " Xose Vazquez Perez
@ 2020-10-27 16:06 ` Martin Wilck
0 siblings, 0 replies; 7+ messages in thread
From: Martin Wilck @ 2020-10-27 16:06 UTC (permalink / raw)
To: Xose Vazquez Perez, Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel
On Tue, 2020-10-27 at 12:41 +0100, Xose Vazquez Perez wrote:
>
> musl-libc shows a warning(missing binary operator):
Thanks for pointing this out. There are more issues with musl libc,
in particular with the unit tests.
I'll send patches as soon as I've figured it out.
@Christophe, please don't tag the current code just yet. We should
include these fixes.
Regards
Martin
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-10-27 16:06 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-12 11:32 [PATCH v2 00/39] multipath-tools series part I: minor changes mwilck
2020-08-12 11:32 ` [PATCH v2 08/35] libmultipath: create bitfield abstraction mwilck
2020-08-12 17:28 ` Benjamin Marzinski
2020-10-27 11:41 ` [dm-devel] " Xose Vazquez Perez
2020-10-27 16:06 ` Martin Wilck
2020-08-12 11:32 ` [PATCH v2 12/35] libmultipath: strlcpy()/strlcat(): use restrict qualifier mwilck
2020-08-12 18:01 ` Benjamin Marzinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.