2017-05-26 04:48:44 +08:00
|
|
|
|
/*
|
|
|
|
|
* Net2FileSystem.cpp
|
|
|
|
|
*
|
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
2018-02-22 02:25:11 +08:00
|
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
|
* 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
|
2018-02-22 02:25:11 +08:00
|
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2018-02-22 02:25:11 +08:00
|
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-10-20 01:30:13 +08:00
|
|
|
|
#include "fdbrpc/Net2FileSystem.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
|
|
// Define boost::asio::io_service
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#define BOOST_SYSTEM_NO_LIB
|
|
|
|
|
#define BOOST_DATE_TIME_NO_LIB
|
|
|
|
|
#define BOOST_REGEX_NO_LIB
|
|
|
|
|
#include <boost/asio.hpp>
|
|
|
|
|
#include <boost/bind.hpp>
|
|
|
|
|
|
|
|
|
|
#define FILESYSTEM_IMPL 1
|
|
|
|
|
|
2018-10-20 01:30:13 +08:00
|
|
|
|
#include "fdbrpc/AsyncFileCached.actor.h"
|
|
|
|
|
#include "fdbrpc/AsyncFileEIO.actor.h"
|
2021-01-26 04:09:29 +08:00
|
|
|
|
#if (!defined(TLS_DISABLED) && !defined(_WIN32))
|
2021-01-23 13:47:36 +08:00
|
|
|
|
#include "fdbrpc/AsyncFileEncrypted.h"
|
2021-01-26 04:09:29 +08:00
|
|
|
|
#endif
|
2018-10-20 01:30:13 +08:00
|
|
|
|
#include "fdbrpc/AsyncFileWinASIO.actor.h"
|
|
|
|
|
#include "fdbrpc/AsyncFileKAIO.actor.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
|
#include "flow/AsioReactor.h"
|
|
|
|
|
#include "flow/Platform.h"
|
2018-10-20 01:30:13 +08:00
|
|
|
|
#include "fdbrpc/AsyncFileWriteChecker.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
|
|
// Opens a file for asynchronous I/O
|
2020-12-28 12:43:47 +08:00
|
|
|
|
Future<Reference<class IAsyncFile>> Net2FileSystem::open(const std::string& filename, int64_t flags, int64_t mode) {
|
2017-05-26 04:48:44 +08:00
|
|
|
|
#ifdef __linux__
|
|
|
|
|
if (checkFileSystem) {
|
|
|
|
|
dev_t fileDeviceId = getDeviceId(filename);
|
|
|
|
|
if (fileDeviceId != this->fileSystemDeviceId) {
|
2021-03-11 02:06:03 +08:00
|
|
|
|
TraceEvent(SevError, "DeviceIdMismatched")
|
|
|
|
|
.detail("FileSystemDeviceId", this->fileSystemDeviceId)
|
|
|
|
|
.detail("FileDeviceId", fileDeviceId);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
throw io_error();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
|
if ((flags & IAsyncFile::OPEN_EXCLUSIVE))
|
|
|
|
|
ASSERT(flags & IAsyncFile::OPEN_CREATE);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
if (!(flags & IAsyncFile::OPEN_UNCACHED))
|
|
|
|
|
return AsyncFileCached::open(filename, flags, mode);
|
2017-06-16 17:14:19 +08:00
|
|
|
|
|
|
|
|
|
Future<Reference<IAsyncFile>> f;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
#ifdef __linux__
|
2019-03-13 05:04:18 +08:00
|
|
|
|
// In the vast majority of cases, we wish to use Kernel AIO. However, some systems
|
2019-09-28 02:28:15 +08:00
|
|
|
|
// don’t properly support kernel async I/O without O_DIRECT or AIO at all. In such
|
|
|
|
|
// cases, DISABLE_POSIX_KERNEL_AIO knob can be enabled to fallback to EIO instead
|
2019-10-25 02:45:32 +08:00
|
|
|
|
// of Kernel AIO. And EIO_USE_ODIRECT can be used to turn on or off O_DIRECT within
|
|
|
|
|
// EIO.
|
2019-03-13 05:04:18 +08:00
|
|
|
|
if ((flags & IAsyncFile::OPEN_UNBUFFERED) && !(flags & IAsyncFile::OPEN_NO_AIO) &&
|
|
|
|
|
!FLOW_KNOBS->DISABLE_POSIX_KERNEL_AIO)
|
2020-08-19 05:43:17 +08:00
|
|
|
|
f = AsyncFileKAIO::open(filename, flags, mode, nullptr);
|
2017-06-16 17:14:19 +08:00
|
|
|
|
else
|
2017-05-26 04:48:44 +08:00
|
|
|
|
#endif
|
2021-03-11 02:06:03 +08:00
|
|
|
|
f = Net2AsyncFile::open(
|
|
|
|
|
filename,
|
|
|
|
|
flags,
|
|
|
|
|
mode,
|
|
|
|
|
static_cast<boost::asio::io_service*>((void*)g_network->global(INetwork::enASIOService)));
|
|
|
|
|
if (FLOW_KNOBS->PAGE_WRITE_CHECKSUM_HISTORY > 0)
|
2017-06-16 17:14:19 +08:00
|
|
|
|
f = map(f, [=](Reference<IAsyncFile> r) { return Reference<IAsyncFile>(new AsyncFileWriteChecker(r)); });
|
2021-01-26 04:09:29 +08:00
|
|
|
|
#if (!defined(TLS_DISABLED) && !defined(_WIN32))
|
2021-01-23 13:47:36 +08:00
|
|
|
|
if (flags & IAsyncFile::OPEN_ENCRYPTED)
|
|
|
|
|
f = map(f, [flags](Reference<IAsyncFile> r) {
|
|
|
|
|
return Reference<IAsyncFile>(new AsyncFileEncrypted(r, flags & IAsyncFile::OPEN_READWRITE));
|
|
|
|
|
});
|
2021-01-26 02:42:14 +08:00
|
|
|
|
#endif
|
2017-06-16 17:14:19 +08:00
|
|
|
|
return f;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
|
// Deletes the given file. If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power
|
|
|
|
|
// failure.
|
2020-12-28 12:43:47 +08:00
|
|
|
|
Future<Void> Net2FileSystem::deleteFile(const std::string& filename, bool mustBeDurable) {
|
2017-05-26 04:48:44 +08:00
|
|
|
|
return Net2AsyncFile::deleteFile(filename, mustBeDurable);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 12:43:47 +08:00
|
|
|
|
Future<std::time_t> Net2FileSystem::lastWriteTime(const std::string& filename) {
|
2021-03-11 02:06:03 +08:00
|
|
|
|
return Net2AsyncFile::lastWriteTime(filename);
|
2018-07-07 09:51:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 12:43:47 +08:00
|
|
|
|
void Net2FileSystem::newFileSystem(double ioTimeout, const std::string& fileSystemPath) {
|
2017-05-26 04:48:44 +08:00
|
|
|
|
g_network->setGlobal(INetwork::enFileSystem, (flowGlobalType) new Net2FileSystem(ioTimeout, fileSystemPath));
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 12:43:47 +08:00
|
|
|
|
Net2FileSystem::Net2FileSystem(double ioTimeout, const std::string& fileSystemPath) {
|
2017-05-26 04:48:44 +08:00
|
|
|
|
Net2AsyncFile::init();
|
|
|
|
|
#ifdef __linux__
|
2020-04-17 01:56:01 +08:00
|
|
|
|
if (!FLOW_KNOBS->DISABLE_POSIX_KERNEL_AIO)
|
2021-03-11 02:06:03 +08:00
|
|
|
|
AsyncFileKAIO::init(Reference<IEventFD>(N2::ASIOReactor::getEventFD()), ioTimeout);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
|
|
if (fileSystemPath.empty()) {
|
|
|
|
|
checkFileSystem = false;
|
|
|
|
|
} else {
|
|
|
|
|
checkFileSystem = true;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
this->fileSystemDeviceId = getDeviceId(fileSystemPath);
|
|
|
|
|
if (fileSystemPath != "/") {
|
|
|
|
|
dev_t fileSystemParentDeviceId = getDeviceId(parentDirectory(fileSystemPath));
|
|
|
|
|
if (this->fileSystemDeviceId == fileSystemParentDeviceId) {
|
2021-03-11 02:06:03 +08:00
|
|
|
|
criticalError(FDB_EXIT_ERROR,
|
|
|
|
|
"FileSystemError",
|
|
|
|
|
format("`%s' is not a mount point", fileSystemPath.c_str()).c_str());
|
2017-05-26 04:48:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-21 00:29:01 +08:00
|
|
|
|
} catch (Error&) {
|
2021-03-11 02:06:03 +08:00
|
|
|
|
criticalError(FDB_EXIT_ERROR,
|
|
|
|
|
"FileSystemError",
|
|
|
|
|
format("Could not get device id from `%s'", fileSystemPath.c_str()).c_str());
|
2017-05-26 04:48:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2020-04-19 10:40:55 +08:00
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
|
Future<Void> Net2FileSystem::renameFile(const std::string& from, const std::string& to) {
|
2021-03-03 08:34:23 +08:00
|
|
|
|
return Net2AsyncFile::renameFile(from, to);
|
2021-03-03 07:38:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-19 10:40:55 +08:00
|
|
|
|
void Net2FileSystem::stop() {
|
|
|
|
|
Net2AsyncFile::stop();
|
|
|
|
|
}
|