nfs4: Use global open owner, check whether delegation was granted
This commit is contained in:
@@ -551,7 +551,7 @@ ConnectionBase::Disconnect()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ConnectionListener::Listen(ConnectionListener** _listener, uint16 port)
|
ConnectionListener::Listen(ConnectionListener** listener, uint16 port)
|
||||||
{
|
{
|
||||||
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
@@ -577,16 +577,13 @@ ConnectionListener::Listen(ConnectionListener** _listener, uint16 port)
|
|||||||
address.fProtocol = IPPROTO_TCP;
|
address.fProtocol = IPPROTO_TCP;
|
||||||
memset(&address.fAddress, 0, sizeof(address.fAddress));
|
memset(&address.fAddress, 0, sizeof(address.fAddress));
|
||||||
|
|
||||||
ConnectionListener* listener;
|
*listener = new(std::nothrow) ConnectionListener(address);
|
||||||
listener = new(std::nothrow) ConnectionListener(address);
|
if (*listener == NULL) {
|
||||||
if (listener == NULL) {
|
|
||||||
close(sock);
|
close(sock);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
listener->fSocket = sock;
|
(*listener)->fSocket = sock;
|
||||||
|
|
||||||
*_listener = listener;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,16 @@ FileSystem::FileSystem()
|
|||||||
fPrev(NULL),
|
fPrev(NULL),
|
||||||
fOpenFiles(NULL),
|
fOpenFiles(NULL),
|
||||||
fOpenCount(0),
|
fOpenCount(0),
|
||||||
|
fOpenOwnerSequence(0),
|
||||||
fPath(NULL),
|
fPath(NULL),
|
||||||
fRoot(NULL),
|
fRoot(NULL),
|
||||||
fId(1)
|
fId(1)
|
||||||
{
|
{
|
||||||
|
fOpenOwner = rand();
|
||||||
|
fOpenOwner <<= 32;
|
||||||
|
fOpenOwner |= rand();
|
||||||
|
|
||||||
|
mutex_init(&fOpenOwnerLock, NULL);
|
||||||
mutex_init(&fOpenLock, NULL);
|
mutex_init(&fOpenLock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +46,7 @@ FileSystem::~FileSystem()
|
|||||||
NFSServer()->RemoveFileSystem(this);
|
NFSServer()->RemoveFileSystem(this);
|
||||||
|
|
||||||
mutex_destroy(&fOpenLock);
|
mutex_destroy(&fOpenLock);
|
||||||
|
mutex_destroy(&fOpenOwnerLock);
|
||||||
|
|
||||||
free(const_cast<char*>(fPath));
|
free(const_cast<char*>(fPath));
|
||||||
delete fRoot;
|
delete fRoot;
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ public:
|
|||||||
inline dev_t DevId() const;
|
inline dev_t DevId() const;
|
||||||
inline InodeIdMap* InoIdMap();
|
inline InodeIdMap* InoIdMap();
|
||||||
|
|
||||||
|
inline uint64 OpenOwner() const;
|
||||||
|
inline uint32 OpenOwnerSequenceLock();
|
||||||
|
inline void OpenOwnerSequenceUnlock(bool increment = true);
|
||||||
|
|
||||||
FileSystem* fNext;
|
FileSystem* fNext;
|
||||||
FileSystem* fPrev;
|
FileSystem* fPrev;
|
||||||
private:
|
private:
|
||||||
@@ -62,6 +66,10 @@ private:
|
|||||||
uint32 fOpenCount;
|
uint32 fOpenCount;
|
||||||
mutex fOpenLock;
|
mutex fOpenLock;
|
||||||
|
|
||||||
|
uint64 fOpenOwner;
|
||||||
|
uint32 fOpenOwnerSequence;
|
||||||
|
mutex fOpenOwnerLock;
|
||||||
|
|
||||||
uint32 fExpireType;
|
uint32 fExpireType;
|
||||||
uint32 fSupAttrs[2];
|
uint32 fSupAttrs[2];
|
||||||
|
|
||||||
@@ -163,5 +171,29 @@ FileSystem::InoIdMap()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint64
|
||||||
|
FileSystem::OpenOwner() const
|
||||||
|
{
|
||||||
|
return fOpenOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint32
|
||||||
|
FileSystem::OpenOwnerSequenceLock()
|
||||||
|
{
|
||||||
|
mutex_lock(&fOpenOwnerLock);
|
||||||
|
return fOpenOwnerSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
FileSystem::OpenOwnerSequenceUnlock(bool increment = true)
|
||||||
|
{
|
||||||
|
if (increment)
|
||||||
|
fOpenOwnerSequence++;
|
||||||
|
mutex_unlock(&fOpenOwnerLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // FILESYSTEM_H
|
#endif // FILESYSTEM_H
|
||||||
|
|
||||||
|
|||||||
@@ -207,11 +207,32 @@ enum OpenClaim {
|
|||||||
CLAIM_DELEGATE_PREV = 3
|
CLAIM_DELEGATE_PREV = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum OpenDelegation {
|
||||||
|
OPEN_DELEGATE_NONE = 0,
|
||||||
|
OPEN_DELEGATE_READ = 1,
|
||||||
|
OPEN_DELEGATE_WRITE = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OpenDelegationData {
|
||||||
|
OpenDelegation fType;
|
||||||
|
|
||||||
|
uint32 fStateSeq;
|
||||||
|
uint32 fStateID[3];
|
||||||
|
|
||||||
|
bool fRecall;
|
||||||
|
uint64 fSpaceLimit;
|
||||||
|
};
|
||||||
|
|
||||||
enum OpenFlags {
|
enum OpenFlags {
|
||||||
OPEN4_RESULT_CONFIRM = 2,
|
OPEN4_RESULT_CONFIRM = 2,
|
||||||
OPEN4_RESULT_LOCKTYPE_POSIX = 4
|
OPEN4_RESULT_LOCKTYPE_POSIX = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NFS_LIMIT_SIZE = 1,
|
||||||
|
NFS_LIMIT_BLOCKS = 2
|
||||||
|
};
|
||||||
|
|
||||||
struct ChangeInfo {
|
struct ChangeInfo {
|
||||||
bool fAtomic;
|
bool fAtomic;
|
||||||
uint64 fBefore;
|
uint64 fBefore;
|
||||||
|
|||||||
@@ -389,6 +389,8 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
|
|||||||
status_t result;
|
status_t result;
|
||||||
|
|
||||||
bool badOwner = false;
|
bool badOwner = false;
|
||||||
|
OpenDelegationData delegation;
|
||||||
|
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
do {
|
do {
|
||||||
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
||||||
|
|
||||||
@@ -396,8 +398,6 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
|
|||||||
Request request(serv);
|
Request request(serv);
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
state->fOwnerID = atomic_add64(&state->fLastOwnerID, 1);
|
|
||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
AttrValue cattr[4];
|
AttrValue cattr[4];
|
||||||
@@ -427,9 +427,9 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode),
|
req.Open(CLAIM_NULL, sequence, sModeToAccess(mode),
|
||||||
state->fClientID, OPEN4_CREATE, state->fOwnerID, name, cattr,
|
state->fClientID, OPEN4_CREATE, fFileSystem->OpenOwner(), name,
|
||||||
i, (mode & O_EXCL) == O_EXCL);
|
cattr, i, (mode & O_EXCL) == O_EXCL);
|
||||||
|
|
||||||
req.GetFH();
|
req.GetFH();
|
||||||
|
|
||||||
@@ -439,22 +439,29 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = request.Send();
|
result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock(false);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
if (reply.NFS4Error() == NFS4ERR_BADOWNER) {
|
if (reply.NFS4Error() == NFS4ERR_BADOWNER) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
|
sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
|
|
||||||
badOwner = true;
|
badOwner = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (HandleErrors(reply.NFS4Error(), serv))
|
if (HandleErrors(reply.NFS4Error(), serv))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
|
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
|
|
||||||
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm,
|
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm,
|
||||||
&changeInfo->fBefore, &changeInfo->fAfter, &changeInfo->fAtomic);
|
&delegation, changeInfo);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -488,8 +495,10 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms,
|
|||||||
status_t
|
status_t
|
||||||
NFS4Inode::OpenFile(OpenState* state, int mode)
|
NFS4Inode::OpenFile(OpenState* state, int mode)
|
||||||
{
|
{
|
||||||
|
OpenDelegationData delegation;
|
||||||
bool confirm;
|
bool confirm;
|
||||||
status_t result;
|
status_t result;
|
||||||
|
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
do {
|
do {
|
||||||
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
||||||
|
|
||||||
@@ -497,8 +506,6 @@ NFS4Inode::OpenFile(OpenState* state, int mode)
|
|||||||
Request request(serv);
|
Request request(serv);
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
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.
|
||||||
if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
|
if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
|
||||||
@@ -526,22 +533,27 @@ NFS4Inode::OpenFile(OpenState* state, 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, state->fSequence++, sModeToAccess(mode),
|
req.Open(CLAIM_NULL, sequence, sModeToAccess(mode),
|
||||||
state->fClientID, OPEN4_CREATE, state->fOwnerID, fInfo.fName,
|
state->fClientID, OPEN4_CREATE, fFileSystem->OpenOwner(),
|
||||||
&attr, 1, false);
|
fInfo.fName, &attr, 1, false);
|
||||||
} else
|
} else
|
||||||
req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode),
|
req.Open(CLAIM_NULL, sequence, sModeToAccess(mode), state->fClientID,
|
||||||
state->fClientID, OPEN4_NOCREATE, state->fOwnerID, fInfo.fName);
|
OPEN4_NOCREATE, fFileSystem->OpenOwner(), fInfo.fName);
|
||||||
|
req.GetFH();
|
||||||
|
|
||||||
result = request.Send();
|
result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock(false);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
if (HandleErrors(reply.NFS4Error(), serv, NULL, state))
|
if (HandleErrors(reply.NFS4Error(), serv, NULL, state))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
|
|
||||||
// Verify if the file we want to open is the file this Inode
|
// Verify if the file we want to open is the file this Inode
|
||||||
// represents.
|
// represents.
|
||||||
if (fFileSystem->IsAttrSupported(FATTR4_FILEID) ||
|
if (fFileSystem->IsAttrSupported(FATTR4_FILEID) ||
|
||||||
@@ -558,7 +570,12 @@ NFS4Inode::OpenFile(OpenState* state, int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm);
|
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm,
|
||||||
|
&delegation);
|
||||||
|
|
||||||
|
FileHandle handle;
|
||||||
|
reply.GetFH(&handle);
|
||||||
|
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -570,6 +587,9 @@ NFS4Inode::OpenFile(OpenState* state, int mode)
|
|||||||
if (confirm)
|
if (confirm)
|
||||||
return ConfirmOpen(fInfo.fHandle, state);
|
return ConfirmOpen(fInfo.fHandle, state);
|
||||||
|
|
||||||
|
if (delegation.fType != OPEN_DELEGATE_NONE)
|
||||||
|
dprintf("GOT A DELEGATION!\n");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -891,6 +911,7 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* type, uint64* position,
|
|||||||
status_t
|
status_t
|
||||||
NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait)
|
NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait)
|
||||||
{
|
{
|
||||||
|
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
do {
|
do {
|
||||||
MutexLocker ownerLocker(lockInfo->fOwner->fLock);
|
MutexLocker ownerLocker(lockInfo->fOwner->fLock);
|
||||||
|
|
||||||
@@ -899,11 +920,13 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait)
|
|||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
req.Lock(cookie, lockInfo);
|
req.Lock(cookie, lockInfo, sequence);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock(false);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ReplyInterpreter &reply = request.Reply();
|
ReplyInterpreter &reply = request.Reply();
|
||||||
|
|
||||||
@@ -912,13 +935,16 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait)
|
|||||||
|
|
||||||
ownerLocker.Unlock();
|
ownerLocker.Unlock();
|
||||||
if (wait && reply.NFS4Error() == NFS4ERR_DENIED) {
|
if (wait && reply.NFS4Error() == NFS4ERR_DENIED) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE,
|
snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE,
|
||||||
B_RELATIVE_TIMEOUT);
|
B_RELATIVE_TIMEOUT);
|
||||||
|
sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (HandleErrors(reply.NFS4Error(), serv, cookie))
|
if (HandleErrors(reply.NFS4Error(), serv, cookie))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
|
|||||||
status_t
|
status_t
|
||||||
NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state)
|
NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state)
|
||||||
{
|
{
|
||||||
|
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
do {
|
do {
|
||||||
RPC::Server* serv = fFileSystem->Server();
|
RPC::Server* serv = fFileSystem->Server();
|
||||||
Request request(serv);
|
Request request(serv);
|
||||||
@@ -110,17 +111,21 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state)
|
|||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fh);
|
req.PutFH(fh);
|
||||||
req.OpenConfirm(state->fSequence++, state->fStateID, state->fStateSeq);
|
req.OpenConfirm(sequence, state->fStateID, state->fStateSeq);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock(false);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
if (HandleErrors(reply.NFS4Error(), serv))
|
if (HandleErrors(reply.NFS4Error(), serv))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
|
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
result = reply.OpenConfirm(&state->fStateSeq);
|
result = reply.OpenConfirm(&state->fStateSeq);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
|
|||||||
@@ -15,11 +15,8 @@
|
|||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
vint64 OpenState::fLastOwnerID = 0;
|
|
||||||
|
|
||||||
OpenState::OpenState()
|
OpenState::OpenState()
|
||||||
:
|
:
|
||||||
fSequence(0),
|
|
||||||
fOpened(false)
|
fOpened(false)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, NULL);
|
mutex_init(&fLock, NULL);
|
||||||
@@ -46,27 +43,34 @@ OpenState::Reclaim(uint64 newClientID)
|
|||||||
fClientID = newClientID;
|
fClientID = newClientID;
|
||||||
|
|
||||||
bool confirm;
|
bool confirm;
|
||||||
|
OpenDelegationData delegation;
|
||||||
|
|
||||||
|
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
do {
|
do {
|
||||||
RPC::Server* server = fFileSystem->Server();
|
RPC::Server* server = fFileSystem->Server();
|
||||||
Request request(server);
|
Request request(server);
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
req.Open(CLAIM_PREVIOUS, fSequence++, sModeToAccess(fMode), newClientID,
|
req.Open(CLAIM_PREVIOUS, sequence, sModeToAccess(fMode), newClientID,
|
||||||
OPEN4_NOCREATE, fOwnerID, NULL);
|
OPEN4_NOCREATE, fFileSystem->OpenOwner(), NULL);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock(false);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
if (HandleErrors(reply.NFS4Error(), server))
|
if (HandleErrors(reply.NFS4Error(), server))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
|
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
|
|
||||||
result = reply.Open(fStateID, &fStateSeq, &confirm);
|
result = reply.Open(fStateID, &fStateSeq, &confirm, &delegation);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
} while (true);
|
} while (true);
|
||||||
@@ -87,24 +91,29 @@ OpenState::Close()
|
|||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
fOpened = false;
|
fOpened = false;
|
||||||
|
|
||||||
|
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||||
do {
|
do {
|
||||||
RPC::Server* serv = fFileSystem->Server();
|
RPC::Server* serv = fFileSystem->Server();
|
||||||
Request request(serv);
|
Request request(serv);
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
req.Close(fSequence++, fStateID, fStateSeq);
|
req.Close(sequence, fStateID, fStateSeq);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock(false);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
if (HandleErrors(reply.NFS4Error(), serv, NULL, this))
|
if (HandleErrors(reply.NFS4Error(), serv, NULL, this))
|
||||||
continue;
|
continue;
|
||||||
|
fFileSystem->OpenOwnerSequenceUnlock();
|
||||||
|
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
|
|
||||||
return reply.Close();
|
return reply.Close();
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,14 +28,8 @@ struct OpenState : public NFS4Object, public KernelReferenceable {
|
|||||||
uint32 fStateID[3];
|
uint32 fStateID[3];
|
||||||
uint32 fStateSeq;
|
uint32 fStateSeq;
|
||||||
|
|
||||||
uint32 fSequence;
|
|
||||||
|
|
||||||
uint64 fOwnerID;
|
|
||||||
static vint64 fLastOwnerID;
|
|
||||||
|
|
||||||
bool fOpened;
|
bool fOpened;
|
||||||
|
|
||||||
|
|
||||||
status_t Reclaim(uint64 newClientID);
|
status_t Reclaim(uint64 newClientID);
|
||||||
|
|
||||||
status_t Close();
|
status_t Close();
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ CallbackServer::ListenerThread()
|
|||||||
{
|
{
|
||||||
while (fThreadRunning) {
|
while (fThreadRunning) {
|
||||||
Connection* connection;
|
Connection* connection;
|
||||||
|
|
||||||
status_t result = fListener->AcceptConnection(&connection);
|
status_t result = fListener->AcceptConnection(&connection);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
fThreadRunning = false;
|
fThreadRunning = false;
|
||||||
|
|||||||
@@ -266,8 +266,8 @@ ReplyInterpreter::LockU(LockInfo* linfo)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before,
|
ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm,
|
||||||
uint64* _after, bool* _atomic)
|
OpenDelegationData* delegData, ChangeInfo* changeInfo)
|
||||||
{
|
{
|
||||||
status_t res = _OperationError(OpOpen);
|
status_t res = _OperationError(OpOpen);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
@@ -280,14 +280,13 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before,
|
|||||||
|
|
||||||
// change info
|
// change info
|
||||||
bool atomic = fReply->Stream().GetBoolean();
|
bool atomic = fReply->Stream().GetBoolean();
|
||||||
if (_atomic != NULL)
|
|
||||||
*_atomic = atomic;
|
|
||||||
uint64 before = fReply->Stream().GetUHyper();
|
uint64 before = fReply->Stream().GetUHyper();
|
||||||
if (_before != NULL)
|
|
||||||
*_before = before;
|
|
||||||
uint64 after = fReply->Stream().GetUHyper();
|
uint64 after = fReply->Stream().GetUHyper();
|
||||||
if (_after != NULL)
|
if (changeInfo != NULL) {
|
||||||
*_after = after;
|
changeInfo->fAtomic = atomic;
|
||||||
|
changeInfo->fBefore = before;
|
||||||
|
changeInfo->fAfter = after;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 flags = fReply->Stream().GetUInt();
|
uint32 flags = fReply->Stream().GetUInt();
|
||||||
*confirm = (flags & OPEN4_RESULT_CONFIRM) == OPEN4_RESULT_CONFIRM;
|
*confirm = (flags & OPEN4_RESULT_CONFIRM) == OPEN4_RESULT_CONFIRM;
|
||||||
@@ -298,7 +297,41 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before,
|
|||||||
fReply->Stream().GetUInt();
|
fReply->Stream().GetUInt();
|
||||||
|
|
||||||
// delegation info
|
// delegation info
|
||||||
|
uint32 delegation = fReply->Stream().GetUInt();
|
||||||
|
if (delegation == OPEN_DELEGATE_NONE) {
|
||||||
|
delegData->fType = OPEN_DELEGATE_NONE;
|
||||||
|
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegData->fStateSeq = fReply->Stream().GetUInt();
|
||||||
|
delegData->fStateID[0] = fReply->Stream().GetUInt();
|
||||||
|
delegData->fStateID[1] = fReply->Stream().GetUInt();
|
||||||
|
delegData->fStateID[2] = fReply->Stream().GetUInt();
|
||||||
|
|
||||||
|
delegData->fRecall = fReply->Stream().GetBoolean();
|
||||||
|
|
||||||
|
switch (delegation) {
|
||||||
|
case OPEN_DELEGATE_READ:
|
||||||
|
delegData->fType = OPEN_DELEGATE_READ;
|
||||||
|
break;
|
||||||
|
case OPEN_DELEGATE_WRITE:
|
||||||
|
delegData->fType = OPEN_DELEGATE_WRITE;
|
||||||
|
|
||||||
|
int32 limitBy = fReply->Stream().GetInt();
|
||||||
|
if (limitBy == NFS_LIMIT_SIZE)
|
||||||
|
delegData->fSpaceLimit = fReply->Stream().GetUHyper();
|
||||||
|
else if (limitBy == NFS_LIMIT_BLOCKS) {
|
||||||
|
uint32 numBlocks = fReply->Stream().GetUInt();
|
||||||
|
delegData->fSpaceLimit = fReply->Stream().GetUInt() * numBlocks;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACE data
|
||||||
fReply->Stream().GetUInt();
|
fReply->Stream().GetUInt();
|
||||||
|
fReply->Stream().GetUInt();
|
||||||
|
fReply->Stream().GetUInt();
|
||||||
|
fReply->Stream().GetOpaque(NULL);
|
||||||
|
|
||||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ public:
|
|||||||
inline status_t LookUpUp();
|
inline status_t LookUpUp();
|
||||||
inline status_t Nverify();
|
inline status_t Nverify();
|
||||||
status_t Open(uint32* id, uint32* seq, bool* confirm,
|
status_t Open(uint32* id, uint32* seq, bool* confirm,
|
||||||
uint64* before = NULL, uint64* after = NULL,
|
OpenDelegationData* delegData,
|
||||||
bool* atomic = NULL);
|
ChangeInfo* changeInfo = NULL);
|
||||||
status_t OpenConfirm(uint32* stateSeq);
|
status_t OpenConfirm(uint32* stateSeq);
|
||||||
inline status_t PutFH();
|
inline status_t PutFH();
|
||||||
inline status_t PutRootFH();
|
inline status_t PutRootFH();
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim)
|
RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence,
|
||||||
|
bool reclaim)
|
||||||
{
|
{
|
||||||
if (fProcedure != ProcCompound)
|
if (fProcedure != ProcCompound)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -213,7 +214,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim)
|
|||||||
else
|
else
|
||||||
state = cookie->fWriteState;
|
state = cookie->fWriteState;
|
||||||
|
|
||||||
fRequest->Stream().AddUInt(state->fSequence++);
|
fRequest->Stream().AddUInt(sequence);
|
||||||
fRequest->Stream().AddUInt(state->fStateSeq);
|
fRequest->Stream().AddUInt(state->fStateSeq);
|
||||||
fRequest->Stream().AddUInt(state->fStateID[0]);
|
fRequest->Stream().AddUInt(state->fStateID[0]);
|
||||||
fRequest->Stream().AddUInt(state->fStateID[1]);
|
fRequest->Stream().AddUInt(state->fStateID[1]);
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ public:
|
|||||||
status_t GetFH();
|
status_t GetFH();
|
||||||
status_t Link(const char* name);
|
status_t Link(const char* name);
|
||||||
status_t Lock(OpenFileCookie* cookie,
|
status_t Lock(OpenFileCookie* cookie,
|
||||||
LockInfo* lock, bool reclaim = false);
|
LockInfo* lock, uint32 sequence,
|
||||||
|
bool reclaim = false);
|
||||||
status_t LockT(LockType type, uint64 pos,
|
status_t LockT(LockType type, uint64 pos,
|
||||||
uint64 len, OpenFileCookie* cookie);
|
uint64 len, OpenFileCookie* cookie);
|
||||||
status_t LockU(LockInfo* lock);
|
status_t LockU(LockInfo* lock);
|
||||||
|
|||||||
Reference in New Issue
Block a user