nfs4: Fix minor private cache issues

* Allow Inode::LookUp to handle the case in which the inode number in
  a DirectoryCache entry has no corresponding entry in the InoIdMap.
  This situation can occur after an unused node is freed (due to low
  system resources), since ~VnodeToInode will remove the node's
  InoIdMap entry.
* When a file is overwritten by a rename operation, remove the
  overwritten file's entry from the parent DirectoryCache (although a
  file with this name is still present in the directory, the old
  DirectoryCache entry is now invalid because the name is now linked
  to a different inode).
* Invalidate the cached stat info, including the number of links, in
  Inode::fMetaCache when linking to that inode.
* Make a correction to the assert added in
  https://review.haiku-os.org/c/haiku/+/9282. Entries may still be
  left in this client's InoIdMap if the file was deleted by another
  client.

Change-Id: Id437be32e51a4b324eb818b398d7facd23b7be56
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9308
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Jim906
2025-05-26 18:27:35 +00:00
committed by waddlesplash
parent 742a3c3359
commit b3ffc5acf6
2 changed files with 32 additions and 11 deletions
+26 -8
View File
@@ -212,15 +212,15 @@ Inode::LookUp(const char* name, ino_t* id)
entry = entriesList.GetNext(entry);
}
if (entry != NULL) {
// we are skipping ChildAdded(); verify that it is not needed because the InoIdMap
// already has this entry
// Verify that the InoIdMap already has an entry for this inode.
// If not, we need to get the file handle from the server and call ChildAdded().
FileInfo info;
result = fFileSystem->InoIdMap()->GetFileInfo(&info, entry->fNode);
ASSERT(result == B_OK);
*id = entry->fNode;
fCache->Unlock();
return B_OK;
if (result == B_OK) {
*id = entry->fNode;
fCache->Unlock();
return B_OK;
}
}
}
fCache->Unlock();
@@ -265,6 +265,7 @@ Inode::Link(Inode* dir, const char* name)
fFileSystem->Root()->MakeInfoInvalid();
fInfo.fNames->AddName(dir->fInfo.fNames, name);
fMetaCache.InvalidateStat();
dir->fCache->Lock();
if (dir->fCache->Valid()) {
@@ -385,7 +386,24 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName,
if (oldID != NULL)
*oldID = FileIdToInoT(oldFileID);
DirectoryCache* cache = attribute ? from->fAttrCache : from->fCache;
DirectoryCache* cache = NULL;
if (*oldID != 0) {
// If we overwrote an existing file, remove the DirectoryCache entry of
// the overwritten file, which now contains an incorrect inode value.
cache = attribute ? to->fAttrCache : to->fCache;
cache->Lock();
if (cache->Valid()) {
if (toChange.fAtomic
&& (cache->ChangeInfo() == toChange.fBefore)) {
cache->RemoveEntry(toName);
} else {
cache->Trash();
}
}
cache->Unlock();
}
cache = attribute ? from->fAttrCache : from->fCache;
cache->Lock();
if (cache->Valid()) {
if (fromChange.fAtomic && cache->ChangeInfo() == fromChange.fBefore) {
@@ -341,9 +341,12 @@ nfs4_remove_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter)
if (node == fs->Root())
return B_OK;
// Verify that all known names have been unlinked.
FileInfo fileInfo;
ASSERT(fs->InoIdMap()->GetFileInfo(&fileInfo, vti->ID()) == B_ENTRY_NOT_FOUND);
// Unless the file was deleted by someone else, verify that all known names have been
// unlinked.
if (node->IsStale() == false) {
FileInfo fileInfo;
ASSERT(fs->InoIdMap()->GetFileInfo(&fileInfo, vti->ID()) == B_ENTRY_NOT_FOUND);
}
delete vti;