[haiku-commits] BRANCH pdziepak-github.nfs4_attr [7cca381] src/add-ons/kernel/file_systems/layers/attribute_overlay

  • From: pdziepak-github.nfs4_attr <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 25 Feb 2014 02:31:23 +0100 (CET)

added 5 changesets to branch 'refs/remotes/pdziepak-github/nfs4_attr'
old head: 0000000000000000000000000000000000000000
new head: 7cca381a1508e72d80be45370f7f44bdc5ef667a
overview: https://github.com/pdziepak/Haiku/compare/7cca381

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

996c494: attribute_overlay: Do not require get_vnode_name() hook
  
  File systems that support hard links cannot really implement get_vnode_name().
  That prevents attribute_overlay from working with such file systems.
  
  It is true that attribute_overlay does not support hard links either, but
  if the user knows about its limitations there is no reason to prevent it
  from being used.

2cadf56: attribute_overlay: Fix NULL dereference

a0d8b49: attribute_overlay: Save modified attributes

b6fa76f: attribute_overlay: read_dir: Handle multiple entries properly

7cca381: attribute_overlay: Ignore errors at creating _HAIKU directory
  
  Someone else may have created that directory after out initial lookup.

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

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

1 file changed, 163 insertions(+), 61 deletions(-)
.../attribute_overlay/attribute_overlay.cpp      | 224 ++++++++++++++-----

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

Commit:      996c494e026dfb9b5926f5f760c25d0f59a068a2
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Mon Feb 24 02:43:36 2014 UTC

attribute_overlay: Do not require get_vnode_name() hook

File systems that support hard links cannot really implement get_vnode_name().
That prevents attribute_overlay from working with such file systems.

It is true that attribute_overlay does not support hard links either, but
if the user knows about its limitations there is no reason to prevent it
from being used.

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

diff --git 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
index 201c558..df7c310 100644
--- 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
+++ 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
@@ -1,8 +1,9 @@
 /*
- * Copyright 2009-2010, Haiku Inc. All rights reserved.
+ * Copyright 2009-2014, Haiku Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
+ *             Paweł Dziepak <pdziepak@xxxxxxxxxxx>
  *             Michael Lotz <mmlr@xxxxxxxx>
  */
 
@@ -92,6 +93,8 @@ public:
                fs_vnode *                      SuperVnode() { return 
&fSuperVnode; }
                ino_t                           InodeNumber() { return 
fInodeNumber; }
 
+               status_t                        GetName(char* name, size_t 
length);
+
                status_t                        GetAttributeFile(AttributeFile 
**attributeFile);
                status_t                        WriteAttributeFile();
                status_t                        RemoveAttributeFile();
@@ -106,8 +109,8 @@ private:
 
 class AttributeFile {
 public:
-                                                               
AttributeFile(fs_volume *overlay,
-                                                                       
fs_volume *volume, fs_vnode *vnode);
+                                                               
AttributeFile(fs_volume* overlay,
+                                                                       
fs_volume* volume, OverlayInode* subVnode);
                                                                
~AttributeFile();
 
                        status_t                        InitCheck() { return 
fStatus; }
@@ -116,10 +119,10 @@ public:
                        ino_t                           FileInode() { return 
fFileInode; }
 
                        status_t                        CreateEmpty();
-                       status_t                        
WriteAttributeFile(fs_volume *overlay,
-                                                                       
fs_volume *volume, fs_vnode *vnode);
-                       status_t                        
RemoveAttributeFile(fs_volume *overlay,
-                                                                       
fs_volume *volume, fs_vnode *vnode);
+                       status_t                        
WriteAttributeFile(fs_volume* overlay,
+                                                                       
fs_volume* volume, OverlayInode* subVnode);
+                       status_t                        
RemoveAttributeFile(fs_volume* overlay,
+                                                                       
fs_volume* volume, OverlayInode* subVnode);
 
                        status_t                        ReadAttributeDir(struct 
dirent *dirent,
                                                                        size_t 
bufferSize, uint32 *numEntries,
@@ -256,11 +259,97 @@ OverlayInode::InitCheck()
 
 
 status_t
+OverlayInode::GetName(char* name, size_t length)
+{
+       if (fSuperVnode.ops->get_vnode_name != NULL) {
+               name[length - 1] = '\0';
+               status_t result = fSuperVnode.ops->get_vnode_name(Volume(),
+                               &fSuperVnode, name, length - 1);
+               if (result == B_OK)
+                       return B_OK;
+       }
+
+       if (fSuperVnode.ops->lookup == NULL) {
+               TRACE_ALWAYS("cannot get vnode name, required hooks missing\n");
+               return B_UNSUPPORTED;
+       }
+
+       // TODO: we are using a hack here, cf. TODO in AttributeFile constructor
+       ino_t parentInode;
+       status_t result
+               = fSuperVnode.ops->lookup(Volume(), &fSuperVnode, "..", 
&parentInode);
+       if (result != B_OK)
+               return result;
+
+       if (parentInode == fInodeNumber)
+               strlcpy(name, "_ROOT_DIR", length);
+       else {
+               OverlayInode* overlayInode;
+               result = get_vnode(Volume(), parentInode, (void 
**)&overlayInode);
+               if (result != B_OK) {
+                       TRACE_ALWAYS("getting vnode failed: %s\n", 
strerror(result));
+                       return result;
+               }
+
+               fs_vnode parentVnode = *overlayInode->SuperVnode();
+
+               if (parentVnode.ops->open_dir == NULL
+                       || parentVnode.ops->read_dir == NULL) {
+                       TRACE_ALWAYS("cannot get vnode name, required hooks 
missing\n");
+                       put_vnode(Volume(), parentInode);
+                       return B_UNSUPPORTED;
+               }
+
+               void* cookie;
+               result = parentVnode.ops->open_dir(Volume(), &parentVnode, 
&cookie);
+               if (result != B_OK) {
+                       TRACE_ALWAYS("cannot open parent directory\n");
+                       put_vnode(Volume(), parentInode);
+                       return result;
+               }
+
+               uint8 directoryEntryBuffer[sizeof(dirent) + B_FILE_NAME_LENGTH];
+               dirent* directoryEntry = (dirent*)directoryEntryBuffer;
+               while (true) {
+                       uint32 entriesRead = 1;
+
+                       result = parentVnode.ops->read_dir(Volume(), 
&parentVnode, cookie,
+                                       (dirent*)directoryEntryBuffer, 
sizeof(directoryEntryBuffer),
+                                       &entriesRead);
+                       if (entriesRead == 0)
+                               result = B_ENTRY_NOT_FOUND;
+                       if (result != B_OK)
+                               break;
+                       if (directoryEntry->d_ino != fInodeNumber)
+                               continue;
+
+                       strlcpy(name, directoryEntry->d_name, length);
+                       break;
+               }
+
+               if (parentVnode.ops->close_dir != NULL)
+                       parentVnode.ops->close_dir(Volume(), &parentVnode, 
cookie);
+               if (parentVnode.ops->free_dir_cookie != NULL)
+                       parentVnode.ops->free_dir_cookie(Volume(), 
&parentVnode, cookie);
+
+               put_vnode(Volume(), parentInode);
+
+               if (result != B_OK) {
+                       TRACE_ALWAYS("could not find vnode in its parent 
directory\n");
+                       return result;
+               }
+       }
+
+       return B_OK;
+}
+
+
+status_t
 OverlayInode::GetAttributeFile(AttributeFile **attributeFile)
 {
        if (fAttributeFile == NULL) {
                fAttributeFile = new(std::nothrow) AttributeFile(Volume(),
-                       SuperVolume(), &fSuperVnode);
+                       SuperVolume(), this);
                if (fAttributeFile == NULL) {
                        TRACE_ALWAYS("no memory to allocate attribute file\n");
                        return B_NO_MEMORY;
@@ -294,8 +383,7 @@ OverlayInode::WriteAttributeFile()
        if (result != B_OK)
                return result;
 
-       return fAttributeFile->WriteAttributeFile(Volume(), SuperVolume(),
-               &fSuperVnode);
+       return fAttributeFile->WriteAttributeFile(Volume(), SuperVolume(), 
this);
 }
 
 
@@ -309,8 +397,7 @@ OverlayInode::RemoveAttributeFile()
        if (result != B_OK)
                return result;
 
-       return fAttributeFile->RemoveAttributeFile(Volume(), SuperVolume(),
-               &fSuperVnode);
+       return fAttributeFile->RemoveAttributeFile(Volume(), SuperVolume(), 
this);
 }
 
 
@@ -318,11 +405,11 @@ OverlayInode::RemoveAttributeFile()
 
 
 AttributeFile::AttributeFile(fs_volume *overlay, fs_volume *volume,
-       fs_vnode *vnode)
+       OverlayInode* subVnode)
        :
        fStatus(B_NO_INIT),
        fVolumeID(volume->id),
-       fFileInode(0),
+       fFileInode(subVnode->InodeNumber()),
        fDirectoryInode(0),
        fAttributeDirInode(0),
        fAttributeFileInode(0),
@@ -330,20 +417,10 @@ AttributeFile::AttributeFile(fs_volume *overlay, 
fs_volume *volume,
        fAttributeDirIndex(0),
        fEntries(NULL)
 {
-       if (vnode->ops->get_vnode_name == NULL) {
-               TRACE_ALWAYS("cannot get vnode name, hook missing\n");
-               fStatus = B_UNSUPPORTED;
-               return;
-       }
-
        char nameBuffer[B_FILE_NAME_LENGTH];
-       nameBuffer[sizeof(nameBuffer) - 1] = 0;
-       fStatus = vnode->ops->get_vnode_name(volume, vnode, nameBuffer,
-               sizeof(nameBuffer) - 1);
-       if (fStatus != B_OK) {
-               TRACE_ALWAYS("failed to get vnode name: %s\n", 
strerror(fStatus));
+       fStatus = subVnode->GetName(nameBuffer, B_FILE_NAME_LENGTH);
+       if (fStatus != B_OK)
                return;
-       }
 
        if (strcmp(nameBuffer, ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME) == 0) {
                // we don't want attribute overlays on the attribute dir itself
@@ -351,12 +428,6 @@ AttributeFile::AttributeFile(fs_volume *overlay, fs_volume 
*volume,
                return;
        }
 
-       struct stat stat;
-       if (vnode->ops->read_stat != NULL
-               && vnode->ops->read_stat(volume, vnode, &stat) == B_OK) {
-               fFileInode = stat.st_ino;
-       }
-
        // TODO: the ".." lookup is not actually valid for non-directory vnodes.
        // we make use of the fact that a filesystem probably still provides the
        // lookup hook and has hardcoded ".." to resolve to the parent entry. 
if we
@@ -365,7 +436,7 @@ AttributeFile::AttributeFile(fs_volume *overlay, fs_volume 
*volume,
        const char *lookup[]
                = { "..", ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME, nameBuffer };
        int32 lookupCount = sizeof(lookup) / sizeof(lookup[0]);
-       fs_vnode currentVnode = *vnode;
+       fs_vnode currentVnode = *subVnode->SuperVnode();
        ino_t lastInodeNumber = 0;
 
        for (int32 i = 0; i < lookupCount; i++) {
@@ -418,6 +489,7 @@ AttributeFile::AttributeFile(fs_volume *overlay, fs_volume 
*volume,
                return;
        }
 
+       struct stat stat;
        fStatus = currentVnode.ops->read_stat(volume, &currentVnode, &stat);
        if (fStatus != B_OK) {
                TRACE_ALWAYS("failed to stat attribute file: %s\n", 
strerror(fStatus));
@@ -534,22 +606,20 @@ AttributeFile::CreateEmpty()
 
 
 status_t
-AttributeFile::WriteAttributeFile(fs_volume *overlay, fs_volume *volume,
-       fs_vnode *vnode)
+AttributeFile::WriteAttributeFile(fs_volume* overlay, fs_volume* volume,
+       OverlayInode* subVnode)
 {
        if (fFile == NULL)
                return B_NO_INIT;
 
        char nameBuffer[B_FILE_NAME_LENGTH];
-       nameBuffer[sizeof(nameBuffer) - 1] = 0;
-       status_t result = vnode->ops->get_vnode_name(volume, vnode, nameBuffer,
-               sizeof(nameBuffer) - 1);
+       status_t result = subVnode->GetName(nameBuffer, B_FILE_NAME_LENGTH);
        if (result != B_OK) {
                TRACE_ALWAYS("failed to get vnode name: %s\n", 
strerror(result));
                return result;
        }
 
-       fs_vnode currentVnode = *vnode;
+       fs_vnode currentVnode = *subVnode->SuperVnode();
        if (fDirectoryInode == 0) {
                if (currentVnode.ops->lookup == NULL) {
                        TRACE_ALWAYS("lookup not possible, lookup hook 
missing\n");
@@ -700,8 +770,8 @@ close_and_put:
 
 
 status_t
-AttributeFile::RemoveAttributeFile(fs_volume *overlay, fs_volume *volume,
-       fs_vnode *vnode)
+AttributeFile::RemoveAttributeFile(fs_volume* overlay, fs_volume* volume,
+       OverlayInode* subVnode)
 {
        bool hasAttributeFile = fAttributeFileInode != 0;
        ino_t attributeDirInode = fAttributeDirInode;
@@ -717,9 +787,7 @@ AttributeFile::RemoveAttributeFile(fs_volume *overlay, 
fs_volume *volume,
        }
 
        char nameBuffer[B_FILE_NAME_LENGTH];
-       nameBuffer[sizeof(nameBuffer) - 1] = 0;
-       status_t result = vnode->ops->get_vnode_name(volume, vnode, nameBuffer,
-               sizeof(nameBuffer) - 1);
+       status_t result = subVnode->GetName(nameBuffer, B_FILE_NAME_LENGTH);
        if (result != B_OK) {
                TRACE_ALWAYS("failed to get vnode name: %s\n", 
strerror(result));
                return result;

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

Commit:      2cadf566f140374926d9d9f5d6d0e0f3b6ba8967
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Feb 25 00:10:52 2014 UTC

attribute_overlay: Fix NULL dereference

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

diff --git 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
index df7c310..c8da506 100644
--- 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
+++ 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
@@ -833,6 +833,9 @@ AttributeFile::CountAttributes()
 AttributeEntry *
 AttributeFile::FindAttribute(const char *name, uint32 *index)
 {
+       if (fEntries == NULL)
+               return NULL;
+
        for (uint32 i = 0; i < fFile->entry_count; i++) {
                if (strcmp(fEntries[i]->Name(), name) == 0) {
                        if (index)

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

Commit:      a0d8b4924b18dc3d3c1791d182f5c67ee590908f
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Feb 25 00:14:47 2014 UTC

attribute_overlay: Save modified attributes

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

diff --git 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
index c8da506..b8d9a46 100644
--- 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
+++ 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
@@ -732,6 +732,7 @@ AttributeFile::WriteAttributeFile(fs_volume* overlay, 
fs_volume* volume,
        size_t writeLength = sizeof(attribute_file) - 1;
        result = currentVnode.ops->write(volume, &currentVnode, attrFileCookie,
                position, fFile, &writeLength);
+       position += writeLength;
        if (result != B_OK) {
                TRACE_ALWAYS("failed to write to attribute file: %s\n",
                        strerror(result));
@@ -742,6 +743,7 @@ AttributeFile::WriteAttributeFile(fs_volume* overlay, 
fs_volume* volume,
                writeLength = fEntries[i]->EntrySize();
                result = currentVnode.ops->write(volume, &currentVnode, 
attrFileCookie,
                        position, fEntries[i]->Entry(), &writeLength);
+               position += writeLength;
                if (result != B_OK) {
                        TRACE_ALWAYS("failed to write to attribute file: %s\n",
                                strerror(result));
@@ -751,6 +753,7 @@ AttributeFile::WriteAttributeFile(fs_volume* overlay, 
fs_volume* volume,
                writeLength = fEntries[i]->DataSize();
                result = currentVnode.ops->write(volume, &currentVnode, 
attrFileCookie,
                        position, fEntries[i]->Data(), &writeLength);
+               position += writeLength;
                if (result != B_OK) {
                        TRACE_ALWAYS("failed to write to attribute file: %s\n",
                                strerror(result));
@@ -1617,6 +1620,8 @@ overlay_close_attr(fs_volume *volume, fs_vnode *vnode, 
void *cookie)
 static status_t
 overlay_free_attr_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
 {
+       OverlayInode* node = (OverlayInode* )vnode->private_node;
+       node->WriteAttributeFile();
        return B_OK;
 }
 
@@ -1649,7 +1654,13 @@ static status_t
 overlay_write_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie,
        const struct stat *stat, int statMask)
 {
-       return ((AttributeEntry *)cookie)->WriteStat(stat, statMask);
+       status_t result = ((AttributeEntry *)cookie)->WriteStat(stat, statMask);
+       if (result == B_OK) {
+               OverlayInode* node = (OverlayInode*)vnode->private_node;
+               node->WriteAttributeFile();
+       }
+
+       return result;
 }
 
 
@@ -1691,7 +1702,7 @@ overlay_rename_attr(fs_volume *volume, fs_vnode *vnode,
                return result;
        }
 
-       return B_OK;
+       return node->WriteAttributeFile();
 }
 
 
@@ -1704,7 +1715,11 @@ overlay_remove_attr(fs_volume *volume, fs_vnode *vnode, 
const char *name)
        if (result != B_OK)
                return result;
 
-       return attributeFile->RemoveAttribute(name, NULL);
+       result = attributeFile->RemoveAttribute(name, NULL);
+       if (result != B_OK)
+               return result;
+
+       return node->WriteAttributeFile();
 }
 
 

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

Commit:      b6fa76f4611f45b559179562cf7f715b0c73cce7
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Feb 25 00:54:08 2014 UTC

attribute_overlay: read_dir: Handle multiple entries properly

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

diff --git 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
index b8d9a46..ff41bda 100644
--- 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
+++ 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
@@ -1502,13 +1502,31 @@ overlay_read_dir(fs_volume *volume, fs_vnode *vnode, 
void *cookie,
        if (superVnode->ops->read_dir != NULL) {
                status_t result = 
superVnode->ops->read_dir(volume->super_volume,
                        superVnode, cookie, buffer, bufferSize, num);
+               if (result != B_OK)
+                       return result;
+
+               dirent* currentEntry = buffer;
+               size_t bufferPosition = 0;
+               for (uint32 i = 0; i < *num; i++) {
+                       size_t entrySize = currentEntry->d_reclen;
+                       dirent* nextEntry = (dirent*)((uint8*)currentEntry + 
entrySize);
+
+                       bufferPosition += entrySize;
+                       if (strcmp(currentEntry->d_name,
+                                       ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME) 
== 0) {
+
+                               // skip over the attribute directory
+                               (*num)--;
+                               if (*num == 0) {
+                                       return 
superVnode->ops->read_dir(volume->super_volume,
+                                               superVnode, cookie, buffer, 
bufferSize, num);
+                               } else {
+                                       memmove(currentEntry, nextEntry,
+                                               bufferSize - bufferPosition);
+                               }
+                       }
 
-               // TODO: handle multiple records
-               if (result == B_OK && *num == 1 && strcmp(buffer->d_name,
-                       ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME) == 0) {
-                       // skip over the attribute directory
-                       return superVnode->ops->read_dir(volume->super_volume, 
superVnode,
-                               cookie, buffer, bufferSize, num);
+                       currentEntry = nextEntry;
                }
 
                return result;

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

Commit:      7cca381a1508e72d80be45370f7f44bdc5ef667a
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Feb 25 01:08:08 2014 UTC

attribute_overlay: Ignore errors at creating _HAIKU directory

Someone else may have created that directory after out initial lookup.

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

diff --git 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
index ff41bda..b7f0a41 100644
--- 
a/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
+++ 
b/src/add-ons/kernel/file_systems/layers/attribute_overlay/attribute_overlay.cpp
@@ -650,17 +650,15 @@ AttributeFile::WriteAttributeFile(fs_volume* overlay, 
fs_volume* volume,
                currentVnode = *overlayInode->SuperVnode();
 
                // create the attribute directory
-               result = currentVnode.ops->create_dir(volume, &currentVnode,
+               currentVnode.ops->create_dir(volume, &currentVnode,
                        ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME, S_IRWXU | S_IRWXG 
| S_IRWXO);
 
-               if (result == B_OK) {
-                       result = currentVnode.ops->lookup(volume, &currentVnode,
-                               ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME, 
&fAttributeDirInode);
+               result = currentVnode.ops->lookup(volume, &currentVnode,
+                       ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME, 
&fAttributeDirInode);
 
-                       // lookup() got us a reference we don't need -- put it
-                       if (result == B_OK)
-                               put_vnode(volume, fAttributeDirInode);
-               }
+               // lookup() got us a reference we don't need -- put it
+               if (result == B_OK)
+                       put_vnode(volume, fAttributeDirInode);
 
                put_vnode(volume, fDirectoryInode);
 


Other related posts:

  • » [haiku-commits] BRANCH pdziepak-github.nfs4_attr [7cca381] src/add-ons/kernel/file_systems/layers/attribute_overlay - pdziepak-github . nfs4_attr