nfs4: Make the client more configurable
This commit is contained in:
@@ -105,6 +105,7 @@ CacheRevalidator::_DirectoryCacheRevalidator()
|
||||
}
|
||||
|
||||
fDirectoryCaches.RemoveHead();
|
||||
current->fRevalidated = false;
|
||||
|
||||
if (current->Revalidate() == B_OK)
|
||||
AddDirectory(current);
|
||||
|
||||
@@ -58,6 +58,7 @@ CacheRevalidator::Unlock()
|
||||
inline void
|
||||
CacheRevalidator::AddDirectory(DirectoryCache* cache)
|
||||
{
|
||||
cache->fRevalidated = true;
|
||||
fDirectoryCaches.InsertAfter(fDirectoryCaches.Tail(), cache);
|
||||
}
|
||||
|
||||
@@ -65,7 +66,9 @@ CacheRevalidator::AddDirectory(DirectoryCache* cache)
|
||||
inline void
|
||||
CacheRevalidator::RemoveDirectory(DirectoryCache* cache)
|
||||
{
|
||||
if (cache->fRevalidated == true)
|
||||
fDirectoryCaches.Remove(cache);
|
||||
cache->fRevalidated = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -77,6 +77,16 @@ PeerAddress::ProtocolString() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PeerAddress::SetProtocol(const char* protocol)
|
||||
{
|
||||
if (strcmp(protocol, "tcp") == 0)
|
||||
fProtocol = IPPROTO_TCP;
|
||||
else if (strcmp(protocol, "udp") == 0)
|
||||
fProtocol = IPPROTO_UDP;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
PeerAddress::UniversalAddress() const
|
||||
{
|
||||
|
||||
@@ -27,6 +27,8 @@ struct PeerAddress {
|
||||
PeerAddress();
|
||||
|
||||
const char* ProtocolString() const;
|
||||
void SetProtocol(const char* protocol);
|
||||
|
||||
char* UniversalAddress() const;
|
||||
|
||||
socklen_t AddressSize() const;
|
||||
|
||||
@@ -41,7 +41,7 @@ Delegation::ReturnDelegation()
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
|
||||
@@ -49,6 +49,7 @@ DirectoryCacheSnapshot::~DirectoryCacheSnapshot()
|
||||
|
||||
DirectoryCache::DirectoryCache(Inode* inode, bool attr)
|
||||
:
|
||||
fRevalidated(false),
|
||||
fDirectoryCache(NULL),
|
||||
fInode(inode),
|
||||
fAttrDir(attr),
|
||||
@@ -60,6 +61,10 @@ DirectoryCache::DirectoryCache(Inode* inode, bool attr)
|
||||
|
||||
DirectoryCache::~DirectoryCache()
|
||||
{
|
||||
fInode->GetFileSystem()->Revalidator().Lock();
|
||||
fInode->GetFileSystem()->Revalidator().RemoveDirectory(this);
|
||||
fInode->GetFileSystem()->Revalidator().Unlock();
|
||||
|
||||
mutex_destroy(&fLock);
|
||||
}
|
||||
|
||||
@@ -179,7 +184,12 @@ status_t
|
||||
DirectoryCache::Revalidate()
|
||||
{
|
||||
uint64 change;
|
||||
if (fInode->GetChangeInfo(&change, true) == B_OK && change == fChange) {
|
||||
if (fInode->GetChangeInfo(&change, true) != B_OK) {
|
||||
Trash();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (change == fChange) {
|
||||
fExpireTime = system_time() + kExpirationTime;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ public:
|
||||
inline time_t ExpireTime();
|
||||
|
||||
static const bigtime_t kExpirationTime = 15000000;
|
||||
|
||||
bool fRevalidated;
|
||||
protected:
|
||||
void NotifyChanges(DirectoryCacheSnapshot* oldSnapshot,
|
||||
DirectoryCacheSnapshot* newSnapshot);
|
||||
|
||||
@@ -49,7 +49,7 @@ FileInfo::ParsePath(RequestBuilder& req, uint32& count, const char* _path)
|
||||
status_t
|
||||
FileInfo::UpdateFileHandles(FileSystem* fs)
|
||||
{
|
||||
Request request(fs->Server());
|
||||
Request request(fs->Server(), fs);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutRootFH();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <lock.h>
|
||||
|
||||
#include "Request.h"
|
||||
@@ -21,7 +22,7 @@ extern RPC::ServerManager* gRPCServerManager;
|
||||
extern RPC::ProgramData* CreateNFS4Server(RPC::Server* serv);
|
||||
|
||||
|
||||
FileSystem::FileSystem()
|
||||
FileSystem::FileSystem(const MountConfiguration& configuration)
|
||||
:
|
||||
fNext(NULL),
|
||||
fPrev(NULL),
|
||||
@@ -30,7 +31,8 @@ FileSystem::FileSystem()
|
||||
fNamedAttrs(true),
|
||||
fPath(NULL),
|
||||
fRoot(NULL),
|
||||
fId(1)
|
||||
fId(1),
|
||||
fConfiguration(configuration)
|
||||
{
|
||||
fOpenOwner = rand();
|
||||
fOpenOwner <<= 32;
|
||||
@@ -73,9 +75,14 @@ sGetPath(const char* root, const char* path)
|
||||
|
||||
status_t
|
||||
FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
dev_t id)
|
||||
dev_t id, const MountConfiguration& configuration)
|
||||
{
|
||||
Request request(serv);
|
||||
FileSystem* fs = new(std::nothrow) FileSystem(configuration);
|
||||
if (fs == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<FileSystem> fsDeleter(fs);
|
||||
|
||||
Request request(serv, fs);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutRootFH();
|
||||
@@ -120,10 +127,6 @@ FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
if (result != B_OK || count < 2)
|
||||
return result;
|
||||
|
||||
FileSystem* fs = new(std::nothrow) FileSystem;
|
||||
if (fs == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// FATTR4_SUPPORTED_ATTRS is mandatory
|
||||
memcpy(fs->fSupAttrs, &values[0].fData.fValue64, sizeof(fs->fSupAttrs));
|
||||
|
||||
@@ -163,23 +166,20 @@ FileSystem::Mount(FileSystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
|
||||
delete[] values;
|
||||
|
||||
if (fi.fName == NULL || fi.fPath == NULL) {
|
||||
delete fs;
|
||||
if (fi.fName == NULL || fi.fPath == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
Inode* inode;
|
||||
result = Inode::CreateInode(fs, fi, &inode);
|
||||
if (result != B_OK) {
|
||||
delete fs;
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
fs->fRoot = reinterpret_cast<RootInode*>(inode);
|
||||
|
||||
fs->NFSServer()->AddFileSystem(fs);
|
||||
*pfs = fs;
|
||||
|
||||
fsDeleter.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,19 @@
|
||||
class Inode;
|
||||
class RootInode;
|
||||
|
||||
struct MountConfiguration {
|
||||
bool fHard;
|
||||
int fRetryLimit;
|
||||
|
||||
bool fEmulateNamedAttrs;
|
||||
bool fCacheMetadata;
|
||||
};
|
||||
|
||||
class FileSystem {
|
||||
public:
|
||||
static status_t Mount(FileSystem** pfs, RPC::Server* serv,
|
||||
const char* path, dev_t id);
|
||||
const char* path, dev_t id,
|
||||
const MountConfiguration& configuration);
|
||||
~FileSystem();
|
||||
|
||||
status_t GetInode(ino_t id, Inode** inode);
|
||||
@@ -65,10 +74,12 @@ public:
|
||||
inline bool NamedAttrs();
|
||||
inline void SetNamedAttrs(bool attrs);
|
||||
|
||||
inline const MountConfiguration& GetConfiguration();
|
||||
|
||||
FileSystem* fNext;
|
||||
FileSystem* fPrev;
|
||||
private:
|
||||
FileSystem();
|
||||
FileSystem(const MountConfiguration& config);
|
||||
|
||||
CacheRevalidator fCacheRevalidator;
|
||||
|
||||
@@ -99,6 +110,8 @@ private:
|
||||
dev_t fDevId;
|
||||
|
||||
InodeIdMap fInoIdMap;
|
||||
|
||||
MountConfiguration fConfiguration;
|
||||
};
|
||||
|
||||
|
||||
@@ -223,5 +236,12 @@ FileSystem::SetNamedAttrs(bool attrs)
|
||||
}
|
||||
|
||||
|
||||
inline const MountConfiguration&
|
||||
FileSystem::GetConfiguration()
|
||||
{
|
||||
return fConfiguration;
|
||||
}
|
||||
|
||||
|
||||
#endif // FILESYSTEM_H
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
|
||||
uint64 size;
|
||||
do {
|
||||
RPC::Server* serv = fs->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fs);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(inode->fInfo.fHandle);
|
||||
|
||||
@@ -67,7 +67,23 @@ Inode::LoadAttrDirHandle()
|
||||
|
||||
FileHandle handle;
|
||||
status_t result;
|
||||
if (!fFileSystem->NamedAttrs()) {
|
||||
|
||||
if (fFileSystem->NamedAttrs()) {
|
||||
result = NFS4Inode::OpenAttrDir(&handle);
|
||||
if (result == B_OK) {
|
||||
fInfo.fAttrDir = handle;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (result != B_UNSUPPORTED)
|
||||
return result;
|
||||
|
||||
fFileSystem->SetNamedAttrs(false);
|
||||
}
|
||||
|
||||
if (!fFileSystem->GetConfiguration().fEmulateNamedAttrs)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
char* attrDir
|
||||
= reinterpret_cast<char*>(malloc(strlen(fInfo.fName) + 32));
|
||||
if (attrDir == NULL)
|
||||
@@ -87,11 +103,6 @@ Inode::LoadAttrDirHandle()
|
||||
}
|
||||
|
||||
free(attrDir);
|
||||
} else {
|
||||
result = NFS4Inode::OpenAttrDir(&handle);
|
||||
if (result == B_UNSUPPORTED)
|
||||
fFileSystem->SetNamedAttrs(false);
|
||||
}
|
||||
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -128,7 +139,7 @@ Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
|
||||
@@ -35,7 +35,8 @@ status_t
|
||||
MetadataCache::GetStat(struct stat* st)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
if (fForceValid || fExpire > time(NULL)) {
|
||||
bool cache = fInode->GetFileSystem()->GetConfiguration().fCacheMetadata;
|
||||
if (fForceValid || (cache && fExpire > time(NULL))) {
|
||||
// Do not touch other members of struct stat
|
||||
st->st_size = fStatCache.st_size;
|
||||
st->st_mode = fStatCache.st_mode;
|
||||
@@ -110,6 +111,9 @@ MetadataCache::SetAccess(uid_t uid, uint32 allowed)
|
||||
entry.fAllowed = allowed;
|
||||
entry.fExpire = time(NULL) + kExpirationTime;
|
||||
entry.fForceValid = fForceValid;
|
||||
|
||||
bool cache = fInode->GetFileSystem()->GetConfiguration().fCacheMetadata;
|
||||
if (fForceValid || cache)
|
||||
fAccessCache.Insert(uid, entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ NFS4Inode::GetChangeInfo(uint64* change, bool attrDir)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (attrDir)
|
||||
@@ -60,7 +60,7 @@ NFS4Inode::CommitWrites()
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -86,7 +86,7 @@ NFS4Inode::Access(uint32* allowed)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -114,7 +114,7 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* fileID,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (parent)
|
||||
@@ -199,7 +199,7 @@ NFS4Inode::Link(Inode* dir, const char* name, ChangeInfo* changeInfo)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -231,7 +231,7 @@ NFS4Inode::ReadLink(void* buffer, size_t* length)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -262,7 +262,7 @@ NFS4Inode::GetStat(AttrValue** values, uint32* count, OpenAttrCookie* cookie)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (cookie != NULL)
|
||||
@@ -297,7 +297,7 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, uint32 attrCount)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (state != NULL) {
|
||||
@@ -335,7 +335,7 @@ NFS4Inode::Rename(Inode* from, Inode* to, const char* fromName,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = from->fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, from->fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (attribute)
|
||||
@@ -421,7 +421,7 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, OpenState* state,
|
||||
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
||||
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -512,7 +512,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation)
|
||||
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
||||
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
// Since we are opening the file using a pair (parentFH, name) we
|
||||
@@ -613,7 +613,7 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, int mode,
|
||||
state->fClientID = fFileSystem->NFSServer()->ClientId();
|
||||
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fAttrDir);
|
||||
@@ -665,7 +665,7 @@ NFS4Inode::ReadFile(OpenStateCookie* cookie, OpenState* state, uint64 position,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(state->fInfo.fHandle);
|
||||
@@ -697,7 +697,7 @@ NFS4Inode::WriteFile(OpenStateCookie* cookie, OpenState* state, uint64 position,
|
||||
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(state->fInfo.fHandle);
|
||||
@@ -732,7 +732,7 @@ NFS4Inode::CreateObject(const char* name, const char* path, int mode,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (parent)
|
||||
@@ -810,7 +810,7 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -888,7 +888,7 @@ NFS4Inode::ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
if (attribute)
|
||||
@@ -958,7 +958,7 @@ NFS4Inode::OpenAttrDir(FileHandle* handle)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -990,7 +990,7 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* type, uint64* position,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -1027,7 +1027,7 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait)
|
||||
MutexLocker ownerLocker(lockInfo->fOwner->fLock);
|
||||
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -1073,7 +1073,7 @@ NFS4Inode::ReleaseLock(OpenFileCookie* cookie, LockInfo* lockInfo)
|
||||
MutexLocker ownerLocker(lockInfo->fOwner->fLock);
|
||||
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
|
||||
@@ -111,6 +111,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
|
||||
return false;
|
||||
|
||||
// FileHandle has expired or is invalid
|
||||
case NFS4ERR_NOFILEHANDLE:
|
||||
case NFS4ERR_BADHANDLE:
|
||||
case NFS4ERR_FHEXPIRED:
|
||||
if (fInfo.UpdateFileHandles(fFileSystem) == B_OK)
|
||||
@@ -143,7 +144,7 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state,
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
|
||||
@@ -27,10 +27,20 @@ public:
|
||||
|
||||
static uint32 IncrementSequence(uint32 error);
|
||||
|
||||
inline NFS4Object();
|
||||
|
||||
FileInfo fInfo;
|
||||
FileSystem* fFileSystem;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
NFS4Object::NFS4Object()
|
||||
:
|
||||
fFileSystem(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endif // NFS4OBJECT_H
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew)
|
||||
if ((fUseCount == 0 && fClientIdLastUse + (time_t)LeaseTime() < time(NULL))
|
||||
|| (forceNew && fClientId == prevId)) {
|
||||
|
||||
Request request(fServer);
|
||||
Request request(fServer, NULL);
|
||||
request.Builder().SetClientID(fServer);
|
||||
|
||||
status_t result = request.Send();
|
||||
@@ -159,7 +159,7 @@ NFS4Server::FileSystemMigrated()
|
||||
status_t
|
||||
NFS4Server::_GetLeaseTime()
|
||||
{
|
||||
Request request(fServer);
|
||||
Request request(fServer, NULL);
|
||||
request.Builder().PutRootFH();
|
||||
Attribute attr[] = { FATTR4_LEASE_TIME };
|
||||
request.Builder().GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||
@@ -246,7 +246,7 @@ NFS4Server::_Renewal()
|
||||
}
|
||||
}
|
||||
|
||||
Request request(fServer);
|
||||
Request request(fServer, NULL);
|
||||
request.Builder().Renew(fClientId);
|
||||
request.Send();
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ OpenState::_ReleaseLockOwner(LockOwner* owner)
|
||||
{
|
||||
do {
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server);
|
||||
Request request(server, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.ReleaseLockOwner(this, owner);
|
||||
@@ -166,7 +166,7 @@ OpenState::_ReclaimOpen(uint64 newClientID)
|
||||
: OPEN_DELEGATE_NONE;
|
||||
do {
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server);
|
||||
Request request(server, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -231,7 +231,7 @@ OpenState::_ReclaimLocks(uint64 newClientID)
|
||||
|
||||
do {
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server);
|
||||
Request request(server, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -272,7 +272,7 @@ OpenState::Close()
|
||||
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
Request request(serv, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "Inode.h"
|
||||
#include "Request.h"
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
status_t
|
||||
Request::Send(Cookie* cookie)
|
||||
@@ -36,10 +38,17 @@ Request::_SendUDP(Cookie* cookie)
|
||||
if (cookie != NULL)
|
||||
cookie->RegisterRequest(rpc);
|
||||
|
||||
int retryLimit = 0;
|
||||
bool hard = true;
|
||||
if (fFileSystem != NULL) {
|
||||
retryLimit = fFileSystem->GetConfiguration().fRetryLimit;
|
||||
hard = fFileSystem->GetConfiguration().fHard;
|
||||
}
|
||||
|
||||
result = fServer->WaitCall(rpc);
|
||||
if (result != B_OK) {
|
||||
int attempts = 1;
|
||||
while (result != B_OK && attempts++ < kRetryLimit) {
|
||||
while (result != B_OK && (hard || attempts++ < retryLimit)) {
|
||||
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
|
||||
if (result != B_OK) {
|
||||
if (cookie != NULL)
|
||||
@@ -83,6 +92,15 @@ Request::_SendTCP(Cookie* cookie)
|
||||
|
||||
status_t result;
|
||||
int attempts = 0;
|
||||
|
||||
int retryLimit = 0;
|
||||
bool hard = true;
|
||||
|
||||
if (fFileSystem != NULL) {
|
||||
retryLimit = fFileSystem->GetConfiguration().fRetryLimit;
|
||||
hard = fFileSystem->GetConfiguration().fHard;
|
||||
}
|
||||
|
||||
do {
|
||||
result = fServer->SendCallAsync(fBuilder.Request(), &rpl, &rpc);
|
||||
if (result == B_NO_MEMORY)
|
||||
@@ -105,7 +123,7 @@ Request::_SendTCP(Cookie* cookie)
|
||||
|
||||
fServer->Repair();
|
||||
}
|
||||
} while (result != B_OK && attempts++ < kRetryLimit);
|
||||
} while (result != B_OK && (hard || attempts++ < retryLimit));
|
||||
|
||||
if (cookie != NULL)
|
||||
cookie->UnregisterRequest(rpc);
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
|
||||
|
||||
class Cookie;
|
||||
class FileSystem;
|
||||
|
||||
class Request {
|
||||
public:
|
||||
inline Request(RPC::Server* serv);
|
||||
inline Request(RPC::Server* server,
|
||||
FileSystem* fileSystem);
|
||||
|
||||
inline RequestBuilder& Builder();
|
||||
inline ReplyInterpreter& Reply();
|
||||
@@ -31,18 +33,18 @@ private:
|
||||
status_t _SendTCP(Cookie* cookie);
|
||||
|
||||
RPC::Server* fServer;
|
||||
FileSystem* fFileSystem;
|
||||
|
||||
RequestBuilder fBuilder;
|
||||
ReplyInterpreter fReply;
|
||||
|
||||
static const int kRetryLimit = 5;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
Request::Request(RPC::Server* serv)
|
||||
Request::Request(RPC::Server* server, FileSystem* fileSystem)
|
||||
:
|
||||
fServer(serv)
|
||||
fServer(server),
|
||||
fFileSystem(fileSystem)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ RootInode::_UpdateInfo(bool force)
|
||||
return B_OK;
|
||||
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -71,7 +71,7 @@ RootInode::_UpdateInfo(bool force)
|
||||
|
||||
ReplyInterpreter& reply = request.Reply();
|
||||
|
||||
if (HandleErrors(reply.NFS4Error(), serv))
|
||||
if (HandleErrors(reply.NFS4Error(), server))
|
||||
continue;
|
||||
|
||||
reply.PutFH();
|
||||
@@ -137,8 +137,8 @@ bool
|
||||
RootInode::ProbeMigration()
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -153,7 +153,7 @@ RootInode::ProbeMigration()
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED)
|
||||
return true;
|
||||
|
||||
if (HandleErrors(reply.NFS4Error(), serv))
|
||||
if (HandleErrors(reply.NFS4Error(), server))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
@@ -166,8 +166,8 @@ status_t
|
||||
RootInode::GetLocations(AttrValue** attrv)
|
||||
{
|
||||
do {
|
||||
RPC::Server* serv = fFileSystem->Server();
|
||||
Request request(serv);
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server, fFileSystem);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
@@ -180,7 +180,7 @@ RootInode::GetLocations(AttrValue** attrv)
|
||||
|
||||
ReplyInterpreter& reply = request.Reply();
|
||||
|
||||
if (HandleErrors(reply.NFS4Error(), serv))
|
||||
if (HandleErrors(reply.NFS4Error(), server))
|
||||
continue;
|
||||
|
||||
reply.PutFH();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <fs_cache.h>
|
||||
#include <fs_interface.h>
|
||||
|
||||
@@ -28,9 +29,6 @@
|
||||
extern fs_volume_ops gNFSv4VolumeOps;
|
||||
extern fs_vnode_ops gNFSv4VnodeOps;
|
||||
|
||||
extern "C" void
|
||||
dprintf(const char* format, ...);
|
||||
|
||||
|
||||
RPC::ServerManager* gRPCServerManager;
|
||||
|
||||
@@ -42,30 +40,80 @@ CreateNFS4Server(RPC::Server* serv)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: IPv6 address will cause problems
|
||||
// Format: ip{4,6}_address:path options
|
||||
// Available options:
|
||||
// hard - retry requests until success
|
||||
// soft - retry requests no more than retrans times (default)
|
||||
// retrans=X - retry requests X times (default: 5)
|
||||
// ac - use metadata cache (default)
|
||||
// noac - do not use metadata cache
|
||||
// xattr-emu - emulate named attributes
|
||||
// noxattr-emu - do not emulate named attributes (default)
|
||||
// port=X - connect to port X (default: 2049)
|
||||
// proto=X - user transport protocol X (default: tcp)
|
||||
static status_t
|
||||
ParseArguments(const char* _args, PeerAddress* address, char* _path)
|
||||
ParseArguments(const char* _args, PeerAddress* address, char** _path,
|
||||
MountConfiguration* conf)
|
||||
{
|
||||
if (_args == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
char* args = strdup(_args);
|
||||
char* path = strpbrk(args, ":");
|
||||
if (path == NULL) {
|
||||
free(args);
|
||||
if (args == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter argsDeleter(args);
|
||||
|
||||
char* options = strchr(args, ' ');
|
||||
if (options != NULL)
|
||||
*options++ = '\0';
|
||||
|
||||
char* path = strrchr(args, ':');
|
||||
if (path == NULL)
|
||||
return B_MISMATCHED_VALUES;
|
||||
}
|
||||
*path++ = '\0';
|
||||
|
||||
status_t result = PeerAddress::ResolveName(args, address);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
_path[255] = '\0';
|
||||
strncpy(_path, path, 255);
|
||||
*_path = strdup(path);
|
||||
if (*_path == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
conf->fHard = false;
|
||||
conf->fRetryLimit = 5;
|
||||
conf->fEmulateNamedAttrs = false;
|
||||
conf->fCacheMetadata = true;
|
||||
|
||||
char* optionsEnd;
|
||||
if (options != NULL)
|
||||
optionsEnd = strchr(options, ' ');
|
||||
while (options != NULL && *options != '\0') {
|
||||
if (optionsEnd != NULL)
|
||||
*optionsEnd++ = '\0';
|
||||
|
||||
if (strcmp(options, "hard") == 0)
|
||||
conf->fHard = true;
|
||||
else if (strncmp(options, "retrans=", 8) == 0) {
|
||||
options += strlen("retrans=");
|
||||
conf->fRetryLimit = atoi(options);
|
||||
} else if (strcmp(options, "noac") == 0)
|
||||
conf->fCacheMetadata = false;
|
||||
else if (strcmp(options, "xattr-emu") == 0)
|
||||
conf->fEmulateNamedAttrs = true;
|
||||
else if (strncmp(options, "port=", 5) == 0) {
|
||||
options += strlen("port=");
|
||||
address->SetPort(atoi(options));
|
||||
} else if (strncmp(options, "proto=", 6) == 0) {
|
||||
options += strlen("proto=");
|
||||
address->SetProtocol(options);
|
||||
}
|
||||
|
||||
options = optionsEnd;
|
||||
if (options != NULL)
|
||||
optionsEnd = strchr(options, ' ');
|
||||
}
|
||||
|
||||
free(args);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -83,10 +131,12 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
||||
locker.Unlock();
|
||||
|
||||
PeerAddress address;
|
||||
char path[256];
|
||||
result = ParseArguments(args, &address, path);
|
||||
MountConfiguration config;
|
||||
char *path;
|
||||
result = ParseArguments(args, &address, &path, &config);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
MemoryDeleter pathDeleter(path);
|
||||
|
||||
RPC::Server *server;
|
||||
result = gRPCServerManager->Acquire(&server, address, CreateNFS4Server);
|
||||
@@ -94,7 +144,7 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
||||
return result;
|
||||
|
||||
FileSystem* fs;
|
||||
result = FileSystem::Mount(&fs, server, path, volume->id);
|
||||
result = FileSystem::Mount(&fs, server, path, volume->id, config);
|
||||
if (result != B_OK) {
|
||||
gRPCServerManager->Release(server);
|
||||
return result;
|
||||
@@ -824,8 +874,6 @@ nfs4_release_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie,
|
||||
status_t
|
||||
nfs4_init()
|
||||
{
|
||||
dprintf("NFS4 Init\n");
|
||||
|
||||
gRPCServerManager = new(std::nothrow) RPC::ServerManager;
|
||||
if (gRPCServerManager == NULL)
|
||||
return B_NO_MEMORY;
|
||||
@@ -856,8 +904,6 @@ nfs4_init()
|
||||
status_t
|
||||
nfs4_uninit()
|
||||
{
|
||||
dprintf("NFS4 Uninit\n");
|
||||
|
||||
delete gRPCCallbackServer;
|
||||
delete gIdMapper;
|
||||
delete gWorkQueue;
|
||||
|
||||
Reference in New Issue
Block a user