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