From 1c22e49312cdeb877dbab0a7cb62fe5d984d094f Mon Sep 17 00:00:00 2001 From: Thorsten Engel Date: Wed, 19 Apr 2006 18:54:43 +0000 Subject: [PATCH] improve vss - writer states shown *after* backup (the old printing was not reliable) - take out VSS_TIMEOUT (empty define made problems) - improve errorhandling - allow multiple checkwriterstates - fix handle leak git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2944 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/filed/job.c | 49 ++++--- bacula/src/win32/compat/vss_generic.cpp | 168 ++++++++++++++---------- 2 files changed, 124 insertions(+), 93 deletions(-) diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 50a60ae353..ac389dc45d 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -1243,38 +1243,37 @@ static int backup_cmd(JCR *jcr) if (g_pVSSClient && enable_vss) { /* Run only one at a time */ P(vss_mutex); - if (g_pVSSClient->InitializeForBackup()) { - /* tell vss which drives to snapshot */ - char szWinDriveLetters[27]; - if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) { + if (g_pVSSClient->InitializeForBackup()) { + /* tell vss which drives to snapshot */ + char szWinDriveLetters[27]; + if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) { Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters); - if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) { - berrno be; - Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed. ERR=%s\n"), - be.strerror()); + if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) { + Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n")); + jcr->Errors++; } else { /* tell user if snapshot creation of a specific drive failed */ size_t i; for (i=0; iErrors++; } } /* inform user about writer states */ - for (i=0; iGetWriterCount(); i++) { - int msg_type = M_INFO; - if (g_pVSSClient->GetWriterState(i) < 0) { - msg_type = M_WARNING; - } - Jmsg(jcr, msg_type, 0, _("VSS Writer: %s\n"), g_pVSSClient->GetWriterInfo(i)); - } + for (i=0; iGetWriterCount(); i++) + if (g_pVSSClient->GetWriterState(i) < 1) { + Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i)); + jcr->Errors++; + } } - } else { + } else { Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n")); - } + } } else { - Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled.\n")); - } + berrno be; + Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.strerror()); + } } #endif @@ -1336,7 +1335,17 @@ cleanup: /* STOP VSS ON WIN 32 */ /* tell vss to close the backup session */ if (g_pVSSClient && enable_vss) { - g_pVSSClient->CloseBackup(); + if (g_pVSSClient->CloseBackup()) { + /* inform user about writer states */ + for (size_t i=0; iGetWriterCount(); i++) { + int msg_type = M_INFO; + if (g_pVSSClient->GetWriterState(i) < 1) { + msg_type = M_WARNING; + jcr->Errors++; + } + Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i)); + } + } V(vss_mutex); } #endif diff --git a/bacula/src/win32/compat/vss_generic.cpp b/bacula/src/win32/compat/vss_generic.cpp index e4e4526c17..c3ce639f7d 100644 --- a/bacula/src/win32/compat/vss_generic.cpp +++ b/bacula/src/win32/compat/vss_generic.cpp @@ -67,9 +67,7 @@ using namespace std; #ifdef B_VSS_XP #pragma message("compile VSS for Windows XP") #define VSSClientGeneric VSSClientXP - // wait is not available under XP... - #define VSS_TIMEOUT - + #include "vss/inc/WinXP/vss.h" #include "vss/inc/WinXP/vswriter.h" #include "vss/inc/WinXP/vsbackup.h" @@ -87,10 +85,7 @@ using namespace std; #ifdef B_VSS_W2K3 #pragma message("compile VSS for Windows 2003") #define VSSClientGeneric VSSClient2003 - // wait x ms for a VSS asynchronous operation (-1 = infinite) - // unfortunately, it doesn't work, so do not set timeout - #define VSS_TIMEOUT - + #include "vss/inc/Win2003/vss.h" #include "vss/inc/Win2003/vswriter.h" #include "vss/inc/Win2003/vsbackup.h" @@ -180,7 +175,7 @@ inline wstring GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus) CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_BACKUP_COMPLETE); CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_PRE_RESTORE); CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_POST_RESTORE); - + default: return wstring(L"Error or Undefined"); } @@ -242,7 +237,7 @@ BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL bDuringRestore) NULL // Reserved parameter ); - if (FAILED(hr)) { + if (FAILED(hr)) { errno = b_errno_win32; return FALSE; } @@ -257,7 +252,7 @@ BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL bDuringRestore) // Create the internal backup components object hr = p_CreateVssBackupComponents((IVssBackupComponents**) &m_pVssObject); - if (FAILED(hr)) { + if (FAILED(hr)) { errno = b_errno_win32; return FALSE; } @@ -272,6 +267,33 @@ BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL bDuringRestore) } #endif + if (!bDuringRestore) { + // 1. InitializeForBackup + hr = ((IVssBackupComponents*) m_pVssObject)->InitializeForBackup(); + if (FAILED(hr)) { + errno = b_errno_win32; + return FALSE; + } + + // 2. SetBackupState + hr = ((IVssBackupComponents*) m_pVssObject)->SetBackupState(true, true, VSS_BT_FULL, false); + if (FAILED(hr)) { + errno = b_errno_win32; + return FALSE; + } + + CComPtr pAsync1; + // 3. GatherWriterMetaData + hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1); + if (FAILED(hr)) { + errno = b_errno_win32; + return FALSE; + } + // Waits for the async operation to finish and checks the result + WaitAndCheckForAsyncOperation(pAsync1); + } + + // We are during restore now? m_bDuringRestore = bDuringRestore; @@ -287,7 +309,7 @@ void VSSClientGeneric::WaitAndCheckForAsyncOperation(IVssAsync* pAsync) // Wait until the async operation finishes // unfortunately we can't use a timeout here yet. // the interface would allow it on W2k3, but it is not implemented yet.... - HRESULT hr = pAsync->Wait(VSS_TIMEOUT); + HRESULT hr = pAsync->Wait(); // Check the result of the asynchronous operation HRESULT hrReturned = S_OK; @@ -326,42 +348,11 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters) IVssBackupComponents *pVss = (IVssBackupComponents*)m_pVssObject; - // 1. InitializeForBackup - HRESULT hr = pVss->InitializeForBackup(); - if (FAILED(hr)) { - errno = b_errno_win32; - return FALSE; - } - - // 2. SetBackupState - hr = pVss->SetBackupState(true, true, VSS_BT_FULL, false); - if (FAILED(hr)) { - errno = b_errno_win32; - return FALSE; - } - - CComPtr pAsync1; - CComPtr pAsync2; - CComPtr pAsync3; - VSS_ID pid; - - // 3. GatherWriterMetaData - hr = pVss->GatherWriterMetadata(&pAsync3); - if (FAILED(hr)) { - errno = b_errno_win32; - return FALSE; - } - - // Waits for the async operation to finish and checks the result - WaitAndCheckForAsyncOperation(pAsync3); - - CheckWriterStatus(); - - // 4. startSnapshotSet + /* startSnapshotSet */ pVss->StartSnapshotSet(&m_uidCurrentSnapshotSet); - // 4. AddToSnapshotSet + /* AddToSnapshotSet */ WCHAR szDrive[3]; szDrive[1] = ':'; @@ -369,6 +360,10 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters) wstring volume; + CComPtr pAsync1; + CComPtr pAsync2; + VSS_ID pid; + for (size_t i=0; i < strlen (szDriveLetters); i++) { szDrive[0] = szDriveLetters[i]; volume = GetUniqueVolumeNameForPath(szDrive); @@ -376,22 +371,33 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters) if (SUCCEEDED(pVss->AddToSnapshotSet((LPWSTR)volume.c_str(), GUID_NULL, &pid))) wcsncpy (m_wszUniqueVolumeName[szDriveLetters[i]-'A'], (LPWSTR) volume.c_str(), MAX_PATH); else + { szDriveLetters[i] = tolower (szDriveLetters[i]); + } } - // 5. PrepareForBackup - pVss->PrepareForBackup(&pAsync1); + /* PrepareForBackup */ + if (FAILED(pVss->PrepareForBackup(&pAsync1))) { + return FALSE; + } // Waits for the async operation to finish and checks the result WaitAndCheckForAsyncOperation(pAsync1); - // 6. DoSnapShotSet - pVss->DoSnapshotSet(&pAsync2); + /* get latest info about writer status */ + if (!CheckWriterStatus()) { + return FALSE; + } + + /* DoSnapShotSet */ + if (FAILED(pVss->DoSnapshotSet(&pAsync2))) { + return FALSE; + } // Waits for the async operation to finish and checks the result WaitAndCheckForAsyncOperation(pAsync2); - /* query snapshot info */ + /* query snapshot info */ QuerySnapshotSet(m_uidCurrentSnapshotSet); m_bBackupIsInitialized = true; @@ -419,6 +425,9 @@ BOOL VSSClientGeneric::CloseBackup() pVss->AbortBackup(); } + /* get latest info about writer status */ + CheckWriterStatus(); + if (m_uidCurrentSnapshotSet != GUID_NULL) { VSS_ID idNonDeletedSnapshotID = GUID_NULL; LONG lSnapshots; @@ -506,6 +515,9 @@ void VSSClientGeneric::QuerySnapshotSet(GUID snapshotSetID) // Check the status for all selected writers BOOL VSSClientGeneric::CheckWriterStatus() { + /* + http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vss/base/ivssbackupcomponents_startsnapshotset.asp + */ IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject; vector* pVWriterStates = (vector*) m_pVectorWriterStates; vector* pVWriterInfo = (vector*) m_pVectorWriterInfo; @@ -549,38 +561,48 @@ BOOL VSSClientGeneric::CheckWriterStatus() &eWriterStatus, &hrWriterFailure); if (FAILED(hr)) { - continue; + /* unknown */ + pVWriterStates->push_back(0); } - - // If the writer is in non-stable state, break - switch(eWriterStatus) { - case VSS_WS_FAILED_AT_IDENTIFY: - case VSS_WS_FAILED_AT_PREPARE_BACKUP: - case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT: - case VSS_WS_FAILED_AT_FREEZE: - case VSS_WS_FAILED_AT_THAW: - case VSS_WS_FAILED_AT_POST_SNAPSHOT: - case VSS_WS_FAILED_AT_BACKUP_COMPLETE: - case VSS_WS_FAILED_AT_PRE_RESTORE: - case VSS_WS_FAILED_AT_POST_RESTORE: -#ifdef B_VSS_W2K3 - case VSS_WS_FAILED_AT_BACKUPSHUTDOWN: -#endif - /* failed */ - pVWriterStates->push_back(-1); - break; - - default: - /* okay */ - pVWriterStates->push_back(1); + else { + switch(eWriterStatus) { + case VSS_WS_FAILED_AT_IDENTIFY: + case VSS_WS_FAILED_AT_PREPARE_BACKUP: + case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT: + case VSS_WS_FAILED_AT_FREEZE: + case VSS_WS_FAILED_AT_THAW: + case VSS_WS_FAILED_AT_POST_SNAPSHOT: + case VSS_WS_FAILED_AT_BACKUP_COMPLETE: + case VSS_WS_FAILED_AT_PRE_RESTORE: + case VSS_WS_FAILED_AT_POST_RESTORE: + #ifdef B_VSS_W2K3 + case VSS_WS_FAILED_AT_BACKUPSHUTDOWN: + #endif + /* failed */ + pVWriterStates->push_back(-1); + break; + + default: + /* ok */ + pVWriterStates->push_back(1); + } } - + /* store text info */ stringstream osf; osf << "\"" << CW2A(bstrWriterName) << "\", State: " << eWriterStatus << " (" << CW2A(GetStringFromWriterStatus(eWriterStatus).c_str()) << ")"; pVWriterInfo->push_back(osf.str()); + SysFreeString (bstrWriterName); } + + hr = pVss->FreeWriterStatus(); + + if (FAILED(hr)) { + errno = b_errno_win32; + return FALSE; + } + errno = 0; return TRUE; } -- 2.39.5