DEVEL15-windows-get-acls-20060528

It is possible to have a valid callback but not to have the
required ACL info for the current user.  Force acquisition of
a FetchStatus but do so without making multiple calls.


(cherry picked from commit 83732fdb158e79b64774667ee09fc1b81062707e)
This commit is contained in:
Jeffrey Altman 2006-06-01 16:40:57 +00:00 committed by Derrick Brashear
parent 5d53e77aa7
commit 29bf66303a
3 changed files with 24 additions and 17 deletions

View File

@ -32,7 +32,7 @@
* can't be locked. Thus, this must always be called in a while loop to stabilize
* things, since we can always lose the race condition getting to the parent vnode.
*/
int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, afs_uint32 rights,
int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32 rights,
afs_uint32 *outRightsp)
{
cm_scache_t *aclScp;
@ -82,7 +82,7 @@ int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, afs_uint32 ri
*outRightsp = rights;
} else {
/* we have to check the specific rights info */
code = cm_FindACLCache(aclScp, up, &trights);
code = cm_FindACLCache(aclScp, userp, &trights);
if (code) {
code = 0;
goto done;
@ -107,30 +107,35 @@ int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, afs_uint32 ri
}
/* called with locked scp; ensures that we have an ACL cache entry for the
* user specified by the parameter "up."
* user specified by the parameter "userp."
* In pathological race conditions, this function may return success without
* having loaded the entry properly (due to a racing callback revoke), so this
* function must also be called in a while loop to make sure that we eventually
* succeed.
*/
long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
struct cm_req *reqp)
{
long code;
cm_fid_t tfid;
cm_scache_t *aclScp;
int got_cb = 0;
/* pretty easy: just force a pass through the fetch status code */
osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, up);
osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, userp);
/* first, start by finding out whether we have a directory or something
* else, so we can find what object's ACL we need.
*/
code = cm_SyncOp(scp, NULL, up, reqp, 0,
if (!cm_HaveCallback(scp)) {
code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code)
return code;
if (code)
return code;
got_cb = 1;
}
if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
/* not a dir, use parent dir's acl */
@ -139,19 +144,21 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
tfid.vnode = scp->parentVnode;
tfid.unique = scp->parentUnique;
lock_ReleaseMutex(&scp->mx);
code = cm_GetSCache(&tfid, &aclScp, up, reqp);
code = cm_GetSCache(&tfid, &aclScp, userp, reqp);
if (code) {
lock_ObtainMutex(&scp->mx);
return code;
}
osi_Log1(afsd_logp, "GetAccess parent scp %x user %x", aclScp, up);
osi_Log1(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp);
lock_ObtainMutex(&aclScp->mx);
code = cm_SyncOp(aclScp, NULL, up, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
code = cm_GetCallback(aclScp, userp, reqp, 1);
lock_ReleaseMutex(&aclScp->mx);
cm_ReleaseSCache(aclScp);
lock_ObtainMutex(&scp->mx);
} else if (!got_cb) {
code = cm_GetCallback(scp, userp, reqp, 1);
}
return code;

View File

@ -1681,7 +1681,7 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
/* otherwise, we have to make an RPC to get the status */
sflags = CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK;
cm_SyncOp(scp, NULL, NULL, NULL, 0, sflags);
cm_SyncOp(scp, NULL, userp, reqp, 0, sflags);
cm_StartCallbackGrantingCall(scp, &cbr);
sfid = scp->fid;
lock_ReleaseMutex(&scp->mx);

View File

@ -667,7 +667,7 @@ cm_scache_t * cm_FindSCacheParent(cm_scache_t * scp)
* is to serialize all StoreData RPC's. This is the reason we defined
* CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING.
*/
long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *reqp,
afs_uint32 rights, afs_uint32 flags)
{
osi_queueData_t *qdp;
@ -854,7 +854,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
osi_Log1(afsd_logp, "CM SyncOp getting callback on scp 0x%p",
scp);
if (bufLocked) lock_ReleaseMutex(&bufp->mx);
code = cm_GetCallback(scp, up, reqp, 0);
code = cm_GetCallback(scp, userp, reqp, 0);
if (bufLocked) {
lock_ReleaseMutex(&scp->mx);
lock_ObtainMutex(&bufp->mx);
@ -873,14 +873,14 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO))
return CM_ERROR_READONLY;
if (cm_HaveAccessRights(scp, up, rights, &outRights)) {
if (cm_HaveAccessRights(scp, userp, rights, &outRights)) {
if (~outRights & rights)
return CM_ERROR_NOACCESS;
}
else {
/* we don't know the required access rights */
if (bufLocked) lock_ReleaseMutex(&bufp->mx);
code = cm_GetAccessRights(scp, up, reqp);
code = cm_GetAccessRights(scp, userp, reqp);
if (code)
return code;
if (bufLocked) {