diff --git a/cloud/filestore/config/filesystem.proto b/cloud/filestore/config/filesystem.proto index ab287318c59..2bcc7c5ce6a 100644 --- a/cloud/filestore/config/filesystem.proto +++ b/cloud/filestore/config/filesystem.proto @@ -48,4 +48,7 @@ message TFileSystemConfig // Aligment needed for buffers when using direct io optional uint32 DirectIoAlign = 14; + + // Enable Writeback cache on guest (fuse client) + optional bool GuestWritebackCacheEnabled = 15; } diff --git a/cloud/filestore/config/server.proto b/cloud/filestore/config/server.proto index cfdd16e66fd..c619fe22b0c 100644 --- a/cloud/filestore/config/server.proto +++ b/cloud/filestore/config/server.proto @@ -89,6 +89,10 @@ message TLocalServiceConfig // Aligment needed for buffers when using direct io optional uint32 DirectIoAlign = 10; + + // Enable Writeback cache on guest (fuse client) + optional bool GuestWritebackCacheEnabled = 11; + } //////////////////////////////////////////////////////////////////////////////// diff --git a/cloud/filestore/config/storage.proto b/cloud/filestore/config/storage.proto index b5ab5e50a3f..7f071056ece 100644 --- a/cloud/filestore/config/storage.proto +++ b/cloud/filestore/config/storage.proto @@ -456,4 +456,7 @@ message TStorageConfig // Disables TwoStageRead for HDD filesystems. optional bool TwoStageReadDisabledForHDD = 404; + + // Enable Writeback cache on guest (fuse client) + optional bool GuestWritebackCacheEnabled = 405; } diff --git a/cloud/filestore/libs/service_local/config.cpp b/cloud/filestore/libs/service_local/config.cpp index 0aa5e8d8d3a..41a9c1dfcaf 100644 --- a/cloud/filestore/libs/service_local/config.cpp +++ b/cloud/filestore/libs/service_local/config.cpp @@ -21,6 +21,7 @@ namespace { xxx(MaxHandlePerSessionCount, ui32, 10000 )\ xxx(DirectIoEnabled, bool, false )\ xxx(DirectIoAlign, ui32, 4_KB )\ + xxx(GuestWritebackCacheEnabled, bool, false )\ // FILESTORE_SERVICE_CONFIG #define FILESTORE_SERVICE_DECLARE_CONFIG(name, type, value) \ diff --git a/cloud/filestore/libs/service_local/config.h b/cloud/filestore/libs/service_local/config.h index 24478167b30..851606e4983 100644 --- a/cloud/filestore/libs/service_local/config.h +++ b/cloud/filestore/libs/service_local/config.h @@ -31,6 +31,7 @@ class TLocalFileStoreConfig ui32 GetMaxHandlePerSessionCount() const; bool GetDirectIoEnabled() const; ui32 GetDirectIoAlign() const; + bool GetGuestWritebackCacheEnabled() const; void Dump(IOutputStream& out) const; void DumpHtml(IOutputStream& out) const; diff --git a/cloud/filestore/libs/service_local/fs_session.cpp b/cloud/filestore/libs/service_local/fs_session.cpp index 01416d4c9da..9c5a3f21be6 100644 --- a/cloud/filestore/libs/service_local/fs_session.cpp +++ b/cloud/filestore/libs/service_local/fs_session.cpp @@ -78,6 +78,8 @@ NProto::TCreateSessionResponse TLocalFileSystem::CreateSession( auto* features = response.MutableFileStore()->MutableFeatures(); features->SetDirectIoEnabled(Config->GetDirectIoEnabled()); features->SetDirectIoAlign(Config->GetDirectIoAlign()); + features->SetGuestWritebackCacheEnabled( + Config->GetGuestWritebackCacheEnabled()); return response; } diff --git a/cloud/filestore/libs/storage/core/config.cpp b/cloud/filestore/libs/storage/core/config.cpp index ba4999b20ad..b898e56701e 100644 --- a/cloud/filestore/libs/storage/core/config.cpp +++ b/cloud/filestore/libs/storage/core/config.cpp @@ -43,6 +43,7 @@ using TAliases = NProto::TStorageConfig::TFilestoreAliases; xxx(GarbageCompactionThresholdAverage, ui32, 20 )\ xxx(CompactRangeGarbagePercentageThreshold, ui32, 0 )\ xxx(CompactRangeAverageBlobSizeThreshold, ui32, 0 )\ + xxx(GuestWritebackCacheEnabled, bool, false )\ xxx(NewCompactionEnabled, bool, false )\ xxx(UseMixedBlocksInsteadOfAliveBlocksInCompaction, bool, false )\ xxx(CollectGarbageThreshold, ui32, 4_MB )\ diff --git a/cloud/filestore/libs/storage/core/config.h b/cloud/filestore/libs/storage/core/config.h index 7181307d31a..c2e716c7138 100644 --- a/cloud/filestore/libs/storage/core/config.h +++ b/cloud/filestore/libs/storage/core/config.h @@ -286,6 +286,8 @@ class TStorageConfig bool GetTwoStageReadDisabledForHDD() const; bool GetThreeStageWriteDisabledForHDD() const; + + bool GetGuestWritebackCacheEnabled() const; }; } // namespace NCloud::NFileStore::NStorage diff --git a/cloud/filestore/libs/storage/tablet/tablet_actor_createsession.cpp b/cloud/filestore/libs/storage/tablet/tablet_actor_createsession.cpp index 6e25a6104eb..718f727ec7a 100644 --- a/cloud/filestore/libs/storage/tablet/tablet_actor_createsession.cpp +++ b/cloud/filestore/libs/storage/tablet/tablet_actor_createsession.cpp @@ -43,6 +43,9 @@ void FillFeatures(const TStorageConfig& config, NProto::TFileStore& fileStore) config.GetAsyncDestroyHandleEnabled()); features->SetAsyncHandleOperationPeriod( config.GetAsyncHandleOperationPeriod().MilliSeconds()); + + features->SetGuestWritebackCacheEnabled( + config.GetGuestWritebackCacheEnabled()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/cloud/filestore/libs/vfs_fuse/config.cpp b/cloud/filestore/libs/vfs_fuse/config.cpp index 16f22fe1a10..c3b2b0c7ad2 100644 --- a/cloud/filestore/libs/vfs_fuse/config.cpp +++ b/cloud/filestore/libs/vfs_fuse/config.cpp @@ -32,6 +32,8 @@ namespace { \ xxx(DirectIoEnabled, bool, false )\ xxx(DirectIoAlign, ui32, 4_KB )\ + \ + xxx(GuestWritebackCacheEnabled, bool, false )\ // FILESTORE_FUSE_CONFIG #define FILESTORE_FILESYSTEM_DECLARE_CONFIG(name, type, value) \ diff --git a/cloud/filestore/libs/vfs_fuse/config.h b/cloud/filestore/libs/vfs_fuse/config.h index 95b11590563..d04c360c744 100644 --- a/cloud/filestore/libs/vfs_fuse/config.h +++ b/cloud/filestore/libs/vfs_fuse/config.h @@ -42,6 +42,8 @@ struct TFileSystemConfig bool GetDirectIoEnabled() const; ui32 GetDirectIoAlign() const; + bool GetGuestWritebackCacheEnabled() const; + void Dump(IOutputStream& out) const; void DumpHtml(IOutputStream& out) const; }; diff --git a/cloud/filestore/libs/vfs_fuse/loop.cpp b/cloud/filestore/libs/vfs_fuse/loop.cpp index 58bb5c16bc1..7cac1ce95d6 100644 --- a/cloud/filestore/libs/vfs_fuse/loop.cpp +++ b/cloud/filestore/libs/vfs_fuse/loop.cpp @@ -508,6 +508,7 @@ class TFileSystemLoop final std::shared_ptr CompletionQueue; IRequestStatsPtr RequestStats; IFileSystemPtr FileSystem; + TFileSystemConfigPtr FileSystemConfig; bool HandleOpsQueueInitialized = false; @@ -785,13 +786,13 @@ class TFileSystemLoop final RequestStats, Log, StorageMediaKind); - auto filestoreConfig = MakeFileSystemConfig(filestore); + FileSystemConfig = MakeFileSystemConfig(filestore); std::unique_ptr handleOpsQueue; - if (filestoreConfig->GetAsyncDestroyHandleEnabled()) { + if (FileSystemConfig->GetAsyncDestroyHandleEnabled()) { TString path = TFsPath(Config->GetHandleOpsQueuePath()) / - filestoreConfig->GetFileSystemId() / + FileSystemConfig->GetFileSystemId() / response.GetSession().GetSessionId(); if (!NFs::MakeDirectoryRecursive(path)) { TString msg = TStringBuilder() @@ -816,7 +817,7 @@ class TFileSystemLoop final ProfileLog, Scheduler, Timer, - filestoreConfig, + FileSystemConfig, Session, RequestStats, CompletionQueue, @@ -834,7 +835,7 @@ class TFileSystemLoop final SessionState.empty() ? "new" : "existing"); TStringStream filestoreConfigDump; - filestoreConfig->Dump(filestoreConfigDump); + FileSystemConfig->Dump(filestoreConfigDump); STORAGE_INFO( "[f:%s][c:%s] new session filestore config: %s", Config->GetFileSystemId().Quote().c_str(), @@ -900,6 +901,9 @@ class TFileSystemLoop final config.SetDirectIoEnabled(features.GetDirectIoEnabled()); config.SetDirectIoAlign(features.GetDirectIoAlign()); + config.SetGuestWritebackCacheEnabled( + features.GetGuestWritebackCacheEnabled()); + return std::make_shared(config); } @@ -931,6 +935,10 @@ class TFileSystemLoop final // e.g. left from a crash or smth, paranoid mode ResetSessionState(SessionThread->GetSession().Dump()); + if (FileSystemConfig->GetGuestWritebackCacheEnabled()) { + conn->want |= FUSE_CAP_WRITEBACK_CACHE; + } + FileSystem->Init(); } diff --git a/cloud/filestore/public/api/protos/fs.proto b/cloud/filestore/public/api/protos/fs.proto index 85a4a68f505..76c4e7d96a1 100644 --- a/cloud/filestore/public/api/protos/fs.proto +++ b/cloud/filestore/public/api/protos/fs.proto @@ -26,6 +26,7 @@ message TFileStoreFeatures uint32 DirectIoAlign = 11; bool TwoStageReadDisabledForHDD = 12; bool ThreeStageWriteDisabledForHDD = 13; + bool GuestWritebackCacheEnabled = 14; } message TFileStore diff --git a/contrib/libs/fuse/include/fuse_common.h b/contrib/libs/fuse/include/fuse_common.h index a4d980d5a1a..91f4d46df83 100644 --- a/contrib/libs/fuse/include/fuse_common.h +++ b/contrib/libs/fuse/include/fuse_common.h @@ -100,6 +100,7 @@ struct fuse_file_info { * FUSE_CAP_SPLICE_MOVE: ability to move data to the fuse device with splice() * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device * FUSE_CAP_IOCTL_DIR: ioctl support on directories + * FUSE_CAP_WRITEBACK_CACHE: writeback caching should be enabled */ #define FUSE_CAP_ASYNC_READ (1 << 0) #define FUSE_CAP_POSIX_LOCKS (1 << 1) @@ -112,6 +113,7 @@ struct fuse_file_info { #define FUSE_CAP_SPLICE_READ (1 << 9) #define FUSE_CAP_FLOCK_LOCKS (1 << 10) #define FUSE_CAP_IOCTL_DIR (1 << 11) +#define FUSE_CAP_WRITEBACK_CACHE (1 << 16) /** * Ioctl flags diff --git a/contrib/libs/fuse/include/fuse_kernel.h b/contrib/libs/fuse/include/fuse_kernel.h index 9e02fe3482a..5796406bda4 100644 --- a/contrib/libs/fuse/include/fuse_kernel.h +++ b/contrib/libs/fuse/include/fuse_kernel.h @@ -211,6 +211,7 @@ struct fuse_file_lock { #define FUSE_BIG_WRITES (1 << 5) #define FUSE_DONT_MASK (1 << 6) #define FUSE_FLOCK_LOCKS (1 << 10) +#define FUSE_WRITEBACK_CACHE (1 << 16) /** * CUSE INIT request/reply flags diff --git a/contrib/libs/fuse/lib/fuse_lowlevel.c b/contrib/libs/fuse/lib/fuse_lowlevel.c index ff03c6301aa..f3869fd8e7b 100644 --- a/contrib/libs/fuse/lib/fuse_lowlevel.c +++ b/contrib/libs/fuse/lib/fuse_lowlevel.c @@ -1856,6 +1856,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_DONT_MASK; if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) outarg.flags |= FUSE_FLOCK_LOCKS; + if (f->conn.want & FUSE_CAP_WRITEBACK_CACHE) + outarg.flags |= FUSE_WRITEBACK_CACHE; + outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) {