From f7c35cf464752e44ce966c9a12d61882f5387611 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Thu, 9 Aug 2012 02:37:04 +0200 Subject: [PATCH] nfs4: Add attribute directory related hooks --- src/add-ons/kernel/file_systems/nfs4/Cookie.h | 2 + .../file_systems/nfs4/DirectoryCache.cpp | 35 ++++++++--- .../kernel/file_systems/nfs4/DirectoryCache.h | 3 +- .../kernel/file_systems/nfs4/FileInfo.h | 2 + .../kernel/file_systems/nfs4/Inode.cpp | 4 ++ src/add-ons/kernel/file_systems/nfs4/Inode.h | 3 + .../kernel/file_systems/nfs4/InodeDir.cpp | 59 ++++++++++++++----- .../kernel/file_systems/nfs4/NFS4Defs.h | 1 + .../kernel/file_systems/nfs4/NFS4Inode.cpp | 36 ++++++++++- .../kernel/file_systems/nfs4/NFS4Inode.h | 2 + .../file_systems/nfs4/ReplyInterpreter.h | 8 +++ .../file_systems/nfs4/RequestBuilder.cpp | 17 ++++++ .../kernel/file_systems/nfs4/RequestBuilder.h | 1 + .../file_systems/nfs4/kernel_interface.cpp | 56 ++++++++++++++++-- 14 files changed, 199 insertions(+), 30 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.h b/src/add-ons/kernel/file_systems/nfs4/Cookie.h index 1fd8c9c29a..0f57b822bb 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.h +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.h @@ -92,6 +92,8 @@ struct OpenDirCookie : public Cookie { NameCacheEntry* fCurrent; bool fEOF; + bool fAttrDir; + ~OpenDirCookie(); }; diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp index 2e571664e3..eb8ca9ab8b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.cpp @@ -10,6 +10,7 @@ #include "DirectoryCache.h" #include +#include #include "Inode.h" @@ -46,10 +47,11 @@ DirectoryCacheSnapshot::~DirectoryCacheSnapshot() } -DirectoryCache::DirectoryCache(Inode* inode) +DirectoryCache::DirectoryCache(Inode* inode, bool attr) : fDirectoryCache(NULL), fInode(inode), + fAttrDir(attr), fTrashed(true) { mutex_init(&fLock, NULL); @@ -114,8 +116,12 @@ DirectoryCache::AddEntry(const char* name, ino_t node, bool created) fDirectoryCache->fEntries.Add(entry); } - return entry_cache_add(fInode->GetFileSystem()->DevId(), fInode->ID(), name, - node); + if (!fAttrDir) { + return entry_cache_add(fInode->GetFileSystem()->DevId(), fInode->ID(), + name, node); + } + + return B_OK; } void @@ -153,7 +159,10 @@ DirectoryCache::RemoveEntry(const char* name) } } - entry_cache_remove(fInode->GetFileSystem()->DevId(), fInode->ID(), name); + if (!fAttrDir) { + entry_cache_remove(fInode->GetFileSystem()->DevId(), fInode->ID(), + name); + } } @@ -231,8 +240,13 @@ DirectoryCache::NotifyChanges(DirectoryCacheSnapshot* oldSnapshot, } if (!found) { - notify_entry_created(fInode->GetFileSystem()->DevId(), - fInode->ID(), newCurrent->fName, newCurrent->fNode); + if (fAttrDir) { + notify_attribute_changed(fInode->GetFileSystem()->DevId(), + fInode->ID(), newCurrent->fName, B_ATTR_CREATED); + } else { + notify_entry_created(fInode->GetFileSystem()->DevId(), + fInode->ID(), newCurrent->fName, newCurrent->fNode); + } } else oldSnapshot->fEntries.Remove(prev, oldCurrent); @@ -243,8 +257,13 @@ DirectoryCache::NotifyChanges(DirectoryCacheSnapshot* oldSnapshot, oldCurrent = oldIt.Next(); while (oldCurrent != NULL) { - notify_entry_removed(fInode->GetFileSystem()->DevId(), fInode->ID(), - oldCurrent->fName, oldCurrent->fNode); + if (fAttrDir) { + notify_attribute_changed(fInode->GetFileSystem()->DevId(), + fInode->ID(), newCurrent->fName, B_ATTR_REMOVED); + } else { + notify_entry_removed(fInode->GetFileSystem()->DevId(), fInode->ID(), + oldCurrent->fName, oldCurrent->fNode); + } oldCurrent = oldIt.Next(); } } diff --git a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h index 3f22e47c4b..ac152f0158 100644 --- a/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h +++ b/src/add-ons/kernel/file_systems/nfs4/DirectoryCache.h @@ -37,7 +37,7 @@ struct DirectoryCacheSnapshot : public KernelReferenceable { class DirectoryCache : public DoublyLinkedListLinkImpl { public: - DirectoryCache(Inode* inode); + DirectoryCache(Inode* inode, bool attr = false); ~DirectoryCache(); inline status_t Lock(); @@ -76,6 +76,7 @@ private: Inode* fInode; + bool fAttrDir; bool fTrashed; mutex fLock; diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h index 5cd0f2af3c..47c377ddc8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h @@ -44,6 +44,8 @@ struct FileInfo { const char* fName; const char* fPath; + FileHandle fAttrDir; + inline FileInfo(); inline ~FileInfo(); inline FileInfo(const FileInfo& fi); diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index be97c45558..805ba5ae9c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -24,6 +24,7 @@ Inode::Inode() : fMetaCache(this), fCache(NULL), + fAttrCache(NULL), fDelegation(NULL), fFileCache(NULL), fMaxFileSize(0), @@ -93,6 +94,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode) if (inode->fType == NF4DIR) inode->fCache = new DirectoryCache(inode); + inode->fAttrCache = new DirectoryCache(inode, true); // FATTR4_CHANGE is mandatory inode->fChange = values[1].fData.fValue64; @@ -131,6 +133,8 @@ Inode::~Inode() file_cache_delete(fFileCache); delete fCache; + delete fAttrCache; + mutex_destroy(&fStateLock); mutex_destroy(&fFileCacheLock); rw_lock_destroy(&fDelegationLock); diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 35dc4d8bbe..03a03ace65 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -82,6 +82,8 @@ public: status_t ReadDir(void* buffer, uint32 size, uint32* count, OpenDirCookie* cookie); + status_t OpenAttrDir(OpenDirCookie* cookie); + status_t TestLock(OpenFileCookie* cookie, struct flock* lock); status_t AcquireLock(OpenFileCookie* cookie, @@ -124,6 +126,7 @@ private: MetadataCache fMetaCache; DirectoryCache* fCache; + DirectoryCache* fAttrCache; rw_lock fDelegationLock; Delegation* fDelegation; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index c303678c9b..b4d1a9e0d8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -39,11 +39,36 @@ Inode::OpenDir(OpenDirCookie* cookie) cookie->fSnapshot = NULL; cookie->fCurrent = NULL; cookie->fEOF = false; + cookie->fAttrDir = false; return B_OK; } +status_t +Inode::OpenAttrDir(OpenDirCookie* cookie) +{ + cookie->fFileSystem = fFileSystem; + cookie->fSpecial = 0; + cookie->fSnapshot = NULL; + cookie->fCurrent = NULL; + cookie->fEOF = false; + cookie->fAttrDir = true; + + if (fInfo.fAttrDir.fSize == 0) { + FileHandle handle; + + status_t result = NFS4Inode::OpenAttrDir(&handle); + if (result != B_OK) + return result; + + fInfo.fAttrDir = handle; + } + + return B_OK; +} + + status_t Inode::FillDirEntry(struct dirent* de, ino_t id, const char* name, uint32 pos, uint32 size) @@ -152,10 +177,13 @@ Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot, continue; ino_t id; - if (dirents[i].fAttrCount == 2) - id = FileIdToInoT(dirents[i].fAttrs[1].fData.fValue64); - else - id = FileIdToInoT(fFileSystem->AllocFileId()); + if (!cookie->fAttrDir) { + if (dirents[i].fAttrCount == 2) + id = FileIdToInoT(dirents[i].fAttrs[1].fData.fValue64); + else + id = FileIdToInoT(fFileSystem->AllocFileId()); + } else + id = 0; NameCacheEntry* entry = new NameCacheEntry(dirents[i].fName, id); if (entry == NULL || entry->fName == NULL) { @@ -188,29 +216,30 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, } status_t result; + DirectoryCache* cache = cookie->fAttrDir ? fAttrCache : fCache; if (cookie->fSnapshot == NULL) { fFileSystem->Revalidator().Lock(); - if (fCache->Lock() != B_OK) { - fCache->ResetAndLock(); + if (cache->Lock() != B_OK) { + cache->ResetAndLock(); } else { - fFileSystem->Revalidator().RemoveDirectory(fCache); + fFileSystem->Revalidator().RemoveDirectory(cache); } - cookie->fSnapshot = fCache->GetSnapshot(); + cookie->fSnapshot = cache->GetSnapshot(); if (cookie->fSnapshot == NULL) { uint64 change; result = GetDirSnapshot(&cookie->fSnapshot, cookie, &change); if (result != B_OK) { - fCache->Unlock(); + cache->Unlock(); fFileSystem->Revalidator().Unlock(); return result; } - fCache->ValidateChangeInfo(change); - fCache->SetSnapshot(cookie->fSnapshot); + cache->ValidateChangeInfo(change); + cache->SetSnapshot(cookie->fSnapshot); } cookie->fSnapshot->AcquireReference(); - fFileSystem->Revalidator().AddDirectory(fCache); - fCache->Unlock(); + fFileSystem->Revalidator().AddDirectory(cache); + cache->Unlock(); fFileSystem->Revalidator().Unlock(); } @@ -219,7 +248,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint32 i = 0; bool overflow = false; - if (cookie->fSpecial == 0 && i < *_count) { + if (cookie->fSpecial == 0 && i < *_count && !cookie->fAttrDir) { struct dirent* de = reinterpret_cast(buffer + pos); status_t result; @@ -235,7 +264,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, return result; } - if (cookie->fSpecial == 1 && i < *_count) { + if (cookie->fSpecial == 1 && i < *_count && !cookie->fAttrDir) { struct dirent* de = reinterpret_cast(buffer + pos); status_t result; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index e60b45cd1e..1a617ff67f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -46,6 +46,7 @@ enum Opcode { OpLookUpUp = 16, OpNverify = 17, OpOpen = 18, + OpOpenAttrDir = 19, OpOpenConfirm = 20, OpPutFH = 22, OpPutRootFH = 24, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 24bb38d269..aca6514b6f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -817,7 +817,10 @@ NFS4Inode::ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie, Request request(serv); RequestBuilder& req = request.Builder(); - req.PutFH(fInfo.fHandle); + if (cookie->fAttrDir) + req.PutFH(fInfo.fAttrDir); + else + req.PutFH(fInfo.fHandle); Attribute dirAttr[] = { FATTR4_CHANGE }; if (*change == 0) @@ -875,6 +878,37 @@ NFS4Inode::ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie, } +status_t +NFS4Inode::OpenAttrDir(FileHandle* handle) +{ + do { + RPC::Server* serv = fFileSystem->Server(); + Request request(serv); + RequestBuilder& req = request.Builder(); + + req.PutFH(fInfo.fHandle); + req.OpenAttrDir(true); + req.GetFH(); + + status_t result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter& reply = request.Reply(); + + if (HandleErrors(reply.NFS4Error(), serv)) + continue; + + reply.PutFH(); + result = reply.OpenAttrDir(); + if (result != B_OK) + return result; + + return reply.GetFH(handle); + } while (true); +} + + status_t NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* type, uint64* position, uint64* length, bool& conflict) diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index f340a42b3c..d7cd36669a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -68,6 +68,8 @@ protected: OpenDirCookie* cookie, bool* eof, uint64* change, uint64* dirCookie, uint64* dirCookieVerf); + status_t OpenAttrDir(FileHandle* handle); + status_t TestLock(OpenFileCookie* cookie, LockType* type, uint64* position, uint64* length, bool& conflict); status_t AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 986fcd8a7c..b630b8ffb9 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -84,6 +84,7 @@ public: status_t Open(uint32* id, uint32* seq, bool* confirm, OpenDelegationData* delegData, ChangeInfo* changeInfo = NULL); + inline status_t OpenAttrDir(); status_t OpenConfirm(uint32* stateSeq); inline status_t PutFH(); inline status_t PutRootFH(); @@ -172,6 +173,13 @@ ReplyInterpreter::LookUpUp() } +inline status_t +ReplyInterpreter::OpenAttrDir() +{ + return _OperationError(OpOpenAttrDir); +} + + inline status_t ReplyInterpreter::Nverify() { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 08f4dff29c..04add4c0e4 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -445,6 +445,23 @@ RequestBuilder::OpenConfirm(uint32 seq, const uint32* id, uint32 stateSeq) } +status_t +RequestBuilder::OpenAttrDir(bool create) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpOpenAttrDir); + fRequest->Stream().AddBoolean(create); + + fOpCount++; + + return B_OK; +} + + status_t RequestBuilder::PutFH(const FileHandle& fh) { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index d958d6d05a..9ef417413b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -56,6 +56,7 @@ public: uint32 count = 0, bool excl = false, OpenDelegation delegType = OPEN_DELEGATE_NONE); + status_t OpenAttrDir(bool create); status_t OpenConfirm(uint32 seq, const uint32* id, uint32 stateSeq); status_t PutFH(const FileHandle& fh); 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 a146e0674e..d62a9a4e98 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -610,6 +610,52 @@ nfs4_rewind_dir(fs_volume* volume, fs_vnode* vnode, void* _cookie) } +static status_t +nfs4_open_attr_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie) +{ + OpenDirCookie* cookie = new(std::nothrow) OpenDirCookie; + if (cookie == NULL) + return B_NO_MEMORY; + *_cookie = cookie; + + Inode* inode = reinterpret_cast(vnode->private_node); + status_t result = inode->OpenAttrDir(cookie); + if (result != B_OK) + delete cookie; + + return result; +} + + +static status_t +nfs4_close_attr_dir(fs_volume* volume, fs_vnode* vnode, void* cookie) +{ + return nfs4_close_attr_dir(volume, vnode, cookie); +} + + +static status_t +nfs4_free_attr_dir_cookie(fs_volume* volume, fs_vnode* vnode, void* cookie) +{ + return nfs4_free_dir_cookie(volume, vnode, cookie); +} + + +static status_t +nfs4_read_attr_dir(fs_volume* volume, fs_vnode* vnode, void* cookie, + struct dirent* buffer, size_t bufferSize, uint32* _num) +{ + return nfs4_read_dir(volume, vnode, cookie, buffer, bufferSize, _num); +} + + +static status_t +nfs4_rewind_attr_dir(fs_volume* volume, fs_vnode* vnode, void* cookie) +{ + return nfs4_rewind_attr_dir(volume, vnode, cookie); +} + + static status_t nfs4_test_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie, struct flock* lock) @@ -774,11 +820,11 @@ fs_vnode_ops gNFSv4VnodeOps = { nfs4_rewind_dir, /* attribute directory operations */ - NULL, // open_attr_dir - NULL, // close_attr_dir - NULL, // free_attr_dir_cookie - NULL, // read_attr_dir - NULL, // rewind_attr_dir + nfs4_open_attr_dir, + nfs4_close_attr_dir, + nfs4_free_attr_dir_cookie, + nfs4_read_attr_dir, + nfs4_rewind_attr_dir, /* attribute operations */ NULL, // create_attr