summaryrefslogtreecommitdiffstats
path: root/src/pmdk/src/librpmem/rpmem_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdk/src/librpmem/rpmem_util.c')
-rw-r--r--src/pmdk/src/librpmem/rpmem_util.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/pmdk/src/librpmem/rpmem_util.c b/src/pmdk/src/librpmem/rpmem_util.c
new file mode 100644
index 000000000..6709d7298
--- /dev/null
+++ b/src/pmdk/src/librpmem/rpmem_util.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright 2016-2019, Intel Corporation */
+
+/*
+ * rpmem_util.c -- util functions for librpmem source file
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "out.h"
+#include "os.h"
+#include "librpmem.h"
+#include "rpmem_proto.h"
+#include "rpmem_common.h"
+#include "rpmem_util.h"
+
+static const struct rpmem_err_str_errno {
+ int err;
+ const char *str;
+} rpmem_err_str_errno[MAX_RPMEM_ERR] = {
+ [RPMEM_SUCCESS] = {
+ .err = 0,
+ .str = "Success",
+ },
+ [RPMEM_ERR_BADPROTO] = {
+ .err = EPROTONOSUPPORT,
+ .str = "Protocol version number mismatch",
+ },
+ [RPMEM_ERR_BADNAME] = {
+ .err = EINVAL,
+ .str = "Invalid pool descriptor",
+ },
+ [RPMEM_ERR_BADSIZE] = {
+ .err = EFBIG,
+ .str = "Invalid pool size",
+ },
+ [RPMEM_ERR_BADNLANES] = {
+ .err = EINVAL,
+ .str = "Invalid number of lanes",
+ },
+ [RPMEM_ERR_BADPROVIDER] = {
+ .err = EINVAL,
+ .str = "Invalid provider",
+ },
+ [RPMEM_ERR_FATAL] = {
+ .err = EREMOTEIO,
+ .str = "Fatal error",
+ },
+ [RPMEM_ERR_FATAL_CONN] = {
+ .err = ECONNABORTED,
+ .str = "Fatal in-band connection error",
+ },
+ [RPMEM_ERR_BUSY] = {
+ .err = EBUSY,
+ .str = "Pool already in use",
+ },
+ [RPMEM_ERR_EXISTS] = {
+ .err = EEXIST,
+ .str = "Pool already exists",
+ },
+ [RPMEM_ERR_PROVNOSUP] = {
+ .err = EMEDIUMTYPE,
+ .str = "Provider not supported",
+ },
+ [RPMEM_ERR_NOEXIST] = {
+ .err = ENOENT,
+ .str = "Pool set or its part doesn't exist or it is "
+ "unavailable",
+ },
+ [RPMEM_ERR_NOACCESS] = {
+ .err = EACCES,
+ .str = "Pool set permission denied",
+ },
+ [RPMEM_ERR_POOL_CFG] = {
+ .err = EINVAL,
+ .str = "Invalid pool set configuration",
+ },
+};
+
+static char *Rpmem_cmds;
+static char **Rpmem_cmd_arr;
+static size_t Rpmem_current_cmd;
+static size_t Rpmem_ncmds;
+
+#define RPMEM_CMD_SEPARATOR '|'
+
+/*
+ * rpmem_util_proto_errstr -- return error string for error code
+ */
+const char *
+rpmem_util_proto_errstr(enum rpmem_err err)
+{
+ RPMEM_ASSERT(err < MAX_RPMEM_ERR);
+
+ const char *ret = rpmem_err_str_errno[err].str;
+ RPMEM_ASSERT(ret);
+
+ return ret;
+}
+
+/*
+ * rpmem_util_proto_errno -- return appropriate errno value for error code
+ */
+int
+rpmem_util_proto_errno(enum rpmem_err err)
+{
+ RPMEM_ASSERT(err < MAX_RPMEM_ERR);
+
+ return rpmem_err_str_errno[err].err;
+}
+
+/*
+ * rpmem_util_cmds_inc -- increase size of array for rpmem commands
+ */
+static void
+rpmem_util_cmds_inc(void)
+{
+ Rpmem_ncmds++;
+ Rpmem_cmd_arr = realloc(Rpmem_cmd_arr,
+ Rpmem_ncmds * sizeof(*Rpmem_cmd_arr));
+ if (!Rpmem_cmd_arr)
+ RPMEM_FATAL("!realloc");
+
+}
+
+/*
+ * rpmem_util_cmds_init -- read a RPMEM_CMD from the environment variable
+ */
+void
+rpmem_util_cmds_init(void)
+{
+ char *cmd = os_getenv(RPMEM_CMD_ENV);
+ if (!cmd)
+ cmd = RPMEM_DEF_CMD;
+
+ Rpmem_cmds = strdup(cmd);
+ if (!Rpmem_cmds)
+ RPMEM_FATAL("!strdup");
+
+ char *next = Rpmem_cmds;
+ while (next) {
+ rpmem_util_cmds_inc();
+ Rpmem_cmd_arr[Rpmem_ncmds - 1] = next;
+
+ next = strchr(next, RPMEM_CMD_SEPARATOR);
+ if (next) {
+ *next = '\0';
+ next++;
+ }
+ }
+}
+
+/*
+ * rpmem_util_env_fini -- release RPMEM_CMD copy
+ */
+void
+rpmem_util_cmds_fini(void)
+{
+ RPMEM_ASSERT(Rpmem_cmds);
+ RPMEM_ASSERT(Rpmem_cmd_arr);
+ RPMEM_ASSERT(Rpmem_current_cmd < Rpmem_ncmds);
+
+ free(Rpmem_cmds);
+ Rpmem_cmds = NULL;
+
+ free(Rpmem_cmd_arr);
+ Rpmem_cmd_arr = NULL;
+
+ Rpmem_ncmds = 0;
+ Rpmem_current_cmd = 0;
+}
+
+/*
+ * rpmem_util_cmd_get -- get a next command from RPMEM_CMD
+ *
+ * RPMEM_CMD can contain multiple commands separated by RPMEM_CMD_SEPARATOR.
+ * Commands from RPMEM_CMD are read sequentially and used to establish out of
+ * band connections to remote nodes in the order read from a poolset file.
+ *
+ */
+const char *
+rpmem_util_cmd_get(void)
+{
+ RPMEM_ASSERT(Rpmem_cmds);
+ RPMEM_ASSERT(Rpmem_cmd_arr);
+ RPMEM_ASSERT(Rpmem_current_cmd < Rpmem_ncmds);
+
+ char *ret = Rpmem_cmd_arr[Rpmem_current_cmd];
+
+ Rpmem_current_cmd = (Rpmem_current_cmd + 1) % Rpmem_ncmds;
+
+ return ret;
+}
+
+/*
+ * rpmem_util_get_env_uint -- read the unsigned value from environment
+ */
+static void
+rpmem_util_get_env_uint(const char *env, unsigned *pval)
+{
+ char *env_val = os_getenv(env);
+ if (env_val && env_val[0] != '\0') {
+ char *endptr;
+ errno = 0;
+
+ long val = strtol(env_val, &endptr, 10);
+
+ if (endptr[0] != '\0' || val <= 0 ||
+ (errno == ERANGE &&
+ (val == LONG_MAX || val == LONG_MIN))) {
+ RPMEM_LOG(ERR, "%s variable must be a positive integer",
+ env);
+ } else {
+ *pval = val < UINT_MAX ? (unsigned)val: UINT_MAX;
+ }
+ }
+}
+
+/*
+ * rpmem_util_get_env_max_nlanes -- read the maximum number of lanes from
+ * RPMEM_MAX_NLANES
+ */
+void
+rpmem_util_get_env_max_nlanes(unsigned *max_nlanes)
+{
+ rpmem_util_get_env_uint(RPMEM_MAX_NLANES_ENV, max_nlanes);
+}
+
+/*
+ * rpmem_util_get_env_wq_size -- read the required WQ size from env
+ */
+void
+rpmem_util_get_env_wq_size(unsigned *wq_size)
+{
+ rpmem_util_get_env_uint(RPMEM_WQ_SIZE_ENV, wq_size);
+}