summaryrefslogtreecommitdiffstats
path: root/src/spdk/lib/util
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/spdk/lib/util
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/spdk/lib/util')
-rw-r--r--src/spdk/lib/util/Makefile41
-rw-r--r--src/spdk/lib/util/base64.c228
-rw-r--r--src/spdk/lib/util/bit_array.c313
-rw-r--r--src/spdk/lib/util/cpuset.c320
-rw-r--r--src/spdk/lib/util/crc16.c53
-rw-r--r--src/spdk/lib/util/crc32.c66
-rw-r--r--src/spdk/lib/util/crc32_ieee.c48
-rw-r--r--src/spdk/lib/util/crc32c.c89
-rw-r--r--src/spdk/lib/util/fd.c103
-rw-r--r--src/spdk/lib/util/strerror_tls.c43
-rw-r--r--src/spdk/lib/util/string.c405
-rw-r--r--src/spdk/lib/util/uuid.c67
12 files changed, 1776 insertions, 0 deletions
diff --git a/src/spdk/lib/util/Makefile b/src/spdk/lib/util/Makefile
new file mode 100644
index 00000000..c31a506b
--- /dev/null
+++ b/src/spdk/lib/util/Makefile
@@ -0,0 +1,41 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+C_SRCS = base64.c bit_array.c cpuset.c crc16.c crc32.c crc32c.c crc32_ieee.c fd.c strerror_tls.c string.c uuid.c
+LIBNAME = util
+LOCAL_SYS_LIBS = -luuid
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/lib/util/base64.c b/src/spdk/lib/util/base64.c
new file mode 100644
index 00000000..81361263
--- /dev/null
+++ b/src/spdk/lib/util/base64.c
@@ -0,0 +1,228 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+#include "spdk/endian.h"
+#include "spdk/base64.h"
+
+#define BASE64_ENC_BITMASK 0x3FUL
+#define BASE64_PADDING_CHAR '='
+
+static const char base64_enc_table[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+static const char base64_urfsafe_enc_table[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789-_";
+
+static const uint8_t
+base64_dec_table[] = {
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+};
+
+static const uint8_t
+base64_urlsafe_dec_table[] = {
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+};
+
+static int
+_spdk_base64_encode(char *dst, const char *enc_table, const void *src, size_t src_len)
+{
+ uint32_t raw_u32;
+
+ if (!dst || !src || src_len <= 0) {
+ return -EINVAL;
+ }
+
+ while (src_len >= 4) {
+ raw_u32 = from_be32(src);
+
+ *dst++ = enc_table[(raw_u32 >> 26) & BASE64_ENC_BITMASK];
+ *dst++ = enc_table[(raw_u32 >> 20) & BASE64_ENC_BITMASK];
+ *dst++ = enc_table[(raw_u32 >> 14) & BASE64_ENC_BITMASK];
+ *dst++ = enc_table[(raw_u32 >> 8) & BASE64_ENC_BITMASK];
+
+ src_len -= 3;
+ src += 3;
+ }
+
+ if (src_len == 0) {
+ goto out;
+ }
+
+ raw_u32 = 0;
+ memcpy(&raw_u32, src, src_len);
+ raw_u32 = from_be32(&raw_u32);
+
+ *dst++ = enc_table[(raw_u32 >> 26) & BASE64_ENC_BITMASK];
+ *dst++ = enc_table[(raw_u32 >> 20) & BASE64_ENC_BITMASK];
+ *dst++ = (src_len >= 2) ? enc_table[(raw_u32 >> 14) & BASE64_ENC_BITMASK] : BASE64_PADDING_CHAR;
+ *dst++ = (src_len == 3) ? enc_table[(raw_u32 >> 8) & BASE64_ENC_BITMASK] : BASE64_PADDING_CHAR;
+
+out:
+ *dst = '\0';
+
+ return 0;
+}
+
+int
+spdk_base64_encode(char *dst, const void *src, size_t src_len)
+{
+ return _spdk_base64_encode(dst, base64_enc_table, src, src_len);
+}
+
+int
+spdk_base64_urlsafe_encode(char *dst, const void *src, size_t src_len)
+{
+ return _spdk_base64_encode(dst, base64_urfsafe_enc_table, src, src_len);
+}
+
+static int
+_spdk_base64_decode(void *dst, size_t *_dst_len, const uint8_t *dec_table, const char *src)
+{
+ size_t src_strlen, dst_len;
+ size_t tail_len = 0;
+ const uint8_t *src_in;
+ uint32_t tmp[4];
+ int i;
+
+ if (!dst || !src) {
+ return -EINVAL;
+ }
+
+ src_strlen = strlen(src);
+
+ /* strlen of src should be 4n */
+ if (src_strlen == 0 || src_strlen % 4 != 0) {
+ return -EINVAL;
+ }
+
+ /* Consider Base64 padding, it at most has 2 padding characters. */
+ for (i = 0; i < 2; i++) {
+ if (src[src_strlen - 1] != BASE64_PADDING_CHAR) {
+ break;
+ }
+ src_strlen--;
+ }
+
+ /* strlen of src without padding shouldn't be 4n+1 */
+ if (src_strlen == 0 || src_strlen % 4 == 1) {
+ return -EINVAL;
+ }
+
+ dst_len = spdk_base64_get_decoded_len(src_strlen);
+ src_in = (const uint8_t *) src;
+
+ /* space of dst can be used by to_be32 */
+ while (src_strlen > 4) {
+ tmp[0] = dec_table[*src_in++];
+ tmp[1] = dec_table[*src_in++];
+ tmp[2] = dec_table[*src_in++];
+ tmp[3] = dec_table[*src_in++];
+
+ if (tmp[0] == 255 || tmp[1] == 255 || tmp[2] == 255 || tmp[3] == 255) {
+ return -EINVAL;
+ }
+
+ to_be32(dst, tmp[3] << 8 | tmp[2] << 14 | tmp[1] << 20 | tmp[0] << 26);
+
+ dst += 3;
+ src_strlen -= 4;
+ }
+
+ /* space of dst is not enough to be used by to_be32 */
+ tmp[0] = dec_table[src_in[0]];
+ tmp[1] = dec_table[src_in[1]];
+ tmp[2] = (src_strlen >= 3) ? dec_table[src_in[2]] : 0;
+ tmp[3] = (src_strlen == 4) ? dec_table[src_in[3]] : 0;
+ tail_len = src_strlen - 1;
+
+ if (tmp[0] == 255 || tmp[1] == 255 || tmp[2] == 255 || tmp[3] == 255) {
+ return -EINVAL;
+ }
+
+ to_be32(&tmp[3], tmp[3] << 8 | tmp[2] << 14 | tmp[1] << 20 | tmp[0] << 26);
+ memcpy(dst, (uint8_t *)&tmp[3], tail_len);
+
+ /* Assign pointers */
+ if (_dst_len) {
+ *_dst_len = dst_len;
+ }
+
+ return 0;
+}
+
+int
+spdk_base64_decode(void *dst, size_t *dst_len, const char *src)
+{
+ return _spdk_base64_decode(dst, dst_len, base64_dec_table, src);
+}
+
+int
+spdk_base64_urlsafe_decode(void *dst, size_t *dst_len, const char *src)
+{
+ return _spdk_base64_decode(dst, dst_len, base64_urlsafe_dec_table, src);
+}
diff --git a/src/spdk/lib/util/bit_array.c b/src/spdk/lib/util/bit_array.c
new file mode 100644
index 00000000..d6c112f7
--- /dev/null
+++ b/src/spdk/lib/util/bit_array.c
@@ -0,0 +1,313 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/bit_array.h"
+#include "spdk/env.h"
+
+#include "spdk/likely.h"
+#include "spdk/util.h"
+
+typedef uint64_t spdk_bit_array_word;
+#define SPDK_BIT_ARRAY_WORD_TZCNT(x) (__builtin_ctzll(x))
+#define SPDK_BIT_ARRAY_WORD_POPCNT(x) (__builtin_popcountll(x))
+#define SPDK_BIT_ARRAY_WORD_C(x) ((spdk_bit_array_word)(x))
+#define SPDK_BIT_ARRAY_WORD_BYTES sizeof(spdk_bit_array_word)
+#define SPDK_BIT_ARRAY_WORD_BITS (SPDK_BIT_ARRAY_WORD_BYTES * 8)
+#define SPDK_BIT_ARRAY_WORD_INDEX_SHIFT spdk_u32log2(SPDK_BIT_ARRAY_WORD_BITS)
+#define SPDK_BIT_ARRAY_WORD_INDEX_MASK ((1u << SPDK_BIT_ARRAY_WORD_INDEX_SHIFT) - 1)
+
+struct spdk_bit_array {
+ uint32_t bit_count;
+ spdk_bit_array_word words[];
+};
+
+struct spdk_bit_array *
+spdk_bit_array_create(uint32_t num_bits)
+{
+ struct spdk_bit_array *ba = NULL;
+
+ spdk_bit_array_resize(&ba, num_bits);
+
+ return ba;
+}
+
+void
+spdk_bit_array_free(struct spdk_bit_array **bap)
+{
+ struct spdk_bit_array *ba;
+
+ if (!bap) {
+ return;
+ }
+
+ ba = *bap;
+ *bap = NULL;
+ spdk_dma_free(ba);
+}
+
+static inline uint32_t
+spdk_bit_array_word_count(uint32_t num_bits)
+{
+ return (num_bits + SPDK_BIT_ARRAY_WORD_BITS - 1) >> SPDK_BIT_ARRAY_WORD_INDEX_SHIFT;
+}
+
+static inline spdk_bit_array_word
+spdk_bit_array_word_mask(uint32_t num_bits)
+{
+ assert(num_bits < SPDK_BIT_ARRAY_WORD_BITS);
+ return (SPDK_BIT_ARRAY_WORD_C(1) << num_bits) - 1;
+}
+
+int
+spdk_bit_array_resize(struct spdk_bit_array **bap, uint32_t num_bits)
+{
+ struct spdk_bit_array *new_ba;
+ uint32_t old_word_count, new_word_count;
+ size_t new_size;
+
+ /*
+ * Max number of bits allowed is UINT32_MAX - 1, because we use UINT32_MAX to denote
+ * when a set or cleared bit cannot be found.
+ */
+ if (!bap || num_bits == UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ new_word_count = spdk_bit_array_word_count(num_bits);
+ new_size = offsetof(struct spdk_bit_array, words) + new_word_count * SPDK_BIT_ARRAY_WORD_BYTES;
+
+ /*
+ * Always keep one extra word with a 0 and a 1 past the actual required size so that the
+ * find_first functions can just keep going until they match.
+ */
+ new_size += SPDK_BIT_ARRAY_WORD_BYTES;
+
+ new_ba = (struct spdk_bit_array *)spdk_dma_realloc(*bap, new_size, 64, NULL);
+ if (!new_ba) {
+ return -ENOMEM;
+ }
+
+ /*
+ * Set up special extra word (see above comment about find_first_clear).
+ *
+ * This is set to 0b10 so that find_first_clear will find a 0 at the very first
+ * bit past the end of the buffer, and find_first_set will find a 1 at the next bit
+ * past that.
+ */
+ new_ba->words[new_word_count] = 0x2;
+
+ if (*bap == NULL) {
+ old_word_count = 0;
+ new_ba->bit_count = 0;
+ } else {
+ old_word_count = spdk_bit_array_word_count(new_ba->bit_count);
+ }
+
+ if (new_word_count > old_word_count) {
+ /* Zero out new entries */
+ memset(&new_ba->words[old_word_count], 0,
+ (new_word_count - old_word_count) * SPDK_BIT_ARRAY_WORD_BYTES);
+ } else if (new_word_count == old_word_count && num_bits < new_ba->bit_count) {
+ /* Make sure any existing partial last word is cleared beyond the new num_bits. */
+ uint32_t last_word_bits;
+ spdk_bit_array_word mask;
+
+ last_word_bits = num_bits & SPDK_BIT_ARRAY_WORD_INDEX_MASK;
+ mask = spdk_bit_array_word_mask(last_word_bits);
+ new_ba->words[old_word_count - 1] &= mask;
+ }
+
+ new_ba->bit_count = num_bits;
+ *bap = new_ba;
+ return 0;
+}
+
+uint32_t
+spdk_bit_array_capacity(const struct spdk_bit_array *ba)
+{
+ return ba->bit_count;
+}
+
+static inline int
+_spdk_bit_array_get_word(const struct spdk_bit_array *ba, uint32_t bit_index,
+ uint32_t *word_index, uint32_t *word_bit_index)
+{
+ if (spdk_unlikely(bit_index >= ba->bit_count)) {
+ return -EINVAL;
+ }
+
+ *word_index = bit_index >> SPDK_BIT_ARRAY_WORD_INDEX_SHIFT;
+ *word_bit_index = bit_index & SPDK_BIT_ARRAY_WORD_INDEX_MASK;
+
+ return 0;
+}
+
+bool
+spdk_bit_array_get(const struct spdk_bit_array *ba, uint32_t bit_index)
+{
+ uint32_t word_index, word_bit_index;
+
+ if (_spdk_bit_array_get_word(ba, bit_index, &word_index, &word_bit_index)) {
+ return false;
+ }
+
+ return (ba->words[word_index] >> word_bit_index) & 1U;
+}
+
+int
+spdk_bit_array_set(struct spdk_bit_array *ba, uint32_t bit_index)
+{
+ uint32_t word_index, word_bit_index;
+
+ if (_spdk_bit_array_get_word(ba, bit_index, &word_index, &word_bit_index)) {
+ return -EINVAL;
+ }
+
+ ba->words[word_index] |= (SPDK_BIT_ARRAY_WORD_C(1) << word_bit_index);
+ return 0;
+}
+
+void
+spdk_bit_array_clear(struct spdk_bit_array *ba, uint32_t bit_index)
+{
+ uint32_t word_index, word_bit_index;
+
+ if (_spdk_bit_array_get_word(ba, bit_index, &word_index, &word_bit_index)) {
+ /*
+ * Clearing past the end of the bit array is a no-op, since bit past the end
+ * are implicitly 0.
+ */
+ return;
+ }
+
+ ba->words[word_index] &= ~(SPDK_BIT_ARRAY_WORD_C(1) << word_bit_index);
+}
+
+static inline uint32_t
+_spdk_bit_array_find_first(const struct spdk_bit_array *ba, uint32_t start_bit_index,
+ spdk_bit_array_word xor_mask)
+{
+ uint32_t word_index, first_word_bit_index;
+ spdk_bit_array_word word, first_word_mask;
+ const spdk_bit_array_word *words, *cur_word;
+
+ if (spdk_unlikely(start_bit_index >= ba->bit_count)) {
+ return ba->bit_count;
+ }
+
+ word_index = start_bit_index >> SPDK_BIT_ARRAY_WORD_INDEX_SHIFT;
+ words = ba->words;
+ cur_word = &words[word_index];
+
+ /*
+ * Special case for first word: skip start_bit_index % SPDK_BIT_ARRAY_WORD_BITS bits
+ * within the first word.
+ */
+ first_word_bit_index = start_bit_index & SPDK_BIT_ARRAY_WORD_INDEX_MASK;
+ first_word_mask = spdk_bit_array_word_mask(first_word_bit_index);
+
+ word = (*cur_word ^ xor_mask) & ~first_word_mask;
+
+ /*
+ * spdk_bit_array_resize() guarantees that an extra word with a 1 and a 0 will always be
+ * at the end of the words[] array, so just keep going until a word matches.
+ */
+ while (word == 0) {
+ word = *++cur_word ^ xor_mask;
+ }
+
+ return ((uintptr_t)cur_word - (uintptr_t)words) * 8 + SPDK_BIT_ARRAY_WORD_TZCNT(word);
+}
+
+
+uint32_t
+spdk_bit_array_find_first_set(const struct spdk_bit_array *ba, uint32_t start_bit_index)
+{
+ uint32_t bit_index;
+
+ bit_index = _spdk_bit_array_find_first(ba, start_bit_index, 0);
+
+ /*
+ * If we ran off the end of the array and found the 1 bit in the extra word,
+ * return UINT32_MAX to indicate no actual 1 bits were found.
+ */
+ if (bit_index >= ba->bit_count) {
+ bit_index = UINT32_MAX;
+ }
+
+ return bit_index;
+}
+
+uint32_t
+spdk_bit_array_find_first_clear(const struct spdk_bit_array *ba, uint32_t start_bit_index)
+{
+ uint32_t bit_index;
+
+ bit_index = _spdk_bit_array_find_first(ba, start_bit_index, SPDK_BIT_ARRAY_WORD_C(-1));
+
+ /*
+ * If we ran off the end of the array and found the 0 bit in the extra word,
+ * return UINT32_MAX to indicate no actual 0 bits were found.
+ */
+ if (bit_index >= ba->bit_count) {
+ bit_index = UINT32_MAX;
+ }
+
+ return bit_index;
+}
+
+uint32_t
+spdk_bit_array_count_set(const struct spdk_bit_array *ba)
+{
+ const spdk_bit_array_word *cur_word = ba->words;
+ uint32_t word_count = spdk_bit_array_word_count(ba->bit_count);
+ uint32_t set_count = 0;
+
+ while (word_count--) {
+ /*
+ * No special treatment is needed for the last (potentially partial) word, since
+ * spdk_bit_array_resize() makes sure the bits past bit_count are cleared.
+ */
+ set_count += SPDK_BIT_ARRAY_WORD_POPCNT(*cur_word++);
+ }
+
+ return set_count;
+}
+
+uint32_t
+spdk_bit_array_count_clear(const struct spdk_bit_array *ba)
+{
+ return ba->bit_count - spdk_bit_array_count_set(ba);
+}
diff --git a/src/spdk/lib/util/cpuset.c b/src/spdk/lib/util/cpuset.c
new file mode 100644
index 00000000..1a02e59f
--- /dev/null
+++ b/src/spdk/lib/util/cpuset.c
@@ -0,0 +1,320 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/cpuset.h"
+#include "spdk/log.h"
+
+struct spdk_cpuset {
+ char str[SPDK_CPUSET_SIZE / 4];
+ uint8_t cpus[SPDK_CPUSET_SIZE / 8];
+};
+
+struct spdk_cpuset *
+spdk_cpuset_alloc(void)
+{
+ return (struct spdk_cpuset *)calloc(sizeof(struct spdk_cpuset), 1);
+}
+
+void
+spdk_cpuset_free(struct spdk_cpuset *set)
+{
+ free(set);
+}
+
+bool
+spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
+{
+ assert(set1 != NULL);
+ assert(set2 != NULL);
+ return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
+}
+
+void
+spdk_cpuset_copy(struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
+{
+ assert(set1 != NULL);
+ assert(set2 != NULL);
+ memcpy(&set1->cpus, &set2->cpus, sizeof(set2->cpus));
+}
+
+void
+spdk_cpuset_and(struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
+{
+ unsigned int i;
+ assert(set1 != NULL);
+ assert(set2 != NULL);
+ for (i = 0; i < sizeof(set2->cpus); i++) {
+ set1->cpus[i] &= set2->cpus[i];
+ }
+}
+
+void
+spdk_cpuset_or(struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
+{
+ unsigned int i;
+ assert(set1 != NULL);
+ assert(set2 != NULL);
+ for (i = 0; i < sizeof(set2->cpus); i++) {
+ set1->cpus[i] |= set2->cpus[i];
+ }
+}
+
+void
+spdk_cpuset_zero(struct spdk_cpuset *set)
+{
+ assert(set != NULL);
+ memset(set->cpus, 0, sizeof(set->cpus));
+}
+
+void
+spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
+{
+ assert(set != NULL);
+ assert(cpu < sizeof(set->cpus) * 8);
+ if (state) {
+ set->cpus[cpu / 8] |= (1U << (cpu % 8));
+ } else {
+ set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
+ }
+}
+
+bool
+spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
+{
+ assert(set != NULL);
+ assert(cpu < sizeof(set->cpus) * 8);
+ return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
+}
+
+uint32_t
+spdk_cpuset_count(const struct spdk_cpuset *set)
+{
+ uint32_t count = 0;
+ uint8_t n;
+ unsigned int i;
+ for (i = 0; i < sizeof(set->cpus); i++) {
+ n = set->cpus[i];
+ while (n) {
+ n &= (n - 1);
+ count++;
+ }
+ }
+ return count;
+}
+
+const char *
+spdk_cpuset_fmt(struct spdk_cpuset *set)
+{
+ uint32_t lcore, lcore_max = 0;
+ int val, i, n;
+ char *ptr;
+ static const char *hex = "0123456789abcdef";
+
+ assert(set != NULL);
+
+ for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
+ if (spdk_cpuset_get_cpu(set, lcore)) {
+ lcore_max = lcore;
+ }
+ }
+
+ ptr = set->str;
+ n = lcore_max / 8;
+ val = set->cpus[n];
+
+ /* Store first number only if it is not leading zero */
+ if ((val & 0xf0) != 0) {
+ *(ptr++) = hex[(val & 0xf0) >> 4];
+ }
+ *(ptr++) = hex[val & 0x0f];
+
+ for (i = n - 1; i >= 0; i--) {
+ val = set->cpus[i];
+ *(ptr++) = hex[(val & 0xf0) >> 4];
+ *(ptr++) = hex[val & 0x0f];
+ }
+ *ptr = '\0';
+
+ return set->str;
+}
+
+static int
+hex_value(uint8_t c)
+{
+#define V(x, y) [x] = y + 1
+ static const int8_t val[256] = {
+ V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
+ V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
+ V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
+ V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
+ };
+#undef V
+
+ return val[c] - 1;
+}
+
+static int
+parse_list(const char *mask, struct spdk_cpuset *set)
+{
+ char *end;
+ const char *ptr = mask;
+ uint32_t lcore;
+ uint32_t lcore_min, lcore_max;
+
+ spdk_cpuset_zero(set);
+ lcore_min = UINT32_MAX;
+
+ ptr++;
+ end = (char *)ptr;
+ do {
+ while (isblank(*ptr)) {
+ ptr++;
+ }
+ if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
+ goto invalid_character;
+ }
+
+ errno = 0;
+ lcore = strtoul(ptr, &end, 10);
+ if (errno) {
+ SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
+ return -1;
+ }
+
+ if (lcore >= sizeof(set->cpus) * 8) {
+ SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
+ return -1;
+ }
+
+ while (isblank(*end)) {
+ end++;
+ }
+
+ if (*end == '-') {
+ lcore_min = lcore;
+ } else if (*end == ',' || *end == ']') {
+ lcore_max = lcore;
+ if (lcore_min == UINT32_MAX) {
+ lcore_min = lcore;
+ }
+ if (lcore_min > lcore_max) {
+ SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
+ lcore_min, lcore_max);
+ return -1;
+ }
+ for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
+ spdk_cpuset_set_cpu(set, lcore, true);
+ }
+ lcore_min = UINT32_MAX;
+ } else {
+ goto invalid_character;
+ }
+
+ ptr = end + 1;
+
+ } while (*end != ']');
+
+ return 0;
+
+invalid_character:
+ if (*end == '\0') {
+ SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
+ } else {
+ SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
+ }
+ return -1;
+}
+
+static int
+parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
+{
+ int i, j;
+ char c;
+ int val;
+ uint32_t lcore = 0;
+
+ if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
+ mask += 2;
+ len -= 2;
+ }
+
+ spdk_cpuset_zero(set);
+ for (i = len - 1; i >= 0; i--) {
+ c = mask[i];
+ val = hex_value(c);
+ if (val < 0) {
+ /* Invalid character */
+ SPDK_ERRLOG("Invalid character in core mask '%s' (%c)\n", mask, c);
+ return -1;
+ }
+ for (j = 0; j < 4 && lcore < sizeof(set->cpus); j++, lcore++) {
+ if ((1 << j) & val) {
+ spdk_cpuset_set_cpu(set, lcore, true);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
+{
+ int ret;
+ size_t len;
+
+ if (mask == NULL || set == NULL) {
+ return -1;
+ }
+
+ while (isblank(*mask)) {
+ mask++;
+ }
+
+ len = strlen(mask);
+ while (len > 0 && isblank(mask[len - 1])) {
+ len--;
+ }
+
+ if (len == 0) {
+ return -1;
+ }
+
+ if (mask[0] == '[') {
+ ret = parse_list(mask, set);
+ } else {
+ ret = parse_mask(mask, set, len);
+ }
+
+ return ret;
+}
diff --git a/src/spdk/lib/util/crc16.c b/src/spdk/lib/util/crc16.c
new file mode 100644
index 00000000..491c9058
--- /dev/null
+++ b/src/spdk/lib/util/crc16.c
@@ -0,0 +1,53 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/crc16.h"
+
+uint16_t
+spdk_crc16_t10dif(const void *buf, size_t len)
+{
+ uint32_t j, rem = 0;
+ const uint8_t *data = (const uint8_t *)buf;
+ size_t i;
+
+ uint16_t poly = SPDK_T10DIF_CRC16_POLYNOMIAL;
+
+ for (i = 0; i < len; i++) {
+ rem = rem ^ (data[i] << 8);
+ for (j = 0; j < 8; j++) {
+ rem = rem << 1;
+ rem = (rem & 0x10000) ? rem ^ poly : rem;
+ }
+ }
+ return (uint16_t)rem;
+}
diff --git a/src/spdk/lib/util/crc32.c b/src/spdk/lib/util/crc32.c
new file mode 100644
index 00000000..dfef9c54
--- /dev/null
+++ b/src/spdk/lib/util/crc32.c
@@ -0,0 +1,66 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/crc32.h"
+
+void
+spdk_crc32_table_init(struct spdk_crc32_table *table, uint32_t polynomial_reflect)
+{
+ int i, j;
+ uint32_t val;
+
+ for (i = 0; i < 256; i++) {
+ val = i;
+ for (j = 0; j < 8; j++) {
+ if (val & 1) {
+ val = (val >> 1) ^ polynomial_reflect;
+ } else {
+ val = (val >> 1);
+ }
+ }
+ table->table[i] = val;
+ }
+}
+
+uint32_t
+spdk_crc32_update(const struct spdk_crc32_table *table, const void *buf, size_t len, uint32_t crc)
+{
+ const uint8_t *buf_u8 = buf;
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ crc = (crc >> 8) ^ table->table[(crc ^ buf_u8[i]) & 0xff];
+ }
+
+ return crc;
+}
diff --git a/src/spdk/lib/util/crc32_ieee.c b/src/spdk/lib/util/crc32_ieee.c
new file mode 100644
index 00000000..2956e3fc
--- /dev/null
+++ b/src/spdk/lib/util/crc32_ieee.c
@@ -0,0 +1,48 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/crc32.h"
+
+static struct spdk_crc32_table g_crc32_ieee_table;
+
+__attribute__((constructor)) static void
+spdk_crc32_ieee_init(void)
+{
+ spdk_crc32_table_init(&g_crc32_ieee_table, SPDK_CRC32_POLYNOMIAL_REFLECT);
+}
+
+uint32_t
+spdk_crc32_ieee_update(const void *buf, size_t len, uint32_t crc)
+{
+ return spdk_crc32_update(&g_crc32_ieee_table, buf, len, crc);
+}
diff --git a/src/spdk/lib/util/crc32c.c b/src/spdk/lib/util/crc32c.c
new file mode 100644
index 00000000..e95283b3
--- /dev/null
+++ b/src/spdk/lib/util/crc32c.c
@@ -0,0 +1,89 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/crc32.h"
+
+#if defined(__x86_64__) && defined(__SSE4_2__)
+#include <x86intrin.h>
+
+uint32_t
+spdk_crc32c_update(const void *buf, size_t len, uint32_t crc)
+{
+ uint64_t crc_tmp64;
+ size_t count;
+
+ /* _mm_crc32_u64() needs a 64-bit intermediate value */
+ crc_tmp64 = crc;
+
+ /* Process as much of the buffer as possible in 64-bit blocks. */
+ count = len / 8;
+ while (count--) {
+ uint64_t block;
+
+ /*
+ * Use memcpy() to avoid unaligned loads, which are undefined behavior in C.
+ * The compiler will optimize out the memcpy() in release builds.
+ */
+ memcpy(&block, buf, sizeof(block));
+ crc_tmp64 = _mm_crc32_u64(crc_tmp64, block);
+ buf += sizeof(block);
+ }
+ crc = (uint32_t)crc_tmp64;
+
+ /* Handle any trailing bytes. */
+ count = len & 7;
+ while (count--) {
+ crc = _mm_crc32_u8(crc, *(const uint8_t *)buf);
+ buf++;
+ }
+
+ return crc;
+}
+
+#else /* SSE 4.2 (CRC32 instruction) not available */
+
+static struct spdk_crc32_table g_crc32c_table;
+
+__attribute__((constructor)) static void
+spdk_crc32c_init(void)
+{
+ spdk_crc32_table_init(&g_crc32c_table, SPDK_CRC32C_POLYNOMIAL_REFLECT);
+}
+
+uint32_t
+spdk_crc32c_update(const void *buf, size_t len, uint32_t crc)
+{
+ return spdk_crc32_update(&g_crc32c_table, buf, len, crc);
+}
+
+#endif
diff --git a/src/spdk/lib/util/fd.c b/src/spdk/lib/util/fd.c
new file mode 100644
index 00000000..6b0d0d55
--- /dev/null
+++ b/src/spdk/lib/util/fd.c
@@ -0,0 +1,103 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/fd.h"
+
+#ifdef __linux__
+#include <linux/fs.h>
+#endif
+
+static uint64_t
+dev_get_size(int fd)
+{
+#if defined(DIOCGMEDIASIZE) /* FreeBSD */
+ off_t size;
+
+ if (ioctl(fd, DIOCGMEDIASIZE, &size) == 0) {
+ return size;
+ }
+#elif defined(__linux__) && defined(BLKGETSIZE64)
+ uint64_t size;
+
+ if (ioctl(fd, BLKGETSIZE64, &size) == 0) {
+ return size;
+ }
+#endif
+
+ return 0;
+}
+
+uint32_t
+spdk_fd_get_blocklen(int fd)
+{
+#if defined(DKIOCGETBLOCKSIZE) /* FreeBSD */
+ uint32_t blocklen;
+
+ if (ioctl(fd, DKIOCGETBLOCKSIZE, &blocklen) == 0) {
+ return blocklen;
+ }
+#elif defined(__linux__) && defined(BLKSSZGET)
+ uint32_t blocklen;
+
+ if (ioctl(fd, BLKSSZGET, &blocklen) == 0) {
+ return blocklen;
+ }
+#endif
+
+ return 0;
+}
+
+uint64_t
+spdk_fd_get_size(int fd)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) != 0) {
+ return 0;
+ }
+
+ if (S_ISLNK(st.st_mode)) {
+ return 0;
+ }
+
+ if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
+ return dev_get_size(fd);
+ } else if (S_ISREG(st.st_mode)) {
+ return st.st_size;
+ }
+
+ /* Not REG, CHR or BLK */
+ return 0;
+}
diff --git a/src/spdk/lib/util/strerror_tls.c b/src/spdk/lib/util/strerror_tls.c
new file mode 100644
index 00000000..c9dc8f13
--- /dev/null
+++ b/src/spdk/lib/util/strerror_tls.c
@@ -0,0 +1,43 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/string.h"
+
+static __thread char strerror_message[64];
+
+const char *
+spdk_strerror(int errnum)
+{
+ spdk_strerror_r(errnum, strerror_message, sizeof(strerror_message));
+ return strerror_message;
+}
diff --git a/src/spdk/lib/util/string.c b/src/spdk/lib/util/string.c
new file mode 100644
index 00000000..455aa20f
--- /dev/null
+++ b/src/spdk/lib/util/string.c
@@ -0,0 +1,405 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/string.h"
+
+char *
+spdk_vsprintf_alloc(const char *format, va_list args)
+{
+ va_list args_copy;
+ char *buf;
+ size_t bufsize;
+ int rc;
+
+ /* Try with a small buffer first. */
+ bufsize = 32;
+
+ /* Limit maximum buffer size to something reasonable so we don't loop forever. */
+ while (bufsize <= 1024 * 1024) {
+ buf = malloc(bufsize);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ va_copy(args_copy, args);
+ rc = vsnprintf(buf, bufsize, format, args_copy);
+ va_end(args_copy);
+
+ /*
+ * If vsnprintf() returned a count within our current buffer size, we are done.
+ * The count does not include the \0 terminator, so rc == bufsize is not OK.
+ */
+ if (rc >= 0 && (size_t)rc < bufsize) {
+ return buf;
+ }
+
+ /*
+ * vsnprintf() should return the required space, but some libc versions do not
+ * implement this correctly, so just double the buffer size and try again.
+ *
+ * We don't need the data in buf, so rather than realloc(), use free() and malloc()
+ * again to avoid a copy.
+ */
+ free(buf);
+ bufsize *= 2;
+ }
+
+ return NULL;
+}
+
+char *
+spdk_sprintf_alloc(const char *format, ...)
+{
+ va_list args;
+ char *ret;
+
+ va_start(args, format);
+ ret = spdk_vsprintf_alloc(format, args);
+ va_end(args);
+
+ return ret;
+}
+
+char *
+spdk_strlwr(char *s)
+{
+ char *p;
+
+ if (s == NULL) {
+ return NULL;
+ }
+
+ p = s;
+ while (*p != '\0') {
+ *p = tolower(*p);
+ p++;
+ }
+
+ return s;
+}
+
+char *
+spdk_strsepq(char **stringp, const char *delim)
+{
+ char *p, *q, *r;
+ int quoted = 0, bslash = 0;
+
+ p = *stringp;
+ if (p == NULL) {
+ return NULL;
+ }
+
+ r = q = p;
+ while (*q != '\0' && *q != '\n') {
+ /* eat quoted characters */
+ if (bslash) {
+ bslash = 0;
+ *r++ = *q++;
+ continue;
+ } else if (quoted) {
+ if (quoted == '"' && *q == '\\') {
+ bslash = 1;
+ q++;
+ continue;
+ } else if (*q == quoted) {
+ quoted = 0;
+ q++;
+ continue;
+ }
+ *r++ = *q++;
+ continue;
+ } else if (*q == '\\') {
+ bslash = 1;
+ q++;
+ continue;
+ } else if (*q == '"' || *q == '\'') {
+ quoted = *q;
+ q++;
+ continue;
+ }
+
+ /* separator? */
+ if (strchr(delim, *q) == NULL) {
+ *r++ = *q++;
+ continue;
+ }
+
+ /* new string */
+ q++;
+ break;
+ }
+ *r = '\0';
+
+ /* skip tailer */
+ while (*q != '\0' && strchr(delim, *q) != NULL) {
+ q++;
+ }
+ if (*q != '\0') {
+ *stringp = q;
+ } else {
+ *stringp = NULL;
+ }
+
+ return p;
+}
+
+char *
+spdk_str_trim(char *s)
+{
+ char *p, *q;
+
+ if (s == NULL) {
+ return NULL;
+ }
+
+ /* remove header */
+ p = s;
+ while (*p != '\0' && isspace(*p)) {
+ p++;
+ }
+
+ /* remove tailer */
+ q = p + strlen(p);
+ while (q - 1 >= p && isspace(*(q - 1))) {
+ q--;
+ *q = '\0';
+ }
+
+ /* if remove header, move */
+ if (p != s) {
+ q = s;
+ while (*p != '\0') {
+ *q++ = *p++;
+ }
+ *q = '\0';
+ }
+
+ return s;
+}
+
+void
+spdk_strcpy_pad(void *dst, const char *src, size_t size, int pad)
+{
+ size_t len;
+
+ len = strlen(src);
+ if (len < size) {
+ memcpy(dst, src, len);
+ memset((char *)dst + len, pad, size - len);
+ } else {
+ memcpy(dst, src, size);
+ }
+}
+
+size_t
+spdk_strlen_pad(const void *str, size_t size, int pad)
+{
+ const uint8_t *start;
+ const uint8_t *iter;
+ uint8_t pad_byte;
+
+ pad_byte = (uint8_t)pad;
+ start = (const uint8_t *)str;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ iter = start + size - 1;
+ while (1) {
+ if (*iter != pad_byte) {
+ return iter - start + 1;
+ }
+
+ if (iter == start) {
+ /* Hit the start of the string finding only pad_byte. */
+ return 0;
+ }
+ iter--;
+ }
+}
+
+int
+spdk_parse_ip_addr(char *ip, char **host, char **port)
+{
+ char *p;
+
+ if (ip == NULL) {
+ return -EINVAL;
+ }
+
+ *host = NULL;
+ *port = NULL;
+
+ if (ip[0] == '[') {
+ /* IPv6 */
+ p = strchr(ip, ']');
+ if (p == NULL) {
+ return -EINVAL;
+ }
+ *host = &ip[1];
+ *p = '\0';
+
+ p++;
+ if (*p == '\0') {
+ return 0;
+ } else if (*p != ':') {
+ return -EINVAL;
+ }
+
+ p++;
+ if (*p == '\0') {
+ return 0;
+ }
+
+ *port = p;
+ } else {
+ /* IPv4 */
+ p = strchr(ip, ':');
+ if (p == NULL) {
+ *host = ip;
+ return 0;
+ }
+
+ *host = ip;
+ *p = '\0';
+
+ p++;
+ if (*p == '\0') {
+ return 0;
+ }
+
+ *port = p;
+ }
+
+ return 0;
+}
+
+size_t
+spdk_str_chomp(char *s)
+{
+ size_t len = strlen(s);
+ size_t removed = 0;
+
+ while (len > 0) {
+ if (s[len - 1] != '\r' && s[len - 1] != '\n') {
+ break;
+ }
+
+ s[len - 1] = '\0';
+ len--;
+ removed++;
+ }
+
+ return removed;
+}
+
+void
+spdk_strerror_r(int errnum, char *buf, size_t buflen)
+{
+ int rc;
+
+#if defined(__USE_GNU)
+ char *new_buffer;
+ new_buffer = strerror_r(errnum, buf, buflen);
+ if (new_buffer != NULL) {
+ snprintf(buf, buflen, "%s", new_buffer);
+ rc = 0;
+ } else {
+ rc = 1;
+ }
+#else
+ rc = strerror_r(errnum, buf, buflen);
+#endif
+
+ if (rc != 0) {
+ snprintf(buf, buflen, "Unknown error %d", errnum);
+ }
+}
+
+int
+spdk_parse_capacity(const char *cap_str, uint64_t *cap, bool *has_prefix)
+{
+ int rc;
+ char bin_prefix;
+
+ rc = sscanf(cap_str, "%"SCNu64"%c", cap, &bin_prefix);
+ if (rc == 1) {
+ *has_prefix = false;
+ return 0;
+ } else if (rc == 0) {
+ if (errno == 0) {
+ /* No scanf matches - the string does not start with a digit */
+ return -EINVAL;
+ } else {
+ /* Parsing error */
+ return -errno;
+ }
+ }
+
+ *has_prefix = true;
+ switch (bin_prefix) {
+ case 'k':
+ case 'K':
+ *cap *= 1024;
+ break;
+ case 'm':
+ case 'M':
+ *cap *= 1024 * 1024;
+ break;
+ case 'g':
+ case 'G':
+ *cap *= 1024 * 1024 * 1024;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+bool
+spdk_mem_all_zero(const void *data, size_t size)
+{
+ const uint8_t *buf = data;
+
+ while (size--) {
+ if (*buf++ != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/spdk/lib/util/uuid.c b/src/spdk/lib/util/uuid.c
new file mode 100644
index 00000000..1af7368f
--- /dev/null
+++ b/src/spdk/lib/util/uuid.c
@@ -0,0 +1,67 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/uuid.h"
+
+#include <uuid/uuid.h>
+
+SPDK_STATIC_ASSERT(sizeof(struct spdk_uuid) == sizeof(uuid_t), "Size mismatch");
+
+int
+spdk_uuid_parse(struct spdk_uuid *uuid, const char *uuid_str)
+{
+ return uuid_parse(uuid_str, (void *)uuid) == 0 ? 0 : -EINVAL;
+}
+
+int
+spdk_uuid_fmt_lower(char *uuid_str, size_t uuid_str_size, const struct spdk_uuid *uuid)
+{
+ if (uuid_str_size < SPDK_UUID_STRING_LEN) {
+ return -EINVAL;
+ }
+
+ uuid_unparse_lower((void *)uuid, uuid_str);
+ return 0;
+}
+
+int
+spdk_uuid_compare(const struct spdk_uuid *u1, const struct spdk_uuid *u2)
+{
+ return uuid_compare((void *)u1, (void *)u2);
+}
+
+void
+spdk_uuid_generate(struct spdk_uuid *uuid)
+{
+ uuid_generate((void *)uuid);
+}