nfs4: Add basic support for extended attributes

This commit is contained in:
Pawel Dziepak
2012-08-09 23:39:56 +02:00
parent 29fb3a4af2
commit 20d1b02eef
17 changed files with 475 additions and 121 deletions
@@ -73,11 +73,12 @@ struct Cookie {
status_t CancelAll();
};
struct OpenFileCookie : public Cookie {
struct OpenStateCookie : public Cookie {
OpenState* fOpenState;
uint32 fMode;
};
struct OpenFileCookie : public OpenStateCookie {
LockInfo* fLocks;
void AddLock(LockInfo* lock);
@@ -97,6 +98,8 @@ struct OpenDirCookie : public Cookie {
~OpenDirCookie();
};
struct OpenAttrCookie : public OpenStateCookie { };
#endif // COOKIE_H
@@ -14,11 +14,12 @@
Delegation::Delegation(const OpenDelegationData& data, Inode* inode,
uint64 clientID)
uint64 clientID, bool attribute)
:
fClientID(clientID),
fData(data),
fInode(inode)
fInode(inode),
fAttribute(attribute)
{
}
@@ -26,7 +27,7 @@ Delegation::Delegation(const OpenDelegationData& data, Inode* inode,
status_t
Delegation::GiveUp(bool truncate)
{
if (!truncate)
if (!fAttribute && !truncate)
fInode->SyncAndCommit(true);
ReturnDelegation();
@@ -21,7 +21,7 @@ class Delegation : public NFS4Object,
public DoublyLinkedListLinkImpl<Delegation> {
public:
Delegation(const OpenDelegationData& data, Inode* inode,
uint64 clientID);
uint64 clientID, bool attr = false);
status_t GiveUp(bool truncate = false);
@@ -35,6 +35,7 @@ private:
uint64 fClientID;
OpenDelegationData fData;
Inode* fInode;
bool fAttribute;
};
@@ -25,6 +25,8 @@ struct FileHandle {
inline FileHandle(const FileHandle& fh);
inline FileHandle& operator=(const FileHandle& fh);
inline bool operator!=(const FileHandle& handle) const;
inline bool operator>(const FileHandle& handle) const;
inline bool operator<(const FileHandle& handle) const;
};
@@ -92,6 +94,15 @@ FileHandle::operator=(const FileHandle& fh)
}
inline bool
FileHandle::operator!=(const FileHandle& handle) const
{
if (fSize != handle.fSize)
return true;
return memcmp(fData, handle.fData, fSize) != 0;
}
inline bool
FileHandle::operator>(const FileHandle& handle) const
{
+75 -37
View File
@@ -262,68 +262,100 @@ Inode::Link(Inode* dir, const char* name)
status_t
Inode::Remove(const char* name, FileType type)
{
if (type == NF4NAMEDATTR) {
status_t result = LoadAttrDirHandle();
if (result != B_OK)
return result;
}
ChangeInfo changeInfo;
uint64 fileID;
status_t result = NFS4Inode::RemoveObject(name, type, &changeInfo, &fileID);
if (result != B_OK)
return result;
if (fCache->Lock() == B_OK) {
DirectoryCache* cache = type != NF4NAMEDATTR ? fCache : fAttrCache;
if (cache->Lock() == B_OK) {
if (changeInfo.fAtomic
&& fCache->ChangeInfo() == changeInfo.fBefore) {
fCache->RemoveEntry(name);
fCache->SetChangeInfo(changeInfo.fAfter);
} else if (fCache->ChangeInfo() != changeInfo.fBefore)
fCache->Trash();
fCache->Unlock();
cache->RemoveEntry(name);
cache->SetChangeInfo(changeInfo.fAfter);
} else if (cache->ChangeInfo() != changeInfo.fBefore)
cache->Trash();
cache->Unlock();
}
fFileSystem->Root()->MakeInfoInvalid();
notify_entry_removed(fFileSystem->DevId(), ID(), name,
FileIdToInoT(fileID));
if (type == NF4NAMEDATTR) {
notify_attribute_changed(fFileSystem->DevId(), ID(), name,
B_ATTR_REMOVED);
} else {
notify_entry_removed(fFileSystem->DevId(), ID(), name,
FileIdToInoT(fileID));
}
return B_OK;
}
status_t
Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName)
Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName,
bool attribute)
{
if (from->fFileSystem != to->fFileSystem)
return B_DONT_DO_THAT;
if (attribute) {
status_t result = from->LoadAttrDirHandle();
if (result != B_OK)
return result;
result = to->LoadAttrDirHandle();
if (result != B_OK)
return result;
}
ChangeInfo fromChange, toChange;
uint64 fileID;
status_t result = NFS4Inode::Rename(from, to, fromName, toName, &fromChange,
&toChange, &fileID);
&toChange, &fileID, attribute);
if (result != B_OK)
return result;
from->fFileSystem->Root()->MakeInfoInvalid();
if (from->fCache->Lock() == B_OK) {
DirectoryCache* cache = attribute ? from->fAttrCache : from->fCache;
if (cache->Lock() == B_OK) {
if (fromChange.fAtomic
&& from->fCache->ChangeInfo() == fromChange.fBefore) {
from->fCache->RemoveEntry(fromName);
from->fCache->SetChangeInfo(fromChange.fAfter);
} else if (from->fCache->ChangeInfo() != fromChange.fBefore)
from->fCache->Trash();
from->fCache->Unlock();
&& cache->ChangeInfo() == fromChange.fBefore) {
cache->RemoveEntry(fromName);
cache->SetChangeInfo(fromChange.fAfter);
} else if (cache->ChangeInfo() != fromChange.fBefore)
cache->Trash();
cache->Unlock();
}
if (to->fCache->Lock() == B_OK) {
cache = attribute ? to->fAttrCache : to->fCache;
if (cache->Lock() == B_OK) {
if (toChange.fAtomic
&& to->fCache->ChangeInfo() == toChange.fBefore) {
to->fCache->AddEntry(toName, fileID, true);
to->fCache->SetChangeInfo(toChange.fAfter);
&& cache->ChangeInfo() == toChange.fBefore) {
cache->AddEntry(toName, fileID, true);
cache->SetChangeInfo(toChange.fAfter);
} else if (to->fCache->ChangeInfo() != toChange.fBefore)
to->fCache->Trash();
to->fCache->Unlock();
cache->Trash();
cache->Unlock();
}
notify_entry_moved(from->fFileSystem->DevId(), from->ID(), fromName,
to->ID(), toName, FileIdToInoT(fileID));
if (attribute) {
notify_attribute_changed(from->fFileSystem->DevId(), from->ID(),
fromName, B_ATTR_REMOVED);
notify_attribute_changed(to->fFileSystem->DevId(), to->ID(), toName,
B_ATTR_CREATED);
} else {
notify_entry_moved(from->fFileSystem->DevId(), from->ID(), fromName,
to->ID(), toName, FileIdToInoT(fileID));
}
return B_OK;
}
@@ -404,8 +436,11 @@ Inode::Access(int mode)
status_t
Inode::Stat(struct stat* st)
Inode::Stat(struct stat* st, OpenAttrCookie* attr)
{
if (attr != NULL)
return GetStat(st, attr);
status_t result = fMetaCache.GetStat(st);
if (result != B_OK) {
struct stat temp;
@@ -421,11 +456,11 @@ Inode::Stat(struct stat* st)
status_t
Inode::GetStat(struct stat* st)
Inode::GetStat(struct stat* st, OpenAttrCookie* attr)
{
AttrValue* values;
uint32 count;
status_t result = NFS4Inode::GetStat(&values, &count);
status_t result = NFS4Inode::GetStat(&values, &count, attr);
if (result != B_OK)
return result;
@@ -504,7 +539,7 @@ Inode::GetStat(struct stat* st)
status_t
Inode::WriteStat(const struct stat* st, uint32 mask)
Inode::WriteStat(const struct stat* st, uint32 mask, OpenAttrCookie* cookie)
{
status_t result;
AttrValue attr[6];
@@ -554,15 +589,18 @@ Inode::WriteStat(const struct stat* st, uint32 mask)
i++;
}
MutexLocker stateLocker(fStateLock);
result = NFS4Inode::WriteStat(fOpenState, attr, i);
stateLocker.Unlock();
if (cookie == NULL) {
MutexLocker stateLocker(fStateLock);
result = NFS4Inode::WriteStat(fOpenState, attr, i);
stateLocker.Unlock();
fMetaCache.InvalidateStat();
if ((mask & B_STAT_MODE) != 0 || (mask & B_STAT_UID) != 0
|| (mask & B_STAT_GID) != 0) {
fMetaCache.InvalidateAccess();
}
fMetaCache.InvalidateStat();
if ((mask & B_STAT_MODE) != 0 || (mask & B_STAT_UID) != 0
|| (mask & B_STAT_GID) != 0) {
fMetaCache.InvalidateAccess();
}
} else
result = NFS4Inode::WriteStat(cookie->fOpenState, attr, i);
return result;
}
+18 -6
View File
@@ -57,24 +57,33 @@ public:
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);
const char* fromName, const char* toName,
bool attribute = false);
status_t Stat(struct stat* st);
status_t WriteStat(const struct stat* st, uint32 mask);
status_t Stat(struct stat* st,
OpenAttrCookie* attr = NULL);
status_t WriteStat(const struct stat* st, uint32 mask,
OpenAttrCookie* attr = NULL);
status_t Create(const char* name, int mode, int perms,
OpenFileCookie* cookie,
OpenDelegationData* data, ino_t* id);
status_t Open(int mode, OpenFileCookie* cookie);
status_t Close(OpenFileCookie* cookie);
status_t OpenAttr(const char* name, int mode,
OpenAttrCookie* cookie, bool create,
int32 type = 0);
status_t CloseAttr(OpenAttrCookie* cookie);
status_t Read(OpenFileCookie* cookie, off_t pos,
void* buffer, size_t* length);
status_t Write(OpenFileCookie* cookie, off_t pos,
const void* buffer, size_t *_length);
status_t ReadDirect(OpenFileCookie* cookie, off_t pos,
status_t ReadDirect(OpenStateCookie* cookie, off_t pos,
void* buffer, size_t* length, bool* eof);
status_t WriteDirect(OpenFileCookie* cookie, off_t pos,
status_t WriteDirect(OpenStateCookie* cookie, off_t pos,
const void* buffer, size_t *_length);
status_t CreateDir(const char* name, int mode);
@@ -96,6 +105,8 @@ public:
_snapshot, OpenDirCookie* cookie,
uint64* _change, bool attribute);
status_t LoadAttrDirHandle();
protected:
Inode();
@@ -115,7 +126,8 @@ protected:
status_t ChildAdded(const char* name, uint64 fileID,
const FileHandle& fileHandle);
status_t GetStat(struct stat* st);
status_t GetStat(struct stat* st,
OpenAttrCookie* attr = NULL);
static inline status_t CheckLockType(short ltype, uint32 mode);
@@ -55,6 +55,13 @@ Inode::OpenAttrDir(OpenDirCookie* cookie)
cookie->fEOF = false;
cookie->fAttrDir = true;
return LoadAttrDirHandle();
}
status_t
Inode::LoadAttrDirHandle()
{
if (fInfo.fAttrDir.fSize == 0) {
FileHandle handle;
@@ -65,7 +72,7 @@ Inode::OpenAttrDir(OpenDirCookie* cookie)
fInfo.fAttrDir = handle;
}
return B_OK;
return B_OK;
}
@@ -193,7 +193,72 @@ Inode::Close(OpenFileCookie* cookie)
status_t
Inode::ReadDirect(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length,
Inode::OpenAttr(const char* name, int mode, OpenAttrCookie* cookie, bool create,
int32 type)
{
(void)type;
status_t result = LoadAttrDirHandle();
if (result != B_OK)
return result;
OpenDelegationData data;
data.fType = OPEN_DELEGATE_NONE;
OpenState* state = new OpenState;
if (state == NULL)
return B_NO_MEMORY;
state->fInfo.fName = name;
state->fInfo.fParent = fInfo.fAttrDir;
result = NFS4Inode::OpenAttr(state, name, mode, &data, create);
if (result != B_OK) {
delete state;
return result;
}
fFileSystem->AddOpenFile(state);
cookie->fOpenState = state;
cookie->fFileSystem = fFileSystem;
cookie->fMode = mode;
if (data.fType != OPEN_DELEGATE_NONE) {
Delegation* delegation
= new(std::nothrow) Delegation(data, this, fOpenState->fClientID,
true);
if (delegation != NULL) {
delegation->fInfo = state->fInfo;
delegation->fFileSystem = fFileSystem;
state->fDelegation = delegation;
fFileSystem->AddDelegation(delegation);
}
}
if ((mode & O_TRUNC) == O_TRUNC) {
struct stat st;
st.st_size = 0;
WriteStat(&st, B_STAT_SIZE, cookie);
}
return B_OK;
}
status_t
Inode::CloseAttr(OpenAttrCookie* cookie)
{
cookie->fOpenState->fDelegation->GiveUp();
fFileSystem->RemoveDelegation(cookie->fOpenState->fDelegation);
delete cookie->fOpenState->fDelegation;
delete cookie->fOpenState;
return B_OK;
}
status_t
Inode::ReadDirect(OpenStateCookie* cookie, off_t pos, void* buffer, size_t* _length,
bool* eof)
{
*eof = false;
@@ -203,9 +268,10 @@ Inode::ReadDirect(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _leng
*_length = min_c(ioSize, *_length);
status_t result;
OpenState* state = cookie != NULL ? cookie->fOpenState : fOpenState;
while (size < *_length && !*eof) {
uint32 len = *_length - size;
result = ReadFile(cookie, fOpenState, pos + size, &len,
result = ReadFile(cookie, state, pos + size, &len,
reinterpret_cast<char*>(buffer) + size, eof);
if (result != B_OK) {
if (size == 0)
@@ -234,7 +300,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
status_t
Inode::WriteDirect(OpenFileCookie* cookie, off_t pos, const void* _buffer,
Inode::WriteDirect(OpenStateCookie* cookie, off_t pos, const void* _buffer,
size_t *_length)
{
uint32 size = 0;
@@ -243,12 +309,20 @@ Inode::WriteDirect(OpenFileCookie* cookie, off_t pos, const void* _buffer,
uint32 ioSize = fFileSystem->Root()->IOSize();
*_length = min_c(ioSize, *_length);
fWriteDirty = true;
bool attribute = false;
OpenState* state = fOpenState;
if (cookie != NULL) {
attribute = cookie->fOpenState->fInfo.fHandle != fInfo.fHandle;
state = cookie->fOpenState;
}
if (!attribute)
fWriteDirty = true;
while (size < *_length) {
uint32 len = *_length - size;
status_t result = WriteFile(cookie, fOpenState, pos + size, &len,
buffer + size);
status_t result = WriteFile(cookie, state, pos + size,
&len, buffer + size, attribute);
if (result != B_OK) {
if (size == 0)
return result;
@@ -83,7 +83,10 @@ MetadataCache::GetAccess(uid_t uid, uint32* allowed)
if (!it.HasCurrent())
return B_ENTRY_NOT_FOUND;
if (it.Current().fExpire < time(NULL)) {
if (!fForceValid)
it.Current().fForceValid = false;
if (!it.Current().fForceValid && it.Current().fExpire < time(NULL)) {
it.Remove();
return B_ERROR;
}
@@ -105,6 +108,7 @@ MetadataCache::SetAccess(uid_t uid, uint32 allowed)
AccessEntry entry;
entry.fAllowed = allowed;
entry.fExpire = time(NULL) + kExpirationTime;
entry.fForceValid = fForceValid;
fAccessCache.Insert(uid, entry);
}
@@ -20,6 +20,8 @@ class Inode;
struct AccessEntry {
time_t fExpire;
bool fForceValid;
uint32 fAllowed;
};
@@ -245,14 +245,17 @@ NFS4Inode::ReadLink(void* buffer, size_t* length)
status_t
NFS4Inode::GetStat(AttrValue** values, uint32* count)
NFS4Inode::GetStat(AttrValue** values, uint32* count, OpenAttrCookie* cookie)
{
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
if (cookie != NULL)
req.PutFH(cookie->fOpenState->fInfo.fHandle);
else
req.PutFH(fInfo.fHandle);
Attribute attr[] = { FATTR4_SIZE, FATTR4_MODE, FATTR4_NUMLINKS,
FATTR4_OWNER, FATTR4_OWNER_GROUP,
@@ -260,7 +263,7 @@ NFS4Inode::GetStat(AttrValue** values, uint32* count)
FATTR4_TIME_METADATA, FATTR4_TIME_MODIFY };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
status_t result = request.Send();
status_t result = request.Send(cookie);
if (result != B_OK)
return result;
@@ -284,7 +287,7 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, uint32 attrCount)
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.PutFH(state->fInfo.fHandle);
if (state != NULL)
req.SetAttr(state->fStateID, state->fStateSeq, attrs, attrCount);
else
@@ -313,21 +316,29 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, uint32 attrCount)
status_t
NFS4Inode::Rename(Inode* from, Inode* to, const char* fromName,
const char* toName, ChangeInfo* fromChange, ChangeInfo* toChange,
uint64* fileID)
uint64* fileID, bool attribute)
{
do {
RPC::Server* serv = from->fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(from->fInfo.fHandle);
if (attribute)
req.PutFH(from->fInfo.fAttrDir);
else
req.PutFH(from->fInfo.fHandle);
req.SaveFH();
req.PutFH(to->fInfo.fHandle);
if (attribute)
req.PutFH(to->fInfo.fAttrDir);
else
req.PutFH(to->fInfo.fHandle);
req.Rename(fromName, toName);
Attribute attr[] = { FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
req.LookUp(toName);
if (!attribute) {
req.LookUp(toName);
Attribute attr[] = { FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
}
status_t result = request.Send();
if (result != B_OK)
@@ -358,22 +369,24 @@ NFS4Inode::Rename(Inode* from, Inode* to, const char* fromName,
if (result != B_OK)
return result;
result = reply.LookUp();
if (result != B_OK)
return result;
if (!attribute) {
result = reply.LookUp();
if (result != B_OK)
return result;
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK)
return result;
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK)
return result;
if (count == 0)
*fileID = from->fFileSystem->AllocFileId();
else
*fileID = values[0].fData.fValue64;
if (count == 0)
*fileID = from->fFileSystem->AllocFileId();
else
*fileID = values[0].fData.fValue64;
delete[] values;
delete[] values;
}
return B_OK;
} while (true);
@@ -581,7 +594,61 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation)
status_t
NFS4Inode::ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
NFS4Inode::OpenAttr(OpenState* state, const char* name, int mode,
OpenDelegationData* delegation, bool create)
{
bool confirm;
status_t result;
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
do {
state->fClientID = fFileSystem->NFSServer()->ClientId();
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fAttrDir);
req.Open(CLAIM_NULL, sequence, sModeToAccess(mode), state->fClientID,
create ? OPEN4_CREATE : OPEN4_NOCREATE, fFileSystem->OpenOwner(),
name);
req.GetFH();
result = request.Send();
if (result != B_OK) {
fFileSystem->OpenOwnerSequenceUnlock(false);
return result;
}
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv, NULL, state))
continue;
fFileSystem->OpenOwnerSequenceUnlock();
reply.PutFH();
result = reply.Open(state->fStateID, &state->fStateSeq, &confirm,
delegation);
reply.GetFH(&state->fInfo.fHandle);
if (result != B_OK)
return result;
break;
} while (true);
state->fOpened = true;
if (confirm)
return ConfirmOpen(fInfo.fHandle, state);
return B_OK;
}
status_t
NFS4Inode::ReadFile(OpenStateCookie* cookie, OpenState* state, uint64 position,
uint32* length, void* buffer, bool* eof)
{
do {
@@ -589,7 +656,7 @@ NFS4Inode::ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.PutFH(state->fInfo.fHandle);
req.Read(state->fStateID, state->fStateSeq, position, *length);
status_t result = request.Send(cookie);
@@ -612,8 +679,8 @@ NFS4Inode::ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
status_t
NFS4Inode::WriteFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
uint32* length, const void* buffer)
NFS4Inode::WriteFile(OpenStateCookie* cookie, OpenState* state, uint64 position,
uint32* length, const void* buffer, bool commit)
{
do {
@@ -621,9 +688,10 @@ NFS4Inode::WriteFile(OpenFileCookie* cookie, OpenState* state, uint64 position,
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle);
req.PutFH(state->fInfo.fHandle);
req.Write(state->fStateID, state->fStateSeq, buffer, position, *length);
req.Write(state->fStateID, state->fStateSeq, buffer, position, *length,
commit);
status_t result = request.Send(cookie);
if (result != B_OK)
@@ -757,8 +825,10 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo,
req.PutFH(fInfo.fHandle);
Attribute idAttr[] = { FATTR4_FILEID };
req.GetAttr(idAttr, sizeof(idAttr) / sizeof(Attribute));
if (type != NF4NAMEDATTR) {
Attribute idAttr[] = { FATTR4_FILEID };
req.GetAttr(idAttr, sizeof(idAttr) / sizeof(Attribute));
}
req.Remove(name);
@@ -790,17 +860,19 @@ NFS4Inode::RemoveObject(const char* name, FileType type, ChangeInfo* changeInfo,
reply.PutFH();
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK)
return result;
if (type != NF4NAMEDATTR) {
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK)
return result;
if (count == 0)
*fileID = fFileSystem->AllocFileId();
else
*fileID = values[0].fData.fValue64;
delete[] values;
if (count == 0)
*fileID = fFileSystem->AllocFileId();
else
*fileID = values[0].fData.fValue64;
delete[] values;
}
return reply.Remove(&changeInfo->fBefore, &changeInfo->fAfter,
changeInfo->fAtomic);
@@ -38,9 +38,11 @@ protected:
static status_t Rename(Inode* from, Inode* to, const char* fromName,
const char* toName, ChangeInfo* fromChange,
ChangeInfo* toChange, uint64* fileID);
ChangeInfo* toChange, uint64* fileID,
bool attribute = false);
status_t GetStat(AttrValue** values, uint32* count);
status_t GetStat(AttrValue** values, uint32* count,
OpenAttrCookie* attr = NULL);
status_t WriteStat(OpenState* state, AttrValue* attrs,
uint32 attrCount);
@@ -51,12 +53,15 @@ protected:
status_t OpenFile(OpenState* state, int mode,
OpenDelegationData* delegation);
status_t ReadFile(OpenFileCookie* cookie, OpenState* state,
status_t OpenAttr(OpenState* state, const char* name, int mode,
OpenDelegationData* delegation, bool create);
status_t ReadFile(OpenStateCookie* cookie, OpenState* state,
uint64 position, uint32* length, void* buffer,
bool* eof);
status_t WriteFile(OpenFileCookie* cookie, OpenState* state,
status_t WriteFile(OpenStateCookie* cookie, OpenState* state,
uint64 position, uint32* length,
const void* buffer);
const void* buffer, bool commit = false);
status_t CreateObject(const char* name, const char* path,
int mode, FileType type, ChangeInfo* changeInfo,
@@ -16,7 +16,7 @@
bool
NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
OpenFileCookie* cookie, OpenState* state)
OpenStateCookie* cookie, OpenState* state)
{
uint32 leaseTime;
@@ -13,13 +13,13 @@
#include "RPCServer.h"
class OpenFileCookie;
class OpenStateCookie;
class OpenState;
class NFS4Object {
public:
bool HandleErrors(uint32 nfs4Error, RPC::Server* serv,
OpenFileCookie* cookie = NULL, OpenState* state = NULL);
OpenStateCookie* cookie = NULL, OpenState* state = NULL);
status_t ConfirmOpen(const FileHandle& fileHandle, OpenState* state);
@@ -788,7 +788,7 @@ RequestBuilder::Verify(AttrValue* attr, uint32 count)
status_t
RequestBuilder::Write(const uint32* id, uint32 stateSeq, const void* buffer,
uint64 pos, uint32 len)
uint64 pos, uint32 len, bool stable)
{
if (fProcedure != ProcCompound)
return B_BAD_VALUE;
@@ -801,7 +801,7 @@ RequestBuilder::Write(const uint32* id, uint32 stateSeq, const void* buffer,
fRequest->Stream().AddUInt(id[1]);
fRequest->Stream().AddUInt(id[2]);
fRequest->Stream().AddUHyper(pos);
fRequest->Stream().AddInt(UNSTABLE4);
fRequest->Stream().AddInt(stable ? FILE_SYNC4 : UNSTABLE4);
fRequest->Stream().AddOpaque(buffer, len);
fOpCount++;
@@ -862,6 +862,12 @@ void
RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr,
uint32 count)
{
if (count == 0) {
stream.AddUInt(0);
stream.AddOpaque(NULL, 0);
return;
}
Attribute* attrs =
reinterpret_cast<Attribute*>(malloc(sizeof(Attribute) * count));
for (uint32 i = 0; i < count; i++)
@@ -78,7 +78,7 @@ public:
status_t Verify(AttrValue* attr, uint32 count);
status_t Write(const uint32* id, uint32 stateSeq,
const void* buffer, uint64 pos,
uint32 len);
uint32 len, bool stable = false);
status_t ReleaseLockOwner(OpenState* state,
LockOwner* owner);
@@ -636,7 +636,7 @@ nfs4_open_attr_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
static status_t
nfs4_close_attr_dir(fs_volume* volume, fs_vnode* vnode, void* cookie)
{
return nfs4_close_attr_dir(volume, vnode, cookie);
return nfs4_close_dir(volume, vnode, cookie);
}
@@ -658,7 +658,125 @@ nfs4_read_attr_dir(fs_volume* volume, fs_vnode* vnode, void* cookie,
static status_t
nfs4_rewind_attr_dir(fs_volume* volume, fs_vnode* vnode, void* cookie)
{
return nfs4_rewind_attr_dir(volume, vnode, cookie);
return nfs4_rewind_dir(volume, vnode, cookie);
}
static status_t
nfs4_create_attr(fs_volume* volume, fs_vnode* vnode, const char* name,
uint32 type, int openMode, void** _cookie)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = new OpenAttrCookie;
if (cookie == NULL)
return B_NO_MEMORY;
*_cookie = cookie;
status_t result = inode->OpenAttr(name, openMode, cookie, true, type);
if (result != B_OK)
delete cookie;
return result;
}
static status_t
nfs4_open_attr(fs_volume* volume, fs_vnode* vnode, const char* name,
int openMode, void** _cookie)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = new OpenAttrCookie;
if (cookie == NULL)
return B_NO_MEMORY;
*_cookie = cookie;
status_t result = inode->OpenAttr(name, openMode, cookie, false);
if (result != B_OK)
delete cookie;
return result;
}
static status_t
nfs4_close_attr(fs_volume* volume, fs_vnode* vnode, void* _cookie)
{
Cookie* cookie = reinterpret_cast<Cookie*>(_cookie);
return cookie->CancelAll();
}
static status_t
nfs4_free_attr_cookie(fs_volume* volume, fs_vnode* vnode, void* _cookie)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = reinterpret_cast<OpenAttrCookie*>(_cookie);
inode->CloseAttr(cookie);
delete cookie;
return B_OK;
}
static status_t
nfs4_read_attr(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
void* buffer, size_t* length)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = reinterpret_cast<OpenAttrCookie*>(_cookie);
bool eof;
return inode->ReadDirect(cookie, pos, buffer, length, &eof);
}
static status_t
nfs4_write_attr(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
const void* buffer, size_t* length)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = reinterpret_cast<OpenAttrCookie*>(_cookie);
return inode->WriteDirect(cookie, pos, buffer, length);
}
static status_t
nfs4_read_attr_stat(fs_volume* volume, fs_vnode* vnode, void* _cookie,
struct stat* stat)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = reinterpret_cast<OpenAttrCookie*>(_cookie);
return inode->Stat(stat, cookie);
}
static status_t
nfs4_write_attr_stat(fs_volume* volume, fs_vnode* vnode, void* _cookie,
const struct stat* stat, int statMask)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
OpenAttrCookie* cookie = reinterpret_cast<OpenAttrCookie*>(_cookie);
return inode->WriteStat(stat, statMask, cookie);
}
static status_t
nfs4_rename_attr(fs_volume* volume, fs_vnode* fromVnode, const char* fromName,
fs_vnode* toVnode, const char* toName)
{
Inode* fromInode = reinterpret_cast<Inode*>(fromVnode->private_node);
Inode* toInode = reinterpret_cast<Inode*>(toVnode->private_node);
return Inode::Rename(fromInode, toInode, fromName, toName, true);
}
static status_t
nfs4_remove_attr(fs_volume* volume, fs_vnode* vnode, const char* name)
{
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
return inode->Remove(name, NF4NAMEDATTR);
}
@@ -832,17 +950,17 @@ fs_vnode_ops gNFSv4VnodeOps = {
nfs4_rewind_attr_dir,
/* attribute operations */
NULL, // create_attr
NULL, // open_attr
NULL, // close_attr
NULL, // free_attr_cookie
NULL, // read_attr
NULL, // write_attr
nfs4_create_attr,
nfs4_open_attr,
nfs4_close_attr,
nfs4_free_attr_cookie,
nfs4_read_attr,
nfs4_write_attr,
NULL, // read_attr_stat
NULL, // write_attr_stat
NULL, // rename_attr
NULL, // remove_attr
nfs4_read_attr_stat,
nfs4_write_attr_stat,
nfs4_rename_attr,
nfs4_remove_attr,
/* support for node and FS layers */
NULL, // create_special_node