Skip to content

Commit

Permalink
[merge to stable]: issue-2190, issue-2189, issue-2263 (#2344)
Browse files Browse the repository at this point in the history
* issue-2190: persistent table data structure (#2199)

Implementation of records table on top of memory mapped file.

This will be used to recover inodes and file descriptors in later PRs

* issue-2263: generate nfs-vhost-local.txt config file (#2264)

* [Filestore] issue-2190: support reconnect for local file system (#2103)

* [Filestore] issue-2189: support O_DIRECT in local filestore (#2188)

* fix compilation
  • Loading branch information
budevg authored Oct 28, 2024
1 parent cd693be commit 3f709c6
Show file tree
Hide file tree
Showing 56 changed files with 2,478 additions and 83 deletions.
6 changes: 6 additions & 0 deletions cloud/filestore/config/filesystem.proto
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ message TFileSystemConfig

// Period of processing create/destroy handle requests.
optional uint32 AsyncHandleOperationPeriod = 12;

// Enable O_DIRECT when working with files
optional bool DirectIoEnabled = 13;

// Aligment needed for buffers when using direct io
optional uint32 DirectIoAlign = 14;
}
17 changes: 17 additions & 0 deletions cloud/filestore/config/server.proto
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,23 @@ message TLocalServiceConfig
optional uint32 DefaultPermissions = 3;
optional uint32 IdleSessionTimeout = 4;
optional uint32 NumThreads = 5;

// directory where state for session recovery is saved
optional string StatePath = 6;

// Maximum number of nodes which can be opened by all sessions
// for single local file system
optional uint32 MaxNodeCount = 7;

// Maximum number of file handles which can be opened by single session
// for single local file system
optional uint32 MaxHandlePerSessionCount = 8;

// Enable O_DIRECT when working with files
optional bool DirectIoEnabled = 9;

// Aligment needed for buffers when using direct io
optional uint32 DirectIoAlign = 10;
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions cloud/filestore/libs/diagnostics/critical_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ namespace NCloud::NFileStore{
xxx(InvalidDupCacheEntry) \
xxx(GeneratedOrphanNode) \
xxx(ReceivedNodeOpErrorFromShard) \
xxx(LocalFsMaxSessionNodesInUse) \
xxx(LocalFsMaxSessionFileHandlesInUse) \
xxx(LocalFsMissingHandleNode) \
// FILESTORE_CRITICAL_EVENTS

#define FILESTORE_IMPOSSIBLE_EVENTS(xxx) \
Expand All @@ -41,6 +44,7 @@ namespace NCloud::NFileStore{
xxx(NewChildNodeIsNull) \
xxx(IndexOutOfBounds) \
xxx(CheckFreshBytesFailed) \
xxx(LocalFsDuplicateFileHandle) \
// FILESTORE_IMPOSSIBLE_EVENTS

////////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions cloud/filestore/libs/service/filestore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ constexpr std::array SUPPORTED_HANDLE_FLAGS = {
TFlag2Proto{O_NOFOLLOW, TCreateHandleRequest::E_NOFOLLOW},
TFlag2Proto{O_NONBLOCK, TCreateHandleRequest::E_NONBLOCK},
TFlag2Proto{O_PATH, TCreateHandleRequest::E_PATH},
TFlag2Proto{O_DIRECT, TCreateHandleRequest::E_DIRECT},
};

constexpr std::array SUPPORTED_RENAME_FLAGS = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ target_link_libraries(filestore-libs-service_local PUBLIC
contrib-libs-cxxsupp
yutil
cloud-filestore-config
filestore-libs-diagnostics
filestore-libs-service
core-libs-common
core-libs-diagnostics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ target_link_libraries(filestore-libs-service_local PUBLIC
contrib-libs-cxxsupp
yutil
cloud-filestore-config
filestore-libs-diagnostics
filestore-libs-service
core-libs-common
core-libs-diagnostics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ target_link_libraries(filestore-libs-service_local PUBLIC
contrib-libs-cxxsupp
yutil
cloud-filestore-config
filestore-libs-diagnostics
filestore-libs-service
core-libs-common
core-libs-diagnostics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ target_link_libraries(filestore-libs-service_local PUBLIC
contrib-libs-cxxsupp
yutil
cloud-filestore-config
filestore-libs-diagnostics
filestore-libs-service
core-libs-common
core-libs-diagnostics
Expand Down
7 changes: 7 additions & 0 deletions cloud/filestore/libs/service_local/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <library/cpp/monlib/service/pages/templates.h>

#include <util/generic/size_literals.h>

namespace NCloud::NFileStore {

namespace {
Expand All @@ -14,6 +16,11 @@ namespace {
xxx(DefaultPermissions, ui32, 0775 )\
xxx(IdleSessionTimeout, TDuration, TDuration::Seconds(30) )\
xxx(NumThreads, ui32, 4 )\
xxx(StatePath, TString, "./" )\
xxx(MaxNodeCount, ui32, 1000000 )\
xxx(MaxHandlePerSessionCount, ui32, 10000 )\
xxx(DirectIoEnabled, bool, false )\
xxx(DirectIoAlign, ui32, 4_KB )\
// FILESTORE_SERVICE_CONFIG

#define FILESTORE_SERVICE_DECLARE_CONFIG(name, type, value) \
Expand Down
5 changes: 5 additions & 0 deletions cloud/filestore/libs/service_local/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class TLocalFileStoreConfig
ui32 GetDefaultPermissions() const;
TDuration GetIdleSessionTimeout() const;
ui32 GetNumThreads() const;
TString GetStatePath() const;
ui32 GetMaxNodeCount() const;
ui32 GetMaxHandlePerSessionCount() const;
bool GetDirectIoEnabled() const;
ui32 GetDirectIoAlign() const;

void Dump(IOutputStream& out) const;
void DumpHtml(IOutputStream& out) const;
Expand Down
23 changes: 14 additions & 9 deletions cloud/filestore/libs/service_local/fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,34 @@ TLocalFileSystem::TLocalFileSystem(
TLocalFileStoreConfigPtr config,
NProto::TFileStore store,
TFsPath root,
TFsPath statePath,
ITimerPtr timer,
ISchedulerPtr scheduler,
ILoggingServicePtr logging,
IFileIOServicePtr fileIOService)
: Config(std::move(config))
, Root(std::move(root))
, StatePath(std::move(statePath))
, Timer(std::move(timer))
, Scheduler(std::move(scheduler))
, Logging(std::move(logging))
, FileIOService(std::move(fileIOService))
, Store(std::move(store))
{
Log = logging->CreateLog(Store.GetFileSystemId());
Log = Logging->CreateLog(Store.GetFileSystemId());

InitIndex();
ScheduleCleanupSessions();
}
STORAGE_INFO(
"LocalFileSystemId=" << Store.GetFileSystemId() <<
", DirectIoEnabled=" << Config->GetDirectIoEnabled() <<
", DirectIoAlign=" << Config->GetDirectIoAlign());

void TLocalFileSystem::InitIndex()
{
TLocalIndex::TNodeMap nodes;
nodes.insert(TIndexNode::CreateRoot(Root));
Index = std::make_shared<TLocalIndex>(
Root,
StatePath,
Config->GetMaxNodeCount(),
Log);

Index = std::make_shared<TLocalIndex>(std::move(nodes));
ScheduleCleanupSessions();
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 3 additions & 1 deletion cloud/filestore/libs/service_local/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ class TLocalFileSystem final
private:
const TLocalFileStoreConfigPtr Config;
const TFsPath Root;
const TFsPath StatePath;
const ITimerPtr Timer;
const ISchedulerPtr Scheduler;
const ILoggingServicePtr Logging;
const IFileIOServicePtr FileIOService;

NProto::TFileStore Store;
Expand All @@ -111,6 +113,7 @@ class TLocalFileSystem final
TLocalFileStoreConfigPtr config,
NProto::TFileStore store,
TFsPath root,
TFsPath statePath,
ITimerPtr timer,
ISchedulerPtr scheduler,
ILoggingServicePtr logging,
Expand Down Expand Up @@ -144,7 +147,6 @@ class TLocalFileSystem final
}

private:
void InitIndex();

void ScheduleCleanupSessions();
void CleanupSessions();
Expand Down
11 changes: 10 additions & 1 deletion cloud/filestore/libs/service_local/fs_attrs.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "fs.h"

#include <cloud/filestore/libs/diagnostics/critical_events.h>

#include <optional>

namespace NCloud::NFileStore {
Expand Down Expand Up @@ -87,7 +89,14 @@ NProto::TGetNodeAttrResponse TLocalFileSystem::GetNodeAttr(
// TODO: better? race between statting one child and creating another one
// but maybe too costly...
stat = child->Stat();
session->TryInsertNode(std::move(child));
if (!session->TryInsertNode(
std::move(child),
node->GetNodeId(),
name))
{
ReportLocalFsMaxSessionNodesInUse();
return TErrorResponse(ErrorNoSpaceLeft());
}
}
} else {
stat = node->Stat();
Expand Down
56 changes: 44 additions & 12 deletions cloud/filestore/libs/service_local/fs_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include "lowlevel.h"

#include <cloud/filestore/libs/diagnostics/critical_events.h>

#include <cloud/storage/core/libs/common/aligned_buffer.h>
#include <cloud/storage/core/libs/common/file_io_service.h>

#include <util/string/builder.h>
Expand All @@ -28,29 +31,49 @@ NProto::TCreateHandleResponse TLocalFileSystem::CreateHandle(
return TErrorResponse(ErrorInvalidParent(request.GetNodeId()));
}

const int flags = HandleFlagsToSystem(request.GetFlags());
int flags = HandleFlagsToSystem(request.GetFlags());
if (!Config->GetDirectIoEnabled()) {
flags &= ~O_DIRECT;
}
const int mode = request.GetMode()
? request.GetMode() : Config->GetDefaultPermissions();

TFileHandle handle;
TFileStat stat;
ui64 nodeId;
if (const auto& pathname = request.GetName()) {
handle = node->OpenHandle(pathname, flags, mode);

auto newnode = TIndexNode::Create(*node, pathname);
stat = newnode->Stat();

session->TryInsertNode(std::move(newnode));
nodeId = newnode->GetNodeId();

if (!session->TryInsertNode(
std::move(newnode),
node->GetNodeId(),
pathname))
{
ReportLocalFsMaxSessionNodesInUse();
return TErrorResponse(ErrorNoSpaceLeft());
}
} else {
handle = node->OpenHandle(flags);
stat = node->Stat();
nodeId = node->GetNodeId();
}

const FHANDLE fd = handle;
session->InsertHandle(std::move(handle));
// Don't persist flags that only make sense on initial open
flags = flags & ~(O_CREAT | O_EXCL | O_TRUNC);

auto [handleId, error] =
session->InsertHandle(std::move(handle), nodeId, flags);
if (HasError(error)) {
ReportLocalFsMaxSessionFileHandlesInUse();
return TErrorResponse(error);
}

NProto::TCreateHandleResponse response;
response.SetHandle(fd);
response.SetHandle(handleId);
ConvertStats(stat, *response.MutableNodeAttr());

return response;
Expand Down Expand Up @@ -79,18 +102,23 @@ TFuture<NProto::TReadDataResponse> TLocalFileSystem::ReadDataAsync(
TErrorResponse(ErrorInvalidHandle(request.GetHandle())));
}

auto b = TString::Uninitialized(request.GetLength());
NSan::Unpoison(b.data(), b.size());
auto align = Config->GetDirectIoEnabled() ? Config->GetDirectIoAlign() : 0;
auto b = std::make_shared<TAlignedBuffer>(request.GetLength(), align);
NSan::Unpoison(b->Begin(), b->Size());

TArrayRef<char> data(b.begin(), b.vend());
TArrayRef<char> data(b->Begin(), b->End());
auto promise = NewPromise<NProto::TReadDataResponse>();
FileIOService->AsyncRead(*handle, request.GetOffset(), data).Subscribe(
[b = std::move(b), promise] (const TFuture<ui32>& f) mutable {
NProto::TReadDataResponse response;
try {
auto bytesRead = f.GetValue();
b.resize(bytesRead);
response.SetBuffer(std::move(b));
b->TrimSize(bytesRead);
response.SetBufferOffset(b->AlignedDataOffset());
response.SetBuffer(std::move(b->AccessBuffer()));
} catch (const TServiceError& e) {
*response.MutableError() = MakeError(MAKE_FILESTORE_ERROR(
ErrnoToFileStoreError(STATUS_FROM_CODE(e.GetCode()))));
} catch (...) {
*response.MutableError() =
MakeError(E_IO, CurrentExceptionMessage());
Expand All @@ -113,13 +141,17 @@ TFuture<NProto::TWriteDataResponse> TLocalFileSystem::WriteDataAsync(
}

auto b = std::move(*request.MutableBuffer());
TArrayRef<char> data(b.begin(), b.vend());
auto offset = request.GetBufferOffset();
TArrayRef<char> data(b.begin() + offset, b.vend());
auto promise = NewPromise<NProto::TWriteDataResponse>();
FileIOService->AsyncWrite(*handle, request.GetOffset(), data).Subscribe(
[b = std::move(b), promise] (const TFuture<ui32>& f) mutable {
NProto::TWriteDataResponse response;
try {
f.GetValue();
} catch (const TServiceError& e) {
*response.MutableError() = MakeError(MAKE_FILESTORE_ERROR(
ErrnoToFileStoreError(STATUS_FROM_CODE(e.GetCode()))));
} catch (...) {
*response.MutableError() =
MakeError(E_IO, CurrentExceptionMessage());
Expand Down
20 changes: 18 additions & 2 deletions cloud/filestore/libs/service_local/fs_node.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "fs.h"

#include <cloud/filestore/libs/diagnostics/critical_events.h>

#include <util/generic/guid.h>

namespace NCloud::NFileStore {
Expand Down Expand Up @@ -80,7 +82,14 @@ NProto::TCreateNodeResponse TLocalFileSystem::CreateNode(
}

auto stat = target->Stat();
session->TryInsertNode(std::move(target));
if (!session->TryInsertNode(
std::move(target),
parent->GetNodeId(),
request.GetName()))
{
ReportLocalFsMaxSessionNodesInUse();
return TErrorResponse(ErrorNoSpaceLeft());
}

NProto::TCreateNodeResponse response;
ConvertStats(stat, *response.MutableNode());
Expand Down Expand Up @@ -192,7 +201,14 @@ NProto::TListNodesResponse TLocalFileSystem::ListNodes(
if (!session->LookupNode(entry.second.INode)) {
auto node = TryCreateChildNode(*parent, entry.first);
if (node && node->GetNodeId() == entry.second.INode) {
session->TryInsertNode(std::move(node));
if (!session->TryInsertNode(
std::move(node),
parent->GetNodeId(),
entry.first))
{
ReportLocalFsMaxSessionNodesInUse();
return TErrorResponse(ErrorNoSpaceLeft());
}
}
}

Expand Down
Loading

0 comments on commit 3f709c6

Please sign in to comment.