nfs4: Make the client more configurable

This commit is contained in:
Pawel Dziepak
2012-08-16 19:59:50 +02:00
parent 870528b799
commit 060a4636e4
22 changed files with 251 additions and 111 deletions
@@ -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;