]> git.proxmox.com Git - ceph.git/blame - ceph/src/pmdk/src/libpmem2/vm_reservation_posix.c
import ceph 16.2.7
[ceph.git] / ceph / src / pmdk / src / libpmem2 / vm_reservation_posix.c
CommitLineData
a4b75251
TL
1// SPDX-License-Identifier: BSD-3-Clause
2/* Copyright 2020, Intel Corporation */
3
4/*
5 * vm_reservation_posix.c -- implementation of virtual memory
6 * reservation API (POSIX)
7 */
8
9#include <sys/mman.h>
10
11#include "alloc.h"
12#include "map.h"
13#include "out.h"
14#include "pmem2_utils.h"
15
16int vm_reservation_reserve_memory(void *addr, size_t size, void **raddr,
17 size_t *rsize);
18int vm_reservation_release_memory(void *addr, size_t size);
19
20/*
21 * vm_reservation_reserve_memory -- create a blank virual memory mapping
22 */
23int
24vm_reservation_reserve_memory(void *addr, size_t size, void **raddr,
25 size_t *rsize)
26{
27 int map_flag = 0;
28 if (addr) {
29/*
30 * glibc started exposing MAP_FIXED_NOREPLACE flag in version 4.17,
31 * but even if the flag is not supported, we can imitate its behavior
32 */
33#ifdef MAP_FIXED_NOREPLACE
34 map_flag = MAP_FIXED_NOREPLACE;
35#endif
36 }
37
38 /*
39 * Create a dummy mapping to find an unused region of given size.
40 * If the flag is supported and requested region is occupied,
41 * mmap will fail with EEXIST.
42 */
43 char *daddr = mmap(addr, size, PROT_NONE,
44 MAP_PRIVATE | MAP_ANONYMOUS | map_flag, -1, 0);
45 if (daddr == MAP_FAILED) {
46 if (errno == EEXIST) {
47 ERR("!mmap MAP_FIXED_NOREPLACE");
48 return PMEM2_E_MAPPING_EXISTS;
49 }
50 ERR("!mmap MAP_ANONYMOUS");
51 return PMEM2_E_ERRNO;
52 }
53
54 /*
55 * When requested address is not specified, any returned address
56 * is acceptable. If kernel does not support flag and given addr
57 * is occupied, kernel chooses new addr randomly and returns it.
58 * We do not want that behavior, so we validate it and fail when
59 * addresses do not match.
60 */
61 if (addr && daddr != addr) {
62 munmap(daddr, size);
63 ERR("mapping exists in the given address");
64 return PMEM2_E_MAPPING_EXISTS;
65 }
66
67 *raddr = daddr;
68 *rsize = roundup(size, Pagesize);
69
70 return 0;
71}
72
73/*
74 * vm_reservation_release_memory -- releases blank virtual memory mapping
75 */
76int
77vm_reservation_release_memory(void *addr, size_t size)
78{
79 if (munmap(addr, size)) {
80 ERR("!munmap");
81 return PMEM2_E_ERRNO;
82 }
83
84 return 0;
85}