windows-btree-flush-race-20090522
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index 3457bb1..c2b1e2b 100644 (file)
@@ -60,7 +60,8 @@ extern void afsi_log(char *pattern, ...);
 
 void cm_InitIoctl(void)
 {
-    lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
+    lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock",
+                          LOCK_HIERARCHY_AFSDBSBMT_GLOBAL);
 }
 
 /* 
@@ -101,8 +102,14 @@ cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 
     code = buf_FlushCleanPages(scp, userp, reqp);
         
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
+        lock_ObtainWrite(&scp->dirlock);
     lock_ObtainWrite(&scp->rw);
     cm_DiscardSCache(scp);
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+        cm_ResetSCacheDirectory(scp, 1);
+        lock_ReleaseWrite(&scp->dirlock);
+    }
     lock_ReleaseWrite(&scp->rw);
 
     osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
@@ -166,31 +173,6 @@ cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 vol
 }
 
 /*
- * Utility function.  Used within this file.
- * Invalidate ACL info for a user that has just        obtained or lost tokens.
- */
-void 
-cm_ResetACLCache(cm_user_t *userp)
-{
-    cm_scache_t *scp;
-    int hash;
-
-    lock_ObtainWrite(&cm_scacheLock);
-    for (hash=0; hash < cm_data.scacheHashTableSize; hash++) {
-        for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
-            cm_HoldSCacheNoLock(scp);
-            lock_ReleaseWrite(&cm_scacheLock);
-            lock_ObtainWrite(&scp->rw);
-            cm_InvalidateACLUser(scp, userp);
-            lock_ReleaseWrite(&scp->rw);
-            lock_ObtainWrite(&cm_scacheLock);
-            cm_ReleaseSCacheNoLock(scp);
-        }
-    }
-    lock_ReleaseWrite(&cm_scacheLock);
-}       
-
-/*
  *  TranslateExtendedChars - This is a fix for TR 54482.
  *
  *  If an extended character (80 - FF) is entered into a file
@@ -364,6 +346,37 @@ cm_NormalizeAfsPath(clientchar_t *outpathp, long cchlen, clientchar_t *inpathp)
     }
 }
 
+void cm_NormalizeAfsPathAscii(char *outpathp, long outlen, char *inpathp)
+{
+    char *cp;
+    char bslash_mountRoot[256];
+       
+    strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
+    bslash_mountRoot[0] = '\\';
+       
+    if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
+        StringCbCopy(outpathp, outlen, inpathp);
+    else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
+        StringCbCopy(outpathp, outlen, inpathp);
+    else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
+        StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
+    else // inpathp looks like "<cell>/usr"
+        StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
+
+    for (cp = outpathp; *cp != 0; ++cp) {
+        if (*cp == '\\')
+            *cp = '/';
+    }       
+
+    if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
+        outpathp[strlen(outpathp)-1] = 0;
+    }
+
+    if (!strcmpi (outpathp, cm_mountRoot)) {
+        StringCbCopy(outpathp, outlen, cm_mountRoot);
+    }
+}
+
 
 /* 
  * VIOCGETAL internals.
@@ -381,7 +394,7 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
     AFSVolSync volSync;
     AFSFid afid;
     int tlen;
-    struct rx_connection * callp;
+    struct rx_connection * rxconnp;
 
     /* now make the get acl call */
 #ifdef AFS_FREELANCE_CLIENT
@@ -401,9 +414,9 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
             if (code) 
                 continue;
 
-            callp = cm_GetRxConn(connp);
-            code = RXAFS_FetchACL(callp, &afid, &acl, &fileStatus, &volSync);
-            rx_PutConnection(callp);
+            rxconnp = cm_GetRxConn(connp);
+            code = RXAFS_FetchACL(rxconnp, &afid, &acl, &fileStatus, &volSync);
+            rx_PutConnection(rxconnp);
 
         } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
         code = cm_MapRPCError(code, reqp);
@@ -448,9 +461,13 @@ cm_IoctlGetFileCellName(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
             clientchar_t * cellname;
 
             cellname = cm_FsStringToClientStringAlloc(cellp->name, -1, NULL); 
-            cm_UnparseIoctlString(ioctlp, NULL, cellname, -1);
-            free(cellname);
-            code = 0;
+            if (cellname == NULL) {
+                code = CM_ERROR_NOSUCHCELL;
+            } else {
+                cm_UnparseIoctlString(ioctlp, NULL, cellname, -1);
+                free(cellname);
+                code = 0;
+            }
         } else
             code = CM_ERROR_NOSUCHCELL;
     }
@@ -474,7 +491,7 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
     AFSFetchStatus fileStatus;
     AFSVolSync volSync;
     AFSFid fid;
-    struct rx_connection * callp;
+    struct rx_connection * rxconnp;
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
@@ -493,9 +510,9 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
             if (code) 
                 continue;
 
-            callp = cm_GetRxConn(connp);
-            code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
-            rx_PutConnection(callp);
+            rxconnp = cm_GetRxConn(connp);
+            code = RXAFS_StoreACL(rxconnp, &fid, &acl, &fileStatus, &volSync);
+            rx_PutConnection(rxconnp);
 
         } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
         code = cm_MapRPCError(code, reqp);
@@ -515,14 +532,11 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
  * Assumes that pioctl path has been parsed or skipped.
  */
 afs_int32 
-cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp)
+cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_req_t *reqp)
 {
     afs_int32 code;
     cm_scache_t *scp;
     int i;
-    cm_req_t req;
-
-    cm_InitReq(&req);
 
     lock_ObtainWrite(&cm_scacheLock);
     for (i=0; i<cm_data.scacheHashTableSize; i++) {
@@ -531,7 +545,7 @@ cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp)
            lock_ReleaseWrite(&cm_scacheLock);
 
            /* now flush the file */
-           code = cm_FlushFile(scp, userp, &req);
+           code = cm_FlushFile(scp, userp, reqp);
            lock_ObtainWrite(&cm_scacheLock);
            cm_ReleaseSCacheNoLock(scp);
         }
@@ -610,7 +624,7 @@ cm_IoctlSetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
     cm_cell_t *cellp;
     char *cp;
     clientchar_t *strp;
-    struct rx_connection * callp;
+    struct rx_connection * rxconnp;
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
@@ -664,10 +678,10 @@ cm_IoctlSetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
             if (code)
                 continue;
 
-            callp = cm_GetRxConn(tcp);
-            code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
+            rxconnp = cm_GetRxConn(tcp);
+            code = RXAFS_SetVolumeStatus(rxconnp, scp->fid.volume,
                                          &storeStat, volName, offLineMsg, motd);
-            rx_PutConnection(callp);
+            rx_PutConnection(rxconnp);
 
         } while (cm_Analyze(tcp, userp, reqp, &scp->fid, NULL, NULL, NULL, code));
         code = cm_MapRPCError(code, reqp);
@@ -717,7 +731,7 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
     char *Name;
     char *OfflineMsg;
     char *MOTD;
-    struct rx_connection * callp;
+    struct rx_connection * rxconnp;
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
@@ -740,10 +754,10 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
            code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp);
            if (code) continue;
 
-           callp = cm_GetRxConn(connp);
-           code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
+           rxconnp = cm_GetRxConn(connp);
+           code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
                                         &volStat, &Name, &OfflineMsg, &MOTD);
-           rx_PutConnection(callp);
+           rx_PutConnection(rxconnp);
 
        } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, NULL, NULL, code));
        code = cm_MapRPCError(code, reqp);
@@ -877,7 +891,7 @@ cm_IoctlGetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *sc
 afs_int32 
 cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
 {
-    afs_int32 code;
+    afs_int32 code = 0;
     cm_cell_t *cellp;
     cm_volume_t *tvp;
     cm_serverRef_t **tsrpp, *current;
@@ -921,16 +935,19 @@ cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp
        
         cp = ioctlp->outDatap;
         
-        tsrpp = cm_GetVolServers(tvp, volume);
-        lock_ObtainRead(&cm_serverLock);
-        for (current = *tsrpp; current; current = current->next) {
-            tsp = current->server;
-            memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
-            cp += sizeof(long);
+        tsrpp = cm_GetVolServers(tvp, volume, userp, reqp);
+        if (tsrpp == NULL) {
+            code = CM_ERROR_NOSUCHVOLUME;
+        } else {
+            lock_ObtainRead(&cm_serverLock);
+            for (current = *tsrpp; current; current = current->next) {
+                tsp = current->server;
+                memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
+                cp += sizeof(long);
+            }
+            lock_ReleaseRead(&cm_serverLock);
+            cm_FreeServerList(tsrpp, 0);
         }
-        lock_ReleaseRead(&cm_serverLock);
-        cm_FreeServerList(tsrpp, 0);
-
         /* still room for terminating NULL, add it on */
         volume = 0;    /* reuse vbl */
         memcpy(cp, (char *)&volume, sizeof(long));
@@ -939,7 +956,7 @@ cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp
         ioctlp->outDatap = cp;
         cm_PutVolume(tvp);
     }
-    return 0;
+    return code;
 }       
 
 /* 
@@ -956,7 +973,8 @@ cm_IoctlStatMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache
     clientchar_t *cp;
 
     cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
-    code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+
+    code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     if (code) 
         goto done_2;
 
@@ -1011,7 +1029,7 @@ cm_IoctlDeleteMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
 
     cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
 
-    code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
         
     /* if something went wrong, bail out now */
     if (code)
@@ -1344,8 +1362,12 @@ cm_IoctlGetCell(struct cm_ioctl *ioctlp, struct cm_user *userp)
         ioctlp->outDatap = basep + max * sizeof(afs_int32);
 
         cellnamep = cm_FsStringToClientStringAlloc(tcellp->name, -1, NULL);
-        cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
-        free(cellnamep);
+        if (cellnamep) {
+            cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
+            free(cellnamep);
+        } else {
+            tcellp = NULL;
+        }
     }
 
     if (tcellp) 
@@ -1378,39 +1400,49 @@ cm_IoctlNewCell(struct cm_ioctl *ioctlp, struct cm_user *userp)
     for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) 
     {
         afs_int32 code;
-       lock_ObtainMutex(&cp->mx);
+
         /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
         cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
         cp->vlServersp = NULL;
+        lock_ReleaseWrite(&cm_cellLock);
+
         rock.cellp = cp;
         rock.flags = 0;
-        code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, &rock);
+        code = cm_SearchCellFileEx(cp->name, cp->name, cp->linkedName, cm_AddCellProc, &rock);
 #ifdef AFS_AFSDB_ENV
         if (code) {
             if (cm_dnsEnabled) {
                 int ttl;
                 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, &rock);
                 if ( code == 0 ) { /* got cell from DNS */
+                    lock_ObtainMutex(&cp->mx);
                     cp->flags |= CM_CELLFLAG_DNS;
                     cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                     cp->timeout = time(0) + ttl;
+                    lock_ReleaseMutex(&cp->mx);
                 }
             }
         } 
         else {
+            lock_ObtainMutex(&cp->mx);
             cp->flags &= ~CM_CELLFLAG_DNS;
+            lock_ReleaseMutex(&cp->mx);
         }
 #endif /* AFS_AFSDB_ENV */
         if (code) {
+            lock_ObtainMutex(&cp->mx);
             cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
+            lock_ReleaseMutex(&cp->mx);
+            lock_ObtainWrite(&cm_cellLock);
         }
         else {
+            lock_ObtainMutex(&cp->mx);
             cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
+            lock_ReleaseMutex(&cp->mx);
+            lock_ObtainWrite(&cm_cellLock);
             cm_RandomizeServer(&cp->vlServersp);
         }
-       lock_ReleaseMutex(&cp->mx);
     }
-    
     lock_ReleaseWrite(&cm_cellLock);
     return 0;       
 }
@@ -1432,8 +1464,12 @@ cm_IoctlGetWsCell(cm_ioctl_t *ioctlp, cm_user_t *userp)
     } else if (cm_data.rootCellp) {
         clientchar_t * cellnamep = cm_FsStringToClientStringAlloc(cm_data.rootCellp->name, -1, NULL);
         /* return the default cellname to the caller */
-        cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
-        free(cellnamep);
+        if (cellnamep) {
+            cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
+            free(cellnamep);
+        } else {
+            code = CM_ERROR_NOSUCHCELL;
+        }
     } else {
         /* if we don't know our default cell, return failure */
         code = CM_ERROR_NOSUCHCELL;
@@ -1655,7 +1691,7 @@ cm_IoctlSetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
         }
         else   /* add a new server without a cell */
         {
-            tsp = cm_NewServer(&tmp, type, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
+            tsp = cm_NewServer(&tmp, type, NULL, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
             tsp->ipRank = rank;
         }
        lock_ObtainMutex(&tsp->mx);
@@ -1730,13 +1766,15 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
     cm_attr_t tattr;
     clientchar_t *cp;
     fschar_t mpInfo[512];           /* mount point string */
-    fschar_t fullCell[MAXCELLCHARS];
+    fschar_t fullCell[CELL_MAXNAMELEN];
     fschar_t *fscell = NULL;
     fschar_t *fsvolume = NULL;
     clientchar_t volume[VL_MAXNAMELEN];
     clientchar_t *mpp = NULL;
     clientchar_t *cell = NULL;
-    int ttl;
+    cm_volume_t *volp = NULL;
+    cm_cell_t *cellp = NULL;
+    size_t len;
 
    /* 
      * The fs command allows the user to specify partial cell names on NT.  These must
@@ -1757,12 +1795,8 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
         fsvolume = cm_ClientStringToFsStringAlloc(volume, -1, NULL);
 
         /* Get the full name for this cell */
-        code = cm_SearchCellFile(fscell, fullCell, 0, 0);
-#ifdef AFS_AFSDB_ENV
-        if (code && cm_dnsEnabled)
-            code = cm_SearchCellByDNS(fscell, fullCell, &ttl, 0, 0);
-#endif
-        if (code) {
+        cellp = cm_GetCell_Gen(fscell, fullCell, CM_FLAG_NOPROBE);
+        if (!cellp) {
             code = CM_ERROR_NOSUCHCELL;
             goto done;
         }
@@ -1774,8 +1808,25 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
         /* No cell name specified, so cell points at the volume instead. */
         fsvolume = cm_ClientStringToFsStringAlloc(cell, -1, NULL);
         cm_ClientStringToFsString(mpp, -1, mpInfo, lengthof(mpInfo));
+        cellp = cm_FindCellByID(dscp->fid.cell, CM_FLAG_NOPROBE);
     }
 
+    /* remove the trailing dot if it is present */
+    len = strlen(fsvolume);
+    if (len > 1 && fsvolume[len-1] == '.')
+        fsvolume[len-1] = '\0';
+
+    /* validate the target info */
+    if (cm_VolNameIsID(fsvolume)) {
+        code = cm_FindVolumeByID(cellp, atoi(fsvolume), userp, reqp, 
+                                CM_GETVOL_FLAG_CREATE, &volp);
+    } else {
+        code = cm_FindVolumeByName(cellp, fsvolume, userp, reqp, 
+                                  CM_GETVOL_FLAG_CREATE, &volp);
+    }
+    if (code)
+        goto done;
+
 #ifdef AFS_FREELANCE_CLIENT
     if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
         /* we are adding the mount point to the root dir, so call
@@ -1803,6 +1854,8 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
                          dscp, leaf, NULL, TRUE);
 
   done:
+    if (volp)
+        cm_PutVolume(volp);
     if (mpp)
         free(mpp);
     if (fscell)
@@ -1898,7 +1951,7 @@ cm_IoctlListlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *ds
     cp = ioctlp->inDatap;
 
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
-    code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     free(clientp);
     if (code) 
         return code;
@@ -1914,16 +1967,20 @@ cm_IoctlListlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *ds
     code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, reqp);
     cm_ReleaseSCache(scp);
     if (code == 0) {
+        char * linkstr;
         cp = ioctlp->outDatap;
         if (newRootScp != NULL) {
             StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
             StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
             cp += strlen(cp);
         }
-        StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
+
+        linkstr = cm_ClientStringToFsStringAlloc(spacep->wdata, -1, NULL);
+        StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), linkstr);
         cp += strlen(cp) + 1;
         ioctlp->outDatap = cp;
         cm_FreeSpace(spacep);
+        free(linkstr);
         if (newRootScp != NULL)
             cm_ReleaseSCache(newRootScp);
         code = 0;
@@ -1964,7 +2021,7 @@ cm_IoctlIslink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp
     osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
 
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
-    code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     free(clientp);
     if (code)
         return code;
@@ -2001,7 +2058,7 @@ cm_IoctlDeletelink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *
     cp = ioctlp->inDatap;
 
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
-    code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
 
     /* if something went wrong, bail out now */
     if (code)
@@ -2104,6 +2161,7 @@ cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
     int i;
     char * p, * r;
 
+    memset(&info, 0, sizeof(info));
     tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
     code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
     afsconf_Close(tdir);
@@ -2129,6 +2187,8 @@ cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
 
     code = ubik_ClientInit(serverconns, &pruclient);
     if (code) {
+        if (info.linkedCell)
+            free(info.linkedCell);
        return code;
     }
 
@@ -2162,6 +2222,8 @@ cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
        pruclient = NULL;
     }
 
+    if (info.linkedCell)
+        free(info.linkedCell);
     return 0;
 }
 #endif /* QUERY_AFSID */
@@ -2296,7 +2358,7 @@ cm_IoctlSetToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
         ioctlp->flags |= CM_IOCTLFLAG_LOGON;
     }
 
-    cm_ResetACLCache(userp);
+    cm_ResetACLCache(cellp, userp);
 
     if (release_userp)
        cm_ReleaseUser(userp);
@@ -2519,7 +2581,7 @@ cm_IoctlDelToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     lock_ReleaseMutex(&userp->mx);
 
-    cm_ResetACLCache(userp);
+    cm_ResetACLCache(cellp, userp);
 
     return 0;
 }
@@ -2554,7 +2616,7 @@ cm_IoctlDelAllToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     lock_ReleaseMutex(&userp->mx);
 
-    cm_ResetACLCache(userp);
+    cm_ResetACLCache(NULL, userp);
 
     return 0;
 }
@@ -2584,6 +2646,7 @@ cm_IoctlMakeSubmount(cm_ioctl_t *ioctlp, cm_user_t *userp)
     /* Parse the input parameters--first the required afs path,
      * then the requested submount name (which may be "").
      */
+    cm_NormalizeAfsPathAscii(afspath, sizeof(afspath), ioctlp->inDatap);
     submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
 
     /* If the caller supplied a suggested submount name, see if
@@ -2760,8 +2823,10 @@ cm_IoctlSetRxkcrypt(cm_ioctl_t *ioctlp, cm_user_t *userp)
     memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
 
     if (c != cryptall) {
-       if (cryptall)
+       if (cryptall == 1)
             LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
+       else if (cryptall == 2)
+            LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_AUTH);
        else
             LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
     }
@@ -2955,7 +3020,10 @@ cm_IoctlMemoryDump(struct cm_ioctl *ioctlp, struct cm_user *userp)
     cm_DumpVolumes(hLogFile, cookie, 1);
     cm_DumpSCache(hLogFile, cookie, 1);
     cm_DumpBufHashTable(hLogFile, cookie, 1);
+    cm_DumpServers(hLogFile, cookie, 1);
     smb_DumpVCP(hLogFile, cookie, 1);
+    rx_DumpCalls(hLogFile, cookie);
+    rx_DumpPackets(hLogFile, cookie);
 
     CloseHandle(hLogFile);                          
   
@@ -2982,6 +3050,8 @@ cm_CheckServersStatus(cm_serverRef_t *serversp)
 
     lock_ObtainRead(&cm_serverLock);
     for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+        if (tsrp->status == srv_deleted)
+            continue;
         if (tsp = tsrp->server) {
             cm_GetServerNoLock(tsp);
             lock_ReleaseRead(&cm_serverLock);
@@ -3077,7 +3147,7 @@ cm_IoctlPathAvailability(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
  * Assumes that pioctl path has been parsed or skipped.
  */
 afs_int32
-cm_IoctlVolStatTest(struct cm_ioctl *ioctlp, struct cm_user *userp)
+cm_IoctlVolStatTest(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_req_t *reqp)
 {
     afs_int32 code;
     cm_cell_t *cellp = NULL;
@@ -3085,9 +3155,6 @@ cm_IoctlVolStatTest(struct cm_ioctl *ioctlp, struct cm_user *userp)
     cm_vol_state_t *statep;
     struct VolStatTest * testp;
     afs_uint32 n;
-    cm_req_t req;
-
-    cm_InitReq(&req);
 
     testp = (struct VolStatTest *)ioctlp->inDatap;
 
@@ -3139,11 +3206,11 @@ cm_IoctlVolStatTest(struct cm_ioctl *ioctlp, struct cm_user *userp)
         if (n)
             testp->fid.volume = n;
         else
-            code = cm_FindVolumeByName(cellp, testp->volname, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
+            code = cm_FindVolumeByName(cellp, testp->volname, userp, reqp, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
     }
 
     if (testp->fid.volume > 0)
-        code = cm_FindVolumeByID(cellp, testp->fid.volume, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
+        code = cm_FindVolumeByID(cellp, testp->fid.volume, userp, reqp, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
 
     if (code)
         return code;