nfs4: Add support for server migration
This commit is contained in:
@@ -11,14 +11,21 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Request.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <net/dns_resolver.h>
|
||||
|
||||
#include "Request.h"
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
extern RPC::ServerManager* gRPCServerManager;
|
||||
extern RPC::ProgramData* CreateNFS4Server(RPC::Server* serv);
|
||||
|
||||
|
||||
Filesystem::Filesystem()
|
||||
:
|
||||
fPath(NULL),
|
||||
fName(NULL),
|
||||
fId(1)
|
||||
{
|
||||
}
|
||||
@@ -26,10 +33,27 @@ Filesystem::Filesystem()
|
||||
|
||||
Filesystem::~Filesystem()
|
||||
{
|
||||
free(const_cast<char*>(fName));
|
||||
free(const_cast<char*>(fPath));
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
sGetPath(const char* root, const char* path)
|
||||
{
|
||||
int slash = 0;
|
||||
for (int i = 0; path[i] != '\0'; i++) {
|
||||
if (path[i] != root[i] || root[i] == '\0')
|
||||
break;
|
||||
|
||||
if (path[i] == '/')
|
||||
slash = i;
|
||||
}
|
||||
|
||||
return path + slash;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
dev_t id)
|
||||
@@ -67,7 +91,7 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
req.GetFH();
|
||||
req.Access();
|
||||
|
||||
Attribute attr[] = { FATTR4_FSID };
|
||||
Attribute attr[] = { FATTR4_FSID, FATTR4_FS_LOCATIONS };
|
||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||
|
||||
status_t result = request.Send();
|
||||
@@ -110,15 +134,39 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
reinterpret_cast<FilesystemId*>(values[0].fData.fPointer);
|
||||
|
||||
Filesystem* fs = new(std::nothrow) Filesystem;
|
||||
|
||||
if (count == 2 && values[1].fAttribute == FATTR4_FS_LOCATIONS) {
|
||||
FSLocations* locs =
|
||||
reinterpret_cast<FSLocations*>(values[1].fData.fLocations);
|
||||
|
||||
fs->fPath = strdup(locs->fRootPath);
|
||||
|
||||
delete locs;
|
||||
} else
|
||||
fs->fPath = NULL;
|
||||
|
||||
const char* name;
|
||||
if (fsPath != NULL && fsPath[0] == '/')
|
||||
fs->fPath = strdup(fsPath + 1);
|
||||
else
|
||||
fs->fPath = strdup(fsPath + 1);
|
||||
fsPath++;
|
||||
name = strrchr(fsPath, '/');
|
||||
if (name != NULL) {
|
||||
name++;
|
||||
fs->fName = strdup(name);
|
||||
} else
|
||||
fs->fName = strdup(fsPath);
|
||||
|
||||
memcpy(&fs->fRootFH, &fh, sizeof(Filehandle));
|
||||
fs->fServer = serv;
|
||||
fs->fDevId = id;
|
||||
fs->fFsId = *fsid;
|
||||
|
||||
FileInfo fi;
|
||||
fi.fFH = fh;
|
||||
fi.fParent = fh;
|
||||
fi.fName = strdup("/");
|
||||
fi.fPath = strdup(sGetPath(fs->fPath, fsPath));
|
||||
fs->fRoot = fi;
|
||||
|
||||
*pfs = fs;
|
||||
|
||||
return B_OK;
|
||||
@@ -149,14 +197,8 @@ Filesystem::GetInode(ino_t id, Inode** _inode)
|
||||
Inode*
|
||||
Filesystem::CreateRootInode()
|
||||
{
|
||||
FileInfo fi;
|
||||
fi.fFH = fRootFH;
|
||||
fi.fParent = fRootFH;
|
||||
fi.fName = strdup("/");
|
||||
fi.fPath = strdup(fPath);
|
||||
|
||||
Inode* inode;
|
||||
status_t result = Inode::CreateInode(this, fi, &inode);
|
||||
status_t result = Inode::CreateInode(this, fRoot, &inode);
|
||||
if (result == B_OK)
|
||||
return inode;
|
||||
else
|
||||
@@ -229,12 +271,95 @@ Filesystem::ReadInfo(struct fs_info* info)
|
||||
}
|
||||
|
||||
info->flags = B_FS_IS_READONLY;
|
||||
const char* name = strrchr(fPath, '/');
|
||||
if (name != NULL) {
|
||||
name++;
|
||||
strncpy(info->volume_name, name, B_FILE_NAME_LENGTH);
|
||||
} else
|
||||
strncpy(info->volume_name, fPath, B_FILE_NAME_LENGTH);
|
||||
strncpy(info->volume_name, fName, B_FILE_NAME_LENGTH);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Filesystem::Migrate(const Filehandle& fh, const RPC::Server* serv)
|
||||
{
|
||||
mutex_lock(&fMigrationLock);
|
||||
if (serv != fServer) {
|
||||
mutex_unlock(&fMigrationLock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
Request request(fServer);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fh);
|
||||
Attribute attr[] = { FATTR4_FS_LOCATIONS };
|
||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK) {
|
||||
mutex_unlock(&fMigrationLock);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReplyInterpreter& reply = request.Reply();
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK) {
|
||||
mutex_unlock(&fMigrationLock);
|
||||
return result;
|
||||
}
|
||||
|
||||
AttrValue* values;
|
||||
uint32 count;
|
||||
result = reply.GetAttr(&values, &count);
|
||||
if (result != B_OK || count < 1) {
|
||||
mutex_unlock(&fMigrationLock);
|
||||
return result;
|
||||
}
|
||||
|
||||
FSLocations* locs =
|
||||
reinterpret_cast<FSLocations*>(values[0].fData.fLocations);
|
||||
|
||||
dns_resolver_module* dns;
|
||||
result = get_module(DNS_RESOLVER_MODULE_NAME,
|
||||
reinterpret_cast<module_info**>(&dns));
|
||||
if (result != B_OK) {
|
||||
mutex_unlock(&fMigrationLock);
|
||||
return result;
|
||||
}
|
||||
|
||||
RPC::Server* server = fServer;
|
||||
for (uint32 i = 0; i < locs->fCount; i++) {
|
||||
for (uint32 j = 0; j < locs->fLocations[i].fCount; j++) {
|
||||
uint32 ip;
|
||||
struct in_addr addr;
|
||||
if (inet_aton(locs->fLocations[i].fLocations[j], &addr) == 0) {
|
||||
result = dns->dns_resolve(locs->fLocations[i].fLocations[j],
|
||||
&ip);
|
||||
if (result != B_OK)
|
||||
continue;
|
||||
} else
|
||||
ip = addr.s_addr;
|
||||
|
||||
if (gRPCServerManager->Acquire(&fServer, ip, 2049,
|
||||
ProtocolUDP, CreateNFS4Server) == B_OK) {
|
||||
|
||||
free(const_cast<char*>(fPath));
|
||||
fPath = strdup(locs->fLocations[j].fRootPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
put_module(DNS_RESOLVER_MODULE_NAME);
|
||||
delete locs;
|
||||
|
||||
if (server == fServer) {
|
||||
mutex_unlock(&fMigrationLock);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
gRPCServerManager->Release(server);
|
||||
|
||||
mutex_unlock(&fMigrationLock);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,13 @@ public:
|
||||
|
||||
status_t ReadInfo(struct fs_info* info);
|
||||
|
||||
status_t Migrate(const Filehandle& fh,
|
||||
const RPC::Server* serv);
|
||||
|
||||
inline RPC::Server* Server();
|
||||
inline NFS4Server* NFSServer();
|
||||
|
||||
inline const char* Path() const;
|
||||
inline const FilesystemId& FsId() const;
|
||||
|
||||
inline uint64 AllocFileId();
|
||||
@@ -42,9 +46,12 @@ public:
|
||||
private:
|
||||
Filesystem();
|
||||
|
||||
const char* fPath;
|
||||
FilesystemId fFsId;
|
||||
const char* fPath;
|
||||
mutex fMigrationLock;
|
||||
|
||||
const char* fName;
|
||||
FileInfo fRoot;
|
||||
Filehandle fRootFH;
|
||||
|
||||
RPC::Server* fServer;
|
||||
@@ -70,6 +77,13 @@ Filesystem::NFSServer()
|
||||
}
|
||||
|
||||
|
||||
inline const char*
|
||||
Filesystem::Path() const
|
||||
{
|
||||
return fPath;
|
||||
}
|
||||
|
||||
|
||||
inline const FilesystemId&
|
||||
Filesystem::FsId() const
|
||||
{
|
||||
|
||||
@@ -37,7 +37,8 @@ Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
||||
inode->fPath = strdup(fi.fPath);
|
||||
|
||||
do {
|
||||
Request request(fs->Server());
|
||||
RPC::Server* serv = fs->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(inode->fHandle);
|
||||
@@ -57,6 +58,12 @@ Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fs->Migrate(inode->fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -113,7 +120,8 @@ Inode::LookUp(const char* name, ino_t* id)
|
||||
}
|
||||
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -140,6 +148,12 @@ Inode::LookUp(const char* name, ino_t* id)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -206,7 +220,8 @@ Inode::ReadLink(void* buffer, size_t* length)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -224,6 +239,12 @@ Inode::ReadLink(void* buffer, size_t* length)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -241,7 +262,8 @@ status_t
|
||||
Inode::Access(int mode)
|
||||
{
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -259,6 +281,12 @@ Inode::Access(int mode)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -293,7 +321,8 @@ status_t
|
||||
Inode::Stat(struct stat* st)
|
||||
{
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -315,6 +344,12 @@ Inode::Stat(struct stat* st)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -419,7 +454,8 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
||||
do {
|
||||
cookie->fClientId = fFilesystem->NFSServer()->ClientId();
|
||||
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
cookie->fOwnerId = atomic_add64(&cookie->fLastOwnerId, 1);
|
||||
@@ -440,6 +476,12 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
// server is in grace period, we need to wait
|
||||
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||
fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId);
|
||||
@@ -501,7 +543,8 @@ Inode::Close(OpenFileCookie* cookie)
|
||||
fFilesystem->NFSServer()->RemoveOpenFile(cookie);
|
||||
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -520,6 +563,12 @@ Inode::Close(OpenFileCookie* cookie)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
// server is in grace period, we need to wait
|
||||
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||
@@ -553,7 +602,8 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
||||
|
||||
while (size < *_length && !eof) {
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -572,6 +622,12 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
// server is in grace period, we need to wait
|
||||
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||
@@ -614,7 +670,8 @@ Inode::OpenDir(uint64* cookie)
|
||||
return B_NOT_A_DIRECTORY;
|
||||
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -632,6 +689,12 @@ Inode::OpenDir(uint64* cookie)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -657,7 +720,8 @@ Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
||||
bool* eof)
|
||||
{
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -677,6 +741,12 @@ Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -712,7 +782,8 @@ status_t
|
||||
Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
||||
{
|
||||
do {
|
||||
Request request(fFilesystem->Server());
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
@@ -733,6 +804,12 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
||||
continue;
|
||||
}
|
||||
|
||||
// filesystem has been moved
|
||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||
fFilesystem->Migrate(fHandle, serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -849,16 +926,10 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::_LookUpFilehandle()
|
||||
static status_t
|
||||
sParsePath(RequestBuilder& req, uint32* count, const char* _path)
|
||||
{
|
||||
Request request(fFilesystem->Server());
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutRootFH();
|
||||
|
||||
uint32 lookupCount = 0;
|
||||
char* path = strdup(fPath);
|
||||
char* path = strdup(_path);
|
||||
char* pathStart = path;
|
||||
char* pathEnd;
|
||||
while (pathStart != NULL) {
|
||||
@@ -873,10 +944,27 @@ Inode::_LookUpFilehandle()
|
||||
else
|
||||
pathStart = NULL;
|
||||
|
||||
lookupCount++;
|
||||
(*count)++;
|
||||
}
|
||||
free(path);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::_LookUpFilehandle()
|
||||
{
|
||||
Request request(fFilesystem->Server());
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutRootFH();
|
||||
|
||||
uint32 lookupCount = 0;
|
||||
|
||||
sParsePath(req, &lookupCount, fFilesystem->Path());
|
||||
sParsePath(req, &lookupCount, fPath);
|
||||
|
||||
req.GetFH();
|
||||
|
||||
status_t result = request.Send();
|
||||
|
||||
@@ -14,6 +14,22 @@
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
|
||||
FSLocation::~FSLocation()
|
||||
{
|
||||
free(const_cast<char*>(fRootPath));
|
||||
for (uint32 i = 0; i < fCount; i++)
|
||||
free(const_cast<char*>(fLocations[i]));
|
||||
delete[] fLocations;
|
||||
}
|
||||
|
||||
|
||||
FSLocations::~FSLocations()
|
||||
{
|
||||
free(const_cast<char*>(fRootPath));
|
||||
delete[] fLocations;
|
||||
}
|
||||
|
||||
|
||||
AttrValue::AttrValue()
|
||||
:
|
||||
fFreePointer(false)
|
||||
@@ -25,6 +41,8 @@ AttrValue::~AttrValue()
|
||||
{
|
||||
if (fFreePointer)
|
||||
free(fData.fPointer);
|
||||
if (fAttribute == FATTR4_FS_LOCATIONS)
|
||||
delete fData.fLocations;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,6 +303,30 @@ ReplyInterpreter::SetClientID(uint64* clientid, uint64* verifier)
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
sFlattenPathname(XDR::ReadStream& str)
|
||||
{
|
||||
uint32 count = str.GetUInt();
|
||||
char* pathname = NULL;
|
||||
uint32 size = 0;
|
||||
for (uint32 i = 0; i < count; i++) {
|
||||
const char* path = str.GetString();
|
||||
size += strlen(path) + 1;
|
||||
if (pathname == NULL) {
|
||||
pathname = reinterpret_cast<char*>(malloc(strlen(path + 1)));
|
||||
pathname[0] = '\0';
|
||||
} else {
|
||||
*pathname++ = '/';
|
||||
pathname = reinterpret_cast<char*>(realloc(pathname, size));
|
||||
}
|
||||
strcat(pathname, path);
|
||||
free(const_cast<char*>(path));
|
||||
}
|
||||
|
||||
return pathname;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
||||
uint32* count)
|
||||
@@ -374,6 +416,25 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
||||
current++;
|
||||
}
|
||||
|
||||
if (sIsAttrSet(FATTR4_FS_LOCATIONS, bitmap, bcount)) {
|
||||
values[current].fAttribute = FATTR4_FS_LOCATIONS;
|
||||
|
||||
FSLocations* locs = new FSLocations;
|
||||
locs->fRootPath = sFlattenPathname(stream);
|
||||
locs->fCount = stream.GetUInt();
|
||||
locs->fLocations = new FSLocation[locs->fCount];
|
||||
for (uint32 i = 0; i < locs->fCount; i++) {
|
||||
locs->fLocations[i].fRootPath = sFlattenPathname(stream);
|
||||
locs->fLocations[i].fCount = stream.GetUInt();
|
||||
locs->fLocations[i].fLocations =
|
||||
new const char*[locs->fLocations[i].fCount];
|
||||
for (uint32 j = 0; j < locs->fLocations[i].fCount; j++)
|
||||
locs->fLocations[i].fLocations[j] = stream.GetString();
|
||||
}
|
||||
values[current].fData.fLocations = locs;
|
||||
current++;
|
||||
}
|
||||
|
||||
if (sIsAttrSet(FATTR4_MAXREAD, bitmap, bcount)) {
|
||||
values[current].fAttribute = FATTR4_MAXREAD;
|
||||
values[current].fData.fValue64 = stream.GetUHyper();
|
||||
|
||||
@@ -15,6 +15,22 @@
|
||||
#include "RPCReply.h"
|
||||
|
||||
|
||||
struct FSLocation {
|
||||
const char* fRootPath;
|
||||
const char** fLocations;
|
||||
uint32 fCount;
|
||||
|
||||
~FSLocation();
|
||||
};
|
||||
|
||||
struct FSLocations {
|
||||
const char* fRootPath;
|
||||
FSLocation* fLocations;
|
||||
uint32 fCount;
|
||||
|
||||
~FSLocations();
|
||||
};
|
||||
|
||||
struct AttrValue {
|
||||
AttrValue();
|
||||
~AttrValue();
|
||||
@@ -25,6 +41,7 @@ struct AttrValue {
|
||||
uint32 fValue32;
|
||||
uint64 fValue64;
|
||||
void* fPointer;
|
||||
FSLocations* fLocations;
|
||||
} fData;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ dprintf(const char* format, ...);
|
||||
RPC::ServerManager* gRPCServerManager;
|
||||
|
||||
|
||||
static RPC::ProgramData*
|
||||
sCreateNFS4Server(RPC::Server* serv)
|
||||
RPC::ProgramData*
|
||||
CreateNFS4Server(RPC::Server* serv)
|
||||
{
|
||||
return new NFS4Server(serv);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
||||
|
||||
RPC::Server *server;
|
||||
result = gRPCServerManager->Acquire(&server, ip, 2049, ProtocolUDP,
|
||||
sCreateNFS4Server);
|
||||
CreateNFS4Server);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user