added 2 changesets to branch 'refs/remotes/pdziepak-github/nfs4' old head: ff4d16ded4782a2967ffa2413761c078516b2ae6 new head: c0344ea198e280a3e8f23191262e2d7fffe9ff0c ---------------------------------------------------------------------------- 70472e1: nfs4: Add basic emulation of named attributes c0344ea: nfs4: Get correct change value for attribute directories [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 7 files changed, 176 insertions(+), 59 deletions(-) .../kernel/file_systems/nfs4/DirectoryCache.cpp | 2 +- src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp | 81 ++++++++++++-- .../kernel/file_systems/nfs4/InodeRegular.cpp | 49 ++++++-- src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp | 92 ++++++++++------ src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h | 7 +- src/add-ons/kernel/file_systems/nfs4/OpenState.cpp | 3 +- .../kernel/file_systems/nfs4/ReplyInterpreter.cpp | 1 + ############################################################################ Commit: 70472e11d37500a8cb434906f20254046bef0f5e Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Wed Aug 15 02:11:25 2012 UTC nfs4: Add basic emulation of named attributes ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index d78d28f..33e7822 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -62,22 +62,41 @@ Inode::OpenAttrDir(OpenDirCookie* cookie) status_t Inode::LoadAttrDirHandle() { - if (!fFileSystem->NamedAttrs()) - return B_UNSUPPORTED; + if (fInfo.fAttrDir.fSize != 0) + return B_OK; - if (fInfo.fAttrDir.fSize == 0) { - FileHandle handle; + 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); + } - status_t result = NFS4Inode::OpenAttrDir(&handle); + free(attrDir); + } else { + result = NFS4Inode::OpenAttrDir(&handle); if (result == B_UNSUPPORTED) fFileSystem->SetNamedAttrs(false); - - if (result != B_OK) - return result; - - fInfo.fAttrDir = handle; } + if (result != B_OK) + return result; + + fInfo.fAttrDir = handle; return B_OK; } @@ -156,6 +175,31 @@ Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size) } +static char* +FileToAttrName(const char* path) +{ + char* name = strdup(path); + if (name == NULL) + return NULL; + + char* current = strpbrk(name, "#$"); + while (current != NULL) { + switch (*current) { + case '#': + *current = '/'; + break; + case '$': + *current = ':'; + break; + } + current = strpbrk(name, "#$"); + } + + return name; +} + + + status_t Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot, OpenDirCookie* cookie, uint64* _change, bool attribute) @@ -189,6 +233,9 @@ Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot, if (*fsid != fFileSystem->FsId()) continue; + if (strstr(dirents[i].fName, "-haiku-attrs") != NULL) + continue; + ino_t id; if (!attribute) { if (dirents[i].fAttrCount == 2) @@ -198,7 +245,19 @@ Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot, } else id = 0; - NameCacheEntry* entry = new NameCacheEntry(dirents[i].fName, id); + const char* name = dirents[i].fName; + if (attribute) + name = FileToAttrName(name); + if (name == NULL) { + delete snapshot; + delete[] dirents; + return B_NO_MEMORY; + } + + NameCacheEntry* entry = new NameCacheEntry(name, id); + if (attribute) + free(const_cast<char*>(name)); + if (entry == NULL || entry->fName == NULL) { if (entry->fName == NULL) delete entry; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 5490ee0..921d52a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -11,6 +11,7 @@ #include <string.h> +#include <AutoDeleter.h> #include <fs_cache.h> #include <NodeMonitor.h> @@ -192,9 +193,33 @@ Inode::Close(OpenFileCookie* cookie) } +static char* +AttrToFileName(const char* path) +{ + char* name = strdup(path); + if (name == NULL) + return NULL; + + char* current = strpbrk(name, "/:"); + while (current != NULL) { + switch (*current) { + case '/': + *current = '#'; + break; + case ':': + *current = '$'; + break; + } + current = strpbrk(name, "/:"); + } + + return name; +} + + status_t -Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create, - int32 type) +Inode::OpenAttr(const char* _name, int mode, OpenAttrCookie* cookie, + bool create, int32 type) { (void)type; @@ -202,6 +227,11 @@ Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create, if (result != B_OK) return result; + char* name = AttrToFileName(_name); + if (name == NULL) + return B_NO_MEMORY; + MemoryDeleter nameDeleter(name); + OpenDelegationData data; data.fType = OPEN_DELEGATE_NONE; @@ -209,8 +239,9 @@ Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create, if (state == NULL) return B_NO_MEMORY; - state->fInfo.fName = name; + state->fInfo.fName = strdup(name); state->fInfo.fParent = fInfo.fAttrDir; + state->fFileSystem = fFileSystem; result = NFS4Inode::OpenAttr(state, name, mode, &data, create); if (result != B_OK) { delete state; @@ -225,8 +256,7 @@ Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create, if (data.fType != OPEN_DELEGATE_NONE) { Delegation* delegation - = new(std::nothrow) Delegation(data, this, fOpenState->fClientID, - true); + = new(std::nothrow) Delegation(data, this, state->fClientID, true); if (delegation != NULL) { delegation->fInfo = state->fInfo; delegation->fFileSystem = fFileSystem; @@ -235,7 +265,7 @@ Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create, } } - if ((mode & O_TRUNC) == O_TRUNC) { + if (create || (mode & O_TRUNC) == O_TRUNC) { struct stat st; st.st_size = 0; WriteStat(&st, B_STAT_SIZE, cookie); @@ -248,8 +278,11 @@ Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create, status_t Inode::CloseAttr(OpenAttrCookie* cookie) { - cookie->fOpenState->fDelegation->GiveUp(); - fFileSystem->RemoveDelegation(cookie->fOpenState->fDelegation); + if (cookie->fOpenState->fDelegation != NULL) { + cookie->fOpenState->fDelegation->GiveUp(); + fFileSystem->RemoveDelegation(cookie->fOpenState->fDelegation); + } + delete cookie->fOpenState->fDelegation; delete cookie->fOpenState; return B_OK; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 62a9acc..6f66c32 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -107,17 +107,22 @@ NFS4Inode::Access(uint32* allowed) status_t NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID, - FileHandle* handle) + FileHandle* handle, bool parent) { do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); RequestBuilder& req = request.Builder(); - req.PutFH(fInfo.fHandle); + if (parent) + req.PutFH(fInfo.fParent); + else + req.PutFH(fInfo.fHandle); - Attribute dirAttr[] = { FATTR4_CHANGE }; - req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute)); + if (change != NULL) { + Attribute dirAttr[] = { FATTR4_CHANGE }; + req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute)); + } if (!strcmp(name, "..")) req.LookUpUp(); @@ -142,12 +147,14 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID, AttrValue* values; uint32 count; - result = reply.GetAttr(&values, &count); - if (result != B_OK) - return result; + if (change != NULL) { + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; - *change = values[0].fData.fValue64; - delete[] values; + *change = values[0].fData.fValue64; + delete[] values; + } if (!strcmp(name, "..")) result = reply.LookUpUp(); @@ -170,10 +177,13 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID, return B_ENTRY_NOT_FOUND; } - if (count < 2 || values[1].fAttribute != FATTR4_FILEID) - *fileID = fFileSystem->AllocFileId(); - else - *fileID = values[1].fData.fValue64; + if (fileID != NULL) { + if (count < 2 || values[1].fAttribute != FATTR4_FILEID) + *fileID = fFileSystem->AllocFileId(); + else + *fileID = values[1].fData.fValue64; + } + delete[] values; return B_OK; @@ -536,11 +546,11 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) ReplyInterpreter& reply = request.Reply(); + sequence += IncrementSequence(reply.NFS4Error()); + if (HandleErrors(reply.NFS4Error(), serv, NULL, state, &sequence)) continue; - sequence += IncrementSequence(reply.NFS4Error()); - // Verify if the file we want to open is the file this Inode // represents. if (fFileSystem->IsAttrSupported(FATTR4_FILEID) || @@ -617,11 +627,11 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, int mode, ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) - continue; - sequence += IncrementSequence(reply.NFS4Error()); + if (HandleErrors(reply.NFS4Error(), serv, NULL, state, &sequence)) + continue; + reply.PutFH(); result = reply.Open(state->fStateID, &state->fStateSeq, &confirm, delegation); @@ -639,7 +649,7 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, int mode, state->fOpened = true; if (confirm) - result = ConfirmOpen(fInfo.fHandle, state, &sequence); + result = ConfirmOpen(state->fInfo.fHandle, state, &sequence); fFileSystem->OpenOwnerSequenceUnlock(sequence); return result; @@ -714,14 +724,18 @@ NFS4Inode::WriteFile(OpenStateCookie* cookie, OpenState* state, uint64 position, status_t NFS4Inode::CreateObject(const char* name, const char* path, int mode, - FileType type, ChangeInfo* changeInfo, uint64* fileID, FileHandle* handle) + FileType type, ChangeInfo* changeInfo, uint64* fileID, FileHandle* handle, + bool parent) { do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); RequestBuilder& req = request.Builder(); - req.PutFH(fInfo.fHandle); + if (parent) + req.PutFH(fInfo.fParent); + else + req.PutFH(fInfo.fHandle); uint32 i = 0; AttrValue cattr[1]; @@ -742,8 +756,11 @@ NFS4Inode::CreateObject(const char* name, const char* path, int mode, } req.GetFH(); - Attribute attr[] = { FATTR4_FILEID }; - req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + + if (fileID != NULL) { + Attribute attr[] = { FATTR4_FILEID }; + req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + } status_t result = request.Send(); if (result != B_OK) @@ -764,18 +781,20 @@ NFS4Inode::CreateObject(const char* name, const char* path, int mode, if (result != B_OK) return result; - AttrValue* values; - uint32 count; - result = reply.GetAttr(&values, &count); - if (result != B_OK) - return result; + if (fileID != NULL) { + AttrValue* values; + uint32 count; + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; - if (count == 0) - *fileID = fFileSystem->AllocFileId(); - else - *fileID = values[0].fData.fValue64; + if (count == 0) + *fileID = fFileSystem->AllocFileId(); + else + *fileID = values[0].fData.fValue64; - delete[] values; + delete[] values; + } return B_OK; } while (true); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index 110cce7..fcb1090 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -31,7 +31,7 @@ protected: status_t CommitWrites(); status_t LookUp(const char* name, uint64* change, uint64* fileID, - FileHandle* handle); + FileHandle* handle, bool parent = false); status_t Link(Inode* dir, const char* name, ChangeInfo* changeInfo); @@ -65,7 +65,8 @@ protected: status_t CreateObject(const char* name, const char* path, int mode, FileType type, ChangeInfo* changeInfo, - uint64* fileID, FileHandle* handle); + uint64* fileID, FileHandle* handle, + bool parent = false); status_t RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo, uint64* fileID); diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp index b311ceb..7de9b42 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp @@ -32,7 +32,8 @@ OpenState::OpenState() OpenState::~OpenState() { - fFileSystem->RemoveOpenFile(this); + if (fOpened) + fFileSystem->RemoveOpenFile(this); Close(); mutex_destroy(&fLock); diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index 5812827..6f04552 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -34,6 +34,7 @@ FSLocations::~FSLocations() AttrValue::AttrValue() : + fAttribute(0), fFreePointer(false) { } ############################################################################ Commit: c0344ea198e280a3e8f23191262e2d7fffe9ff0c Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Wed Aug 15 02:22:18 2012 UTC nfs4: Get correct change value for attribute directories ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp index e7062c0..325a764 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp @@ -179,7 +179,7 @@ status_t DirectoryCache::Revalidate() { uint64 change; - if (fInode->GetChangeInfo(&change) == B_OK && change == fChange) { + if (fInode->GetChangeInfo(&change, true) == B_OK && change == fChange) { fExpireTime = system_time() + kExpirationTime; return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 6f66c32..145c50f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -14,14 +14,17 @@ status_t -NFS4Inode::GetChangeInfo(uint64* change) +NFS4Inode::GetChangeInfo(uint64* change, bool attrDir) { do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); RequestBuilder& req = request.Builder(); - req.PutFH(fInfo.fHandle); + if (attrDir) + req.PutFH(fInfo.fAttrDir); + else + req.PutFH(fInfo.fHandle); Attribute attr[] = { FATTR4_CHANGE }; req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index fcb1090..62db373 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -22,7 +22,7 @@ class NFS4Inode : protected NFS4Object { public: - status_t GetChangeInfo(uint64* change); + status_t GetChangeInfo(uint64* change, bool attrDir = false); status_t ReadLink(void* buffer, size_t* length); protected: