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