From c0de7aca1ccdb82519b67c63dfc5f4586fb9b368 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 22 Jun 2012 02:27:49 +0200 Subject: [PATCH] nfs4: Add link() hook --- .../kernel/file_systems/nfs4/Inode.cpp | 50 +++++++++++++++++++ src/add-ons/kernel/file_systems/nfs4/Inode.h | 1 + .../kernel/file_systems/nfs4/NFS4Defs.h | 1 + .../file_systems/nfs4/ReplyInterpreter.cpp | 15 ++++++ .../file_systems/nfs4/ReplyInterpreter.h | 1 + .../file_systems/nfs4/RequestBuilder.cpp | 18 +++++++ .../kernel/file_systems/nfs4/RequestBuilder.h | 1 + .../file_systems/nfs4/kernel_interface.cpp | 11 +++- 8 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index f7c837c35b..2d73127b89 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -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 // more than one hard link and we delete the name it stores for filehandle // restoration node will inocorectly become unavailable. diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 3f1498eecb..1809604c27 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -32,6 +32,7 @@ public: status_t LookUp(const char* name, ino_t* id); status_t ReadLink(void* buffer, size_t* length); + status_t Link(Inode* dir, const char* name); status_t Remove(const char* name, FileType type); static status_t Rename(Inode* from, Inode* to, const char* fromName, const char* toName); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 84d9b934a5..8a07f035c9 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -25,6 +25,7 @@ enum Opcode { OpClose = 4, OpGetAttr = 9, OpGetFH = 10, + OpLink = 11, OpLookUp = 15, OpLookUpUp = 16, OpOpen = 18, diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index 003e31f585..3e133faf48 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -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 ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm) { diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index b0b3ba1411..51fd364514 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -68,6 +68,7 @@ public: status_t Close(); status_t GetAttr(AttrValue** attrs, uint32* count); status_t GetFH(Filehandle* fh); + status_t Link(); inline status_t LookUp(); inline status_t LookUpUp(); status_t Open(uint32* id, uint32* seq, bool* confirm); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index e28bce3916..4ce72edc8e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -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 RequestBuilder::LookUp(const char* name) { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 795d6106be..9710cf171e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -30,6 +30,7 @@ public: uint32 stateSeq); status_t GetAttr(Attribute* attrs, uint32 count); status_t GetFH(); + status_t Link(const char* name); status_t LookUp(const char* name); status_t LookUpUp(); status_t Open(OpenClaim claim, uint32 seq, diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index f784dbf740..e8f7b2949f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -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(vnode->private_node); + Inode* dirInode = reinterpret_cast(dir->private_node); + return inode->Link(dirInode, name); +} + + static status_t nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name) { @@ -449,7 +458,7 @@ fs_vnode_ops gNFSv4VnodeOps = { nfs4_read_symlink, NULL, // create_symlink() - NULL, // link() + nfs4_link, nfs4_unlink, nfs4_rename,