From 7cac2f6e50588ad130d2770ada1b1981569a1602 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 20 Jul 2012 04:09:16 +0200 Subject: [PATCH] nfs4: Local creation of node should not invalidate the cache --- .../file_systems/nfs4/DirectoryCache.cpp | 17 +++- .../kernel/file_systems/nfs4/DirectoryCache.h | 4 +- .../kernel/file_systems/nfs4/Inode.cpp | 78 ++++++++++++++++--- .../kernel/file_systems/nfs4/InodeDir.cpp | 22 +++++- 4 files changed, 105 insertions(+), 16 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp index a3065aa286..dbb10f0c50 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp @@ -87,9 +87,9 @@ DirectoryCache::Trash() fTrashed = true; } -// TODO: separate AddEntry() for Name and Directory Cache are needed + status_t -DirectoryCache::AddEntry(const char* name, ino_t node) +DirectoryCache::AddEntry(const char* name, ino_t node, bool created) { NameCacheEntry* entry = new(std::nothrow) NameCacheEntry(name, node); if (entry == NULL) @@ -101,6 +101,19 @@ DirectoryCache::AddEntry(const char* name, ino_t node) fNameCache.Add(entry); + if (created && fDirectoryCache != NULL) { + MutexLocker _(fDirectoryCache->fLock); + NameCacheEntry* entry = new(std::nothrow) NameCacheEntry(name, node); + if (entry == NULL) + return B_NO_MEMORY; + if (entry->fName == NULL) { + delete entry; + return B_NO_MEMORY; + } + + fDirectoryCache->fEntries.Add(entry); + } + return entry_cache_add(fInode->GetFileSystem()->DevId(), fInode->ID(), name, node); } diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h index 0e9b07ba13..9e880f67ff 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h @@ -46,7 +46,8 @@ public: void ResetAndLock(); void Trash(); - status_t AddEntry(const char* name, ino_t node); + status_t AddEntry(const char* name, ino_t node, + bool created = false); void RemoveEntry(const char* name); void SetSnapshot(DirectoryCacheSnapshot* snapshot); @@ -68,7 +69,6 @@ private: SinglyLinkedList fNameCache; DirectoryCacheSnapshot* fDirectoryCache; - //mutex fDirectoryCacheLock; Inode* fInode; diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index f49a0c2f25..3d87f3662b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -281,6 +281,10 @@ Inode::Link(Inode* dir, const char* name) req.PutFH(dir->fInfo.fHandle); req.Link(name); + req.LookUp(name); + Attribute attr[] = { FATTR4_FILEID }; + req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + status_t result = request.Send(); if (result != B_OK) return result; @@ -310,10 +314,27 @@ Inode::Link(Inode* dir, const char* name) if (result != B_OK) return result; + result = reply.LookUp(); + if (result != B_OK) + return result; + + AttrValue* values; + uint32 count; + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; + + uint32 fileID; + if (count == 0) + fileID = fFileSystem->AllocFileId(); + else + fileID = values[1].fData.fValue64; + + fFileSystem->Root()->MakeInfoInvalid(); + if (fCache->Lock() == B_OK) { if (atomic && fCache->ChangeInfo() == before) { - // TODO: update cache - //fCache->AddEntry(name, ); + fCache->AddEntry(name, fileID, true); fCache->SetChangeInfo(after); } else if (fCache->ChangeInfo() != before) fCache->Trash(); @@ -418,6 +439,10 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName) req.PutFH(to->fInfo.fHandle); req.Rename(fromName, toName); + Attribute attr[] = { FATTR4_FILEID }; + req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + req.LookUp(toName); + status_t result = request.Send(); if (result != B_OK) return result; @@ -445,6 +470,26 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName) bool fromAtomic, toAtomic; result = reply.Rename(&fromBefore, &fromAfter, fromAtomic, &toBefore, &toAfter, toAtomic); + if (result != B_OK) + return result; + + result = reply.LookUp(); + if (result != B_OK) + return result; + + AttrValue* values; + uint32 count; + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; + + uint32 fileID; + if (count == 0) + fileID = from->fFileSystem->AllocFileId(); + else + fileID = values[1].fData.fValue64; + + from->fFileSystem->Root()->MakeInfoInvalid(); if (from->fCache->Lock() == B_OK) { if (fromAtomic && from->fCache->ChangeInfo() == fromBefore) { @@ -457,15 +502,14 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName) if (to->fCache->Lock() == B_OK) { if (toAtomic && to->fCache->ChangeInfo() == toBefore) { - // TODO: update cache - //fCache->AddEntry(toName, ); + to->fCache->AddEntry(toName, fileID, true); to->fCache->SetChangeInfo(toAfter); } else if (to->fCache->ChangeInfo() != toBefore) to->fCache->Trash(); to->fCache->Unlock(); - }; + } - return result; + return B_OK; } while (true); } @@ -505,6 +549,9 @@ Inode::CreateLink(const char* name, const char* path, int mode) req.Create(NF4LNK, name, cattr, i, path); + Attribute attr[] = { FATTR4_FILEID }; + req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + status_t result = request.Send(); if (result != B_OK) return result; @@ -523,20 +570,33 @@ Inode::CreateLink(const char* name, const char* path, int mode) uint64 before, after; bool atomic; result = reply.Create(&before, &after, atomic); + if (result != B_OK) + return result; + + AttrValue* values; + uint32 count; + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; + + uint32 fileID; + if (count == 0) + fileID = fFileSystem->AllocFileId(); + else + fileID = values[1].fData.fValue64; fFileSystem->Root()->MakeInfoInvalid(); if (fCache->Lock() == B_OK) { if (atomic && fCache->ChangeInfo() == before) { - // TODO: update cache - //fCache->AddEntry(name, ); + fCache->AddEntry(name, fileID, true); fCache->SetChangeInfo(after); } else if (fCache->ChangeInfo() != before) fCache->Trash(); fCache->Unlock(); } - return result; + return B_OK; } while (true); } diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index 2c84afbd69..28addc3171 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -52,6 +52,9 @@ Inode::CreateDir(const char* name, int mode) req.Create(NF4DIR, name, cattr, i); + Attribute attr[] = { FATTR4_FILEID }; + req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + status_t result = request.Send(); if (result != B_OK) return result; @@ -70,20 +73,33 @@ Inode::CreateDir(const char* name, int mode) uint64 before, after; bool atomic; result = reply.Create(&before, &after, atomic); + if (result != B_OK) + return result; + + AttrValue* values; + uint32 count; + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; + + uint32 fileID; + if (count == 0) + fileID = fFileSystem->AllocFileId(); + else + fileID = values[1].fData.fValue64; fFileSystem->Root()->MakeInfoInvalid(); if (fCache->Lock() == B_OK) { if (atomic && fCache->ChangeInfo() == before) { - // TODO: update cache - //fCache->AddEntry(name, ); + fCache->AddEntry(name, fileID, true); fCache->SetChangeInfo(after); } else if (fCache->ChangeInfo() != before) fCache->Trash(); fCache->Unlock(); } - return result; + return B_OK; } while (true); }