From 7b6f80fee2eee9724b8146cc480c0ffe87b25c32 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Thu, 19 Jul 2012 02:25:04 +0200 Subject: [PATCH] nfs4: Do not let local changes invalidate cache --- .../kernel/file_systems/nfs4/Inode.cpp | 70 +++++++++++++++++-- .../kernel/file_systems/nfs4/InodeDir.cpp | 18 ++++- .../file_systems/nfs4/ReplyInterpreter.cpp | 40 +++++------ .../file_systems/nfs4/ReplyInterpreter.h | 10 +-- 4 files changed, 107 insertions(+), 31 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index f5ba22c80f..f49a0c2f25 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -304,7 +304,23 @@ Inode::Link(Inode* dir, const char* name) reply.SaveFH(); reply.PutFH(); - return reply.Link(); + uint64 before, after; + bool atomic; + result = reply.Link(&before, &after, atomic); + if (result != B_OK) + return result; + + if (fCache->Lock() == B_OK) { + if (atomic && fCache->ChangeInfo() == before) { + // TODO: update cache + //fCache->AddEntry(name, ); + fCache->SetChangeInfo(after); + } else if (fCache->ChangeInfo() != before) + fCache->Trash(); + fCache->Unlock(); + } + + return B_OK; } while (true); } @@ -361,9 +377,19 @@ Inode::Remove(const char* name, FileType type) return result; reply.PutFH(); - result = reply.Remove(); - // remove entry + uint64 before, after; + bool atomic; + result = reply.Remove(&before, &after, atomic); + + if (fCache->Lock() == B_OK) { + if (atomic && fCache->ChangeInfo() == before) { + fCache->RemoveEntry(name); + fCache->SetChangeInfo(after); + } else if (fCache->ChangeInfo() != before) + fCache->Trash(); + fCache->Unlock(); + } fFileSystem->Root()->MakeInfoInvalid(); @@ -415,9 +441,29 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName) reply.SaveFH(); reply.PutFH(); - result = reply.Rename(); + uint64 fromBefore, fromAfter, toBefore, toAfter; + bool fromAtomic, toAtomic; + result = reply.Rename(&fromBefore, &fromAfter, fromAtomic, &toBefore, + &toAfter, toAtomic); - // remove entry + if (from->fCache->Lock() == B_OK) { + if (fromAtomic && from->fCache->ChangeInfo() == fromBefore) { + from->fCache->RemoveEntry(fromName); + from->fCache->SetChangeInfo(fromAfter); + } else if (from->fCache->ChangeInfo() != fromBefore) + from->fCache->Trash(); + from->fCache->Unlock(); + } + + if (to->fCache->Lock() == B_OK) { + if (toAtomic && to->fCache->ChangeInfo() == toBefore) { + // TODO: update cache + //fCache->AddEntry(toName, ); + to->fCache->SetChangeInfo(toAfter); + } else if (to->fCache->ChangeInfo() != toBefore) + to->fCache->Trash(); + to->fCache->Unlock(); + }; return result; } while (true); @@ -474,10 +520,22 @@ Inode::CreateLink(const char* name, const char* path, int mode) reply.PutFH(); - result = reply.Create(); + uint64 before, after; + bool atomic; + result = reply.Create(&before, &after, atomic); fFileSystem->Root()->MakeInfoInvalid(); + if (fCache->Lock() == B_OK) { + if (atomic && fCache->ChangeInfo() == before) { + // TODO: update cache + //fCache->AddEntry(name, ); + fCache->SetChangeInfo(after); + } else if (fCache->ChangeInfo() != before) + fCache->Trash(); + fCache->Unlock(); + } + return result; } 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 47d6f8766b..4671f97a31 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -67,7 +67,23 @@ Inode::CreateDir(const char* name, int mode) reply.PutFH(); - return reply.Create(); + uint64 before, after; + bool atomic; + result = reply.Create(&before, &after, atomic); + + fFileSystem->Root()->MakeInfoInvalid(); + + if (fCache->Lock() == B_OK) { + if (atomic && fCache->ChangeInfo() == before) { + // TODO: update cache + //fCache->AddEntry(name, ); + fCache->SetChangeInfo(after); + } else if (fCache->ChangeInfo() != before) + fCache->Trash(); + fCache->Unlock(); + } + + return result; } while (true); } diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index a142bac08a..eedc5afeee 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -126,15 +126,15 @@ ReplyInterpreter::Close() status_t -ReplyInterpreter::Create() +ReplyInterpreter::Create(uint64* before, uint64* after, bool& atomic) { status_t res = _OperationError(OpCreate); if (res != B_OK) return res; - fReply->Stream().GetBoolean(); - fReply->Stream().GetUHyper(); - fReply->Stream().GetUHyper(); + atomic = fReply->Stream().GetBoolean(); + *before = fReply->Stream().GetUHyper(); + *after = fReply->Stream().GetUHyper(); uint32 count = fReply->Stream().GetUInt(); for (uint32 i; i < count; i++) fReply->Stream().GetUInt(); @@ -187,15 +187,15 @@ ReplyInterpreter::GetFH(FileHandle* fh) status_t -ReplyInterpreter::Link() +ReplyInterpreter::Link(uint64* before, uint64* after, bool& atomic) { status_t res = _OperationError(OpLink); if (res != B_OK) return res; - fReply->Stream().GetBoolean(); - fReply->Stream().GetUHyper(); - fReply->Stream().GetUHyper(); + atomic = fReply->Stream().GetBoolean(); + *before = fReply->Stream().GetUHyper(); + *after = fReply->Stream().GetUHyper(); return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; } @@ -369,35 +369,35 @@ ReplyInterpreter::ReadLink(void* buffer, uint32* size, uint32 maxSize) status_t -ReplyInterpreter::Remove() +ReplyInterpreter::Remove(uint64* before, uint64* after, bool& atomic) { status_t res = _OperationError(OpRemove); if (res != B_OK) return res; - fReply->Stream().GetBoolean(); - fReply->Stream().GetUHyper(); - fReply->Stream().GetUHyper(); + atomic = fReply->Stream().GetBoolean(); + *before = fReply->Stream().GetUHyper(); + *after = fReply->Stream().GetUHyper(); return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; } status_t -ReplyInterpreter::Rename() +ReplyInterpreter::Rename(uint64* fromBefore, uint64* fromAfter, + bool& fromAtomic, uint64* toBefore, uint64* toAfter, bool& toAtomic) { status_t res = _OperationError(OpRename); if (res != B_OK) return res; - fReply->Stream().GetBoolean(); - fReply->Stream().GetUHyper(); - fReply->Stream().GetUHyper(); - - fReply->Stream().GetBoolean(); - fReply->Stream().GetUHyper(); - fReply->Stream().GetUHyper(); + fromAtomic = fReply->Stream().GetBoolean(); + *fromBefore = fReply->Stream().GetUHyper(); + *fromAfter = fReply->Stream().GetUHyper(); + toAtomic = fReply->Stream().GetBoolean(); + *toBefore = fReply->Stream().GetUHyper(); + *toAfter = fReply->Stream().GetUHyper(); return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index eedd9ea645..92739d2f95 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -69,10 +69,10 @@ public: status_t Access(uint32* supported, uint32* allowed); status_t Close(); - status_t Create(); + status_t Create(uint64* before, uint64* after, bool& atomic); status_t GetAttr(AttrValue** attrs, uint32* count); status_t GetFH(FileHandle* fh); - status_t Link(); + status_t Link(uint64* before, uint64* after, bool& atomic); status_t Lock(LockInfo* linfo); status_t LockT(uint64* pos, uint64* len, LockType* type); status_t LockU(LockInfo* linfo); @@ -87,8 +87,10 @@ public: status_t ReadDir(uint64* cookie, uint64* cookieVerf, DirEntry** dirents, uint32* count, bool* eof); status_t ReadLink(void* buffer, uint32* size, uint32 maxSize); - status_t Remove(); - status_t Rename(); + status_t Remove(uint64* before, uint64* after, bool& atomic); + status_t Rename(uint64* fromBefore, uint64* fromAfter, + bool& fromAtomic, uint64* toBefore, uint64* toAfter, + bool& toAtomic); inline status_t Renew(); inline status_t SaveFH(); status_t SetAttr();