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

  • From: pdziepak-github.nfs4 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 3 Jul 2012 22:49:28 +0200 (CEST)

added 6 changesets to branch 'refs/remotes/pdziepak-github/nfs4'
old head: 491a326b7126c8a866eeb0de6cd50a552e1ad14f
new head: 8f57d30ea4934abc215ae850fa3612474087d7a3

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

9b7f2d1: nfs4: Move file handle recovery code out of Inode class

b2cea80: nfs4: Add id mapper

ed097dd: nfs4: Do not attempt to set owner, owner_group when not supported

6197fa8: nfs4: Allow WriteStat() to set UID and GID

16ff38f: nfs4: Support legacy owner and owner_group values

8f57d30: nfs4: Abandon owner and owner_group when id mapping causes problems

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

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

23 files changed, 827 insertions(+), 100 deletions(-)
build/jam/HaikuImage                               |    2 +-
src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp  |   90 ++++++
.../file_systems/nfs4/{Filehandle.h => FileInfo.h} |   10 +-
src/add-ons/kernel/file_systems/nfs4/IdMap.cpp     |  190 +++++++++++
src/add-ons/kernel/file_systems/nfs4/IdMap.h       |   47 +++
src/add-ons/kernel/file_systems/nfs4/Inode.cpp     |  155 +++++----
src/add-ons/kernel/file_systems/nfs4/Inode.h       |    1 -
src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp  |   34 +-
src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h  |    2 +-
.../kernel/file_systems/nfs4/InodeRegular.cpp      |   26 +-
src/add-ons/kernel/file_systems/nfs4/Jamfile       |    5 +
src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h    |    1 -
.../kernel/file_systems/nfs4/ReplyInterpreter.cpp  |   14 +
.../kernel/file_systems/nfs4/ReplyInterpreter.h    |    1 +
.../kernel/file_systems/nfs4/RequestBuilder.cpp    |   10 +
.../kernel/file_systems/nfs4/RequestBuilder.h      |    1 +
src/add-ons/kernel/file_systems/nfs4/XDR.cpp       |    2 +-
src/add-ons/kernel/file_systems/nfs4/XDR.h         |    2 +-
.../kernel/file_systems/nfs4/idmapper/IdMapper.cpp |  266 ++++++++++++++++
.../kernel/file_systems/nfs4/idmapper/IdMapper.h   |   26 ++
.../kernel/file_systems/nfs4/idmapper/Jamfile      |   13 +
.../nfs4/idmapper/nfs4_idmapper_server.rdef        |   20 ++
.../kernel/file_systems/nfs4/kernel_interface.cpp  |    9 +

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

Commit:      9b7f2d1b24a8f67aacc5f80434f9480a10f88e25

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Jul  3 00:01:30 2012 UTC

nfs4: Move file handle recovery code out of Inode class

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

diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp 
b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp
new file mode 100644
index 0000000..1ec4daa
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Paweł Dziepak, pdziepak@xxxxxxxxxxx
+ */
+
+
+#include "FileInfo.h"
+
+#include "Filesystem.h"
+#include "Request.h"
+
+
+static status_t
+sParsePath(RequestBuilder& req, uint32* count, const char* _path)
+{
+       char* path = strdup(_path);
+       char* pathStart = path;
+       char* pathEnd;
+       while (pathStart != NULL) {
+               pathEnd = strpbrk(pathStart, "/");
+               if (pathEnd != NULL)
+                       *pathEnd = '\0';
+
+               req.LookUp(pathStart);
+
+               if (pathEnd != NULL && pathEnd[1] != '\0')
+                       pathStart = pathEnd + 1;
+               else
+                       pathStart = NULL;
+
+               (*count)++;
+       }
+       free(path);
+
+       return B_OK;
+}
+
+
+status_t
+FileInfo::UpdateFileHandles(Filesystem* fs)
+{
+       Request request(fs->Server());
+       RequestBuilder& req = request.Builder();
+
+       req.PutRootFH();
+
+       uint32 lookupCount = 0;
+
+       sParsePath(req, &lookupCount, fs->Path());
+       sParsePath(req, &lookupCount, fPath);
+
+       if (fs->IsAttrSupported(FATTR4_FILEID)) {
+               AttrValue attr;
+               attr.fAttribute = FATTR4_FILEID;
+               attr.fFreePointer = false;
+               attr.fData.fValue64 = fFileId;
+               req.Verify(&attr, 1);
+       }
+
+       req.GetFH();
+       req.LookUpUp();
+       req.GetFH();
+
+       status_t result = request.Send();
+       if (result != B_OK)
+               return result;
+
+       ReplyInterpreter& reply = request.Reply();
+
+       reply.PutRootFH();
+       for (uint32 i = 0; i < lookupCount; i++)
+               reply.LookUp();
+
+       if (fs->IsAttrSupported(FATTR4_FILEID)) {
+               result = reply.Verify();
+               if (result != B_OK)
+                       return result;
+       }
+
+       reply.GetFH(&fHandle);
+       if (reply.LookUpUp() == B_ENTRY_NOT_FOUND) {
+               fParent = fHandle;
+               return B_OK;
+       } else
+               return reply.GetFH(&fParent);
+}
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h 
b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h
similarity index 94%
rename from src/add-ons/kernel/file_systems/nfs4/Filehandle.h
rename to src/add-ons/kernel/file_systems/nfs4/FileInfo.h
index 423a721..a250262 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h
+++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h
@@ -5,8 +5,8 @@
  * Authors:
  *             Paweł Dziepak, pdziepak@xxxxxxxxxxx
  */
-#ifndef FILEHANDLE_H
-#define FILEHANDLE_H
+#ifndef FILEINFO_H
+#define FILEINFO_H
 
 
 #include <stdlib.h>
@@ -27,6 +27,8 @@ struct Filehandle {
 };
 
 
+class Filesystem;
+
 // Complete information needed to identify a file in any situation.
 // Unfortunately just a filehandle is not enough even when they are persistent
 // since OPEN requires both parent filehandle and file name (just like LOOKUP).
@@ -42,6 +44,8 @@ struct FileInfo {
        inline                          ~FileInfo();
        inline                          FileInfo(const FileInfo& fi);
        inline  FileInfo&       operator=(const FileInfo& fi);
+
+                       status_t        UpdateFileHandles(Filesystem* fs);
 };
 
 struct FilesystemId {
@@ -140,5 +144,5 @@ FilesystemId::operator!=(const FilesystemId& fsid) const
 }
 
 
-#endif // FILEHANDLE_H
+#endif // FILEHINFO_H
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index ea5cc28..ccecb6f 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -210,8 +210,8 @@ Inode::Link(Inode* dir, const char* name)
 
                // filehandle has expired
                if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
-                       _LookUpFilehandle();
-                       dir->_LookUpFilehandle();
+                       fInfo.UpdateFileHandles(fFilesystem);
+                       dir->fInfo.UpdateFileHandles(dir->fFilesystem);
                        continue;
                }
 
@@ -315,8 +315,8 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, 
const char* toName)
 
                // filehandle has expired
                if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
-                       from->_LookUpFilehandle();
-                       to->_LookUpFilehandle();
+                       from->fInfo.UpdateFileHandles(from->fFilesystem);
+                       to->fInfo.UpdateFileHandles(to->fFilesystem);
                        continue;
                }
 
@@ -956,7 +956,7 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv,
 
                // filehandle has expired
                case NFS4ERR_FHEXPIRED:
-                       if (_LookUpFilehandle() == B_OK)
+                       if (fInfo.UpdateFileHandles(fFilesystem) == B_OK)
                                return true;
                        else
                                return false;
@@ -980,73 +980,3 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv,
        }
 }
 
-
-static status_t
-sParsePath(RequestBuilder& req, uint32* count, const char* _path)
-{
-       char* path = strdup(_path);
-       char* pathStart = path;
-       char* pathEnd;
-       while (pathStart != NULL) {
-               pathEnd = strpbrk(pathStart, "/");
-               if (pathEnd != NULL)
-                       *pathEnd = '\0';
-
-               req.LookUp(pathStart);
-
-               if (pathEnd != NULL && pathEnd[1] != '\0')
-                       pathStart = pathEnd + 1;
-               else
-                       pathStart = NULL;
-
-               (*count)++;
-       }
-       free(path);
-
-       return B_OK;
-}
-
-
-status_t
-Inode::_LookUpFilehandle()
-{
-       Request request(fFilesystem->Server());
-       RequestBuilder& req = request.Builder();
-
-       req.PutRootFH();
-
-       uint32 lookupCount = 0;
-
-       sParsePath(req, &lookupCount, fFilesystem->Path());
-       sParsePath(req, &lookupCount, fInfo.fPath);
-
-       req.GetFH();
-
-       if (fFilesystem->IsAttrSupported(FATTR4_FILEID)) {
-               AttrValue attr;
-               attr.fAttribute = FATTR4_FILEID;
-               attr.fFreePointer = false;
-               attr.fData.fValue64 = fInfo.fFileId;
-               req.Verify(&attr, 1);
-       }
-
-       status_t result = request.Send();
-       if (result != B_OK)
-               return result;
-
-       ReplyInterpreter& reply = request.Reply();
-
-       reply.PutRootFH();
-       for (uint32 i = 0; i < lookupCount; i++)
-               reply.LookUp();
-
-       result = reply.GetFH(&fInfo.fHandle);
-       if (result != B_OK)
-               return result;
-
-       if (fFilesystem->IsAttrSupported(FATTR4_FILEID))
-               return reply.Verify();
-       else
-               return B_OK;
-}
-
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h 
b/src/add-ons/kernel/file_systems/nfs4/Inode.h
index 1551782..76445e7 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.h
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h
@@ -74,7 +74,6 @@ protected:
                                        bool            _HandleErrors(uint32 
nfs4Error,
                                                                        
RPC::Server* serv,
                                                                        
OpenFileCookie* cookie = NULL);
-                                       status_t        _LookUpFilehandle();
 
                                        status_t        _ConfirmOpen(const 
Filehandle& fh,
                                                                        
OpenFileCookie* cookie);
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h 
b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
index 6cde1f3..63ec1b0 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
@@ -14,7 +14,7 @@
 #include <util/AutoLock.h>
 #include <util/AVLTreeMap.h>
 
-#include "Filehandle.h"
+#include "FileInfo.h"
 
 
 class InodeIdMap {
diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile 
b/src/add-ons/kernel/file_systems/nfs4/Jamfile
index 57060a1..eb8e5e8 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Jamfile
+++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile
@@ -6,6 +6,7 @@ UsePrivateHeaders shared ;
 KernelAddon nfs4 :
        Cookie.cpp
        Connection.cpp
+       FileInfo.cpp
        Filesystem.cpp
        Inode.cpp
        InodeDir.cpp
diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h 
b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h
index 853c783..31e82c2 100644
--- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h
+++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h
@@ -14,7 +14,6 @@
 
 #include <SupportDefs.h>
 
-#include "Filehandle.h"
 
 enum Procedure {
        ProcNull                = 0,
diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h 
b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h
index 0595a8b..8e99e9e 100644
--- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h
+++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h
@@ -11,6 +11,7 @@
 
 #include <SupportDefs.h>
 
+#include "FileInfo.h"
 #include "NFS4Defs.h"
 #include "RPCReply.h"
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h 
b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h
index 0143a9a..f59aac7 100644
--- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h
+++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h
@@ -11,6 +11,7 @@
 
 #include <SupportDefs.h>
 
+#include "FileInfo.h"
 #include "NFS4Defs.h"
 #include "ReplyInterpreter.h"
 #include "RPCCall.h"

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

Commit:      b2cea80ce5328c07e9f5c42c72213c186737aea5

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Jul  3 17:17:37 2012 UTC

nfs4: Add id mapper

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

diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage
index 0d2714b..3c7bb0e 100644
--- a/build/jam/HaikuImage
+++ b/build/jam/HaikuImage
@@ -106,7 +106,7 @@ PRIVATE_SYSTEM_LIBS =
 SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
        media_addon_server media_server midi_server mount_server net_server
        notification_server power_daemon print_server print_addon_server 
registrar syslog_daemon
-       dns_resolver_server
+       dns_resolver_server nfs4_idmapper_server
 ;
 
 SYSTEM_NETWORK_DEVICES = ethernet loopback ;
diff --git a/src/add-ons/kernel/file_systems/nfs4/IdMap.cpp 
b/src/add-ons/kernel/file_systems/nfs4/IdMap.cpp
new file mode 100644
index 0000000..37d7559
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/IdMap.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Paweł Dziepak, pdziepak@xxxxxxxxxxx
+ */
+
+
+#include "IdMap.h"
+
+#include <FindDirectory.h>
+#include <team.h>
+#include <util/AutoLock.h>
+
+#include "idmapper/IdMapper.h"
+
+
+IdMap* gIdMapper       = NULL;
+
+
+IdMap::IdMap()
+{
+       mutex_init(&fLock, NULL);
+       _Repair();
+}
+
+
+IdMap::~IdMap()
+{
+       delete_port(fRequestPort);
+       delete_port(fReplyPort);
+       mutex_destroy(&fLock);
+}
+
+
+uid_t
+IdMap::GetUserId(const char* owner)
+{
+       return _GetValue<uid_t>(owner, MsgNameToUID);
+}
+
+
+gid_t
+IdMap::GetGroupId(const char* ownerGroup)
+{
+       return _GetValue<gid_t>(ownerGroup, MsgNameToGID);
+}
+
+
+char*
+IdMap::GetOwner(uid_t user)
+{
+       return reinterpret_cast<char*>(_GetBuffer(user, MsgUIDToName));
+}
+
+
+char*
+IdMap::GetOwnerGroup(gid_t group)
+{
+       return reinterpret_cast<char*>(_GetBuffer(group, MsgGIDToName));
+}
+
+
+template<typename T>
+T
+IdMap::_GetValue(const char* buffer, int32 code)
+{
+       MutexLocker _(fLock);
+       do {
+               status_t result = write_port(fRequestPort, MsgNameToUID, buffer,
+                       strlen(buffer) + 1);
+               if (result != B_OK) {
+                       if (_Repair() != B_OK)
+                               return 0;
+                       else
+                               continue;
+               }
+
+               int32 code;
+               T value;
+               result = read_port(fReplyPort, &code, &value, sizeof(T));
+               if (result < B_OK) {
+                       if (_Repair() != B_OK)
+                               return 0;
+                       else
+                               continue;
+               }
+
+               if (code != MsgReply)
+                       return 0;
+               else
+                       return value;
+       } while (true);
+}
+
+
+template<typename T>
+void*
+IdMap::_GetBuffer(T value, int32 code)
+{
+       MutexLocker _(fLock);
+       do {
+               status_t result = write_port(fRequestPort, code, &value, 
sizeof(value));
+               if (result != B_OK) {
+                       if (_Repair() != B_OK)
+                               return NULL;
+                       else
+                               continue;
+               }
+
+               ssize_t size = port_buffer_size(fReplyPort);
+               if (size < B_OK) {
+                       if (_Repair() != B_OK)
+                               return NULL;
+                       else
+                               continue;
+               }
+
+               int32 code;
+               void* buffer = malloc(size);
+               if (buffer == NULL)
+                       return NULL;
+
+               result = read_port(fReplyPort, &code, buffer, size);
+               if (result < B_OK) {
+                       free(buffer);
+
+                       if (_Repair() != B_OK)
+                               return 0;
+                       else
+                               continue;
+               }
+
+               if (code != MsgReply) {
+                       free(buffer);
+                       return NULL;
+               } else
+                       return buffer;
+       } while (true);
+}
+
+
+status_t
+IdMap::_Repair()
+{
+       status_t result = B_OK;
+
+       fRequestPort = create_port(1, kRequestPortName);
+       if (fRequestPort < B_OK)
+               return fRequestPort;
+
+       fReplyPort = create_port(1, kReplyPortName);
+       if (fReplyPort < B_OK) {
+               delete_port(fRequestPort);
+               return fReplyPort;
+       }
+
+       char path[256];
+       if (find_directory(B_SYSTEM_SERVERS_DIRECTORY, static_cast<dev_t>(-1),
+               false, path, sizeof(path)) != B_OK) {
+               delete_port(fReplyPort);
+               delete_port(fRequestPort);
+               return B_NAME_NOT_FOUND;
+       }
+       strlcat(path, "/nfs4_idmapper_server", sizeof(path));
+
+       const char* args[] = { path, NULL };
+       thread_id thread = load_image_etc(1, args, NULL, B_NORMAL_PRIORITY,
+               B_SYSTEM_TEAM, 0);
+       if (thread < B_OK) {
+               delete_port(fReplyPort);
+               delete_port(fRequestPort);
+               return thread;
+       }
+
+       set_port_owner(fRequestPort, thread);
+       set_port_owner(fReplyPort, thread);
+
+       result = resume_thread(thread);
+       if (result != B_OK) {
+               kill_thread(thread);
+               delete_port(fReplyPort);
+               delete_port(fRequestPort);
+               return result;
+       }
+
+       return B_OK;
+}
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/IdMap.h 
b/src/add-ons/kernel/file_systems/nfs4/IdMap.h
new file mode 100644
index 0000000..266bef6
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/IdMap.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Paweł Dziepak, pdziepak@xxxxxxxxxxx
+ */
+#ifndef IDMAP_H
+#define IDMAP_H
+
+
+#include <lock.h>
+#include <port.h>
+#include <SupportDefs.h>
+
+
+class IdMap {
+public:
+                                       IdMap();
+                                       ~IdMap();
+
+               uid_t           GetUserId(const char* owner);
+               gid_t           GetGroupId(const char* ownerGroup);
+
+               char*           GetOwner(uid_t user);
+               char*           GetOwnerGroup(gid_t group);
+
+private:
+               status_t        _Repair();
+
+               template<typename T>
+               void*           _GetBuffer(T value, int32 code);
+
+               template<typename T>
+               T                       _GetValue(const char* buffer, int32 
code);
+
+               mutex           fLock;
+
+               port_id         fRequestPort;
+               port_id         fReplyPort;
+};
+
+extern IdMap*  gIdMapper;
+
+
+#endif // IDMAP_H
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index ccecb6f..836962b 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -13,6 +13,7 @@
 
 #include <NodeMonitor.h>
 
+#include "IdMap.h"
 #include "Request.h"
 #include "RootInode.h"
 
@@ -345,11 +346,24 @@ Inode::CreateLink(const char* name, const char* path, int 
mode)
 
                req.PutFH(fInfo.fHandle);
 
-               AttrValue attr;
-               attr.fAttribute = FATTR4_MODE;
-               attr.fFreePointer = false;
-               attr.fData.fValue32 = mode;
-               req.Create(NF4LNK, name, &attr, 1, path);
+               uint32 i = 0;
+               AttrValue cattr[3];
+               cattr[i].fAttribute = FATTR4_MODE;
+               cattr[i].fFreePointer = false;
+               cattr[i].fData.fValue32 = mode;
+               i++;
+
+               cattr[i].fAttribute = FATTR4_OWNER;
+               cattr[i].fFreePointer = true;
+               cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
+               i++;
+
+               cattr[i].fAttribute = FATTR4_OWNER_GROUP;
+               cattr[i].fFreePointer = true;
+               cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
+               i++;
+
+               req.Create(NF4LNK, name, cattr, i, path);
 
                status_t result = request.Send();
                if (result != B_OK)
@@ -460,6 +474,7 @@ Inode::Stat(struct stat* st)
                req.PutFH(fInfo.fHandle);
 
                Attribute attr[] = { FATTR4_SIZE, FATTR4_MODE, FATTR4_NUMLINKS,
+                                                       FATTR4_OWNER, 
FATTR4_OWNER_GROUP,
                                                        FATTR4_TIME_ACCESS, 
FATTR4_TIME_CREATE,
                                                        FATTR4_TIME_METADATA, 
FATTR4_TIME_MODIFY };
                req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
@@ -526,6 +541,20 @@ Inode::Stat(struct stat* st)
                } else
                        st->st_nlink = 1;
 
+               if (count >= next && values[next].fAttribute == FATTR4_OWNER) {
+                       char* owner = 
reinterpret_cast<char*>(values[next].fData.fPointer);
+                       st->st_uid = gIdMapper->GetUserId(owner);
+                       next++;
+               } else
+                       st->st_uid = 0;
+
+               if (count >= next && values[next].fAttribute == 
FATTR4_OWNER_GROUP) {
+                       char* group = 
reinterpret_cast<char*>(values[next].fData.fPointer);
+                       st->st_gid = gIdMapper->GetGroupId(group);
+                       next++;
+               } else
+                       st->st_gid = 0;
+
                if (count >= next && values[next].fAttribute == 
FATTR4_TIME_ACCESS) {
                        memcpy(&st->st_atim, values[next].fData.fPointer, 
sizeof(timespec));
                        next++;
@@ -551,9 +580,6 @@ Inode::Stat(struct stat* st)
                } else
                        memset(&st->st_mtim, 0, sizeof(timespec));
 
-               st->st_uid = 0;
-               st->st_gid = 0;
-
                delete[] values;
                return B_OK;
        } while (true);
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
index c1a3bb1..d41ddca 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
@@ -12,6 +12,7 @@
 #include <dirent.h>
 #include <string.h>
 
+#include "IdMap.h"
 #include "Request.h"
 #include "RootInode.h"
 
@@ -26,11 +27,24 @@ Inode::CreateDir(const char* name, int mode)
 
                req.PutFH(fInfo.fHandle);
 
-               AttrValue attr;
-               attr.fAttribute = FATTR4_MODE;
-               attr.fFreePointer = false;
-               attr.fData.fValue32 = mode;
-               req.Create(NF4DIR, name, &attr, 1);
+               uint32 i = 0;
+               AttrValue cattr[3];
+               cattr[i].fAttribute = FATTR4_MODE;
+               cattr[i].fFreePointer = false;
+               cattr[i].fData.fValue32 = mode;
+               i++;
+
+               cattr[i].fAttribute = FATTR4_OWNER;
+               cattr[i].fFreePointer = true;
+               cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
+               i++;
+
+               cattr[i].fAttribute = FATTR4_OWNER_GROUP;
+               cattr[i].fFreePointer = true;
+               cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
+               i++;
+
+               req.Create(NF4DIR, name, cattr, i);
 
                status_t result = request.Send();
                if (result != B_OK)
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
index 199dabe..b0e92cb 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
@@ -13,6 +13,7 @@
 
 #include <NodeMonitor.h>
 
+#include "IdMap.h"
 #include "Request.h"
 
 
@@ -77,7 +78,7 @@ Inode::Create(const char* name, int mode, int perms, 
OpenFileCookie* cookie,
 
                req.PutFH(fInfo.fHandle);
 
-               AttrValue cattr[2];
+               AttrValue cattr[4];
                uint32 i = 0;
                if ((mode & O_TRUNC) == O_TRUNC) {
                        cattr[i].fAttribute = FATTR4_SIZE;
@@ -88,9 +89,21 @@ Inode::Create(const char* name, int mode, int perms, 
OpenFileCookie* cookie,
                cattr[i].fAttribute = FATTR4_MODE;
                cattr[i].fFreePointer = false;
                cattr[i].fData.fValue32 = perms;
+               i++;
+
+               cattr[i].fAttribute = FATTR4_OWNER;
+               cattr[i].fFreePointer = true;
+               cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
+               i++;
+
+               cattr[i].fAttribute = FATTR4_OWNER_GROUP;
+               cattr[i].fFreePointer = true;
+               cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
+               i++;
+
                req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode),
                        cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, 
name, cattr,
-                       i + 1, (mode & O_EXCL) == O_EXCL);
+                       i, (mode & O_EXCL) == O_EXCL);
 
                req.GetFH();
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile 
b/src/add-ons/kernel/file_systems/nfs4/Jamfile
index eb8e5e8..822bf41 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Jamfile
+++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile
@@ -8,6 +8,7 @@ KernelAddon nfs4 :
        Connection.cpp
        FileInfo.cpp
        Filesystem.cpp
+       IdMap.cpp
        Inode.cpp
        InodeDir.cpp
        InodeRegular.cpp
@@ -23,3 +24,6 @@ KernelAddon nfs4 :
        RPCServer.cpp
        XDR.cpp
 ;
+
+SubInclude HAIKU_TOP src add-ons kernel file_systems nfs4 idmapper ;
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp 
b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp
index c5c97c84..43755b2 100644
--- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp
@@ -614,6 +614,20 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, 
AttrValue** attrs,
                current++;
        }
 
+       if (sIsAttrSet(FATTR4_OWNER, bitmap, bcount)) {
+               values[current].fAttribute = FATTR4_OWNER;
+               values[current].fFreePointer = true;
+               values[current].fData.fPointer = stream.GetString();
+               current++;
+       }
+
+       if (sIsAttrSet(FATTR4_OWNER_GROUP, bitmap, bcount)) {
+               values[current].fAttribute = FATTR4_OWNER_GROUP;
+               values[current].fFreePointer = true;
+               values[current].fData.fPointer = stream.GetString();
+               current++;
+       }
+
        if (sIsAttrSet(FATTR4_SPACE_FREE, bitmap, bcount)) {
                values[current].fAttribute = FATTR4_SPACE_FREE;
                values[current].fData.fValue64 = stream.GetUHyper();
diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp 
b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp
index 8f67dbc..81cade2 100644
--- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp
@@ -776,6 +776,16 @@ RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, 
AttrValue* attr,
                i++;
        }
 
+       if (i < count && attr[i].fAttribute == FATTR4_OWNER) {
+               str.AddString(reinterpret_cast<char*>(attr[i].fData.fPointer));
+               i++;
+       }
+
+       if (i < count && attr[i].fAttribute == FATTR4_OWNER_GROUP) {
+               str.AddString(reinterpret_cast<char*>(attr[i].fData.fPointer));
+               i++;
+       }
+
        if (i < count && attr[i].fAttribute == FATTR4_TIME_ACCESS_SET) {
                str.AddInt(1);          // SET_TO_CLIENT_TIME4
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/XDR.cpp 
b/src/add-ons/kernel/file_systems/nfs4/XDR.cpp
index 423d444..9cc116d 100644
--- a/src/add-ons/kernel/file_systems/nfs4/XDR.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/XDR.cpp
@@ -115,7 +115,7 @@ ReadStream::GetUHyper()
 }
 
 
-const char*
+char*
 ReadStream::GetString()
 {
        if (_PositionToSize() >= fSize) {
diff --git a/src/add-ons/kernel/file_systems/nfs4/XDR.h 
b/src/add-ons/kernel/file_systems/nfs4/XDR.h
index 5d5300e..f52ae0f 100644
--- a/src/add-ons/kernel/file_systems/nfs4/XDR.h
+++ b/src/add-ons/kernel/file_systems/nfs4/XDR.h
@@ -48,7 +48,7 @@ public:
 
        inline  bool                    GetBoolean();
 
-                       const char*             GetString();
+                       char*                   GetString();
 
                        const void*             GetOpaque(uint32* size);
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.cpp 
b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.cpp
new file mode 100644
index 0000000..a0d6c49
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Paweł Dziepak, pdziepak@xxxxxxxxxxx
+ */
+
+
+#include "IdMapper.h"
+
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <File.h>
+#include <FindDirectory.h>
+#include <OS.h>
+#include <Path.h>
+
+
+port_id                gRequestPort;
+port_id                gReplyPort;
+
+const char*    kNobodyName             = "nobody";
+uid_t          gNobodyId;
+
+const char*    kNogroupName    = "nobody";
+uid_t          gNogroupId;
+
+const char* gDomainName                = "localdomain";
+
+
+status_t
+SendError(status_t error)
+{
+       return write_port(gReplyPort, MsgError, &error, sizeof(error));
+}
+
+
+status_t
+MatchDomain(char* name)
+{
+       char* domain = strchr(name, '@');
+       if (domain == NULL)
+               return B_MISMATCHED_VALUES;
+
+       if (strcmp(domain + 1, gDomainName) != 0)
+               return B_BAD_VALUE;
+
+       *domain = '\0';
+
+       return B_OK;
+}
+
+
+char*
+AddDomain(const char* name)
+{
+       uint32 fullLength = strlen(name) + strlen(gDomainName) + 2;
+       char* fullName = reinterpret_cast<char*>(malloc(fullLength));
+
+       strcpy(fullName, name);
+       strcat(fullName, "@");
+       strcat(fullName, gDomainName);
+
+       return fullName;
+}
+
+
+status_t
+NameToUID(void* buffer)
+{
+       char* userName = reinterpret_cast<char*>(buffer);
+
+       struct passwd* userInfo = NULL;
+
+       if (MatchDomain(userName) == B_OK)
+               userInfo = getpwnam(userName);
+
+       if (userInfo == NULL)
+               return write_port(gReplyPort, MsgReply, &gNobodyId, 
sizeof(gNobodyId));
+
+       return write_port(gReplyPort, MsgReply, &userInfo->pw_uid, 
sizeof(uid_t));
+}
+
+
+status_t
+UIDToName(void* buffer)
+{
+       uid_t userId = *reinterpret_cast<uid_t*>(buffer);
+
+       const char* fullName = kNobodyName;
+
+       struct passwd* userInfo = getpwuid(userId);
+       if (userInfo != NULL) {
+               const char* name = userInfo->pw_name;
+               fullName = AddDomain(name);
+       }
+
+       status_t result = write_port(gReplyPort, MsgReply, fullName,
+               strlen(fullName) + 1);
+       free(const_cast<char*>(fullName));
+
+       return result;
+}
+
+
+status_t
+NameToGID(void* buffer)
+{
+       char* groupName = reinterpret_cast<char*>(buffer);
+       
+       struct group* groupInfo = NULL;
+
+       if (MatchDomain(groupName) == B_OK)
+               groupInfo = getgrnam(groupName);
+
+       if (groupInfo == NULL) {
+               return write_port(gReplyPort, MsgReply, &gNogroupId,
+                       sizeof(gNogroupId));
+       }
+
+       return write_port(gReplyPort, MsgReply, &groupInfo->gr_gid, 
sizeof(gid_t));
+}
+
+
+status_t
+GIDToName(void* buffer)
+{
+       gid_t groupId = *reinterpret_cast<gid_t*>(buffer);
+
+       const char* fullName = kNogroupName;
+
+       struct group* groupInfo = getgrgid(groupId);
+       if (groupInfo != NULL) {
+               const char* name = groupInfo->gr_name;
+               fullName = AddDomain(name);
+       }
+
+       status_t result = write_port(gReplyPort, MsgReply, fullName,
+               strlen(fullName) + 1);
+       free(const_cast<char*>(fullName));
+
+       return result;
+}
+
+
+status_t
+ParseRequest(int32 code, void* buffer)
+{
+       switch (code) {
+               case MsgNameToUID:
+                       return NameToUID(buffer);
+
+               case MsgUIDToName:
+                       return UIDToName(buffer);
+
+               case MsgNameToGID:
+                       return NameToGID(buffer);
+
+               case MsgGIDToName:
+                       return GIDToName(buffer);
+
+               default:
+                       return SendError(B_BAD_VALUE);
+       }
+}
+
+
+status_t
+MainLoop()
+{
+       do {
+               ssize_t size = port_buffer_size(gRequestPort);
+               if (size < B_OK)
+                       return 0;
+
+               void* buffer = malloc(size);
+               if (buffer == NULL)
+                       return B_NO_MEMORY;
+
+               int32 code;
+               status_t result = read_port(gRequestPort, &code, buffer, size);
+               if (size < B_OK) {
+                       free(buffer);
+                       return 0;
+               }
+
+               result = ParseRequest(code, buffer);
+               free(buffer);
+
+               if (result == B_BAD_PORT_ID)
+                       return 0;
+
+       } while (true);
+}
+
+
+status_t
+ReadSettings()
+{
+       BPath path;
+       status_t result = find_directory(B_COMMON_SETTINGS_DIRECTORY, &path);
+       if (result != B_OK)
+               return result;
+       result = path.Append("nfs4_idmapper.conf");
+       if (result != B_OK)
+               return result;
+
+       BFile file(path.Path(), B_READ_ONLY);
+       if (file.InitCheck() != B_OK)
+               return file.InitCheck();
+
+       off_t size;
+       result = file.GetSize(&size);
+       if (result != B_OK)
+               return result;
+
+       void* buffer = malloc(size);
+       if (buffer == NULL)
+               return B_NO_MEMORY;
+
+       file.Read(buffer, size);
+
+       gDomainName = reinterpret_cast<char*>(buffer);
+
+       return B_OK;
+}
+
+
+int
+main(int argc, char** argv)
+{
+       gRequestPort = find_port(kRequestPortName);
+       if (gRequestPort == B_NAME_NOT_FOUND) {
+               fprintf(stderr, "%s\n", strerror(gRequestPort));
+               return gRequestPort;
+       }
+
+       gReplyPort = find_port(kReplyPortName);
+       if (gReplyPort == B_NAME_NOT_FOUND) {
+               fprintf(stderr, "%s\n", strerror(gReplyPort));
+               return gReplyPort;
+       }
+
+       ReadSettings();
+
+       struct passwd* userInfo = getpwnam(kNobodyName);
+       if (userInfo != NULL)
+               gNobodyId = userInfo->pw_uid;
+       else
+               gNobodyId = 0;
+
+       struct group* groupInfo = getgrnam(kNogroupName);
+       if (groupInfo != NULL)
+               gNogroupId = groupInfo->gr_gid;
+       else
+               gNogroupId = 0;
+
+       return MainLoop();
+}
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.h 
b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.h
new file mode 100644
index 0000000..bf0707e
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2012 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Paweł Dziepak, pdziepak@xxxxxxxxxxx
+ */
+#ifndef IDMAPPER_H
+#define IDMAPPER_H
+
+
+enum MsgCode {
+       MsgError,
+       MsgReply,
+       MsgNameToUID,
+       MsgUIDToName,
+       MsgNameToGID,
+       MsgGIDToName
+};
+
+static const char*     kRequestPortName        = "nfs4idmap_request";
+static const char*     kReplyPortName          = "nfs4idmap_reply";
+
+
+#endif // IDMAPPER_H
+
diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/Jamfile 
b/src/add-ons/kernel/file_systems/nfs4/idmapper/Jamfile
new file mode 100644
index 0000000..f9f4bb2
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/Jamfile
@@ -0,0 +1,13 @@
+SubDir HAIKU_TOP src add-ons kernel file_systems nfs4 idmapper ;
+
+Application nfs4_idmapper_server
+       :
+       IdMapper.cpp
+
+       :
+       be
+       $(TARGET_LIBSUPC++)
+
+       :
+       nfs4_idmapper_server.rdef
+;
diff --git 
a/src/add-ons/kernel/file_systems/nfs4/idmapper/nfs4_idmapper_server.rdef 
b/src/add-ons/kernel/file_systems/nfs4/idmapper/nfs4_idmapper_server.rdef
new file mode 100644
index 0000000..9b60181
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/nfs4_idmapper_server.rdef
@@ -0,0 +1,20 @@
+/*
+ * nfs4_idmapper_server.rdef
+ */
+
+resource app_signature "application/x-vnd.Haiku-nfs4_idmapper-server";
+
+resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP;
+
+resource app_version {
+       major  = 1,
+       middle = 0,
+       minor  = 0,
+
+       variety = B_APPV_ALPHA,
+       internal = 0,
+
+       short_info = "nfs4_idmapper_server",
+       long_info = "nfs4_idmapper_server ©2012 Haiku, Inc"
+};
+
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 e2b40f9..1f3c216 100644
--- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp
@@ -15,6 +15,7 @@
 
 #include "Connection.h"
 #include "Filesystem.h"
+#include "IdMap.h"
 #include "Inode.h"
 #include "NFS4Defs.h"
 #include "RequestBuilder.h"
@@ -546,6 +547,13 @@ nfs4_init()
        gRPCServerManager = new(std::nothrow) RPC::ServerManager;
        if (gRPCServerManager == NULL)
                return B_NO_MEMORY;
+
+       gIdMapper = new(std::nothrow) IdMap;
+       if (gIdMapper == NULL) {
+               delete gRPCServerManager;
+               return B_NO_MEMORY;
+       }
+
        return B_OK;
 }
 
@@ -555,6 +563,7 @@ nfs4_uninit()
 {
        dprintf("NFS4 Uninit\n");
 
+       delete gIdMapper;
        delete gRPCServerManager;
 
        return B_OK;

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

Commit:      ed097dd0a27587d885a777401a519bf03991d62e

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Jul  3 19:57:08 2012 UTC

nfs4: Do not attempt to set owner, owner_group when not supported

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

diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index 836962b..3a8a995 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -353,15 +353,19 @@ Inode::CreateLink(const char* name, const char* path, int 
mode)
                cattr[i].fData.fValue32 = mode;
                i++;
 
-               cattr[i].fAttribute = FATTR4_OWNER;
-               cattr[i].fFreePointer = true;
-               cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
-               i++;
+               if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
+                       cattr[i].fAttribute = FATTR4_OWNER;
+                       cattr[i].fFreePointer = true;
+                       cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
+                       i++;
+               }
 
-               cattr[i].fAttribute = FATTR4_OWNER_GROUP;
-               cattr[i].fFreePointer = true;
-               cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
-               i++;
+               if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
+                       cattr[i].fAttribute = FATTR4_OWNER_GROUP;
+                       cattr[i].fFreePointer = true;
+                       cattr[i].fData.fPointer = 
gIdMapper->GetOwnerGroup(getgid());
+                       i++;
+               }
 
                req.Create(NF4LNK, name, cattr, i, path);
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
index d41ddca..bde7506 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
@@ -34,15 +34,19 @@ Inode::CreateDir(const char* name, int mode)
                cattr[i].fData.fValue32 = mode;
                i++;
 
-               cattr[i].fAttribute = FATTR4_OWNER;
-               cattr[i].fFreePointer = true;
-               cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
-               i++;
+               if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
+                       cattr[i].fAttribute = FATTR4_OWNER;
+                       cattr[i].fFreePointer = true;
+                       cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
+                       i++;
+               }
 
-               cattr[i].fAttribute = FATTR4_OWNER_GROUP;
-               cattr[i].fFreePointer = true;
-               cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
-               i++;
+               if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
+                       cattr[i].fAttribute = FATTR4_OWNER_GROUP;
+                       cattr[i].fFreePointer = true;
+                       cattr[i].fData.fPointer = 
gIdMapper->GetOwnerGroup(getgid());
+                       i++;
+               }
 
                req.Create(NF4DIR, name, cattr, i);
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
index b0e92cb..3f104fc 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
@@ -91,15 +91,19 @@ Inode::Create(const char* name, int mode, int perms, 
OpenFileCookie* cookie,
                cattr[i].fData.fValue32 = perms;
                i++;
 
-               cattr[i].fAttribute = FATTR4_OWNER;
-               cattr[i].fFreePointer = true;
-               cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
-               i++;
+               if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
+                       cattr[i].fAttribute = FATTR4_OWNER;
+                       cattr[i].fFreePointer = true;
+                       cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
+                       i++;
+               }
 
-               cattr[i].fAttribute = FATTR4_OWNER_GROUP;
-               cattr[i].fFreePointer = true;
-               cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
-               i++;
+               if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
+                       cattr[i].fAttribute = FATTR4_OWNER_GROUP;
+                       cattr[i].fFreePointer = true;
+                       cattr[i].fData.fPointer = 
gIdMapper->GetOwnerGroup(getgid());
+                       i++;
+               }
 
                req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode),
                        cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, 
name, cattr,

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

Commit:      6197fa881fea5641fd7c1433c3c1adf27c5d3fdf

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Jul  3 20:00:55 2012 UTC

nfs4: Allow WriteStat() to set UID and GID

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

diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index 3a8a995..3286dc6 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -595,7 +595,7 @@ Inode::WriteStat(const struct stat* st, uint32 mask)
 {
        status_t result;
        OpenFileCookie* cookie = NULL;
-       AttrValue attr[4];
+       AttrValue attr[6];
        uint32 i = 0;
 
        if ((mask & B_STAT_SIZE) != 0) {
@@ -623,6 +623,20 @@ Inode::WriteStat(const struct stat* st, uint32 mask)
                i++;
        }
 
+       if ((mask & B_STAT_UID) != 0) {
+               attr[i].fAttribute = FATTR4_OWNER;
+               attr[i].fFreePointer = true;
+               attr[i].fData.fPointer = gIdMapper->GetOwner(st->st_uid);
+               i++;
+       }
+
+       if ((mask & B_STAT_GID) != 0) {
+               attr[i].fAttribute = FATTR4_OWNER_GROUP;
+               attr[i].fFreePointer = true;
+               attr[i].fData.fPointer = gIdMapper->GetOwnerGroup(st->st_gid);
+               i++;
+       }
+
        if ((mask & B_STAT_ACCESS_TIME) != 0) {
                attr[i].fAttribute = FATTR4_TIME_ACCESS_SET;
                attr[i].fFreePointer = true;

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

Commit:      16ff38f8289b93fe84a8e04aeddf33f9e78434fb

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Jul  3 20:08:35 2012 UTC

nfs4: Support legacy owner and owner_group values

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

diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index 3286dc6..5199cb2 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -9,6 +9,7 @@
 
 #include "Inode.h"
 
+#include <ctype.h>
 #include <string.h>
 
 #include <NodeMonitor.h>
@@ -547,14 +548,20 @@ Inode::Stat(struct stat* st)
 
                if (count >= next && values[next].fAttribute == FATTR4_OWNER) {
                        char* owner = 
reinterpret_cast<char*>(values[next].fData.fPointer);
-                       st->st_uid = gIdMapper->GetUserId(owner);
+                       if (owner != NULL && isdigit(owner[0]))
+                               st->st_uid = atoi(owner);
+                       else
+                               st->st_uid = gIdMapper->GetUserId(owner);
                        next++;
                } else
                        st->st_uid = 0;
 
                if (count >= next && values[next].fAttribute == 
FATTR4_OWNER_GROUP) {
                        char* group = 
reinterpret_cast<char*>(values[next].fData.fPointer);
-                       st->st_gid = gIdMapper->GetGroupId(group);
+                       if (group != NULL && isdigit(group[0]))
+                               st->st_gid = atoi(group);
+                       else
+                               st->st_gid = gIdMapper->GetGroupId(group);
                        next++;
                } else
                        st->st_gid = 0;

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

Commit:      8f57d30ea4934abc215ae850fa3612474087d7a3

Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Tue Jul  3 20:16:08 2012 UTC

nfs4: Abandon owner and owner_group when id mapping causes problems

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

diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index 5199cb2..055b6b2 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -340,6 +340,8 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, 
const char* toName)
 status_t
 Inode::CreateLink(const char* name, const char* path, int mode)
 {
+       bool badOwner = false;
+
        do {
                RPC::Server* serv = fFilesystem->Server();
                Request request(serv);
@@ -354,14 +356,14 @@ Inode::CreateLink(const char* name, const char* path, int 
mode)
                cattr[i].fData.fValue32 = mode;
                i++;
 
-               if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
+               if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
                        cattr[i].fAttribute = FATTR4_OWNER;
                        cattr[i].fFreePointer = true;
                        cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
                        i++;
                }
 
-               if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
+               if (!badOwner && 
fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
                        cattr[i].fAttribute = FATTR4_OWNER_GROUP;
                        cattr[i].fFreePointer = true;
                        cattr[i].fData.fPointer = 
gIdMapper->GetOwnerGroup(getgid());
@@ -376,6 +378,10 @@ Inode::CreateLink(const char* name, const char* path, int 
mode)
 
                ReplyInterpreter& reply = request.Reply();
 
+               if (reply.NFS4Error() == NFS4ERR_BADOWNER) {
+                       badOwner = true;
+                       continue;
+               }
                if (_HandleErrors(reply.NFS4Error(), serv))
                        continue;
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
index bde7506..19b2743 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
@@ -20,6 +20,8 @@
 status_t
 Inode::CreateDir(const char* name, int mode)
 {
+       bool badOwner = false;
+
        do {
                RPC::Server* serv = fFilesystem->Server();
                Request request(serv);
@@ -34,14 +36,14 @@ Inode::CreateDir(const char* name, int mode)
                cattr[i].fData.fValue32 = mode;
                i++;
 
-               if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
+               if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
                        cattr[i].fAttribute = FATTR4_OWNER;
                        cattr[i].fFreePointer = true;
                        cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
                        i++;
                }
 
-               if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
+               if (!badOwner && 
fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
                        cattr[i].fAttribute = FATTR4_OWNER_GROUP;
                        cattr[i].fFreePointer = true;
                        cattr[i].fData.fPointer = 
gIdMapper->GetOwnerGroup(getgid());
@@ -56,6 +58,10 @@ Inode::CreateDir(const char* name, int mode)
 
                ReplyInterpreter& reply = request.Reply();
 
+               if (reply.NFS4Error() == NFS4ERR_BADOWNER) {
+                       badOwner = true;
+                       continue;
+               }
                if (_HandleErrors(reply.NFS4Error(), serv))
                        continue;
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
index 3f104fc..742ba45 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp
@@ -66,6 +66,7 @@ Inode::Create(const char* name, int mode, int perms, 
OpenFileCookie* cookie,
        cookie->fSequence = 0;
        cookie->fLocks = NULL;
 
+       bool badOwner = false;
        Filehandle fh;
        do {
                cookie->fClientId = fFilesystem->NFSServer()->ClientId();
@@ -91,14 +92,14 @@ Inode::Create(const char* name, int mode, int perms, 
OpenFileCookie* cookie,
                cattr[i].fData.fValue32 = perms;
                i++;
 
-               if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
+               if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER)) {
                        cattr[i].fAttribute = FATTR4_OWNER;
                        cattr[i].fFreePointer = true;
                        cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
                        i++;
                }
 
-               if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
+               if (!badOwner && 
fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
                        cattr[i].fAttribute = FATTR4_OWNER_GROUP;
                        cattr[i].fFreePointer = true;
                        cattr[i].fData.fPointer = 
gIdMapper->GetOwnerGroup(getgid());
@@ -122,6 +123,10 @@ Inode::Create(const char* name, int mode, int perms, 
OpenFileCookie* cookie,
 
                ReplyInterpreter& reply = request.Reply();
 
+               if (reply.NFS4Error() == NFS4ERR_BADOWNER) {
+                       badOwner = true;
+                       continue;
+               }
                if (_HandleErrors(reply.NFS4Error(), serv))
                        continue;
 


Other related posts: