Skip to content

Commit

Permalink
vss: Get rid of one VSS client at a time.
Browse files Browse the repository at this point in the history
The VSS code is currently one big minefield with global variables
all over the place.

These changes make it a bit better at the costs of using some so
called thread specific data pointers e.g. using
pthread_set_specific() and pthread_get_specific().

The big change is that we setup two TSD keys which control the
Thread Specific Data. There is one key which holds the so called
UTF8 to UCS2 cache which caches the last conversion done as this
conversion is rather expensive and is done multiple times. The
second key is used for registering the callback for the VSS
pathconvert functions.

In the FILED code we now keep track of the VSS instance used
using a variable in the JCR instead of using a global VSS instance.

As each Job uses one thread we could now run multiple Jobs which
shouldn't clobber each others caches, have callbacks for VSS if
they use VSS and have their own instance of the VSS class.

By removing these limits we also had to fix the following problems:
- CoInitializeSecurity may only be called once.
- Wait for Snapshotset to complete

Fixes #253: Enable concurrent jobs on Windows platforms

Signed-off-by: Philipp Storz <philipp.storz@bareos.com>
  • Loading branch information
Marco van Wieringen committed Dec 24, 2015
1 parent 6c03073 commit 37a083f
Show file tree
Hide file tree
Showing 25 changed files with 556 additions and 378 deletions.
12 changes: 6 additions & 6 deletions src/filed/backup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1574,25 +1574,25 @@ static void close_vss_backup_session(JCR *jcr)
* STOP VSS ON WIN32
* Tell vss to close the backup session
*/
if (jcr->VSS) {
if (g_pVSSClient->CloseBackup()) {
if (jcr->pVSSClient) {
if (jcr->pVSSClient->CloseBackup()) {
/*
* Inform user about writer states
*/
for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
for (int i = 0; i < (int)jcr->pVSSClient->GetWriterCount(); i++) {
int msg_type = M_INFO;
if (g_pVSSClient->GetWriterState(i) < 1) {
if (jcr->pVSSClient->GetWriterState(i) < 1) {
msg_type = M_WARNING;
jcr->JobErrors++;
}
Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), jcr->pVSSClient->GetWriterInfo(i));
}
}

/*
* Generate Job global writer metadata
*/
WCHAR *metadata = g_pVSSClient->GetMetadata();
WCHAR *metadata = jcr->pVSSClient->GetMetadata();
if (metadata) {
FF_PKT *ff_pkt = jcr->ff;
ff_pkt->fname = (char *)"*all*"; /* for all plugins */
Expand Down
98 changes: 37 additions & 61 deletions src/filed/dir_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@

#if defined(WIN32_VSS)
#include "vss.h"

static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool enable_vss = false;
#endif

extern bool backup_only_mode;
Expand Down Expand Up @@ -525,7 +522,7 @@ void *handle_director_connection(BSOCK *dir)
/* Send termination status back to Dir */
dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
edit_uint64(jcr->ReadBytes, ed1),
edit_uint64(jcr->JobBytes, ed2), jcr->JobErrors, jcr->VSS,
edit_uint64(jcr->JobBytes, ed2), jcr->JobErrors, jcr->enable_vss,
jcr->crypto.pki_encrypt);
Dmsg1(110, "End FD msg: %s\n", dir->msg);
}
Expand Down Expand Up @@ -1172,7 +1169,7 @@ static bool fileset_cmd(JCR *jcr)
}

#if defined(WIN32_VSS)
enable_vss = (vss && (count_include_list_file_entries(jcr) > 0)) ? true : false;
jcr->enable_vss = (vss && (count_include_list_file_entries(jcr) > 0)) ? true : false;
#endif

retval = dir->fsend(OKinc);
Expand Down Expand Up @@ -1708,17 +1705,8 @@ static bool backup_cmd(JCR *jcr)
}

#if defined(WIN32_VSS)
/*
* Capture state here, if client is backed up by multiple directors
* and one enables vss and the other does not then enable_vss can change
* between here and where its evaluated after the job completes.
*/
jcr->VSS = g_pVSSClient && enable_vss;
if (jcr->VSS) {
/*
* Run only one at a time
*/
P(vss_mutex);
if (jcr->enable_vss) {
VSSInit(jcr);
}
#endif

Expand Down Expand Up @@ -1807,8 +1795,8 @@ static bool backup_cmd(JCR *jcr)
/*
* START VSS ON WIN32
*/
if (jcr->VSS) {
if (g_pVSSClient->InitializeForBackup(jcr)) {
if (jcr->pVSSClient) {
if (jcr->pVSSClient->InitializeForBackup(jcr)) {
int drive_count;
char szWinDriveLetters[27];
bool onefs_disabled;
Expand All @@ -1831,16 +1819,16 @@ static bool backup_cmd(JCR *jcr)

if (drive_count > 0) {
Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"),
g_pVSSClient->GetDriverName(), (drive_count) ? szWinDriveLetters : "None");
jcr->pVSSClient->GetDriverName(), (drive_count) ? szWinDriveLetters : "None");

if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters, onefs_disabled)) {
if (!jcr->pVSSClient->CreateSnapshots(szWinDriveLetters, onefs_disabled)) {
berrno be;
Jmsg(jcr, M_FATAL, 0, _("CreateSGenerate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
} else {
/*
* Inform about VMPs if we have them
*/
g_pVSSClient->ShowVolumeMountPointStats(jcr);
jcr->pVSSClient->ShowVolumeMountPointStats(jcr);

/*
* Tell user if snapshot creation of a specific drive failed
Expand All @@ -1854,9 +1842,9 @@ static bool backup_cmd(JCR *jcr)
/*
* Inform user about writer states
*/
for (int i = 0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
if (g_pVSSClient->GetWriterState(i) < 1) {
Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));
for (int i = 0; i < (int)jcr->pVSSClient->GetWriterCount(); i++) {
if (jcr->pVSSClient->GetWriterState(i) < 1) {
Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), jcr->pVSSClient->GetWriterInfo(i));
}
}
}
Expand Down Expand Up @@ -1932,10 +1920,8 @@ static bool backup_cmd(JCR *jcr)

cleanup:
#if defined(WIN32_VSS)
if (jcr->VSS) {
Win32ConvCleanupCache();
g_pVSSClient->DestroyWriterInfo();
V(vss_mutex);
if (jcr->pVSSClient) {
jcr->pVSSClient->DestroyWriterInfo();
}
#endif

Expand Down Expand Up @@ -2110,20 +2096,10 @@ static bool restore_cmd(JCR *jcr)
/**
* No need to enable VSS for restore if we do not have plugin data to restore
*/
enable_vss = jcr->got_metadata;
jcr->enable_vss = jcr->got_metadata;

Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
/*
* Capture state here, if client is backed up by multiple directors
* and one enables vss and the other does not then enable_vss can change
* between here and where its evaluated after the job completes.
*/
jcr->VSS = g_pVSSClient && enable_vss;
if (jcr->VSS) {
/*
* Run only one at a time
*/
P(vss_mutex);
if (jcr->enable_vss) {
VSSInit(jcr);
}
#endif

Expand All @@ -2149,14 +2125,6 @@ static bool restore_cmd(JCR *jcr)
if (!jcr->where_bregexp) {
Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
free_pool_memory(args);
#if defined(WIN32_VSS)
if (jcr->VSS) {
/*
* clear mutex
*/
V(vss_mutex);
}
#endif
return false;
}
} else {
Expand Down Expand Up @@ -2186,13 +2154,15 @@ static bool restore_cmd(JCR *jcr)
generate_plugin_event(jcr, bEventStartRestoreJob);

#if defined(WIN32_VSS)
/* START VSS ON WIN32 */
if (jcr->VSS) {
if (!g_pVSSClient->InitializeForRestore(jcr)) {
/*
* START VSS ON WIN32
*/
if (jcr->pVSSClient) {
if (!jcr->pVSSClient->InitializeForRestore(jcr)) {
berrno be;
Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
}
//free_and_null_pool_memory(jcr->job_metadata);

run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS",
(jcr->director && jcr->director->allowed_script_dirs) ?
jcr->director->allowed_script_dirs :
Expand Down Expand Up @@ -2223,28 +2193,27 @@ static bool restore_cmd(JCR *jcr)
/* STOP VSS ON WIN32 */
/* tell vss to close the restore session */
Dmsg0(100, "About to call CloseRestore\n");
if (jcr->VSS) {
if (jcr->pVSSClient) {
#if 0
generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
#endif
Dmsg0(100, "Really about to call CloseRestore\n");
if (g_pVSSClient->CloseRestore()) {
if (jcr->pVSSClient->CloseRestore()) {
Dmsg0(100, "CloseRestore success\n");
#if 0
/* inform user about writer states */
for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
for (int i=0; i<(int)jcr->pVSSClient->GetWriterCount(); i++) {
int msg_type = M_INFO;
if (g_pVSSClient->GetWriterState(i) < 1) {
if (jcr->pVSSClient->GetWriterState(i) < 1) {
//msg_type = M_WARNING;
//jcr->JobErrors++;
}
Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), jcr->pVSSClient->GetWriterInfo(i));
}
#endif
}
else
} else {
Dmsg1(100, "CloseRestore fail - %08x\n", errno);
V(vss_mutex);
}
}
#endif

Expand Down Expand Up @@ -2339,6 +2308,13 @@ static bool open_sd_read_session(JCR *jcr)
*/
static void filed_free_jcr(JCR *jcr)
{
#if defined(WIN32_VSS)
if (jcr->pVSSClient) {
delete jcr->pVSSClient;
jcr->pVSSClient = NULL;
}
#endif

if (jcr->store_bsock) {
jcr->store_bsock->close();
delete jcr->store_bsock;
Expand Down
8 changes: 4 additions & 4 deletions src/filed/fd_plugins.c
Original file line number Diff line number Diff line change
Expand Up @@ -2001,17 +2001,17 @@ static bRC bareosGetValue(bpContext *ctx, bVariable var, void *value)
break; /* a write only variable, ignore read request */
case bVarVssObject:
#ifdef HAVE_WIN32
if (g_pVSSClient) {
*(void **)value = g_pVSSClient->GetVssObject();
if (jcr->pVSSClient) {
*(void **)value = jcr->pVSSClient->GetVssObject();
Dmsg1(dbglvl, "fd-plugin: return bVarVssObject=%p\n", *(void **)value);
break;
}
#endif
return bRC_Error;
case bVarVssDllHandle:
#ifdef HAVE_WIN32
if (g_pVSSClient) {
*(void **)value = g_pVSSClient->GetVssDllHandle();
if (jcr->pVSSClient) {
*(void **)value = jcr->pVSSClient->GetVssDllHandle();
Dmsg1(dbglvl, "fd-plugin: return bVarVssDllHandle=%p\n", *(void **)value);
break;
}
Expand Down
4 changes: 4 additions & 0 deletions src/filed/filed.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@

#define FILE_DAEMON 1
#include "filed_conf.h"
#ifdef HAVE_WIN32
#include "vss.h"
#endif
#include "jcr.h"
#include "lib/breg.h"
#include "lib/htable.h"
#include "lib/runscript.h"
Expand Down
34 changes: 16 additions & 18 deletions src/filed/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ static int privs = 0;
#ifdef WIN32_VSS
#include "vss.h"
#define VSS " VSS"
extern VSSClient *g_pVSSClient;
#else
#define VSS ""
#endif
Expand Down Expand Up @@ -98,7 +97,7 @@ static void list_status_header(STATUS_PKT *sp)
if (!privs) {
privs = enable_backup_privileges(NULL, 1);
}
len = Mmsg(msg, "VSS %s, Priv 0x%x\n", g_pVSSClient ? "enabled" : "disabled", privs);
len = Mmsg(msg, "Priv 0x%x\n", privs);
sendit(msg, len, sp);
len = Mmsg(msg, "APIs=%sOPT,%sATP,%sLPV,%sCFA,%sCFW,\n",
p_OpenProcessToken ? "" : "!",
Expand Down Expand Up @@ -176,12 +175,6 @@ static void list_running_jobs_plain(STATUS_PKT *sp)
Dmsg0(1000, "Begin status jcr loop.\n");
len = Mmsg(msg, _("\nRunning Jobs:\n"));
sendit(msg, len, sp);
const char *vss = "";
#ifdef WIN32_VSS
if (g_pVSSClient && g_pVSSClient->IsInitialized()) {
vss = "VSS ";
}
#endif

foreach_jcr(njcr) {
bstrftime_nc(dt, sizeof(dt), njcr->start_time);
Expand All @@ -191,9 +184,16 @@ static void list_running_jobs_plain(STATUS_PKT *sp)
len = Mmsg(msg, _("JobId %d Job %s is running.\n"),
njcr->JobId, njcr->Job);
sendit(msg, len, sp);
#ifdef WIN32_VSS
len = Mmsg(msg, _(" %s%s %s Job started: %s\n"),
vss, level_to_str(njcr->getJobLevel()),
(njcr->pVSSClient && njcr->pVSSClient->IsInitialized()) ? "VSS " : "",
level_to_str(njcr->getJobLevel()),
job_type_to_str(njcr->getJobType()), dt);
#else
len = Mmsg(msg, _(" %s %s Job started: %s\n"),
level_to_str(njcr->getJobLevel()),
job_type_to_str(njcr->getJobType()), dt);
#endif
}
sendit(msg, len, sp);
if (njcr->JobId == 0) {
Expand Down Expand Up @@ -253,13 +253,6 @@ static void list_running_jobs_api(STATUS_PKT *sp)
/*
* List running jobs for Bat/Bweb (simple to parse)
*/
int vss = 0;
#ifdef WIN32_VSS
if (g_pVSSClient && g_pVSSClient->IsInitialized()) {
vss = 1;
}
#endif

foreach_jcr(njcr) {
bstrutime(dt, sizeof(dt), njcr->start_time);
if (njcr->JobId == 0) {
Expand All @@ -268,9 +261,14 @@ static void list_running_jobs_api(STATUS_PKT *sp)
len = Mmsg(msg, "JobId=%d\n Job=%s\n",
njcr->JobId, njcr->Job);
sendit(msg, len, sp);
#ifdef WIN32_VSS
len = Mmsg(msg," VSS=%d\n Level=%c\n JobType=%c\n JobStarted=%s\n",
vss, njcr->getJobLevel(),
njcr->getJobType(), dt);
(njcr->pVSSClient && njcr->pVSSClient->IsInitialized()) ? 1 : 0,
njcr->getJobLevel(), njcr->getJobType(), dt);
#else
len = Mmsg(msg," VSS=%d\n Level=%c\n JobType=%c\n JobStarted=%s\n",
0, njcr->getJobLevel(), njcr->getJobType(), dt);
#endif
}
sendit(msg, len, sp);
if (njcr->JobId == 0) {
Expand Down
1 change: 1 addition & 0 deletions src/findlib/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
*/

#include "bareos.h"
#include "jcr.h"
#include "find.h"

#if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL)
Expand Down
1 change: 1 addition & 0 deletions src/findlib/attribs.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*/

#include "bareos.h"
#include "jcr.h"
#include "find.h"
#include "ch.h"

Expand Down
1 change: 1 addition & 0 deletions src/findlib/create_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/

#include "bareos.h"
#include "jcr.h"
#include "find.h"

#ifndef S_IRWXUGO
Expand Down
1 change: 1 addition & 0 deletions src/findlib/find.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*/

#include "bareos.h"
#include "jcr.h"
#include "find.h"

static const int dbglvl = 450;
Expand Down
1 change: 0 additions & 1 deletion src/findlib/find.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#ifndef __FIND_H
#define __FIND_H

#include "jcr.h"
#include "fileopts.h"
#include "bfile.h"

Expand Down
Loading

0 comments on commit 37a083f

Please sign in to comment.