Skip to content

Commit

Permalink
eal: introduce internal wrappers for file operations
Browse files Browse the repository at this point in the history
Introduce OS-independent wrappers in order to support common EAL code
on Unix and Windows:

* eal_file_open: open or create a file.
* eal_file_lock: lock or unlock an open file.
* eal_file_truncate: enforce a given size for an open file.

Implementation for Linux and FreeBSD is placed in "unix" subdirectory,
which is intended for common code between the two. These thin wrappers
require no special maintenance.

Common code supporting multi-process doesn't use the new wrappers,
because it is inherently Unix-specific and would impose excessive
requirements on the wrappers.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
  • Loading branch information
PlushBeaver authored and tmonjalo committed Jun 15, 2020
1 parent 67a661e commit 176bb37
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 19 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Expand Up @@ -168,6 +168,7 @@ T: git://dpdk.org/dpdk

EAL API and common code
F: lib/librte_eal/common/
F: lib/librte_eal/unix/
F: lib/librte_eal/include/
F: lib/librte_eal/rte_eal_version.map
F: doc/guides/prog_guide/env_abstraction_layer.rst
Expand Down
31 changes: 12 additions & 19 deletions lib/librte_eal/common/eal_common_fbarray.c
Expand Up @@ -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>
Expand Down Expand Up @@ -85,10 +85,8 @@ 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;
return -1;
}

Expand Down Expand Up @@ -772,15 +770,15 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,
* and see if we succeed. If we don't, someone else is using it
* already.
*/
fd = open(path, O_CREAT | O_RDWR, 0600);
fd = eal_file_open(path, EAL_OPEN_CREATE | EAL_OPEN_READWRITE);
if (fd < 0) {
RTE_LOG(DEBUG, EAL, "%s(): couldn't open %s: %s\n",
__func__, path, strerror(errno));
rte_errno = errno;
__func__, path, rte_strerror(rte_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));
__func__, path, rte_strerror(rte_errno));
rte_errno = EBUSY;
goto fail;
}
Expand All @@ -789,10 +787,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;
Expand Down Expand Up @@ -888,17 +884,14 @@ rte_fbarray_attach(struct rte_fbarray *arr)

eal_get_fbarray_path(path, sizeof(path), arr->name);

fd = open(path, O_RDWR);
fd = eal_file_open(path, EAL_OPEN_READWRITE);
if (fd < 0) {
rte_errno = errno;
goto fail;
}

/* 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;
Expand Down Expand Up @@ -1025,7 +1018,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;
Expand All @@ -1042,7 +1035,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;
Expand Down
73 changes: 73 additions & 0 deletions lib/librte_eal/common/eal_private.h
Expand Up @@ -420,4 +420,77 @@ eal_malloc_no_trace(const char *type, size_t size, unsigned int align);

void eal_free_no_trace(void *addr);

/** Options for eal_file_open(). */
enum eal_open_flags {
/** Open file for reading. */
EAL_OPEN_READONLY = 0x00,
/** Open file for reading and writing. */
EAL_OPEN_READWRITE = 0x02,
/**
* Create the file if it doesn't exist.
* New files are only accessible to the owner (0600 equivalent).
*/
EAL_OPEN_CREATE = 0x04
};

/**
* Open or create a file.
*
* @param path
* Path to the file.
* @param flags
* A combination of eal_open_flags controlling operation and FD behavior.
* @return
* Open file descriptor on success, (-1) on failure and rte_errno is set.
*/
int
eal_file_open(const char *path, int flags);

/** 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_ */
4 changes: 4 additions & 0 deletions lib/librte_eal/freebsd/Makefile
Expand Up @@ -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
Expand Down Expand Up @@ -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_file.c

# from arch dir
SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_cpuflags.c
SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_hypervisor.c
Expand Down
4 changes: 4 additions & 0 deletions lib/librte_eal/linux/Makefile
Expand Up @@ -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
Expand Down Expand Up @@ -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_file.c

# from arch dir
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_cpuflags.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_hypervisor.c
Expand Down
4 changes: 4 additions & 0 deletions lib/librte_eal/meson.build
Expand Up @@ -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)

Expand Down
80 changes: 80 additions & 0 deletions lib/librte_eal/unix/eal_file.c
@@ -0,0 +1,80 @@
/* 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_open(const char *path, int flags)
{
static const int MODE_MASK = EAL_OPEN_READONLY | EAL_OPEN_READWRITE;

int ret, sys_flags;

switch (flags & MODE_MASK) {
case EAL_OPEN_READONLY:
sys_flags = O_RDONLY;
break;
case EAL_OPEN_READWRITE:
sys_flags = O_RDWR;
break;
default:
rte_errno = ENOTSUP;
return -1;
}

if (flags & EAL_OPEN_CREATE)
sys_flags |= O_CREAT;

ret = open(path, sys_flags, 0600);
if (ret < 0)
rte_errno = errno;

return ret;
}

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;
}
6 changes: 6 additions & 0 deletions lib/librte_eal/unix/meson.build
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2020 Dmitry Kozlyuk

sources += files(
'eal_file.c',
)

0 comments on commit 176bb37

Please sign in to comment.