Windows: reset local mount point count during freelance re-initialization
[openafs.git] / src / WINNT / afsd / cm_freelance.c
index 8dca8af..f512a1d 100644 (file)
 
 extern void afsi_log(char *pattern, ...);
 
-int cm_noLocalMountPoints;
+static int cm_noLocalMountPoints = 0;
 char * cm_FakeRootDir = NULL;
 int cm_fakeDirSize = 0;
 int cm_fakeDirCallback=0;
 int cm_fakeGettingCallback=0;
-cm_localMountPoint_t* cm_localMountPoints;
+static cm_localMountPoint_t* cm_localMountPoints;
 osi_mutex_t cm_Freelance_Lock;
-int cm_localMountPointChangeFlag = 0;
+static int cm_localMountPointChangeFlag = 0;
 int cm_freelanceEnabled = 1;
 time_t FakeFreelanceModTime = 0x3b49f6e2;
 
@@ -139,12 +139,9 @@ void cm_InitFreelance() {
     thread_t phandle;
     int lpid;
 
-    lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
+    lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
 
-    // make sure we sync the data version to the cached root scache_t                  
-    if (cm_data.rootSCachep && cm_data.rootSCachep->fid.cell == AFS_FAKE_ROOT_CELL_ID) 
-        cm_data.fakeDirVersion = cm_data.rootSCachep->dataVersion;                          
-                                                                                      
+    lock_ObtainMutex(&cm_Freelance_Lock);
     // yj: first we make a call to cm_initLocalMountPoints
     // to read all the local mount points from the registry
     cm_InitLocalMountPoints();
@@ -153,6 +150,7 @@ void cm_InitFreelance() {
     // a fake root directory based on the local mount points
     cm_InitFakeRootDir();
     // --- end of yj code
+    lock_ReleaseMutex(&cm_Freelance_Lock);
 
     /* Start the registry monitor */
     phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
@@ -167,7 +165,7 @@ void cm_InitFreelance() {
 }
 
 /* yj: Initialization of the fake root directory */
-/* to be called while holding freelance lock unless during init. */
+/* to be called while holding freelance lock. */
 void cm_InitFakeRootDir() {
     int i, t1, t2;
     char* currentPos;
@@ -257,7 +255,6 @@ void cm_InitFakeRootDir() {
     curChunk = 13;
 
     // stick the first 2 entries "." and ".." in
-    fakeEntry.fid.unique = htonl(1);
     fakeEntry.fid.vnode = htonl(1);
     strcpy(fakeEntry.name, ".");
     currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
@@ -279,7 +276,9 @@ void cm_InitFakeRootDir() {
     {       
 
         noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
-        fakeEntry.fid.vnode = htonl(curDirEntry + 2);
+        /* enforce the rule that only directories have odd vnode values */
+        fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
+        fakeEntry.fid.unique = htonl(curDirEntry + 1);
         currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
 
         memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
@@ -321,7 +320,9 @@ void cm_InitFakeRootDir() {
             // add an entry to this page
 
             noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
-            fakeEntry.fid.vnode=htonl(curDirEntry+2);
+            /* enforce the rule that only directories have odd vnode values */
+            fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
+            fakeEntry.fid.unique = htonl(curDirEntry + 1);
             currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
             memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
             strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
@@ -386,43 +387,44 @@ int cm_reInitLocalMountPoints() {
 
     osi_Log0(afsd_logp,"Invalidating local mount point scp...  ");
 
-    cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 2);
-
     lock_ObtainWrite(&cm_scacheLock);
     lock_ObtainMutex(&cm_Freelance_Lock);  /* always scache then freelance lock */
-    for (i=0; i<cm_noLocalMountPoints; i++) {
+    for (i=0; i<=cm_noLocalMountPoints; i++) {
+        if (i == 0)
+            cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
+        else
+            cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
         hash = CM_SCACHE_HASH(&aFid);
         for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
-            if (scp->fid.volume == aFid.volume &&
-                 scp->fid.vnode == aFid.vnode &&
-                 scp->fid.unique == aFid.unique 
-                 ) {
-
+            if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
                 // mark the scp to be reused
                 cm_HoldSCacheNoLock(scp);
+                lock_ReleaseMutex(&cm_Freelance_Lock);
                 lock_ReleaseWrite(&cm_scacheLock);
                 lock_ObtainWrite(&scp->rw);
                 cm_DiscardSCache(scp);
-                lock_ReleaseWrite(&scp->rw);
-                cm_CallbackNotifyChange(scp);
-                lock_ObtainWrite(&cm_scacheLock);
-                cm_ReleaseSCacheNoLock(scp);
 
                 // take the scp out of the hash
+                lock_ObtainWrite(&cm_scacheLock);
                 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash]; 
                      tscp; 
                      lscpp = &tscp->nextp, tscp = tscp->nextp) {
                     if (tscp == scp) {
                         *lscpp = scp->nextp;
-                       lock_ObtainWrite(&scp->rw);
+                        scp->nextp = NULL;
                         scp->flags &= ~CM_SCACHEFLAG_INHASH;
-                       lock_ReleaseWrite(&scp->rw);
                         break;
                     }
                 }
+
+                lock_ReleaseWrite(&scp->rw);
+                lock_ReleaseWrite(&cm_scacheLock);
+                cm_CallbackNotifyChange(scp);
+                lock_ObtainWrite(&cm_scacheLock);
+                cm_ReleaseSCacheNoLock(scp);
+                lock_ObtainMutex(&cm_Freelance_Lock);
             }
         }
-        cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, aFid.vnode + 1, 2);
     }
     lock_ReleaseWrite(&cm_scacheLock);
     osi_Log0(afsd_logp,"\tall old scp cleared!");
@@ -431,6 +433,8 @@ int cm_reInitLocalMountPoints() {
     // cm_InitLocalMountPoints call
     osi_Log0(afsd_logp,"Removing old localmountpoints...  ");
     free(cm_localMountPoints);
+    cm_localMountPoints = NULL;
+    cm_noLocalMountPoints = 0;
     osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
 
     // now re-init the localmountpoints
@@ -453,7 +457,7 @@ int cm_reInitLocalMountPoints() {
 // yj: open up the registry and read all the local mount 
 // points that are stored there. Part of the initialization
 // process for the freelance client.
-/* to be called while holding freelance lock unless during init. */
+/* to be called while holding freelance lock. */
 long cm_InitLocalMountPoints() {
     FILE *fp;
     int i;
@@ -490,15 +494,17 @@ long cm_InitLocalMountPoints() {
                          &ftLastWriteTime /* lpftLastWriteTime */
                          );
 
-        smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
+        cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
 
         if ( dwMountPoints == 0 ) {
             rootCellName[0] = '.';
             code = cm_GetRootCellName(&rootCellName[1]);
             if (code == 0) {
+                lock_ReleaseMutex(&cm_Freelance_Lock);
                 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
                 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
                 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
+                lock_ObtainMutex(&cm_Freelance_Lock);
                 dwMountPoints = 3;
             }
         }
@@ -693,9 +699,11 @@ long cm_InitLocalMountPoints() {
         rootCellName[0] = '.';
        code = cm_GetRootCellName(&rootCellName[1]);
         if (code == 0) {
+            lock_ReleaseMutex(&cm_Freelance_Lock);
             cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
             cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
             cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
+            lock_ObtainMutex(&cm_Freelance_Lock);
         }
         return 0;
     }
@@ -855,7 +863,7 @@ long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
             memcpy(shortname, line, cp-line);
             shortname[cp-line]=0;
 
-            if (!stricmp(shortname, filename)) {
+            if (!cm_stricmp_utf8(shortname, filename)) {
                 found = 1;
                 break;
             }
@@ -938,7 +946,7 @@ long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
             memcpy(shortname, line, cp-line);
             shortname[cp-line]=0;
 
-            if (!stricmp(shortname, filename)) {
+            if (!cm_stricmp_utf8(shortname, filename)) {
                 found = 1;
                 break;
             }
@@ -956,7 +964,7 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
     FILE *fp;
     char hfile[260];
     char line[512];
-    char fullname[200];
+    char fullname[CELL_MAXNAMELEN];
     int n;
     int alias = 0;
     HKEY hkFreelance = 0;
@@ -1066,12 +1074,33 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
             fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
         fclose(fp);
     }
+
+    /* Do this while we are holding the lock */
+    cm_data.fakeDirVersion++;
+    cm_localMountPointChangeFlag = 1;
     lock_ReleaseMutex(&cm_Freelance_Lock);
 
-    /* cm_reInitLocalMountPoints(); */
-    if (fidp)
-        cm_SetFid(fidp, fidp->cell, fidp->volume, cm_noLocalMountPoints + 1, 1);
-    cm_noteLocalMountPointChange();
+    if (fidp) {
+        cm_req_t req;
+        afs_uint32 code;
+        cm_scache_t *scp;
+        clientchar_t *cpath;
+
+        cm_InitReq(&req);
+
+        cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);        
+        if (!cpath)
+            return CM_ERROR_NOSUCHPATH;
+        code = cm_NameI(cm_data.rootSCachep, cpath,
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
+                        cm_rootUserp, NULL, &req, &scp);
+        free(cpath);
+        if (code)
+            return code;
+        *fidp = scp->fid;
+        cm_ReleaseSCache(scp);
+    }
+    
     return 0;
 }
 
@@ -1126,6 +1155,7 @@ long cm_FreelanceRemoveMount(char *toremove)
 
             if (!strcmp(shortname, toremove)) {
                 RegDeleteValue( hkFreelance, szValueName );
+                found = 1;
                 break;
             }
         }
@@ -1167,22 +1197,25 @@ long cm_FreelanceRemoveMount(char *toremove)
 
         fclose(fp1);
         fclose(fp2);
-        if (!found)
-            return CM_ERROR_NOSUCHFILE;
+        if (found) {
+            unlink(hfile);
+            rename(hfile2, hfile);
+        }
+    }
 
-        unlink(hfile);
-        rename(hfile2, hfile);
+    if (found) {
+        /* Do this while we are holding the lock */
+        cm_data.fakeDirVersion++;
+        cm_localMountPointChangeFlag = 1;
     }
-    
     lock_ReleaseMutex(&cm_Freelance_Lock);
-    cm_noteLocalMountPointChange();
-    return 0;
+    return (found ? 0 : CM_ERROR_NOSUCHFILE);
 }
 
 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
 {
     char line[512];
-    char fullname[200];
+    char fullname[CELL_MAXNAMELEN];
     int alias = 0;
     HKEY hkFreelanceSymlinks = 0;
     DWORD dwType, dwSize;
@@ -1202,11 +1235,11 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
     fullname[0] = '\0';
     if (filename[0] == '.') {
         cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
-        if (stricmp(&filename[1],fullname) == 0)
+        if (cm_stricmp_utf8(&filename[1],fullname) == 0)
             return CM_ERROR_EXISTS;
     } else {
         cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
-        if (stricmp(filename,fullname) == 0)
+        if (cm_stricmp_utf8(filename,fullname) == 0)
             return CM_ERROR_EXISTS;
     }
 
@@ -1270,12 +1303,33 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
         }
         RegCloseKey(hkFreelanceSymlinks);
     } 
+
+    /* Do this while we are holding the lock */
+    cm_data.fakeDirVersion++;
+    cm_localMountPointChangeFlag = 1;
     lock_ReleaseMutex(&cm_Freelance_Lock);
 
-    /* cm_reInitLocalMountPoints(); */
-    if (fidp)
-        cm_SetFid(fidp, fidp->cell, fidp->volume, cm_noLocalMountPoints + 1, 1);
-    cm_noteLocalMountPointChange();
+    if (fidp) {
+        cm_req_t req;
+        afs_uint32 code;
+        cm_scache_t *scp;
+        clientchar_t *cpath;
+
+        cm_InitReq(&req);
+
+        cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);        
+        if (!cpath)
+            return CM_ERROR_NOSUCHPATH;
+        code = cm_NameI(cm_data.rootSCachep, cpath,
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
+                        cm_rootUserp, NULL, &req, &scp);
+        free(cpath);
+        if (code)
+            return code;
+        *fidp = scp->fid;
+        cm_ReleaseSCache(scp);
+    }
+
     return 0;
 }
 
@@ -1325,14 +1379,58 @@ long cm_FreelanceRemoveSymlink(char *toremove)
 
             if (!strcmp(shortname, toremove)) {
                 RegDeleteValue( hkFreelanceSymlinks, szValueName );
+                found = 1;
                 break;
             }
         }
         RegCloseKey(hkFreelanceSymlinks);
     }
     
+    if (found) {
+        /* Do this while we are holding the lock */
+        cm_data.fakeDirVersion++;
+        cm_localMountPointChangeFlag = 1;
+    }
+    lock_ReleaseMutex(&cm_Freelance_Lock);
+    return (found ? 0 : CM_ERROR_NOSUCHFILE);
+}
+
+long
+cm_FreelanceFetchMountPointString(cm_scache_t *scp)
+{
+    lock_ObtainMutex(&cm_Freelance_Lock);
+    if (!scp->mountPointStringp[0] && 
+        scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
+        scp->fid.volume == AFS_FAKE_ROOT_VOL_ID && 
+        scp->fid.unique <= cm_noLocalMountPoints) {
+        strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-1].mountPointStringp, MOUNTPOINTLEN);
+        scp->mountPointStringp[MOUNTPOINTLEN-1] = 0;   /* null terminate */
+    }
     lock_ReleaseMutex(&cm_Freelance_Lock);
-    cm_noteLocalMountPointChange();
+
+    return 0;
+}
+
+long 
+cm_FreelanceFetchFileType(cm_scache_t *scp)
+{
+    lock_ObtainMutex(&cm_Freelance_Lock);
+    if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
+        scp->fid.volume == AFS_FAKE_ROOT_VOL_ID && 
+        scp->fid.unique <= cm_noLocalMountPoints) 
+    {
+        scp->fileType = cm_localMountPoints[scp->fid.unique-1].fileType;
+    
+        if ( scp->fileType == CM_SCACHETYPE_SYMLINK &&
+             !strnicmp(cm_localMountPoints[scp->fid.unique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
+        {
+            scp->fileType = CM_SCACHETYPE_DFSLINK;
+        } 
+    } else {
+        scp->fileType = CM_SCACHETYPE_INVALID;
+    }
+    lock_ReleaseMutex(&cm_Freelance_Lock);
+
     return 0;
 }
 #endif /* AFS_FREELANCE_CLIENT */