DEVEL15-windows-dirty-buffers-20090608
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 19 Jun 2009 04:12:34 +0000 (04:12 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 19 Jun 2009 04:12:34 +0000 (04:12 +0000)
LICENSE MIT

In the buf_IncrSync thread, if the volume is known to be unavailable
do not attempt to write the buffer.  Just skip it.

In buf_Sync(), if we are shutting down and a buffer is left dirty,
log a message to the Windows Event Log indicating that the dirty buffer
was lost.

(cherry picked from commit 2033fa9ec62089887f074381ac118a2c60e9c311)

src/WINNT/afsd/afsd_eventlog.c
src/WINNT/afsd/afsd_eventmessages.mc
src/WINNT/afsd/cm_buf.c

index 756392b..58027fb 100644 (file)
@@ -289,6 +289,19 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...)
        lpArgs[1] = lpStrings[1];
        lpArgs[2] = va_arg(listArgs,LPTSTR);
        break;
+    case MSG_DIRTY_BUFFER_AT_SHUTDOWN:
+       wNumArgs = 6;
+       lpArgs[0] = va_arg(listArgs, LPTSTR);
+        lpArgs[1] = va_arg(listArgs, LPTSTR);
+       StringCbPrintf(lpStrings[2],STRLEN,"%u",va_arg(listArgs,int));
+       StringCbPrintf(lpStrings[3],STRLEN,"%u",va_arg(listArgs,int));
+       StringCbPrintf(lpStrings[4],STRLEN,"%I64u",va_arg(listArgs,afs_int64));
+       StringCbPrintf(lpStrings[5],STRLEN,"%I64u",va_arg(listArgs,afs_int64));
+       lpArgs[2] = lpStrings[2];
+       lpArgs[3] = lpStrings[3];
+       lpArgs[4] = lpStrings[4];
+       lpArgs[5] = lpStrings[5];
+       break;
     }
     va_end(listArgs);
 
index 37c76a0..c2afae4 100644 (file)
@@ -374,4 +374,12 @@ Language=English
 MaxBufferSize for client is too small (Client=%1, Server=%2).
 .
 
+MessageId=
+Severity=Warning
+Facility=System
+SymbolicName=MSG_DIRTY_BUFFER_AT_SHUTDOWN
+Language=English
+A dirty buffer was not written to the file server (Cell=%1, Volume=%2, Vnode=%3, Unique=%4, Offset=%5, Length=%6).
+.
+
 ;#endif /* __AFSD_EVENTMESSAGES_H_ 1 */
index b4a9630..ad2ce2f 100644 (file)
@@ -234,15 +234,25 @@ buf_Sync(int quitOnShutdown)
 
         if (bp->flags & CM_BUF_DIRTY && !(bp->flags & CM_BUF_REDIR)) {
             /* start cleaning the buffer; don't touch log pages since
-            * the log code counts on knowing exactly who is writing
-            * a log page at any given instant.
-            */
+             * the log code counts on knowing exactly who is writing
+             * a log page at any given instant.
+             *
+             * only attempt to write the buffer if the volume might
+             * be online.
+             */
             afs_uint32 dirty;
+            cm_volume_t * volp;
 
-            cm_InitReq(&req);
-            req.flags |= CM_REQ_NORETRY;
-            buf_CleanAsyncLocked(bp, &req, &dirty);
-            wasDirty |= dirty;
+            volp = cm_GetVolumeByFID(&bp->fid);
+            switch (cm_GetVolumeStatus(volp, bp->fid.volume)) {
+            case vl_online:
+            case vl_unknown:
+                cm_InitReq(&req);
+                req.flags |= CM_REQ_NORETRY;
+                buf_CleanAsyncLocked(bp, &req, &dirty);
+                wasDirty |= dirty;
+            }
+            cm_PutVolume(volp);
         }
 
         /* the buffer may or may not have been dirty
@@ -268,6 +278,34 @@ buf_Sync(int quitOnShutdown)
             buf_ReleaseLocked(bp, TRUE);
             lock_ConvertWToR(&buf_globalLock);
         } else {
+            if (buf_ShutdownFlag) {
+                cm_cell_t *cellp;
+                cm_volume_t *volp;
+                char volstr[VL_MAXNAMELEN+12]="";
+                char *ext = "";
+
+                volp = cm_GetVolumeByFID(&bp->fid);
+                if (volp) {
+                    cellp = volp->cellp;
+                    if (bp->fid.volume == volp->vol[RWVOL].ID)
+                        ext = "";
+                    else if (bp->fid.volume == volp->vol[ROVOL].ID)
+                        ext = ".readonly";
+                    else if (bp->fid.volume == volp->vol[BACKVOL].ID)
+                        ext = ".backup";
+                    else
+                        ext = ".nomatch";
+                    snprintf(volstr, sizeof(volstr), "%s%s", volp->namep, ext);
+                } else {
+                    cellp = cm_FindCellByID(bp->fid.cell, CM_FLAG_NOPROBE);
+                    snprintf(volstr, sizeof(volstr), "%u", bp->fid.volume);
+                }
+
+                LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_DIRTY_BUFFER_AT_SHUTDOWN, 
+                         cellp->name, volstr, bp->fid.vnode, bp->fid.unique, 
+                         bp->offset.QuadPart+bp->dirty_offset, bp->dirty_length);
+            }
+
             /* advance the pointer so we don't loop forever */
             lock_ObtainRead(&buf_globalLock);
             bpp = &bp->dirtyp;