On 29-Apr-20 12:50 AM, Dmitry Kozlyuk wrote:
> EAL common code uses file locking and truncation. Introduce
> OS-independent wrappers in order to support both Linux/FreeBSD
> and Windows:
>
> * eal_file_lock: lock or unlock an open file.
> * eal_file_truncate: enforce a given size for an open file.
>
> Wrappers follow POSIX semantics, but interface is not POSIX,
> so that it can be made more clean, e.g. by not mixing locking
> operation and behaviour on conflict.
>
> Implementation for Linux and FreeBSD is placed in "unix" subdirectory,
> which is intended for common code between the two. Files should be named
> after the ones from which the code is factored in OS subdirectory.
>
> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> ---
<snip>
>
> #include <rte_common.h>
> #include <rte_log.h>
> @@ -85,7 +85,7 @@ resize_and_map(int fd, void *addr, size_t len)
> char path[PATH_MAX];
> void *map_addr;
>
> - if (ftruncate(fd, len)) {
> + if (eal_file_truncate(fd, len)) {
> RTE_LOG(ERR, EAL, "Cannot truncate %s\n", path);
> /* pass errno up the chain */
> rte_errno = errno;
eal_file_truncate sets rte_errno, so no need to pass it up the chain any
more.
Otherwise,
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
@@ -8,8 +8,8 @@
#include <sys/mman.h>
#include <stdint.h>
#include <errno.h>
-#include <sys/file.h>
#include <string.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_log.h>
@@ -85,7 +85,7 @@ resize_and_map(int fd, void *addr, size_t len)
char path[PATH_MAX];
void *map_addr;
- if (ftruncate(fd, len)) {
+ if (eal_file_truncate(fd, len)) {
RTE_LOG(ERR, EAL, "Cannot truncate %s\n", path);
/* pass errno up the chain */
rte_errno = errno;
@@ -778,7 +778,8 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,
__func__, path, strerror(errno));
rte_errno = errno;
goto fail;
- } else if (flock(fd, LOCK_EX | LOCK_NB)) {
+ } else if (eal_file_lock(
+ fd, EAL_FLOCK_EXCLUSIVE, EAL_FLOCK_RETURN)) {
RTE_LOG(DEBUG, EAL, "%s(): couldn't lock %s: %s\n",
__func__, path, strerror(errno));
rte_errno = EBUSY;
@@ -789,10 +790,8 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,
* still attach to it, but no other process could reinitialize
* it.
*/
- if (flock(fd, LOCK_SH | LOCK_NB)) {
- rte_errno = errno;
+ if (eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN))
goto fail;
- }
if (resize_and_map(fd, data, mmap_len))
goto fail;
@@ -895,10 +894,8 @@ rte_fbarray_attach(struct rte_fbarray *arr)
}
/* lock the file, to let others know we're using it */
- if (flock(fd, LOCK_SH | LOCK_NB)) {
- rte_errno = errno;
+ if (eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN))
goto fail;
- }
if (resize_and_map(fd, data, mmap_len))
goto fail;
@@ -1025,7 +1022,7 @@ rte_fbarray_destroy(struct rte_fbarray *arr)
* has been detached by all other processes
*/
fd = tmp->fd;
- if (flock(fd, LOCK_EX | LOCK_NB)) {
+ if (eal_file_lock(fd, EAL_FLOCK_EXCLUSIVE, EAL_FLOCK_RETURN)) {
RTE_LOG(DEBUG, EAL, "Cannot destroy fbarray - another process is using it\n");
rte_errno = EBUSY;
ret = -1;
@@ -1042,7 +1039,7 @@ rte_fbarray_destroy(struct rte_fbarray *arr)
* we're still holding an exclusive lock, so drop it to
* shared.
*/
- flock(fd, LOCK_SH | LOCK_NB);
+ eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN);
ret = -1;
goto out;
@@ -448,4 +448,49 @@ eal_malloc_no_trace(const char *type, size_t size, unsigned int align);
void eal_free_no_trace(void *addr);
+/** File locking operation. */
+enum eal_flock_op {
+ EAL_FLOCK_SHARED, /**< Acquire a shared lock. */
+ EAL_FLOCK_EXCLUSIVE, /**< Acquire an exclusive lock. */
+ EAL_FLOCK_UNLOCK /**< Release a previously taken lock. */
+};
+
+/** Behavior on file locking conflict. */
+enum eal_flock_mode {
+ EAL_FLOCK_WAIT, /**< Wait until the file gets unlocked to lock it. */
+ EAL_FLOCK_RETURN /**< Return immediately if the file is locked. */
+};
+
+/**
+ * Lock or unlock the file.
+ *
+ * On failure @code rte_errno @endcode is set to the error code
+ * specified by POSIX flock(3) description.
+ *
+ * @param fd
+ * Opened file descriptor.
+ * @param op
+ * Operation to perform.
+ * @param mode
+ * Behavior on conflict.
+ * @return
+ * 0 on success, (-1) on failure.
+ */
+int eal_file_lock(int fd, enum eal_flock_op op, enum eal_flock_mode mode);
+
+/**
+ * Truncate or extend the file to the specified size.
+ *
+ * On failure @code rte_errno @endcode is set to the error code
+ * specified by POSIX ftruncate(3) description.
+ *
+ * @param fd
+ * Opened file descriptor.
+ * @param size
+ * Desired file size.
+ * @return
+ * 0 on success, (-1) on failure.
+ */
+int eal_file_truncate(int fd, ssize_t size);
+
#endif /* _EAL_PRIVATE_H_ */
@@ -7,6 +7,7 @@ LIB = librte_eal.a
ARCH_DIR ?= $(RTE_ARCH)
VPATH += $(RTE_SDK)/lib/librte_eal/$(ARCH_DIR)
+VPATH += $(RTE_SDK)/lib/librte_eal/unix
VPATH += $(RTE_SDK)/lib/librte_eal/common
CFLAGS += -I$(SRCDIR)/include
@@ -74,6 +75,9 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_service.c
SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_random.c
SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_reciprocal.c
+# from unix dir
+SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_unix.c
+
# from arch dir
SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_cpuflags.c
SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_hypervisor.c
@@ -7,6 +7,7 @@ LIB = librte_eal.a
ARCH_DIR ?= $(RTE_ARCH)
VPATH += $(RTE_SDK)/lib/librte_eal/$(ARCH_DIR)
+VPATH += $(RTE_SDK)/lib/librte_eal/unix
VPATH += $(RTE_SDK)/lib/librte_eal/common
CFLAGS += -I$(SRCDIR)/include
@@ -81,6 +82,9 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_service.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_random.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_reciprocal.c
+# from unix dir
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_unix.c
+
# from arch dir
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_cpuflags.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_hypervisor.c
@@ -6,6 +6,10 @@ subdir('include')
subdir('common')
+if not is_windows
+ subdir('unix')
+endif
+
dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1)
subdir(exec_env)
new file mode 100644
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Dmitry Kozlyuk
+ */
+
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <rte_errno.h>
+
+#include "eal_private.h"
+
+int
+eal_file_truncate(int fd, ssize_t size)
+{
+ int ret;
+
+ ret = ftruncate(fd, size);
+ if (ret)
+ rte_errno = errno;
+
+ return ret;
+}
+
+int
+eal_file_lock(int fd, enum eal_flock_op op, enum eal_flock_mode mode)
+{
+ int sys_flags = 0;
+ int ret;
+
+ if (mode == EAL_FLOCK_RETURN)
+ sys_flags |= LOCK_NB;
+
+ switch (op) {
+ case EAL_FLOCK_EXCLUSIVE:
+ sys_flags |= LOCK_EX;
+ break;
+ case EAL_FLOCK_SHARED:
+ sys_flags |= LOCK_SH;
+ break;
+ case EAL_FLOCK_UNLOCK:
+ sys_flags |= LOCK_UN;
+ break;
+ }
+
+ ret = flock(fd, sys_flags);
+ if (ret)
+ rte_errno = errno;
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Dmitry Kozlyuk
+
+sources += files(
+ 'eal_unix.c',
+)