nfs4: Make Inode::Access() use cached attributes

This commit is contained in:
Pawel Dziepak
2012-07-10 21:31:11 +02:00
parent 78fc85a6ba
commit 9cd76686f1
+57 -29
View File
@@ -445,48 +445,76 @@ Inode::ReadLink(void* buffer, size_t* length)
status_t status_t
Inode::Access(int mode) Inode::Access(int mode)
{ {
do { int acc = 0;
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutFH(fInfo.fHandle); if (fFileSystem->IsAttrSupported(FATTR4_MODE)) {
req.Access(); status_t result = _UpdateAttrCache();
status_t result = request.Send();
if (result != B_OK) if (result != B_OK)
return result; return result;
ReplyInterpreter& reply = request.Reply(); // Root squashing and owner mapping problems may make this function
// return false values. However, since due to race condition it can
// not be used for anything critical, it is not a serius problem.
if (_HandleErrors(reply.NFS4Error(), serv)) mode_t nodeMode = fAttrCache.st_mode;
continue; uint8 userMode = (nodeMode & S_IRWXU) >> 6;
uint8 groupMode = (nodeMode & S_IRWXG) >> 3;
uint8 otherMode = (nodeMode & S_IRWXO);
reply.PutFH(); uid_t uid = geteuid();
if (uid == 0)
acc = userMode | groupMode | otherMode | R_OK | W_OK;
else if (uid == fAttrCache.st_uid)
acc = userMode;
else if (getegid() == fAttrCache.st_gid)
acc = groupMode;
else
acc = otherMode;
} else {
do {
RPC::Server* serv = fFileSystem->Server();
Request request(serv);
RequestBuilder& req = request.Builder();
uint32 allowed; req.PutFH(fInfo.fHandle);
result = reply.Access(NULL, &allowed); req.Access();
if (result != B_OK)
return result;
int acc = 0; status_t result = request.Send();
if ((allowed & ACCESS4_READ) != 0) if (result != B_OK)
acc |= R_OK; return result;
if (fType == NF4DIR && (allowed & ACCESS4_LOOKUP) != 0) ReplyInterpreter& reply = request.Reply();
acc |= X_OK | R_OK;
if (fType != NF4DIR && (allowed & ACCESS4_EXECUTE) != 0) if (_HandleErrors(reply.NFS4Error(), serv))
acc |= X_OK; continue;
if ((allowed & ACCESS4_MODIFY) != 0) reply.PutFH();
acc |= W_OK;
if ((mode & acc) != mode) uint32 allowed;
return B_NOT_ALLOWED; result = reply.Access(NULL, &allowed);
if (result != B_OK)
return result;
return B_OK; if ((allowed & ACCESS4_READ) != 0)
} while (true); acc |= R_OK;
if (fType == NF4DIR && (allowed & ACCESS4_LOOKUP) != 0)
acc |= X_OK | R_OK;
if (fType != NF4DIR && (allowed & ACCESS4_EXECUTE) != 0)
acc |= X_OK;
if ((allowed & ACCESS4_MODIFY) != 0)
acc |= W_OK;
break;
} while (true);
}
if ((mode & acc) != mode)
return B_NOT_ALLOWED;
return B_OK;
} }