nfs4: Return delegation before open upgrade
This commit is contained in:
@@ -26,12 +26,9 @@ Delegation::Delegation(const OpenDelegationData& data, Inode* inode,
|
|||||||
status_t
|
status_t
|
||||||
Delegation::GiveUp(bool truncate)
|
Delegation::GiveUp(bool truncate)
|
||||||
{
|
{
|
||||||
if (!truncate) {
|
if (!truncate)
|
||||||
fInode->SyncAndCommit(true);
|
fInode->SyncAndCommit(true);
|
||||||
|
|
||||||
// TODO: claim locks
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnDelegation();
|
ReturnDelegation();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ public:
|
|||||||
Delegation(const OpenDelegationData& data, Inode* inode,
|
Delegation(const OpenDelegationData& data, Inode* inode,
|
||||||
uint64 clientID);
|
uint64 clientID);
|
||||||
|
|
||||||
// TODO: locks
|
|
||||||
|
|
||||||
status_t GiveUp(bool truncate = false);
|
status_t GiveUp(bool truncate = false);
|
||||||
|
|
||||||
inline Inode* GetInode();
|
inline Inode* GetInode();
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ Inode::~Inode()
|
|||||||
status_t
|
status_t
|
||||||
Inode::RevalidateFileCache()
|
Inode::RevalidateFileCache()
|
||||||
{
|
{
|
||||||
|
if (fDelegation != NULL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
uint64 change;
|
uint64 change;
|
||||||
status_t result = GetChangeInfo(&change);
|
status_t result = GetChangeInfo(&change);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
@@ -153,8 +156,7 @@ Inode::RevalidateFileCache()
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
file_cache_sync(fFileCache);
|
SyncAndCommit(true);
|
||||||
Commit();
|
|
||||||
file_cache_delete(fFileCache);
|
file_cache_delete(fFileCache);
|
||||||
|
|
||||||
fFileCache = file_cache_create(fFileSystem->DevId(), ID(), st.st_size);
|
fFileCache = file_cache_create(fFileSystem->DevId(), ID(), st.st_size);
|
||||||
@@ -760,6 +762,12 @@ void
|
|||||||
Inode::SetDelegation(Delegation* delegation)
|
Inode::SetDelegation(Delegation* delegation)
|
||||||
{
|
{
|
||||||
WriteLocker _(fDelegationLock);
|
WriteLocker _(fDelegationLock);
|
||||||
|
|
||||||
|
fMetaCache.InvalidateStat();
|
||||||
|
struct stat st;
|
||||||
|
Stat(&st);
|
||||||
|
fMetaCache.LockValid();
|
||||||
|
|
||||||
fDelegation = delegation;
|
fDelegation = delegation;
|
||||||
fOpenState->AcquireReference();
|
fOpenState->AcquireReference();
|
||||||
fOpenState->fDelegation = delegation;
|
fOpenState->fDelegation = delegation;
|
||||||
@@ -773,6 +781,24 @@ Inode::RecallDelegation(bool truncate)
|
|||||||
WriteLocker _(fDelegationLock);
|
WriteLocker _(fDelegationLock);
|
||||||
if (fDelegation == NULL)
|
if (fDelegation == NULL)
|
||||||
return;
|
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);
|
fDelegation->GiveUp(truncate);
|
||||||
fFileSystem->RemoveDelegation(fDelegation);
|
fFileSystem->RemoveDelegation(fDelegation);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
|
|
||||||
void SetDelegation(Delegation* delegation);
|
void SetDelegation(Delegation* delegation);
|
||||||
void RecallDelegation(bool truncate = false);
|
void RecallDelegation(bool truncate = false);
|
||||||
|
void RecallReadDelegation();
|
||||||
|
|
||||||
status_t LookUp(const char* name, ino_t* id);
|
status_t LookUp(const char* name, ino_t* id);
|
||||||
|
|
||||||
@@ -93,6 +94,8 @@ protected:
|
|||||||
int perms, OpenState* state,
|
int perms, OpenState* state,
|
||||||
OpenDelegationData* data);
|
OpenDelegationData* data);
|
||||||
|
|
||||||
|
void ReturnDelegation(bool truncate);
|
||||||
|
|
||||||
status_t ReadDirUp(struct dirent* de, uint32 pos,
|
status_t ReadDirUp(struct dirent* de, uint32 pos,
|
||||||
uint32 size);
|
uint32 size);
|
||||||
status_t FillDirEntry(struct dirent* de, ino_t id,
|
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
|
status_t
|
||||||
Inode::Open(int mode, OpenFileCookie* cookie)
|
Inode::Open(int mode, OpenFileCookie* cookie)
|
||||||
{
|
{
|
||||||
MutexLocker _(fStateLock);
|
MutexLocker locker(fStateLock);
|
||||||
|
|
||||||
OpenDelegationData data;
|
OpenDelegationData data;
|
||||||
data.fType = OPEN_DELEGATE_NONE;
|
data.fType = OPEN_DELEGATE_NONE;
|
||||||
if (fOpenState == NULL) {
|
if (fOpenState == NULL) {
|
||||||
// TODO: revalidate cache
|
RevalidateFileCache();
|
||||||
|
|
||||||
OpenState* state = new OpenState;
|
OpenState* state = new OpenState;
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
@@ -114,16 +114,28 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
|
|
||||||
fFileSystem->AddOpenFile(state);
|
fFileSystem->AddOpenFile(state);
|
||||||
fOpenState = state;
|
fOpenState = state;
|
||||||
|
locker.Unlock();
|
||||||
} else {
|
} else {
|
||||||
|
fOpenState->AcquireReference();
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
int newMode = mode & O_RWMASK;
|
int newMode = mode & O_RWMASK;
|
||||||
int oldMode = fOpenState->fMode & O_RWMASK;
|
int oldMode = fOpenState->fMode & O_RWMASK;
|
||||||
if (oldMode != newMode && oldMode != O_RDWR) {
|
if (oldMode != newMode && oldMode != O_RDWR) {
|
||||||
|
if (oldMode == O_RDONLY)
|
||||||
|
RecallReadDelegation();
|
||||||
|
|
||||||
status_t result = OpenFile(fOpenState, O_RDWR, &data);
|
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;
|
return result;
|
||||||
|
}
|
||||||
fOpenState->fMode = O_RDWR;
|
fOpenState->fMode = O_RDWR;
|
||||||
}
|
}
|
||||||
fOpenState->AcquireReference();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cookie->fOpenState = fOpenState;
|
cookie->fOpenState = fOpenState;
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
MetadataCache::MetadataCache()
|
MetadataCache::MetadataCache()
|
||||||
:
|
:
|
||||||
fExpire(0)
|
fExpire(0),
|
||||||
|
fForceValid(false)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, NULL);
|
mutex_init(&fLock, NULL);
|
||||||
}
|
}
|
||||||
@@ -28,7 +29,7 @@ status_t
|
|||||||
MetadataCache::GetStat(struct stat* st)
|
MetadataCache::GetStat(struct stat* st)
|
||||||
{
|
{
|
||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
if (fExpire > time(NULL)) {
|
if (fForceValid || fExpire > time(NULL)) {
|
||||||
// Do not touch other members of struct stat
|
// Do not touch other members of struct stat
|
||||||
st->st_size = fStatCache.st_size;
|
st->st_size = fStatCache.st_size;
|
||||||
st->st_mode = fStatCache.st_mode;
|
st->st_mode = fStatCache.st_mode;
|
||||||
@@ -97,3 +98,26 @@ MetadataCache::SetAccess(uid_t uid, uint32 allowed)
|
|||||||
fAccessCache.Insert(uid, entry);
|
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);
|
status_t GetAccess(uid_t uid, uint32* allowed);
|
||||||
void SetAccess(uid_t uid, uint32 allowed);
|
void SetAccess(uid_t uid, uint32 allowed);
|
||||||
|
|
||||||
|
status_t LockValid();
|
||||||
|
void UnlockValid();
|
||||||
|
|
||||||
inline void InvalidateStat();
|
inline void InvalidateStat();
|
||||||
inline void InvalidateAccess();
|
inline void InvalidateAccess();
|
||||||
|
|
||||||
@@ -41,6 +44,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct stat fStatCache;
|
struct stat fStatCache;
|
||||||
time_t fExpire;
|
time_t fExpire;
|
||||||
|
bool fForceValid;
|
||||||
|
|
||||||
AVLTreeMap<uid_t, AccessEntry> fAccessCache;
|
AVLTreeMap<uid_t, AccessEntry> fAccessCache;
|
||||||
|
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ NFS4Server::CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply)
|
|||||||
delegation->GetInode()->RecallDelegation(truncate);
|
delegation->GetInode()->RecallDelegation(truncate);
|
||||||
|
|
||||||
reply->Recall(B_OK);
|
reply->Recall(B_OK);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user