From 29bf66303a3f6778907df351b183ba84dfd60a34 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Thu, 1 Jun 2006 16:40:57 +0000 Subject: [PATCH] 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) --- src/WINNT/afsd/cm_access.c | 31 +++++++++++++++++++------------ src/WINNT/afsd/cm_callback.c | 2 +- src/WINNT/afsd/cm_scache.c | 8 ++++---- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/WINNT/afsd/cm_access.c b/src/WINNT/afsd/cm_access.c index b2b86c9aec..e3097f9be1 100644 --- a/src/WINNT/afsd/cm_access.c +++ b/src/WINNT/afsd/cm_access.c @@ -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; diff --git a/src/WINNT/afsd/cm_callback.c b/src/WINNT/afsd/cm_callback.c index 23bcd26f3f..b282aaad7f 100644 --- a/src/WINNT/afsd/cm_callback.c +++ b/src/WINNT/afsd/cm_callback.c @@ -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); diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index 826b269763..18b599a26c 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -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) {