nfs4: Return delegation before open upgrade
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user