added 3 changesets to branch 'refs/remotes/pdziepak-github/nfs4' old head: 8568341ae61b9ecdd5f96b6167c5eb5589a20ed1 new head: e422d059c8b56324f663ad5d2f611cfa109643e8 ---------------------------------------------------------------------------- 7c6cdb8: nfs4: Fix node removal dee0fd8: nfs4: Update FileInfo at rename e422d05: nfs4: Properly handle NFS4ERR_DELAY during node rename [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 12 files changed, 112 insertions(+), 89 deletions(-) .../kernel/file_systems/nfs4/DirectoryCache.cpp | 22 +----- src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp | 34 ++++++++- src/add-ons/kernel/file_systems/nfs4/FileInfo.h | 4 +- src/add-ons/kernel/file_systems/nfs4/Inode.cpp | 58 ++++------------ src/add-ons/kernel/file_systems/nfs4/Inode.h | 5 +- .../kernel/file_systems/nfs4/InodeRegular.cpp | 12 +--- src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h | 7 ++ src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp | 14 ++-- src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h | 2 +- .../kernel/file_systems/nfs4/NFS4Object.cpp | 3 +- .../kernel/file_systems/nfs4/ReplyInterpreter.cpp | 8 ++- .../kernel/file_systems/nfs4/kernel_interface.cpp | 32 +++++++-- ############################################################################ Commit: 7c6cdb836049521a65ae47018e15020b1701dc5c Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Fri Aug 17 00:51:20 2012 UTC nfs4: Fix node removal ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 29f9cb7..2ff488e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -266,7 +266,7 @@ Inode::Link(Inode* dir, const char* name) status_t -Inode::Remove(const char* name, FileType type) +Inode::Remove(const char* name, FileType type, ino_t* id) { MemoryDeleter nameDeleter; if (type == NF4NAMEDATTR) { @@ -298,6 +298,8 @@ Inode::Remove(const char* name, FileType type) } fFileSystem->Root()->MakeInfoInvalid(); + if (id != NULL) + *id = FileIdToInoT(fileID); if (type == NF4NAMEDATTR) { notify_attribute_changed(fFileSystem->DevId(), ID(), name, diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 3815e97..6c9e1fc 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -57,7 +57,8 @@ public: int mode); status_t Link(Inode* dir, const char* name); - status_t Remove(const char* name, FileType type); + status_t Remove(const char* name, FileType type, + ino_t* id); static status_t Rename(Inode* from, Inode* to, const char* fromName, const char* toName, bool attribute = false); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 1a617ff..236d377 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -303,6 +303,13 @@ enum Errors { NFS4ERR_ISDIR = 21, NFS4ERR_INVAL = 22, NFS4ERR_FBIG = 27, + NFS4ERR_NOSPC = 28, + NFS4ERR_ROFS = 30, + NFS4ERR_MLINK = 31, + NFS4ERR_NAMETOOLONG = 63, + NFS4ERR_NOTEMPTY = 66, + NFS4ERR_DQUOT = 69, + NFS4ERR_STALE = 70, NFS4ERR_BADHANDLE = 10001, NFS4ERR_BAD_COOKIE = 10003, NFS4ERR_NOTSUPP = 10004, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 43ae3fe..3ae8de5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -824,13 +824,12 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo, else req.Nverify(&attr, 1); - req.PutFH(fInfo.fHandle); - if (type != NF4NAMEDATTR) { Attribute idAttr[] = { FATTR4_FILEID }; req.GetAttr(idAttr, sizeof(idAttr) / sizeof(Attribute)); } + req.PutFH(fInfo.fHandle); req.Remove(name); status_t result = request.Send(); @@ -859,8 +858,6 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo, if (result != B_OK) return result; - reply.PutFH(); - if (type != NF4NAMEDATTR) { AttrValue* values; uint32 count; @@ -875,6 +872,7 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo, delete[] values; } + reply.PutFH(); return reply.Remove(&changeInfo->fBefore, &changeInfo->fAfter, changeInfo->fAtomic); } while (true); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index e24abce..918c44f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -110,10 +110,11 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, } return false; - // FileHandle has expired or is invalid + // File Handle has expired, is invalid or the node has been deleted case NFS4ERR_NOFILEHANDLE: case NFS4ERR_BADHANDLE: case NFS4ERR_FHEXPIRED: + case NFS4ERR_STALE: if (fInfo.UpdateFileHandles(fFileSystem) == B_OK) return true; return false; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index bf4f4dd..4ed2023 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -829,13 +829,19 @@ ReplyInterpreter::_NFS4ErrorToHaiku(uint32 x) case NFS4ERR_INVAL: return B_BAD_VALUE; case NFS4ERR_FBIG: return B_FILE_TOO_LARGE; case NFS4ERR_NOTSUPP: return B_UNSUPPORTED; + case NFS4ERR_ROFS: return B_READ_ONLY_DEVICE; + case NFS4ERR_NAMETOOLONG: return B_NAME_TOO_LONG; + case NFS4ERR_NOTEMPTY: return B_DIRECTORY_NOT_EMPTY; // ... case NFS4ERR_DELAY: case NFS4ERR_DENIED: case NFS4ERR_LOCKED: case NFS4ERR_GRACE: return B_WOULD_BLOCK; - case NFS4ERR_FHEXPIRED: return B_ENTRY_NOT_FOUND; + + case NFS4ERR_STALE: + case NFS4ERR_FHEXPIRED: + return B_FILE_NOT_FOUND; // ... default: return B_ERROR; } 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 a675138..c2e4b6a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -413,7 +413,13 @@ static status_t nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name) { Inode* inode = reinterpret_cast<Inode*>(dir->private_node); - return inode->Remove(name, NF4REG); + + ino_t id; + status_t result = inode->Remove(name, NF4REG, &id); + if (result != B_OK) + return result; + + return remove_vnode(volume, id); } @@ -607,7 +613,11 @@ static status_t nfs4_remove_dir(fs_volume* volume, fs_vnode* parent, const char* name) { Inode* inode = reinterpret_cast<Inode*>(parent->private_node); - return inode->Remove(name, NF4DIR); + ino_t id; + status_t result = inode->Remove(name, NF4DIR, &id); + if (result != B_OK) + return result; + return remove_vnode(volume, id); } @@ -826,7 +836,7 @@ static status_t nfs4_remove_attr(fs_volume* volume, fs_vnode* vnode, const char* name) { Inode* inode = reinterpret_cast<Inode*>(vnode->private_node); - return inode->Remove(name, NF4NAMEDATTR); + return inode->Remove(name, NF4NAMEDATTR, NULL); } ############################################################################ Commit: dee0fd8348ec064654517af747c9554c993eed4f Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Fri Aug 17 01:13:02 2012 UTC nfs4: Update FileInfo at rename ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp index 370a337..9798386 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp @@ -267,27 +267,11 @@ DirectoryCache::NotifyChanges(DirectoryCacheSnapshot* oldSnapshot, FileInfo fi; fi.fFileId = newCurrent->fNode; fi.fParent = fInode->fInfo.fHandle; - fi.fName = strdup(newCurrent->fName); - if (fi.fName == NULL) + status_t result = fi.CreateName(fInode->fInfo.fPath, + newCurrent->fName); + if (result != B_OK) break; - if (fInode->fInfo.fPath != NULL) { - size_t pathLength = strlen(newCurrent->fName) + 2 + - strlen(fInode->fInfo.fPath); - char* path = reinterpret_cast<char*>(pathLength); - if (path == NULL) - break; - - strcpy(path, fInode->fInfo.fPath); - strcat(path, "/"); - strcat(path, newCurrent->fName); - fi.fPath = path; - } else { - fi.fPath = strdup(newCurrent->fName); - if (fi.fPath == NULL) - break; - } - fInode->GetFileSystem()->InoIdMap()->AddEntry(fi, Inode::FileIdToInoT(newCurrent->fNode), true); } while (false); diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp index 9ff0e49..b33eaa4 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp @@ -47,6 +47,38 @@ FileInfo::ParsePath(RequestBuilder& req, uint32& count, const char* _path) status_t +FileInfo::CreateName(const char* dirPath, const char* name) +{ + free(const_cast<char*>(fName)); + fName = strdup(name); + if (fName == NULL) + return B_NO_MEMORY; + + if (dirPath != NULL) { + char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 + + strlen(dirPath))); + if (path == NULL) + return B_NO_MEMORY; + + strcpy(path, dirPath); + strcat(path, "/"); + strcat(path, name); + + free(const_cast<char*>(fPath)); + fPath = path; + } else { + free(const_cast<char*>(fPath)); + fPath = strdup(name); + } + + if (fPath == NULL) + return B_NO_MEMORY; + + return B_OK; +} + + +status_t FileInfo::UpdateFileHandles(FileSystem* fs) { Request request(fs->Server(), fs); @@ -56,7 +88,7 @@ FileInfo::UpdateFileHandles(FileSystem* fs) uint32 lookupCount = 0; status_t result; -dprintf("%s %s\n", fs->Path(), fPath); + result = ParsePath(req, lookupCount, fs->Path()); if (result != B_OK) return result; diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h index ecacc0c..4182dcc 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h @@ -55,8 +55,10 @@ struct FileInfo { status_t UpdateFileHandles(FileSystem* fs); - static status_t ParsePath(RequestBuilder& req, uint32& count, + static status_t ParsePath(RequestBuilder& req, uint32& count, const char* _path); + + status_t CreateName(const char* dirPath, const char* name); }; struct FileSystemId { diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 2ff488e..d52409d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -226,26 +226,9 @@ Inode::Link(Inode* dir, const char* name) FileInfo fi = fInfo; fi.fParent = dir->fInfo.fHandle; - free(const_cast<char*>(fi.fName)); - fi.fName = strdup(name); - if (fi.fName == NULL) - return B_NO_MEMORY; - - if (fInfo.fPath != NULL) { - char* path = reinterpret_cast<char*>(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; - } else { - fi.fPath = strdup(name); - if (fi.fPath == NULL) - return B_NO_MEMORY; - } + result = fi.CreateName(fInfo.fPath, name); + if (result != B_OK) + return result; fFileSystem->InoIdMap()->AddEntry(fi, fInfo.fFileId); @@ -315,7 +298,7 @@ Inode::Remove(const char* name, FileType type, ino_t* id) status_t Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName, - bool attribute) + bool attribute, ino_t* id) { if (from->fFileSystem != to->fFileSystem) return B_DONT_DO_THAT; @@ -342,8 +325,8 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName, ChangeInfo fromChange, toChange; uint64 fileID; - status_t result = NFS4Inode::Rename(from, to, fromName, toName, &fromChange, - &toChange, &fileID, attribute); + status_t result = NFS4Inode::RenameNode(from, to, fromName, toName, + &fromChange, &toChange, &fileID, attribute); if (result != B_OK) return result; @@ -360,6 +343,9 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName, cache->Unlock(); } + if (id != NULL) + *id = FileIdToInoT(fileID); + cache = attribute ? to->fAttrCache : to->fCache; if (cache->Lock() == B_OK) { if (toChange.fAtomic @@ -828,25 +814,9 @@ Inode::ChildAdded(const char* name, uint64 fileID, fi.fFileId = fileID; fi.fHandle = fileHandle; fi.fParent = fInfo.fHandle; - fi.fName = strdup(name); - if (fi.fName == NULL) - return B_NO_MEMORY; - - if (fInfo.fPath != NULL) { - char* path = reinterpret_cast<char*>(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; - } else { - fi.fPath = strdup(name); - if (fi.fPath == NULL) - return B_NO_MEMORY; - } + status_t result = fi.CreateName(fInfo.fPath, name); + if (result != B_OK) + return result; 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 6c9e1fc..6a89c94 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -58,10 +58,10 @@ public: status_t Link(Inode* dir, const char* name); status_t Remove(const char* name, FileType type, - ino_t* id); + ino_t* id = NULL); static status_t Rename(Inode* from, Inode* to, const char* fromName, const char* toName, - bool attribute = false); + bool attribute = false, ino_t* id = NULL); status_t Stat(struct stat* st, OpenAttrCookie* attr = NULL); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index b677477..756d49e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -38,17 +38,7 @@ Inode::CreateState(const char* name, int mode, int perms, OpenState* state, fi.fFileId = fileID; fi.fHandle = handle; fi.fParent = fInfo.fHandle; - fi.fName = strdup(name); - - if (fInfo.fPath != NULL) { - char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 + - strlen(fInfo.fPath))); - strcpy(path, fInfo.fPath); - strcat(path, "/"); - strcat(path, name); - fi.fPath = path; - } else - fi.fPath = strdup(name); + fi.CreateName(fInfo.fPath, name); fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID)); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 3ae8de5..fa50569 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -329,7 +329,7 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, uint32 attrCount) status_t -NFS4Inode::Rename(Inode* from, Inode* to, const char* fromName, +NFS4Inode::RenameNode(Inode* from, Inode* to, const char* fromName, const char* toName, ChangeInfo* fromChange, ChangeInfo* toChange, uint64* fileID, bool attribute) { diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index cd3c461..4aff688 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -36,7 +36,7 @@ protected: status_t Link(Inode* dir, const char* name, ChangeInfo* changeInfo); - static status_t Rename(Inode* from, Inode* to, const char* fromName, + static status_t RenameNode(Inode* from, Inode* to, const char* fromName, const char* toName, ChangeInfo* fromChange, ChangeInfo* toChange, uint64* fileID, bool attribute = false); 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 c2e4b6a..9958fa0 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -429,7 +429,21 @@ nfs4_rename(fs_volume* volume, fs_vnode* fromDir, const char* fromName, { Inode* fromInode = reinterpret_cast<Inode*>(fromDir->private_node); Inode* toInode = reinterpret_cast<Inode*>(toDir->private_node); - return Inode::Rename(fromInode, toInode, fromName, toName); + + ino_t id; + status_t result = Inode::Rename(fromInode, toInode, fromName, toName, false, + &id); + if (result != B_OK) + return result; + + Inode* child; + result = get_vnode(volume, id, reinterpret_cast<void**>(&child)); + if (result == B_OK) { + child->fInfo.fParent = toInode->fInfo.fHandle; + child->fInfo.CreateName(toInode->fInfo.fPath, toName); + } + + return B_OK; } ############################################################################ Commit: e422d059c8b56324f663ad5d2f611cfa109643e8 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Fri Aug 17 01:32:57 2012 UTC nfs4: Properly handle NFS4ERR_DELAY during node rename ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index fa50569..dd59008 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -374,6 +374,12 @@ NFS4Inode::RenameNode(Inode* from, Inode* to, const char* fromName, continue; } + // need to wait + if (reply.NFS4Error() == NFS4ERR_DELAY) { + snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); + continue; + } + reply.PutFH(); reply.SaveFH(); reply.PutFH();