From 224d602294491975618b856227b84120a5e1e0fc Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Mon, 6 Aug 2012 23:26:37 +0200 Subject: [PATCH] nfs4: Add support for CB_GETATTR --- src/add-ons/kernel/file_systems/nfs4/Inode.h | 17 +++++++ .../kernel/file_systems/nfs4/InodeRegular.cpp | 2 + .../kernel/file_systems/nfs4/NFS4Defs.h | 5 +++ .../kernel/file_systems/nfs4/NFS4Server.cpp | 45 +++++++++++++++++++ .../kernel/file_systems/nfs4/NFS4Server.h | 3 ++ .../kernel/file_systems/nfs4/ReplyBuilder.cpp | 34 ++++++++++++++ .../kernel/file_systems/nfs4/ReplyBuilder.h | 2 + .../file_systems/nfs4/RequestInterpreter.cpp | 34 ++++++++++++++ .../file_systems/nfs4/RequestInterpreter.h | 1 + 9 files changed, 143 insertions(+) diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index d2bafcf5db..6dce7ba4cf 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -34,6 +34,9 @@ public: inline uint64 MaxFileSize(); + inline uint64 Change(); + inline bool Dirty(); + void SetDelegation(Delegation* delegation); void RecallDelegation(bool truncate = false); void RecallReadDelegation(); @@ -195,5 +198,19 @@ Inode::MaxFileSize() } +inline uint64 +Inode::Change() +{ + return fChange; +} + + +inline bool +Inode::Dirty() +{ + return fWriteDirty; +} + + #endif // INODE_H diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index f132762264..a4dcd76d96 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -31,6 +31,8 @@ Inode::CreateState(const char* name, int mode, int perms, OpenState* state, if (result != B_OK) return result; + RevalidateFileCache(); + FileInfo fi; fi.fFileId = fileID; fi.fHandle = handle; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index c162462178..e60b45cd1e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -26,6 +26,7 @@ enum CallbackProcedure { }; enum CallbackOpcode { + OpCallbackGetAttr = 3, OpCallbackRecall = 4 }; @@ -135,6 +136,10 @@ enum Attribute { FATTR4_MAXIMUM_ATTR_ID }; +enum CallbackAttr { + CallbackAttrSize = 1, + CallbackAttrChange = 2 +}; static inline bool sIsAttrSet(Attribute attr, const uint32* bitmap, uint32 count) diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 9dea65cc9a..07acb75e53 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -284,6 +284,9 @@ NFS4Server::ProcessCallback(RPC::CallbackRequest* request, for (uint32 i = 0; i < count; i++) { switch (req.Operation()) { + case OpCallbackGetAttr: + result = CallbackGetAttr(&req, &reply); + break; case OpCallbackRecall: result = CallbackRecall(&req, &reply); break; @@ -343,6 +346,48 @@ NFS4Server::CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply) } +status_t +NFS4Server::CallbackGetAttr(RequestInterpreter* request, ReplyBuilder* reply) +{ + FileHandle handle; + int mask; + + status_t result = request->GetAttr(&handle, &mask); + if (result != B_OK) + return result; + return B_OK; + + MutexLocker locker(fFSLock); + + Delegation* delegation = NULL; + FileSystem* current = fFileSystems; + while (current != NULL) { + delegation = current->GetDelegation(handle); + if (delegation != NULL) + break; + + current = current->fNext; + } + locker.Unlock(); + + if (delegation == NULL) { + reply->GetAttr(B_FILE_NOT_FOUND, 0, 0, 0); + return B_FILE_NOT_FOUND; + } + + struct stat st; + delegation->GetInode()->Stat(&st); + + uint64 change; + change = delegation->GetInode()->Change(); + if (delegation->GetInode()->Dirty()) + change++; + reply->GetAttr(B_OK, mask, st.st_size, change); + + return B_OK; +} + + status_t NFS4Server::RecallAll() { diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index fe159b3b74..4fe2dccb23 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -43,6 +43,9 @@ public: status_t CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply); status_t RecallAll(); + + status_t CallbackGetAttr(RequestInterpreter* request, + ReplyBuilder* reply); private: status_t _GetLeaseTime(); diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp index e18a4a64ad..152d5de25b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp @@ -56,6 +56,40 @@ ReplyBuilder::Reply() } +status_t +ReplyBuilder::GetAttr(status_t status, int mask, uint64 size, uint64 change) +{ + if (fStatus != B_OK) + return B_ERROR; + + fReply->Stream().AddUInt(OpCallbackGetAttr); + fReply->Stream().AddUInt(_HaikuErrorToNFS4(fStatus)); + fStatus = status; + + if (status == B_OK) { + uint32 bitmap = 0; + if ((mask & CallbackAttrChange) != 0) + bitmap |= 1 << FATTR4_CHANGE; + if ((mask & CallbackAttrSize) != 0) + bitmap |= 1 << FATTR4_SIZE; + fReply->Stream().AddUInt(1); + fReply->Stream().AddUInt(bitmap); + + XDR::WriteStream str; + if ((mask & CallbackAttrChange) != 0) + str.AddUHyper(change); + + if ((mask & CallbackAttrSize) != 0) + str.AddUHyper(size); + fReply->Stream().AddOpaque(str); + } + + fOpCount++; + + return B_OK; +} + + status_t ReplyBuilder::Recall(status_t status) { diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h index be85416261..2a12a0d522 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h @@ -22,6 +22,8 @@ public: RPC::CallbackReply* Reply(); + status_t GetAttr(status_t status, int mask, + uint64 size, uint64 change); status_t Recall(status_t status); private: diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp index c129cde78d..11ca0a235b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp @@ -28,6 +28,40 @@ RequestInterpreter::~RequestInterpreter() } +status_t +RequestInterpreter::GetAttr(FileHandle* handle, int* _mask) +{ + if (fLastOperation != OpCallbackGetAttr) + return B_BAD_VALUE; + + uint32 size; + const void* ptr = fRequest->Stream().GetOpaque(&size); + handle->fSize = size; + memcpy(handle->fData, ptr, size); + + uint32 count = fRequest->Stream().GetUInt(); + if (count < 1) { + *_mask = 0; + return fRequest->Stream().IsEOF() ? B_BAD_VALUE : B_OK; + } + + uint32 bitmap = fRequest->Stream().GetUInt(); + uint32 mask = 0; + + if ((bitmap & (1 << FATTR4_CHANGE)) != 0) + mask |= CallbackAttrChange; + if ((bitmap & (1 << FATTR4_SIZE)) != 0) + mask |= CallbackAttrSize; + + *_mask = mask; + + for (uint32 i = 1; i < count; i++) + fRequest->Stream().GetUInt(); + + return fRequest->Stream().IsEOF() ? B_BAD_VALUE : B_OK; +} + + status_t RequestInterpreter::Recall(FileHandle* handle, bool& truncate, uint32* stateSeq, uint32* stateID) diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h index 5febb48399..a17f2cebd7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h @@ -24,6 +24,7 @@ public: inline uint32 OperationCount(); inline uint32 Operation(); + status_t GetAttr(FileHandle* handle, int* mask); status_t Recall(FileHandle* handle, bool& truncate, uint32* stateSeq, uint32* stateID);