mirror of
https://git.openafs.org/openafs.git
synced 2025-01-31 21:47:45 +00:00
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:
parent
5d53e77aa7
commit
29bf66303a
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user