nfs4: Revalidate cache before locks

This commit is contained in:
Pawel Dziepak
2012-08-03 19:37:32 +02:00
parent d4a75b9c9f
commit 13a90e3795
3 changed files with 52 additions and 8 deletions
+40 -7
View File
@@ -29,6 +29,7 @@ Inode::Inode()
fWriteDirty(false)
{
mutex_init(&fAttrCacheLock, NULL);
mutex_init(&fFileCacheLock, NULL);
}
@@ -55,8 +56,8 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
req.PutFH(inode->fInfo.fHandle);
Attribute attr[] = { FATTR4_TYPE, FATTR4_SIZE, FATTR4_FSID,
FATTR4_FILEID };
Attribute attr[] = { FATTR4_TYPE, FATTR4_CHANGE, FATTR4_SIZE,
FATTR4_FSID, FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
status_t result = request.Send();
@@ -73,14 +74,14 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK || count < 3)
if (result != B_OK || count < 4)
return result;
if (fi.fFileId == 0) {
if (count < 4 || values[3].fAttribute != FATTR4_FILEID)
if (count < 5 || values[4].fAttribute != FATTR4_FILEID)
inode->fInfo.fFileId = fs->AllocFileId();
else
inode->fInfo.fFileId = values[3].fData.fValue64;
inode->fInfo.fFileId = values[4].fData.fValue64;
} else
inode->fInfo.fFileId = fi.fFileId;
@@ -90,12 +91,15 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
if (inode->fType == NF4DIR)
inode->fCache = new DirectoryCache(inode);
// FATTR4_CHANGE is mandatory
inode->fChange = values[1].fData.fValue64;
// FATTR4_SIZE is mandatory
size = values[1].fData.fValue64;
size = values[2].fData.fValue64;
// FATTR4_FSID is mandatory
FileSystemId* fsid =
reinterpret_cast<FileSystemId*>(values[2].fData.fPointer);
reinterpret_cast<FileSystemId*>(values[3].fData.fPointer);
if (*fsid != fs->FsId()) {
delete[] values;
return B_ENTRY_NOT_FOUND;
@@ -121,10 +125,39 @@ Inode::~Inode()
file_cache_delete(fFileCache);
delete fCache;
mutex_destroy(&fFileCacheLock);
mutex_destroy(&fAttrCacheLock);
}
status_t
Inode::RevalidateFileCache()
{
uint64 change;
status_t result = GetChangeInfo(&change);
if (result != B_OK)
return result;
MutexLocker _(fFileCacheLock);
if (change == fChange)
return B_OK;
result = _UpdateAttrCache(true);
if (result != B_OK)
return result;
file_cache_sync(fFileCache);
Commit();
file_cache_delete(fFileCache);
fFileCache = file_cache_create(fFileSystem->DevId(), ID(),
fAttrCache.st_size);
change = fChange;
return B_OK;
}
status_t
Inode::GetChangeInfo(uint64* change)
{
@@ -31,6 +31,8 @@ public:
inline FileSystem* GetFileSystem() const;
inline void* FileCache();
status_t RevalidateFileCache();
inline OpenFileCookie* WriteCookie();
inline void SetWriteCookie(OpenFileCookie* cookie);
@@ -117,8 +119,11 @@ protected:
FileSystem* fFileSystem;
DirectoryCache* fCache;
uint64 fChange;
void* fFileCache;
OpenFileCookie* fWriteCookie;
mutex fFileCacheLock;
bool fWriteDirty;
};
@@ -429,7 +429,6 @@ nfs4_open(fs_volume* volume, fs_vnode* vnode, int openMode, void** _cookie)
return B_NO_MEMORY;
*_cookie = cookie;
status_t result = inode->Open(openMode, cookie);
if (result != B_OK)
delete cookie;
@@ -605,6 +604,9 @@ nfs4_acquire_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie,
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
inode->RevalidateFileCache();
return inode->AcquireLock(cookie, lock, wait);
}
@@ -619,6 +621,10 @@ nfs4_release_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie,
return B_OK;
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
file_cache_sync(inode->FileCache());
inode->Commit();
if (lock != NULL)
return inode->ReleaseLock(cookie, lock);
else