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

  • From: pdziepak-github.nfs4 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 19 Dec 2012 08:30:49 +0100 (CET)

added 1 changeset to branch 'refs/remotes/pdziepak-github/nfs4'
old head: aec9dfc921c4624711e9636fb76e0a75d839c1ee
new head: eed5b716d0d47b766659295406c54f910dc1a092
overview: https://github.com/pdziepak/Haiku/compare/aec9dfc...eed5b71

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

eed5b71: nfs4: Fix problems with reading directory entries
   * Inode::ReadDir missed an entry when given buffer was too small
   * Each OpenDirCookie now has its own copy of directory snapshot what
     would prevent Inode::ReadDir from accessing freed memory when removing
     files and reading directory entries simultaneously
   * Several minor issues fixed

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

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

Commit:      eed5b716d0d47b766659295406c54f910dc1a092
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Wed Dec 19 07:12:39 2012 UTC

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

7 files changed, 51 insertions(+), 18 deletions(-)
.../kernel/file_systems/nfs4/DirectoryCache.cpp  | 28 ++++++++++++++++++++
.../kernel/file_systems/nfs4/DirectoryCache.h    | 11 +++++---
src/add-ons/kernel/file_systems/nfs4/Inode.cpp   |  4 +--
.../kernel/file_systems/nfs4/InodeDir.cpp        | 16 ++++++-----
.../kernel/file_systems/nfs4/InodeRegular.cpp    |  2 +-
.../file_systems/nfs4/ReplyInterpreter.cpp       |  5 +---
.../file_systems/nfs4/kernel_interface.cpp       |  3 +++

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

diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp 
b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp
index 8585f81..923ae53 100644
--- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp
@@ -25,6 +25,14 @@ NameCacheEntry::NameCacheEntry(const char* name, ino_t node)
 }
 
 
+NameCacheEntry::NameCacheEntry(const NameCacheEntry& entry)
+       :
+       fNode(entry.fNode),
+       fName(strdup(entry.fName))
+{
+}
+
+
 NameCacheEntry::~NameCacheEntry()
 {
        free(const_cast<char*>(fName));
@@ -37,6 +45,26 @@ DirectoryCacheSnapshot::DirectoryCacheSnapshot()
 }
 
 
+DirectoryCacheSnapshot::DirectoryCacheSnapshot(
+       const DirectoryCacheSnapshot& snapshot)
+{
+       mutex_init(&fLock, NULL);
+
+       MutexLocker _(snapshot.fLock);
+       NameCacheEntry* entry = snapshot.fEntries.Head();
+       NameCacheEntry* new_entry;
+       while (entry) {
+               new_entry = new NameCacheEntry(*entry);
+               if (new_entry == NULL)
+                       break;
+
+               fEntries.Add(new_entry);
+
+               entry = snapshot.fEntries.GetNext(entry);
+       }
+}
+
+
 DirectoryCacheSnapshot::~DirectoryCacheSnapshot()
 {
        while (!fEntries.IsEmpty()) {
diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h 
b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h
index 45b7bf3..5cc6854 100644
--- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h
+++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h
@@ -24,15 +24,18 @@ struct NameCacheEntry :
                        const char*             fName;
 
                                                        NameCacheEntry(const 
char* name, ino_t node);
+                                                       NameCacheEntry(const 
NameCacheEntry& entry);
                                                        ~NameCacheEntry();
 };
 
 struct DirectoryCacheSnapshot : public KernelReferenceable {
-       SinglyLinkedList<NameCacheEntry>        fEntries;
-       mutex                                                           fLock;
+                       SinglyLinkedList<NameCacheEntry>        fEntries;
+       mutable mutex                   fLock;
 
-                                                                               
DirectoryCacheSnapshot();
-                                                                               
~DirectoryCacheSnapshot();
+                                                       
DirectoryCacheSnapshot();
+                                                       DirectoryCacheSnapshot(
+                                                               const 
DirectoryCacheSnapshot& snapshot);
+                                                       
~DirectoryCacheSnapshot();
 };
 
 class DirectoryCache : public DoublyLinkedListLinkImpl<DirectoryCache> {
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index 600a15d..be79b53 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -250,7 +250,7 @@ Inode::Link(Inode* dir, const char* name)
                        && dir->fCache->ChangeInfo() == changeInfo.fBefore) {
                        dir->fCache->AddEntry(name, fInfo.fFileId, true);
                        dir->fCache->SetChangeInfo(changeInfo.fAfter);
-               } else if (dir->fCache->ChangeInfo() != changeInfo.fBefore)
+               } else
                        dir->fCache->Trash();
        }
        dir->fCache->Unlock();
@@ -428,7 +428,7 @@ Inode::CreateObject(const char* name, const char* path, int 
mode, FileType type,
                if (changeInfo.fAtomic && fCache->ChangeInfo() == 
changeInfo.fBefore) {
                        fCache->AddEntry(name, fileID, true);
                        fCache->SetChangeInfo(changeInfo.fAfter);
-               } else if (fCache->ChangeInfo() != changeInfo.fBefore)
+               } else
                        fCache->Trash();
        }
        fCache->Unlock();
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
index 508b5c8..2b71dce 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
@@ -123,7 +123,7 @@ Inode::FillDirEntry(struct dirent* de, ino_t id, const 
char* name, uint32 pos,
        ASSERT(de != NULL);
        ASSERT(name != NULL);
 
-       uint32 nameSize = strlen(name);
+       uint32 nameSize = strlen(name) + 1;
        const uint32 entSize = sizeof(struct dirent);
 
        if (pos + entSize + nameSize > size)
@@ -282,7 +282,7 @@ Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot,
                                free(const_cast<char*>(name));
 
                        if (entry == NULL || entry->fName == NULL) {
-                               if (entry->fName == NULL)
+                               if (entry != NULL)
                                        delete entry;
                                delete snapshot;
                                delete[] dirents;
@@ -324,10 +324,10 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
                else
                        fFileSystem->Revalidator().RemoveDirectory(cache);
 
-               cookie->fSnapshot = cache->GetSnapshot();
-               if (cookie->fSnapshot == NULL) {
+               DirectoryCacheSnapshot* snapshot = cache->GetSnapshot();
+               if (snapshot == NULL) {
                        uint64 change;
-                       result = GetDirSnapshot(&cookie->fSnapshot, cookie, 
&change,
+                       result = GetDirSnapshot(&snapshot, cookie, &change,
                                cookie->fAttrDir);
                        if (result != B_OK) {
                                cache->Unlock();
@@ -335,9 +335,9 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
                                return result;
                        }
                        cache->ValidateChangeInfo(change);
-                       cache->SetSnapshot(cookie->fSnapshot);
+                       cache->SetSnapshot(snapshot);
                }
-               cookie->fSnapshot->AcquireReference();
+               cookie->fSnapshot = new DirectoryCacheSnapshot(*snapshot);
                fFileSystem->Revalidator().AddDirectory(cache);
                cache->Unlock();
                fFileSystem->Revalidator().Unlock();
@@ -387,6 +387,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
        MutexLocker _(cookie->fSnapshot->fLock);
        for (; !overflow && i < *_count; i++) {
                struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
+               NameCacheEntry* temp = cookie->fCurrent;
 
                if (cookie->fCurrent == NULL)
                        cookie->fCurrent = cookie->fSnapshot->fEntries.Head();
@@ -402,6 +403,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
 
                if (FillDirEntry(de, cookie->fCurrent->fNode, 
cookie->fCurrent->fName,
                        pos, size) == B_BUFFER_OVERFLOW) {
+                       cookie->fCurrent = temp;
                        overflow = true;
                        break;
                }
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
index d5fa76d..7533b86 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
@@ -52,7 +52,7 @@ Inode::CreateState(const char* name, int mode, int perms, 
OpenState* state,
                        && fCache->ChangeInfo() == changeInfo.fBefore) {
                        fCache->AddEntry(name, fileID, true);
                        fCache->SetChangeInfo(changeInfo.fAfter);
-               } else if (fCache->ChangeInfo() != changeInfo.fBefore)
+               } else
                        fCache->Trash();
        }
        fCache->Unlock();
diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp 
b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp
index 14b8df8..271cabb 100644
--- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp
@@ -421,10 +421,7 @@ ReplyInterpreter::ReadDir(uint64* cookie, uint64* 
cookieVerf,
 
                isNext = fReply->Stream().GetBoolean();
        }
-       if (!isNext)
-               *eof = fReply->Stream().GetBoolean();
-       else
-               *eof = false;
+       *eof = fReply->Stream().GetBoolean();
 
        *_count = count;
        *dirents = entries;
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 7641ac9..546aa02 100644
--- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp
@@ -1039,6 +1039,9 @@ nfs4_rewind_dir(fs_volume* volume, fs_vnode* vnode, void* 
_cookie)
 
        OpenDirCookie* cookie = reinterpret_cast<OpenDirCookie*>(_cookie);
        cookie->fSpecial = 0;
+       if (cookie->fSnapshot != NULL)
+               cookie->fSnapshot->ReleaseReference();
+       cookie->fSnapshot = NULL;
        cookie->fCurrent = NULL;
        cookie->fEOF = false;
 


Other related posts: