nfs4: Do not open too much files on server

This commit is contained in:
Pawel Dziepak
2012-08-04 03:30:01 +02:00
parent 7efb4c9b49
commit eeabdab19f
15 changed files with 412 additions and 237 deletions
@@ -13,9 +13,6 @@
#include "Request.h"
vint64 OpenFileCookie::fLastOwnerId = 0;
LockOwner::LockOwner(uint32 owner)
:
fSequence(0),
@@ -164,7 +161,7 @@ OpenFileCookie::GetLockOwner(uint32 owner)
if (current == NULL)
return NULL;
current->fClientId = fClientId;
current->fClientId = fClientID;
current->fNext = fLockOwners;
if (fLockOwners != NULL)
fLockOwners->fPrev = current;
+5 -10
View File
@@ -12,6 +12,7 @@
#include <SupportDefs.h>
#include "FileSystem.h"
#include "OpenState.h"
struct LockOwner {
@@ -70,19 +71,13 @@ struct Cookie {
};
struct OpenFileCookie : public Cookie {
uint64 fClientId;
uint64 fClientID;
OpenState* fReadState;
OpenState* fWriteState;
uint32 fMode;
FileInfo fInfo;
uint32 fStateId[3];
uint32 fStateSeq;
uint32 fSequence;
uint64 fOwnerId;
static vint64 fLastOwnerId;
LockInfo* fLocks;
mutex fLocksLock;
+7 -20
View File
@@ -24,9 +24,11 @@ Inode::Inode()
:
fCache(NULL),
fFileCache(NULL),
fWriteCookie(NULL),
fWriteState(NULL),
fReadState(NULL),
fWriteDirty(false)
{
mutex_init(&fStateLock, NULL);
mutex_init(&fFileCacheLock, NULL);
}
@@ -123,6 +125,7 @@ Inode::~Inode()
file_cache_delete(fFileCache);
delete fCache;
mutex_destroy(&fStateLock);
mutex_destroy(&fFileCacheLock);
}
@@ -479,22 +482,10 @@ status_t
Inode::WriteStat(const struct stat* st, uint32 mask)
{
status_t result;
OpenFileCookie* cookie = NULL;
AttrValue attr[6];
uint32 i = 0;
if ((mask & B_STAT_SIZE) != 0) {
delete cookie;
cookie = new OpenFileCookie;
if (cookie == NULL)
return B_NO_MEMORY;
result = Open(O_WRONLY, cookie);
if (result != B_OK) {
delete cookie;
return result;
}
attr[i].fAttribute = FATTR4_SIZE;
attr[i].fFreePointer = false;
attr[i].fData.fValue64 = st->st_size;
@@ -538,12 +529,9 @@ Inode::WriteStat(const struct stat* st, uint32 mask)
i++;
}
result = NFS4Inode::WriteStat(cookie, attr, i);
if ((mask & B_STAT_SIZE) != 0) {
Close(cookie);
delete cookie;
}
MutexLocker stateLocker(fStateLock);
result = NFS4Inode::WriteStat(fWriteState, attr, i);
stateLocker.Unlock();
fMetaCache.InvalidateStat();
if ((mask & B_STAT_MODE) != 0 || (mask & B_STAT_UID) != 0
@@ -689,7 +677,6 @@ Inode::ReleaseAllLocks(OpenFileCookie* cookie)
MutexLocker _(cookie->fLocksLock);
LockInfo* linfo = cookie->fLocks;
while (linfo != NULL) {
MutexLocker ownerLocker(linfo->fOwner->fLock);
NFS4Inode::ReleaseLock(cookie, linfo);
cookie->RemoveLock(linfo, NULL);
cookie->DeleteLock(linfo);
+8 -18
View File
@@ -11,6 +11,7 @@
#include "MetadataCache.h"
#include "NFS4Inode.h"
#include "OpenState.h"
class Inode : public NFS4Inode {
@@ -27,9 +28,6 @@ public:
inline void* FileCache();
status_t RevalidateFileCache();
inline OpenFileCookie* WriteCookie();
inline void SetWriteCookie(OpenFileCookie* cookie);
status_t LookUp(const char* name, ino_t* id);
status_t Access(int mode);
@@ -75,6 +73,9 @@ public:
protected:
Inode();
status_t CreateState(const char* name, int mode,
int perms, OpenState* state);
status_t ReadDirUp(struct dirent* de, uint32 pos,
uint32 size);
status_t FillDirEntry(struct dirent* de, ino_t id,
@@ -99,9 +100,12 @@ protected:
uint64 fChange;
void* fFileCache;
OpenFileCookie* fWriteCookie;
mutex fFileCacheLock;
OpenState* fWriteState;
OpenState* fReadState;
mutex fStateLock;
bool fWriteDirty;
};
@@ -152,19 +156,5 @@ Inode::FileCache()
}
inline OpenFileCookie*
Inode::WriteCookie()
{
return fWriteCookie;
}
inline void
Inode::SetWriteCookie(OpenFileCookie* cookie)
{
fWriteCookie = cookie;
}
#endif // INODE_H
@@ -20,23 +20,16 @@
status_t
Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
ino_t* id)
{
cookie->fMode = mode;
cookie->fSequence = 0;
cookie->fLocks = NULL;
Inode::CreateState(const char* name, int mode, int perms, OpenState* state) {
uint64 fileID;
FileHandle handle;
ChangeInfo changeInfo;
status_t result = CreateFile(name, mode, perms, cookie, &changeInfo,
status_t result = CreateFile(name, mode, perms, state, &changeInfo,
&fileID, &handle);
if (result != B_OK)
return result;
*id = FileIdToInoT(fileID);
FileInfo fi;
fi.fFileId = fileID;
fi.fHandle = handle;
@@ -50,7 +43,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
strcat(path, name);
fi.fPath = path;
fFileSystem->InoIdMap()->AddEntry(fi, *id);
fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID));
if (fCache->Lock() == B_OK) {
if (changeInfo.fAtomic
@@ -62,8 +55,59 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
fCache->Unlock();
}
state->fFileSystem = fFileSystem;
state->fInfo = fi;
return B_OK;
}
status_t
Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
ino_t* id)
{
cookie->fMode = mode;
cookie->fLocks = NULL;
MutexLocker _(fStateLock);
int openMode = mode & O_RWMASK;
if (openMode == O_WRONLY || openMode == O_RDWR) {
OpenState* state = new OpenState;
status_t result = CreateState(name, O_WRONLY, perms, state);
if (result != B_OK)
return result;
fWriteState = state;
*id = FileIdToInoT(cookie->fWriteState->fInfo.fFileId);
cookie->fWriteState = fWriteState;
}
if (openMode == O_RDONLY || openMode == O_RDWR) {
OpenState* state = new OpenState;
state->fInfo = fInfo;
state->fFileSystem = fFileSystem;
status_t result;
if (openMode == O_RDWR)
result = OpenFile(state, O_RDONLY);
else
result = CreateState(name, O_RDONLY, perms, state);
if (result != B_OK) {
if (fWriteState != NULL)
if (fWriteState->ReleaseReference() == 1)
fWriteState = NULL;
return result;
}
fReadState = state;
*id = FileIdToInoT(cookie->fReadState->fInfo.fFileId);
cookie->fReadState = fReadState;
}
cookie->fFileSystem = fFileSystem;
cookie->fInfo = fi;
cookie->fClientID = fFileSystem->NFSServer()->ClientId();
fFileSystem->AddOpenFile(cookie);
fFileSystem->Root()->MakeInfoInvalid();
@@ -75,15 +119,59 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
status_t
Inode::Open(int mode, OpenFileCookie* cookie)
{
cookie->fFileSystem = fFileSystem;
cookie->fInfo = fInfo;
cookie->fMode = mode;
cookie->fSequence = 0;
cookie->fLocks = NULL;
MutexLocker _(fStateLock);
int openMode = mode & O_RWMASK;
status_t result = OpenFile(cookie, mode);
if (result != B_OK)
return result;
if (openMode == O_WRONLY || openMode == O_RDWR) {
if (fWriteState == NULL) {
OpenState* state = new OpenState;
if (state == NULL)
return B_NO_MEMORY;
state->fInfo = fInfo;
state->fFileSystem = fFileSystem;
status_t result = OpenFile(state, O_WRONLY);
if (result != B_OK)
return result;
fWriteState = state;
} else
fWriteState->AcquireReference();
cookie->fWriteState = fWriteState;
}
if (openMode == O_RDONLY || openMode == O_RDWR) {
if (fReadState == NULL) {
OpenState* state = new OpenState;
if (state == NULL) {
if (fWriteState != NULL)
if (fWriteState->ReleaseReference() == 1)
fWriteState = NULL;
return B_NO_MEMORY;
}
state->fInfo = fInfo;
state->fFileSystem = fFileSystem;
status_t result = OpenFile(state, O_RDONLY);
if (result != B_OK) {
if (fWriteState != NULL)
if (fWriteState->ReleaseReference() == 1)
fWriteState = NULL;
return result;
}
fReadState = state;
} else
fReadState->AcquireReference();
cookie->fReadState = fReadState;
}
cookie->fClientID = fFileSystem->NFSServer()->ClientId();
cookie->fFileSystem = fFileSystem;
cookie->fMode = mode;
cookie->fLocks = NULL;
fFileSystem->AddOpenFile(cookie);
@@ -95,7 +183,17 @@ status_t
Inode::Close(OpenFileCookie* cookie)
{
fFileSystem->RemoveOpenFile(cookie);
return CloseFile(cookie);
MutexLocker _(fStateLock);
if (cookie->fWriteState != NULL)
if (cookie->fWriteState->ReleaseReference() == 1)
fWriteState = NULL;
if (cookie->fReadState != NULL)
if (cookie->fReadState->ReleaseReference() == 1)
fReadState = NULL;
return B_OK;
}
@@ -109,7 +207,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length,
status_t result;
while (size < *_length && !*eof) {
uint32 len = *_length - size;
result = ReadFile(cookie, pos + size, &len,
result = ReadFile(cookie, fReadState, pos + size, &len,
reinterpret_cast<char*>(buffer) + size, eof);
if (result != B_OK) {
if (size == 0)
@@ -138,7 +236,8 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
while (size < *_length) {
uint32 len = *_length - size;
status_t result = WriteFile(cookie, pos + size, &len, buffer + size);
status_t result = WriteFile(cookie, fWriteState, pos + size, &len,
buffer + size);
if (result != B_OK) {
if (size == 0)
return result;
@@ -19,6 +19,7 @@ KernelAddon nfs4 :
NFS4Inode.cpp
NFS4Object.cpp
NFS4Server.cpp
OpenState.cpp
ReplyInterpreter.cpp
Request.cpp
RequestBuilder.cpp
@@ -244,38 +244,6 @@ NFS4Inode::ReadLink(void* buffer, size_t* length)
}
status_t
NFS4Inode::ConfirmOpen(const FileHandle& fh, OpenFileCookie* cookie)
{
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fh);
req.OpenConfirm(cookie->fSequence++, cookie->fStateId,
cookie->fStateSeq);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv))
continue;
reply.PutFH();
result = reply.OpenConfirm(&cookie->fStateSeq);
if (result != B_OK)
return result;
return B_OK;
} while (true);
}
status_t
NFS4Inode::GetStat(AttrValue** values, uint32* count)
{
@@ -309,7 +277,7 @@ NFS4Inode::GetStat(AttrValue** values, uint32* count)
status_t
NFS4Inode::WriteStat(OpenFileCookie* cookie, AttrValue* attrs, uint32 attrCount)
NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, uint32 attrCount)
{
do {
RPC::Server* serv = fFileSystem->Server();
@@ -317,8 +285,8 @@ NFS4Inode::WriteStat(OpenFileCookie* cookie, AttrValue* attrs, uint32 attrCount)
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
if (cookie != NULL)
req.SetAttr(cookie->fStateId, cookie->fStateSeq, attrs, attrCount);
if (state != NULL)
req.SetAttr(state->fStateID, state->fStateSeq, attrs, attrCount);
else
req.SetAttr(NULL, 0, attrs, attrCount);
@@ -414,7 +382,7 @@ NFS4Inode::Rename(Inode* from, Inode* to, const char* fromName,
status_t
NFS4Inode::CreateFile(const char* name, int mode, int perms,
OpenFileCookie* cookie, ChangeInfo* changeInfo, uint64* fileID,
OpenState* state, ChangeInfo* changeInfo, uint64* fileID,
FileHandle* handle)
{
bool confirm;
@@ -422,13 +390,13 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
bool badOwner = false;
do {
cookie->fClientId = fFileSystem->NFSServer()->ClientId();
state->fClientID = fFileSystem->NFSServer()->ClientId();
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
cookie->fOwnerId = atomic_add64(&cookie->fLastOwnerId, 1);
state->fOwnerID = atomic_add64(&state->fLastOwnerID, 1);
req.PutFH(fInfo.fHandle);
@@ -459,8 +427,8 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
i++;
}
req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode),
cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, name, cattr,
req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode),
state->fClientID, OPEN4_CREATE, state->fOwnerID, name, cattr,
i, (mode & O_EXCL) == O_EXCL);
req.GetFH();
@@ -485,7 +453,7 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
reply.PutFH();
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm,
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm,
&changeInfo->fBefore, &changeInfo->fAfter, &changeInfo->fAtomic);
if (result != B_OK)
return result;
@@ -508,26 +476,28 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
break;
} while (true);
state->fOpened = true;
if (confirm)
return ConfirmOpen(*handle, cookie);
return ConfirmOpen(*handle, state);
return B_OK;
}
status_t
NFS4Inode::OpenFile(OpenFileCookie* cookie, int mode)
NFS4Inode::OpenFile(OpenState* state, int mode)
{
bool confirm;
status_t result;
do {
cookie->fClientId = fFileSystem->NFSServer()->ClientId();
state->fClientID = fFileSystem->NFSServer()->ClientId();
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
cookie->fOwnerId = atomic_add64(&cookie->fLastOwnerId, 1);
state->fOwnerID = atomic_add64(&state->fLastOwnerID, 1);
// Since we are opening the file using a pair (parentFH, name) we
// need to check for race conditions.
@@ -556,12 +526,12 @@ NFS4Inode::OpenFile(OpenFileCookie* cookie, int mode)
attr.fAttribute = FATTR4_SIZE;
attr.fFreePointer = false;
attr.fData.fValue64 = 0;
req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode),
cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, fInfo.fName,
req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode),
state->fClientID, OPEN4_CREATE, state->fOwnerID, fInfo.fName,
&attr, 1, false);
} else
req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode),
cookie->fClientId, OPEN4_NOCREATE, cookie->fOwnerId, fInfo.fName);
req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode),
state->fClientID, OPEN4_NOCREATE, state->fOwnerID, fInfo.fName);
result = request.Send();
if (result != B_OK)
@@ -588,22 +558,25 @@ NFS4Inode::OpenFile(OpenFileCookie* cookie, int mode)
}
reply.PutFH();
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm);
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm);
if (result != B_OK)
return result;
break;
} while (true);
state->fOpened = true;
if (confirm)
return ConfirmOpen(fInfo.fHandle, cookie);
return ConfirmOpen(fInfo.fHandle, state);
return B_OK;
}
status_t
NFS4Inode::CloseFile(OpenFileCookie* cookie)
NFS4Inode::ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
uint32* length, void* buffer, bool* eof)
{
do {
RPC::Server* serv = fFileSystem->Server();
@@ -611,34 +584,7 @@ NFS4Inode::CloseFile(OpenFileCookie* cookie)
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.Close(cookie->fSequence++, cookie->fStateId, cookie->fStateSeq);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv, cookie))
continue;
reply.PutFH();
return reply.Close();
} while (true);
}
status_t
NFS4Inode::ReadFile(OpenFileCookie* cookie, uint64 position, uint32* length,
void* buffer, bool* eof)
{
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.Read(cookie->fStateId, cookie->fStateSeq, position, *length);
req.Read(state->fStateID, state->fStateSeq, position, *length);
status_t result = request.Send(cookie);
if (result != B_OK)
@@ -660,9 +606,10 @@ NFS4Inode::ReadFile(OpenFileCookie* cookie, uint64 position, uint32* length,
status_t
NFS4Inode::WriteFile(OpenFileCookie* cookie, uint64 position, uint32* length,
const void* buffer)
NFS4Inode::WriteFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
uint32* length, const void* buffer)
{
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
@@ -670,8 +617,7 @@ NFS4Inode::WriteFile(OpenFileCookie* cookie, uint64 position, uint32* length,
req.PutFH(fInfo.fHandle);
req.Write(cookie->fStateId, cookie->fStateSeq, buffer, position,
*length);
req.Write(state->fStateID, state->fStateSeq, buffer, position, *length);
status_t result = request.Send(cookie);
if (result != B_OK)
@@ -13,6 +13,9 @@
#include <SupportDefs.h>
#include "Cookie.h"
#include "FileInfo.h"
#include "FileSystem.h"
#include "NFS4Object.h"
#include "ReplyInterpreter.h"
@@ -38,19 +41,20 @@ protected:
ChangeInfo* toChange, uint64* fileID);
status_t GetStat(AttrValue** values, uint32* count);
status_t WriteStat(OpenFileCookie* cookie, AttrValue* attrs,
status_t WriteStat(OpenState* state, AttrValue* attrs,
uint32 attrCount);
status_t CreateFile(const char* name, int mode, int perms,
OpenFileCookie* cookie, ChangeInfo* changeInfo,
OpenState* state, ChangeInfo* changeInfo,
uint64* fileID, FileHandle* handle);
status_t OpenFile(OpenFileCookie* cookie, int mode);
status_t CloseFile(OpenFileCookie* cookie);
status_t OpenFile(OpenState* state, int mode);
status_t ReadFile(OpenFileCookie* cookie, uint64 position,
uint32* length, void* buffer, bool* eof);
status_t WriteFile(OpenFileCookie* cookie, uint64 position,
uint32* length, const void* buffer);
status_t ReadFile(OpenFileCookie* cookie, OpenState* state,
uint64 position, uint32* length, void* buffer,
bool* eof);
status_t WriteFile(OpenFileCookie* cookie, OpenState* state,
uint64 position, uint32* length,
const void* buffer);
status_t CreateObject(const char* name, const char* path,
int mode, FileType type, ChangeInfo* changeInfo,
@@ -67,10 +71,6 @@ protected:
status_t AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo,
bool wait);
status_t ReleaseLock(OpenFileCookie* cookie, LockInfo* lockInfo);
status_t ConfirmOpen(const FileHandle& fileHandle,
OpenFileCookie* cookie);
};
@@ -7,7 +7,10 @@
*/
#include "Cookie.h"
#include "FileSystem.h"
#include "NFS4Object.h"
#include "Request.h"
bool
@@ -59,7 +62,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
// server has rebooted, reclaim share and try again
case NFS4ERR_STALE_CLIENTID:
case NFS4ERR_STALE_STATEID:
fFileSystem->NFSServer()->ServerRebooted(cookie->fClientId);
fFileSystem->NFSServer()->ServerRebooted(cookie->fClientID);
return true;
// FileHandle has expired
@@ -77,7 +80,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
// lease has expired
case NFS4ERR_EXPIRED:
if (cookie != NULL) {
fFileSystem->NFSServer()->ClientId(cookie->fClientId, true);
fFileSystem->NFSServer()->ClientId(cookie->fClientID, true);
return true;
}
return false;
@@ -87,3 +90,34 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
}
}
status_t
NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state)
{
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fh);
req.OpenConfirm(state->fSequence++, state->fStateID, state->fStateSeq);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv))
continue;
reply.PutFH();
result = reply.OpenConfirm(&state->fStateSeq);
if (result != B_OK)
return result;
return B_OK;
} while (true);
}
@@ -8,18 +8,21 @@
#ifndef NFS4OBJECT_H
#define NFS4OBJECT_H
#include "Cookie.h"
#include "FileSystem.h"
#include "FileInfo.h"
#include "NFS4Defs.h"
#include "RPCServer.h"
class OpenFileCookie;
class OpenState;
class NFS4Object {
public:
bool HandleErrors(uint32 nfs4Error, RPC::Server* serv,
OpenFileCookie* cookie = NULL);
protected:
status_t ConfirmOpen(const FileHandle& fileHandle, OpenState* state);
FileInfo fInfo;
FileSystem* fFileSystem;
};
@@ -59,6 +59,7 @@ NFS4Server::ServerRebooted(uint64 clientId)
while (fs != NULL) {
OpenFileCookie* current = fs->OpenFilesLock();
while (current != NULL) {
current->fClientID = fClientId;
_ReclaimOpen(current);
_ReclaimLocks(current);
current = current->fNext;
@@ -74,47 +75,10 @@ NFS4Server::ServerRebooted(uint64 clientId)
status_t
NFS4Server::_ReclaimOpen(OpenFileCookie* cookie)
{
if (cookie->fClientId == fClientId)
return B_OK;
cookie->fClientId = fClientId;
Request request(fServer);
RequestBuilder& req = request.Builder();
req.PutFH(cookie->fInfo.fHandle);
req.Open(CLAIM_PREVIOUS, cookie->fSequence++, sModeToAccess(cookie->fMode),
cookie->fClientId, OPEN4_NOCREATE, cookie->fOwnerId, NULL);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
reply.PutFH();
bool confirm;
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm);
if (result != B_OK)
return result;
if (confirm) {
request.Reset();
req.PutFH(cookie->fInfo.fHandle);
req.OpenConfirm(cookie->fSequence++, cookie->fStateId,
cookie->fStateSeq);
result = request.Send();
if (result != B_OK)
return result;
reply.PutFH();
result = reply.OpenConfirm(&cookie->fStateSeq);
if (result != B_OK)
return result;
}
if (cookie->fWriteState != NULL)
cookie->fWriteState->Reclaim(fClientId);
if (cookie->fReadState != NULL)
cookie->fReadState->Reclaim(fClientId);
return B_OK;
}
@@ -136,7 +100,10 @@ NFS4Server::_ReclaimLocks(OpenFileCookie* cookie)
Request request(fServer);
RequestBuilder& req = request.Builder();
req.PutFH(cookie->fInfo.fHandle);
if (cookie->fWriteState != NULL)
req.PutFH(cookie->fWriteState->fInfo.fHandle);
else
req.PutFH(cookie->fReadState->fInfo.fHandle);
req.Lock(cookie, linfo, true);
status_t result = request.Send();
@@ -0,0 +1,111 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, [email protected]
*/
#include "OpenState.h"
#include <util/AutoLock.h>
#include "FileSystem.h"
#include "Request.h"
vint64 OpenState::fLastOwnerID = 0;
OpenState::OpenState()
:
fSequence(0),
fOpened(false)
{
mutex_init(&fLock, NULL);
}
OpenState::~OpenState()
{
Close();
mutex_destroy(&fLock);
}
status_t
OpenState::Reclaim(uint64 newClientID)
{
if (!fOpened)
return B_OK;
MutexLocker _(fLock);
if (fClientID == newClientID)
return B_OK;
fClientID = newClientID;
bool confirm;
do {
RPC::Server* server = fFileSystem->Server();
Request request(server);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.Open(CLAIM_PREVIOUS, fSequence++, sModeToAccess(fMode), newClientID,
OPEN4_NOCREATE, fOwnerID, NULL);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), server))
continue;
reply.PutFH();
result = reply.Open(fStateID, &fStateSeq, &confirm);
if (result != B_OK)
return result;
} while (true);
if (confirm)
return ConfirmOpen(fInfo.fHandle, this);
return B_OK;
}
status_t
OpenState::Close()
{
if (!fOpened)
return B_OK;
MutexLocker _(fLock);
fOpened = false;
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.Close(fSequence++, fStateID, fStateSeq);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv))
continue;
reply.PutFH();
return reply.Close();
} while (true);
}
@@ -0,0 +1,46 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, [email protected]
*/
#ifndef OPENSTATE_H
#define OPENSTATE_H
#include <lock.h>
#include <SupportDefs.h>
#include <util/KernelReferenceable.h>
#include "NFS4Object.h"
struct OpenState : public NFS4Object, public KernelReferenceable {
OpenState();
~OpenState();
uint64 fClientID;
int fMode;
mutex fLock;
uint32 fStateID[3];
uint32 fStateSeq;
uint32 fSequence;
uint64 fOwnerID;
static vint64 fLastOwnerID;
bool fOpened;
status_t Reclaim(uint64 newClientID);
status_t Close();
};
#endif // OPENSTATE_H
@@ -171,11 +171,14 @@ void
RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream,
OpenFileCookie* cookie, LockOwner* owner)
{
stream.AddUHyper(cookie->fClientId);
stream.AddUHyper(cookie->fClientID);
uint64 lockOwner[2];
lockOwner[0] = owner->fOwner;
lockOwner[1] = cookie->fInfo.fFileId;
if (cookie->fWriteState != NULL)
lockOwner[1] = cookie->fWriteState->fInfo.fFileId;
else
lockOwner[1] = cookie->fReadState->fInfo.fFileId;
stream.AddOpaque(lockOwner, sizeof(lockOwner));
}
@@ -202,11 +205,17 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim)
fRequest->Stream().AddBoolean(true); // new lock owner
// open seq stateid
fRequest->Stream().AddUInt(cookie->fSequence++);
fRequest->Stream().AddUInt(cookie->fStateSeq);
fRequest->Stream().AddUInt(cookie->fStateId[0]);
fRequest->Stream().AddUInt(cookie->fStateId[1]);
fRequest->Stream().AddUInt(cookie->fStateId[2]);
OpenState* state;
if (lock->fType == READ_LT || lock->fType == READW_LT)
state = cookie->fReadState;
else
state = cookie->fWriteState;
fRequest->Stream().AddUInt(state->fSequence++);
fRequest->Stream().AddUInt(state->fStateSeq);
fRequest->Stream().AddUInt(state->fStateID[0]);
fRequest->Stream().AddUInt(state->fStateID[1]);
fRequest->Stream().AddUInt(state->fStateID[2]);
// lock seq owner
fRequest->Stream().AddUInt(lock->fOwner->fSequence++);
@@ -246,7 +255,7 @@ RequestBuilder::LockT(LockType type, uint64 pos, uint64 len,
fRequest->Stream().AddUHyper(pos);
fRequest->Stream().AddUHyper(len);
fRequest->Stream().AddUHyper(cookie->fClientId);
fRequest->Stream().AddUHyper(cookie->fClientID);
uint32 owner = find_thread(NULL);
fRequest->Stream().AddOpaque(&owner, sizeof(owner));
@@ -253,12 +253,6 @@ nfs4_write_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos,
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
if (cookie == NULL) {
cookie = inode->WriteCookie();
if (cookie == NULL)
return B_BAD_VALUE;
}
status_t result;
uint32 ioSize = inode->GetFileSystem()->Root()->IOSize();
for (size_t i = 0; i < count; i++) {
@@ -462,9 +456,6 @@ nfs4_free_cookie(fs_volume* volume, fs_vnode* vnode, void* _cookie)
file_cache_sync(inode->FileCache());
inode->Commit();
if (inode->WriteCookie() == cookie)
inode->SetWriteCookie(NULL);
inode->Close(cookie);
delete cookie;
@@ -512,7 +503,6 @@ nfs4_write(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
if (result != B_OK)
return result;
inode->SetWriteCookie(cookie);
return file_cache_write(inode->FileCache(), cookie, pos, _buffer, length);
}