nfs4: Add write_stat() hook
This commit is contained in:
parent
684d0a1036
commit
abba2fddf1
@ -12,6 +12,8 @@
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <NodeMonitor.h>
|
||||
|
||||
#include "Request.h"
|
||||
|
||||
|
||||
@ -554,6 +556,93 @@ Inode::Stat(struct stat* st)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::WriteStat(const struct stat* st, uint32 mask)
|
||||
{
|
||||
status_t result;
|
||||
OpenFileCookie* cookie = NULL;
|
||||
AttrValue attr[4];
|
||||
uint32 i = 0;
|
||||
|
||||
if ((mask & B_STAT_SIZE) != 0) {
|
||||
delete cookie;
|
||||
cookie = new OpenFileCookie;
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
result = Open(O_WRONLY, cookie);
|
||||
if (result != B_OK) {
|
||||
delete cookie;
|
||||
return result;
|
||||
}
|
||||
|
||||
attr[i].fAttribute = FATTR4_SIZE;
|
||||
attr[i].fFreePointer = false;
|
||||
attr[i].fData.fValue64 = st->st_size;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((mask & B_STAT_MODE) != 0) {
|
||||
attr[i].fAttribute = FATTR4_MODE;
|
||||
attr[i].fFreePointer = false;
|
||||
attr[i].fData.fValue32 = st->st_mode;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((mask & B_STAT_ACCESS_TIME) != 0) {
|
||||
attr[i].fAttribute = FATTR4_TIME_ACCESS_SET;
|
||||
attr[i].fFreePointer = true;
|
||||
attr[i].fData.fPointer = malloc(sizeof(st->st_atime));
|
||||
memcpy(attr[i].fData.fPointer, &st->st_atime, sizeof(st->st_atime));
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((mask & B_STAT_MODIFICATION_TIME) != 0) {
|
||||
attr[i].fAttribute = FATTR4_TIME_MODIFY_SET;
|
||||
attr[i].fFreePointer = true;
|
||||
attr[i].fData.fPointer = malloc(sizeof(st->st_mtime));
|
||||
memcpy(attr[i].fData.fPointer, &st->st_mtime, sizeof(st->st_mtime));
|
||||
i++;
|
||||
}
|
||||
|
||||
do {
|
||||
RPC::Server* serv = fFilesystem->Server();
|
||||
Request request(serv);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fHandle);
|
||||
if ((mask & B_STAT_SIZE) != 0)
|
||||
req.SetAttr(cookie->fStateId, cookie->fStateSeq, attr, i);
|
||||
else
|
||||
req.SetAttr(NULL, 0, attr, i);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK) {
|
||||
Close(cookie);
|
||||
delete cookie;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReplyInterpreter& reply = request.Reply();
|
||||
|
||||
if (_HandleErrors(reply.NFS4Error(), serv))
|
||||
continue;
|
||||
|
||||
reply.PutFH();
|
||||
result = reply.SetAttr();
|
||||
|
||||
if ((mask & B_STAT_SIZE) != 0) {
|
||||
Close(cookie);
|
||||
delete cookie;
|
||||
}
|
||||
|
||||
return result;
|
||||
} while (true);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static OpenAccess
|
||||
sModeToAccess(int mode)
|
||||
{
|
||||
|
@ -40,8 +40,10 @@ public:
|
||||
status_t Remove(const char* name, FileType type);
|
||||
static status_t Rename(Inode* from, Inode* to,
|
||||
const char* fromName, const char* toName);
|
||||
|
||||
status_t Access(int mode);
|
||||
status_t Stat(struct stat* st);
|
||||
status_t WriteStat(const struct stat* st, uint32 mask);
|
||||
|
||||
status_t Create(const char* name, int mode, int perms,
|
||||
OpenFileCookie* cookie, ino_t* id);
|
||||
|
@ -41,6 +41,7 @@ enum Opcode {
|
||||
OpRename = 29,
|
||||
OpRenew = 30,
|
||||
OpSaveFH = 32,
|
||||
OpSetAttr = 34,
|
||||
OpSetClientID = 35,
|
||||
OpSetClientIDConfirm = 36,
|
||||
OpVerify = 37,
|
||||
|
@ -359,6 +359,21 @@ ReplyInterpreter::Rename()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyInterpreter::SetAttr()
|
||||
{
|
||||
status_t res = _OperationError(OpSetAttr);
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
uint32 bcount = fReply->Stream().GetUInt();
|
||||
for (uint32 i = 0; i < bcount; i++)
|
||||
fReply->Stream().GetUInt();
|
||||
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyInterpreter::SetClientID(uint64* clientid, uint64* verifier)
|
||||
{
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
status_t Rename();
|
||||
inline status_t Renew();
|
||||
inline status_t SaveFH();
|
||||
status_t SetAttr();
|
||||
status_t SetClientID(uint64* clientid, uint64* verifier);
|
||||
inline status_t SetClientIDConfirm();
|
||||
inline status_t Verify();
|
||||
|
@ -444,6 +444,34 @@ RequestBuilder::SaveFH()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::SetAttr(const uint32* id, uint32 stateSeq, AttrValue* attr,
|
||||
uint32 count)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpSetAttr);
|
||||
fRequest->Stream().AddUInt(stateSeq);
|
||||
if (id != NULL) {
|
||||
fRequest->Stream().AddUInt(id[0]);
|
||||
fRequest->Stream().AddUInt(id[1]);
|
||||
fRequest->Stream().AddUInt(id[2]);
|
||||
} else {
|
||||
fRequest->Stream().AddUInt(0);
|
||||
fRequest->Stream().AddUInt(0);
|
||||
fRequest->Stream().AddUInt(0);
|
||||
}
|
||||
_EncodeAttrs(fRequest->Stream(), attr, count);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::SetClientID(const RPC::Server* serv)
|
||||
{
|
||||
@ -601,6 +629,28 @@ RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr,
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < count && attr[i].fAttribute == FATTR4_TIME_ACCESS_SET) {
|
||||
str.AddInt(1); // SET_TO_CLIENT_TIME4
|
||||
|
||||
struct timespec* ts =
|
||||
reinterpret_cast<timespec*>(attr[i].fData.fPointer);
|
||||
str.AddHyper(ts->tv_sec);
|
||||
str.AddUInt(ts->tv_nsec);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < count && attr[i].fAttribute == FATTR4_TIME_MODIFY_SET) {
|
||||
str.AddInt(1); // SET_TO_CLIENT_TIME4
|
||||
|
||||
struct timespec* ts =
|
||||
reinterpret_cast<timespec*>(attr[i].fData.fPointer);
|
||||
str.AddHyper(ts->tv_sec);
|
||||
str.AddUInt(ts->tv_nsec);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
stream.AddOpaque(str);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
status_t Rename(const char* from, const char* to);
|
||||
status_t Renew(uint64 clientId);
|
||||
status_t SaveFH();
|
||||
status_t SetAttr(const uint32* id, uint32 stateSeq,
|
||||
AttrValue* attr, uint32 count);
|
||||
status_t SetClientID(const RPC::Server* serv);
|
||||
status_t SetClientIDConfirm(uint64 id, uint64 ver);
|
||||
status_t Verify(AttrValue* attr, uint32 count);
|
||||
|
@ -264,6 +264,15 @@ nfs4_read_stat(fs_volume* volume, fs_vnode* vnode, struct stat* stat)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
nfs4_write_stat(fs_volume* volume, fs_vnode* vnode, const struct stat* stat,
|
||||
uint32 statMask)
|
||||
{
|
||||
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||
return inode->WriteStat(stat, statMask);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
nfs4_create(fs_volume* volume, fs_vnode* dir, const char* name, int openMode,
|
||||
int perms, void** _cookie, ino_t* _newVnodeID)
|
||||
@ -523,7 +532,7 @@ fs_vnode_ops gNFSv4VnodeOps = {
|
||||
|
||||
nfs4_access,
|
||||
nfs4_read_stat,
|
||||
NULL, // write_stat()
|
||||
nfs4_write_stat,
|
||||
NULL, // fs_preallocate()
|
||||
|
||||
/* file operations */
|
||||
|
Loading…
Reference in New Issue
Block a user