]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Windows: Readonly Volume Versioning for Windows Cache Manager
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 5 Oct 2009 18:00:50 +0000 (14:00 -0400)
committerJeffrey Altman <jaltman|account-1000011@unknown>
Mon, 12 Oct 2009 14:38:52 +0000 (07:38 -0700)
When the HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters
"ReadOnlyVolumeVersioning" DWORD registry value is non-zero, the volserver
will be queried for each .readonly volume to obtain the lastUpdateTime.
The lastUpdateTime will be used as a volume version identifier for each
cm_scache_t object stored in the volume.  With a known volume version,
whenever a current status is obtained for any object within the .readonly volume,
all the cached objects within that volume that have the same volume version
can share the resulting callback registration.

LICENSE MIT

Reviewed-on: http://gerrit.openafs.org/579
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_server.h
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/cm_volume.h

index 77c242f882b27a35ceca369b440347327a31bb09..46032514fe2468fefb664255cd75d3bebe2b04f1 100644 (file)
@@ -424,6 +424,7 @@ AFSD_EXELIBS =\
        $(DESTDIR)\lib\libafsconf.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afspthread.lib \
+        $(DESTDIR)\lib\afs\afstvolser.lib \
         $(LANAHELPERLIB)
 
 $(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res  $(RXOBJS) $(AFSD_EXELIBS)
index 2176154fcee7a79425e14070dc7c0e9721a2c9b9..17835aea4921cb6839efe81c7390583b8b31ace0 100644 (file)
@@ -111,6 +111,7 @@ extern int cm_fakeGettingCallback;                  // 1 if currently updating the fake root.af
 
 extern int cm_dnsEnabled;
 extern int cm_freelanceEnabled;
+extern int cm_readonlyVolumeVersioning;
 
 extern long rx_mtu;
 
index d9f85f348f3d5b180a774afda614e4e91703e86f..54a8a39015d3ca0c7acaef1f71eeabb3fe9121e0 100644 (file)
@@ -68,6 +68,7 @@ DWORD cm_mountRootLen;
 clientchar_t cm_mountRootC[1024];
 DWORD cm_mountRootCLen;
 
+int cm_readonlyVolumeVersioning = 0;
 int cm_logChunkSize;
 int cm_chunkSize;
 
@@ -398,6 +399,21 @@ static void afsd_InitServerPreferences(void)
                 tsp->flags |= CM_SERVERFLAG_PREF_SET;
                 lock_ReleaseMutex(&tsp->mx);
             }
+
+            if (cm_readonlyVolumeVersioning) {
+                /* Add a matching vol server */
+                tsp = cm_FindServer(&saddr, CM_SERVER_VOL);
+                if ( tsp )             /* an existing server - ref count increased */
+                {
+                    tsp->ipRank = (USHORT)dwRank; /* no need to protect by mutex*/
+                    cm_PutServer(tsp);  /* decrease refcount */
+                }
+                else   /* add a new server without a cell */
+                {
+                    tsp = cm_NewServer(&saddr, CM_SERVER_VOL, NULL, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
+                    tsp->ipRank = (USHORT)dwRank;
+                }
+            }
         }
 
         RegCloseKey(hkPrefs);
@@ -1199,7 +1215,7 @@ afsd_InitCM(char **reasonP)
                            (BYTE *) &dwValue, &dummyLen);
     if (code == ERROR_SUCCESS) {
         cm_followBackupPath = (unsigned short) dwValue;
-    } 
+    }
     afsi_log("CM FollowBackupPath is %u", cm_followBackupPath);
 
     dummyLen = sizeof(DWORD);
@@ -1210,6 +1226,14 @@ afsd_InitCM(char **reasonP)
     } 
     afsi_log("CM PerFileAccessCheck is %d", cm_accessPerFileCheck);
 
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "ReadOnlyVolumeVersioning", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS) {
+        cm_readonlyVolumeVersioning = (unsigned short) dwValue;
+    }
+    afsi_log("CM ReadOnlyVolumeVersioning is %u", cm_readonlyVolumeVersioning);
+
     RegCloseKey (parmKey);
 
     cacheBlocks = ((afs_uint64)cacheSize * 1024) / blockSize;
index e919bf443aaa32c8f31affae4988831c2eb4630c..60ce24d21b49d1434c9c07742d6d5c5822955cfb 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <WINNT/syscfg.h>
 #include <WINNT/afsreg.h>
+#include <afs/vldbint.h>
+#include <afs/volint.h>
 
 int
 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid);
@@ -1729,6 +1731,60 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
         if (scp && scp->flags & CM_SCACHEFLAG_PURERO) {
             cm_volume_t * volp = cm_GetVolumeByFID(&scp->fid);
             if (volp) {
+                /* If the volume has a valid callback from the same
+                 * server as issued this latest callback and we know
+                 * the last update time of the RO volume,
+                 * then the last update time of the RO volume
+                 * must not have changed.  Otherwise, we must obtain
+                 * the volume status info from the volserver that
+                 * matches the file server the callback was received
+                 * from.
+                 */
+                if (cm_readonlyVolumeVersioning &&
+                    (volp->cbExpiresRO == 0 || volp->cbServerpRO != scp->cbServerp)) {
+                    cm_server_t *volserverp;
+
+                    volserverp = cm_FindServer(&scp->cbServerp->addr, CM_SERVER_VOL);
+                    if (volserverp) {
+                        afs_int32 vcode = -1, code = -1;
+                        volEntries volumeInfo;
+                        struct nvldbentry entry;
+                        int i;
+                        afs_uint32 addr = volserverp->addr.sin_addr.s_addr;
+                        cm_cell_t *cellp;
+                        cm_conn_t *connp;
+                        struct rx_connection * rxconnp;
+                        cm_req_t req;
+
+                        cm_InitReq(&req);
+
+                        cellp = cm_FindCellByID(scp->fid.cell, 0);
+                        code = cm_ConnByMServers(cellp->vlServersp, cm_rootUserp, &req, &connp);
+                        if (code == 0) {
+                            rxconnp = cm_GetRxConn(connp);
+                            vcode = VL_GetEntryByIDN(rxconnp, scp->fid.volume, -1, &entry);
+                            rx_PutConnection(rxconnp);
+                        }
+                        if (vcode == 0) {
+                            for (i=0, code=-1; i < entry.nServers; i++) {
+                                if ( entry.serverNumber[i] == htonl(addr)) {
+                                    code = cm_ConnByServer(volserverp, cm_rootUserp, &connp);
+                                    if (code == 0) {
+                                        rxconnp = cm_GetRxConn(connp);
+                                        memset(&volumeInfo, 0, sizeof(volumeInfo));
+                                        code = AFSVolListOneVolume(rxconnp, entry.serverPartition[i], scp->fid.volume, &volumeInfo);
+                                        rx_PutConnection(rxconnp);
+                                    }
+                                    break;
+                                }
+                            }
+                        }
+                        volp->lastUpdateRO = (vcode == 0 && code == 0 ? volumeInfo.volEntries_val->updateDate : 0);
+                        cm_PutServer(volserverp);
+                    }
+                }
+
+                scp->lastUpdateRO = volp->lastUpdateRO;
                 volp->cbExpiresRO = scp->cbExpires;
                 if (volp->cbServerpRO != scp->cbServerp) {
                     if (volp->cbServerpRO)
@@ -1941,8 +1997,22 @@ void cm_CheckCBExpiration(void)
             if (scp->flags & CM_SCACHEFLAG_PURERO) {
                 cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
                 if (volp) {
+                    /* In the case of a scp from a .readonly volume
+                     * we can automatically refresh the scp callback
+                     * state under one of two conditions:
+                     *
+                     *   - there is currently an unexpired callback
+                     *     and the callback is simply being extended
+                     *
+                     *   - the lastUpdateRO time for the scp and the
+                     *     volp are the same indicating that the
+                     *     .readonly has not changed
+                     */
                     if (volp->cbExpiresRO > scp->cbExpires &&
-                        scp->cbExpires > 0) 
+                        (volp->cbServerpRO == scp->cbServerp &&
+                         scp->cbExpires > 0 ||
+                         volp->lastUpdateRO > 0 &&
+                         scp->lastUpdateRO == volp->lastUpdateRO))
                     {
                         scp->cbExpires = volp->cbExpiresRO;
                         if (volp->cbServerpRO != scp->cbServerp) {
index 6bc2bdfead6feca507da4bae8e6bc0c9fee48966..3eca87d9460d17fe38fd897ab3d883c44e368fd4 100644 (file)
@@ -1074,6 +1074,11 @@ static void cm_NewRXConnection(cm_conn_t *tcp, cm_ucell_t *ucellp,
             port = htons(7000);
         serviceID = 1;
         break;
+    case CM_SERVER_VOL:
+        if (port == 0)
+            port = htons(7005);
+        serviceID = 4;
+        break;
     default:
         osi_panic("unknown server type", __FILE__, __LINE__);
     }
index c86453f67bb03cfd8f5d615b28268e81ae88872c..8512b601194580d3a37d1865c96cf3ff68100e1a 100644 (file)
@@ -208,6 +208,7 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
         scp->cbServerp = NULL;
     }
     scp->cbExpires = 0;
+    scp->lastUpdateRO = 0;
 
     scp->fid.vnode = 0;
     scp->fid.volume = 0;
@@ -619,6 +620,7 @@ void cm_InitSCache(int newFile, long maxSCaches)
 #endif
                 scp->cbServerp = NULL;
                 scp->cbExpires = 0;
+                scp->lastUpdateRO = 0;
                 scp->fileLocksH = NULL;
                 scp->fileLocksT = NULL;
                 scp->serverLock = (-1);
@@ -1963,11 +1965,44 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock)
   
     for (scp = cm_data.allSCachesp; scp; scp = scp->allNextp) 
     {
-        sprintf(output, "%s scp=0x%p, fid (cell=%d, volume=%d, vnode=%d, unique=%d) type=%d dv=%I64d len=0x%I64x mp='%s' Locks (server=0x%x shared=%u excl=%u clnt=%u) lockCount=%d flags=0x%x cb=0x%x refCount=%u\r\n",
-                cookie, scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique, 
-                scp->fileType, scp->dataVersion, scp->length.QuadPart, scp->mountPointStringp, 
+        time_t t;
+        char *srvStr = NULL;
+        afs_uint32 srvStrRpc = TRUE;
+        char *cbt = NULL;
+        char *lurot = NULL;
+
+        if (scp->cbServerp) {
+            if (!((scp->cbServerp->flags & CM_SERVERFLAG_UUID) &&
+                UuidToString((UUID *)&scp->cbServerp->uuid, &srvStr) == RPC_S_OK)) {
+                afs_asprintf(&srvStr, "%.0I", scp->cbServerp->addr.sin_addr.s_addr);
+                srvStrRpc = FALSE;
+            }
+        }
+        if (scp->cbExpires) {
+            t = scp->cbExpires;
+            cbt = ctime(&t);
+            if (cbt) {
+                cbt = strdup(cbt);
+                cbt[strlen(cbt)-1] = '\0';
+            }
+        }
+        if (scp->lastUpdateRO) {
+            t = scp->lastUpdateRO;
+            lurot = ctime(&t);
+            if (lurot) {
+                lurot = strdup(lurot);
+                lurot[strlen(lurot)-1] = '\0';
+            }
+        }
+        sprintf(output,
+                "%s scp=0x%p, fid (cell=%d, volume=%d, vnode=%d, unique=%d) type=%d dv=%I64d len=0x%I64x "
+                "mp='%s' Locks (server=0x%x shared=%d excl=%d clnt=%d) fsLockCount=%d linkCount=%d anyAccess=0x%x "
+                "flags=0x%x cbServer='%s' cbExpires='%s' lastUpdateRO='%s' refCount=%u\r\n",
+                cookie, scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
+                scp->fileType, scp->dataVersion, scp->length.QuadPart, scp->mountPointStringp,
                 scp->serverLock, scp->sharedLocks, scp->exclusiveLocks, scp->clientLocks, scp->fsLockCount,
-                scp->flags, (unsigned long)scp->cbExpires, scp->refCount);
+                scp->linkCount, scp->anyAccess, scp->flags, srvStr ? srvStr : "<none>", cbt ? cbt : "<none>",
+                lurot ? lurot : "<none>", scp->refCount);
         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
 
         if (scp->fileLocksH) {
@@ -1976,27 +2011,41 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock)
 
             for (q = scp->fileLocksH; q; q = osi_QNext(q)) {
                 cm_file_lock_t * lockp = (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
-                sprintf(output, "  %s lockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x key=0x%I64x flags=0x%x update=0x%I64u\r\n", 
-                         cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length, 
-                         lockp->lockType, lockp->key, lockp->flags, (afs_uint64)lockp->lastUpdate);
+                sprintf(output,
+                        "  %s lockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x "
+                        "key=0x%I64x flags=0x%x update=0x%I64u\r\n",
+                        cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length,
+                        lockp->lockType, lockp->key, lockp->flags, (afs_uint64)lockp->lastUpdate);
                 WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
             }       
 
             sprintf(output, "  %s - done dumping scp locks\r\n", cookie);
             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }
+
+        if (srvStr) {
+            if (srvStrRpc)
+                RpcStringFree(&srvStr);
+            else
+                free(srvStr);
+        }
+        if (cbt)
+            free(cbt);
+        if (lurot)
+            free(lurot);
     }
   
     sprintf(output, "%s - Done dumping all scache.\r\n", cookie);
     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
-    sprintf(output, "%s - dumping cm_data.scacheHashTable - cm_data.scacheHashTableSize=%d\r\n", cookie, cm_data.scacheHashTableSize);
+    sprintf(output, "%s - dumping cm_data.scacheHashTable - cm_data.scacheHashTableSize=%d\r\n",
+            cookie, cm_data.scacheHashTableSize);
     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
   
     for (i = 0; i < cm_data.scacheHashTableSize; i++)
     {
         for(scp = cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) 
         {
-            sprintf(output, "%s scp=0x%p, hash=%d, fid (cell=%d, volume=%d, vnode=%d, unique=%d)\r\n", 
+            sprintf(output, "%s scp=0x%p, hash=%d, fid (cell=%d, volume=%d, vnode=%d, unique=%d)\r\n",
                     cookie, scp, i, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }
@@ -2010,9 +2059,11 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock)
 
     for (q = cm_allFileLocks; q; q = osi_QNext(q)) {
         cm_file_lock_t * lockp = (cm_file_lock_t *)q;
-        sprintf(output, "%s filelockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x key=0x%I64x flags=0x%x update=0x%I64u\r\n", 
-                 cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length, 
-                 lockp->lockType, lockp->key, lockp->flags, (afs_uint64)lockp->lastUpdate);
+        sprintf(output,
+                "%s filelockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x "
+                "key=0x%I64x flags=0x%x update=0x%I64u\r\n",
+                cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length,
+                lockp->lockType, lockp->key, lockp->flags, (afs_uint64)lockp->lastUpdate);
         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
     }       
 
index 79046f9e3757e337c2b74456bcf15182c6e972a0..9c480c029ea3a930e4eba1a748dc57a7ebc25f1e 100644 (file)
@@ -128,6 +128,9 @@ typedef struct cm_scache {
     afs_uint32 group;                  /* file owning group */
     cm_user_t *creator;                        /* user, if new file */
 
+    /* volume status */
+    time_t lastUpdateRO;                /* last update time for readonly volume */
+
     /* pseudo file status */
     osi_hyper_t serverLength;          /* length known to server */
 
index 16e68242822f7d230a384ee542b34412e64c3e9c..b49a6c91ed7f717f45d78ff9d7f5f076c4726be8 100644 (file)
@@ -29,6 +29,7 @@ osi_rwlock_t cm_syscfgLock;
 cm_server_t *cm_allServersp;
 afs_uint32   cm_numFileServers = 0;
 afs_uint32   cm_numVldbServers = 0;
+afs_uint32   cm_numVolServers = 0;
 
 void
 cm_ForceNewConnectionsAllServers(void)
@@ -59,6 +60,10 @@ cm_PingServer(cm_server_t *tsp)
     char hoststr[16];
     cm_req_t req;
 
+    /* do not probe vol server (yet) */
+    if (tsp->type == CM_SERVER_VOL)
+        return;
+
     lock_ObtainMutex(&tsp->mx);
     if (tsp->flags & CM_SERVERFLAG_PINGING) {
        tsp->waitCount++;
@@ -86,7 +91,7 @@ cm_PingServer(cm_server_t *tsp)
 
        osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x",
                  osi_LogSaveString(afsd_logp, hoststr), 
-                 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
+                 tsp->type == CM_SERVER_VLDB ? "vldb" : (tsp->type == CM_SERVER_FILE ? "file" : "vol"),
                  wasDown ? "down" : "up",
                  tsp->capabilities);
 
@@ -210,9 +215,14 @@ static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
     int doPing;
     int isDown;
     int isFS;
+    int isVLDB;
 
     lock_ObtainRead(&cm_serverLock);
     for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
+        /* do not probe vol server (yet) */
+        if (tsp->type == CM_SERVER_VOL)
+            continue;
+
         cm_GetServerNoLock(tsp);
         lock_ReleaseRead(&cm_serverLock);
 
@@ -222,6 +232,7 @@ static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
         doPing = 0;
         isDown = tsp->flags & CM_SERVERFLAG_DOWN;
         isFS   = tsp->type == CM_SERVER_FILE;
+        isVLDB = tsp->type == CM_SERVER_VLDB;
 
         /* only do the ping if the cell matches the requested cell, or we're
          * matching all cells (cellp == NULL), and if we've requested to ping
@@ -231,7 +242,7 @@ static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
              ((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
                (!isDown && (flags & CM_FLAG_CHECKUPSERVERS))) &&
              ((!(flags & CM_FLAG_CHECKVLDBSERVERS) || 
-               !isFS && (flags & CM_FLAG_CHECKVLDBSERVERS)) &&
+               isVLDB && (flags & CM_FLAG_CHECKVLDBSERVERS)) &&
               (!(flags & CM_FLAG_CHECKFILESERVERS) || 
                  isFS && (flags & CM_FLAG_CHECKFILESERVERS)))) {
             doPing = 1;
@@ -837,7 +848,7 @@ void cm_SetServerPrefs(cm_server_t * serverp)
     }
 
     serverAddr = ntohl(serverp->addr.sin_addr.s_addr);
-    serverp->ipRank  = CM_IPRANK_LOW;  /* default setings */
+    serverp->ipRank  = CM_IPRANK_LOW;  /* default settings */
 
     for ( i=0; i < cm_noIPAddr; i++)
     {
@@ -908,11 +919,14 @@ cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cell
         case CM_SERVER_FILE:
             cm_numFileServers++;
             break;
+        case CM_SERVER_VOL:
+            cm_numVolServers++;
+            break;
         }
 
         lock_ReleaseWrite(&cm_serverLock);     /* release server lock */
 
-        if ( !(flags & CM_FLAG_NOPROBE) ) {
+        if ( !(flags & CM_FLAG_NOPROBE) && (type != CM_SERVER_VOL)) {
             tsp->flags |= CM_SERVERFLAG_DOWN;  /* assume down; ping will mark up if available */
             cm_PingServer(tsp);                        /* Obtain Capabilities and check up/down state */
         }
@@ -1241,6 +1255,9 @@ void cm_FreeServer(cm_server_t* serverp)
             case CM_SERVER_FILE:
                 cm_numFileServers--;
                 break;
+            case CM_SERVER_VOL:
+                cm_numVolServers--;
+                break;
             }
 
            lock_FinalizeMutex(&serverp->mx);
@@ -1337,8 +1354,8 @@ int cm_DumpServers(FILE *outputFile, char *cookie, int lock)
     if (lock)
         lock_ObtainRead(&cm_serverLock);
   
-    sprintf(output, "%s - dumping servers - cm_numFileServers=%d, cm_numVldbServers=%d\r\n", 
-            cookie, cm_numFileServers, cm_numVldbServers);
+    sprintf(output, "%s - dumping servers - cm_numFileServers=%d, cm_numVolServers=%d, cm_numVldbServers=%d\r\n",
+            cookie, cm_numFileServers, cm_numVolServers, cm_numVldbServers);
     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
   
     for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp)
@@ -1353,6 +1370,9 @@ int cm_DumpServers(FILE *outputFile, char *cookie, int lock)
         case CM_SERVER_FILE:
             type = "file";
             break;
+        case CM_SERVER_VOL:
+            type = "vol";
+            break;
         default:
             type = "unknown";
         }
index f4011237ed0bb0659e0993500a1eabf1014dec59..dd3fb89f87b032222563cfa536f2d1c40bcb4117 100644 (file)
@@ -53,6 +53,7 @@ typedef struct cm_serverRef {
 /* types */
 #define CM_SERVER_VLDB         1       /* a VLDB server */
 #define CM_SERVER_FILE         2       /* a file server */
+#define CM_SERVER_VOL           3       /* a vol server */
 
 /* flags */
 #define CM_SERVERFLAG_DOWN     0x1     /* server is down */
index 4e150519edf132730ed6374a70b9807a5d0e861a..c9df208109e72ddcf0ef71e094ba3f2e24e7fd4a 100644 (file)
@@ -169,7 +169,7 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
     afs_uint32 j, k;
     cm_serverRef_t *tsrp;
     cm_server_t *tsp;
-    struct sockaddr_in tsockAddr;
+    struct sockaddr_in tsockAddr, tsockAddr2;
     long tflags;
     u_long tempAddr;
     struct vldbentry vldbEntry;
@@ -526,9 +526,18 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
                 }
             }
             if (!tsp) {
-                /* cm_NewServer will probe the server which in turn will
-                 * update the state on the volume group object */
                 lock_ReleaseWrite(&volp->rw);
+
+                if (cm_readonlyVolumeVersioning) {
+                    tsockAddr2 = tsockAddr;
+                    tsockAddr2.sin_port = htons(7005);
+                    /* Do not probe the volserver.  We will always use the file server's state. */
+                    tsp = cm_NewServer(&tsockAddr2, CM_SERVER_VOL, cellp, &serverUUID[i], CM_FLAG_NOPROBE);
+                    cm_PutServer(tsp); /* no longer need to vol server reference */
+                }
+
+                /* cm_NewServer will probe the file server which in turn will
+                 * update the state on the volume group object */
                 tsp = cm_NewServer(&tsockAddr, CM_SERVER_FILE, cellp, &serverUUID[i], 0);
                 lock_ObtainWrite(&volp->rw);
             }
@@ -937,6 +946,7 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
         }
         volp->cbExpiresRO = 0;
         volp->cbServerpRO = NULL;
+        volp->lastUpdateRO = 0;
         cm_AddVolumeToNameHashTable(volp);
         lock_ReleaseWrite(&cm_volumeLock);
     }
@@ -1484,10 +1494,50 @@ int cm_DumpVolumes(FILE *outputFile, char *cookie, int lock)
   
     for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp)
     {
-        sprintf(output, "%s - volp=0x%p cell=%s name=%s rwID=%u roID=%u bkID=%u flags=0x%x refCount=%u\r\n", 
-                 cookie, volp, volp->cellp->name, volp->namep, volp->vol[RWVOL].ID, volp->vol[ROVOL].ID, volp->vol[BACKVOL].ID, volp->flags, 
-                 volp->refCount);
+        time_t t;
+        char *srvStr = NULL;
+        afs_uint32 srvStrRpc = TRUE;
+        char *cbt = NULL;
+        char *lurot = NULL;
+
+        if (volp->cbServerpRO) {
+            if (!((volp->cbServerpRO->flags & CM_SERVERFLAG_UUID) &&
+                UuidToString((UUID *)&volp->cbServerpRO->uuid, &srvStr) == RPC_S_OK)) {
+                afs_asprintf(&srvStr, "%.0I", volp->cbServerpRO->addr.sin_addr.s_addr);
+                srvStrRpc = FALSE;
+            }
+        }
+        if (volp->cbExpiresRO) {
+            t = volp->cbExpiresRO;
+            cbt = ctime(&t);
+            if (cbt) {
+                cbt = strdup(cbt);
+                cbt[strlen(cbt)-1] = '\0';
+            }
+        }
+        if (volp->lastUpdateRO) {
+            t = volp->lastUpdateRO;
+            lurot = ctime(&t);
+            if (lurot) {
+                lurot = strdup(lurot);
+                lurot[strlen(lurot)-1] = '\0';
+            }
+        }
+
+        sprintf(output, "%s - volp=0x%p cell=%s name=%s rwID=%u roID=%u bkID=%u flags=0x%x cbServerpRO='%s' cbExpiresRO='%s' lastUpdateRO='%s' refCount=%u\r\n",
+                 cookie, volp, volp->cellp->name, volp->namep, volp->vol[RWVOL].ID, volp->vol[ROVOL].ID, volp->vol[BACKVOL].ID, volp->flags,
+                 srvStr ? srvStr : "<none>", cbt ? cbt : "<none>", lurot ? lurot : "<none>", volp->refCount);
         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        if (srvStr) {
+            if (srvStrRpc)
+                RpcStringFree(&srvStr);
+            else
+                free(srvStr);
+        }
+        if (cbt)
+            free(cbt);
+        if (lurot)
+            free(lurot);
     }
     sprintf(output, "%s - Done dumping volumes.\r\n", cookie);
     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
index a7aecff46d48512923a6dddaeb43195a073852c9..d3cdd48c228e0e734b8d084035795e38d2f99663 100644 (file)
@@ -44,6 +44,7 @@ typedef struct cm_volume {
     afs_int32 refCount;                        /* by Interlocked operations */
     struct cm_server *cbServerpRO;      /* server granting RO callback; by cm_scacheLock */
     time_t cbExpiresRO;                 /* latest RO expiration time; by cm_scacheLock */
+    time_t lastUpdateRO;                /* latest RO volume update time; 0 if unknown; by cm_scacheLock */
 } cm_volume_t;
 
 #define CM_VOLUMEFLAG_RESET       1    /* reload this info on next use */