Repair vlib API socket server
[vpp.git] / src / svm / memfd.c
1 /*
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
17 int
18 memfd_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
95 int
96 memfd_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  */