nfs4: Add full support for lease migration
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
#include <net/dns_resolver.h>
|
#include <net/dns_resolver.h>
|
||||||
|
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "Inode.h"
|
#include "RootInode.h"
|
||||||
|
|
||||||
|
|
||||||
extern RPC::ServerManager* gRPCServerManager;
|
extern RPC::ServerManager* gRPCServerManager;
|
||||||
@@ -30,7 +30,7 @@ Filesystem::Filesystem()
|
|||||||
fOpenFiles(NULL),
|
fOpenFiles(NULL),
|
||||||
fOpenCount(0),
|
fOpenCount(0),
|
||||||
fPath(NULL),
|
fPath(NULL),
|
||||||
fName(NULL),
|
fRoot(NULL),
|
||||||
fId(1)
|
fId(1)
|
||||||
{
|
{
|
||||||
mutex_init(&fOpenLock, NULL);
|
mutex_init(&fOpenLock, NULL);
|
||||||
@@ -43,8 +43,8 @@ Filesystem::~Filesystem()
|
|||||||
|
|
||||||
mutex_destroy(&fOpenLock);
|
mutex_destroy(&fOpenLock);
|
||||||
|
|
||||||
free(const_cast<char*>(fName));
|
|
||||||
free(const_cast<char*>(fPath));
|
free(const_cast<char*>(fPath));
|
||||||
|
delete fRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -155,33 +155,39 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
|||||||
} else
|
} else
|
||||||
fs->fPath = NULL;
|
fs->fPath = NULL;
|
||||||
|
|
||||||
|
FileInfo fi;
|
||||||
const char* name;
|
const char* name;
|
||||||
if (fsPath != NULL && fsPath[0] == '/')
|
if (fsPath != NULL && fsPath[0] == '/')
|
||||||
fsPath++;
|
fsPath++;
|
||||||
name = strrchr(fsPath, '/');
|
name = strrchr(fsPath, '/');
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
name++;
|
name++;
|
||||||
fs->fName = strdup(name);
|
fi.fName = strdup(name);
|
||||||
} else
|
} else
|
||||||
fs->fName = strdup(fsPath);
|
fi.fName = strdup(fsPath);
|
||||||
|
|
||||||
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.fFH = fh;
|
||||||
fi.fParent = fh;
|
fi.fParent = fh;
|
||||||
fi.fName = strdup("/");
|
|
||||||
fi.fPath = strdup(sGetPath(fs->fPath, fsPath));
|
fi.fPath = strdup(sGetPath(fs->fPath, fsPath));
|
||||||
fs->fRoot = fi;
|
|
||||||
|
|
||||||
*pfs = fs;
|
|
||||||
|
|
||||||
delete[] values;
|
delete[] values;
|
||||||
|
|
||||||
|
Inode* inode;
|
||||||
|
result = Inode::CreateInode(fs, fi, &inode);
|
||||||
|
if (result != B_OK) {
|
||||||
|
delete fs;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs->fRoot = reinterpret_cast<RootInode*>(inode);
|
||||||
|
|
||||||
fs->NFSServer()->AddFilesystem(fs);
|
fs->NFSServer()->AddFilesystem(fs);
|
||||||
|
*pfs = fs;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,115 +213,19 @@ Filesystem::GetInode(ino_t id, Inode** _inode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Inode*
|
|
||||||
Filesystem::CreateRootInode()
|
|
||||||
{
|
|
||||||
Inode* inode;
|
|
||||||
status_t result = Inode::CreateInode(this, fRoot, &inode);
|
|
||||||
if (result == B_OK)
|
|
||||||
return inode;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Filesystem::ReadInfo(struct fs_info* info)
|
Filesystem::Migrate(const RPC::Server* serv)
|
||||||
{
|
{
|
||||||
Request request(fServer);
|
MutexLocker _(fOpenLock);
|
||||||
RequestBuilder& req = request.Builder();
|
|
||||||
|
|
||||||
req.PutFH(fRootFH);
|
|
||||||
Attribute attr[] = { FATTR4_FILES_FREE, FATTR4_FILES_TOTAL,
|
|
||||||
FATTR4_MAXREAD, FATTR4_MAXWRITE, FATTR4_SPACE_FREE,
|
|
||||||
FATTR4_SPACE_TOTAL };
|
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
|
||||||
|
|
||||||
status_t result = request.Send();
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
|
||||||
|
|
||||||
reply.PutFH();
|
|
||||||
|
|
||||||
AttrValue* values;
|
|
||||||
uint32 count, next = 0;
|
|
||||||
result = reply.GetAttr(&values, &count);
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_FILES_FREE) {
|
|
||||||
info->free_nodes = values[next].fData.fValue64;
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_FILES_TOTAL) {
|
|
||||||
info->total_nodes = values[next].fData.fValue64;
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 io_size = LONGLONG_MAX;
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_MAXREAD) {
|
|
||||||
io_size = min_c(io_size, values[next].fData.fValue64);
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_MAXWRITE) {
|
|
||||||
io_size = min_c(io_size, values[next].fData.fValue64);
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (io_size == LONGLONG_MAX)
|
|
||||||
io_size = 32768;
|
|
||||||
info->io_size = io_size;
|
|
||||||
info->block_size = io_size;
|
|
||||||
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_SPACE_FREE) {
|
|
||||||
info->free_blocks = values[next].fData.fValue64 / io_size;
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_SPACE_TOTAL) {
|
|
||||||
info->total_blocks = values[next].fData.fValue64 / io_size;
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
info->flags = B_FS_IS_READONLY;
|
|
||||||
strncpy(info->volume_name, fName, B_FILE_NAME_LENGTH);
|
|
||||||
|
|
||||||
delete[] values;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Filesystem::Migrate(const Filehandle& fh, const RPC::Server* serv)
|
|
||||||
{
|
|
||||||
MutexLocker _(fMigrationLock);
|
|
||||||
if (serv != fServer)
|
if (serv != fServer)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
Request request(fServer);
|
if (!fRoot->ProbeMigration())
|
||||||
RequestBuilder& req = request.Builder();
|
return B_OK;
|
||||||
|
|
||||||
req.PutFH(fh);
|
|
||||||
Attribute attr[] = { FATTR4_FS_LOCATIONS };
|
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
|
||||||
|
|
||||||
status_t result = request.Send();
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
|
||||||
|
|
||||||
reply.PutFH();
|
|
||||||
|
|
||||||
AttrValue* values;
|
AttrValue* values;
|
||||||
uint32 count;
|
status_t result = fRoot->GetLocations(&values);
|
||||||
result = reply.GetAttr(&values, &count);
|
if (result != B_OK)
|
||||||
if (result != B_OK || count < 1)
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
FSLocations* locs =
|
FSLocations* locs =
|
||||||
@@ -358,6 +268,10 @@ Filesystem::Migrate(const Filehandle& fh, const RPC::Server* serv)
|
|||||||
if (server == fServer)
|
if (server == fServer)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
|
NFS4Server* old = reinterpret_cast<NFS4Server*>(server->PrivateData());
|
||||||
|
old->RemoveFilesystem(this);
|
||||||
|
NFSServer()->AddFilesystem(this);
|
||||||
|
|
||||||
gRPCServerManager->Release(server);
|
gRPCServerManager->Release(server);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -9,15 +9,13 @@
|
|||||||
#define FILESYSTEM_H
|
#define FILESYSTEM_H
|
||||||
|
|
||||||
|
|
||||||
#include <fs_info.h>
|
|
||||||
|
|
||||||
#include "InodeIdMap.h"
|
#include "InodeIdMap.h"
|
||||||
#include "NFS4Defs.h"
|
#include "NFS4Defs.h"
|
||||||
#include "NFS4Server.h"
|
#include "NFS4Server.h"
|
||||||
|
|
||||||
|
|
||||||
class Inode;
|
class Inode;
|
||||||
class InodeIdMap;
|
class RootInode;
|
||||||
|
|
||||||
class Filesystem {
|
class Filesystem {
|
||||||
public:
|
public:
|
||||||
@@ -26,12 +24,9 @@ public:
|
|||||||
~Filesystem();
|
~Filesystem();
|
||||||
|
|
||||||
status_t GetInode(ino_t id, Inode** inode);
|
status_t GetInode(ino_t id, Inode** inode);
|
||||||
Inode* CreateRootInode();
|
inline Inode* Root();
|
||||||
|
|
||||||
status_t ReadInfo(struct fs_info* info);
|
status_t Migrate(const RPC::Server* serv);
|
||||||
|
|
||||||
status_t Migrate(const Filehandle& fh,
|
|
||||||
const RPC::Server* serv);
|
|
||||||
|
|
||||||
OpenFileCookie* OpenFilesLock();
|
OpenFileCookie* OpenFilesLock();
|
||||||
void OpenFilesUnlock();
|
void OpenFilesUnlock();
|
||||||
@@ -67,11 +62,8 @@ private:
|
|||||||
|
|
||||||
FilesystemId fFsId;
|
FilesystemId fFsId;
|
||||||
const char* fPath;
|
const char* fPath;
|
||||||
mutex fMigrationLock;
|
|
||||||
|
|
||||||
const char* fName;
|
RootInode* fRoot;
|
||||||
FileInfo fRoot;
|
|
||||||
Filehandle fRootFH;
|
|
||||||
|
|
||||||
RPC::Server* fServer;
|
RPC::Server* fServer;
|
||||||
|
|
||||||
@@ -82,6 +74,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline Inode*
|
||||||
|
Filesystem::Root()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<Inode*>(fRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint32
|
inline uint32
|
||||||
Filesystem::OpenFilesCount()
|
Filesystem::OpenFilesCount()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
#include "RootInode.h"
|
||||||
|
|
||||||
|
|
||||||
Inode::Inode()
|
Inode::Inode()
|
||||||
@@ -25,7 +26,12 @@ Inode::Inode()
|
|||||||
status_t
|
status_t
|
||||||
Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
||||||
{
|
{
|
||||||
Inode* inode = new(std::nothrow) Inode;
|
Inode* inode = NULL;
|
||||||
|
if (fs->Root() == NULL)
|
||||||
|
inode = new(std::nothrow) RootInode;
|
||||||
|
else
|
||||||
|
inode = new(std::nothrow) Inode;
|
||||||
|
|
||||||
if (inode == NULL)
|
if (inode == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -215,8 +221,7 @@ Inode::Link(Inode* dir, const char* name)
|
|||||||
|
|
||||||
// filesystem has been moved
|
// filesystem has been moved
|
||||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||||
fFilesystem->Migrate(fHandle, serv);
|
fFilesystem->Migrate(serv);
|
||||||
dir->fFilesystem->Migrate(dir->fHandle, serv);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,8 +326,7 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName)
|
|||||||
|
|
||||||
// filesystem has been moved
|
// filesystem has been moved
|
||||||
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||||
from->fFilesystem->Migrate(from->fHandle, serv);
|
from->fFilesystem->Migrate(serv);
|
||||||
to->fFilesystem->Migrate(to->fHandle, serv);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1557,13 +1561,9 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// filesystem has been moved
|
// filesystem has been moved
|
||||||
case NFS4ERR_MOVED:
|
|
||||||
fFilesystem->Migrate(fHandle, serv);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// lease has been moved, provoke server to return NFS4ERR_MOVED
|
|
||||||
case NFS4ERR_LEASE_MOVED:
|
case NFS4ERR_LEASE_MOVED:
|
||||||
Access(0);
|
case NFS4ERR_MOVED:
|
||||||
|
fFilesystem->Migrate(serv);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
status_t ReleaseAllLocks(OpenFileCookie* cookie);
|
status_t ReleaseAllLocks(OpenFileCookie* cookie);
|
||||||
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Inode();
|
Inode();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ KernelAddon nfs4 :
|
|||||||
ReplyInterpreter.cpp
|
ReplyInterpreter.cpp
|
||||||
Request.cpp
|
Request.cpp
|
||||||
RequestBuilder.cpp
|
RequestBuilder.cpp
|
||||||
|
RootInode.cpp
|
||||||
RPCAuth.cpp
|
RPCAuth.cpp
|
||||||
RPCCall.cpp
|
RPCCall.cpp
|
||||||
RPCReply.cpp
|
RPCReply.cpp
|
||||||
|
|||||||
@@ -213,6 +213,21 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
NFS4Server::FilesystemMigrated()
|
||||||
|
{
|
||||||
|
// reclaim all opened files and held locks from all filesystems
|
||||||
|
MutexLocker _(fFSLock);
|
||||||
|
Filesystem* fs = fFilesystems;
|
||||||
|
while (fs != NULL) {
|
||||||
|
fs->Migrate(fServer);
|
||||||
|
fs = fs->fNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
NFS4Server::_GetLeaseTime()
|
NFS4Server::_GetLeaseTime()
|
||||||
{
|
{
|
||||||
@@ -297,9 +312,14 @@ NFS4Server::_Renewal()
|
|||||||
request.Builder().Renew(fClientId);
|
request.Builder().Renew(fClientId);
|
||||||
request.Send();
|
request.Send();
|
||||||
|
|
||||||
if (request.Reply().NFS4Error() == NFS4ERR_STALE_CLIENTID)
|
switch (request.Reply().NFS4Error()) {
|
||||||
ServerRebooted(clientId);
|
case NFS4ERR_STALE_CLIENTID:
|
||||||
// TODO: support NFS4ERR_LEASE_MOVED
|
ServerRebooted(clientId);
|
||||||
|
break;
|
||||||
|
case NFS4ERR_LEASE_MOVED:
|
||||||
|
FilesystemMigrated();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
virtual ~NFS4Server();
|
virtual ~NFS4Server();
|
||||||
|
|
||||||
uint64 ServerRebooted(uint64 clientId);
|
uint64 ServerRebooted(uint64 clientId);
|
||||||
|
status_t FilesystemMigrated();
|
||||||
|
|
||||||
void AddFilesystem(Filesystem* fs);
|
void AddFilesystem(Filesystem* fs);
|
||||||
void RemoveFilesystem(Filesystem* fs);
|
void RemoveFilesystem(Filesystem* fs);
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, pdziepak@quarnos.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "RootInode.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RootInode::ReadInfo(struct fs_info* info)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFilesystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fHandle);
|
||||||
|
Attribute attr[] = { FATTR4_FILES_FREE, FATTR4_FILES_TOTAL,
|
||||||
|
FATTR4_MAXREAD, FATTR4_MAXWRITE, FATTR4_SPACE_FREE,
|
||||||
|
FATTR4_SPACE_TOTAL };
|
||||||
|
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||||
|
|
||||||
|
status_t result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
if (_HandleErrors(reply.NFS4Error(), serv))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
reply.PutFH();
|
||||||
|
|
||||||
|
AttrValue* values;
|
||||||
|
uint32 count, next = 0;
|
||||||
|
result = reply.GetAttr(&values, &count);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (count >= next && values[next].fAttribute == FATTR4_FILES_FREE) {
|
||||||
|
info->free_nodes = values[next].fData.fValue64;
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= next && values[next].fAttribute == FATTR4_FILES_TOTAL) {
|
||||||
|
info->total_nodes = values[next].fData.fValue64;
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 io_size = LONGLONG_MAX;
|
||||||
|
if (count >= next && values[next].fAttribute == FATTR4_MAXREAD) {
|
||||||
|
io_size = min_c(io_size, values[next].fData.fValue64);
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= next && values[next].fAttribute == FATTR4_MAXWRITE) {
|
||||||
|
io_size = min_c(io_size, values[next].fData.fValue64);
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io_size == LONGLONG_MAX)
|
||||||
|
io_size = 32768;
|
||||||
|
info->io_size = io_size;
|
||||||
|
info->block_size = io_size;
|
||||||
|
|
||||||
|
if (count >= next && values[next].fAttribute == FATTR4_SPACE_FREE) {
|
||||||
|
info->free_blocks = values[next].fData.fValue64 / io_size;
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= next && values[next].fAttribute == FATTR4_SPACE_TOTAL) {
|
||||||
|
info->total_blocks = values[next].fData.fValue64 / io_size;
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] values;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
info->flags = 0;
|
||||||
|
strncpy(info->volume_name, fName, B_FILE_NAME_LENGTH);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
RootInode::ProbeMigration()
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFilesystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fHandle);
|
||||||
|
req.Access();
|
||||||
|
|
||||||
|
status_t result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_MOVED)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (_HandleErrors(reply.NFS4Error(), serv))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RootInode::GetLocations(AttrValue** attrv)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFilesystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fHandle);
|
||||||
|
Attribute attr[] = { FATTR4_FS_LOCATIONS };
|
||||||
|
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||||
|
|
||||||
|
status_t result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
if (_HandleErrors(reply.NFS4Error(), serv))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
reply.PutFH();
|
||||||
|
|
||||||
|
uint32 count;
|
||||||
|
result = reply.GetAttr(attrv, &count);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
if (count < 1)
|
||||||
|
return B_ERROR;
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, pdziepak@quarnos.org
|
||||||
|
*/
|
||||||
|
#ifndef ROOTINODE_H
|
||||||
|
#define ROOTINODE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <fs_info.h>
|
||||||
|
|
||||||
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
|
class RootInode : public Inode {
|
||||||
|
public:
|
||||||
|
status_t ReadInfo(struct fs_info* info);
|
||||||
|
|
||||||
|
bool ProbeMigration();
|
||||||
|
status_t GetLocations(AttrValue** attr);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ROOTINODE_H
|
||||||
|
|
||||||
@@ -14,12 +14,13 @@
|
|||||||
#include <fs_interface.h>
|
#include <fs_interface.h>
|
||||||
|
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "RPCServer.h"
|
#include "Filesystem.h"
|
||||||
#include "NFS4Defs.h"
|
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
#include "NFS4Defs.h"
|
||||||
#include "RequestBuilder.h"
|
#include "RequestBuilder.h"
|
||||||
#include "ReplyInterpreter.h"
|
#include "ReplyInterpreter.h"
|
||||||
#include "Filesystem.h"
|
#include "RootInode.h"
|
||||||
|
#include "RPCServer.h"
|
||||||
|
|
||||||
|
|
||||||
extern fs_volume_ops gNFSv4VolumeOps;
|
extern fs_volume_ops gNFSv4VolumeOps;
|
||||||
@@ -107,7 +108,7 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inode* inode = fs->CreateRootInode();
|
Inode* inode = fs->Root();
|
||||||
if (inode == NULL) {
|
if (inode == NULL) {
|
||||||
delete fs;
|
delete fs;
|
||||||
gRPCServerManager->Release(server);
|
gRPCServerManager->Release(server);
|
||||||
@@ -166,7 +167,8 @@ static status_t
|
|||||||
nfs4_read_fs_info(fs_volume* volume, struct fs_info* info)
|
nfs4_read_fs_info(fs_volume* volume, struct fs_info* info)
|
||||||
{
|
{
|
||||||
Filesystem* fs = reinterpret_cast<Filesystem*>(volume->private_volume);
|
Filesystem* fs = reinterpret_cast<Filesystem*>(volume->private_volume);
|
||||||
return fs->ReadInfo(info);
|
RootInode* inode = reinterpret_cast<RootInode*>(fs->Root());
|
||||||
|
return inode->ReadInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -196,7 +198,11 @@ nfs4_get_vnode_name(fs_volume* volume, fs_vnode* vnode, char* buffer,
|
|||||||
static status_t
|
static status_t
|
||||||
nfs4_put_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter)
|
nfs4_put_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter)
|
||||||
{
|
{
|
||||||
|
Filesystem* fs = reinterpret_cast<Filesystem*>(volume->private_volume);
|
||||||
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||||
|
if (fs->Root() == inode)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
inode->FileSystem()->InoIdMap()->RemoveEntry(inode->ID());
|
inode->FileSystem()->InoIdMap()->RemoveEntry(inode->ID());
|
||||||
delete inode;
|
delete inode;
|
||||||
|
|
||||||
@@ -211,7 +217,11 @@ nfs4_remove_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter)
|
|||||||
// side are only an attempt to simulate local filesystem. Hence,
|
// side are only an attempt to simulate local filesystem. Hence,
|
||||||
// this hook is the same as put_vnode().
|
// this hook is the same as put_vnode().
|
||||||
|
|
||||||
|
Filesystem* fs = reinterpret_cast<Filesystem*>(volume->private_volume);
|
||||||
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||||
|
if (fs->Root() == inode)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
inode->FileSystem()->InoIdMap()->RemoveEntry(inode->ID());
|
inode->FileSystem()->InoIdMap()->RemoveEntry(inode->ID());
|
||||||
delete inode;
|
delete inode;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user