2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Paweł Dziepak, pdziepak@quarnos.org
10 #include <AutoDeleter.h>
14 #include "NFS4Inode.h"
19 NFS4Inode::GetChangeInfo(uint64
* change
, bool attrDir
)
21 ASSERT(change
!= NULL
);
25 RPC::Server
* serv
= fFileSystem
->Server();
26 Request
request(serv
, fFileSystem
);
27 RequestBuilder
& req
= request
.Builder();
30 req
.PutFH(fInfo
.fAttrDir
);
32 req
.PutFH(fInfo
.fHandle
);
34 Attribute attr
[] = { FATTR4_CHANGE
};
35 req
.GetAttr(attr
, sizeof(attr
) / sizeof(Attribute
));
37 status_t result
= request
.Send();
41 ReplyInterpreter
& reply
= request
.Reply();
43 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
50 result
= reply
.GetAttr(&values
, &count
);
54 // FATTR4_CHANGE is mandatory
55 *change
= values
[0].fData
.fValue64
;
64 NFS4Inode::CommitWrites()
68 RPC::Server
* serv
= fFileSystem
->Server();
69 Request
request(serv
, fFileSystem
);
70 RequestBuilder
& req
= request
.Builder();
72 req
.PutFH(fInfo
.fHandle
);
75 status_t result
= request
.Send();
79 ReplyInterpreter
& reply
= request
.Reply();
81 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
85 return reply
.Commit();
91 NFS4Inode::Access(uint32
* allowed
)
93 ASSERT(allowed
!= NULL
);
97 RPC::Server
* serv
= fFileSystem
->Server();
98 Request
request(serv
, fFileSystem
);
99 RequestBuilder
& req
= request
.Builder();
101 req
.PutFH(fInfo
.fHandle
);
104 status_t result
= request
.Send();
108 ReplyInterpreter
& reply
= request
.Reply();
110 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
115 return reply
.Access(NULL
, allowed
);
121 NFS4Inode::LookUp(const char* name
, uint64
* change
, uint64
* fileID
,
122 FileHandle
* handle
, bool parent
)
124 ASSERT(name
!= NULL
);
128 RPC::Server
* serv
= fFileSystem
->Server();
129 Request
request(serv
, fFileSystem
);
130 RequestBuilder
& req
= request
.Builder();
132 (void)parent
; // TODO: add support for named attributes
133 req
.PutFH(fInfo
.fHandle
);
135 if (change
!= NULL
) {
136 Attribute dirAttr
[] = { FATTR4_CHANGE
};
137 req
.GetAttr(dirAttr
, sizeof(dirAttr
) / sizeof(Attribute
));
140 if (!strcmp(name
, ".."))
148 Attribute attr
[] = { FATTR4_FSID
, FATTR4_FILEID
};
149 req
.GetAttr(attr
, sizeof(attr
) / sizeof(Attribute
));
151 status_t result
= request
.Send();
155 ReplyInterpreter
& reply
= request
.Reply();
157 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
164 if (change
!= NULL
) {
165 result
= reply
.GetAttr(&values
, &count
);
169 *change
= values
[0].fData
.fValue64
;
173 if (!strcmp(name
, ".."))
174 result
= reply
.LookUpUp();
176 result
= reply
.LookUp();
183 result
= reply
.GetAttr(&values
, &count
);
187 // FATTR4_FSID is mandatory
189 = reinterpret_cast<FileSystemId
*>(values
[0].fData
.fPointer
);
190 if (*fsid
!= fFileSystem
->FsId()) {
192 return B_ENTRY_NOT_FOUND
;
195 if (fileID
!= NULL
) {
196 if (count
< 2 || values
[1].fAttribute
!= FATTR4_FILEID
)
197 *fileID
= fFileSystem
->AllocFileId();
199 *fileID
= values
[1].fData
.fValue64
;
210 NFS4Inode::Link(Inode
* dir
, const char* name
, ChangeInfo
* changeInfo
)
213 ASSERT(name
!= NULL
);
214 ASSERT(changeInfo
!= NULL
);
218 RPC::Server
* serv
= fFileSystem
->Server();
219 Request
request(serv
, fFileSystem
);
220 RequestBuilder
& req
= request
.Builder();
222 req
.PutFH(fInfo
.fHandle
);
224 req
.PutFH(dir
->fInfo
.fHandle
);
227 status_t result
= request
.Send();
231 ReplyInterpreter
& reply
= request
.Reply();
233 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
240 return reply
.Link(&changeInfo
->fBefore
, &changeInfo
->fAfter
,
241 changeInfo
->fAtomic
);
247 NFS4Inode::ReadLink(void* buffer
, size_t* length
)
249 ASSERT(buffer
!= NULL
);
250 ASSERT(length
!= NULL
);
254 RPC::Server
* serv
= fFileSystem
->Server();
255 Request
request(serv
, fFileSystem
);
256 RequestBuilder
& req
= request
.Builder();
258 req
.PutFH(fInfo
.fHandle
);
261 status_t result
= request
.Send();
265 ReplyInterpreter
& reply
= request
.Reply();
267 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
273 result
= reply
.ReadLink(buffer
, &size
, *length
);
274 *length
= static_cast<size_t>(size
);
282 NFS4Inode::GetStat(AttrValue
** values
, uint32
* count
, OpenAttrCookie
* cookie
)
284 ASSERT(values
!= NULL
);
285 ASSERT(count
!= NULL
);
289 RPC::Server
* serv
= fFileSystem
->Server();
290 Request
request(serv
, fFileSystem
);
291 RequestBuilder
& req
= request
.Builder();
294 req
.PutFH(cookie
->fOpenState
->fInfo
.fHandle
);
296 req
.PutFH(fInfo
.fHandle
);
298 Attribute attr
[] = { FATTR4_SIZE
, FATTR4_MODE
, FATTR4_NUMLINKS
,
299 FATTR4_OWNER
, FATTR4_OWNER_GROUP
,
300 FATTR4_TIME_ACCESS
, FATTR4_TIME_CREATE
,
301 FATTR4_TIME_METADATA
, FATTR4_TIME_MODIFY
};
302 req
.GetAttr(attr
, sizeof(attr
) / sizeof(Attribute
));
304 status_t result
= request
.Send(cookie
);
308 ReplyInterpreter
& reply
= request
.Reply();
310 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
315 return reply
.GetAttr(values
, count
);
321 NFS4Inode::WriteStat(OpenState
* state
, AttrValue
* attrs
, uint32 attrCount
)
323 ASSERT(attrs
!= NULL
);
327 RPC::Server
* serv
= fFileSystem
->Server();
328 Request
request(serv
, fFileSystem
);
329 RequestBuilder
& req
= request
.Builder();
332 req
.PutFH(state
->fInfo
.fHandle
);
333 req
.SetAttr(state
->fStateID
, state
->fStateSeq
, attrs
, attrCount
);
335 req
.PutFH(fInfo
.fHandle
);
336 req
.SetAttr(NULL
, 0, attrs
, attrCount
);
339 status_t result
= request
.Send();
343 ReplyInterpreter
& reply
= request
.Reply();
345 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
349 result
= reply
.SetAttr();
360 NFS4Inode::RenameNode(Inode
* from
, Inode
* to
, const char* fromName
,
361 const char* toName
, ChangeInfo
* fromChange
, ChangeInfo
* toChange
,
362 uint64
* fileID
, bool attribute
)
364 ASSERT(from
!= NULL
);
366 ASSERT(fromName
!= NULL
);
367 ASSERT(toName
!= NULL
);
368 ASSERT(fromChange
!= NULL
);
369 ASSERT(toChange
!= NULL
);
373 RPC::Server
* server
= from
->fFileSystem
->Server();
374 Request
request(server
, from
->fFileSystem
);
375 RequestBuilder
& req
= request
.Builder();
378 req
.PutFH(from
->fInfo
.fAttrDir
);
380 req
.PutFH(from
->fInfo
.fHandle
);
383 req
.PutFH(to
->fInfo
.fAttrDir
);
385 req
.PutFH(to
->fInfo
.fHandle
);
386 req
.Rename(fromName
, toName
);
390 Attribute attr
[] = { FATTR4_FILEID
};
391 req
.GetAttr(attr
, sizeof(attr
) / sizeof(Attribute
));
394 status_t result
= request
.Send();
398 ReplyInterpreter
& reply
= request
.Reply();
400 // If we have to wait, migrate to another server, etc then the first
401 // HandleErrors() will do that. However, if the file handles
402 // were invalid then we need to update both Inodes.
403 bool retry
= from
->HandleErrors(attempt
, reply
.NFS4Error(), server
);
404 if (IsFileHandleInvalid(reply
.NFS4Error()))
405 retry
|= to
->HandleErrors(attempt
, reply
.NFS4Error(), server
);
413 result
= reply
.Rename(&fromChange
->fBefore
, &fromChange
->fAfter
,
414 fromChange
->fAtomic
, &toChange
->fBefore
, &toChange
->fAfter
,
420 result
= reply
.LookUp();
426 result
= reply
.GetAttr(&values
, &count
);
431 *fileID
= from
->fFileSystem
->AllocFileId();
433 *fileID
= values
[0].fData
.fValue64
;
444 NFS4Inode::CreateFile(const char* name
, int mode
, int perms
, OpenState
* state
,
445 ChangeInfo
* changeInfo
, uint64
* fileID
, FileHandle
* handle
,
446 OpenDelegationData
* delegation
)
448 ASSERT(name
!= NULL
);
449 ASSERT(state
!= NULL
);
450 ASSERT(changeInfo
!= NULL
);
451 ASSERT(handle
!= NULL
);
452 ASSERT(delegation
!= NULL
);
458 uint32 sequence
= fFileSystem
->OpenOwnerSequenceLock();
460 state
->fClientID
= fFileSystem
->NFSServer()->ClientId();
462 RPC::Server
* serv
= fFileSystem
->Server();
463 Request
request(serv
, fFileSystem
);
464 RequestBuilder
& req
= request
.Builder();
466 req
.PutFH(fInfo
.fHandle
);
470 if ((mode
& O_TRUNC
) == O_TRUNC
) {
471 cattr
[i
].fAttribute
= FATTR4_SIZE
;
472 cattr
[i
].fFreePointer
= false;
473 cattr
[i
].fData
.fValue64
= 0;
476 cattr
[i
].fAttribute
= FATTR4_MODE
;
477 cattr
[i
].fFreePointer
= false;
478 cattr
[i
].fData
.fValue32
= perms
;
481 req
.Open(CLAIM_NULL
, sequence
, sModeToAccess(mode
),
482 state
->fClientID
, OPEN4_CREATE
, fFileSystem
->OpenOwner(), name
,
483 cattr
, i
, (mode
& O_EXCL
) == O_EXCL
);
487 if (fFileSystem
->IsAttrSupported(FATTR4_FILEID
)) {
488 Attribute attr
[] = { FATTR4_FILEID
};
489 req
.GetAttr(attr
, sizeof(attr
) / sizeof(Attribute
));
492 result
= request
.Send();
493 if (result
!= B_OK
) {
494 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
498 ReplyInterpreter
& reply
= request
.Reply();
500 result
= reply
.PutFH();
502 sequence
+= IncrementSequence(reply
.NFS4Error());
504 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, NULL
, state
,
509 result
= reply
.Open(state
->fStateID
, &state
->fStateSeq
, &confirm
,
510 delegation
, changeInfo
);
511 if (result
!= B_OK
) {
512 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
518 if (fFileSystem
->IsAttrSupported(FATTR4_FILEID
)) {
521 result
= reply
.GetAttr(&values
, &count
);
522 if (result
!= B_OK
) {
523 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
527 *fileID
= values
[0].fData
.fValue64
;
531 *fileID
= fFileSystem
->AllocFileId();
536 state
->fOpened
= true;
539 result
= ConfirmOpen(*handle
, state
, &sequence
);
541 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
547 NFS4Inode::OpenFile(OpenState
* state
, int mode
, OpenDelegationData
* delegation
)
549 ASSERT(state
!= NULL
);
550 ASSERT(delegation
!= NULL
);
556 uint32 sequence
= fFileSystem
->OpenOwnerSequenceLock();
558 state
->fClientID
= fFileSystem
->NFSServer()->ClientId();
560 RPC::Server
* serv
= fFileSystem
->Server();
561 Request
request(serv
, fFileSystem
);
562 RequestBuilder
& req
= request
.Builder();
564 // Since we are opening the file using a pair (parentFH, name) we
565 // need to check for race conditions.
566 if (fFileSystem
->IsAttrSupported(FATTR4_FILEID
)) {
567 req
.PutFH(fInfo
.fNames
->fNames
.Head()->fParent
->fHandle
);
568 req
.LookUp(fInfo
.fNames
->fNames
.Head()->fName
);
570 attr
.fAttribute
= FATTR4_FILEID
;
571 attr
.fFreePointer
= false;
572 attr
.fData
.fValue64
= fInfo
.fFileId
;
573 req
.Verify(&attr
, 1);
574 } else if (fFileSystem
->ExpireType() == FH4_PERSISTENT
) {
575 req
.PutFH(fInfo
.fNames
->fNames
.Head()->fParent
->fHandle
);
576 req
.LookUp(fInfo
.fNames
->fNames
.Head()->fName
);
578 attr
.fAttribute
= FATTR4_FILEHANDLE
;
579 attr
.fFreePointer
= true;
580 attr
.fData
.fPointer
= malloc(sizeof(fInfo
.fHandle
));
581 memcpy(attr
.fData
.fPointer
, &fInfo
.fHandle
, sizeof(fInfo
.fHandle
));
582 req
.Verify(&attr
, 1);
585 req
.PutFH(fInfo
.fNames
->fNames
.Head()->fParent
->fHandle
);
586 req
.Open(CLAIM_NULL
, sequence
, sModeToAccess(mode
), state
->fClientID
,
587 OPEN4_NOCREATE
, fFileSystem
->OpenOwner(),
588 fInfo
.fNames
->fNames
.Head()->fName
);
591 result
= request
.Send();
592 if (result
!= B_OK
) {
593 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
597 ReplyInterpreter
& reply
= request
.Reply();
599 // Verify if the file we want to open is the file this Inode
601 if (fFileSystem
->IsAttrSupported(FATTR4_FILEID
)
602 || fFileSystem
->ExpireType() == FH4_PERSISTENT
) {
604 result
= reply
.LookUp();
605 if (result
!= B_OK
) {
606 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
610 result
= reply
.Verify();
611 if (result
!= B_OK
&& reply
.NFS4Error() == NFS4ERR_NOT_SAME
) {
612 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
613 return B_ENTRY_NOT_FOUND
;
617 result
= reply
.PutFH();
619 sequence
+= IncrementSequence(reply
.NFS4Error());
621 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, NULL
, state
,
626 result
= reply
.Open(state
->fStateID
, &state
->fStateSeq
, &confirm
,
628 if (result
!= B_OK
) {
629 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
634 result
= reply
.GetFH(&handle
);
635 if (result
!= B_OK
) {
636 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
643 state
->fOpened
= true;
646 result
= ConfirmOpen(fInfo
.fHandle
, state
, &sequence
);
648 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
654 NFS4Inode::OpenAttr(OpenState
* state
, const char* name
, int mode
,
655 OpenDelegationData
* delegation
, bool create
)
657 ASSERT(name
!= NULL
);
658 ASSERT(state
!= NULL
);
659 ASSERT(delegation
!= NULL
);
665 uint32 sequence
= fFileSystem
->OpenOwnerSequenceLock();
667 state
->fClientID
= fFileSystem
->NFSServer()->ClientId();
669 RPC::Server
* serv
= fFileSystem
->Server();
670 Request
request(serv
, fFileSystem
);
671 RequestBuilder
& req
= request
.Builder();
673 req
.PutFH(fInfo
.fAttrDir
);
674 req
.Open(CLAIM_NULL
, sequence
, sModeToAccess(mode
), state
->fClientID
,
675 create
? OPEN4_CREATE
: OPEN4_NOCREATE
, fFileSystem
->OpenOwner(),
679 result
= request
.Send();
680 if (result
!= B_OK
) {
681 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
685 ReplyInterpreter
& reply
= request
.Reply();
687 result
= reply
.PutFH();
689 sequence
+= IncrementSequence(reply
.NFS4Error());
691 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, NULL
, state
,
696 result
= reply
.Open(state
->fStateID
, &state
->fStateSeq
, &confirm
,
699 reply
.GetFH(&state
->fInfo
.fHandle
);
701 if (result
!= B_OK
) {
702 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
709 state
->fOpened
= true;
712 result
= ConfirmOpen(state
->fInfo
.fHandle
, state
, &sequence
);
714 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
720 NFS4Inode::ReadFile(OpenStateCookie
* cookie
, OpenState
* state
, uint64 position
,
721 uint32
* length
, void* buffer
, bool* eof
)
723 ASSERT(state
!= NULL
);
724 ASSERT(length
!= NULL
);
725 ASSERT(buffer
!= NULL
);
730 RPC::Server
* serv
= fFileSystem
->Server();
731 Request
request(serv
, fFileSystem
);
732 RequestBuilder
& req
= request
.Builder();
734 req
.PutFH(state
->fInfo
.fHandle
);
735 req
.Read(state
->fStateID
, state
->fStateSeq
, position
, *length
);
737 status_t result
= request
.Send(cookie
);
741 ReplyInterpreter
& reply
= request
.Reply();
743 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, cookie
, state
))
747 result
= reply
.Read(buffer
, length
, eof
);
757 NFS4Inode::WriteFile(OpenStateCookie
* cookie
, OpenState
* state
, uint64 position
,
758 uint32
* length
, const void* buffer
, bool commit
)
760 ASSERT(state
!= NULL
);
761 ASSERT(length
!= NULL
);
762 ASSERT(buffer
!= NULL
);
766 RPC::Server
* serv
= fFileSystem
->Server();
767 Request
request(serv
, fFileSystem
);
768 RequestBuilder
& req
= request
.Builder();
770 req
.PutFH(state
->fInfo
.fHandle
);
772 req
.Write(state
->fStateID
, state
->fStateSeq
, buffer
, position
, *length
,
775 status_t result
= request
.Send(cookie
);
779 ReplyInterpreter
& reply
= request
.Reply();
781 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, cookie
, state
))
786 result
= reply
.Write(length
);
796 NFS4Inode::CreateObject(const char* name
, const char* path
, int mode
,
797 FileType type
, ChangeInfo
* changeInfo
, uint64
* fileID
, FileHandle
* handle
,
800 ASSERT(name
!= NULL
);
801 ASSERT(changeInfo
!= NULL
);
802 ASSERT(handle
!= NULL
);
806 RPC::Server
* serv
= fFileSystem
->Server();
807 Request
request(serv
, fFileSystem
);
808 RequestBuilder
& req
= request
.Builder();
810 (void)parent
; // TODO: support named attributes
811 req
.PutFH(fInfo
.fHandle
);
815 cattr
[i
].fAttribute
= FATTR4_MODE
;
816 cattr
[i
].fFreePointer
= false;
817 cattr
[i
].fData
.fValue32
= mode
;
822 req
.Create(NF4DIR
, name
, cattr
, i
);
825 req
.Create(NF4LNK
, name
, cattr
, i
, path
);
833 if (fileID
!= NULL
) {
834 Attribute attr
[] = { FATTR4_FILEID
};
835 req
.GetAttr(attr
, sizeof(attr
) / sizeof(Attribute
));
838 status_t result
= request
.Send();
842 ReplyInterpreter
& reply
= request
.Reply();
844 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
848 result
= reply
.Create(&changeInfo
->fBefore
, &changeInfo
->fAfter
,
849 changeInfo
->fAtomic
);
853 result
= reply
.GetFH(handle
);
857 if (fileID
!= NULL
) {
860 result
= reply
.GetAttr(&values
, &count
);
865 *fileID
= fFileSystem
->AllocFileId();
867 *fileID
= values
[0].fData
.fValue64
;
878 NFS4Inode::RemoveObject(const char* name
, FileType type
, ChangeInfo
* changeInfo
,
881 ASSERT(name
!= NULL
);
882 ASSERT(changeInfo
!= NULL
);
886 RPC::Server
* serv
= fFileSystem
->Server();
887 Request
request(serv
, fFileSystem
);
888 RequestBuilder
& req
= request
.Builder();
890 req
.PutFH(fInfo
.fHandle
);
893 attr
.fAttribute
= FATTR4_TYPE
;
894 attr
.fFreePointer
= false;
895 attr
.fData
.fValue32
= NF4DIR
;
897 req
.Verify(&attr
, 1);
899 req
.Nverify(&attr
, 1);
901 if (type
!= NF4NAMEDATTR
) {
902 Attribute idAttr
[] = { FATTR4_FILEID
};
903 req
.GetAttr(idAttr
, sizeof(idAttr
) / sizeof(Attribute
));
906 req
.PutFH(fInfo
.fHandle
);
909 status_t result
= request
.Send();
913 ReplyInterpreter
& reply
= request
.Reply();
915 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
919 result
= reply
.LookUp();
924 result
= reply
.Verify();
926 result
= reply
.Nverify();
928 if (result
== NFS4ERR_SAME
&& type
!= NF4DIR
)
929 return B_IS_A_DIRECTORY
;
930 if (result
== NFS4ERR_NOT_SAME
&& type
== NF4DIR
)
931 return B_NOT_A_DIRECTORY
;
935 if (type
!= NF4NAMEDATTR
) {
938 result
= reply
.GetAttr(&values
, &count
);
943 *fileID
= fFileSystem
->AllocFileId();
945 *fileID
= values
[0].fData
.fValue64
;
950 return reply
.Remove(&changeInfo
->fBefore
, &changeInfo
->fAfter
,
951 changeInfo
->fAtomic
);
957 NFS4Inode::ReadDirOnce(DirEntry
** dirents
, uint32
* count
, OpenDirCookie
* cookie
,
958 bool* eof
, uint64
* change
, uint64
* dirCookie
, uint64
* dirCookieVerf
,
961 ASSERT(dirents
!= NULL
);
962 ASSERT(count
!= NULL
);
967 RPC::Server
* serv
= fFileSystem
->Server();
968 Request
request(serv
, fFileSystem
);
969 RequestBuilder
& req
= request
.Builder();
972 req
.PutFH(fInfo
.fAttrDir
);
974 req
.PutFH(fInfo
.fHandle
);
976 Attribute dirAttr
[] = { FATTR4_CHANGE
};
978 req
.GetAttr(dirAttr
, sizeof(dirAttr
) / sizeof(Attribute
));
980 Attribute attr
[] = { FATTR4_FSID
, FATTR4_FILEID
};
981 req
.ReadDir(*dirCookie
, *dirCookieVerf
, attr
,
982 sizeof(attr
) / sizeof(Attribute
));
984 req
.GetAttr(dirAttr
, sizeof(dirAttr
) / sizeof(Attribute
));
986 status_t result
= request
.Send(cookie
);
990 ReplyInterpreter
& reply
= request
.Reply();
992 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
997 AttrValue
* before
= NULL
;
1000 result
= reply
.GetAttr(&before
, &attrCount
);
1004 ArrayDeleter
<AttrValue
> beforeDeleter(before
);
1006 result
= reply
.ReadDir(dirCookie
, dirCookieVerf
, dirents
, count
, eof
);
1010 ArrayDeleter
<DirEntry
> entriesDeleter(*dirents
);
1013 result
= reply
.GetAttr(&after
, &attrCount
);
1017 ArrayDeleter
<AttrValue
> afterDeleter(after
);
1020 && before
[0].fData
.fValue64
== after
[0].fData
.fValue64
)
1021 || *change
== after
[0].fData
.fValue64
)
1022 *change
= after
[0].fData
.fValue64
;
1026 entriesDeleter
.Detach();
1033 NFS4Inode::OpenAttrDir(FileHandle
* handle
)
1035 ASSERT(handle
!= NULL
);
1039 RPC::Server
* serv
= fFileSystem
->Server();
1040 Request
request(serv
, fFileSystem
);
1041 RequestBuilder
& req
= request
.Builder();
1043 req
.PutFH(fInfo
.fHandle
);
1044 req
.OpenAttrDir(true);
1047 status_t result
= request
.Send();
1051 ReplyInterpreter
& reply
= request
.Reply();
1053 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
))
1057 result
= reply
.OpenAttrDir();
1061 return reply
.GetFH(handle
);
1067 NFS4Inode::TestLock(OpenFileCookie
* cookie
, LockType
* type
, uint64
* position
,
1068 uint64
* length
, bool& conflict
)
1070 ASSERT(cookie
!= NULL
);
1071 ASSERT(type
!= NULL
);
1072 ASSERT(position
!= NULL
);
1073 ASSERT(length
!= NULL
);
1077 RPC::Server
* serv
= fFileSystem
->Server();
1078 Request
request(serv
, fFileSystem
);
1079 RequestBuilder
& req
= request
.Builder();
1081 req
.PutFH(fInfo
.fHandle
);
1082 req
.LockT(*type
, *position
, *length
, cookie
->fOpenState
);
1084 status_t result
= request
.Send();
1088 ReplyInterpreter
& reply
= request
.Reply();
1089 if (reply
.NFS4Error() != NFS4ERR_DENIED
) {
1090 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, cookie
))
1095 result
= reply
.LockT(position
, length
, type
);
1096 if (reply
.NFS4Error() == NFS4ERR_DENIED
) {
1099 } else if (reply
.NFS4Error() == NFS4_OK
)
1110 NFS4Inode::AcquireLock(OpenFileCookie
* cookie
, LockInfo
* lockInfo
, bool wait
)
1112 ASSERT(cookie
!= NULL
);
1113 ASSERT(lockInfo
!= NULL
);
1116 uint32 sequence
= fFileSystem
->OpenOwnerSequenceLock();
1118 MutexLocker
ownerLocker(lockInfo
->fOwner
->fLock
);
1120 RPC::Server
* serv
= fFileSystem
->Server();
1121 Request
request(serv
, fFileSystem
);
1122 RequestBuilder
& req
= request
.Builder();
1124 req
.PutFH(fInfo
.fHandle
);
1125 req
.Lock(cookie
->fOpenState
, lockInfo
, &sequence
);
1127 status_t result
= request
.Send();
1128 if (result
!= B_OK
) {
1129 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
1133 ReplyInterpreter
& reply
= request
.Reply();
1135 result
= reply
.PutFH();
1137 sequence
+= IncrementSequence(reply
.NFS4Error());
1139 result
= reply
.Lock(lockInfo
);
1141 ownerLocker
.Unlock();
1143 if (reply
.NFS4Error() != NFS4ERR_DENIED
|| wait
) {
1144 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, cookie
, NULL
,
1150 fFileSystem
->OpenOwnerSequenceUnlock(sequence
);
1160 NFS4Inode::ReleaseLock(OpenFileCookie
* cookie
, LockInfo
* lockInfo
)
1162 ASSERT(cookie
!= NULL
);
1163 ASSERT(lockInfo
!= NULL
);
1167 MutexLocker
ownerLocker(lockInfo
->fOwner
->fLock
);
1169 RPC::Server
* serv
= fFileSystem
->Server();
1170 Request
request(serv
, fFileSystem
);
1171 RequestBuilder
& req
= request
.Builder();
1173 req
.PutFH(fInfo
.fHandle
);
1174 req
.LockU(lockInfo
);
1176 status_t result
= request
.Send();
1180 ReplyInterpreter
& reply
= request
.Reply();
1183 result
= reply
.LockU(lockInfo
);
1185 ownerLocker
.Unlock();
1186 if (HandleErrors(attempt
, reply
.NFS4Error(), serv
, cookie
))