At hugepage info initialization, EAL takes out a write lock on
hugetlbfs directories, and drops it after the memory init is
finished. However, in non-legacy mode, if "-m" or "--socket-mem"
switches are passed, this leads to a deadlock because EAL tries
to allocate pages (and thus take out a write lock on hugedir)
while still holding a separate hugedir write lock in EAL.
Fix it by checking if write lock in hugepage info is active, and
not trying to lock the directory if the hugedir fd is valid.
Fixes:
1a7dc2252f28 ("mem: revert to using flock and add per-segment lockfiles")
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Tested-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Tested-by: Shahaf Shuler <shahafs@mellanox.com>
Tested-by: Andrew Rybchenko <arybchenko@solarflare.com>
struct alloc_walk_param *wa = arg;
struct rte_memseg_list *cur_msl;
size_t page_sz;
struct alloc_walk_param *wa = arg;
struct rte_memseg_list *cur_msl;
size_t page_sz;
- int cur_idx, start_idx, j, dir_fd;
+ int cur_idx, start_idx, j, dir_fd = -1;
unsigned int msl_idx, need, i;
if (msl->page_sz != wa->page_sz)
unsigned int msl_idx, need, i;
if (msl->page_sz != wa->page_sz)
* because file creation and locking operations are not atomic,
* and we might be the first or the last ones to use a particular page,
* so we need to ensure atomicity of every operation.
* because file creation and locking operations are not atomic,
* and we might be the first or the last ones to use a particular page,
* so we need to ensure atomicity of every operation.
+ *
+ * during init, we already hold a write lock, so don't try to take out
+ * another one.
- dir_fd = open(wa->hi->hugedir, O_RDONLY);
- if (dir_fd < 0) {
- RTE_LOG(ERR, EAL, "%s(): Cannot open '%s': %s\n", __func__,
- wa->hi->hugedir, strerror(errno));
- return -1;
- }
- /* blocking writelock */
- if (flock(dir_fd, LOCK_EX)) {
- RTE_LOG(ERR, EAL, "%s(): Cannot lock '%s': %s\n", __func__,
- wa->hi->hugedir, strerror(errno));
- close(dir_fd);
- return -1;
+ if (wa->hi->lock_descriptor == -1) {
+ dir_fd = open(wa->hi->hugedir, O_RDONLY);
+ if (dir_fd < 0) {
+ RTE_LOG(ERR, EAL, "%s(): Cannot open '%s': %s\n",
+ __func__, wa->hi->hugedir, strerror(errno));
+ return -1;
+ }
+ /* blocking writelock */
+ if (flock(dir_fd, LOCK_EX)) {
+ RTE_LOG(ERR, EAL, "%s(): Cannot lock '%s': %s\n",
+ __func__, wa->hi->hugedir, strerror(errno));
+ close(dir_fd);
+ return -1;
+ }
}
for (i = 0; i < need; i++, cur_idx++) {
}
for (i = 0; i < need; i++, cur_idx++) {
if (wa->ms)
memset(wa->ms, 0, sizeof(*wa->ms) * wa->n_segs);
if (wa->ms)
memset(wa->ms, 0, sizeof(*wa->ms) * wa->n_segs);
+ if (dir_fd >= 0)
+ close(dir_fd);
wa->segs_allocated = i;
if (i > 0)
cur_msl->version++;
wa->segs_allocated = i;
if (i > 0)
cur_msl->version++;
+ if (dir_fd >= 0)
+ close(dir_fd);
struct rte_memseg_list *found_msl;
struct free_walk_param *wa = arg;
uintptr_t start_addr, end_addr;
struct rte_memseg_list *found_msl;
struct free_walk_param *wa = arg;
uintptr_t start_addr, end_addr;
- int msl_idx, seg_idx, ret, dir_fd;
+ int msl_idx, seg_idx, ret, dir_fd = -1;
start_addr = (uintptr_t) msl->base_va;
end_addr = start_addr + msl->memseg_arr.len * (size_t)msl->page_sz;
start_addr = (uintptr_t) msl->base_va;
end_addr = start_addr + msl->memseg_arr.len * (size_t)msl->page_sz;
* because file creation and locking operations are not atomic,
* and we might be the first or the last ones to use a particular page,
* so we need to ensure atomicity of every operation.
* because file creation and locking operations are not atomic,
* and we might be the first or the last ones to use a particular page,
* so we need to ensure atomicity of every operation.
+ *
+ * during init, we already hold a write lock, so don't try to take out
+ * another one.
- dir_fd = open(wa->hi->hugedir, O_RDONLY);
- if (dir_fd < 0) {
- RTE_LOG(ERR, EAL, "%s(): Cannot open '%s': %s\n", __func__,
- wa->hi->hugedir, strerror(errno));
- return -1;
- }
- /* blocking writelock */
- if (flock(dir_fd, LOCK_EX)) {
- RTE_LOG(ERR, EAL, "%s(): Cannot lock '%s': %s\n", __func__,
- wa->hi->hugedir, strerror(errno));
- close(dir_fd);
- return -1;
+ if (wa->hi->lock_descriptor == -1) {
+ dir_fd = open(wa->hi->hugedir, O_RDONLY);
+ if (dir_fd < 0) {
+ RTE_LOG(ERR, EAL, "%s(): Cannot open '%s': %s\n",
+ __func__, wa->hi->hugedir, strerror(errno));
+ return -1;
+ }
+ /* blocking writelock */
+ if (flock(dir_fd, LOCK_EX)) {
+ RTE_LOG(ERR, EAL, "%s(): Cannot lock '%s': %s\n",
+ __func__, wa->hi->hugedir, strerror(errno));
+ close(dir_fd);
+ return -1;
+ }
ret = free_seg(wa->ms, wa->hi, msl_idx, seg_idx);
ret = free_seg(wa->ms, wa->hi, msl_idx, seg_idx);
+ if (dir_fd >= 0)
+ close(dir_fd);