diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index e14598c9a4..be69f682c1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -110,6 +110,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo& fi, Inode** _inode) // FATTR4_SIZE is mandatory size = values[2].fData.fValue64; + inode->fMaxFileSize = size; // FATTR4_FSID is mandatory FileSystemId* fsid @@ -170,14 +171,15 @@ Inode::RevalidateFileCache() if (change == fChange) return B_OK; + SyncAndCommit(true); + file_cache_delete(fFileCache); + struct stat st; + fMetaCache.InvalidateStat(); result = Stat(&st); if (result != B_OK) return result; - SyncAndCommit(true); - file_cache_delete(fFileCache); - fFileCache = file_cache_create(fFileSystem->DevId(), ID(), st.st_size); change = fChange; @@ -600,6 +602,9 @@ Inode::WriteStat(const struct stat* st, uint32 mask, OpenAttrCookie* cookie) uint32 i = 0; if ((mask & B_STAT_SIZE) != 0) { + fMaxFileSize = st->st_size; + file_cache_set_size(fFileCache, st->st_size); + attr[i].fAttribute = FATTR4_SIZE; attr[i].fFreePointer = false; attr[i].fData.fValue64 = st->st_size; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index d61907429d..a343f7c60d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -410,26 +410,29 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, ASSERT(_buffer != NULL); ASSERT(_length != NULL); - struct stat st; - status_t result = Stat(&st); - if (result != B_OK) - return result; + if (pos < 0) + pos = 0; + + if ((cookie->fMode & O_RWMASK) == O_RDONLY) + return B_NOT_ALLOWED; if ((cookie->fMode & O_APPEND) != 0) - pos = st.st_size; + pos = fMaxFileSize; - uint64 fileSize = max_c(st.st_size, pos + *_length); - fMaxFileSize = max_c(fMaxFileSize, fileSize); + uint64 fileSize = max_c((off_t)fMaxFileSize, pos + *_length); + if (fileSize > fMaxFileSize) { + status_t result = file_cache_set_size(fFileCache, fileSize); + if (result != B_OK) + return result; + fMaxFileSize = fileSize; + fMetaCache.GrowFile(fMaxFileSize); + } if ((cookie->fMode & O_NOCACHE) != 0) { WriteDirect(cookie, pos, _buffer, _length); Commit(); } - result = file_cache_set_size(fFileCache, fileSize); - if (result != B_OK) - return result; - return file_cache_write(fFileCache, cookie, pos, _buffer, _length); } diff --git a/src/add-ons/kernel/file_systems/nfs4/WorkQueue.cpp b/src/add-ons/kernel/file_systems/nfs4/WorkQueue.cpp index da435bfb43..524b98346d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/WorkQueue.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/WorkQueue.cpp @@ -12,6 +12,8 @@ #include +#define MAX_BUFFER_SIZE (1024 * 1024) + WorkQueue* gWorkQueue = NULL; @@ -152,43 +154,62 @@ WorkQueue::JobIO(IORequestArgs* args) uint64 offset = io_request_offset(args->fRequest); uint64 length = io_request_length(args->fRequest); - char* buffer = reinterpret_cast(malloc(length)); + size_t bufferLength = min_c(MAX_BUFFER_SIZE, length); + char* buffer = reinterpret_cast(malloc(bufferLength)); if (buffer == NULL) { notify_io_request(args->fRequest, B_NO_MEMORY); args->fInode->EndAIOOp(); return; } - bool eof = false; - uint64 size = 0; status_t result; if (io_request_is_write(args->fRequest)) { if (offset + length > args->fInode->MaxFileSize()) length = args->fInode->MaxFileSize() - offset; - result = read_from_io_request(args->fRequest, buffer, length); + uint64 position = 0; do { - size_t bytesWritten = length - size; - result = args->fInode->WriteDirect(NULL, offset + size, - buffer + size, &bytesWritten); - size += bytesWritten; - } while (size < length && result == B_OK); + size_t size = 0; + size_t thisBufferLength = min_c(bufferLength, length - position); + + result = read_from_io_request(args->fRequest, buffer, + thisBufferLength); + + while (size < thisBufferLength && result == B_OK) { + size_t bytesWritten = thisBufferLength - size; + result = args->fInode->WriteDirect(NULL, + offset + position + size, buffer + size, &bytesWritten); + size += bytesWritten; + } + + position += thisBufferLength; + } while (position < length && result == B_OK); } else { + bool eof = false; + uint64 position = 0; do { - size_t bytesRead = length - size; - result = args->fInode->ReadDirect(NULL, offset + size, buffer, - &bytesRead, &eof); - if (result != B_OK) - break; + size_t size = 0; + size_t thisBufferLength = min_c(bufferLength, length - position); - result = write_to_io_request(args->fRequest, buffer, bytesRead); - if (result != B_OK) - break; + do { + size_t bytesRead = thisBufferLength - size; + result = args->fInode->ReadDirect(NULL, + offset + position + size, buffer + size, &bytesRead, &eof); + if (result != B_OK) + break; - size += bytesRead; - } while (size < length && result == B_OK && !eof); - + result = write_to_io_request(args->fRequest, buffer + size, + bytesRead); + if (result != B_OK) + break; + + size += bytesRead; + } while (size < length && result == B_OK && !eof); + + position += thisBufferLength; + } while (position < length && result == B_OK && !eof); } + free(buffer); notify_io_request(args->fRequest, result); 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 2672ae0b2a..522a9eb477 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -691,7 +691,10 @@ nfs4_read_stat(fs_volume* volume, fs_vnode* vnode, struct stat* stat) if (inode == NULL) return B_ENTRY_NOT_FOUND; - return inode->Stat(stat); + status_t result = inode->Stat(stat); + if (inode->GetOpenState() != NULL) + stat->st_size = inode->MaxFileSize(); + return result; }