Windows: cache readonly volume size information
authorJeffrey Altman <jaltman@your-file-system.com>
Wed, 27 Mar 2013 04:49:56 +0000 (00:49 -0400)
committerJeffrey Altman <jaltman@your-file-system.com>
Thu, 28 Mar 2013 18:24:55 +0000 (11:24 -0700)
Cache the volume size information for .readonly volumes which can
be reset when the volume callback is broken.  This reduces the number
of RXAFS_GetVolumeStatus RPC calls issues on .readonly volumes.

Change-Id: Ie0e63ca9082a004da71098e28df1315d42d364ff
Reviewed-on: http://gerrit.openafs.org/9681
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/cm_volume.h
src/WINNT/afsrdr/user/RDRFunction.c

index 9e23278..a9deefa 100644 (file)
@@ -227,6 +227,8 @@ cm_callbackDiscardROVolumeByFID(cm_fid_t *fidp)
         if (volp->cbExpiresRO) {
             volp->cbExpiresRO = 0;
             volp->cbIssuedRO = 0;
+            volp->volumeSizeRO = 0;
+            _InterlockedAnd(&volp->volumeSizeRO, ~CM_VOLUMEFLAG_RO_SIZE_VALID);
             if (volp->cbServerpRO) {
                 cm_PutServer(volp->cbServerpRO);
                 volp->cbServerpRO = NULL;
index ddd3a58..6337775 100644 (file)
@@ -78,6 +78,9 @@ cm_ShutdownVolume(void)
         volp->cbExpiresRO = 0;
         volp->cbIssuedRO = 0;
         volp->cbServerpRO = NULL;
+        volp->volumeSizeRO = 0;
+        _InterlockedAnd(&volp->volumeSizeRO, ~CM_VOLUMEFLAG_RO_SIZE_VALID);
+
         lock_FinalizeRWLock(&volp->rw);
     }
 
@@ -119,6 +122,8 @@ void cm_InitVolume(int newFile, long maxVols)
                 volp->cbExpiresRO = 0;
                 volp->cbIssuedRO = 0;
                 volp->cbServerpRO = NULL;
+                volp->volumeSizeRO = 0;
+                _InterlockedAnd(&volp->volumeSizeRO, ~CM_VOLUMEFLAG_RO_SIZE_VALID);
             }
         }
         osi_EndOnce(&once);
@@ -1285,6 +1290,7 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
     cm_req_t req;
     struct rx_connection * rxconnp;
     char volName[32];
+    afs_uint32 volType;
     char offLineMsg[256];
     char motd[256];
     long alldown, alldeleted;
@@ -1296,6 +1302,8 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
     OfflineMsg = offLineMsg;
     MOTD = motd;
 
+    volType = cm_VolumeType(volp, volID);
+
     if (statep->ID != 0 && (!volID || volID == statep->ID)) {
         /* create fid for volume root so that VNOVOL and VMOVED errors can be processed */
         cm_SetFid(&vfid, volp->cellp->cellID, statep->ID, 1, 1);
@@ -1354,6 +1362,15 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
                             rx_PutConnection(rxconnp);
                         } while (cm_Analyze(connp, cm_rootUserp, &req, &vfid, NULL, 0, NULL, NULL, NULL, NULL, code));
                         code = cm_MapRPCError(code, &req);
+
+                        if (code == 0 && volType == ROVOL)
+                        {
+
+                            lock_ObtainWrite(&volp->rw);
+                            volp->volumeSizeRO = volStat.BlocksInUse * 1024;
+                            _InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RO_SIZE_VALID);
+                            lock_ReleaseWrite(&volp->rw);
+                        }
                     }
 
                     lock_ObtainWrite(&vscp->rw);
index 8f3072e..8c43076 100644 (file)
@@ -53,6 +53,7 @@ typedef struct cm_volume {
     time_t cbIssuedRO;                  /* latest RO issue time; by cm_scacheLock */
     time_t creationDateRO;              /* latest volume creation date; 0 if unknown; by cm_scacheLock */
     time_t lastUpdateTime;              /* most recent volume location update cm_volumeLock */
+    afs_uint64 volumeSizeRO;            /* latest RO volume size */
 } cm_volume_t;
 
 #define CM_VOLUMEFLAG_RESET       1    /* reload this info on next use */
@@ -60,6 +61,7 @@ typedef struct cm_volume {
 #define CM_VOLUMEFLAG_UPDATING_VL  8
 #define CM_VOLUMEFLAG_DFS_VOLUME  16
 #define CM_VOLUMEFLAG_NOEXIST     32
+#define CM_VOLUMEFLAG_RO_SIZE_VALID 64
 
 #define CM_VOLUME_QFLAG_IN_HASH      1
 #define CM_VOLUME_QFLAG_IN_LRU_QUEUE 2
index 4207e10..fca4332 100644 (file)
@@ -5894,31 +5894,56 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
         if (cm_volumeInfoReadOnlyFlag && (volType == ROVOL || volType == BACKVOL))
             pResultCB->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
 
-        flags = CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS;
-        if (scp->volumeCreationDate == 0)
-            flags |= CM_SCACHESYNC_FORCECB;
-        code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ, flags);
-        if (code == 0)
+        code = -1;
+
+        if ( volType == ROVOL &&
+             (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID))
+        {
+            lock_ObtainRead(&volp->rw);
+            if (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID) {
+                volStat.BlocksInUse = volp->volumeSizeRO / 1024;
+                code = 0;
+            }
+            lock_ReleaseRead(&volp->rw);
+        }
+        
+        if (code == -1)
         {
-            sync_done = 1;
+            flags = CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS;
+            if (scp->volumeCreationDate == 0)
+                flags |= CM_SCACHESYNC_FORCECB;
+            code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ, flags);
+            if (code == 0)
+            {
+                sync_done = 1;
 
-            Name = volName;
-            OfflineMsg = offLineMsg;
-            MOTD = motd;
-            lock_ReleaseWrite(&scp->rw);
-            scp_locked = 0;
+                Name = volName;
+                OfflineMsg = offLineMsg;
+                MOTD = motd;
+                lock_ReleaseWrite(&scp->rw);
+                scp_locked = 0;
+
+                do {
+                    code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
+                    if (code) continue;
 
-            do {
-                code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
-                if (code) continue;
+                    rxconnp = cm_GetRxConn(connp);
+                    code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
+                                                 &volStat, &Name, &OfflineMsg, &MOTD);
+                    rx_PutConnection(rxconnp);
 
-                rxconnp = cm_GetRxConn(connp);
-                code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
-                                              &volStat, &Name, &OfflineMsg, &MOTD);
-                rx_PutConnection(rxconnp);
+                } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
+                code = cm_MapRPCError(code, &req);
+
+                if (code == 0 && volType == ROVOL)
+                {
 
-            } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
-            code = cm_MapRPCError(code, &req);
+                    lock_ObtainWrite(&volp->rw);
+                    volp->volumeSizeRO = volStat.BlocksInUse * 1024;
+                    _InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RO_SIZE_VALID);
+                    lock_ReleaseWrite(&volp->rw);
+                }
+            }
         }
 
         if ( scp->volumeCreationDate )
@@ -6098,29 +6123,54 @@ RDR_GetVolumeSizeInfo( IN cm_user_t     *userp,
 
         volType = cm_VolumeType(volp, scp->fid.volume);
 
-        code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
-                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-        if (code == 0)
+        code = -1;
+
+        if ( volType == ROVOL &&
+             (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID))
+        {
+            lock_ObtainRead(&volp->rw);
+            if (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID) {
+                volStat.BlocksInUse = volp->volumeSizeRO / 1024;
+                code = 0;
+            }
+            lock_ReleaseRead(&volp->rw);
+        }
+        
+        if (code == -1)
         {
-            sync_done = 1;
+            code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
+                              CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+            if (code == 0)
+            {
+                sync_done = 1;
 
-            Name = volName;
-            OfflineMsg = offLineMsg;
-            MOTD = motd;
-            lock_ReleaseWrite(&scp->rw);
-            scp_locked = 0;
+                Name = volName;
+                OfflineMsg = offLineMsg;
+                MOTD = motd;
+                lock_ReleaseWrite(&scp->rw);
+                scp_locked = 0;
 
-            do {
-                code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
-                if (code) continue;
+                do {
+                    code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
+                    if (code) continue;
 
-                rxconnp = cm_GetRxConn(connp);
-                code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
-                                              &volStat, &Name, &OfflineMsg, &MOTD);
-                rx_PutConnection(rxconnp);
+                    rxconnp = cm_GetRxConn(connp);
+                    code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
+                                                  &volStat, &Name, &OfflineMsg, &MOTD);
+                    rx_PutConnection(rxconnp);
 
-            } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
-            code = cm_MapRPCError(code, &req);
+                } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
+                code = cm_MapRPCError(code, &req);
+
+                if (code == 0 && volType == ROVOL)
+                {
+
+                    lock_ObtainWrite(&volp->rw);
+                    volp->volumeSizeRO = volStat.BlocksInUse * 1024;
+                    _InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RO_SIZE_VALID);
+                    lock_ReleaseWrite(&volp->rw);
+                }
+            }
         }
 
         if (code == 0) {