blob: 9fe487db788a97b2cc0310c536ede94fc64291b1 [file] [log] [blame]
Dave Barach59b25652017-09-10 15:04:27 -04001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "memfd.h"
16
17int
18memfd_master_init (memfd_private_t * memfd, u32 master_index)
19{
20 int flags;
21 memfd_shared_header_t *sh;
22 u64 ticks = clib_cpu_time_now ();
23 u64 randomize_baseva;
24 void *oldheap;
25
26 if (memfd->memfd_size == 0)
27 return MEMFD_API_ERROR_NO_SIZE;
28
29 ASSERT (vec_c_string_is_terminated (memfd->name));
30 memfd->name = format (0, "memfd svm region %d", master_index);
31
32 memfd->fd = memfd_create ((char *) memfd->name, MFD_ALLOW_SEALING);
33 if (memfd->fd < 0)
34 {
35 clib_unix_warning ("create segment '%s'", memfd->name);
36 return MEMFD_API_ERROR_CREATE_FAILURE;
37 }
38
39 if ((ftruncate (memfd->fd, memfd->memfd_size)) == -1)
40 {
41 clib_unix_warning ("set memfd size");
42 return MEMFD_API_ERROR_SET_SIZE;
43 }
44
45 if ((fcntl (memfd->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
46 clib_unix_warning ("fcntl (F_ADD_SEALS, F_SEAL_SHRINK)");
47
48 flags = MAP_SHARED;
49 if (memfd->requested_va)
50 flags |= MAP_FIXED;
51
52 randomize_baseva = (ticks & 15) * MMAP_PAGESIZE;
53
54 if (memfd->requested_va)
55 memfd->requested_va += randomize_baseva;
56
57 sh = memfd->sh =
58 (memfd_shared_header_t *) mmap ((void *) memfd->requested_va,
59 memfd->memfd_size, PROT_READ | PROT_WRITE,
60 flags, memfd->fd, 0);
61
62 if (memfd->sh == MAP_FAILED)
63 {
64 clib_unix_warning ("mmap");
65 close (memfd->fd);
66 return MEMFD_API_ERROR_MMAP;
67 }
68
69 memfd->my_pid = getpid ();
70 sh->master_pid = memfd->my_pid;
71 sh->memfd_size = memfd->memfd_size;
72 sh->heap = mheap_alloc_with_flags
73 (((u8 *) sh) + MMAP_PAGESIZE, memfd->memfd_size - MMAP_PAGESIZE,
74 MHEAP_FLAG_DISABLE_VM | MHEAP_FLAG_THREAD_SAFE);
75
76 sh->memfd_va = pointer_to_uword (sh);
77 sh->master_index = master_index;
78
79 oldheap = memfd_push_heap (sh);
80 sh->name = format (0, "%s%c", memfd->name, 0);
81 memfd_pop_heap (oldheap);
82
83 memfd->i_am_master = 1;
84
85 /* The application has to set set sh->ready... */
86 return 0;
87}
88
89/*
90 * Subtly different than svm_slave_init. The caller
91 * needs to acquire a usable file descriptor for the memfd segment
92 * e.g. via vppinfra/socket.c:default_socket_recvmsg
93 */
94
95int
96memfd_slave_init (memfd_private_t * memfd)
97{
98 memfd_shared_header_t *sh;
99
100 memfd->i_am_master = 0;
101
102 /* Map the segment once, to look at the shared header */
103 sh = (void *) mmap (0, MMAP_PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
104 memfd->fd, 0);
105 if (sh == MAP_FAILED)
106 {
107 clib_unix_warning ("slave research mmap");
108 close (memfd->fd);
109 return MEMFD_API_ERROR_MMAP;
110 }
111
112 memfd->requested_va = (u64) sh->memfd_va;
113 memfd->memfd_size = sh->memfd_size;
114 munmap (sh, MMAP_PAGESIZE);
115
116 sh = memfd->sh =
117 (void *) mmap ((void *) memfd->requested_va, memfd->memfd_size,
118 PROT_READ | PROT_WRITE,
119 MAP_SHARED | MAP_FIXED, memfd->fd, 0);
120
121 if (sh == MAP_FAILED)
122 {
123 clib_unix_warning ("slave final mmap");
124 close (memfd->fd);
125 return MEMFD_API_ERROR_MMAP;
126 }
127 sh->slave_pid = getpid ();
128 return 0;
129}
130
131/*
132 * fd.io coding-style-patch-verification: ON
133 *
134 * Local Variables:
135 * eval: (c-set-style "gnu")
136 * End:
137 */