nfs4: fix few issues related with file caches
* update metadata cache when writing to cache * do not limit size of a io request * minor checks in Inode::Write
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <io_requests.h>
|
||||
|
||||
|
||||
#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<char*>(malloc(length));
|
||||
size_t bufferLength = min_c(MAX_BUFFER_SIZE, length);
|
||||
char* buffer = reinterpret_cast<char*>(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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user