windows-volume-status-plugin-20070705
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 5 Jul 2007 20:21:19 +0000 (20:21 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 5 Jul 2007 20:21:19 +0000 (20:21 +0000)
This delta adds an interface to an optional volume status handler.
The handler (if provided) receives status updates when volumes
change state between online, offline, busy, and alldown.

src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_volstat.c [new file with mode: 0644]
src/WINNT/afsd/cm_volstat.h [new file with mode: 0644]
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h

index 6029def..b9ac3e4 100644 (file)
@@ -51,6 +51,7 @@ INCFILES =\
        $(INCFILEDIR)\cm_callback.h \
        $(INCFILEDIR)\cm_aclent.h \
        $(INCFILEDIR)\cm_volume.h \
+        $(INCFILEDIR)\cm_volstat.h \
        $(INCFILEDIR)\cm_dcache.h \
        $(INCFILEDIR)\cm_access.h \
        $(INCFILEDIR)\cm_vnodeops.h \
@@ -100,6 +101,7 @@ AFSDOBJS=\
        $(OUT)\cm_cell.obj \
        $(OUT)\cm_server.obj \
        $(OUT)\cm_volume.obj \
+        $(OUT)\cm_volstat.obj \
        $(OUT)\cm_config.obj \
        $(OUT)\cm_conn.obj \
        $(OUT)\cm_user.obj \
index 82cab84..a06adf6 100644 (file)
@@ -35,6 +35,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #include "cm_cell.h"
 #include "cm_scache.h"
 #include "cm_volume.h"
+#include "cm_volstat.h"
 #include "cm_dcache.h"
 #include "cm_access.h"
 #include "cm_utils.h"
index 20fc69d..6180a89 100644 (file)
@@ -1241,6 +1241,9 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         }
     }
 
+    /* Perform Volume Status Notification Initialization */
+    cm_VolStatus_Initialization();
+
 #ifdef JUMP
     MainThreadId = GetCurrentThreadId();
     jmpret = setjmp(notifier_jmp);
@@ -1360,6 +1363,9 @@ afsd_Main(DWORD argc, LPTSTR *argv)
        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
     }
 
+    /* Notify any volume status handlers that we have started */
+    cm_VolStatus_Service_Started();
+
     /* allow an exit to be called when started */
     hHookDll = LoadLibrary(AFSD_HOOK_DLL);
     if (hHookDll)
@@ -1402,6 +1408,9 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     else
        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
 
+    /* Notify any Volume Status Handlers that we are stopping */
+    cm_VolStatus_Service_Stopped();
+
     /* allow an exit to be called prior to stopping the service */
     hHookDll = LoadLibrary(AFSD_HOOK_DLL);
     if (hHookDll)
@@ -1469,6 +1478,9 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         PowerNotificationThreadExit();
 #endif
 
+    /* Cleanup any Volume Status Notification Handler */
+    cm_VolStatus_Finalize();
+
     /* allow an exit to be called after stopping the service */
     hHookDll = LoadLibrary(AFSD_HOOK_DLL);
     if (hHookDll)
index c193d5f..379d2a3 100644 (file)
@@ -296,6 +296,7 @@ int RXAFS_Lookup (struct rx_connection *,
 #define CM_ERROR_TOOFEWBUFS            (CM_ERROR_BASE+50)
 #define CM_ERROR_TOOMANYBUFS           (CM_ERROR_BASE+51)
 #define CM_ERROR_BAD_LEVEL             (CM_ERROR_BASE+52)
+#define CM_ERROR_NOT_A_DFSLINK          (CM_ERROR_BASE+53)
 
 /* Used by cm_FollowMountPoint and cm_GetVolumeByName */
 #define RWVOL  0
index e5f1bab..a64750e 100644 (file)
@@ -60,6 +60,7 @@ void cm_IpAddrDaemon(long parm)
            cm_ForceNewConnectionsAllServers();
             cm_CheckServers(CM_FLAG_CHECKFILESERVERS | CM_FLAG_CHECKUPSERVERS | CM_FLAG_CHECKDOWNSERVERS, NULL);
            smb_CheckVCs();
+            cm_VolStatus_Network_Addr_Change();
        }       
     }
 }
diff --git a/src/WINNT/afsd/cm_volstat.c b/src/WINNT/afsd/cm_volstat.c
new file mode 100644 (file)
index 0000000..9cb6cbf
--- /dev/null
@@ -0,0 +1,286 @@
+/* Copyright 2007 Secure Endpoints Inc.
+ *
+ * BSD 2-part License 
+ */
+
+/* This source file provides the declarations 
+ * which specify the AFS Cache Manager Volume Status Event
+ * Notification API
+ */
+
+#include <afs/param.h>
+#include <afs/stds.h>
+
+#include <windows.h>
+#include <winsock2.h>
+#include <nb30.h>
+#include <string.h>
+#include <malloc.h>
+#include "afsd.h"
+#include <WINNT/afsreg.h>
+
+HMODULE hVolStatus = NULL;
+dll_VolStatus_Funcs_t dll_funcs;
+cm_VolStatus_Funcs_t cm_funcs;
+
+/* This function is used to load any Volume Status Handlers 
+ * and their associated function pointers.  
+ */
+long 
+cm_VolStatus_Initialization(void)
+{
+    long (__fastcall * dll_VolStatus_Initialization)(dll_VolStatus_Funcs_t * dll_funcs, cm_VolStatus_Funcs_t *cm_funcs) = NULL;
+    long code = 0;
+    HKEY parmKey;
+    DWORD dummyLen;
+    char wd[MAX_PATH+1] = "";
+
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        dummyLen = sizeof(wd);
+        code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL,
+                                (BYTE *) &wd, &dummyLen);
+        RegCloseKey (parmKey);
+    }
+
+    if (code == ERROR_SUCCESS && wd[0])
+        hVolStatus = LoadLibrary(wd);
+    if (hVolStatus) {
+        (FARPROC) dll_VolStatus_Initialization = GetProcAddress(hVolStatus, "@VolStatus_Initialization@8");
+        if (dll_VolStatus_Initialization) {
+            cm_funcs.version = CM_VOLSTATUS_FUNCS_VERSION;
+            cm_funcs.cm_VolStatus_Path_To_ID = cm_VolStatus_Path_To_ID;
+            cm_funcs.cm_VolStatus_Path_To_DFSlink = cm_VolStatus_Path_To_DFSlink;
+
+            code = dll_VolStatus_Initialization(&dll_funcs, &cm_funcs);
+        } 
+
+        if (dll_VolStatus_Initialization == NULL || code != 0 || 
+            dll_funcs.version != DLL_VOLSTATUS_FUNCS_VERSION) {
+            FreeLibrary(hVolStatus);
+            hVolStatus = NULL;
+            code = -1;
+        }
+    }
+
+    return code;
+}
+
+/* This function is used to unload any Volume Status Handlers
+ * that were loaded during initialization.
+ */
+long 
+cm_VolStatus_Finalize(void)
+{
+    if (hVolStatus == NULL)
+        return 0;
+
+    FreeLibrary(hVolStatus);
+    hVolStatus = NULL;
+    return 0;
+}
+
+/* This function notifies the Volume Status Handlers that the
+ * AFS client service has started.  If the network is started
+ * at this point we call cm_VolStatus_Network_Started().
+ */
+long 
+cm_VolStatus_Service_Started(void)
+{
+    long code = 0;
+
+    if (hVolStatus == NULL)
+        return 0;
+   
+    code = dll_funcs.dll_VolStatus_Service_Started();
+    if (code == 0 && smb_IsNetworkStarted())
+        code = dll_funcs.dll_VolStatus_Network_Started(cm_NetbiosName, cm_NetbiosName);
+
+    return code;
+}
+
+/* This function notifies the Volume Status Handlers that the
+ * AFS client service is stopping.
+ */
+long 
+cm_VolStatus_Service_Stopped(void)
+{
+    long code = 0;
+
+    if (hVolStatus == NULL)
+        return 0;
+   
+    code = dll_funcs.dll_VolStatus_Service_Stopped();
+
+    return code;
+}
+
+
+/* This function notifies the Volume Status Handlers that the
+ * AFS client service is accepting network requests using the 
+ * specified netbios names.
+ */
+long
+#ifdef _WIN64
+cm_VolStatus_Network_Started(const char * netbios32, const char * netbios64)
+#else /* _WIN64 */
+cm_VolStatus_Network_Started(const char * netbios)
+#endif /* _WIN64 */
+{
+    long code = 0;
+
+    if (hVolStatus == NULL)
+        return 0;
+
+#ifdef _WIN64
+    code = dll_funcs.dll_VolStatus_Network_Started(netbios32, netbios64);
+#else
+    code = dll_funcs.dll_VolStatus_Network_Started(netbios, netbios);
+#endif
+
+    return code;
+}
+
+/* This function notifies the Volume Status Handlers that the
+ * AFS client service is no longer accepting network requests 
+ * using the specified netbios names 
+ */
+long
+#ifdef _WIN64
+cm_VolStatus_Network_Stopped(const char * netbios32, const char * netbios64)
+#else /* _WIN64 */
+cm_VolStatus_Network_Stopped(const char * netbios)
+#endif /* _WIN64 */
+{
+    long code = 0;
+
+    if (hVolStatus == NULL)
+        return 0;
+
+#ifdef _WIN64
+    code = dll_funcs.dll_VolStatus_Network_Stopped(netbios32, netbios64);
+#else
+    code = dll_funcs.dll_VolStatus_Network_Stopped(netbios, netbios);
+#endif
+
+    return code;
+}
+
+/* This function is called when the IP address list changes.
+ * Volume Status Handlers can use this notification as a hint 
+ * that it might be possible to determine volume IDs for paths 
+ * that previously were not accessible.  
+ */
+long 
+cm_VolStatus_Network_Addr_Change(void)
+{
+    long code = 0;
+
+    if (hVolStatus == NULL)
+        return 0;
+
+    code = dll_funcs.dll_VolStatus_Network_Addr_Change();
+
+    return code;
+}
+
+/* This function notifies the Volume Status Handlers that the 
+ * state of the specified cell.volume has changed.
+ */
+long 
+cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status)
+{
+    long code = 0;
+
+    if (hVolStatus == NULL)
+        return 0;
+
+    code = dll_funcs.dll_VolStatus_Change_Notification(cellID, volID, status);
+
+    return code;
+}
+
+
+long __fastcall
+cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID)
+{
+    afs_uint32  code;
+    cm_req_t    req;
+    cm_scache_t *scp;
+
+    if (cellID == NULL || volID == NULL)
+        return CM_ERROR_INVAL;
+
+    cm_InitReq(&req);
+
+
+    code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
+    if (code)
+        return code;
+
+    lock_ObtainMutex(&scp->mx);
+    code = cm_SyncOp(scp, NULL,cm_rootUserp, &req, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code) {
+        lock_ReleaseMutex(&scp->mx);
+        cm_ReleaseSCache(scp);
+        return code;
+    }
+        
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+    *cellID = scp->fid.cell;
+    *volID  = scp->fid.volume;
+
+    lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseSCache(scp);
+
+    return 0;
+}
+
+long __fastcall
+cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer)
+{
+    afs_uint32  code;
+    cm_req_t    req;
+    cm_scache_t *scp;
+    size_t      len;
+
+    if (pBufSize == NULL || (pBuffer == NULL && *pBufSize != 0))
+        return CM_ERROR_INVAL;
+
+    cm_InitReq(&req);
+
+    code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
+    if (code)
+        return code;
+
+    lock_ObtainMutex(&scp->mx);
+    code = cm_SyncOp(scp, NULL, cm_rootUserp, &req, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code) {
+        lock_ReleaseMutex(&scp->mx);
+        cm_ReleaseSCache(scp);
+        return code;
+    }
+        
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+    if (scp->fileType != CM_SCACHETYPE_DFSLINK)
+        return CM_ERROR_NOT_A_DFSLINK;
+
+    len = strlen(scp->mountPointStringp) + 1;
+    if (pBuffer == NULL)
+        *pBufSize = len;
+    else if (*pBufSize >= len) {
+        strcpy(pBuffer, scp->mountPointStringp);
+        *pBufSize = len;
+    } else 
+        code = CM_ERROR_TOOBIG;
+
+    lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseSCache(scp);
+
+    return 0;
+}
diff --git a/src/WINNT/afsd/cm_volstat.h b/src/WINNT/afsd/cm_volstat.h
new file mode 100644 (file)
index 0000000..834c089
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright 2007 Secure Endpoints Inc.
+ *
+ * BSD 2-part License 
+ */
+
+/* This header file provides the definitions and prototypes 
+ * which specify the AFS Cache Manager Volume Status Event
+ * Notification API
+ */
+
+
+extern long cm_VolStatus_Initialization(void);
+
+extern long cm_VolStatus_Finalize(void);
+
+extern long cm_VolStatus_Service_Started(void);
+
+extern long cm_VolStatus_Service_Stopping(void);
+
+#ifdef _WIN64
+extern long cm_VolStatus_Network_Started(const char * netbios32, const char * netbios64);
+
+extern long cm_VolStatus_Network_Stopped(const char * netbios32, const char * netbios64);
+#else /* _WIN64 */
+extern long cm_VolStatus_Network_Started(const char * netbios);
+
+extern long cm_VolStatus_Network_Stopped(const char * netbios);
+#endif /* _WIN64 */
+
+extern long cm_VolStatus_Network_Addr_Change(void);
+
+extern long cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status);
+
+extern long __fastcall cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID);
+
+extern long __fastcall cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer);
+
+#define DLL_VOLSTATUS_FUNCS_VERSION 1
+typedef struct dll_VolStatus_Funcs {
+    afs_uint32          version;
+    long (__fastcall * dll_VolStatus_Service_Started)(void);
+    long (__fastcall * dll_VolStatus_Service_Stopped)(void);
+    long (__fastcall * dll_VolStatus_Network_Started)(const char *netbios32, const char *netbios64);
+    long (__fastcall * dll_VolStatus_Network_Stopped)(const char *netbios32, const char *netbios64);
+    long (__fastcall * dll_VolStatus_Network_Addr_Change)(void);
+    long (__fastcall * dll_VolStatus_Change_Notification)(afs_uint32 cellID, afs_uint32 volID, enum volstatus status);
+} dll_VolStatus_Funcs_t;
+
+#define CM_VOLSTATUS_FUNCS_VERSION 1
+typedef struct cm_VolStatus_Funcs {
+    afs_uint32          version;
+    long (__fastcall * cm_VolStatus_Path_To_ID)(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID);
+    long (__fastcall * cm_VolStatus_Path_To_DFSlink)(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer);
+} cm_VolStatus_Funcs_t;
+
index 5016a16..a558445 100644 (file)
@@ -1468,4 +1468,6 @@ void cm_VolumeStatusNotification(cm_volume_t * volp, afs_uint32 volID, enum vols
 
     osi_Log4(afsd_logp, "VolumeStatusNotification: %-48s [%10u] (%s -> %s)",
              volstr, volID, volstatus_str(old), volstatus_str(new));
+
+    cm_VolStatus_Change_Notification(volp->cellp->cellID, volID, new);
 }       
index 7e707cd..fddacf1 100644 (file)
@@ -6442,7 +6442,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         offset = LargeIntegerAdd(offset,
                                  ConvertLongToLargeInteger(written));
-        count -= written;
+        count -= (unsigned short)written;
         total_written += written;
         written = 0;
     }
@@ -7969,6 +7969,11 @@ void smb_Listener(void *parmp)
            }
 
            if (lanaRemaining == 0) {
+                cm_VolStatus_Network_Stopped(cm_NetbiosName
+#ifdef _WIN64
+                                             ,cm_NetbiosName
+#endif
+                                              );
                smb_ListenerState = SMB_LISTENER_STOPPED;
                smb_LANadapter = -1;
                lana_list.length = 0;
@@ -8333,6 +8338,11 @@ int smb_NetbiosInit(void)
        lana_list.length = 0;
        smb_LANadapter = -1;
        smb_ListenerState = SMB_LISTENER_STOPPED;
+        cm_VolStatus_Network_Stopped(cm_NetbiosName
+#ifdef _WIN64
+                                      ,cm_NetbiosName
+#endif
+                                      );
     }
         
     /* we're done with the NCB now */
@@ -8351,6 +8361,11 @@ void smb_StartListeners()
        return;
     
     smb_ListenerState = SMB_LISTENER_STARTED;
+    cm_VolStatus_Network_Started(cm_NetbiosName
+#ifdef _WIN64
+                                  , cm_NetbiosName
+#endif
+                                  );
 
     for (i = 0; i < lana_list.length; i++) {
         if (lana_list.lana[i] == 255) 
@@ -8407,6 +8422,11 @@ void smb_StopListeners(void)
        return;
 
     smb_ListenerState = SMB_LISTENER_STOPPED;
+    cm_VolStatus_Network_Stopped(cm_NetbiosName
+#ifdef _WIN64
+                                  , cm_NetbiosName
+#endif
+                                  );
 
     ncbp = GetNCB();
 
@@ -9064,3 +9084,8 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
         lock_ReleaseRead(&smb_rctLock);
     return 0;
 }
+
+long smb_IsNetworkStarted(void)
+{
+    return (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0);
+}
index b355d95..721bca9 100644 (file)
@@ -730,6 +730,7 @@ extern void smb_ResetServerPriority(void);
 extern void smb_RestartListeners(void);
 extern void smb_StopListeners(void);
 extern void smb_StopListener(NCB *ncbp, int lana);
+extern long smb_IsNetworkStarted(void);
 
 #define SMB_LISTENER_UNINITIALIZED -1
 #define SMB_LISTENER_STOPPED 0