nfs4: Add write_stat() hook

This commit is contained in:
Pawel Dziepak 2012-06-26 23:16:23 +02:00
parent 684d0a1036
commit abba2fddf1
8 changed files with 170 additions and 1 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -41,6 +41,7 @@ enum Opcode {
OpRename = 29,
OpRenew = 30,
OpSaveFH = 32,
OpSetAttr = 34,
OpSetClientID = 35,
OpSetClientIDConfirm = 36,
OpVerify = 37,

View File

@ -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)
{

View File

@ -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();

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */