nfs4: Add unlink() and remove_dir() hooks
This commit is contained in:
@@ -210,6 +210,47 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
status_t
|
||||||
|
Inode::Remove(const char* name)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFilesystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fHandle);
|
||||||
|
req.Remove(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();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// filesystem has been moved
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||||
|
fFilesystem->Migrate(fHandle, serv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = reply.PutFH();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return reply.Remove();
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Rename may cause some problems if filehandles are volatile and local Inode
|
// Rename may cause some problems if filehandles are volatile and local Inode
|
||||||
// object exists for renamed node. It's stored filename will become invalid
|
// object exists for renamed node. It's stored filename will become invalid
|
||||||
// and, consequnetly, filehandle restoration will fail. Probably, it will
|
// and, consequnetly, filehandle restoration will fail. Probably, it will
|
||||||
|
|||||||
@@ -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 Remove(const char* name);
|
||||||
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);
|
||||||
status_t Access(int mode);
|
status_t Access(int mode);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ enum Opcode {
|
|||||||
OpRead = 25,
|
OpRead = 25,
|
||||||
OpReadDir = 26,
|
OpReadDir = 26,
|
||||||
OpReadLink = 27,
|
OpReadLink = 27,
|
||||||
|
OpRemove = 28,
|
||||||
OpRename = 29,
|
OpRename = 29,
|
||||||
OpRenew = 30,
|
OpRenew = 30,
|
||||||
OpSaveFH = 32,
|
OpSaveFH = 32,
|
||||||
|
|||||||
@@ -290,6 +290,21 @@ ReplyInterpreter::ReadLink(void* buffer, uint32* size, uint32 maxSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::Remove()
|
||||||
|
{
|
||||||
|
status_t res = _OperationError(OpRemove);
|
||||||
|
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::Rename()
|
ReplyInterpreter::Rename()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public:
|
|||||||
status_t ReadDir(uint64* cookie, uint64* cookieVerf,
|
status_t ReadDir(uint64* cookie, uint64* cookieVerf,
|
||||||
DirEntry** dirents, uint32* count, bool* eof);
|
DirEntry** dirents, uint32* count, bool* eof);
|
||||||
status_t ReadLink(void* buffer, uint32* size, uint32 maxSize);
|
status_t ReadLink(void* buffer, uint32* size, uint32 maxSize);
|
||||||
|
status_t Remove();
|
||||||
status_t Rename();
|
status_t Rename();
|
||||||
inline status_t Renew();
|
inline status_t Renew();
|
||||||
inline status_t SaveFH();
|
inline status_t SaveFH();
|
||||||
|
|||||||
@@ -308,6 +308,23 @@ RequestBuilder::ReadLink()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RequestBuilder::Remove(const char* file)
|
||||||
|
{
|
||||||
|
if (fProcedure != ProcCompound)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (fRequest == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fRequest->Stream().AddUInt(OpRemove);
|
||||||
|
fRequest->Stream().AddString(file);
|
||||||
|
|
||||||
|
fOpCount++;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
RequestBuilder::Rename(const char* from, const char* to)
|
RequestBuilder::Rename(const char* from, const char* to)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public:
|
|||||||
uint64 cookieVerf, Attribute* attrs,
|
uint64 cookieVerf, Attribute* attrs,
|
||||||
uint32 attrCount);
|
uint32 attrCount);
|
||||||
status_t ReadLink();
|
status_t ReadLink();
|
||||||
|
status_t Remove(const char* file);
|
||||||
status_t Rename(const char* from, const char* to);
|
status_t Rename(const char* from, const char* to);
|
||||||
status_t Renew(uint64 clientId);
|
status_t Renew(uint64 clientId);
|
||||||
status_t SaveFH();
|
status_t SaveFH();
|
||||||
|
|||||||
@@ -212,6 +212,14 @@ nfs4_read_symlink(fs_volume* volume, fs_vnode* link, char* buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name)
|
||||||
|
{
|
||||||
|
Inode* inode = reinterpret_cast<Inode*>(dir->private_node);
|
||||||
|
return inode->Remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_rename(fs_volume* volume, fs_vnode* fromDir, const char* fromName,
|
nfs4_rename(fs_volume* volume, fs_vnode* fromDir, const char* fromName,
|
||||||
fs_vnode* toDir, const char* toName)
|
fs_vnode* toDir, const char* toName)
|
||||||
@@ -309,6 +317,14 @@ nfs4_read(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
nfs4_remove_dir(fs_volume* volume, fs_vnode* parent, const char* name)
|
||||||
|
{
|
||||||
|
Inode* inode = reinterpret_cast<Inode*>(parent->private_node);
|
||||||
|
return inode->Remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
||||||
{
|
{
|
||||||
@@ -434,7 +450,7 @@ fs_vnode_ops gNFSv4VnodeOps = {
|
|||||||
NULL, // create_symlink()
|
NULL, // create_symlink()
|
||||||
|
|
||||||
NULL, // link()
|
NULL, // link()
|
||||||
NULL, // unlink()
|
nfs4_unlink,
|
||||||
nfs4_rename,
|
nfs4_rename,
|
||||||
|
|
||||||
nfs4_access,
|
nfs4_access,
|
||||||
@@ -452,7 +468,7 @@ fs_vnode_ops gNFSv4VnodeOps = {
|
|||||||
|
|
||||||
/* directory operations */
|
/* directory operations */
|
||||||
NULL, // create_dir()
|
NULL, // create_dir()
|
||||||
NULL, // remove_dir()
|
nfs4_remove_dir,
|
||||||
nfs4_open_dir,
|
nfs4_open_dir,
|
||||||
nfs4_close_dir,
|
nfs4_close_dir,
|
||||||
nfs4_free_dir_cookie,
|
nfs4_free_dir_cookie,
|
||||||
|
|||||||
Reference in New Issue
Block a user