in turbonfs/src/rpc_readdir.cpp [487:558]
std::shared_ptr<struct directory_entry> readdirectory_cache::lookup(
cookie3 cookie,
const char *filename_hint,
bool acquire_lock) const
{
AZLogDebug("[{}] lookup(cookie: {}, filename_hint: {})",
dir_inode->ino, cookie, filename_hint ? filename_hint : "");
// Either cookie or filename_hint (not both) must be passed.
assert((cookie == 0) == (filename_hint != nullptr));
/*
* If acquire_lock is true, get shared lock on the map for looking up the
* entry in the map. We use a dummy_lock for minimal code changes in the
* no-lock case.
* If you call it with acquire_lock=false make sure readdircache_lock_2
* is held in shared or exclusive mode.
*/
std::shared_mutex dummy_lock;
std::shared_lock<std::shared_mutex> lock(
acquire_lock ? readdircache_lock_2 : dummy_lock);
if (filename_hint) {
cookie = filename_to_cookie(filename_hint);
if (cookie == 0) {
AZLogDebug("[{}] filename_hint: {}, not found",
dir_inode->ino, filename_hint);
return nullptr;
}
AZLogDebug("[{}] filename_hint: {}, found with cookie: {}",
dir_inode->ino, filename_hint, cookie);
}
const auto it = dir_entries.find(cookie);
const std::shared_ptr<struct directory_entry>& dirent =
(it != dir_entries.end()) ? it->second : nullptr;
if (!dirent) {
AZLogDebug("[{}] cookie: {}, not found",
dir_inode->ino, cookie);
} else {
AZLogDebug("[{}] cookie: {}, found, ino: {}",
dir_inode->ino, cookie,
dirent->nfs_inode ? dirent->nfs_inode->get_fuse_ino() : -1);
}
/*
* If filename_hint was passed it MUST match the name in the dirent.
*/
assert(!dirent || !filename_hint ||
(::strcmp(dirent->name, filename_hint) == 0));
if (dirent && dirent->nfs_inode) {
/*
* When a directory_entry is added to to readdirectory_cache we
* hold a ref on the inode, so while it's in the dir_entries map,
* dircachecnt must be non-zero.
*/
assert(dirent->nfs_inode->dircachecnt > 0);
/*
* Grab a ref on behalf of the caller so that the inode doesn't
* get freed while the directory_entry is referring to it.
* Once they are done using this directory_entry, they must drop
* this ref, mostly done in send_readdir_or_readdirplus_response().
*/
dirent->nfs_inode->dircachecnt++;
}
return dirent;
}