From 060a4636e4a286dd70b9cbf335d12ddc10924937 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Thu, 16 Aug 2012 19:59:50 +0200 Subject: [PATCH] nfs4: Make the client more configurable --- .../file_systems/nfs4/CacheRevalidator.cpp | 1 + .../file_systems/nfs4/CacheRevalidator.h | 5 +- .../kernel/file_systems/nfs4/Connection.cpp | 10 +++ .../kernel/file_systems/nfs4/Connection.h | 2 + .../kernel/file_systems/nfs4/Delegation.cpp | 2 +- .../file_systems/nfs4/DirectoryCache.cpp | 12 ++- .../kernel/file_systems/nfs4/DirectoryCache.h | 2 + .../kernel/file_systems/nfs4/FileInfo.cpp | 2 +- .../kernel/file_systems/nfs4/FileSystem.cpp | 28 +++--- .../kernel/file_systems/nfs4/FileSystem.h | 24 +++++- .../kernel/file_systems/nfs4/Inode.cpp | 2 +- .../kernel/file_systems/nfs4/InodeDir.cpp | 55 +++++++----- .../file_systems/nfs4/MetadataCache.cpp | 8 +- .../kernel/file_systems/nfs4/NFS4Inode.cpp | 42 ++++----- .../kernel/file_systems/nfs4/NFS4Object.cpp | 3 +- .../kernel/file_systems/nfs4/NFS4Object.h | 10 +++ .../kernel/file_systems/nfs4/NFS4Server.cpp | 6 +- .../kernel/file_systems/nfs4/OpenState.cpp | 8 +- .../kernel/file_systems/nfs4/Request.cpp | 24 +++++- .../kernel/file_systems/nfs4/Request.h | 12 +-- .../kernel/file_systems/nfs4/RootInode.cpp | 18 ++-- .../file_systems/nfs4/kernel_interface.cpp | 86 ++++++++++++++----- 22 files changed, 251 insertions(+), 111 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.cpp b/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.cpp index 749d6f8d57..d1abbbf4e6 100644 --- a/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.cpp @@ -105,6 +105,7 @@ CacheRevalidator::_DirectoryCacheRevalidator() } fDirectoryCaches.RemoveHead(); + current->fRevalidated = false; if (current->Revalidate() == B_OK) AddDirectory(current); diff --git a/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.h b/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.h index b3bfed9541..7e1e4a7862 100644 --- a/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.h +++ b/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.h @@ -58,6 +58,7 @@ CacheRevalidator::Unlock() inline void CacheRevalidator::AddDirectory(DirectoryCache* cache) { + cache->fRevalidated = true; fDirectoryCaches.InsertAfter(fDirectoryCaches.Tail(), cache); } @@ -65,7 +66,9 @@ CacheRevalidator::AddDirectory(DirectoryCache* cache) inline void CacheRevalidator::RemoveDirectory(DirectoryCache* cache) { - fDirectoryCaches.Remove(cache); + if (cache->fRevalidated == true) + fDirectoryCaches.Remove(cache); + cache->fRevalidated = false; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp index 22f08f27e1..d94801b2b0 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp @@ -77,6 +77,16 @@ PeerAddress::ProtocolString() const } +void +PeerAddress::SetProtocol(const char* protocol) +{ + if (strcmp(protocol, "tcp") == 0) + fProtocol = IPPROTO_TCP; + else if (strcmp(protocol, "udp") == 0) + fProtocol = IPPROTO_UDP; +} + + char* PeerAddress::UniversalAddress() const { diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.h b/src/add-ons/kernel/file_systems/nfs4/Connection.h index b10cc9c2d7..aceb2c0742 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.h +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.h @@ -27,6 +27,8 @@ struct PeerAddress { PeerAddress(); const char* ProtocolString() const; + void SetProtocol(const char* protocol); + char* UniversalAddress() const; socklen_t AddressSize() const; diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp index a0ce499edb..bf2b33a11f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp @@ -41,7 +41,7 @@ Delegation::ReturnDelegation() { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp index b9483a0c07..52be9fddff 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp @@ -49,6 +49,7 @@ DirectoryCacheSnapshot::~DirectoryCacheSnapshot() DirectoryCache::DirectoryCache(Inode* inode, bool attr) : + fRevalidated(false), fDirectoryCache(NULL), fInode(inode), fAttrDir(attr), @@ -60,6 +61,10 @@ DirectoryCache::DirectoryCache(Inode* inode, bool attr) DirectoryCache::~DirectoryCache() { + fInode->GetFileSystem()->Revalidator().Lock(); + fInode->GetFileSystem()->Revalidator().RemoveDirectory(this); + fInode->GetFileSystem()->Revalidator().Unlock(); + mutex_destroy(&fLock); } @@ -179,7 +184,12 @@ status_t DirectoryCache::Revalidate() { uint64 change; - if (fInode->GetChangeInfo(&change, true) == B_OK && change == fChange) { + if (fInode->GetChangeInfo(&change, true) != B_OK) { + Trash(); + return B_ERROR; + } + + if (change == fChange) { fExpireTime = system_time() + kExpirationTime; return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h index ac152f0158..4099950833 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h @@ -65,6 +65,8 @@ public: inline time_t ExpireTime(); static const bigtime_t kExpirationTime = 15000000; + + bool fRevalidated; protected: void NotifyChanges(DirectoryCacheSnapshot* oldSnapshot, DirectoryCacheSnapshot* newSnapshot); diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp index 402c642356..e81242e526 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp @@ -49,7 +49,7 @@ FileInfo::ParsePath(RequestBuilder& req, uint32& count, const char* _path) status_t FileInfo::UpdateFileHandles(FileSystem* fs) { - Request request(fs->Server()); + Request request(fs->Server(), fs); RequestBuilder& req = request.Builder(); req.PutRootFH(); diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp index 46bd002dc8..4c8963aa9e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp @@ -11,6 +11,7 @@ #include +#include #include #include "Request.h" @@ -21,7 +22,7 @@ extern RPC::ServerManager* gRPCServerManager; extern RPC::ProgramData* CreateNFS4Server(RPC::Server* serv); -FileSystem::FileSystem() +FileSystem::FileSystem(const MountConfiguration& configuration) : fNext(NULL), fPrev(NULL), @@ -30,7 +31,8 @@ FileSystem::FileSystem() fNamedAttrs(true), fPath(NULL), fRoot(NULL), - fId(1) + fId(1), + fConfiguration(configuration) { fOpenOwner = rand(); fOpenOwner <<= 32; @@ -73,9 +75,14 @@ sGetPath(const char* root, const char* path) status_t FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, const char* fsPath, - dev_t id) + dev_t id, const MountConfiguration& configuration) { - Request request(serv); + FileSystem* fs = new(std::nothrow) FileSystem(configuration); + if (fs == NULL) + return B_NO_MEMORY; + ObjectDeleter fsDeleter(fs); + + Request request(serv, fs); RequestBuilder& req = request.Builder(); req.PutRootFH(); @@ -120,10 +127,6 @@ FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, const char* fsPath, if (result != B_OK || count < 2) return result; - FileSystem* fs = new(std::nothrow) FileSystem; - if (fs == NULL) - return B_NO_MEMORY; - // FATTR4_SUPPORTED_ATTRS is mandatory memcpy(fs->fSupAttrs, &values[0].fData.fValue64, sizeof(fs->fSupAttrs)); @@ -163,23 +166,20 @@ FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, const char* fsPath, delete[] values; - if (fi.fName == NULL || fi.fPath == NULL) { - delete fs; + if (fi.fName == NULL || fi.fPath == NULL) return B_NO_MEMORY; - } Inode* inode; result = Inode::CreateInode(fs, fi, &inode); - if (result != B_OK) { - delete fs; + if (result != B_OK) return result; - } fs->fRoot = reinterpret_cast(inode); fs->NFSServer()->AddFileSystem(fs); *pfs = fs; + fsDeleter.Detach(); return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h index 3a2dfaceea..e7884fed41 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -19,10 +19,19 @@ class Inode; class RootInode; +struct MountConfiguration { + bool fHard; + int fRetryLimit; + + bool fEmulateNamedAttrs; + bool fCacheMetadata; +}; + class FileSystem { public: static status_t Mount(FileSystem** pfs, RPC::Server* serv, - const char* path, dev_t id); + const char* path, dev_t id, + const MountConfiguration& configuration); ~FileSystem(); status_t GetInode(ino_t id, Inode** inode); @@ -65,10 +74,12 @@ public: inline bool NamedAttrs(); inline void SetNamedAttrs(bool attrs); + inline const MountConfiguration& GetConfiguration(); + FileSystem* fNext; FileSystem* fPrev; private: - FileSystem(); + FileSystem(const MountConfiguration& config); CacheRevalidator fCacheRevalidator; @@ -99,6 +110,8 @@ private: dev_t fDevId; InodeIdMap fInoIdMap; + + MountConfiguration fConfiguration; }; @@ -223,5 +236,12 @@ FileSystem::SetNamedAttrs(bool attrs) } +inline const MountConfiguration& +FileSystem::GetConfiguration() +{ + return fConfiguration; +} + + #endif // FILESYSTEM_H diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 02ea63e224..c8cfd2c808 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -55,7 +55,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode) uint64 size; do { RPC::Server* serv = fs->Server(); - Request request(serv); + Request request(serv, fs); RequestBuilder& req = request.Builder(); req.PutFH(inode->fInfo.fHandle); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index 33e782251c..65f735aa79 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -67,32 +67,43 @@ Inode::LoadAttrDirHandle() FileHandle handle; status_t result; - if (!fFileSystem->NamedAttrs()) { - char* attrDir - = reinterpret_cast(malloc(strlen(fInfo.fName) + 32)); - if (attrDir == NULL) - return B_NO_MEMORY; - strcpy(attrDir, "."); - strcat(attrDir, fInfo.fName); - strcat(attrDir, "-haiku-attrs"); - result = NFS4Inode::LookUp(attrDir, NULL, NULL, &handle, true); - if (result == B_ENTRY_NOT_FOUND) { - ChangeInfo change; - struct stat st; - Stat(&st); - st.st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; - result = NFS4Inode::CreateObject(attrDir, NULL, st.st_mode, NF4DIR, - &change, NULL, &handle, true); + if (fFileSystem->NamedAttrs()) { + result = NFS4Inode::OpenAttrDir(&handle); + if (result == B_OK) { + fInfo.fAttrDir = handle; + return B_OK; } - free(attrDir); - } else { - result = NFS4Inode::OpenAttrDir(&handle); - if (result == B_UNSUPPORTED) - fFileSystem->SetNamedAttrs(false); + if (result != B_UNSUPPORTED) + return result; + + fFileSystem->SetNamedAttrs(false); } + if (!fFileSystem->GetConfiguration().fEmulateNamedAttrs) + return B_UNSUPPORTED; + + char* attrDir + = reinterpret_cast(malloc(strlen(fInfo.fName) + 32)); + if (attrDir == NULL) + return B_NO_MEMORY; + strcpy(attrDir, "."); + strcat(attrDir, fInfo.fName); + strcat(attrDir, "-haiku-attrs"); + + result = NFS4Inode::LookUp(attrDir, NULL, NULL, &handle, true); + if (result == B_ENTRY_NOT_FOUND) { + ChangeInfo change; + struct stat st; + Stat(&st); + st.st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + result = NFS4Inode::CreateObject(attrDir, NULL, st.st_mode, NF4DIR, + &change, NULL, &handle, true); + } + + free(attrDir); + if (result != B_OK) return result; @@ -128,7 +139,7 @@ Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); diff --git a/src/add-ons/kernel/file_systems/nfs4/MetadataCache.cpp b/src/add-ons/kernel/file_systems/nfs4/MetadataCache.cpp index 3c0f9b6008..bc345a9401 100644 --- a/src/add-ons/kernel/file_systems/nfs4/MetadataCache.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/MetadataCache.cpp @@ -35,7 +35,8 @@ status_t MetadataCache::GetStat(struct stat* st) { MutexLocker _(fLock); - if (fForceValid || fExpire > time(NULL)) { + bool cache = fInode->GetFileSystem()->GetConfiguration().fCacheMetadata; + if (fForceValid || (cache && fExpire > time(NULL))) { // Do not touch other members of struct stat st->st_size = fStatCache.st_size; st->st_mode = fStatCache.st_mode; @@ -110,7 +111,10 @@ MetadataCache::SetAccess(uid_t uid, uint32 allowed) entry.fAllowed = allowed; entry.fExpire = time(NULL) + kExpirationTime; entry.fForceValid = fForceValid; - fAccessCache.Insert(uid, entry); + + bool cache = fInode->GetFileSystem()->GetConfiguration().fCacheMetadata; + if (fForceValid || cache) + fAccessCache.Insert(uid, entry); } diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 81e6280867..43ae3fe060 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -18,7 +18,7 @@ NFS4Inode::GetChangeInfo(uint64* change, bool attrDir) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); if (attrDir) @@ -60,7 +60,7 @@ NFS4Inode::CommitWrites() { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -86,7 +86,7 @@ NFS4Inode::Access(uint32* allowed) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -114,7 +114,7 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); if (parent) @@ -199,7 +199,7 @@ NFS4Inode::Link(Inode* dir, const char* name, ChangeInfo* changeInfo) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -231,7 +231,7 @@ NFS4Inode::ReadLink(void* buffer, size_t* length) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -262,7 +262,7 @@ NFS4Inode::GetStat(AttrValue** values, uint32* count, OpenAttrCookie* cookie) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); if (cookie != NULL) @@ -297,7 +297,7 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, uint32 attrCount) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); if (state != NULL) { @@ -335,7 +335,7 @@ NFS4Inode::Rename(Inode* from, Inode* to, const char* fromName, { do { RPC::Server* serv = from->fFileSystem->Server(); - Request request(serv); + Request request(serv, from->fFileSystem); RequestBuilder& req = request.Builder(); if (attribute) @@ -421,7 +421,7 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, OpenState* state, state->fClientID = fFileSystem->NFSServer()->ClientId(); RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -512,7 +512,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) state->fClientID = fFileSystem->NFSServer()->ClientId(); RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); // Since we are opening the file using a pair (parentFH, name) we @@ -613,7 +613,7 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, int mode, state->fClientID = fFileSystem->NFSServer()->ClientId(); RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fAttrDir); @@ -665,7 +665,7 @@ NFS4Inode::ReadFile(OpenStateCookie* cookie, OpenState* state, uint64 position, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(state->fInfo.fHandle); @@ -697,7 +697,7 @@ NFS4Inode::WriteFile(OpenStateCookie* cookie, OpenState* state, uint64 position, do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(state->fInfo.fHandle); @@ -732,7 +732,7 @@ NFS4Inode::CreateObject(const char* name, const char* path, int mode, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); if (parent) @@ -810,7 +810,7 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -888,7 +888,7 @@ NFS4Inode::ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); if (attribute) @@ -958,7 +958,7 @@ NFS4Inode::OpenAttrDir(FileHandle* handle) { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -990,7 +990,7 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* type, uint64* position, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -1027,7 +1027,7 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait) MutexLocker ownerLocker(lockInfo->fOwner->fLock); RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -1073,7 +1073,7 @@ NFS4Inode::ReleaseLock(OpenFileCookie* cookie, LockInfo* lockInfo) MutexLocker ownerLocker(lockInfo->fOwner->fLock); RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index 0e089acd2f..e24abcecd0 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -111,6 +111,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, return false; // FileHandle has expired or is invalid + case NFS4ERR_NOFILEHANDLE: case NFS4ERR_BADHANDLE: case NFS4ERR_FHEXPIRED: if (fInfo.UpdateFileHandles(fFileSystem) == B_OK) @@ -143,7 +144,7 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state, { do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h index 8cb927f118..d0ac9cb83a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h @@ -27,10 +27,20 @@ public: static uint32 IncrementSequence(uint32 error); + inline NFS4Object(); + FileInfo fInfo; FileSystem* fFileSystem; }; +inline +NFS4Object::NFS4Object() + : + fFileSystem(NULL) +{ +} + + #endif // NFS4OBJECT_H diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 1b09e633a7..8a39021bd8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -112,7 +112,7 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew) if ((fUseCount == 0 && fClientIdLastUse + (time_t)LeaseTime() < time(NULL)) || (forceNew && fClientId == prevId)) { - Request request(fServer); + Request request(fServer, NULL); request.Builder().SetClientID(fServer); status_t result = request.Send(); @@ -159,7 +159,7 @@ NFS4Server::FileSystemMigrated() status_t NFS4Server::_GetLeaseTime() { - Request request(fServer); + Request request(fServer, NULL); request.Builder().PutRootFH(); Attribute attr[] = { FATTR4_LEASE_TIME }; request.Builder().GetAttr(attr, sizeof(attr) / sizeof(Attribute)); @@ -246,7 +246,7 @@ NFS4Server::_Renewal() } } - Request request(fServer); + Request request(fServer, NULL); request.Builder().Renew(fClientId); request.Send(); diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp index 7de9b42d04..1655c79170 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp @@ -114,7 +114,7 @@ OpenState::_ReleaseLockOwner(LockOwner* owner) { do { RPC::Server* server = fFileSystem->Server(); - Request request(server); + Request request(server, fFileSystem); RequestBuilder& req = request.Builder(); req.ReleaseLockOwner(this, owner); @@ -166,7 +166,7 @@ OpenState::_ReclaimOpen(uint64 newClientID) : OPEN_DELEGATE_NONE; do { RPC::Server* server = fFileSystem->Server(); - Request request(server); + Request request(server, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -231,7 +231,7 @@ OpenState::_ReclaimLocks(uint64 newClientID) do { RPC::Server* server = fFileSystem->Server(); - Request request(server); + Request request(server, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -272,7 +272,7 @@ OpenState::Close() uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + Request request(serv, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); diff --git a/src/add-ons/kernel/file_systems/nfs4/Request.cpp b/src/add-ons/kernel/file_systems/nfs4/Request.cpp index 5262341889..d68d5b2176 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Request.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Request.cpp @@ -7,9 +7,11 @@ */ -#include "Inode.h" #include "Request.h" +#include "FileSystem.h" +#include "Inode.h" + status_t Request::Send(Cookie* cookie) @@ -36,10 +38,17 @@ Request::_SendUDP(Cookie* cookie) if (cookie != NULL) cookie->RegisterRequest(rpc); + int retryLimit = 0; + bool hard = true; + if (fFileSystem != NULL) { + retryLimit = fFileSystem->GetConfiguration().fRetryLimit; + hard = fFileSystem->GetConfiguration().fHard; + } + result = fServer->WaitCall(rpc); if (result != B_OK) { int attempts = 1; - while (result != B_OK && attempts++ < kRetryLimit) { + while (result != B_OK && (hard || attempts++ < retryLimit)) { result = fServer->ResendCallAsync(fBuilder.Request(), rpc); if (result != B_OK) { if (cookie != NULL) @@ -83,6 +92,15 @@ Request::_SendTCP(Cookie* cookie) status_t result; int attempts = 0; + + int retryLimit = 0; + bool hard = true; + + if (fFileSystem != NULL) { + retryLimit = fFileSystem->GetConfiguration().fRetryLimit; + hard = fFileSystem->GetConfiguration().fHard; + } + do { result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc); if (result == B_NO_MEMORY) @@ -105,7 +123,7 @@ Request::_SendTCP(Cookie* cookie) fServer->Repair(); } - } while (result != B_OK && attempts++ < kRetryLimit); + } while (result != B_OK && (hard || attempts++ < retryLimit)); if (cookie != NULL) cookie->UnregisterRequest(rpc); diff --git a/src/add-ons/kernel/file_systems/nfs4/Request.h b/src/add-ons/kernel/file_systems/nfs4/Request.h index cb8e5e02f4..2c0d014708 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Request.h +++ b/src/add-ons/kernel/file_systems/nfs4/Request.h @@ -15,10 +15,12 @@ class Cookie; +class FileSystem; class Request { public: - inline Request(RPC::Server* serv); + inline Request(RPC::Server* server, + FileSystem* fileSystem); inline RequestBuilder& Builder(); inline ReplyInterpreter& Reply(); @@ -31,18 +33,18 @@ private: status_t _SendTCP(Cookie* cookie); RPC::Server* fServer; + FileSystem* fFileSystem; RequestBuilder fBuilder; ReplyInterpreter fReply; - - static const int kRetryLimit = 5; }; inline -Request::Request(RPC::Server* serv) +Request::Request(RPC::Server* server, FileSystem* fileSystem) : - fServer(serv) + fServer(server), + fFileSystem(fileSystem) { } diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp index 1369d2fe2d..0275f67f01 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp @@ -55,8 +55,8 @@ RootInode::_UpdateInfo(bool force) return B_OK; do { - RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + RPC::Server* server = fFileSystem->Server(); + Request request(server, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -71,7 +71,7 @@ RootInode::_UpdateInfo(bool force) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), server)) continue; reply.PutFH(); @@ -137,8 +137,8 @@ bool RootInode::ProbeMigration() { do { - RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + RPC::Server* server = fFileSystem->Server(); + Request request(server, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -153,7 +153,7 @@ RootInode::ProbeMigration() if (reply.NFS4Error() == NFS4ERR_MOVED) return true; - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), server)) continue; return false; @@ -166,8 +166,8 @@ status_t RootInode::GetLocations(AttrValue** attrv) { do { - RPC::Server* serv = fFileSystem->Server(); - Request request(serv); + RPC::Server* server = fFileSystem->Server(); + Request request(server, fFileSystem); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); @@ -180,7 +180,7 @@ RootInode::GetLocations(AttrValue** attrv) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), server)) continue; reply.PutFH(); diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index f40cc40f2e..a675138ce9 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -9,6 +9,7 @@ #include +#include #include #include @@ -28,9 +29,6 @@ extern fs_volume_ops gNFSv4VolumeOps; extern fs_vnode_ops gNFSv4VnodeOps; -extern "C" void -dprintf(const char* format, ...); - RPC::ServerManager* gRPCServerManager; @@ -42,30 +40,80 @@ CreateNFS4Server(RPC::Server* serv) } - -// TODO: IPv6 address will cause problems +// Format: ip{4,6}_address:path options +// Available options: +// hard - retry requests until success +// soft - retry requests no more than retrans times (default) +// retrans=X - retry requests X times (default: 5) +// ac - use metadata cache (default) +// noac - do not use metadata cache +// xattr-emu - emulate named attributes +// noxattr-emu - do not emulate named attributes (default) +// port=X - connect to port X (default: 2049) +// proto=X - user transport protocol X (default: tcp) static status_t -ParseArguments(const char* _args, PeerAddress* address, char* _path) +ParseArguments(const char* _args, PeerAddress* address, char** _path, + MountConfiguration* conf) { if (_args == NULL) return B_BAD_VALUE; char* args = strdup(_args); - char* path = strpbrk(args, ":"); - if (path == NULL) { - free(args); + if (args == NULL) + return B_NO_MEMORY; + MemoryDeleter argsDeleter(args); + + char* options = strchr(args, ' '); + if (options != NULL) + *options++ = '\0'; + + char* path = strrchr(args, ':'); + if (path == NULL) return B_MISMATCHED_VALUES; - } *path++ = '\0'; status_t result = PeerAddress::ResolveName(args, address); if (result != B_OK) return result; - _path[255] = '\0'; - strncpy(_path, path, 255); + *_path = strdup(path); + if (*_path == NULL) + return B_NO_MEMORY; + + conf->fHard = false; + conf->fRetryLimit = 5; + conf->fEmulateNamedAttrs = false; + conf->fCacheMetadata = true; + + char* optionsEnd; + if (options != NULL) + optionsEnd = strchr(options, ' '); + while (options != NULL && *options != '\0') { + if (optionsEnd != NULL) + *optionsEnd++ = '\0'; + + if (strcmp(options, "hard") == 0) + conf->fHard = true; + else if (strncmp(options, "retrans=", 8) == 0) { + options += strlen("retrans="); + conf->fRetryLimit = atoi(options); + } else if (strcmp(options, "noac") == 0) + conf->fCacheMetadata = false; + else if (strcmp(options, "xattr-emu") == 0) + conf->fEmulateNamedAttrs = true; + else if (strncmp(options, "port=", 5) == 0) { + options += strlen("port="); + address->SetPort(atoi(options)); + } else if (strncmp(options, "proto=", 6) == 0) { + options += strlen("proto="); + address->SetProtocol(options); + } + + options = optionsEnd; + if (options != NULL) + optionsEnd = strchr(options, ' '); + } - free(args); return B_OK; } @@ -83,10 +131,12 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags, locker.Unlock(); PeerAddress address; - char path[256]; - result = ParseArguments(args, &address, path); + MountConfiguration config; + char *path; + result = ParseArguments(args, &address, &path, &config); if (result != B_OK) return result; + MemoryDeleter pathDeleter(path); RPC::Server *server; result = gRPCServerManager->Acquire(&server, address, CreateNFS4Server); @@ -94,7 +144,7 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags, return result; FileSystem* fs; - result = FileSystem::Mount(&fs, server, path, volume->id); + result = FileSystem::Mount(&fs, server, path, volume->id, config); if (result != B_OK) { gRPCServerManager->Release(server); return result; @@ -824,8 +874,6 @@ nfs4_release_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie, status_t nfs4_init() { - dprintf("NFS4 Init\n"); - gRPCServerManager = new(std::nothrow) RPC::ServerManager; if (gRPCServerManager == NULL) return B_NO_MEMORY; @@ -856,8 +904,6 @@ nfs4_init() status_t nfs4_uninit() { - dprintf("NFS4 Uninit\n"); - delete gRPCCallbackServer; delete gIdMapper; delete gWorkQueue;