diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 3d87f3662b..b87792ece7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -229,25 +229,9 @@ Inode::LookUp(const char* name, ino_t* id) *id = _FileIdToInoT(fileId); - FileInfo fi; - fi.fFileId = fileId; - fi.fHandle = fh; - fi.fParent = fInfo.fHandle; - fi.fName = strdup(name); - if (fi.fName == NULL) - return B_NO_MEMORY; - - char* path = reinterpret_cast(malloc(strlen(name) + 2 + - strlen(fInfo.fPath))); - if (path == NULL) - return B_NO_MEMORY; - - strcpy(path, fInfo.fPath); - strcat(path, "/"); - strcat(path, name); - fi.fPath = path; - - fFileSystem->InoIdMap()->AddEntry(fi, *id); + result = _ChildAdded(name, fileId, fh); + if (result != B_OK) + return result; fFileSystem->Revalidator().Lock(); if (fCache->Lock() != B_OK) { @@ -281,10 +265,6 @@ Inode::Link(Inode* dir, const char* name) req.PutFH(dir->fInfo.fHandle); req.Link(name); - req.LookUp(name); - Attribute attr[] = { FATTR4_FILEID }; - req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); - status_t result = request.Send(); if (result != B_OK) return result; @@ -314,31 +294,35 @@ Inode::Link(Inode* dir, const char* name) if (result != B_OK) return result; - result = reply.LookUp(); - if (result != B_OK) - return result; - - AttrValue* values; - uint32 count; - result = reply.GetAttr(&values, &count); - if (result != B_OK) - return result; - - uint32 fileID; - if (count == 0) - fileID = fFileSystem->AllocFileId(); - else - fileID = values[1].fData.fValue64; - fFileSystem->Root()->MakeInfoInvalid(); - if (fCache->Lock() == B_OK) { - if (atomic && fCache->ChangeInfo() == before) { - fCache->AddEntry(name, fileID, true); - fCache->SetChangeInfo(after); - } else if (fCache->ChangeInfo() != before) - fCache->Trash(); - fCache->Unlock(); + FileInfo fi = fInfo; + fi.fParent = dir->fInfo.fHandle; + free(const_cast(fi.fName)); + fi.fName = strdup(name); + if (fi.fName == NULL) + return B_NO_MEMORY; + + char* path = reinterpret_cast(malloc(strlen(name) + 2 + + strlen(fInfo.fPath))); + if (path == NULL) + return B_NO_MEMORY; + + strcpy(path, dir->fInfo.fPath); + strcat(path, "/"); + strcat(path, name); + free(const_cast(fi.fPath)); + fi.fPath = path; + + fFileSystem->InoIdMap()->AddEntry(fi, fInfo.fFileId); + + if (dir->fCache->Lock() == B_OK) { + if (atomic && dir->fCache->ChangeInfo() == before) { + dir->fCache->AddEntry(name, fInfo.fFileId, true); + dir->fCache->SetChangeInfo(after); + } else if (dir->fCache->ChangeInfo() != before) + dir->fCache->Trash(); + dir->fCache->Unlock(); } return B_OK; @@ -549,6 +533,7 @@ Inode::CreateLink(const char* name, const char* path, int mode) req.Create(NF4LNK, name, cattr, i, path); + req.GetFH(); Attribute attr[] = { FATTR4_FILEID }; req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); @@ -573,6 +558,9 @@ Inode::CreateLink(const char* name, const char* path, int mode) if (result != B_OK) return result; + FileHandle handle; + reply.GetFH(&handle); + AttrValue* values; uint32 count; result = reply.GetAttr(&values, &count); @@ -583,10 +571,14 @@ Inode::CreateLink(const char* name, const char* path, int mode) if (count == 0) fileID = fFileSystem->AllocFileId(); else - fileID = values[1].fData.fValue64; + fileID = values[0].fData.fValue64; fFileSystem->Root()->MakeInfoInvalid(); + result = _ChildAdded(name, fileID, handle); + if (result != B_OK) + return B_OK; + if (fCache->Lock() == B_OK) { if (atomic && fCache->ChangeInfo() == before) { fCache->AddEntry(name, fileID, true); @@ -1310,3 +1302,31 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv, } } + +status_t +Inode::_ChildAdded(const char* name, uint64 fileID, + const FileHandle& fileHandle) +{ + fFileSystem->Root()->MakeInfoInvalid(); + + FileInfo fi; + fi.fFileId = fileID; + fi.fHandle = fileHandle; + fi.fParent = fInfo.fHandle; + fi.fName = strdup(name); + if (fi.fName == NULL) + return B_NO_MEMORY; + + char* path = reinterpret_cast(malloc(strlen(name) + 2 + + strlen(fInfo.fPath))); + if (path == NULL) + return B_NO_MEMORY; + + strcpy(path, fInfo.fPath); + strcat(path, "/"); + strcat(path, name); + fi.fPath = path; + + return fFileSystem->InoIdMap()->AddEntry(fi, _FileIdToInoT(fileID)); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index feb9964c94..6a7a584bca 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -92,6 +92,9 @@ protected: _snapshot, OpenDirCookie* cookie, uint64* _change); + status_t _ChildAdded(const char* name, uint64 fileID, + const FileHandle& fileHandle); + static inline status_t _CheckLockType(short ltype, uint32 mode); static inline ino_t _FileIdToInoT(uint64 fileid); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index 28addc3171..e12ab4c97e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -52,6 +52,7 @@ Inode::CreateDir(const char* name, int mode) req.Create(NF4DIR, name, cattr, i); + req.GetFH(); Attribute attr[] = { FATTR4_FILEID }; req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); @@ -76,6 +77,11 @@ Inode::CreateDir(const char* name, int mode) if (result != B_OK) return result; + FileHandle handle; + result = reply.GetFH(&handle); + if (result != B_OK) + return result; + AttrValue* values; uint32 count; result = reply.GetAttr(&values, &count); @@ -86,9 +92,11 @@ Inode::CreateDir(const char* name, int mode) if (count == 0) fileID = fFileSystem->AllocFileId(); else - fileID = values[1].fData.fValue64; + fileID = values[0].fData.fValue64; - fFileSystem->Root()->MakeInfoInvalid(); + result = _ChildAdded(name, fileID, handle); + if (result != B_OK) + return B_OK; if (fCache->Lock() == B_OK) { if (atomic && fCache->ChangeInfo() == before) { diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 9c7c83d491..ace10fa343 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -132,7 +132,14 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, continue; reply.PutFH(); - reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm); + + bool atomic; + uint64 before, after; + result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm, + &before, &after, &atomic); + if (result != B_OK) + return result; + reply.GetFH(&fh); uint64 fileId; @@ -143,7 +150,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, if (result != B_OK) return result; - fileId = values[1].fData.fValue64; + fileId = values[0].fData.fValue64; delete[] values; } else @@ -166,6 +173,15 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, fFileSystem->InoIdMap()->AddEntry(fi, *id); + if (fCache->Lock() == B_OK) { + if (atomic && fCache->ChangeInfo() == before) { + fCache->AddEntry(name, fileId, true); + fCache->SetChangeInfo(after); + } else if (fCache->ChangeInfo() != before) + fCache->Trash(); + fCache->Unlock(); + } + cookie->fFileSystem = fFileSystem; cookie->fInfo = fi; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index c80b5da395..0fdf732f0b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -135,8 +135,9 @@ ReplyInterpreter::Create(uint64* before, uint64* after, bool& atomic) atomic = fReply->Stream().GetBoolean(); *before = fReply->Stream().GetUHyper(); *after = fReply->Stream().GetUHyper(); + uint32 count = fReply->Stream().GetUInt(); - for (uint32 i; i < count; i++) + for (uint32 i = 0; i < count; i++) fReply->Stream().GetUInt(); return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; @@ -252,7 +253,8 @@ ReplyInterpreter::LockU(LockInfo* linfo) status_t -ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm) +ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before, + uint64* _after, bool* _atomic) { status_t res = _OperationError(OpOpen); if (res != B_OK) @@ -264,9 +266,15 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm) id[2] = fReply->Stream().GetUInt(); // change info - fReply->Stream().GetBoolean(); - fReply->Stream().GetUHyper(); - fReply->Stream().GetUHyper(); + bool atomic = fReply->Stream().GetBoolean(); + if (_atomic != NULL) + *_atomic = atomic; + uint64 before = fReply->Stream().GetUHyper(); + if (_before != NULL) + *_before = before; + uint64 after = fReply->Stream().GetUHyper(); + if (_after != NULL) + *_after = after; uint32 flags = fReply->Stream().GetUInt(); *confirm = (flags & OPEN4_RESULT_CONFIRM) == OPEN4_RESULT_CONFIRM; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 92739d2f95..27a60d73b4 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -79,7 +79,9 @@ public: inline status_t LookUp(); inline status_t LookUpUp(); inline status_t Nverify(); - status_t Open(uint32* id, uint32* seq, bool* confirm); + status_t Open(uint32* id, uint32* seq, bool* confirm, + uint64* before = NULL, uint64* after = NULL, + bool* atomic = NULL); status_t OpenConfirm(uint32* stateSeq); inline status_t PutFH(); inline status_t PutRootFH();