nfs4: Return delegation before open upgrade

This commit is contained in:
Pawel Dziepak
2012-08-06 18:14:55 +02:00
parent 2c36184f19
commit cde3994e69
8 changed files with 79 additions and 14 deletions
@@ -26,12 +26,9 @@ Delegation::Delegation(const OpenDelegationData& data, Inode* inode,
status_t
Delegation::GiveUp(bool truncate)
{
if (!truncate) {
if (!truncate)
fInode->SyncAndCommit(true);
// TODO: claim locks
}
ReturnDelegation();
return B_OK;
@@ -23,8 +23,6 @@ public:
Delegation(const OpenDelegationData& data, Inode* inode,
uint64 clientID);
// TODO: locks
status_t GiveUp(bool truncate = false);
inline Inode* GetInode();
+28 -2
View File
@@ -139,6 +139,9 @@ Inode::~Inode()
status_t
Inode::RevalidateFileCache()
{
if (fDelegation != NULL)
return B_OK;
uint64 change;
status_t result = GetChangeInfo(&change);
if (result != B_OK)
@@ -153,8 +156,7 @@ Inode::RevalidateFileCache()
if (result != B_OK)
return result;
file_cache_sync(fFileCache);
Commit();
SyncAndCommit(true);
file_cache_delete(fFileCache);
fFileCache = file_cache_create(fFileSystem->DevId(), ID(), st.st_size);
@@ -760,6 +762,12 @@ void
Inode::SetDelegation(Delegation* delegation)
{
WriteLocker _(fDelegationLock);
fMetaCache.InvalidateStat();
struct stat st;
Stat(&st);
fMetaCache.LockValid();
fDelegation = delegation;
fOpenState->AcquireReference();
fOpenState->fDelegation = delegation;
@@ -773,6 +781,24 @@ Inode::RecallDelegation(bool truncate)
WriteLocker _(fDelegationLock);
if (fDelegation == NULL)
return;
ReturnDelegation(truncate);
}
void
Inode::RecallReadDelegation()
{
WriteLocker _(fDelegationLock);
if (fDelegation == NULL || fDelegation->Type() != OPEN_DELEGATE_READ)
return;
ReturnDelegation(false);
}
void
Inode::ReturnDelegation(bool truncate)
{
fMetaCache.UnlockValid();
fDelegation->GiveUp(truncate);
fFileSystem->RemoveDelegation(fDelegation);
@@ -36,6 +36,7 @@ public:
void SetDelegation(Delegation* delegation);
void RecallDelegation(bool truncate = false);
void RecallReadDelegation();
status_t LookUp(const char* name, ino_t* id);
@@ -93,6 +94,8 @@ protected:
int perms, OpenState* state,
OpenDelegationData* data);
void ReturnDelegation(bool truncate);
status_t ReadDirUp(struct dirent* de, uint32 pos,
uint32 size);
status_t FillDirEntry(struct dirent* de, ino_t id,
@@ -95,12 +95,12 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
status_t
Inode::Open(int mode, OpenFileCookie* cookie)
{
MutexLocker _(fStateLock);
MutexLocker locker(fStateLock);
OpenDelegationData data;
data.fType = OPEN_DELEGATE_NONE;
if (fOpenState == NULL) {
// TODO: revalidate cache
RevalidateFileCache();
OpenState* state = new OpenState;
if (state == NULL)
@@ -114,16 +114,28 @@ Inode::Open(int mode, OpenFileCookie* cookie)
fFileSystem->AddOpenFile(state);
fOpenState = state;
locker.Unlock();
} else {
fOpenState->AcquireReference();
locker.Unlock();
int newMode = mode & O_RWMASK;
int oldMode = fOpenState->fMode & O_RWMASK;
if (oldMode != newMode && oldMode != O_RDWR) {
if (oldMode == O_RDONLY)
RecallReadDelegation();
status_t result = OpenFile(fOpenState, O_RDWR, &data);
if (result != B_OK)
if (result != B_OK) {
locker.Lock();
if (fOpenState->ReleaseReference() == 1) {
fFileSystem->RemoveOpenFile(fOpenState);
fOpenState = NULL;
}
return result;
}
fOpenState->fMode = O_RDWR;
}
fOpenState->AcquireReference();
}
cookie->fOpenState = fOpenState;
@@ -12,7 +12,8 @@
MetadataCache::MetadataCache()
:
fExpire(0)
fExpire(0),
fForceValid(false)
{
mutex_init(&fLock, NULL);
}
@@ -28,7 +29,7 @@ status_t
MetadataCache::GetStat(struct stat* st)
{
MutexLocker _(fLock);
if (fExpire > time(NULL)) {
if (fForceValid || fExpire > time(NULL)) {
// Do not touch other members of struct stat
st->st_size = fStatCache.st_size;
st->st_mode = fStatCache.st_mode;
@@ -97,3 +98,26 @@ MetadataCache::SetAccess(uid_t uid, uint32 allowed)
fAccessCache.Insert(uid, entry);
}
status_t
MetadataCache::LockValid()
{
MutexLocker _(fLock);
if (fForceValid || fExpire > time(NULL)) {
fForceValid = true;
return B_OK;
}
return B_ERROR;
}
void
MetadataCache::UnlockValid()
{
MutexLocker _(fLock);
fExpire = time(NULL) + kExpirationTime;
fForceValid = false;
}
@@ -32,6 +32,9 @@ public:
status_t GetAccess(uid_t uid, uint32* allowed);
void SetAccess(uid_t uid, uint32 allowed);
status_t LockValid();
void UnlockValid();
inline void InvalidateStat();
inline void InvalidateAccess();
@@ -41,6 +44,7 @@ public:
private:
struct stat fStatCache;
time_t fExpire;
bool fForceValid;
AVLTreeMap<uid_t, AccessEntry> fAccessCache;
@@ -332,6 +332,7 @@ NFS4Server::CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply)
delegation->GetInode()->RecallDelegation(truncate);
reply->Recall(B_OK);
return B_OK;
}