]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-volume-status-plugin-20070705
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 5 Jul 2007 20:22:15 +0000 (20:22 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 5 Jul 2007 20:22:15 +0000 (20:22 +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.

(cherry picked from commit 2b9525fe9e09ad90b08c9a60fa4b098df542c047)

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 a866bff433238f9c4ce939e1f367a04617f4cb84..126560ab83d49a559045ab6fbc1d091a43f08421 100644 (file)
@@ -52,6 +52,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 \
@@ -101,6 +102,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 8388238fc18aae814a5126b4af2ebe7a0b86ee4c..0e55f143613f4af3baafa59c7ce5707a8343c066 100644 (file)
@@ -44,6 +44,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 20fc69de4e908e16246b422ec1ecbb93a51b6740..6180a891ca66910f220e782b4144b923d0ffec3b 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 cef5ecfb901c2826748317b2ecdca4bae3dca0bb..9a863b64b1bae1bb11b2646fd35a723b7fe0a7c9 100644 (file)
@@ -300,6 +300,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 5486e44d36cb121c04263e812cb783716a6fa738..647a5eac751d1743c8dc1ccc27e2515c5621e6aa 100644 (file)
@@ -65,6 +65,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 1c4c651fcd1f21121c80c1184b8ea6662f6daa11..4982283620f5ba9549e59321f1f49bde310190e9 100644 (file)
@@ -1472,4 +1472,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 ce4c2a4b7417a29093addd1e7299ffc13592a8e0..e3061aff639138d6b86d069c98a2fbc3cadbdb3a 100644 (file)
@@ -6746,7 +6746,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;
     }
@@ -8373,6 +8373,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;
@@ -8802,6 +8807,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 */
@@ -8820,6 +8830,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) 
@@ -8876,6 +8891,11 @@ void smb_StopListeners(void)
        return;
 
     smb_ListenerState = SMB_LISTENER_STOPPED;
+    cm_VolStatus_Network_Stopped(cm_NetbiosName
+#ifdef _WIN64
+                                  , cm_NetbiosName
+#endif
+                                  );
 
     ncbp = GetNCB();
 
@@ -9595,3 +9615,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 1c56143dfd1ac808b979fb2985e1854ae6afdab2..5f7b135e822d141c8d9c39e1d35e1f532b4d03b7 100644 (file)
@@ -755,6 +755,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