nfs4: Add link() hook

This commit is contained in:
Pawel Dziepak
2012-06-29 02:15:04 +02:00
parent cf511f2446
commit c0de7aca1c
8 changed files with 97 additions and 1 deletions
@@ -210,6 +210,56 @@ Inode::LookUp(const char* name, ino_t* id)
} }
status_t
Inode::Link(Inode* dir, const char* name)
{
do {
RPC::Server* serv = fFilesystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
req.SaveFH();
req.PutFH(dir->fHandle);
req.Link(name);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
// filehandle has expired
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
_LookUpFilehandle();
dir->_LookUpFilehandle();
continue;
}
// filesystem has been moved
if (reply.NFS4Error() == NFS4ERR_MOVED) {
fFilesystem->Migrate(fHandle, serv);
dir->fFilesystem->Migrate(dir->fHandle, serv);
continue;
}
result = reply.PutFH();
if (result != B_OK)
return result;
result = reply.SaveFH();
if (result != B_OK)
return result;
result = reply.PutFH();
if (result != B_OK)
return result;
return reply.Link();
} while (true);
}
// May cause problem similar to Rename (described below). When node's is has // May cause problem similar to Rename (described below). When node's is has
// more than one hard link and we delete the name it stores for filehandle // more than one hard link and we delete the name it stores for filehandle
// restoration node will inocorectly become unavailable. // restoration node will inocorectly become unavailable.
@@ -32,6 +32,7 @@ public:
status_t LookUp(const char* name, ino_t* id); status_t LookUp(const char* name, ino_t* id);
status_t ReadLink(void* buffer, size_t* length); status_t ReadLink(void* buffer, size_t* length);
status_t Link(Inode* dir, const char* name);
status_t Remove(const char* name, FileType type); status_t Remove(const char* name, FileType type);
static status_t Rename(Inode* from, Inode* to, static status_t Rename(Inode* from, Inode* to,
const char* fromName, const char* toName); const char* fromName, const char* toName);
@@ -25,6 +25,7 @@ enum Opcode {
OpClose = 4, OpClose = 4,
OpGetAttr = 9, OpGetAttr = 9,
OpGetFH = 10, OpGetFH = 10,
OpLink = 11,
OpLookUp = 15, OpLookUp = 15,
OpLookUpUp = 16, OpLookUpUp = 16,
OpOpen = 18, OpOpen = 18,
@@ -173,6 +173,21 @@ ReplyInterpreter::GetFH(Filehandle* fh)
} }
status_t
ReplyInterpreter::Link()
{
status_t res = _OperationError(OpLink);
if (res != B_OK)
return res;
fReply->Stream().GetBoolean();
fReply->Stream().GetUHyper();
fReply->Stream().GetUHyper();
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
}
status_t status_t
ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm) ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm)
{ {
@@ -68,6 +68,7 @@ public:
status_t Close(); status_t Close();
status_t GetAttr(AttrValue** attrs, uint32* count); status_t GetAttr(AttrValue** attrs, uint32* count);
status_t GetFH(Filehandle* fh); status_t GetFH(Filehandle* fh);
status_t Link();
inline status_t LookUp(); inline status_t LookUp();
inline status_t LookUpUp(); inline status_t LookUpUp();
status_t Open(uint32* id, uint32* seq, bool* confirm); status_t Open(uint32* id, uint32* seq, bool* confirm);
@@ -118,6 +118,24 @@ RequestBuilder::GetFH()
} }
status_t
RequestBuilder::Link(const char* name)
{
if (fProcedure != ProcCompound)
return B_BAD_VALUE;
if (fRequest == NULL)
return B_NO_MEMORY;
if (name == NULL)
return B_BAD_VALUE;
fRequest->Stream().AddUInt(OpLink);
fRequest->Stream().AddString(name);
fOpCount++;
return B_OK;
}
status_t status_t
RequestBuilder::LookUp(const char* name) RequestBuilder::LookUp(const char* name)
{ {
@@ -30,6 +30,7 @@ public:
uint32 stateSeq); uint32 stateSeq);
status_t GetAttr(Attribute* attrs, uint32 count); status_t GetAttr(Attribute* attrs, uint32 count);
status_t GetFH(); status_t GetFH();
status_t Link(const char* name);
status_t LookUp(const char* name); status_t LookUp(const char* name);
status_t LookUpUp(); status_t LookUpUp();
status_t Open(OpenClaim claim, uint32 seq, status_t Open(OpenClaim claim, uint32 seq,
@@ -212,6 +212,15 @@ nfs4_read_symlink(fs_volume* volume, fs_vnode* link, char* buffer,
} }
static status_t
nfs4_link(fs_volume* volume, fs_vnode* dir, const char* name, fs_vnode* vnode)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
Inode* dirInode = reinterpret_cast<Inode*>(dir->private_node);
return inode->Link(dirInode, name);
}
static status_t static status_t
nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name) nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name)
{ {
@@ -449,7 +458,7 @@ fs_vnode_ops gNFSv4VnodeOps = {
nfs4_read_symlink, nfs4_read_symlink,
NULL, // create_symlink() NULL, // create_symlink()
NULL, // link() nfs4_link,
nfs4_unlink, nfs4_unlink,
nfs4_rename, nfs4_rename,