blob: 9fe487db788a97b2cc0310c536ede94fc64291b1 [file] [log] [blame]
/*
* Copyright (c) 2017 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "memfd.h"
int
memfd_master_init (memfd_private_t * memfd, u32 master_index)
{
int flags;
memfd_shared_header_t *sh;
u64 ticks = clib_cpu_time_now ();
u64 randomize_baseva;
void *oldheap;
if (memfd->memfd_size == 0)
return MEMFD_API_ERROR_NO_SIZE;
ASSERT (vec_c_string_is_terminated (memfd->name));
memfd->name = format (0, "memfd svm region %d", master_index);
memfd->fd = memfd_create ((char *) memfd->name, MFD_ALLOW_SEALING);
if (memfd->fd < 0)
{
clib_unix_warning ("create segment '%s'", memfd->name);
return MEMFD_API_ERROR_CREATE_FAILURE;
}
if ((ftruncate (memfd->fd, memfd->memfd_size)) == -1)
{
clib_unix_warning ("set memfd size");
return MEMFD_API_ERROR_SET_SIZE;
}
if ((fcntl (memfd->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
clib_unix_warning ("fcntl (F_ADD_SEALS, F_SEAL_SHRINK)");
flags = MAP_SHARED;
if (memfd->requested_va)
flags |= MAP_FIXED;
randomize_baseva = (ticks & 15) * MMAP_PAGESIZE;
if (memfd->requested_va)
memfd->requested_va += randomize_baseva;
sh = memfd->sh =
(memfd_shared_header_t *) mmap ((void *) memfd->requested_va,
memfd->memfd_size, PROT_READ | PROT_WRITE,
flags, memfd->fd, 0);
if (memfd->sh == MAP_FAILED)
{
clib_unix_warning ("mmap");
close (memfd->fd);
return MEMFD_API_ERROR_MMAP;
}
memfd->my_pid = getpid ();
sh->master_pid = memfd->my_pid;
sh->memfd_size = memfd->memfd_size;
sh->heap = mheap_alloc_with_flags
(((u8 *) sh) + MMAP_PAGESIZE, memfd->memfd_size - MMAP_PAGESIZE,
MHEAP_FLAG_DISABLE_VM | MHEAP_FLAG_THREAD_SAFE);
sh->memfd_va = pointer_to_uword (sh);
sh->master_index = master_index;
oldheap = memfd_push_heap (sh);
sh->name = format (0, "%s%c", memfd->name, 0);
memfd_pop_heap (oldheap);
memfd->i_am_master = 1;
/* The application has to set set sh->ready... */
return 0;
}
/*
* Subtly different than svm_slave_init. The caller
* needs to acquire a usable file descriptor for the memfd segment
* e.g. via vppinfra/socket.c:default_socket_recvmsg
*/
int
memfd_slave_init (memfd_private_t * memfd)
{
memfd_shared_header_t *sh;
memfd->i_am_master = 0;
/* Map the segment once, to look at the shared header */
sh = (void *) mmap (0, MMAP_PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
memfd->fd, 0);
if (sh == MAP_FAILED)
{
clib_unix_warning ("slave research mmap");
close (memfd->fd);
return MEMFD_API_ERROR_MMAP;
}
memfd->requested_va = (u64) sh->memfd_va;
memfd->memfd_size = sh->memfd_size;
munmap (sh, MMAP_PAGESIZE);
sh = memfd->sh =
(void *) mmap ((void *) memfd->requested_va, memfd->memfd_size,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED, memfd->fd, 0);
if (sh == MAP_FAILED)
{
clib_unix_warning ("slave final mmap");
close (memfd->fd);
return MEMFD_API_ERROR_MMAP;
}
sh->slave_pid = getpid ();
return 0;
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/