1a7dc2252f
The original implementation used flock() locks, but was later switched to using fcntl() locks for page locking, because fcntl() locks allow locking parts of a file, which is useful for single-file segments mode, where locking the entire file isn't as useful because we still need to grow and shrink it. However, according to fcntl()'s Ubuntu manpage [1], semantics of fcntl() locks have a giant oversight: This interface follows the completely stupid semantics of System V and IEEE Std 1003.1-1988 (“POSIX.1”) that require that all locks associated with a file for a given process are removed when any file descriptor for that file is closed by that process. This semantic means that applications must be aware of any files that a subroutine library may access. Basically, closing *any* fd with an fcntl() lock (which we do because we don't want to leak fd's) will drop the lock completely. So, in this commit, we will be reverting back to using flock() locks everywhere. However, that still leaves the problem of locking parts of a memseg list file in single file segments mode, and we will be solving it with creating separate lock files per each page, and tracking those with flock(). We will also be removing all of this tailq business and replacing it with a simple array - saving a few bytes is not worth the extra hassle of dealing with pointers and potential memory allocation failures. Also, remove the tailq lock since it is not needed - these fd lists are per-process, and within a given process, it is always only one thread handling access to hugetlbfs. So, first one to allocate a segment will create a lockfile, and put a shared lock on it. When we're shrinking the page file, we will be trying to take out a write lock on that lockfile, which would fail if any other process is holding onto the lockfile as well. This way, we can know if we can shrink the segment file. Also, if no other locks are found in the lock list for a given memseg list, the memseg list fd is automatically closed. One other thing to note is, according to flock() Ubuntu manpage [2], upgrading the lock from shared to exclusive is implemented by dropping and reacquiring the lock, which is not atomic and thus would have created race conditions. So, on attempting to perform operations in hugetlbfs, we will take out a writelock on hugetlbfs directory, so that only one process could perform hugetlbfs operations concurrently. [1] http://manpages.ubuntu.com/manpages/artful/en/man2/fcntl.2freebsd.html [2] http://manpages.ubuntu.com/manpages/bionic/en/man2/flock.2.html Fixes: 66cc45e293ed ("mem: replace memseg with memseg lists") Fixes: 582bed1e1d1d ("mem: support mapping hugepages at runtime") Fixes: a5ff05d60fc5 ("mem: support unmapping pages at runtime") Fixes: 2a04139f66b4 ("eal: add single file segments option") Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
143 lines
3.9 KiB
C
143 lines
3.9 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2010-2018 Intel Corporation
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Stores functions and path defines for files and directories
|
|
* on the filesystem for Linux, that are used by the Linux EAL.
|
|
*/
|
|
|
|
#ifndef EAL_FILESYSTEM_H
|
|
#define EAL_FILESYSTEM_H
|
|
|
|
/** Path of rte config file. */
|
|
#define RUNTIME_CONFIG_FMT "%s/.%s_config"
|
|
#define FBARRAY_FMT "%s/.%s_%s"
|
|
|
|
#include <stdint.h>
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <rte_string_fns.h>
|
|
#include "eal_internal_cfg.h"
|
|
|
|
static const char *default_config_dir = "/var/run";
|
|
|
|
static inline const char *
|
|
eal_runtime_config_path(void)
|
|
{
|
|
static char buffer[PATH_MAX]; /* static so auto-zeroed */
|
|
const char *directory = default_config_dir;
|
|
const char *home_dir = getenv("HOME");
|
|
|
|
if (getuid() != 0 && home_dir != NULL)
|
|
directory = home_dir;
|
|
snprintf(buffer, sizeof(buffer) - 1, RUNTIME_CONFIG_FMT, directory,
|
|
internal_config.hugefile_prefix);
|
|
return buffer;
|
|
}
|
|
|
|
/** Path of primary/secondary communication unix socket file. */
|
|
#define MP_SOCKET_PATH_FMT "%s/.%s_unix"
|
|
static inline const char *
|
|
eal_mp_socket_path(void)
|
|
{
|
|
static char buffer[PATH_MAX]; /* static so auto-zeroed */
|
|
const char *directory = default_config_dir;
|
|
const char *home_dir = getenv("HOME");
|
|
|
|
if (getuid() != 0 && home_dir != NULL)
|
|
directory = home_dir;
|
|
snprintf(buffer, sizeof(buffer) - 1, MP_SOCKET_PATH_FMT,
|
|
directory, internal_config.hugefile_prefix);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static inline const char *
|
|
eal_get_fbarray_path(char *buffer, size_t buflen, const char *name) {
|
|
const char *directory = "/tmp";
|
|
const char *home_dir = getenv("HOME");
|
|
|
|
if (getuid() != 0 && home_dir != NULL)
|
|
directory = home_dir;
|
|
snprintf(buffer, buflen - 1, FBARRAY_FMT, directory,
|
|
internal_config.hugefile_prefix, name);
|
|
return buffer;
|
|
}
|
|
|
|
/** Path of hugepage info file. */
|
|
#define HUGEPAGE_INFO_FMT "%s/.%s_hugepage_info"
|
|
|
|
static inline const char *
|
|
eal_hugepage_info_path(void)
|
|
{
|
|
static char buffer[PATH_MAX]; /* static so auto-zeroed */
|
|
const char *directory = default_config_dir;
|
|
const char *home_dir = getenv("HOME");
|
|
|
|
if (getuid() != 0 && home_dir != NULL)
|
|
directory = home_dir;
|
|
snprintf(buffer, sizeof(buffer) - 1, HUGEPAGE_INFO_FMT, directory,
|
|
internal_config.hugefile_prefix);
|
|
return buffer;
|
|
}
|
|
|
|
/** Path of hugepage info file. */
|
|
#define HUGEPAGE_FILE_FMT "%s/.%s_hugepage_file"
|
|
|
|
static inline const char *
|
|
eal_hugepage_file_path(void)
|
|
{
|
|
static char buffer[PATH_MAX]; /* static so auto-zeroed */
|
|
const char *directory = default_config_dir;
|
|
const char *home_dir = getenv("HOME");
|
|
|
|
if (getuid() != 0 && home_dir != NULL)
|
|
directory = home_dir;
|
|
snprintf(buffer, sizeof(buffer) - 1, HUGEPAGE_FILE_FMT, directory,
|
|
internal_config.hugefile_prefix);
|
|
return buffer;
|
|
}
|
|
|
|
/** String format for hugepage map files. */
|
|
#define HUGEFILE_FMT "%s/%smap_%d"
|
|
#define TEMP_HUGEFILE_FMT "%s/%smap_temp_%d"
|
|
|
|
static inline const char *
|
|
eal_get_hugefile_path(char *buffer, size_t buflen, const char *hugedir, int f_id)
|
|
{
|
|
snprintf(buffer, buflen, HUGEFILE_FMT, hugedir,
|
|
internal_config.hugefile_prefix, f_id);
|
|
buffer[buflen - 1] = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/** String format for hugepage map lock files. */
|
|
#define HUGEFILE_LOCK_FMT "%s/.%smap_%d.lock"
|
|
|
|
static inline const char *
|
|
eal_get_hugefile_lock_path(char *buffer, size_t buflen, int f_id)
|
|
{
|
|
const char *directory = default_config_dir;
|
|
const char *home_dir = getenv("HOME");
|
|
|
|
if (getuid() != 0 && home_dir != NULL)
|
|
directory = home_dir;
|
|
snprintf(buffer, buflen - 1, HUGEFILE_LOCK_FMT, directory,
|
|
internal_config.hugefile_prefix, f_id);
|
|
buffer[buflen - 1] = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/** define the default filename prefix for the %s values above */
|
|
#define HUGEFILE_PREFIX_DEFAULT "rte"
|
|
|
|
/** Function to read a single numeric value from a file on the filesystem.
|
|
* Used to read information from files on /sys */
|
|
int eal_parse_sysfs_value(const char *filename, unsigned long *val);
|
|
|
|
#endif /* EAL_FILESYSTEM_H */
|