[haiku-commits] BRANCH pdziepak-github.nfs4 - src/add-ons/kernel/file_systems/nfs4

  • From: pdziepak-github.nfs4 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 16 Aug 2012 21:49:35 +0200 (CEST)

added 2 changesets to branch 'refs/remotes/pdziepak-github/nfs4'
old head: 870528b79923b065c9d04bc598b43a518f3cfafa
new head: e8c12d9410d16c9a504198755b85c385e7ab667a

----------------------------------------------------------------------------

060a463: nfs4: Make the client more configurable

e8c12d9: nfs4: Fix file handle recovery

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

25 files changed, 361 insertions(+), 168 deletions(-)
.../kernel/file_systems/nfs4/CacheRevalidator.cpp  |    1 +
.../kernel/file_systems/nfs4/CacheRevalidator.h    |    5 +-
.../kernel/file_systems/nfs4/Connection.cpp        |   10 ++
src/add-ons/kernel/file_systems/nfs4/Connection.h  |    2 +
.../kernel/file_systems/nfs4/Delegation.cpp        |    2 +-
.../kernel/file_systems/nfs4/DirectoryCache.cpp    |   48 ++++++---
.../kernel/file_systems/nfs4/DirectoryCache.h      |    2 +
src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp  |    4 +-
.../kernel/file_systems/nfs4/FileSystem.cpp        |   60 ++++++-----
src/add-ons/kernel/file_systems/nfs4/FileSystem.h  |   24 ++++-
src/add-ons/kernel/file_systems/nfs4/Inode.cpp     |   54 ++++++----
src/add-ons/kernel/file_systems/nfs4/Inode.h       |   11 +-
src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp  |   57 +++++-----
src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h  |    7 +-
.../kernel/file_systems/nfs4/MetadataCache.cpp     |    8 +-
src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp |   42 ++++----
.../kernel/file_systems/nfs4/NFS4Object.cpp        |    3 +-
src/add-ons/kernel/file_systems/nfs4/NFS4Object.h  |   10 ++
.../kernel/file_systems/nfs4/NFS4Server.cpp        |    6 +-
src/add-ons/kernel/file_systems/nfs4/OpenState.cpp |    8 +-
src/add-ons/kernel/file_systems/nfs4/Request.cpp   |   24 ++++-
src/add-ons/kernel/file_systems/nfs4/Request.h     |   12 ++-
src/add-ons/kernel/file_systems/nfs4/RootInode.cpp |   30 ++++--
src/add-ons/kernel/file_systems/nfs4/RootInode.h   |   13 +++
.../kernel/file_systems/nfs4/kernel_interface.cpp  |   86 ++++++++++++----

############################################################################

Commit:      060a4636e4a286dd70b9cbf335d12ddc10924937

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Aug 16 17:59:50 2012 UTC

nfs4: Make the client more configurable

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.cpp 
b/src/add-ons/kernel/file_systems/nfs4/CacheRevalidator.cpp
index 749d6f8..d1abbbf 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 b3bfed9..7e1e4a7 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 22f08f2..d94801b 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 b10cc9c..aceb2c0 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 a0ce499..bf2b33a 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 b9483a0..52be9fd 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 ac152f0..4099950 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 402c642..e81242e 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 46bd002..4c8963a 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 <string.h>
 
+#include <AutoDeleter.h>
 #include <lock.h>
 
 #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<FileSystem> 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<RootInode*>(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 3a2dfac..e7884fe 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 02ea63e..c8cfd2c 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 33e7822..65f735a 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<char*>(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);
-       } else {
+       if (fFileSystem->NamedAttrs()) {
                result = NFS4Inode::OpenAttrDir(&handle);
-               if (result == B_UNSUPPORTED)
-                       fFileSystem->SetNamedAttrs(false);
+               if (result == B_OK) {
+                       fInfo.fAttrDir = handle;
+                       return B_OK;
+               }
+
+               if (result != B_UNSUPPORTED)
+                       return result;
+
+               fFileSystem->SetNamedAttrs(false);
        }
 
+       if (!fFileSystem->GetConfiguration().fEmulateNamedAttrs)
+               return B_UNSUPPORTED;
+
+       char* attrDir
+               = reinterpret_cast<char*>(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 3c0f9b6..bc345a9 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 81e6280..43ae3fe 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 0e089ac..e24abce 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 8cb927f..d0ac9cb 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 1b09e63..8a39021 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 7de9b42..1655c79 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 5262341..d68d5b2 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 cb8e5e0..2c0d014 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 1369d2f..0275f67 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 f40cc40..a675138 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 <stdio.h>
 
+#include <AutoDeleter.h>
 #include <fs_cache.h>
 #include <fs_interface.h>
 
@@ -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;

############################################################################

Commit:      e8c12d9410d16c9a504198755b85c385e7ab667a

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Aug 16 19:11:56 2012 UTC

nfs4: Fix file handle recovery

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp 
b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp
index 52be9fd..370a337 100644
--- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp
@@ -184,7 +184,7 @@ status_t
 DirectoryCache::Revalidate()
 {
        uint64 change;
-       if (fInode->GetChangeInfo(&change, true) != B_OK) {
+       if (fInode->GetChangeInfo(&change, fAttrDir) != B_OK) {
                Trash();
                return B_ERROR;
        }
@@ -263,24 +263,34 @@ DirectoryCache::NotifyChanges(DirectoryCacheSnapshot* 
oldSnapshot,
                                
notify_entry_created(fInode->GetFileSystem()->DevId(),
                                        fInode->ID(), newCurrent->fName, 
newCurrent->fNode);
 
-                               FileInfo fi;
-                               fi.fFileId = newCurrent->fNode;
-                               fi.fParent = fInode->fInfo.fHandle;
-                               fi.fName = strdup(newCurrent->fName);
-                               if (fi.fName != NULL) {
-                                       size_t pathLength = 
strlen(newCurrent->fName) + 2 +
-                                               strlen(fInode->fInfo.fPath);
-                                       char* path = 
reinterpret_cast<char*>(malloc(pathLength));
-                                       if (path != NULL) {
+                               do {
+                                       FileInfo fi;
+                                       fi.fFileId = newCurrent->fNode;
+                                       fi.fParent = fInode->fInfo.fHandle;
+                                       fi.fName = strdup(newCurrent->fName);
+                                       if (fi.fName == NULL)
+                                               break;
+
+                                       if (fInode->fInfo.fPath != NULL) {
+                                               size_t pathLength = 
strlen(newCurrent->fName) + 2 +
+                                                       
strlen(fInode->fInfo.fPath);
+                                               char* path = 
reinterpret_cast<char*>(pathLength);
+                                               if (path == NULL)
+                                                       break;
+
                                                strcpy(path, 
fInode->fInfo.fPath);
                                                strcat(path, "/");
                                                strcat(path, newCurrent->fName);
                                                fi.fPath = path;
-
-                                               
fInode->GetFileSystem()->InoIdMap()->AddEntry(fi,
-                                                       
Inode::FileIdToInoT(newCurrent->fNode));
+                                       } else {
+                                               fi.fPath = 
strdup(newCurrent->fName);
+                                               if (fi.fPath == NULL)
+                                                       break;
                                        }
-                               }
+
+                                       
fInode->GetFileSystem()->InoIdMap()->AddEntry(fi,
+                                               
Inode::FileIdToInoT(newCurrent->fNode), true);
+                               } while (false);
                        }
                } else
                        oldSnapshot->fEntries.Remove(prev, oldCurrent);
diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp 
b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp
index e81242e..9ff0e49 100644
--- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp
@@ -56,7 +56,7 @@ FileInfo::UpdateFileHandles(FileSystem* fs)
 
        uint32 lookupCount = 0;
        status_t result;
-
+dprintf("%s %s\n", fs->Path(), fPath);
        result = ParsePath(req, lookupCount, fs->Path());
        if (result != B_OK)
                return result;
diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp 
b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp
index 4c8963a..ec5d992 100644
--- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp
@@ -58,10 +58,11 @@ FileSystem::~FileSystem()
 
 
 static const char*
-sGetPath(const char* root, const char* path)
+GetPath(const char* root, const char* path)
 {
        int slash = 0;
-       for (int i = 0; path[i] != '\0'; i++) {
+       int i;
+       for (i = 0; path[i] != '\0'; i++) {
                if (path[i] != root[i] || root[i] == '\0')
                        break;
 
@@ -69,6 +70,9 @@ sGetPath(const char* root, const char* path)
                        slash = i;
        }
 
+       if (path[i] == '\0')
+               return NULL;
+
        return path + slash;
 }
 
@@ -149,12 +153,6 @@ FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, 
const char* fsPath,
        const char* name;
        if (fsPath != NULL && fsPath[0] == '/')
                fsPath++;
-       name = strrchr(fsPath, '/');
-       if (name != NULL) {
-               name++;
-               fi.fName = strdup(name);
-       } else
-               fi.fName = strdup(fsPath);
 
        fs->fServer = serv;
        fs->fDevId = id;
@@ -162,18 +160,30 @@ FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, 
const char* fsPath,
 
        fi.fHandle = fh;
        fi.fParent = fh;
-       fi.fPath = strdup(sGetPath(fs->fPath, fsPath));
+       fi.fPath = strdup(GetPath(fs->fPath, fsPath));
 
-       delete[] values;
+       if (fi.fPath != NULL) {
+               name = strrchr(fi.fPath, '/');
+               if (name != NULL) {
+                       name++;
+                       fi.fName = strdup(name);
+               }
+       }
 
-       if (fi.fName == NULL || fi.fPath == NULL)
-               return B_NO_MEMORY;
+       delete[] values;
 
        Inode* inode;
        result = Inode::CreateInode(fs, fi, &inode);
        if (result != B_OK)
                return result;
 
+       name = strrchr(fsPath, '/');
+       if (name != NULL) {
+               name++;
+               reinterpret_cast<RootInode*>(inode)->SetName(name);
+       } else
+               reinterpret_cast<RootInode*>(inode)->SetName(fsPath);
+
        fs->fRoot = reinterpret_cast<RootInode*>(inode);
 
        fs->NFSServer()->AddFileSystem(fs);
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index c8cfd2c..a98ca4c 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -230,16 +230,21 @@ Inode::Link(Inode* dir, const char* name)
        if (fi.fName == NULL)
                return B_NO_MEMORY;
 
-       char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 +
-               strlen(fInfo.fPath)));
-       if (path == NULL)
-               return B_NO_MEMORY;
-
-       strcpy(path, dir->fInfo.fPath);
-       strcat(path, "/");
-       strcat(path, name);
-       free(const_cast<char*>(fi.fPath));
-       fi.fPath = path;
+       if (fInfo.fPath != NULL) {
+               char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 +
+                       strlen(fInfo.fPath)));
+               if (path == NULL)
+                       return B_NO_MEMORY;
+
+               strcpy(path, fInfo.fPath);
+               strcat(path, "/");
+               strcat(path, name);
+               fi.fPath = path;
+       } else {
+               fi.fPath = strdup(name);
+               if (fi.fPath == NULL)
+                       return B_NO_MEMORY;
+       }
 
        fFileSystem->InoIdMap()->AddEntry(fi, fInfo.fFileId);
 
@@ -803,20 +808,33 @@ Inode::ChildAdded(const char* name, uint64 fileID,
        if (fi.fName == NULL)
                return B_NO_MEMORY;
 
-       char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 +
-               strlen(fInfo.fPath)));
-       if (path == NULL)
-               return B_NO_MEMORY;
+       if (fInfo.fPath != NULL) {
+               char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 +
+                       strlen(fInfo.fPath)));
+               if (path == NULL)
+                       return B_NO_MEMORY;
 
-       strcpy(path, fInfo.fPath);
-       strcat(path, "/");
-       strcat(path, name);
-       fi.fPath = path;
+               strcpy(path, fInfo.fPath);
+               strcat(path, "/");
+               strcat(path, name);
+               fi.fPath = path;
+       } else {
+               fi.fPath = strdup(name);
+               if (fi.fPath == NULL)
+                       return B_NO_MEMORY;
+       }
 
        return fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID));
 }
 
 
+const char*
+Inode::Name() const
+{
+       return fInfo.fName;
+}
+
+
 void
 Inode::SetDelegation(Delegation* delegation)
 {
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h 
b/src/add-ons/kernel/file_systems/nfs4/Inode.h
index d4d16ac..7497fa5 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.h
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h
@@ -20,11 +20,11 @@ class Inode : public NFS4Inode {
 public:
        static                  status_t        CreateInode(FileSystem* fs, 
const FileInfo& fi,
                                                                        Inode** 
inode);
-                                                               ~Inode();
+       virtual                                         ~Inode();
 
        inline                  ino_t           ID() const;
        inline                  mode_t          Type() const;
-       inline                  const char*     Name() const;
+       virtual                 const char*     Name() const;
        inline                  FileSystem*     GetFileSystem() const;
 
        inline                  void            SetOpenState(OpenState* state);
@@ -181,13 +181,6 @@ Inode::Type() const
 }
 
 
-inline const char*
-Inode::Name() const
-{
-       return fInfo.fName;
-}
-
-
 inline FileSystem*
 Inode::GetFileSystem() const
 {
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h 
b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
index 2a29e07..ae85c32 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
@@ -23,7 +23,7 @@ public:
        inline                                                                  
~InodeIdMap();
 
        inline  status_t                                                
AddEntry(const FileInfo& fi,
-                                                                               
                ino_t id);
+                                                                               
                ino_t id, bool weak = false);
        inline  status_t                                                
RemoveEntry(ino_t id);
        inline  status_t                                                
GetFileInfo(FileInfo* fi, ino_t id);
 
@@ -49,10 +49,11 @@ InodeIdMap::~InodeIdMap()
 
 
 inline status_t
-InodeIdMap::AddEntry(const FileInfo& fi, ino_t id)
+InodeIdMap::AddEntry(const FileInfo& fi, ino_t id, bool weak)
 {
        MutexLocker _(fLock);
-       fMap.Remove(id);
+       //if (weak)
+               fMap.Remove(id);
        return fMap.Insert(id, fi);
 }
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp
index 0275f67..4ca51e2 100644
--- a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp
@@ -18,6 +18,7 @@
 RootInode::RootInode()
        :
        fInfoCacheExpire(0),
+       fName(NULL),
        fIOSize(0)
 {
        mutex_init(&fInfoCacheLock, NULL);
@@ -26,6 +27,7 @@ RootInode::RootInode()
 
 RootInode::~RootInode()
 {
+       free(const_cast<char*>(fName));
        mutex_destroy(&fInfoCacheLock);
 }
 
@@ -125,7 +127,7 @@ RootInode::_UpdateInfo(bool force)
        } while (true);
 
        fInfoCache.flags = 0;
-       strncpy(fInfoCache.volume_name, fInfo.fName, B_FILE_NAME_LENGTH);
+       strncpy(fInfoCache.volume_name, fName, B_FILE_NAME_LENGTH);
 
        fInfoCacheExpire = time(NULL) + MetadataCache::kExpirationTime;
 
@@ -161,7 +163,6 @@ RootInode::ProbeMigration()
 }
 
 
-
 status_t
 RootInode::GetLocations(AttrValue** attrv)
 {
@@ -198,3 +199,10 @@ RootInode::GetLocations(AttrValue** attrv)
        return B_OK;
 }
 
+
+const char*
+RootInode::Name() const
+{
+       return fName;
+}
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.h 
b/src/add-ons/kernel/file_systems/nfs4/RootInode.h
index 864d49d..4810b78 100644
--- a/src/add-ons/kernel/file_systems/nfs4/RootInode.h
+++ b/src/add-ons/kernel/file_systems/nfs4/RootInode.h
@@ -19,6 +19,9 @@ public:
                                                                RootInode();
                                                                ~RootInode();
 
+       virtual const char*                     Name() const;
+       inline  void                            SetName(const char* name);
+
                        status_t                        ReadInfo(struct 
fs_info* info);
        inline  void                            MakeInfoInvalid();
 
@@ -32,6 +35,8 @@ private:
                        mutex                           fInfoCacheLock;
                        time_t                          fInfoCacheExpire;
 
+                       const char*                     fName;
+
                        uint32                          fIOSize;
 
                        status_t                        _UpdateInfo(bool force 
= false);
@@ -55,5 +60,13 @@ RootInode::IOSize()
 }
 
 
+inline void
+RootInode::SetName(const char* name)
+{
+       free(const_cast<char*>(fName));
+       fName = strdup(name);
+}
+
+
 #endif // ROOTINODE_H
 


Other related posts: