nfs4: close*() should wake all blocked operations
This commit is contained in:
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Cookie.h"
|
||||||
|
|
||||||
|
#include "Inode.h"
|
||||||
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
|
vint64 OpenFileCookie::fLastOwnerId = 0;
|
||||||
|
|
||||||
|
|
||||||
|
Cookie::Cookie()
|
||||||
|
:
|
||||||
|
fRequests(NULL)
|
||||||
|
{
|
||||||
|
mutex_init(&fRequestLock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Cookie::~Cookie()
|
||||||
|
{
|
||||||
|
mutex_destroy(&fRequestLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Cookie::RegisterRequest(RPC::Request* req)
|
||||||
|
{
|
||||||
|
mutex_lock(&fRequestLock);
|
||||||
|
RequestEntry* ent = new RequestEntry;
|
||||||
|
if (ent == NULL) {
|
||||||
|
mutex_unlock(&fRequestLock);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->fRequest = req;
|
||||||
|
ent->fNext = fRequests;
|
||||||
|
fRequests = ent;
|
||||||
|
mutex_unlock(&fRequestLock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Cookie::UnregisterRequest(RPC::Request* req)
|
||||||
|
{
|
||||||
|
mutex_lock(&fRequestLock);
|
||||||
|
RequestEntry* ent = fRequests;
|
||||||
|
RequestEntry* prev = NULL;
|
||||||
|
while (ent != NULL) {
|
||||||
|
if (ent->fRequest == req) {
|
||||||
|
if (prev == NULL)
|
||||||
|
fRequests = ent->fNext;
|
||||||
|
else
|
||||||
|
prev->fNext = ent->fNext;
|
||||||
|
delete ent;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = ent;
|
||||||
|
ent = ent->fNext;
|
||||||
|
}
|
||||||
|
mutex_unlock(&fRequestLock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Cookie::CancelAll()
|
||||||
|
{
|
||||||
|
mutex_lock(&fRequestLock);
|
||||||
|
RequestEntry* ent = fRequests;
|
||||||
|
while (ent != NULL) {
|
||||||
|
fInode->FileSystem()->Server()->WakeCall(ent->fRequest);
|
||||||
|
ent = ent->fNext;
|
||||||
|
}
|
||||||
|
mutex_unlock(&fRequestLock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef COOKIE_H
|
||||||
|
#define COOKIE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include "Filesystem.h"
|
||||||
|
|
||||||
|
class Inode;
|
||||||
|
|
||||||
|
struct Cookie {
|
||||||
|
struct RequestEntry {
|
||||||
|
RPC::Request* fRequest;
|
||||||
|
RequestEntry* fNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
Inode* fInode;
|
||||||
|
RequestEntry* fRequests;
|
||||||
|
mutex fRequestLock;
|
||||||
|
|
||||||
|
Cookie();
|
||||||
|
virtual ~Cookie();
|
||||||
|
|
||||||
|
status_t RegisterRequest(RPC::Request* req);
|
||||||
|
status_t UnregisterRequest(RPC::Request* req);
|
||||||
|
status_t CancelAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OpenFileCookie : public Cookie {
|
||||||
|
uint64 fClientId;
|
||||||
|
|
||||||
|
uint32 fMode;
|
||||||
|
|
||||||
|
Filehandle fHandle;
|
||||||
|
uint32 fStateId[3];
|
||||||
|
uint32 fStateSeq;
|
||||||
|
|
||||||
|
uint32 fSequence;
|
||||||
|
|
||||||
|
uint64 fOwnerId;
|
||||||
|
static vint64 fLastOwnerId;
|
||||||
|
|
||||||
|
OpenFileCookie* fNext;
|
||||||
|
OpenFileCookie* fPrev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OpenDirCookie : public Cookie {
|
||||||
|
uint64 fCookie;
|
||||||
|
uint64 fCookieVerf;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // COOKIE_H
|
||||||
|
|
||||||
@@ -15,9 +15,6 @@
|
|||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
vint64 OpenFileCookie::fLastOwnerId = 0;
|
|
||||||
|
|
||||||
|
|
||||||
Inode::Inode()
|
Inode::Inode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -447,6 +444,7 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
bool confirm;
|
bool confirm;
|
||||||
status_t result;
|
status_t result;
|
||||||
|
|
||||||
|
cookie->fInode = this;
|
||||||
cookie->fHandle = fHandle;
|
cookie->fHandle = fHandle;
|
||||||
cookie->fMode = mode;
|
cookie->fMode = mode;
|
||||||
cookie->fSequence = 0;
|
cookie->fSequence = 0;
|
||||||
@@ -610,7 +608,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
|||||||
req.Read(cookie->fStateId, cookie->fStateSeq, pos + size,
|
req.Read(cookie->fStateId, cookie->fStateSeq, pos + size,
|
||||||
*_length - size);
|
*_length - size);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send(cookie);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -664,7 +662,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::OpenDir(uint64* cookie)
|
Inode::OpenDir(OpenDirCookie* cookie)
|
||||||
{
|
{
|
||||||
if (fType != NF4DIR)
|
if (fType != NF4DIR)
|
||||||
return B_NOT_A_DIRECTORY;
|
return B_NOT_A_DIRECTORY;
|
||||||
@@ -707,8 +705,9 @@ Inode::OpenDir(uint64* cookie)
|
|||||||
if (allowed & ACCESS4_READ != ACCESS4_READ)
|
if (allowed & ACCESS4_READ != ACCESS4_READ)
|
||||||
return B_PERMISSION_DENIED;
|
return B_PERMISSION_DENIED;
|
||||||
|
|
||||||
cookie[0] = 0;
|
cookie->fInode = this;
|
||||||
cookie[1] = 2;
|
cookie->fCookie = 0;
|
||||||
|
cookie->fCookieVerf = 2;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} while (true);
|
} while (true);
|
||||||
@@ -716,7 +715,7 @@ Inode::OpenDir(uint64* cookie)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie,
|
||||||
bool* eof)
|
bool* eof)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
@@ -727,9 +726,10 @@ Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
|||||||
req.PutFH(fHandle);
|
req.PutFH(fHandle);
|
||||||
|
|
||||||
Attribute attr[] = { FATTR4_FSID, FATTR4_FILEID };
|
Attribute attr[] = { FATTR4_FSID, FATTR4_FILEID };
|
||||||
req.ReadDir(*count, cookie, attr, sizeof(attr) / sizeof(Attribute));
|
req.ReadDir(*count, cookie->fCookie, cookie->fCookieVerf, attr,
|
||||||
|
sizeof(attr) / sizeof(Attribute));
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send(cookie);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -751,7 +751,8 @@ Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
return reply.ReadDir(cookie, dirents, count, eof);
|
return reply.ReadDir(&cookie->fCookie, &cookie->fCookieVerf, dirents,
|
||||||
|
count, eof);
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,7 +847,8 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
|||||||
// When directories are cached client should store inode numbers it assigned
|
// When directories are cached client should store inode numbers it assigned
|
||||||
// to directroy entries and use them consequently.
|
// to directroy entries and use them consequently.
|
||||||
status_t
|
status_t
|
||||||
Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
|
||||||
|
OpenDirCookie* cookie)
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
uint32 pos = 0;
|
uint32 pos = 0;
|
||||||
@@ -855,17 +857,17 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
|
|
||||||
char* buffer = reinterpret_cast<char*>(_buffer);
|
char* buffer = reinterpret_cast<char*>(_buffer);
|
||||||
|
|
||||||
if (cookie[0] == 0 && cookie[1] == 2 && count < *_count) {
|
if (cookie->fCookie == 0 && cookie->fCookieVerf == 2 && count < *_count) {
|
||||||
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
||||||
|
|
||||||
_FillDirEntry(de, fFileId, ".", pos, size);
|
_FillDirEntry(de, fFileId, ".", pos, size);
|
||||||
|
|
||||||
pos += de->d_reclen;
|
pos += de->d_reclen;
|
||||||
count++;
|
count++;
|
||||||
cookie[1]--;
|
cookie->fCookieVerf--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cookie[0] == 0 && cookie[1] == 1 && count < *_count) {
|
if (cookie->fCookie == 0 && cookie->fCookieVerf == 1 && count < *_count) {
|
||||||
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
||||||
|
|
||||||
if (strcmp(fName, "/"))
|
if (strcmp(fName, "/"))
|
||||||
@@ -875,7 +877,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
|
|
||||||
pos += de->d_reclen;
|
pos += de->d_reclen;
|
||||||
count++;
|
count++;
|
||||||
cookie[1]--;
|
cookie->fCookieVerf--;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overflow = false;
|
bool overflow = false;
|
||||||
|
|||||||
@@ -13,29 +13,12 @@
|
|||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include "Cookie.h"
|
||||||
#include "Filesystem.h"
|
#include "Filesystem.h"
|
||||||
#include "NFS4Defs.h"
|
#include "NFS4Defs.h"
|
||||||
#include "ReplyInterpreter.h"
|
#include "ReplyInterpreter.h"
|
||||||
|
|
||||||
|
|
||||||
struct OpenFileCookie {
|
|
||||||
uint64 fClientId;
|
|
||||||
|
|
||||||
uint32 fMode;
|
|
||||||
|
|
||||||
Filehandle fHandle;
|
|
||||||
uint32 fStateId[3];
|
|
||||||
uint32 fStateSeq;
|
|
||||||
|
|
||||||
uint32 fSequence;
|
|
||||||
|
|
||||||
uint64 fOwnerId;
|
|
||||||
static vint64 fLastOwnerId;
|
|
||||||
|
|
||||||
OpenFileCookie* fNext;
|
|
||||||
OpenFileCookie* fPrev;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Inode {
|
class Inode {
|
||||||
public:
|
public:
|
||||||
static status_t CreateInode(Filesystem* fs, const FileInfo& fi,
|
static status_t CreateInode(Filesystem* fs, const FileInfo& fi,
|
||||||
@@ -45,6 +28,7 @@ public:
|
|||||||
inline ino_t ID() const;
|
inline ino_t ID() const;
|
||||||
inline mode_t Type() const;
|
inline mode_t Type() const;
|
||||||
inline const char* Name() const;
|
inline const char* Name() const;
|
||||||
|
inline Filesystem* FileSystem() const;
|
||||||
|
|
||||||
status_t LookUp(const char* name, ino_t* id);
|
status_t LookUp(const char* name, ino_t* id);
|
||||||
status_t ReadLink(void* buffer, size_t* length);
|
status_t ReadLink(void* buffer, size_t* length);
|
||||||
@@ -56,9 +40,9 @@ public:
|
|||||||
status_t Read(OpenFileCookie* cookie, off_t pos,
|
status_t Read(OpenFileCookie* cookie, off_t pos,
|
||||||
void* buffer, size_t* length);
|
void* buffer, size_t* length);
|
||||||
|
|
||||||
status_t OpenDir(uint64* cookie);
|
status_t OpenDir(OpenDirCookie* cookie);
|
||||||
status_t ReadDir(void* buffer, uint32 size,
|
status_t ReadDir(void* buffer, uint32 size,
|
||||||
uint32* count, uint64* cookie);
|
uint32* count, OpenDirCookie* cookie);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Inode();
|
Inode();
|
||||||
@@ -66,7 +50,7 @@ private:
|
|||||||
status_t _LookUpFilehandle();
|
status_t _LookUpFilehandle();
|
||||||
|
|
||||||
status_t _ReadDirOnce(DirEntry** dirents, uint32* count,
|
status_t _ReadDirOnce(DirEntry** dirents, uint32* count,
|
||||||
uint64* cookie, bool* eof);
|
OpenDirCookie* cookie, bool* eof);
|
||||||
status_t _FillDirEntry(struct dirent* de, ino_t id,
|
status_t _FillDirEntry(struct dirent* de, ino_t id,
|
||||||
const char* name, uint32 pos, uint32 size);
|
const char* name, uint32 pos, uint32 size);
|
||||||
status_t _ReadDirUp(struct dirent* de, uint32 pos,
|
status_t _ReadDirUp(struct dirent* de, uint32 pos,
|
||||||
@@ -119,5 +103,12 @@ Inode::Name() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Filesystem*
|
||||||
|
Inode::FileSystem() const
|
||||||
|
{
|
||||||
|
return fFilesystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // INODE_H
|
#endif // INODE_H
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel file_systems nfs4 ;
|
|||||||
UsePrivateHeaders kernel ;
|
UsePrivateHeaders kernel ;
|
||||||
|
|
||||||
KernelAddon nfs4 :
|
KernelAddon nfs4 :
|
||||||
|
Cookie.cpp
|
||||||
Connection.cpp
|
Connection.cpp
|
||||||
Filesystem.cpp
|
Filesystem.cpp
|
||||||
Inode.cpp
|
Inode.cpp
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ Server::SendCallAsync(Call* call, Reply** reply, Request** request)
|
|||||||
req->fReply = reply;
|
req->fReply = reply;
|
||||||
req->fEvent.Init(&req->fEvent, NULL);
|
req->fEvent.Init(&req->fEvent, NULL);
|
||||||
req->fDone = false;
|
req->fDone = false;
|
||||||
|
req->fError = B_OK;
|
||||||
req->fNext = NULL;
|
req->fNext = NULL;
|
||||||
|
|
||||||
fRequests.AddRequest(req);
|
fRequests.AddRequest(req);
|
||||||
@@ -185,6 +186,22 @@ Server::ResendCallAsync(Call* call, Request* req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Server::WakeCall(Request* request)
|
||||||
|
{
|
||||||
|
Request* req = fRequests.FindRequest(request->fXID);
|
||||||
|
if (req == NULL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
request->fError = B_FILE_ERROR;
|
||||||
|
*request->fReply = NULL;
|
||||||
|
request->fDone = true;
|
||||||
|
request->fEvent.NotifyAll();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Server::Repair()
|
Server::Repair()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ namespace RPC {
|
|||||||
struct Request {
|
struct Request {
|
||||||
uint32 fXID;
|
uint32 fXID;
|
||||||
ConditionVariable fEvent;
|
ConditionVariable fEvent;
|
||||||
|
|
||||||
bool fDone;
|
bool fDone;
|
||||||
Reply** fReply;
|
Reply** fReply;
|
||||||
|
status_t fError;
|
||||||
|
|
||||||
Request* fNext;
|
Request* fNext;
|
||||||
};
|
};
|
||||||
@@ -62,6 +64,7 @@ public:
|
|||||||
inline status_t WaitCall(Request* request,
|
inline status_t WaitCall(Request* request,
|
||||||
bigtime_t time = kWaitTime);
|
bigtime_t time = kWaitTime);
|
||||||
inline status_t CancelCall(Request* request);
|
inline status_t CancelCall(Request* request);
|
||||||
|
status_t WakeCall(Request* request);
|
||||||
|
|
||||||
status_t Repair();
|
status_t Repair();
|
||||||
|
|
||||||
|
|||||||
@@ -237,14 +237,14 @@ ReplyInterpreter::Read(void* buffer, uint32* size, bool* eof)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ReplyInterpreter::ReadDir(uint64* cookie, DirEntry** dirents, uint32* _count,
|
ReplyInterpreter::ReadDir(uint64* cookie, uint64* cookieVerf,
|
||||||
bool* eof)
|
DirEntry** dirents, uint32* _count, bool* eof)
|
||||||
{
|
{
|
||||||
status_t res = _OperationError(OpReadDir);
|
status_t res = _OperationError(OpReadDir);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
cookie[1] = fReply->Stream().GetUHyper();
|
*cookieVerf = fReply->Stream().GetUHyper();
|
||||||
|
|
||||||
bool isNext;
|
bool isNext;
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
@@ -254,7 +254,7 @@ ReplyInterpreter::ReadDir(uint64* cookie, DirEntry** dirents, uint32* _count,
|
|||||||
|
|
||||||
isNext = fReply->Stream().GetBoolean();
|
isNext = fReply->Stream().GetBoolean();
|
||||||
while (isNext && count < *_count) {
|
while (isNext && count < *_count) {
|
||||||
cookie[0] = fReply->Stream().GetUHyper();
|
*cookie = fReply->Stream().GetUHyper();
|
||||||
|
|
||||||
entries[count].fName = fReply->Stream().GetString();
|
entries[count].fName = fReply->Stream().GetString();
|
||||||
_DecodeAttrs(fReply->Stream(), &entries[count].fAttrs,
|
_DecodeAttrs(fReply->Stream(), &entries[count].fAttrs,
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ public:
|
|||||||
inline status_t PutFH();
|
inline status_t PutFH();
|
||||||
inline status_t PutRootFH();
|
inline status_t PutRootFH();
|
||||||
status_t Read(void* buffer, uint32* size, bool* eof);
|
status_t Read(void* buffer, uint32* size, bool* eof);
|
||||||
status_t ReadDir(uint64* cookie, DirEntry** dirents,
|
status_t ReadDir(uint64* cookie, uint64* cookieVerf,
|
||||||
uint32* count, bool* eof);
|
DirEntry** dirents, uint32* count, bool* eof);
|
||||||
status_t ReadLink(void* buffer, uint32* size, uint32 maxSize);
|
status_t ReadLink(void* buffer, uint32* size, uint32 maxSize);
|
||||||
inline status_t Renew();
|
inline status_t Renew();
|
||||||
status_t SetClientID(uint64* clientid, uint64* verifier);
|
status_t SetClientID(uint64* clientid, uint64* verifier);
|
||||||
|
|||||||
@@ -7,15 +7,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Inode.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Request::Send()
|
Request::Send(Cookie* cookie)
|
||||||
{
|
{
|
||||||
switch (fServer->ID().fProtocol) {
|
switch (fServer->ID().fProtocol) {
|
||||||
case ProtocolUDP: return _SendUDP();
|
case ProtocolUDP: return _SendUDP(cookie);
|
||||||
case ProtocolTCP: return _SendTCP();
|
case ProtocolTCP: return _SendTCP(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -23,41 +24,61 @@ Request::Send()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Request::_SendUDP()
|
Request::_SendUDP(Cookie* cookie)
|
||||||
{
|
{
|
||||||
RPC::Reply *rpl;
|
RPC::Reply *rpl = NULL;
|
||||||
RPC::Request *rpc;
|
RPC::Request *rpc;
|
||||||
|
|
||||||
status_t result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
|
status_t result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if (cookie != NULL)
|
||||||
|
cookie->RegisterRequest(rpc);
|
||||||
|
|
||||||
result = fServer->WaitCall(rpc);
|
result = fServer->WaitCall(rpc);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
int attempts = 1;
|
int attempts = 1;
|
||||||
while (result != B_OK && attempts++ < kRetryLimit) {
|
while (result != B_OK && attempts++ < kRetryLimit) {
|
||||||
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
|
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
|
||||||
if (result != B_OK)
|
if (result != B_OK) {
|
||||||
|
if (cookie != NULL)
|
||||||
|
cookie->UnregisterRequest(rpc);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = fServer->WaitCall(rpc);
|
result = fServer->WaitCall(rpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
|
if (cookie != NULL)
|
||||||
|
cookie->UnregisterRequest(rpc);
|
||||||
fServer->CancelCall(rpc);
|
fServer->CancelCall(rpc);
|
||||||
delete rpc;
|
delete rpc;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fReply.SetTo(rpl);
|
if (cookie != NULL)
|
||||||
|
cookie->UnregisterRequest(rpc);
|
||||||
|
|
||||||
|
if (rpc->fError != B_OK) {
|
||||||
|
delete rpl;
|
||||||
|
result = rpc->fError;
|
||||||
|
delete rpc;
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
fReply.SetTo(rpl);
|
||||||
|
delete rpc;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Request::_SendTCP()
|
Request::_SendTCP(Cookie* cookie)
|
||||||
{
|
{
|
||||||
RPC::Reply *rpl;
|
RPC::Reply *rpl = NULL;
|
||||||
RPC::Request *rpc;
|
RPC::Request *rpc;
|
||||||
|
|
||||||
status_t result;
|
status_t result;
|
||||||
@@ -71,8 +92,14 @@ Request::_SendTCP()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cookie != NULL)
|
||||||
|
cookie->RegisterRequest(rpc);
|
||||||
|
|
||||||
result = fServer->WaitCall(rpc);
|
result = fServer->WaitCall(rpc);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
|
if (cookie != NULL)
|
||||||
|
cookie->UnregisterRequest(rpc);
|
||||||
|
|
||||||
fServer->CancelCall(rpc);
|
fServer->CancelCall(rpc);
|
||||||
delete rpc;
|
delete rpc;
|
||||||
|
|
||||||
@@ -80,7 +107,19 @@ Request::_SendTCP()
|
|||||||
}
|
}
|
||||||
} while (result != B_OK && attempts++ < kRetryLimit);
|
} while (result != B_OK && attempts++ < kRetryLimit);
|
||||||
|
|
||||||
return fReply.SetTo(rpl);
|
if (cookie != NULL)
|
||||||
|
cookie->UnregisterRequest(rpc);
|
||||||
|
|
||||||
|
if (rpc->fError != B_OK) {
|
||||||
|
delete rpl;
|
||||||
|
result = rpc->fError;
|
||||||
|
delete rpc;
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
fReply.SetTo(rpl);
|
||||||
|
delete rpc;
|
||||||
|
return B_OK;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include "RPCServer.h"
|
#include "RPCServer.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Cookie;
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
public:
|
public:
|
||||||
inline Request(RPC::Server* serv);
|
inline Request(RPC::Server* serv);
|
||||||
@@ -21,12 +23,12 @@ public:
|
|||||||
inline RequestBuilder& Builder();
|
inline RequestBuilder& Builder();
|
||||||
inline ReplyInterpreter& Reply();
|
inline ReplyInterpreter& Reply();
|
||||||
|
|
||||||
status_t Send();
|
status_t Send(Cookie* cookie = NULL);
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _SendUDP();
|
status_t _SendUDP(Cookie* cookie);
|
||||||
status_t _SendTCP();
|
status_t _SendTCP(Cookie* cookie);
|
||||||
|
|
||||||
RPC::Server* fServer;
|
RPC::Server* fServer;
|
||||||
|
|
||||||
|
|||||||
@@ -267,8 +267,8 @@ RequestBuilder::Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
RequestBuilder::ReadDir(uint32 count, uint64 cookie, uint64 cookieVerf,
|
||||||
uint32 attrCount)
|
Attribute* attrs, uint32 attrCount)
|
||||||
{
|
{
|
||||||
(void)count;
|
(void)count;
|
||||||
|
|
||||||
@@ -278,8 +278,8 @@ RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
fRequest->Stream().AddUInt(OpReadDir);
|
fRequest->Stream().AddUInt(OpReadDir);
|
||||||
fRequest->Stream().AddUHyper(cookie[0]);
|
fRequest->Stream().AddUHyper(cookie);
|
||||||
fRequest->Stream().AddUHyper(cookie[1]);
|
fRequest->Stream().AddUHyper(cookieVerf);
|
||||||
|
|
||||||
// consider predicting this values basing on count or buffer size
|
// consider predicting this values basing on count or buffer size
|
||||||
fRequest->Stream().AddUInt(0x2000);
|
fRequest->Stream().AddUInt(0x2000);
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ public:
|
|||||||
status_t PutRootFH();
|
status_t PutRootFH();
|
||||||
status_t Read(const uint32* id, uint32 stateSeq,
|
status_t Read(const uint32* id, uint32 stateSeq,
|
||||||
uint64 pos, uint32 len);
|
uint64 pos, uint32 len);
|
||||||
status_t ReadDir(uint32 count, uint64* cookie,
|
status_t ReadDir(uint32 count, uint64 cookie,
|
||||||
Attribute* attrs, uint32 attrCount);
|
uint64 cookieVerf, Attribute* attrs,
|
||||||
|
uint32 attrCount);
|
||||||
status_t ReadLink();
|
status_t ReadLink();
|
||||||
status_t Renew(uint64 clientId);
|
status_t Renew(uint64 clientId);
|
||||||
status_t SetClientID(const RPC::Server* serv);
|
status_t SetClientID(const RPC::Server* serv);
|
||||||
|
|||||||
@@ -253,9 +253,15 @@ nfs4_open(fs_volume* volume, fs_vnode* vnode, int openMode, void** _cookie)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_close(fs_volume* volume, fs_vnode* vnode, void* cookie)
|
nfs4_close(fs_volume* volume, fs_vnode* vnode, void* _cookie)
|
||||||
{
|
{
|
||||||
|
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||||
|
|
||||||
|
if (inode->Type() == S_IFDIR || inode->Type() == S_IFLNK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
Cookie* cookie = reinterpret_cast<Cookie*>(_cookie);
|
||||||
|
return cookie->CancelAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -296,7 +302,7 @@ nfs4_read(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
|
|||||||
static status_t
|
static status_t
|
||||||
nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
||||||
{
|
{
|
||||||
uint64* cookie = new(std::nothrow) uint64[2];
|
OpenDirCookie* cookie = new(std::nothrow) OpenDirCookie;
|
||||||
if (cookie == NULL)
|
if (cookie == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
@@ -311,16 +317,17 @@ nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_close_dir(fs_volume* volume, fs_vnode* vnode, void* cookie)
|
nfs4_close_dir(fs_volume* volume, fs_vnode* vnode, void* _cookie)
|
||||||
{
|
{
|
||||||
return B_OK;
|
Cookie* cookie = reinterpret_cast<Cookie*>(_cookie);
|
||||||
|
return cookie->CancelAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_free_dir_cookie(fs_volume* volume, fs_vnode* vnode, void* cookie)
|
nfs4_free_dir_cookie(fs_volume* volume, fs_vnode* vnode, void* cookie)
|
||||||
{
|
{
|
||||||
delete[] reinterpret_cast<uint64*>(cookie);
|
delete reinterpret_cast<OpenDirCookie*>(cookie);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +336,7 @@ static status_t
|
|||||||
nfs4_read_dir(fs_volume* volume, fs_vnode* vnode, void* _cookie,
|
nfs4_read_dir(fs_volume* volume, fs_vnode* vnode, void* _cookie,
|
||||||
struct dirent* buffer, size_t bufferSize, uint32* _num)
|
struct dirent* buffer, size_t bufferSize, uint32* _num)
|
||||||
{
|
{
|
||||||
uint64* cookie = reinterpret_cast<uint64*>(_cookie);
|
OpenDirCookie* cookie = reinterpret_cast<OpenDirCookie*>(_cookie);
|
||||||
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||||
return inode->ReadDir(buffer, bufferSize, _num, cookie);
|
return inode->ReadDir(buffer, bufferSize, _num, cookie);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user