nfs4: Basic data cache implementation

This commit is contained in:
Pawel Dziepak
2012-07-27 01:53:54 +02:00
parent b5162ff580
commit 0bc98afd43
6 changed files with 160 additions and 33 deletions
+22 -7
View File
@@ -12,6 +12,7 @@
#include <ctype.h>
#include <string.h>
#include <fs_cache.h>
#include <NodeMonitor.h>
#include "IdMap.h"
@@ -22,7 +23,8 @@
Inode::Inode()
:
fAttrCacheExpire(0),
fCache(NULL)
fCache(NULL),
fFileCache(NULL)
{
mutex_init(&fAttrCacheLock, NULL);
}
@@ -43,6 +45,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
inode->fInfo = fi;
inode->fFileSystem = fs;
uint64 size;
do {
RPC::Server* serv = fs->Server();
Request request(serv);
@@ -50,7 +53,8 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
req.PutFH(inode->fInfo.fHandle);
Attribute attr[] = { FATTR4_TYPE, FATTR4_FSID, FATTR4_FILEID };
Attribute attr[] = { FATTR4_TYPE, FATTR4_SIZE, FATTR4_FSID,
FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
status_t result = request.Send();
@@ -67,14 +71,14 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK || count < 2)
if (result != B_OK || count < 3)
return result;
if (fi.fFileId == 0) {
if (count < 3 || values[2].fAttribute != FATTR4_FILEID)
if (count < 4 || values[3].fAttribute != FATTR4_FILEID)
inode->fInfo.fFileId = fs->AllocFileId();
else
inode->fInfo.fFileId = values[2].fData.fValue64;
inode->fInfo.fFileId = values[3].fData.fValue64;
} else
inode->fInfo.fFileId = fi.fFileId;
@@ -84,9 +88,12 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
if (inode->fType == NF4DIR)
inode->fCache = new DirectoryCache(inode);
// FATTR4_SIZE is mandatory
size = values[1].fData.fValue64;
// FATTR4_FSID is mandatory
FileSystemId* fsid =
reinterpret_cast<FileSystemId*>(values[1].fData.fPointer);
reinterpret_cast<FileSystemId*>(values[2].fData.fPointer);
if (*fsid != fs->FsId()) {
delete[] values;
return B_ENTRY_NOT_FOUND;
@@ -96,13 +103,21 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
*_inode = inode;
return B_OK;
break;
} while (true);
if (inode->fType == NF4REG)
inode->fFileCache = file_cache_create(fs->DevId(), inode->ID(), size);
return B_OK;
}
Inode::~Inode()
{
if (fFileCache != NULL)
file_cache_delete(fFileCache);
delete fCache;
mutex_destroy(&fAttrCacheLock);
}
+11 -1
View File
@@ -30,6 +30,8 @@ public:
inline const char* Name() const;
inline FileSystem* GetFileSystem() const;
inline void* FileCache();
status_t GetChangeInfo(uint64* change);
status_t LookUp(const char* name, ino_t* id);
@@ -52,7 +54,7 @@ public:
status_t Open(int mode, OpenFileCookie* cookie);
status_t Close(OpenFileCookie* cookie);
status_t Read(OpenFileCookie* cookie, off_t pos,
void* buffer, size_t* length);
void* buffer, size_t* length, bool* eof);
status_t Write(OpenFileCookie* cookie, off_t pos,
const void* buffer, size_t *_length);
@@ -111,6 +113,7 @@ protected:
FileSystem* fFileSystem;
DirectoryCache* fCache;
void* fFileCache;
};
@@ -153,5 +156,12 @@ Inode::GetFileSystem() const
}
inline void*
Inode::FileCache()
{
return fFileCache;
}
#endif // INODE_H
@@ -11,6 +11,7 @@
#include <string.h>
#include <fs_cache.h>
#include <NodeMonitor.h>
#include "IdMap.h"
@@ -330,13 +331,14 @@ Inode::Close(OpenFileCookie* cookie)
status_t
Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length,
bool* eof)
{
bool eof = false;
*eof = false;
uint32 size = 0;
uint32 len = 0;
while (size < *_length && !eof) {
while (size < *_length && !*eof) {
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
@@ -357,7 +359,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
reply.PutFH();
result = reply.Read(reinterpret_cast<char*>(buffer) + size, &len,
&eof);
eof);
if (result != B_OK)
return result;
@@ -16,7 +16,8 @@
RootInode::RootInode()
:
fInfoCacheExpire(0)
fInfoCacheExpire(0),
fIOSize(0)
{
mutex_init(&fInfoCacheLock, NULL);
}
@@ -90,29 +91,30 @@ RootInode::_UpdateInfo(bool force)
next++;
}
uint64 io_size = LONGLONG_MAX;
uint64 ioSize = LONGLONG_MAX;
if (count >= next && values[next].fAttribute == FATTR4_MAXREAD) {
io_size = min_c(io_size, values[next].fData.fValue64);
ioSize = min_c(ioSize, values[next].fData.fValue64);
next++;
}
if (count >= next && values[next].fAttribute == FATTR4_MAXWRITE) {
io_size = min_c(io_size, values[next].fData.fValue64);
ioSize = min_c(ioSize, values[next].fData.fValue64);
next++;
}
if (io_size == LONGLONG_MAX)
io_size = 32768;
fInfoCache.io_size = io_size;
fInfoCache.block_size = io_size;
if (ioSize == LONGLONG_MAX)
ioSize = 32768;
fInfoCache.io_size = ioSize;
fInfoCache.block_size = ioSize;
fIOSize = ioSize;
if (count >= next && values[next].fAttribute == FATTR4_SPACE_FREE) {
fInfoCache.free_blocks = values[next].fData.fValue64 / io_size;
fInfoCache.free_blocks = values[next].fData.fValue64 / ioSize;
next++;
}
if (count >= next && values[next].fAttribute == FATTR4_SPACE_TOTAL) {
fInfoCache.total_blocks = values[next].fData.fValue64 / io_size;
fInfoCache.total_blocks = values[next].fData.fValue64 / ioSize;
next++;
}
@@ -22,6 +22,8 @@ public:
status_t ReadInfo(struct fs_info* info);
inline void MakeInfoInvalid();
inline uint32 IOSize();
bool ProbeMigration();
status_t GetLocations(AttrValue** attr);
@@ -30,6 +32,8 @@ private:
mutex fInfoCacheLock;
time_t fInfoCacheExpire;
uint32 fIOSize;
status_t _UpdateInfo(bool force = false);
};
@@ -42,5 +46,14 @@ RootInode::MakeInfoInvalid()
}
inline uint32
RootInode::IOSize()
{
if (fIOSize == 0)
_UpdateInfo(true);
return fIOSize;
}
#endif // ROOTINODE_H
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <fs_cache.h>
#include <fs_interface.h>
#include "Connection.h"
@@ -212,6 +213,59 @@ nfs4_remove_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter)
}
static status_t
nfs4_read_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<Inode*>(vnode->private_node);
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
status_t result;
bool eof = false;
for (size_t i = 0; i < count && !eof; i++) {
size_t bytesLeft = vecs[i].iov_len;
char* buffer = reinterpret_cast<char*>(vecs[i].iov_base);
do {
size_t bytesRead = bytesLeft;
result = inode->Read(cookie, pos, buffer, &bytesRead, &eof);
if (result != B_OK)
return result;
pos += bytesRead;
buffer += bytesRead;
bytesLeft -= bytesRead;
} while (bytesLeft > 0 && !eof);
}
return B_OK;
}
static status_t
nfs4_write_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos,
const iovec* vecs, size_t count, size_t* _numBytes)
{
return B_OK;
}
static status_t
nfs4_io(fs_volume* volume, fs_vnode* vnode, void* cookie, io_request* request)
{
// no asynchronous calls yet
return B_UNSUPPORTED;
}
static status_t
nfs4_get_file_map(fs_volume* volume, fs_vnode* vnode, off_t _offset,
size_t size, struct file_io_vec* vecs, size_t* _count)
{
return B_ERROR;
}
static status_t
nfs4_set_flags(fs_volume* volume, fs_vnode* vnode, void* _cookie, int flags)
{
@@ -224,7 +278,7 @@ nfs4_set_flags(fs_volume* volume, fs_vnode* vnode, void* _cookie, int flags)
static status_t
nfs4_fsync(fs_volume* volume, fs_vnode* vnode)
{
// Currently, there is no cache and all writes are FILE_SYNC4
// Currently all writes are FILE_SYNC4
return B_OK;
}
@@ -378,7 +432,7 @@ nfs4_free_cookie(fs_volume* volume, fs_vnode* vnode, void* _cookie)
static status_t
nfs4_read(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
nfs4_read(fs_volume* volume, fs_vnode* vnode, void* cookie, off_t pos,
void* buffer, size_t* length)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
@@ -389,15 +443,13 @@ nfs4_read(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
if (inode->Type() == S_IFLNK)
return B_BAD_VALUE;
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
return inode->Read(cookie, pos, buffer, length);
return file_cache_read(inode->FileCache(), cookie, pos, buffer, length);
}
static status_t
nfs4_write(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
const void* buffer, size_t* length)
const void* _buffer, size_t* length)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
@@ -409,7 +461,40 @@ nfs4_write(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
return inode->Write(cookie, pos, buffer, length);
struct stat stat;
status_t result = inode->Stat(&stat);
if (result != B_OK)
return result;
uint64 fileSize = max_c(stat.st_size, pos + *length);
result = file_cache_set_size(inode->FileCache(), fileSize);
if (result != B_OK)
return result;
result = file_cache_write(inode->FileCache(), cookie, pos, _buffer,
length);
if (result != B_OK)
return result;
uint32 ioSize = inode->GetFileSystem()->Root()->IOSize();
size_t bytesLeft = *length;
const char* buffer = reinterpret_cast<const char*>(_buffer);
do {
size_t bytesWritten = min_c(ioSize, bytesLeft);
result = inode->Write(cookie, pos, buffer, &bytesWritten);
if (result != B_OK)
break;
bytesLeft -= bytesWritten;
pos += bytesWritten;
buffer += bytesWritten;
} while (bytesLeft > 0);
if (bytesLeft == *length)
return result;
*length = *length - bytesLeft;
return B_OK;
}
@@ -582,13 +667,13 @@ fs_vnode_ops gNFSv4VnodeOps = {
/* VM file access */
NULL, // can_page()
NULL, // read_pages()
NULL, // write_pages()
nfs4_read_pages,
nfs4_write_pages,
NULL, // io()
nfs4_io,
NULL, // cancel_io()
NULL, // get_file_map()
nfs4_get_file_map,
NULL, // ioctl()
nfs4_set_flags,