nfs4: Add support for O_APPEND mode
This commit is contained in:
@@ -1022,21 +1022,39 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
|
Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
|
||||||
size_t length)
|
size_t *_length)
|
||||||
{
|
{
|
||||||
uint32 size = 0;
|
uint32 size = 0;
|
||||||
uint32 len = 0;
|
uint32 len = 0;
|
||||||
|
uint64 fileSize;
|
||||||
const char* buffer = reinterpret_cast<const char*>(_buffer);
|
const char* buffer = reinterpret_cast<const char*>(_buffer);
|
||||||
|
|
||||||
while (size < length) {
|
while (size < *_length) {
|
||||||
do {
|
do {
|
||||||
RPC::Server* serv = fFilesystem->Server();
|
RPC::Server* serv = fFilesystem->Server();
|
||||||
Request request(serv);
|
Request request(serv);
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
if (size == 0 && (cookie->fMode & O_APPEND) == O_APPEND) {
|
||||||
|
struct stat st;
|
||||||
|
status_t result = Stat(&st);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fileSize = st.st_size;
|
||||||
|
pos = fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
req.PutFH(fHandle);
|
req.PutFH(fHandle);
|
||||||
|
if ((cookie->fMode & O_APPEND) == O_APPEND) {
|
||||||
|
AttrValue attr;
|
||||||
|
attr.fAttribute = FATTR4_SIZE;
|
||||||
|
attr.fFreePointer = false;
|
||||||
|
attr.fData.fValue64 = fileSize + size;
|
||||||
|
req.Verify(&attr, 1);
|
||||||
|
}
|
||||||
req.Write(cookie->fStateId, cookie->fStateSeq, buffer + size,
|
req.Write(cookie->fStateId, cookie->fStateSeq, buffer + size,
|
||||||
pos + size, length - size);
|
pos + size, *_length - size);
|
||||||
|
|
||||||
status_t result = request.Send(cookie);
|
status_t result = request.Send(cookie);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
@@ -1044,6 +1062,16 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// append: race condition
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_NOT_SAME) {
|
||||||
|
if (size == 0)
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
*_length = size;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// filehandle has expired
|
// filehandle has expired
|
||||||
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
_LookUpFilehandle();
|
_LookUpFilehandle();
|
||||||
@@ -1074,6 +1102,12 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if ((cookie->fMode & O_APPEND) == O_APPEND) {
|
||||||
|
result = reply.Verify();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.Write(&len);
|
result = reply.Write(&len);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -1084,6 +1118,8 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
|
|||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*_length = size;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
status_t Read(OpenFileCookie* cookie, off_t pos,
|
status_t Read(OpenFileCookie* cookie, off_t pos,
|
||||||
void* buffer, size_t* length);
|
void* buffer, size_t* length);
|
||||||
status_t Write(OpenFileCookie* cookie, off_t pos,
|
status_t Write(OpenFileCookie* cookie, off_t pos,
|
||||||
const void* buffer, size_t length);
|
const void* buffer, size_t *_length);
|
||||||
|
|
||||||
status_t OpenDir(OpenDirCookie* cookie);
|
status_t OpenDir(OpenDirCookie* cookie);
|
||||||
status_t ReadDir(void* buffer, uint32 size,
|
status_t ReadDir(void* buffer, uint32 size,
|
||||||
|
|||||||
@@ -573,6 +573,11 @@ RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr,
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i < count && attr[i].fAttribute == FATTR4_SIZE) {
|
||||||
|
str.AddUHyper(attr[i].fData.fValue64);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
if (i < count && attr[i].fAttribute == FATTR4_MODE) {
|
if (i < count && attr[i].fAttribute == FATTR4_MODE) {
|
||||||
str.AddUInt(attr[i].fData.fValue32);
|
str.AddUInt(attr[i].fData.fValue32);
|
||||||
i++;
|
i++;
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ nfs4_write(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos,
|
|||||||
|
|
||||||
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
|
OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie);
|
||||||
|
|
||||||
return inode->Write(cookie, pos, buffer, *length);
|
return inode->Write(cookie, pos, buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user