windows-afsd-rename-collision-20081226
[openafs.git] / src / WINNT / afsd / cm_vnodeops.c
index d6b6883..c7a4cab 100644 (file)
@@ -254,7 +254,7 @@ long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
            (*ldpp) = (cm_lock_data_t *)malloc(sizeof(cm_lock_data_t));
            if (!*ldpp) {
                code = ENOMEM;
-               goto _syncopdone;
+               goto _done;
            }
 
            (*ldpp)->key = key;
@@ -288,9 +288,6 @@ long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
         goto _done;
     }
 
-  _syncopdone:
-    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
-
  _done:
     lock_ReleaseWrite(&scp->rw);
 
@@ -302,14 +299,15 @@ extern long cm_CheckNTOpenDone(cm_scache_t *scp, cm_user_t *userp, cm_req_t *req
                               cm_lock_data_t ** ldpp)
 {
     osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, *ldpp);
+    lock_ObtainWrite(&scp->rw);
     if (*ldpp) {
-       lock_ObtainWrite(&scp->rw);
        cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength, 
                  (*ldpp)->key, userp, reqp);
-       lock_ReleaseWrite(&scp->rw);
        free(*ldpp);
        *ldpp = NULL;
     }
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
+    lock_ReleaseWrite(&scp->rw);
     return 0;
 }
 /*
@@ -341,7 +339,8 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
     lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, reqp, PRSFS_DELETE,
                       CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
-    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (!code)
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     lock_ReleaseWrite(&scp->rw);
     if (code)
         return code;
@@ -728,7 +727,11 @@ long cm_LookupSearchProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
 
     sp = (cm_lookupSearch_t *) rockp;
 
-    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+    if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+        /* Can't normalize FS string. */
+        return 0;
+    }
+
     if (sp->caseFold)
         match = cm_NormStrCmpI(matchName, sp->nsearchNamep);
     else
@@ -890,6 +893,8 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
     size_t vnLength;
     int targetType;
 
+    *outScpp = NULL;
+
     if (scp->mountRootFid.cell != 0 && scp->mountRootGen >= cm_data.mountRootGen) {
         tfid = scp->mountRootFid;
         lock_ReleaseWrite(&scp->rw);
@@ -1012,7 +1017,7 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
 }       
 
 long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_user_t *userp,
-                       cm_req_t *reqp, cm_scache_t **outpScpp)
+                       cm_req_t *reqp, cm_scache_t **outScpp)
 {
     long code;
     int dnlcHit = 1;   /* did we hit in the dnlc? yes, we did */
@@ -1023,6 +1028,8 @@ long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_u
     normchar_t *nnamep = NULL;
     fschar_t *fnamep = NULL;
 
+    *outScpp = NULL;
+
     memset(&rock, 0, sizeof(rock));
 
     if (dscp->fid.vnode == 1 && dscp->fid.unique == 1
@@ -1037,7 +1044,15 @@ long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_u
     }
 
     nnamep = cm_ClientStringToNormStringAlloc(cnamep, -1, NULL);
+    if (!nnamep) {
+        code = CM_ERROR_NOSUCHFILE;
+        goto done;
+    }
     fnamep = cm_ClientStringToFsStringAlloc(cnamep, -1, NULL);
+    if (!fnamep) {
+        code = CM_ERROR_NOSUCHFILE;
+        goto done;
+    }
 
     if (flags & CM_FLAG_NOMOUNTCHASE) {
         /* In this case, we should go and call cm_Dir* functions
@@ -1126,7 +1141,7 @@ long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_u
                  cm_ClientStrCmpI(cnamep, _C("ipc$"))) 
         {
             /* nonexistent dir on freelance root, so add it */
-            fschar_t fullname[200] = ".";
+            fschar_t fullname[CELL_MAXNAMELEN + 1] = ".";  /* +1 so that when we skip the . the size is still CELL_MAXNAMELEN */
             int  found = 0;
 
             osi_Log1(afsd_logp,"cm_Lookup adding mount for non-existent directory: %S", 
@@ -1221,7 +1236,7 @@ long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_u
     }
 
     /* copy back pointer */
-    *outpScpp = tscp;
+    *outScpp = tscp;
 
     /* insert scache in dnlc */
     if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) && rock.ExactFound ) {
@@ -1232,7 +1247,8 @@ long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_u
             if (nnamep) 
                 free(nnamep);
             nnamep = cm_ClientStringToNormStringAlloc(cnamep, -1, NULL);
-            cm_dnlcEnter(dscp, nnamep, tscp);
+            if (nnamep)
+                cm_dnlcEnter(dscp, nnamep, tscp);
         }
         lock_ReleaseRead(&dscp->rw);
     }
@@ -1280,7 +1296,7 @@ int cm_ExpandSysName(clientchar_t *inp, clientchar_t *outp, long outSizeCch, uns
 }   
 
 long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * userp,
-                                cm_req_t *reqp, cm_scache_t ** outpScpp)
+                                cm_req_t *reqp, cm_scache_t ** outScpp)
 {
     afs_uint32    code = 0;
     fschar_t      cellName[CELL_MAXNAMELEN];
@@ -1369,7 +1385,7 @@ long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * us
 
     cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
 
-    code = cm_GetSCache(&fid, outpScpp, userp, reqp);
+    code = cm_GetSCache(&fid, outScpp, userp, reqp);
 
   _exit_cleanup:
     if (fnamep)
@@ -1390,10 +1406,10 @@ long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * us
 
 #ifdef DEBUG_REFCOUNT
 long cm_LookupDbg(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
-               cm_req_t *reqp, cm_scache_t **outpScpp, char * file, long line)
+               cm_req_t *reqp, cm_scache_t **outScpp, char * file, long line)
 #else
 long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
-               cm_req_t *reqp, cm_scache_t **outpScpp)
+               cm_req_t *reqp, cm_scache_t **outScpp)
 #endif
 {
     long code;
@@ -1415,7 +1431,7 @@ long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *us
 
     if (dscp == cm_data.rootSCachep &&
         cm_ClientStrCmpNI(namep, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH) == 0) {
-        return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outpScpp);
+        return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outScpp);
     }
 
     if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) {
@@ -1429,7 +1445,7 @@ long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *us
 #endif
 
                 if (code == 0) {
-                    *outpScpp = scp;
+                    *outScpp = scp;
                     return 0;
                 }
                 if (scp) {
@@ -1442,7 +1458,7 @@ long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *us
                 afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
                 osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
 #endif
-                *outpScpp = scp;
+                *outScpp = scp;
                 return code;
             }
         }
@@ -1452,7 +1468,7 @@ long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *us
         afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
         osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
 #endif
-        *outpScpp = scp;
+        *outScpp = scp;
         return code;
     }
 
@@ -1752,12 +1768,19 @@ long cm_AssembleLink(cm_scache_t *linkScp, fschar_t *pathSuffixp,
         StringCchCatA(tsp->data,lengthof(tsp->data), "\\");
         StringCchCatA(tsp->data,lengthof(tsp->data), pathSuffixp);
     }
+
     if (code == 0) {
         clientchar_t * cpath = cm_FsStringToClientStringAlloc(tsp->data, -1, NULL);
+        if (cpath != NULL) {
         cm_ClientStrCpy(tsp->wdata, lengthof(tsp->wdata), cpath);
         free(cpath);
         *newSpaceBufferp = tsp;
     } else {
+            code = CM_ERROR_NOSUCHPATH;
+        }
+    } 
+
+    if (code != 0) {
         cm_FreeSpace(tsp);
 
         if (code == CM_ERROR_PATH_NOT_COVERED && reqp->tidPathp && reqp->relPathp) {
@@ -1803,10 +1826,12 @@ long cm_NameI(cm_scache_t *rootSCachep, clientchar_t *pathp, long flags,
     int fid_count = 0;          /* number of fids processed in this path walk */
     int i;
 
+    *outScpp = NULL;
+
 #ifdef DEBUG_REFCOUNT
     afsi_log("%s:%d cm_NameI rootscp 0x%p ref %d", file, line, rootSCachep, rootSCachep->refCount);
     osi_Log4(afsd_logp,"cm_NameI rootscp 0x%p path %S tidpath %S flags 0x%x",
-             rootSCachep, pathp ? pathp : "<NULL>", tidPathp ? tidPathp : "<NULL>", 
+             rootSCachep, pathp ? pathp : L"<NULL>", tidPathp ? tidPathp : L"<NULL>", 
              flags);
 #endif
 
@@ -2072,7 +2097,7 @@ long cm_NameI(cm_scache_t *rootSCachep, clientchar_t *pathp, long flags,
         cm_ReleaseSCache(tscp);
 
 #ifdef DEBUG_REFCOUNT
-    afsi_log("%s:%d cm_NameI code 0x%x outScpp 0x%p ref %d", file, line, code, *outScpp, (*outScpp)->refCount);
+    afsi_log("%s:%d cm_NameI code 0x%x outScpp 0x%p ref %d", file, line, code, *outScpp, (*outScpp) ? (*outScpp)->refCount : 0);
 #endif
     osi_Log2(afsd_logp,"cm_NameI code 0x%x outScpp 0x%p", code, *outScpp);
     return code;
@@ -2100,6 +2125,8 @@ long cm_EvaluateSymLink(cm_scache_t *dscp, cm_scache_t *linkScp,
     cm_space_t *spacep;
     cm_scache_t *newRootScp;
 
+    *outScpp = NULL;
+
     osi_Log1(afsd_logp, "Evaluating symlink scp 0x%p", linkScp);
 
     code = cm_AssembleLink(linkScp, "", &newRootScp, &spacep, userp, reqp);
@@ -2701,7 +2728,6 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
                 didEnd = 1;     
             }       
             lock_ReleaseWrite(&scp->rw);
-            *scpp = scp;
         }
     }
 
@@ -2720,6 +2746,12 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
     if (fnamep)
         free(fnamep);
 
+    if (scp) {
+        if (scpp)
+            *scpp = scp;
+        else
+            cm_ReleaseSCache(scp);
+    }
     return code;
 }       
 
@@ -2747,7 +2779,7 @@ long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 }
 
 long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *attrp,
-                 cm_user_t *userp, cm_req_t *reqp)
+                cm_user_t *userp, cm_req_t *reqp, cm_scache_t **scpp)
 {
     cm_conn_t *connp;
     long code;
@@ -2860,7 +2892,6 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
                 didEnd = 1;             
             }
             lock_ReleaseWrite(&scp->rw);
-            cm_ReleaseSCache(scp);
         }
     }
 
@@ -2878,6 +2909,13 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
 
     free(fnamep);
 
+    if (scp) {
+        if (scpp)
+            *scpp = scp;
+        else
+            cm_ReleaseSCache(scp);
+    }
+
     /* and return error code */
     return code;
 }       
@@ -3269,6 +3307,46 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
     cm_dirOp_t newDirOp;
     fschar_t * newNamep = NULL;
     int free_oldNamep = FALSE;
+    cm_scache_t *oldScp = NULL, *newScp = NULL;
+
+    if (cOldNamep == NULL || cNewNamep == NULL ||
+        cm_ClientStrLen(cOldNamep) == 0 ||
+        cm_ClientStrLen(cNewNamep) == 0)
+        return CM_ERROR_INVAL;
+
+    /* 
+     * Before we permit the operation, make sure that we do not already have
+     * an object in the destination directory that has a case-insensitive match
+     * for this name UNLESS the matching object is the object we are renaming.
+     */
+    code = cm_Lookup(oldDscp, cOldNamep, 0, userp, reqp, &oldScp);
+    if (code) {
+        osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p cOldName %S old name lookup failed", 
+                 oldDscp, osi_LogSaveStringW(afsd_logp, cOldNamep));
+        goto done;
+    }
+
+    code = cm_Lookup(newDscp, cNewNamep, CM_FLAG_CASEFOLD, userp, reqp, &newScp);
+    if (code == 0) {
+        /* found a matching object with the new name */
+        if (cm_FidCmp(&oldScp->fid, &newScp->fid)) {
+            /* and they don't match so return an error */
+            osi_Log2(afsd_logp, "cm_Rename newDscp 0x%p cNewName %S new name already exists", 
+                      newDscp, osi_LogSaveStringW(afsd_logp, cNewNamep));
+            code = CM_ERROR_EXISTS;
+        }
+        cm_ReleaseSCache(newScp);
+        newScp = NULL;
+    } else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+        code = CM_ERROR_EXISTS;
+    } else {
+        code = 0;
+    }
+    cm_ReleaseSCache(oldScp);
+    oldScp = NULL;
+
+    if (code) 
+        goto done;
 
     if (oldNamep == NULL) {
         code = -1;
@@ -3281,8 +3359,11 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
             cm_EndDirOp(&oldDirOp);
         }
 #endif
-        if (code)
+        if (code) {
+            osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p cOldName %S Original Name lookup failed", 
+                      oldDscp, osi_LogSaveStringW(afsd_logp, cOldNamep));
             goto done;
+        }
     }
 
 
@@ -3294,6 +3375,8 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
     if (oldDscp == newDscp) {
         /* check for identical names */
         if (cm_ClientStrCmp(cOldNamep, cNewNamep) == 0) {
+            osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p newDscp 0x%p CM_ERROR_RENAME_IDENTICAL", 
+                      oldDscp, newDscp);
             code = CM_ERROR_RENAME_IDENTICAL;
             goto done;
         }
@@ -3315,6 +3398,8 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
         oneDir = 0;
         if (oldDscp->fid.cell != newDscp->fid.cell ||
              oldDscp->fid.volume != newDscp->fid.volume) {
+            osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p newDscp 0x%p CM_ERROR_CROSSDEVLINK", 
+                      oldDscp, newDscp);
             code = CM_ERROR_CROSSDEVLINK;
             goto done;
         }
@@ -3324,6 +3409,8 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
          * stale info.  Avoid deadlocks and quit now.
          */
         if (oldDscp->fid.vnode == newDscp->fid.vnode) {
+            osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p newDscp 0x%p vnode collision", 
+                      oldDscp, newDscp);
             code = CM_ERROR_CROSSDEVLINK;
             goto done;
         }
@@ -3876,7 +3963,7 @@ long cm_LockCheckRead(cm_scache_t *scp,
 
         if (INTERSECT_RANGE(range, fileLock->range)) {
             if (IS_LOCK_ACTIVE(fileLock)) {
-                if (fileLock->key == key) {
+                if (cm_KeyEquals(&fileLock->key, &key, 0)) {
 
                     /* If there is an active lock for this client, it
                        is safe to substract ranges.*/
@@ -3898,7 +3985,7 @@ long cm_LockCheckRead(cm_scache_t *scp,
                         cm_LockRangeSubtract(&range, &fileLock->range);
                 }
             } else if (IS_LOCK_LOST(fileLock) &&
-                      (fileLock->key == key || fileLock->lockType == LockWrite)) {
+                       (cm_KeyEquals(&fileLock->key, &key, 0) || fileLock->lockType == LockWrite)) {
                 code = CM_ERROR_BADFD;
                 break;
             }
@@ -3957,7 +4044,7 @@ long cm_LockCheckWrite(cm_scache_t *scp,
 
         if (INTERSECT_RANGE(range, fileLock->range)) {
             if (IS_LOCK_ACTIVE(fileLock)) {
-                if (fileLock->key == key) {
+                if (cm_KeyEquals(&fileLock->key, &key, 0)) {
                     if (fileLock->lockType == LockWrite) {
 
                         /* if there is an active lock for this client, it
@@ -4207,8 +4294,8 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
 
     osi_Log4(afsd_logp, "cm_Lock scp 0x%x type 0x%x offset %d length %d",
              scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
-    osi_Log3(afsd_logp, "... allowWait %d key 0x%x:%x", allowWait, 
-             (unsigned long)(key >> 32), (unsigned long)(key & 0xffffffff));
+    osi_Log4(afsd_logp, "... allowWait %d key <0x%x, 0x%x, 0x%x>", allowWait, 
+             key.process_id, key.session_id, key.file_id);
 
     /*
    A client C can OBTAIN a lock L on cm_scache_t S iff (both 3 and 4):
@@ -4242,7 +4329,7 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
             (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
 
         if (IS_LOCK_LOST(fileLock)) {
-            if (fileLock->key == key) {
+            if (cm_KeyEquals(&fileLock->key, &key, 0)) {
                 code = CM_ERROR_BADFD;
                 break;
             } else if (fileLock->lockType == LockWrite && INTERSECT_RANGE(range, fileLock->range)) {
@@ -4555,8 +4642,6 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
     return code;
 }
 
-static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags);
-
 /* Called with scp->rw held */
 long cm_UnlockByKey(cm_scache_t * scp,
                    cm_key_t key,
@@ -4569,11 +4654,9 @@ long cm_UnlockByKey(cm_scache_t * scp,
     osi_queue_t *q, *qn;
     int n_unlocks = 0;
 
-    osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%p key 0x%x:%x flags=0x%x",
-             scp,
-             (unsigned long)(key >> 32),
-             (unsigned long)(key & 0xffffffff),
-             flags);
+    osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%p key <0x%x,0x%x,0x%x",
+             scp, key.process_id, key.session_id, key.file_id);
+    osi_Log1(afsd_logp, "    flags=0x%x", flags);
 
     lock_ObtainWrite(&cm_scacheLock);
 
@@ -4589,9 +4672,8 @@ long cm_UnlockByKey(cm_scache_t * scp,
                  (unsigned long) fileLock->range.offset,
                  (unsigned long) fileLock->range.length,
                 fileLock->lockType);
-        osi_Log3(afsd_logp, "     key[0x%x:%x] flags[0x%x]",
-                 (unsigned long)(fileLock->key >> 32),
-                 (unsigned long)(fileLock->key & 0xffffffff),
+        osi_Log4(afsd_logp, "     key<0x%x, 0x%x, 0x%x> flags[0x%x]",
+                 fileLock->key.process_id, fileLock->key.session_id, fileLock->key.file_id,
                  fileLock->flags);
 
         if (cm_FidCmp(&fileLock->fid, &fileLock->scp->fid)) {
@@ -4611,7 +4693,7 @@ long cm_UnlockByKey(cm_scache_t * scp,
 #endif
 
         if (!IS_LOCK_DELETED(fileLock) &&
-            cm_KeyEquals(fileLock->key, key, flags)) {
+            cm_KeyEquals(&fileLock->key, &key, flags)) {
             osi_Log3(afsd_logp, "...Unlock range [%d,+%d] type %d",
                     fileLock->range.offset,
                     fileLock->range.length,
@@ -4759,8 +4841,8 @@ long cm_Unlock(cm_scache_t *scp,
 
     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_Log2(afsd_logp, "... key 0x%x:%x",
-             (unsigned long) (key >> 32), (unsigned long) (key & 0xffffffff));
+    osi_Log3(afsd_logp, "... key <0x%x,0x%x,0x%x>",
+             key.process_id, key.session_id, key.file_id);
 
     lock_ObtainRead(&cm_scacheLock);
 
@@ -4785,7 +4867,7 @@ long cm_Unlock(cm_scache_t *scp,
         }
 #endif
         if (!IS_LOCK_DELETED(fileLock) &&
-            fileLock->key == key &&
+            cm_KeyEquals(&fileLock->key, &key, 0) &&
             fileLock->range.offset == LOffset.QuadPart &&
             fileLock->range.length == LLength.QuadPart) {
             break;
@@ -5207,9 +5289,8 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead)
              (unsigned)(oldFileLock->range.offset & 0xffffffff),
              (unsigned)(oldFileLock->range.length >> 32),
              (unsigned)(oldFileLock->range.length & 0xffffffff));
-    osi_Log3(afsd_logp, "    key(%x:%x) flags=%x",
-             (unsigned)(oldFileLock->key >> 32),
-             (unsigned)(oldFileLock->key & 0xffffffff),
+    osi_Log4(afsd_logp, "    key<0x%x,0x%x,0x%x> flags=%x",
+             oldFileLock->key.process_id, oldFileLock->key.session_id, oldFileLock->key.file_id,
              (unsigned)(oldFileLock->flags));
 
     /* if the lock has already been granted, then we have nothing to do */
@@ -5281,7 +5362,7 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead)
                 ((char *) q - offsetof(cm_file_lock_t, fileq));
 
             if (IS_LOCK_LOST(fileLock)) {
-                if (fileLock->key == oldFileLock->key) {
+                if (cm_KeyEquals(&fileLock->key, &oldFileLock->key, 0)) {
                     code = CM_ERROR_BADFD;
                     oldFileLock->flags |= CM_FILELOCK_FLAG_LOST;
                     osi_Log1(afsd_logp, "    found lost lock %p for same key.  Marking lock as lost",
@@ -5483,27 +5564,21 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead)
     return code;
 }
 
-cm_key_t cm_GenerateKey(unsigned int session_id, unsigned long process_id, unsigned int file_id)
+cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint16 file_id)
 {
-#ifdef DEBUG
-    osi_assertx((process_id & 0xffffffff) == process_id, "unexpected process_id");
-    osi_assertx((session_id & 0xffff) == session_id, "unexpected session_id");
-    osi_assertx((file_id & 0xffff) == file_id, "unexpected file_id");
-#endif
+    cm_key_t key;
 
-    return 
-        (((cm_key_t) (process_id & 0xffffffff)) << 32) |
-        (((cm_key_t) (session_id & 0xffff)) << 16) |
-        (((cm_key_t) (file_id & 0xffff)));
+    key.process_id = process_id;
+    key.session_id = session_id;
+    key.file_id = file_id;
+
+    return key;
 }
 
-static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags)
+int cm_KeyEquals(cm_key_t *k1, cm_key_t *k2, int flags)
 {
-    if (flags & CM_UNLOCK_BY_FID) {
-        return ((k1 & 0xffffffff) == (k2 & 0xffffffff));
-    } else {
-        return (k1 == k2);
-    }
+    return (k1->session_id == k2->session_id) && (k1->file_id == k2->file_id) &&
+        ((flags & CM_UNLOCK_BY_FID) || (k1->process_id == k2->process_id));
 }
 
 void cm_ReleaseAllLocks(void)