0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 15:33:54 +01:00

ircd::fs: Add interface to mmap fd.

This commit is contained in:
Jason Volk 2020-08-24 08:49:41 -07:00
parent c863e09f08
commit f6475a2906
3 changed files with 184 additions and 0 deletions

View file

@ -47,6 +47,7 @@ namespace ircd::fs
#include "opts.h"
#include "dev.h"
#include "fd.h"
#include "map.h"
#include "wait.h"
#include "read.h"
#include "write.h"

57
include/ircd/fs/map.h Normal file
View file

@ -0,0 +1,57 @@
// The Construct
//
// Copyright (C) The Construct Developers, Authors & Contributors
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_FS_MAP_H
namespace ircd::fs
{
struct map;
}
/// Interface to map file into memory.
///
/// Note that this was created specifically for file maps and not intended to
/// be a generic mmap(2) interface, at least for now.
struct ircd::fs::map
:mutable_buffer
{
struct opts;
map() = default;
map(const fd &, const opts &opts, const size_t &size = 0UL);
map(map &&) noexcept;
map(const map &) = delete;
map &operator=(map &&) noexcept;
map &operator=(const map &) = delete;
~map() noexcept;
};
/// Descriptor options (open options)
struct ircd::fs::map::opts
:fd::opts
{
bool execute {false};
bool shared {false};
bool reserve {false};
bool populate {false};
opts(const fd::opts &opts = {std::ios::in})
:fd::opts(opts)
{}
};
inline
ircd::fs::map::map(map &&other)
noexcept
:mutable_buffer{other}
{
static_cast<mutable_buffer &>(other) = {};
}

View file

@ -1730,6 +1730,132 @@ noexcept
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
// fs/map.h
//
namespace ircd::fs
{
static uint flags(const map::opts &);
static uint prot(const map::opts &);
}
ircd::fs::map::map(const fd &fd,
const opts &opts,
const size_t &size)
{
const auto map_size
{
size?: fs::size(fd)
};
void *const &ptr
{
::mmap(nullptr, map_size, prot(opts), flags(opts), int(fd), opts.offset)
};
if(unlikely(ptr == MAP_FAILED))
throw_system_error(errno);
static_cast<mutable_buffer &>(*this) = mutable_buffer
{
reinterpret_cast<char *>(ptr),
map_size
};
}
ircd::fs::map::~map()
noexcept try
{
if(mutable_buffer::null())
return;
syscall(::munmap, data(*this), size(*this));
}
catch(const std::exception &e)
{
log::critical
{
log, "munmap(%p, %zu) :%s",
data(static_cast<mutable_buffer &>(*this)),
size(static_cast<mutable_buffer &>(*this)),
e.what(),
};
}
ircd::fs::map &
ircd::fs::map::operator=(map &&other)
noexcept
{
auto &ours
{
static_cast<mutable_buffer &>(*this)
};
auto &theirs
{
static_cast<mutable_buffer &>(other)
};
this->~map();
ours = theirs;
theirs = {};
return *this;
}
uint
ircd::fs::prot(const map::opts &opts)
{
uint ret
{
PROT_NONE
};
if(opts.mode & std::ios::in)
ret |= PROT_READ;
if(opts.mode & std::ios::out)
ret |= PROT_WRITE;
assert(!opts.execute);
if((false) && opts.execute)
ret |= PROT_EXEC;
return ret;
}
uint
ircd::fs::flags(const map::opts &opts)
{
uint ret
{
0
};
if(opts.shared)
ret |= MAP_SHARED;
else
ret |= MAP_PRIVATE;
#if defined(MAP_NONBLOCK)
if(!opts.blocking)
ret |= MAP_NONBLOCK;
#endif
#if defined(MAP_POPULATE)
if(opts.populate)
ret |= MAP_POPULATE;
#endif
#if defined(MAP_NORESERVE)
if(!opts.reserve)
ret |= MAP_NORESERVE;
#endif
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//
// fs/fd.h