Windows: Add cm_GetVolumeType
[openafs.git] / src / WINNT / afsd / cm_volume.c
index 5f8fe84..491d533 100644 (file)
@@ -72,6 +72,7 @@ cm_ShutdownVolume(void)
                 cm_VolumeStatusNotification(volp, volp->vol[volType].ID, volp->vol[volType].state, vl_alldown);
         }
         volp->cbExpiresRO = 0;
+        volp->cbServerpRO = NULL;
         lock_FinalizeRWLock(&volp->rw);
     }
 
@@ -110,6 +111,7 @@ void cm_InitVolume(int newFile, long maxVols)
                         cm_VolumeStatusNotification(volp, volp->vol[volType].ID, vl_unknown, volp->vol[volType].state);
                 }
                 volp->cbExpiresRO = 0;
+                volp->cbServerpRO = NULL;
             }
         }
         osi_EndOnce(&once);
@@ -163,7 +165,8 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
                     cm_volume_t *volp)
 {
     cm_conn_t *connp;
-    int i, j, k;
+    int i;
+    afs_uint32 j, k;
     cm_serverRef_t *tsrp;
     cm_server_t *tsp;
     struct sockaddr_in tsockAddr;
@@ -321,6 +324,7 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
         afs_int32 bkID;
         afs_int32 serverNumber[NMAXNSERVERS];
         afs_int32 serverFlags[NMAXNSERVERS];
+        afsUUID   serverUUID[NMAXNSERVERS];
         afs_int32 rwServers_alldown = 1;
         afs_int32 roServers_alldown = 1;
         afs_int32 bkServers_alldown = 1;
@@ -331,6 +335,8 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
            rwServers_alldown = 0;
 #endif
 
+        memset(serverUUID, 0, sizeof(serverUUID));
+
         switch ( method ) {
         case 0:
             flags = vldbEntry.flags;
@@ -406,9 +412,10 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
                     for (k = 0; k < nentries && j < NMAXNSERVERS; j++, k++) {
                         serverFlags[j] = uvldbEntry.serverFlags[i];
                         serverNumber[j] = addrp[k];
+                        serverUUID[j] = uuid;
                     }
 
-                    free(addrs.bulkaddrs_val);  /* This is wrong */
+                    xdr_free(addrs.bulkaddrs_val, addrs.bulkaddrs_len * sizeof(*addrs.bulkaddrs_val));
 
                     if (nentries == 0)
                         code = CM_ERROR_INVAL;
@@ -445,6 +452,12 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
             cm_AddVolumeToNameHashTable(volp);
         }
 
+        if (flags & VLF_DFSFILESET) {
+            volp->flags |= CM_VOLUMEFLAG_DFS_VOLUME;
+            osi_Log1(afsd_logp, "cm_UpdateVolume Volume Group '%s' is a DFS File Set.  Correct behavior is not implemented.",
+                     osi_LogSaveString(afsd_logp, volp->namep));
+        }
+
         if (flags & VLF_RWEXISTS) {
             if (volp->vol[RWVOL].ID != rwID) {
                 if (volp->vol[RWVOL].flags & CM_VOLUMEFLAG_IN_HASH)
@@ -491,19 +504,48 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
             tempAddr = htonl(serverNumber[i]);
             tsockAddr.sin_addr.s_addr = tempAddr;
             tsp = cm_FindServer(&tsockAddr, CM_SERVER_FILE);
+            if (tsp && (method == 2) && (tsp->flags & CM_SERVERFLAG_UUID)) {
+                /* 
+                 * Check to see if the uuid of the server we know at this address
+                 * matches the uuid of the server we are being told about by the
+                 * vlserver.  If not, ...?
+                 */
+                if (!afs_uuid_equal(&serverUUID[i], &tsp->uuid)) {
+                    char uuid1[128], uuid2[128];
+                    char hoststr[16];
+
+                    afsUUID_to_string(&serverUUID[i], uuid1, sizeof(uuid1));
+                    afsUUID_to_string(&tsp->uuid, uuid2, sizeof(uuid2));
+                    afs_inet_ntoa_r(serverNumber[i], hoststr);
+
+                    osi_Log3(afsd_logp, "cm_UpdateVolumeLocation UUIDs do not match! %s != %s (%s)",
+                              osi_LogSaveString(afsd_logp, uuid1),
+                              osi_LogSaveString(afsd_logp, uuid2),
+                              osi_LogSaveString(afsd_logp, hoststr));
+                }
+            }
             if (!tsp) {
                 /* cm_NewServer will probe the server which in turn will
                  * update the state on the volume group object */
                 lock_ReleaseWrite(&volp->rw);
-                tsp = cm_NewServer(&tsockAddr, CM_SERVER_FILE, cellp, 0);
+                tsp = cm_NewServer(&tsockAddr, CM_SERVER_FILE, cellp, &serverUUID[i], 0);
                 lock_ObtainWrite(&volp->rw);
             }
-            /* if this server was created by fs setserverprefs */
+            osi_assertx(tsp != NULL, "null cm_server_t");
+                        
+            /*
+             * if this server was created by fs setserverprefs
+             * then it won't have either a cell assignment or 
+             * a server uuid.
+             */
             if ( !tsp->cellp ) 
                 tsp->cellp = cellp;
+            if ( (method == 2) && !(tsp->flags & CM_SERVERFLAG_UUID) && 
+                 !afs_uuid_is_nil(&serverUUID[i])) {
+                tsp->uuid = serverUUID[i];
+                tsp->flags |= CM_SERVERFLAG_UUID;
+            }
 
-            osi_assertx(tsp != NULL, "null cm_server_t");
-                        
             /* and add it to the list(s). */
             /*
              * Each call to cm_NewServerRef() increments the
@@ -893,6 +935,7 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
             volp->vol[volType].flags = 0;
         }
         volp->cbExpiresRO = 0;
+        volp->cbServerpRO = NULL;
         cm_AddVolumeToNameHashTable(volp);
         lock_ReleaseWrite(&cm_volumeLock);
     }
@@ -1255,14 +1298,21 @@ cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID)
 }
 
 
-/* called from the Daemon thread */
+/* 
+ * called from the Daemon thread.
+ * when checking the offline status, check those of the most recently used volumes first.
+ */
 void cm_CheckOfflineVolumes(void)
 {
     cm_volume_t *volp;
     afs_int32 refCount;
+    extern int daemon_ShutdownFlag;
+    extern int powerStateSuspended;
 
     lock_ObtainRead(&cm_volumeLock);
-    for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
+    for (volp = cm_data.volumeLRULastp; 
+         volp && !daemon_ShutdownFlag && !powerStateSuspended; 
+         volp=(cm_volume_t *) osi_QPrev(&volp->q)) {
         if (volp->flags & CM_VOLUMEFLAG_IN_HASH) {
             InterlockedIncrement(&volp->refCount);
             lock_ReleaseRead(&cm_volumeLock);
@@ -1283,6 +1333,7 @@ cm_UpdateVolumeStatusInt(cm_volume_t *volp, struct cm_vol_state *statep)
     cm_serverRef_t *tsrp;
     cm_server_t *tsp;
     int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
+    char addr[16];
 
     if (!volp || !statep) {
 #ifdef DEBUG
@@ -1293,29 +1344,50 @@ cm_UpdateVolumeStatusInt(cm_volume_t *volp, struct cm_vol_state *statep)
 
     lock_ObtainWrite(&cm_serverLock);
     for (tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
-        if (tsrp->status == srv_deleted)
-            continue;
         tsp = tsrp->server;
+        sprintf(addr, "%d.%d.%d.%d", 
+                 ((tsp->addr.sin_addr.s_addr & 0xff)),
+                 ((tsp->addr.sin_addr.s_addr & 0xff00)>> 8),
+                 ((tsp->addr.sin_addr.s_addr & 0xff0000)>> 16),
+                 ((tsp->addr.sin_addr.s_addr & 0xff000000)>> 24)); 
+
+        if (tsrp->status == srv_deleted) {
+            osi_Log2(afsd_logp, "cm_UpdateVolumeStatusInt volume %d server reference %s deleted", 
+                     statep->ID, osi_LogSaveString(afsd_logp,addr));
+            continue;
+        }
         if (tsp) {
             cm_GetServerNoLock(tsp);
             if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
                 allDown = 0;
                 if (tsrp->status == srv_busy) {
+                    osi_Log2(afsd_logp, "cm_UpdateVolumeStatusInt volume %d server reference %s busy", 
+                              statep->ID, osi_LogSaveString(afsd_logp,addr));
                     allOffline = 0;
                     someBusy = 1;
                 } else if (tsrp->status == srv_offline) {
+                    osi_Log2(afsd_logp, "cm_UpdateVolumeStatusInt volume %d server reference %s offline", 
+                              statep->ID, osi_LogSaveString(afsd_logp,addr));
                     allBusy = 0;
                     someOffline = 1;
                 } else {
+                    osi_Log2(afsd_logp, "cm_UpdateVolumeStatusInt volume %d server reference %s online", 
+                              statep->ID, osi_LogSaveString(afsd_logp,addr));
                     allOffline = 0;
                     allBusy = 0;
                 }
+            } else {
+                osi_Log2(afsd_logp, "cm_UpdateVolumeStatusInt volume %d server reference %s down", 
+                          statep->ID, osi_LogSaveString(afsd_logp,addr));
             }
             cm_PutServerNoLock(tsp);
         }
     }   
     lock_ReleaseWrite(&cm_serverLock);
 
+    osi_Log5(afsd_logp, "cm_UpdateVolumeStatusInt allDown %d allBusy %d someBusy %d someOffline %d allOffline %d", 
+             allDown, allBusy, someBusy, someOffline, allOffline);
+
     if (allDown)
        newStatus = vl_alldown;
     else if (allBusy || (someBusy && someOffline)) 
@@ -1717,3 +1789,15 @@ cm_VolumeStateByName(cm_volume_t *volp, char *volname)
     return statep;
 }
 
+afs_int32 
+cm_VolumeType(cm_volume_t *volp, afs_uint32 id)
+{
+    if (id == volp->vol[RWVOL].ID)
+        return(RWVOL);
+    else if (id == volp->vol[ROVOL].ID)
+        return(ROVOL);
+    else if (id == volp->vol[BACKVOL].ID)
+        return (BACKVOL);
+
+    return -1;
+}