From 7eafe07c8e4c5f99c8341b89029ab9f5a9240827 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 5 Aug 2008 16:46:37 +0000 Subject: [PATCH] DEVEL15-windows-getaccessrights-20080805 LICENSE MIT Do not permit GetAccessRights() to be called multiple times within cm_SyncOp for the same rights check. If the GetAccessRights() succeeded and in the next loop the rights check fails, the user simply doesn't have the rights. Move a call to cm_SyncOpDone(FETCHSTATUS) from GetBuffer() to MergeStatus(). Anytime an RPC completes successfully we get updated status info for the object. Might as well allow threads waiting for status info to us it. (cherry picked from commit aab4b2b32f933daf48cc138c0eb5d8cf5a2023b5) --- src/WINNT/afsd/cm_access.c | 4 ++-- src/WINNT/afsd/cm_dcache.c | 2 -- src/WINNT/afsd/cm_scache.c | 11 ++++++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/WINNT/afsd/cm_access.c b/src/WINNT/afsd/cm_access.c index da1593c19..90948cfd8 100644 --- a/src/WINNT/afsd/cm_access.c +++ b/src/WINNT/afsd/cm_access.c @@ -157,7 +157,7 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp, /* pretty easy: just force a pass through the fetch status code */ - osi_Log2(afsd_logp, "GetAccess scp 0x%p user 0x%p", scp, userp); + osi_Log2(afsd_logp, "GetAccessRights scp 0x%p user 0x%p", 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. @@ -177,7 +177,7 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp, goto _done; } - osi_Log2(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp); + osi_Log2(afsd_logp, "GetAccessRights parent scp %x user %x", aclScp, userp); lock_ObtainWrite(&aclScp->rw); code = cm_SyncOp(aclScp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB); diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index d7852b6e2..f1f328873 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -1694,8 +1694,6 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp lock_ObtainWrite(&scp->rw); - cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS); - /* we know that no one else has changed the buffer, since we still have * the fetching flag on the buffers, and we have the scp locked again. * Copy in the version # into the buffer if we got code 0 back from the diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index 1ac0e680d..1d44ec719 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -1045,6 +1045,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req afs_uint32 sleep_buf_cmflags = 0; afs_uint32 sleep_scp_bufs = 0; int wakeupCycle; + int getAccessRights = 1; /* lookup this first */ bufLocked = flags & CM_SCACHESYNC_BUFLOCKED; @@ -1247,7 +1248,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO)) return CM_ERROR_READONLY; - if (cm_HaveAccessRights(scp, userp, rights, &outRights)) { + if (cm_HaveAccessRights(scp, userp, rights, &outRights) || !getAccessRights) { if (~outRights & rights) return CM_ERROR_NOACCESS; } @@ -1262,6 +1263,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req } if (code) return code; + getAccessRights = 0; /* do not repeat */ continue; } } @@ -1725,6 +1727,13 @@ void cm_MergeStatus(cm_scache_t *dscp, scp->bufDataVersionLow = dataVersion; scp->dataVersion = dataVersion; + + /* + * If someone is waiting for status information, we can wake them up + * now even though the entity that issued the FetchStatus may not + * have completed yet. + */ + cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS); } /* note that our stat cache info is incorrect, so force us eventually -- 2.39.5