Added a flag to prevent stats cache expiration checks

This commit is contained in:
Takeshi Nakatani
2025-08-17 06:19:03 +00:00
committed by Andrew Gaul
parent 52b263b99c
commit b2e318c5c7
3 changed files with 90 additions and 3 deletions

View File

@ -99,6 +99,8 @@ bool StatCacheNode::IsExpireIntervalType = false;
time_t StatCacheNode::ExpireTime = 15 * 60; time_t StatCacheNode::ExpireTime = 15 * 60;
bool StatCacheNode::UseNegativeCache = true; bool StatCacheNode::UseNegativeCache = true;
std::mutex StatCacheNode::cache_lock; std::mutex StatCacheNode::cache_lock;
unsigned long StatCacheNode::DisableCheckingExpire = 0L;
struct timespec StatCacheNode::DisableExpireDate = {0, 0};
// //
// Class Methods // Class Methods
@ -162,6 +164,57 @@ bool StatCacheNode::SetNegativeCache(bool flag)
return old; return old;
} }
bool StatCacheNode::NeedExpireCheckHasLock(const struct timespec& ts)
{
if(!StatCacheNode::IsEnableExpireTime()){
return false;
}
// [NOTE]
// If the expiration date check is disabled(0 < DisableCheckingExpire)
// and the date is later than DisableExpireDate, it is determined that
// checking is not necessary.
//
if(0L < StatCacheNode::DisableCheckingExpire){
if(0 >= CompareStatCacheTime(StatCacheNode::DisableExpireDate, ts)){
return false;
}
}
return true;
}
bool StatCacheNode::PreventExpireCheck()
{
if(!StatCacheNode::IsEnableExpireTime()){
return false;
}
std::lock_guard<std::mutex> lock(StatCacheNode::cache_lock);
++StatCacheNode::DisableCheckingExpire;
if(0 == StatCacheNode::DisableExpireDate.tv_sec){
SetCurrentTime(StatCacheNode::DisableExpireDate);
StatCacheNode::DisableExpireDate.tv_sec -= StatCacheNode::GetExpireTime();
}
return true;
}
bool StatCacheNode::ResumeExpireCheck()
{
if(!StatCacheNode::IsEnableExpireTime()){
return false;
}
std::lock_guard<std::mutex> lock(StatCacheNode::cache_lock);
if(0 < StatCacheNode::DisableCheckingExpire){
--StatCacheNode::DisableCheckingExpire;
}
if(0 == StatCacheNode::DisableCheckingExpire){
StatCacheNode::DisableExpireDate = {0, 0};
}
return true;
}
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Methods // Methods
//------------------------------------------------------------------- //-------------------------------------------------------------------
@ -654,7 +707,7 @@ s3obj_type_map_t::size_type StatCacheNode::GetChildMap(s3obj_type_map_t& childma
bool StatCacheNode::IsExpireStatCacheTimeHasLock() const bool StatCacheNode::IsExpireStatCacheTimeHasLock() const
{ {
if(StatCacheNode::IsEnableExpireTime()){ if(NeedExpireCheckHasLock(cache_date)){
if(IsExpireStatCacheTime(cache_date, StatCacheNode::GetExpireTime())){ if(IsExpireStatCacheTime(cache_date, StatCacheNode::GetExpireTime())){
// this cache is expired // this cache is expired
return true; return true;
@ -1182,11 +1235,12 @@ std::shared_ptr<StatCacheNode> DirStatCache::FindHasLock(const std::string& strp
bool DirStatCache::NeedTruncateProcessing() bool DirStatCache::NeedTruncateProcessing()
{ {
if(!StatCacheNode::IsEnableExpireTime()){ std::lock_guard<std::mutex> lock(StatCacheNode::cache_lock);
if(!NeedExpireCheckHasLock(cache_date)){
return false; return false;
} }
std::lock_guard<std::mutex> dircachelock(dir_cache_lock);
std::lock_guard<std::mutex> dircachelock(dir_cache_lock);
return IsExpireStatCacheTime(last_check_date, StatCacheNode::GetExpireTime()); return IsExpireStatCacheTime(last_check_date, StatCacheNode::GetExpireTime());
} }

View File

@ -79,6 +79,8 @@ class StatCacheNode : public std::enable_shared_from_this<StatCacheNode>
static time_t ExpireTime; static time_t ExpireTime;
static bool UseNegativeCache; static bool UseNegativeCache;
static std::mutex cache_lock; // for internal data static std::mutex cache_lock; // for internal data
static unsigned long DisableCheckingExpire GUARDED_BY(cache_lock); // If greater than 0, it disables the expiration check, which allows disabling checks during processing.
static struct timespec DisableExpireDate GUARDED_BY(cache_lock); // Data registerd after this time will not be truncated(if 0 < DisableCheckingExpire)
private: private:
objtype_t cache_type GUARDED_BY(StatCacheNode::cache_lock) = objtype_t::UNKNOWN; // object type is set in the constructor(except dir). objtype_t cache_type GUARDED_BY(StatCacheNode::cache_lock) = objtype_t::UNKNOWN; // object type is set in the constructor(except dir).
@ -97,6 +99,7 @@ class StatCacheNode : public std::enable_shared_from_this<StatCacheNode>
static void IncrementCacheCount(objtype_t type); static void IncrementCacheCount(objtype_t type);
static void DecrementCacheCount(objtype_t type); static void DecrementCacheCount(objtype_t type);
static bool SetNegativeCache(bool flag); static bool SetNegativeCache(bool flag);
static bool NeedExpireCheckHasLock(const struct timespec& ts) REQUIRES(StatCacheNode::cache_lock);
// Cache Type // Cache Type
bool isSameObjectTypeHasLock(objtype_t type) const REQUIRES(StatCacheNode::cache_lock); bool isSameObjectTypeHasLock(objtype_t type) const REQUIRES(StatCacheNode::cache_lock);
@ -156,6 +159,8 @@ class StatCacheNode : public std::enable_shared_from_this<StatCacheNode>
static bool EnableNegativeCache() { return SetNegativeCache(true); } static bool EnableNegativeCache() { return SetNegativeCache(true); }
static bool DisableNegativeCache() { return SetNegativeCache(false); } static bool DisableNegativeCache() { return SetNegativeCache(false); }
static bool IsEnabledNegativeCache() { return UseNegativeCache; } static bool IsEnabledNegativeCache() { return UseNegativeCache; }
static bool PreventExpireCheck();
static bool ResumeExpireCheck();
// Constructor/Destructor // Constructor/Destructor
explicit StatCacheNode(const char* path = nullptr, objtype_t type = objtype_t::UNKNOWN); explicit StatCacheNode(const char* path = nullptr, objtype_t type = objtype_t::UNKNOWN);
@ -321,6 +326,28 @@ class NegativeStatCache : public StatCacheNode
NegativeStatCache& operator=(NegativeStatCache&&) = delete; NegativeStatCache& operator=(NegativeStatCache&&) = delete;
}; };
//-------------------------------------------------------------------
// Utility Class : PreventStatCacheExpire
//-------------------------------------------------------------------
class PreventStatCacheExpire
{
public:
explicit PreventStatCacheExpire()
{
StatCacheNode::PreventExpireCheck();
}
~PreventStatCacheExpire()
{
StatCacheNode::ResumeExpireCheck();
}
PreventStatCacheExpire(const PreventStatCacheExpire&) = delete;
PreventStatCacheExpire(PreventStatCacheExpire&&) = delete;
PreventStatCacheExpire& operator=(const PreventStatCacheExpire&) = delete;
PreventStatCacheExpire& operator=(PreventStatCacheExpire&&) = delete;
};
#endif // S3FS_CACHE_NODE_H_ #endif // S3FS_CACHE_NODE_H_
/* /*

View File

@ -1231,6 +1231,9 @@ static int s3fs_mkdir(const char* _path, mode_t mode)
return -EIO; return -EIO;
} }
// keep stat cache without checking expiration
PreventStatCacheExpire nocacheexpire;
// check parent directory attribute. // check parent directory attribute.
if(0 != (result = check_parent_object_access(path, W_OK | X_OK))){ if(0 != (result = check_parent_object_access(path, W_OK | X_OK))){
return result; return result;
@ -1322,6 +1325,9 @@ static int s3fs_rmdir(const char* _path)
FUSE_CTX_INFO("[path=%s]", path); FUSE_CTX_INFO("[path=%s]", path);
// keep stat cache without checking expiration
PreventStatCacheExpire nocacheexpire;
if(0 != (result = check_parent_object_access(path, W_OK | X_OK))){ if(0 != (result = check_parent_object_access(path, W_OK | X_OK))){
return result; return result;
} }