diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 607df773de..68ed4e775d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -24,7 +24,9 @@ Inode::Inode() : fAttrCacheExpire(0), fCache(NULL), - fFileCache(NULL) + fFileCache(NULL), + fWriteCookie(NULL), + fWriteDirty(false) { mutex_init(&fAttrCacheLock, NULL); } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 692bfec298..30e0623d6e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -31,6 +31,8 @@ public: inline FileSystem* GetFileSystem() const; inline void* FileCache(); + inline OpenFileCookie* WriteCookie(); + inline void SetWriteCookie(OpenFileCookie* cookie); status_t GetChangeInfo(uint64* change); @@ -116,6 +118,9 @@ protected: DirectoryCache* fCache; void* fFileCache; + OpenFileCookie* fWriteCookie; + + bool fWriteDirty; }; @@ -165,5 +170,19 @@ Inode::FileCache() } +inline OpenFileCookie* +Inode::WriteCookie() +{ + return fWriteCookie; +} + + +inline void +Inode::SetWriteCookie(OpenFileCookie* cookie) +{ + fWriteCookie = cookie; +} + + #endif // INODE_H diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index c1f6bf86ab..df49273f99 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -384,6 +384,8 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, uint64 fileSize; const char* buffer = reinterpret_cast(_buffer); + fWriteDirty = true; + while (size < *_length) { do { RPC::Server* serv = fFileSystem->Server(); @@ -460,6 +462,9 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, status_t Inode::Commit() { + if (!fWriteDirty) + return B_OK; + do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); 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 b1d0bd61e6..fd0307b282 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -221,6 +221,7 @@ nfs4_read_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, OpenFileCookie* cookie = reinterpret_cast(_cookie); status_t result; + size_t totalRead = 0; bool eof = false; for (size_t i = 0; i < count && !eof; i++) { size_t bytesLeft = vecs[i].iov_len; @@ -232,12 +233,15 @@ nfs4_read_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, if (result != B_OK) return result; + totalRead += bytesRead; pos += bytesRead; buffer += bytesRead; bytesLeft -= bytesRead; } while (bytesLeft > 0 && !eof); } + *_numBytes = totalRead; + return B_OK; } @@ -247,21 +251,12 @@ nfs4_write_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, const iovec* vecs, size_t count, size_t* _numBytes) { Inode* inode = reinterpret_cast(vnode->private_node); - bool freeCookie = false; OpenFileCookie* cookie = reinterpret_cast(_cookie); if (cookie == NULL) { - cookie = new OpenFileCookie; + cookie = inode->WriteCookie(); if (cookie == NULL) - return B_NO_MEMORY; - - status_t result = inode->Open(O_WRONLY, cookie); - if (result != B_OK) { - delete cookie; - return result; - } - - freeCookie = true; + return B_BAD_VALUE; } status_t result; @@ -274,13 +269,8 @@ nfs4_write_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, size_t bytesWritten = min_c(ioSize, bytesLeft); result = inode->Write(cookie, pos, buffer, &bytesWritten); - if (result != B_OK) { - if (freeCookie) { - inode->Close(cookie); - delete cookie; - } + if (result != B_OK) return result; - } bytesLeft -= bytesWritten; pos += bytesWritten; @@ -288,11 +278,6 @@ nfs4_write_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, } while (bytesLeft > 0); } - if (freeCookie) { - inode->Close(cookie); - delete cookie; - } - return B_OK; } @@ -326,7 +311,11 @@ static status_t nfs4_fsync(fs_volume* volume, fs_vnode* vnode) { Inode* inode = reinterpret_cast(vnode->private_node); - return file_cache_sync(inode->FileCache()); + status_t result = file_cache_sync(inode->FileCache()); + if (result != B_OK) + return result; + + return inode->Commit(); } @@ -473,6 +462,10 @@ nfs4_free_cookie(fs_volume* volume, fs_vnode* vnode, void* _cookie) OpenFileCookie* cookie = reinterpret_cast(_cookie); file_cache_sync(inode->FileCache()); inode->Commit(); + + if (inode->WriteCookie() == cookie) + inode->SetWriteCookie(NULL); + inode->Close(cookie); delete cookie; @@ -520,6 +513,7 @@ nfs4_write(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos, if (result != B_OK) return result; + inode->SetWriteCookie(cookie); return file_cache_write(inode->FileCache(), cookie, pos, _buffer, length); }