6969#include " mount/mastercomm.h"
7070#include " mount/masterproxy.h"
7171#include " mount/mount_info.h"
72+ #include " mount/negative_cache.h"
7273#include " mount/notification_area_logging.h"
7374#include " mount/oplog.h"
7475#include " mount/readdata.h"
@@ -896,6 +897,19 @@ void access(Context &ctx, inode_t ino, int mask) {
896897}
897898
898899EntryParam lookup (Context &ctx, inode_t parent, const char *name) {
900+ if (gNegativeCache .lookup (parent, name)) {
901+ if (debug_mode) {
902+ safs::log_debug (" lookup: ({},{}) negative cache hit, skipping master lookup" ,
903+ parent, name);
904+ }
905+ // Negative cache hit, early return
906+ // Kernel may cache negative entries for entry_timeout seconds
907+ EntryParam e{};
908+ e.ino = 0 ;
909+ e.entry_timeout = NegativeCache::getGlobalTimeoutMs () / 1000.0 ;
910+ return e;
911+ }
912+
899913 if (debug_mode) {
900914#ifdef _WIN32
901915 if (parent != SPECIAL_INODE_ROOT || strcmp (name, SPECIAL_FILE_NAME_OPLOG) != 0 ) {
@@ -979,6 +993,16 @@ EntryParam lookup(Context &ctx, inode_t parent, const char *name) {
979993 if (status != SAUNAFS_STATUS_OK) {
980994 oplog_printf (ctx, " lookup (%" PRIiNode " ,%s): %s" , parent, name,
981995 saunafs_error_string (status));
996+
997+ // Negative cache entry miss, adding to negative cache, return early
998+ // Kernel may cache negative entries for entry_timeout seconds
999+ if (status == SAUNAFS_ERROR_ENOENT && gNegativeCache .isMaxSizeAndTimeoutMsSet ()) {
1000+ gNegativeCache .add (parent, name);
1001+ EntryParam e{};
1002+ e.ino = 0 ;
1003+ e.entry_timeout = NegativeCache::getGlobalTimeoutMs () / 1000.0 ;
1004+ return e;
1005+ }
9821006 throw RequestException (status);
9831007 }
9841008 uint64_t maxFileLen = (attr[0 ] == TYPE_FILE) ? write_data_getmaxfleng (inode) : 0 ;
@@ -3546,6 +3570,7 @@ std::vector<ChunkserverListEntry> getchunkservers() {
35463570}
35473571
35483572void init (int debug_mode_, int keep_cache_, double direntry_cache_timeout_, unsigned direntry_cache_size_,
3573+ unsigned negative_cache_timeout_, unsigned negative_cache_size_,
35493574 double entry_cache_timeout_, double attr_cache_timeout_, int mkdir_copy_sgid_,
35503575 SugidClearMode sugid_clear_mode_, bool use_rwlock_,
35513576 double acl_cache_timeout_, unsigned acl_cache_size_, bool direct_io,
@@ -3570,6 +3595,10 @@ void init(int debug_mode_, int keep_cache_, double direntry_cache_timeout_, unsi
35703595 debug_mode = debug_mode_;
35713596 keep_cache = keep_cache_;
35723597 direntry_cache_timeout = direntry_cache_timeout_;
3598+ NegativeCache::setGlobalTimeoutMs (negative_cache_timeout_);
3599+ gNegativeCache .setTimeoutMs (NegativeCache::getGlobalTimeoutMs ());
3600+ NegativeCache::setGlobalMaxSize (negative_cache_size_);
3601+ gNegativeCache .setMaxSize (NegativeCache::getGlobalMaxSize ());
35733602 entry_cache_timeout = entry_cache_timeout_;
35743603 attr_cache_timeout = attr_cache_timeout_;
35753604 mkdir_copy_sgid = mkdir_copy_sgid_;
@@ -3606,6 +3635,8 @@ void init(int debug_mode_, int keep_cache_, double direntry_cache_timeout_, unsi
36063635 std::lock_guard lock (gMountInfoMtx );
36073636 gTweaks .registerVariable (" DirectIO" , gDirectIo , " sfsdirectio" );
36083637 gTweaks .registerVariable (" IgnoreFlush" , gIgnoreFlush , " sfsignoreflush" );
3638+ gTweaks .registerVariable (" NegativeCacheTimeout" , gNegativeCacheTimeoutMs , " sfsnegativecachetimeout" );
3639+ gTweaks .registerVariable (" NegativeCacheMaxSize" , gNegativeCacheMaxSize , " sfsnegativecachesize" );
36093640 gTweaks .registerVariable (" StatfsCacheTimeout" , gStatfsCacheTimeout , " statfscachetimeout" );
36103641 gTweaks .registerVariable (" UseQuotaInVolumeSize" , gUseQuotaInVolumeSize , " usequotainvolumesize" );
36113642#ifdef _WIN32
@@ -3695,6 +3726,7 @@ void fs_init(FsInitParams ¶ms) {
36953726 );
36963727
36973728 init (params.debug_mode , params.keep_cache , params.direntry_cache_timeout , params.direntry_cache_size ,
3729+ params.negative_cache_timeout , params.negative_cache_size ,
36983730 params.entry_cache_timeout , params.attr_cache_timeout , params.mkdir_copy_sgid ,
36993731 params.sugid_clear_mode , params.use_rw_lock ,
37003732 params.acl_cache_timeout , params.acl_cache_size , params.direct_io ,
0 commit comments