nfs4: Revalidate cache before locks
This commit is contained in:
@@ -29,6 +29,7 @@ Inode::Inode()
|
|||||||
fWriteDirty(false)
|
fWriteDirty(false)
|
||||||
{
|
{
|
||||||
mutex_init(&fAttrCacheLock, NULL);
|
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);
|
req.PutFH(inode->fInfo.fHandle);
|
||||||
|
|
||||||
Attribute attr[] = { FATTR4_TYPE, FATTR4_SIZE, FATTR4_FSID,
|
Attribute attr[] = { FATTR4_TYPE, FATTR4_CHANGE, FATTR4_SIZE,
|
||||||
FATTR4_FILEID };
|
FATTR4_FSID, FATTR4_FILEID };
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
@@ -73,14 +74,14 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
AttrValue* values;
|
AttrValue* values;
|
||||||
uint32 count;
|
uint32 count;
|
||||||
result = reply.GetAttr(&values, &count);
|
result = reply.GetAttr(&values, &count);
|
||||||
if (result != B_OK || count < 3)
|
if (result != B_OK || count < 4)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (fi.fFileId == 0) {
|
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();
|
inode->fInfo.fFileId = fs->AllocFileId();
|
||||||
else
|
else
|
||||||
inode->fInfo.fFileId = values[3].fData.fValue64;
|
inode->fInfo.fFileId = values[4].fData.fValue64;
|
||||||
} else
|
} else
|
||||||
inode->fInfo.fFileId = fi.fFileId;
|
inode->fInfo.fFileId = fi.fFileId;
|
||||||
|
|
||||||
@@ -90,12 +91,15 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
if (inode->fType == NF4DIR)
|
if (inode->fType == NF4DIR)
|
||||||
inode->fCache = new DirectoryCache(inode);
|
inode->fCache = new DirectoryCache(inode);
|
||||||
|
|
||||||
|
// FATTR4_CHANGE is mandatory
|
||||||
|
inode->fChange = values[1].fData.fValue64;
|
||||||
|
|
||||||
// FATTR4_SIZE is mandatory
|
// FATTR4_SIZE is mandatory
|
||||||
size = values[1].fData.fValue64;
|
size = values[2].fData.fValue64;
|
||||||
|
|
||||||
// FATTR4_FSID is mandatory
|
// FATTR4_FSID is mandatory
|
||||||
FileSystemId* fsid =
|
FileSystemId* fsid =
|
||||||
reinterpret_cast<FileSystemId*>(values[2].fData.fPointer);
|
reinterpret_cast<FileSystemId*>(values[3].fData.fPointer);
|
||||||
if (*fsid != fs->FsId()) {
|
if (*fsid != fs->FsId()) {
|
||||||
delete[] values;
|
delete[] values;
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
@@ -121,10 +125,39 @@ Inode::~Inode()
|
|||||||
file_cache_delete(fFileCache);
|
file_cache_delete(fFileCache);
|
||||||
|
|
||||||
delete fCache;
|
delete fCache;
|
||||||
|
mutex_destroy(&fFileCacheLock);
|
||||||
mutex_destroy(&fAttrCacheLock);
|
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
|
status_t
|
||||||
Inode::GetChangeInfo(uint64* change)
|
Inode::GetChangeInfo(uint64* change)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ public:
|
|||||||
inline FileSystem* GetFileSystem() const;
|
inline FileSystem* GetFileSystem() const;
|
||||||
|
|
||||||
inline void* FileCache();
|
inline void* FileCache();
|
||||||
|
status_t RevalidateFileCache();
|
||||||
|
|
||||||
inline OpenFileCookie* WriteCookie();
|
inline OpenFileCookie* WriteCookie();
|
||||||
inline void SetWriteCookie(OpenFileCookie* cookie);
|
inline void SetWriteCookie(OpenFileCookie* cookie);
|
||||||
|
|
||||||
@@ -117,8 +119,11 @@ protected:
|
|||||||
FileSystem* fFileSystem;
|
FileSystem* fFileSystem;
|
||||||
|
|
||||||
DirectoryCache* fCache;
|
DirectoryCache* fCache;
|
||||||
|
|
||||||
|
uint64 fChange;
|
||||||
void* fFileCache;
|
void* fFileCache;
|
||||||
OpenFileCookie* fWriteCookie;
|
OpenFileCookie* fWriteCookie;
|
||||||
|
mutex fFileCacheLock;
|
||||||
|
|
||||||
bool fWriteDirty;
|
bool fWriteDirty;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -429,7 +429,6 @@ nfs4_open(fs_volume* volume, fs_vnode* vnode, int openMode, void** _cookie)
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
|
|
||||||
|
|
||||||
status_t result = inode->Open(openMode, cookie);
|
status_t result = inode->Open(openMode, cookie);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
delete cookie;
|
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);
|
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||||
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
|
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
|
||||||
|
|
||||||
|
inode->RevalidateFileCache();
|
||||||
|
|
||||||
return inode->AcquireLock(cookie, lock, wait);
|
return inode->AcquireLock(cookie, lock, wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,6 +621,10 @@ nfs4_release_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
|
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
|
||||||
|
|
||||||
|
file_cache_sync(inode->FileCache());
|
||||||
|
inode->Commit();
|
||||||
|
|
||||||
if (lock != NULL)
|
if (lock != NULL)
|
||||||
return inode->ReleaseLock(cookie, lock);
|
return inode->ReleaseLock(cookie, lock);
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user