nfs4: Add support for CB_GETATTR
This commit is contained in:
@@ -34,6 +34,9 @@ public:
|
||||
|
||||
inline uint64 MaxFileSize();
|
||||
|
||||
inline uint64 Change();
|
||||
inline bool Dirty();
|
||||
|
||||
void SetDelegation(Delegation* delegation);
|
||||
void RecallDelegation(bool truncate = false);
|
||||
void RecallReadDelegation();
|
||||
@@ -195,5 +198,19 @@ Inode::MaxFileSize()
|
||||
}
|
||||
|
||||
|
||||
inline uint64
|
||||
Inode::Change()
|
||||
{
|
||||
return fChange;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
Inode::Dirty()
|
||||
{
|
||||
return fWriteDirty;
|
||||
}
|
||||
|
||||
|
||||
#endif // INODE_H
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ Inode::CreateState(const char* name, int mode, int perms, OpenState* state,
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
RevalidateFileCache();
|
||||
|
||||
FileInfo fi;
|
||||
fi.fFileId = fileID;
|
||||
fi.fHandle = handle;
|
||||
|
||||
@@ -26,6 +26,7 @@ enum CallbackProcedure {
|
||||
};
|
||||
|
||||
enum CallbackOpcode {
|
||||
OpCallbackGetAttr = 3,
|
||||
OpCallbackRecall = 4
|
||||
};
|
||||
|
||||
@@ -135,6 +136,10 @@ enum Attribute {
|
||||
FATTR4_MAXIMUM_ATTR_ID
|
||||
};
|
||||
|
||||
enum CallbackAttr {
|
||||
CallbackAttrSize = 1,
|
||||
CallbackAttrChange = 2
|
||||
};
|
||||
|
||||
static inline bool sIsAttrSet(Attribute attr, const uint32* bitmap,
|
||||
uint32 count)
|
||||
|
||||
@@ -284,6 +284,9 @@ NFS4Server::ProcessCallback(RPC::CallbackRequest* request,
|
||||
|
||||
for (uint32 i = 0; i < count; i++) {
|
||||
switch (req.Operation()) {
|
||||
case OpCallbackGetAttr:
|
||||
result = CallbackGetAttr(&req, &reply);
|
||||
break;
|
||||
case OpCallbackRecall:
|
||||
result = CallbackRecall(&req, &reply);
|
||||
break;
|
||||
@@ -343,6 +346,48 @@ NFS4Server::CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::CallbackGetAttr(RequestInterpreter* request, ReplyBuilder* reply)
|
||||
{
|
||||
FileHandle handle;
|
||||
int mask;
|
||||
|
||||
status_t result = request->GetAttr(&handle, &mask);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
return B_OK;
|
||||
|
||||
MutexLocker locker(fFSLock);
|
||||
|
||||
Delegation* delegation = NULL;
|
||||
FileSystem* current = fFileSystems;
|
||||
while (current != NULL) {
|
||||
delegation = current->GetDelegation(handle);
|
||||
if (delegation != NULL)
|
||||
break;
|
||||
|
||||
current = current->fNext;
|
||||
}
|
||||
locker.Unlock();
|
||||
|
||||
if (delegation == NULL) {
|
||||
reply->GetAttr(B_FILE_NOT_FOUND, 0, 0, 0);
|
||||
return B_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
delegation->GetInode()->Stat(&st);
|
||||
|
||||
uint64 change;
|
||||
change = delegation->GetInode()->Change();
|
||||
if (delegation->GetInode()->Dirty())
|
||||
change++;
|
||||
reply->GetAttr(B_OK, mask, st.st_size, change);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::RecallAll()
|
||||
{
|
||||
|
||||
@@ -43,6 +43,9 @@ public:
|
||||
status_t CallbackRecall(RequestInterpreter* request,
|
||||
ReplyBuilder* reply);
|
||||
status_t RecallAll();
|
||||
|
||||
status_t CallbackGetAttr(RequestInterpreter* request,
|
||||
ReplyBuilder* reply);
|
||||
private:
|
||||
status_t _GetLeaseTime();
|
||||
|
||||
|
||||
@@ -56,6 +56,40 @@ ReplyBuilder::Reply()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyBuilder::GetAttr(status_t status, int mask, uint64 size, uint64 change)
|
||||
{
|
||||
if (fStatus != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
fReply->Stream().AddUInt(OpCallbackGetAttr);
|
||||
fReply->Stream().AddUInt(_HaikuErrorToNFS4(fStatus));
|
||||
fStatus = status;
|
||||
|
||||
if (status == B_OK) {
|
||||
uint32 bitmap = 0;
|
||||
if ((mask & CallbackAttrChange) != 0)
|
||||
bitmap |= 1 << FATTR4_CHANGE;
|
||||
if ((mask & CallbackAttrSize) != 0)
|
||||
bitmap |= 1 << FATTR4_SIZE;
|
||||
fReply->Stream().AddUInt(1);
|
||||
fReply->Stream().AddUInt(bitmap);
|
||||
|
||||
XDR::WriteStream str;
|
||||
if ((mask & CallbackAttrChange) != 0)
|
||||
str.AddUHyper(change);
|
||||
|
||||
if ((mask & CallbackAttrSize) != 0)
|
||||
str.AddUHyper(size);
|
||||
fReply->Stream().AddOpaque(str);
|
||||
}
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyBuilder::Recall(status_t status)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,8 @@ public:
|
||||
|
||||
RPC::CallbackReply* Reply();
|
||||
|
||||
status_t GetAttr(status_t status, int mask,
|
||||
uint64 size, uint64 change);
|
||||
status_t Recall(status_t status);
|
||||
|
||||
private:
|
||||
|
||||
@@ -28,6 +28,40 @@ RequestInterpreter::~RequestInterpreter()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestInterpreter::GetAttr(FileHandle* handle, int* _mask)
|
||||
{
|
||||
if (fLastOperation != OpCallbackGetAttr)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint32 size;
|
||||
const void* ptr = fRequest->Stream().GetOpaque(&size);
|
||||
handle->fSize = size;
|
||||
memcpy(handle->fData, ptr, size);
|
||||
|
||||
uint32 count = fRequest->Stream().GetUInt();
|
||||
if (count < 1) {
|
||||
*_mask = 0;
|
||||
return fRequest->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
uint32 bitmap = fRequest->Stream().GetUInt();
|
||||
uint32 mask = 0;
|
||||
|
||||
if ((bitmap & (1 << FATTR4_CHANGE)) != 0)
|
||||
mask |= CallbackAttrChange;
|
||||
if ((bitmap & (1 << FATTR4_SIZE)) != 0)
|
||||
mask |= CallbackAttrSize;
|
||||
|
||||
*_mask = mask;
|
||||
|
||||
for (uint32 i = 1; i < count; i++)
|
||||
fRequest->Stream().GetUInt();
|
||||
|
||||
return fRequest->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestInterpreter::Recall(FileHandle* handle, bool& truncate, uint32* stateSeq,
|
||||
uint32* stateID)
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
inline uint32 OperationCount();
|
||||
inline uint32 Operation();
|
||||
|
||||
status_t GetAttr(FileHandle* handle, int* mask);
|
||||
status_t Recall(FileHandle* handle, bool& truncate,
|
||||
uint32* stateSeq, uint32* stateID);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user