nfs4: Do not open too much files on server
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user