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:
Pawel Dziepak
2013-04-17 19:29:54 +02:00
parent f6c0237372
commit 3ef8e34c0a
4 changed files with 67 additions and 35 deletions
@@ -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;
}