From afa037ff2bd27dac2d598d8f613d1c9e833e22f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 14 Mar 2009 04:55:09 +0000 Subject: [PATCH] DEVEL15-windows-afsd-unlock-20090312 LICENSE MIT Modify the cm_Unlock() interface to support the ability to unlock all locks within a range. This is required for the redirector. (cherry picked from commit 8e01e5a4dbcaaea03fc3af59bec5ef211d5b4684) --- src/WINNT/afsd/cm_vnodeops.c | 59 +++++++++++++++++++++++++++--------- src/WINNT/afsd/cm_vnodeops.h | 4 ++- src/WINNT/afsd/smb.c | 2 +- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 5d23ccdce..04ddb091f 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -147,7 +147,7 @@ long cm_CheckOpen(cm_scache_t *scp, int openMode, int trunc, cm_user_t *userp, code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, reqp, NULL); if (code == 0) { - cm_Unlock(scp, sLockType, LOffset, LLength, key, userp, reqp); + cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, reqp); } else { /* In this case, we allow the file open to go through even though we can't enforce mandatory locking on the @@ -302,7 +302,7 @@ extern long cm_CheckNTOpenDone(cm_scache_t *scp, cm_user_t *userp, cm_req_t *req lock_ObtainWrite(&scp->rw); if (*ldpp) { cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength, - (*ldpp)->key, userp, reqp); + (*ldpp)->key, 0, userp, reqp); free(*ldpp); *ldpp = NULL; } @@ -4872,6 +4872,7 @@ long cm_Unlock(cm_scache_t *scp, unsigned char sLockType, LARGE_INTEGER LOffset, LARGE_INTEGER LLength, cm_key_t key, + afs_uint32 flags, cm_user_t *userp, cm_req_t *reqp) { @@ -4880,12 +4881,19 @@ long cm_Unlock(cm_scache_t *scp, cm_file_lock_t *fileLock; osi_queue_t *q; int release_userp = FALSE; + int exact_match = !(flags & CM_UNLOCK_FLAG_MATCH_RANGE); + int lock_found = 0; + LARGE_INTEGER RangeEnd; osi_Log4(afsd_logp, "cm_Unlock scp 0x%p type 0x%x offset %d length %d", scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart); - osi_Log3(afsd_logp, "... key <0x%x,0x%x,0x%x>", - key.process_id, key.session_id, key.file_id); + osi_Log4(afsd_logp, "... key <0x%x,0x%x,0x%x> flags 0x%x", + key.process_id, key.session_id, key.file_id, flags); + + if (!exact_match) + RangeEnd.QuadPart = LOffset.QuadPart + LLength.QuadPart; + try_again: lock_ObtainRead(&cm_scacheLock); for (q = scp->fileLocksH; q; q = osi_QNext(q)) { @@ -4908,21 +4916,39 @@ long cm_Unlock(cm_scache_t *scp, osi_assertx(FALSE, "invalid fid value"); } #endif - if (!IS_LOCK_DELETED(fileLock) && - cm_KeyEquals(&fileLock->key, &key, 0) && - fileLock->range.offset == LOffset.QuadPart && - fileLock->range.length == LLength.QuadPart) { - break; + if (exact_match) { + if (!IS_LOCK_DELETED(fileLock) && + cm_KeyEquals(&fileLock->key, &key, 0) && + fileLock->range.offset == LOffset.QuadPart && + fileLock->range.length == LLength.QuadPart) { + lock_found = 1; + break; + } + } else { + + if (!IS_LOCK_DELETED(fileLock) && + cm_KeyEquals(&fileLock->key, &key, 0) && + fileLock->range.offset >= LOffset.QuadPart && + fileLock->range.offset < RangeEnd.QuadPart && + (fileLock->range.offset + fileLock->range.length) <= RangeEnd.QuadPart) { + lock_found = 1; + break; + } } } if (!q) { - osi_Log0(afsd_logp, "cm_Unlock lock not found; failure"); - lock_ReleaseRead(&cm_scacheLock); - /* The lock didn't exist anyway. *shrug* */ - return CM_ERROR_RANGE_NOT_LOCKED; + if (lock_found && !exact_match) { + code = 0; + goto done; + } else { + osi_Log0(afsd_logp, "cm_Unlock lock not found; failure"); + + /* The lock didn't exist anyway. *shrug* */ + return CM_ERROR_RANGE_NOT_LOCKED; + } } /* discard lock record */ @@ -5047,8 +5073,13 @@ long cm_Unlock(cm_scache_t *scp, } } - if (release_userp) + if (release_userp) { cm_ReleaseUser(userp); + release_userp = FALSE; + } + + if (!exact_match) + goto try_again; /* might be more than one lock in the range */ done: diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index 4f403cb2c..985a1fb32 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -204,9 +204,11 @@ extern long cm_UnlockByKey(cm_scache_t * scp, cm_user_t * userp, cm_req_t * reqp); +#define CM_UNLOCK_FLAG_MATCH_RANGE 0x01 + extern long cm_Unlock(cm_scache_t *scp, unsigned char sLockType, LARGE_INTEGER LOffset, LARGE_INTEGER LLength, cm_key_t key, - cm_user_t *userp, cm_req_t *reqp); + afs_uint32 flags, cm_user_t *userp, cm_req_t *reqp); extern long cm_LockCheckRead(cm_scache_t *scp, LARGE_INTEGER LOffset, diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index aac793a3e..05655afc5 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -4109,7 +4109,7 @@ void smb_WaitingLocksDaemon() if (wl->state == SMB_WAITINGLOCKSTATE_DONE) cm_Unlock(scp, wlRequest->lockType, wl->LOffset, - wl->LLength, wl->key, NULL, &req); + wl->LLength, wl->key, 0, NULL, &req); osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q); -- 2.39.5