|
From: <gi...@ba...> - 2013-01-29 21:33:44
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Bacula Community source".
The branch, Branch-5.2 has been updated
via 445b4b625979d97c6c17733a57e3ece51828f6ba (commit)
via f59efd22c90e574033e282fefcfe7b824ee5d08c (commit)
via e40e6216f09113c886420382f58fb98d7b259c98 (commit)
via 1e438dbb6613d2f909ab9ea4238333fddccf660a (commit)
via e4f737b549a1a58384f10bc088a226b29e00270d (commit)
via cdec640313a22e94c7f2fc919bfa9ae0e1627fec (commit)
from f65e6d6be911fec7a4fdd2741ad9ac9030d6c5e5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 445b4b625979d97c6c17733a57e3ece51828f6ba
Author: Kern Sibbald <ke...@si...>
Date: Tue Jan 29 22:32:43 2013 +0100
Fix typo in all-tape-tests
commit f59efd22c90e574033e282fefcfe7b824ee5d08c
Author: Kern Sibbald <ke...@si...>
Date: Tue Jan 29 22:32:22 2013 +0100
Remove unused method
commit e40e6216f09113c886420382f58fb98d7b259c98
Author: Kern Sibbald <ke...@si...>
Date: Tue Jan 29 20:32:02 2013 +0100
Require Qt version 4.8.4
commit 1e438dbb6613d2f909ab9ea4238333fddccf660a
Author: Kern Sibbald <ke...@si...>
Date: Tue Jan 29 20:24:54 2013 +0100
Tweak version+date
commit e4f737b549a1a58384f10bc088a226b29e00270d
Author: Kern Sibbald <ke...@si...>
Date: Tue Jan 29 20:24:39 2013 +0100
Fix bug #1955 that OK to run? does not retry on bad response
commit cdec640313a22e94c7f2fc919bfa9ae0e1627fec
Author: Kern Sibbald <ke...@si...>
Date: Tue Jan 29 20:23:39 2013 +0100
Backport new lock calls + debug for SD
-----------------------------------------------------------------------
Summary of changes:
diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h
index 6a7a69c..58661cb 100644
--- a/bacula/src/baconfig.h
+++ b/bacula/src/baconfig.h
@@ -72,8 +72,16 @@
Emsg1(M_ERROR, 0, _("Failed ASSERT: %s\n"), #x); \
Pmsg1(000, _("Failed ASSERT: %s\n"), #x); \
jcr[0] = 0; }
+
+#define ASSERT2(x,y) if (!(x)) { \
+ assert_msg = y; \
+ Emsg1(M_ERROR, 0, _("Failed ASSERT: %s\n"), #x); \
+ Pmsg1(000, _("Failed ASSERT: %s\n"), #x); \
+ char *jcr = NULL; \
+ jcr[0] = 0; }
#else
#define ASSERT(x)
+#define ASSERT2(x, y)
#endif
/* Allow printing of NULL pointers */
@@ -639,4 +647,15 @@ int getdomainname(char *name, int len);
/** Determine endianes */
static inline bool bigendian() { return htonl(1) == 1L; }
+#ifndef __GNUC__
+#define __PRETTY_FUNCTION__ __func__
+#endif
+#ifdef ENTER_LEAVE
+#define Enter(lvl) Dmsg1(lvl, "Enter: %s\n", __PRETTY_FUNCTION__)
+#define Leave(lvl) Dmsg1(lvl, "Leave: %s\n", __PRETTY_FUNCTION__)
+#else
+#define Enter(lvl)
+#define Leave(lvl)
+#endif
+
#endif /* _BACONFIG_H */
diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c
index f66bdd5..a9941ad 100644
--- a/bacula/src/dird/ua_run.c
+++ b/bacula/src/dird/ua_run.c
@@ -197,6 +197,11 @@ start_job:
}
return JobId;
}
+ if (strncasecmp(ua->cmd, _("no"), strlen(ua->cmd)) == 0) {
+ goto bail_out;
+ }
+ ua->send_msg(_("\nBad response: %s. You must answer yes, mod, or no.\n\n"), ua->cmd);
+ goto try_again;
bail_out:
ua->send_msg(_("Job not run.\n"));
diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c
index 53f72c9..3ae4d37 100644
--- a/bacula/src/lib/message.c
+++ b/bacula/src/lib/message.c
@@ -50,6 +50,7 @@ sql_escape_func p_sql_escape = NULL;
* daemons include this file.
*/
const char *working_directory = NULL; /* working directory path stored here */
+const char *assert_msg = (char *)NULL; /* ASSERT2 error message */
int verbose = 0; /* increase User messages */
int debug_level = 0; /* debug level */
bool dbg_timestamp = false; /* print timestamp in debug output */
diff --git a/bacula/src/lib/message.h b/bacula/src/lib/message.h
index 20cad23..fd6141e 100644
--- a/bacula/src/lib/message.h
+++ b/bacula/src/lib/message.h
@@ -159,6 +159,7 @@ extern DLL_IMP_EXP bool dbg_timestamp; /* print timestamp in d
extern DLL_IMP_EXP bool prt_kaboom; /* Print kaboom output */
extern DLL_IMP_EXP int verbose;
extern DLL_IMP_EXP char my_name[];
+extern DLL_IMP_EXP const char *assert_msg; /* Assert error message */
extern DLL_IMP_EXP const char * working_directory;
extern DLL_IMP_EXP utime_t daemon_start_time;
diff --git a/bacula/src/qt-console/main.cpp b/bacula/src/qt-console/main.cpp
index 5d5a1bf..5214978 100644
--- a/bacula/src/qt-console/main.cpp
+++ b/bacula/src/qt-console/main.cpp
@@ -38,11 +38,11 @@
#include <QTranslator>
/*
- * We need Qt version 4.8.1 or later to be able to comple correctly
+ * We need Qt version 4.8.4 or later to be able to comple correctly
*/
-#if QT_VERSION < 0x040801
+#if QT_VERSION < 0x040804
#error "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
-#error "You need Qt version 4.8.1 or later to build Bat"
+#error "You need Qt version 4.8.4 or later to build Bat"
#error "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
#endif
diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c
index 97936b9..c8db295 100644
--- a/bacula/src/stored/acquire.c
+++ b/bacula/src/stored/acquire.c
@@ -1,7 +1,7 @@
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2002-2012 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-2013 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
@@ -35,6 +35,8 @@
#include "bacula.h" /* pull in global headers */
#include "stored.h" /* pull in Storage Deamon headers */
+static int const rdbglvl = 100;
+
/* Forward referenced functions */
static void attach_dcr_to_dev(DCR *dcr);
static void detach_dcr_from_dev(DCR *dcr);
@@ -51,7 +53,7 @@ static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
*/
bool acquire_device_for_read(DCR *dcr)
{
- DEVICE *dev = dcr->dev;
+ DEVICE *dev;
JCR *jcr = dcr->jcr;
bool ok = false;
bool tape_previously_mounted;
@@ -61,9 +63,11 @@ bool acquire_device_for_read(DCR *dcr)
int vol_label_status;
int retry = 0;
- P(dev->read_acquire_mutex);
- Dmsg2(950, "dcr=%p dev=%p\n", dcr, dcr->dev);
- Dmsg2(950, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
+ Enter(rdbglvl);
+ dev = dcr->dev;
+ dev->Lock_read_acquire();
+ Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
+ Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
dev->dblock(BST_DOING_ACQUIRE);
if (dev->num_writers > 0) {
@@ -91,12 +95,7 @@ bool acquire_device_for_read(DCR *dcr)
}
set_dcr_from_vol(dcr, vol);
- if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
- Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
- goto get_out;
- }
-
- Dmsg2(100, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
+ Dmsg2(rdbglvl, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
/*
* If the MediaType requested for this volume is not the
@@ -110,7 +109,7 @@ bool acquire_device_for_read(DCR *dcr)
* them such as the block pointer (size may change), but we do
* not release the dcr.
*/
- Dmsg2(50, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
+ Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
RCTX rctx;
DIRSTORE *store;
@@ -119,12 +118,10 @@ bool acquire_device_for_read(DCR *dcr)
Jmsg3(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
" device=%s\n"),
dcr->media_type, dev->device->media_type, dev->print_name());
- Dmsg3(50, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
+ Dmsg3(rdbglvl, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
" device=%s\n",
dcr->media_type, dev->device->media_type, dev->print_name());
- generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
-
dev->dunblock(DEV_UNLOCKED);
lock_reservations();
@@ -156,8 +153,8 @@ bool acquire_device_for_read(DCR *dcr)
* Switching devices, so acquire lock on new device,
* then release the old one.
*/
- P(dcr->dev->read_acquire_mutex);
- V(dev->read_acquire_mutex);
+ dcr->dev->Lock_read_acquire(); /* lock new one */
+ dev->Unlock_read_acquire(); /* release old one */
dev = dcr->dev; /* get new device pointer */
dev->dblock(BST_DOING_ACQUIRE);
@@ -165,10 +162,6 @@ bool acquire_device_for_read(DCR *dcr)
Jmsg(jcr, M_INFO, 0, _("Media Type change. New read device %s chosen.\n"),
dev->print_name());
Dmsg1(50, "Media Type change. New read device %s chosen.\n", dev->print_name());
- if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
- Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
- goto get_out;
- }
bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
dcr->setVolCatName(vol->VolumeName);
bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
@@ -180,17 +173,17 @@ bool acquire_device_for_read(DCR *dcr)
/* error */
Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
vol->VolumeName);
- Dmsg1(50, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
+ Dmsg1(rdbglvl, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
goto get_out;
}
}
- Dmsg2(400, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
+ Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
dev->clear_unload();
if (dev->vol && dev->vol->is_swapping()) {
dev->vol->set_slot(vol->Slot);
- Dmsg3(100, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
+ Dmsg3(rdbglvl, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
dev->vol->vol_name, dev->print_name());
}
@@ -201,9 +194,9 @@ bool acquire_device_for_read(DCR *dcr)
// tape_initially_mounted = tape_previously_mounted;
/* Volume info is always needed because of VolParts */
- Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
+ Dmsg1(rdbglvl, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
- Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n",
+ Dmsg2(rdbglvl, "dir_get_vol_info failed for vol=%s: %s\n",
dcr->VolumeName, jcr->errmsg);
Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
}
@@ -232,7 +225,7 @@ bool acquire_device_for_read(DCR *dcr)
* reading. If it is a file, it opens it.
* If it is a tape, it checks the volume name
*/
- Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
+ Dmsg1(rdbglvl, "open vol=%s\n", dcr->VolumeName);
if (!dev->open(dcr, OPEN_READ_ONLY)) {
if (!dev->poll) {
Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
@@ -240,19 +233,19 @@ bool acquire_device_for_read(DCR *dcr)
}
goto default_path;
}
- Dmsg1(50, "opened dev %s OK\n", dev->print_name());
+ Dmsg1(rdbglvl, "opened dev %s OK\n", dev->print_name());
/* Read Volume Label */
- Dmsg0(50, "calling read-vol-label\n");
+ Dmsg0(rdbglvl, "calling read-vol-label\n");
vol_label_status = read_dev_volume_label(dcr);
switch (vol_label_status) {
case VOL_OK:
- Dmsg0(50, "Got correct volume.\n");
+ Dmsg0(rdbglvl, "Got correct volume.\n");
ok = true;
dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
break; /* got it */
case VOL_IO_ERROR:
- Dmsg0(50, "IO Error\n");
+ Dmsg0(rdbglvl, "IO Error\n");
/*
* Send error message generated by read_dev_volume_label()
* only we really had a tape mounted. This supresses superfluous
@@ -263,7 +256,7 @@ bool acquire_device_for_read(DCR *dcr)
}
goto default_path;
case VOL_NAME_ERROR:
- Dmsg3(50, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName,
+ Dmsg3(rdbglvl, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName,
dcr->VolumeName, dev->print_name());
if (dev->is_volume_to_unload()) {
goto default_path;
@@ -279,7 +272,7 @@ bool acquire_device_for_read(DCR *dcr)
default:
Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
default_path:
- Dmsg0(50, "default path\n");
+ Dmsg0(rdbglvl, "default path\n");
tape_previously_mounted = true;
/*
@@ -293,7 +286,7 @@ default_path:
/* Call autochanger only once unless ask_sysop called */
if (try_autochanger) {
int stat;
- Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
+ Dmsg2(rdbglvl, "calling autoload Vol=%s Slot=%d\n",
dcr->VolumeName, dcr->VolCatInfo.Slot);
stat = autoload_device(dcr, 0, NULL);
if (stat > 0) {
@@ -303,7 +296,7 @@ default_path:
}
/* Mount a specific volume and no other */
- Dmsg0(200, "calling dir_ask_sysop\n");
+ Dmsg0(rdbglvl, "calling dir_ask_sysop\n");
if (!dir_ask_sysop_to_mount_volume(dcr, ST_READ)) {
goto get_out; /* error return */
}
@@ -337,12 +330,8 @@ default_path:
dcr->VolumeName, dev->print_name());
get_out:
- dev->dlock();
+ dev->Lock();
dcr->clear_reserved();
- /* If failed and not writing plugin close device */
- if (!ok && dev->num_writers == 0 && dev->num_reserved() == 0) {
- generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
- }
/*
* Normally we are blocked, but in at least one error case above
* we are not blocked because we unsuccessfully tried changing
@@ -351,11 +340,12 @@ get_out:
if (dev->is_blocked()) {
dev->dunblock(DEV_LOCKED);
} else {
- dev->dunlock(); /* dunblock() unlock the device too */
+ dev->Unlock(); /* dunblock() unlock the device too */
}
- Dmsg2(950, "dcr=%p dev=%p\n", dcr, dcr->dev);
- Dmsg2(950, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
- V(dev->read_acquire_mutex);
+ Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
+ Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
+ dev->Unlock_read_acquire();
+ Leave(rdbglvl);
return ok;
}
@@ -375,10 +365,11 @@ DCR *acquire_device_for_append(DCR *dcr)
bool ok = false;
bool have_vol = false;
+ Enter(200);
init_device_wait_timers(dcr);
- P(dev->acquire_mutex); /* only one job at a time */
- dev->dlock();
+ dev->Lock_acquire(); /* only one job at a time */
+ dev->Lock();
Dmsg1(100, "acquire_append device is %s\n", dev->is_tape()?"tape":
(dev->is_dvd()?"DVD":"disk"));
@@ -413,9 +404,9 @@ DCR *acquire_device_for_append(DCR *dcr)
}
if (!have_vol) {
- dev->r_dlock(true);
+ dev->rLock(true);
block_device(dev, BST_DOING_ACQUIRE);
- dev->dunlock();
+ dev->Unlock();
Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
if (!dcr->mount_next_write_volume()) {
if (!job_canceled(jcr)) {
@@ -425,20 +416,15 @@ DCR *acquire_device_for_append(DCR *dcr)
Dmsg1(200, "Could not ready device %s for append.\n",
dev->print_name());
}
- dev->dlock();
+ dev->Lock();
unblock_device(dev);
goto get_out;
}
Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
- dev->dlock();
+ dev->Lock();
unblock_device(dev);
}
- if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
- Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
- goto get_out;
- }
-
dev->num_writers++; /* we are now a writer */
if (jcr->NumWriteVolumes == 0) {
jcr->NumWriteVolumes = 1;
@@ -453,8 +439,9 @@ DCR *acquire_device_for_append(DCR *dcr)
get_out:
/* Don't plugin close here, we might have multiple writers */
dcr->clear_reserved();
- dev->dunlock();
- V(dev->acquire_mutex);
+ dev->Unlock();
+ dev->Unlock_acquire();
+ Leave(200);
return ok ? dcr : NULL;
}
@@ -475,7 +462,7 @@ bool release_device(DCR *dcr)
char tbuf[100];
int was_blocked = BST_NOT_BLOCKED;
- dev->dlock();
+ dev->Lock();
if (!dev->is_blocked()) {
block_device(dev, BST_RELEASING);
} else {
@@ -490,7 +477,6 @@ bool release_device(DCR *dcr)
if (dev->can_read()) {
VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
- generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
dev->clear_read(); /* clear read bit */
Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
dev->is_labeled(), vol->VolCatName);
@@ -539,14 +525,12 @@ bool release_device(DCR *dcr)
* there are no writers. It was probably reserved.
*/
volume_unused(dcr);
- generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
}
Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
dev->print_name());
/* If no writers, close if file or !CAP_ALWAYS_OPEN */
if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
- generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
dvd_remove_empty_part(dcr); /* get rid of any empty spool part */
dev->close();
free_volume(dev);
@@ -593,7 +577,7 @@ bool release_device(DCR *dcr)
} else {
/* Otherwise, reset the prior block status and unlock */
dev->set_blocked(was_blocked);
- dev->dunlock();
+ dev->Unlock();
}
if (dcr->keep_dcr) {
@@ -601,7 +585,7 @@ bool release_device(DCR *dcr)
} else {
free_dcr(dcr);
}
- Dmsg2(100, "===== Device %s released by JobId=%u\n", dev->print_name(),
+ Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
(uint32_t)jcr->JobId);
return ok;
}
@@ -645,6 +629,12 @@ DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev)
Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat));
Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
}
+ if ((errstat = pthread_mutex_init(&dcr->r_mutex, NULL)) != 0) {
+ berrno be;
+ dev->dev_errno = errstat;
+ Mmsg1(dev->errmsg, _("Unable to init r_mutex: ERR=%s\n"), be.bstrerror(errstat));
+ Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
+ }
}
dcr->jcr = jcr; /* point back to jcr */
/* Set device information, possibly change device */
@@ -667,7 +657,7 @@ DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev)
dcr->max_job_spool_size = dev->device->max_job_spool_size;
}
dcr->device = dev->device;
- dcr->dev = dev;
+ dcr->set_dev(dev);
attach_dcr_to_dev(dcr);
}
return dcr;
@@ -713,11 +703,12 @@ static void attach_dcr_to_dev(DCR *dcr)
if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
/* ***FIXME*** return error if dev not initiated */
if (!dcr->attached_to_dev && dev->initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
- dev->dlock();
+ dev->Lock();
+ Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
+ dcr, dev->attached_dcrs->size(), dev->print_name());
dev->attached_dcrs->append(dcr); /* attach dcr to device */
- dev->dunlock();
+ dev->Unlock();
dcr->attached_to_dev = true;
- Dmsg1(500, "JobId=%u attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
}
V(dcr->m_mutex);
}
@@ -733,10 +724,15 @@ static void locked_detach_dcr_from_dev(DCR *dcr)
/* Detach this dcr only if attached */
if (dcr->attached_to_dev && dev) {
dcr->unreserve_device();
- dev->dlock();
- dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
+ dev->Lock();
+ Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId,
+ dcr, dev->attached_dcrs->size(), dev->print_name());
+ dcr->attached_to_dev = false;
+ if (dev->attached_dcrs->size()) {
+ dev->attached_dcrs->remove(dcr); /* detach dcr from device */
+ }
// remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
- dev->dunlock();
+ dev->Unlock();
}
dcr->attached_to_dev = false;
}
@@ -776,6 +772,7 @@ void free_dcr(DCR *dcr)
}
V(dcr->m_mutex);
pthread_mutex_destroy(&dcr->m_mutex);
+ pthread_mutex_destroy(&dcr->r_mutex);
free(dcr);
}
diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c
index b512950..8db3259 100644
--- a/bacula/src/stored/bcopy.c
+++ b/bacula/src/stored/bcopy.c
@@ -197,13 +197,13 @@ int main (int argc, char *argv[])
}
Dmsg0(100, "About to acquire device for writing\n");
/* For we must now acquire the device for writing */
- out_dev->r_dlock();
+ out_dev->rLock(false);
if (!out_dev->open(out_jcr->dcr, OPEN_READ_WRITE)) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
- out_dev->dunlock();
+ out_dev->Unlock();
exit(1);
}
- out_dev->dunlock();
+ out_dev->Unlock();
if (!acquire_device_for_append(out_jcr->dcr)) {
free_jcr(in_jcr);
exit(1);
diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c
index b80c4a0..e731320 100644
--- a/bacula/src/stored/block.c
+++ b/bacula/src/stored/block.c
@@ -365,7 +365,7 @@ bool DCR::write_block_to_device()
if (!dcr->is_dev_locked()) { /* device already locked? */
/* note, do not change this to dcr->r_dlock */
- dev->r_dlock(); /* no, lock it */
+ dev->rLock(); /* no, lock it */
}
/*
@@ -409,7 +409,7 @@ bool DCR::write_block_to_device()
bail_out:
if (!dcr->is_dev_locked()) { /* did we lock dev above? */
/* note, do not change this to dcr->dunlock */
- dev->dunlock(); /* unlock it now */
+ dev->Unlock(); /* unlock it now */
}
return stat;
}
@@ -957,9 +957,9 @@ bool DCR::read_block_from_device(bool check_block_numbers)
bool ok;
Dmsg0(250, "Enter read_block_from_device\n");
- dev->r_dlock();
+ dev->rLock();
ok = read_block_from_dev(check_block_numbers);
- dev->dunlock();
+ dev->Unlock();
Dmsg0(250, "Leave read_block_from_device\n");
return ok;
}
diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c
index 9678872..a3f751c 100644
--- a/bacula/src/stored/btape.c
+++ b/bacula/src/stored/btape.c
@@ -467,7 +467,7 @@ static bool open_the_device()
bool ok = true;
block = new_block(dev);
- dev->r_dlock();
+ dev->rLock();
Dmsg1(200, "Opening device %s\n", dcr->VolumeName);
if (!dev->open(dcr, OPEN_READ_WRITE)) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
@@ -478,7 +478,7 @@ static bool open_the_device()
dev->set_append(); /* put volume in append mode */
bail_out:
- dev->dunlock();
+ dev->Unlock();
free_block(block);
return ok;
}
@@ -2699,7 +2699,7 @@ static int flush_block(DEV_BLOCK *block, int dump)
DEV_BLOCK *tblock;
uint32_t this_file, this_block_num;
- dev->r_dlock();
+ dev->rLock();
if (!this_block) {
this_block = new_block(dev);
}
@@ -2755,12 +2755,12 @@ static int flush_block(DEV_BLOCK *block, int dump)
if (!fixup_device_block_write_error(jcr->dcr)) {
Pmsg1(000, _("Cannot fixup device error. %s\n"), dev->bstrerror());
ok = false;
- dev->dunlock();
+ dev->Unlock();
return 0;
}
BlockNumber = 0; /* start counting for second tape */
}
- dev->dunlock();
+ dev->Unlock();
return 1; /* end of tape reached */
}
@@ -2779,7 +2779,7 @@ static int flush_block(DEV_BLOCK *block, int dump)
last_file = this_file;
last_block_num = this_block_num;
- dev->dunlock();
+ dev->Unlock();
return 1;
}
diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c
index 7c6d57b..3d4e44b 100644
--- a/bacula/src/stored/dev.c
+++ b/bacula/src/stored/dev.c
@@ -32,7 +32,7 @@
* Kern Sibbald, MM
*
* NOTE!!!! None of these routines are reentrant. You must
- * use dev->r_dlock() and dev->unlock() at a higher level,
+ * use dev->rLock() and dev->Unlock() at a higher level,
* or use the xxx_device() equivalents. By moving the
* thread synchronization to a higher level, we permit
* the higher level routines to "seize" the device and
@@ -264,7 +264,7 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init)
dev->errmsg = get_pool_memory(PM_EMSG);
*dev->errmsg = 0;
- if ((errstat = pthread_mutex_init(&dev->m_mutex, NULL)) != 0) {
+ if ((errstat = dev->init_mutex()) != 0) {
berrno be;
dev->dev_errno = errstat;
Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat));
@@ -285,25 +285,25 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init)
if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) {
berrno be;
dev->dev_errno = errstat;
- Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init spool mutex: ERR=%s\n"), be.bstrerror(errstat));
Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
}
- if ((errstat = pthread_mutex_init(&dev->acquire_mutex, NULL)) != 0) {
+ if ((errstat = dev->init_acquire_mutex()) != 0) {
berrno be;
dev->dev_errno = errstat;
- Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init acquire mutex: ERR=%s\n"), be.bstrerror(errstat));
Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
}
- /* Ensure that we respect this order in P/V operations */
- bthread_mutex_set_priority(&dev->m_mutex, PRIO_SD_DEV_ACCESS);
- bthread_mutex_set_priority(&dev->spool_mutex, PRIO_SD_DEV_SPOOL);
- bthread_mutex_set_priority(&dev->acquire_mutex, PRIO_SD_DEV_ACQUIRE);
- if ((errstat = pthread_mutex_init(&dev->read_acquire_mutex, NULL)) != 0) {
+ if ((errstat = dev->init_read_acquire_mutex()) != 0) {
berrno be;
dev->dev_errno = errstat;
- Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init read acquire mutex: ERR=%s\n"), be.bstrerror(errstat));
Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
}
+
+ dev->set_mutex_priorities();
+
+
#ifdef xxx
if ((errstat = rwl_init(&dev->lock)) != 0) {
berrno be;
diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h
index 29d2bfd..96837b7 100644
--- a/bacula/src/stored/dev.h
+++ b/bacula/src/stored/dev.h
@@ -455,16 +455,32 @@ public:
* Locking and blocking calls
*/
#ifdef SD_DEBUG_LOCK
- void _r_dlock(const char *, int, bool locked=false); /* in lock.c */
- void _r_dunlock(const char *, int); /* in lock.c */
- void _dlock(const char *, int); /* in lock.c */
- void _dunlock(const char *, int); /* in lock.c */
+ void dbg_rLock(const char *, int, bool locked=false); /* in lock.c */
+ void dbg_rUnlock(const char *, int); /* in lock.c */
+ void dbg_Lock(const char *, int); /* in lock.c */
+ void dbg_Unlock(const char *, int); /* in lock.c */
+ void dbg_Lock_acquire(const char *, int); /* in lock.c */
+ void dbg_Unlock_acquire(const char *, int); /* in lock.c */
+ void dbg_Lock_read_acquire(const char *, int); /* in lock.c */
+ void dbg_Unlock_read_acquire(const char *, int); /* in lock.c */
#else
- void r_dlock(bool locked=false); /* in lock.c */
- void r_dunlock() { dunlock(); }
- void dlock() { P(m_mutex); }
- void dunlock() { V(m_mutex); }
+ void rLock(bool locked=false); /* in lock.c */
+ void rUnlock(); /* in lock.c */
+ void Lock(); /* in lock.c */
+ void Unlock(); /* in lock.c */
+ void Lock_acquire(); /* in lock.c */
+ void Unlock_acquire(); /* in lock.c */
+ void Lock_read_acquire(); /* in lock.c */
+ void Unlock_read_acquire(); /* in lock.c */
+ void Lock_VolCatInfo(); /* in lock.c */
+ void Unlock_VolCatInfo(); /* in lock.c */
#endif
+ int init_mutex(); /* in lock.c */
+ int init_acquire_mutex(); /* in lock.c */
+ int init_read_acquire_mutex(); /* in lock.c */
+ int init_volcat_mutex(); /* in lock.c */
+ void set_mutex_priorities(); /* in lock.c */
+ int next_vol_timedwait(const struct timespec *timeout); /* in lock.c */
void dblock(int why); /* in lock.c */
void dunblock(bool locked=false); /* in lock.c */
bool is_device_unmounted(); /* in lock.c */
@@ -504,6 +520,7 @@ inline const char *DEVICE::print_name() const { return prt_name; }
class DCR {
private:
bool m_dev_locked; /* set if dev already locked */
+ int m_dev_lock; /* non-zero if rLock already called */
bool m_reserved; /* set if reserved device */
bool m_found_in_use; /* set if a volume found in use */
@@ -511,6 +528,7 @@ public:
dlink dev_link; /* link to attach to dev */
JCR *jcr; /* pointer to JCR */
bthread_mutex_t m_mutex; /* access control */
+ pthread_mutex_t r_mutex; /* rLock pre-mutex */
DEVICE * volatile dev; /* pointer to device */
DEVRES *device; /* pointer to device resource */
DEV_BLOCK *block; /* pointer to block */
@@ -549,6 +567,8 @@ public:
/* Methods */
void set_dev(DEVICE *ndev) { dev = ndev; };
+ void inc_dev_lock() { m_dev_lock++; };
+ void dec_dev_lock() { m_dev_lock--; };
bool found_in_use() const { return m_found_in_use; };
void set_found_in_use() { m_found_in_use = true; };
void clear_found_in_use() { m_found_in_use = false; };
@@ -564,12 +584,12 @@ public:
/* Methods in lock.c */
void dblock(int why) { dev->dblock(why); }
-#ifdef SD_DEBUG_LOCK
- void _dlock(const char *, int); /* in lock.c */
- void _dunlock(const char *, int); /* in lock.c */
+#ifdef SD_DEBUG_LOCK
+ void dbg_mLock(const char *, int, bool locked); /* in lock.c */
+ void dbg_mUnlock(const char *, int); /* in lock.c */
#else
- void dlock() { dev->dlock(); m_dev_locked = true; }
- void dunlock() { m_dev_locked = false; dev->dunlock(); }
+ void mLock(bool locked);
+ void mUnlock();
#endif
/* Methods in record.c */
diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c
index f06b5cd..1f4084d 100644
--- a/bacula/src/stored/device.c
+++ b/bacula/src/stored/device.c
@@ -108,7 +108,7 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
block_device(dev, BST_DOING_ACQUIRE);
/* Continue unlocked, but leave BLOCKED */
- dev->dunlock();
+ dev->Unlock();
bstrncpy(PrevVolName, dev->getVolCatName(), sizeof(PrevVolName));
bstrncpy(dev->VolHdr.PrevVolumeName, PrevVolName, sizeof(dev->VolHdr.PrevVolumeName));
@@ -127,11 +127,11 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
if (!dcr->mount_next_write_volume()) {
free_block(label_blk);
dcr->block = block;
- dev->dlock();
+ dev->Lock();
goto bail_out;
}
Dmsg2(050, "must_unload=%d dev=%s\n", dev->must_unload(), dev->print_name());
- dev->dlock(); /* lock again */
+ dev->Lock(); /* lock again */
dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
@@ -279,7 +279,7 @@ bool first_open_device(DCR *dcr)
return false;
}
- dev->r_dlock();
+ dev->rLock();
/* Defer opening files */
if (!dev->is_tape()) {
@@ -302,7 +302,7 @@ bool first_open_device(DCR *dcr)
Dmsg1(129, "open dev %s OK\n", dev->print_name());
bail_out:
- dev->dunlock();
+ dev->Unlock();
return ok;
}
diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c
index 6a02f9d..a463802 100644
--- a/bacula/src/stored/dircmd.c
+++ b/bacula/src/stored/dircmd.c
@@ -416,7 +416,7 @@ static bool do_label(JCR *jcr, int relabel)
dcr = find_device(jcr, dev_name, drive);
if (dcr) {
dev = dcr->dev;
- dev->dlock(); /* Use P to avoid indefinite block */
+ dev->Lock(); /* Use P to avoid indefinite block */
if (!dev->is_open() && !dev->is_busy()) {
Dmsg1(400, "Can %slabel. Device is not open\n", relabel?"re":"");
label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
@@ -431,7 +431,7 @@ static bool do_label(JCR *jcr, int relabel)
Dmsg0(400, "Can relabel. device not used\n");
label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
}
- dev->dunlock();
+ dev->Unlock();
free_dcr(dcr);
} else {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), dev_name.c_str());
@@ -684,7 +684,7 @@ static bool mount_cmd(JCR *jcr)
dcr = find_device(jcr, devname, drive);
if (dcr) {
dev = dcr->dev;
- dev->dlock(); /* Use P to avoid indefinite block */
+ dev->Lock(); /* Use P to avoid indefinite block */
Dmsg2(100, "mount cmd blocked=%d must_unload=%d\n", dev->blocked(),
dev->must_unload());
switch (dev->blocked()) { /* device blocked? */
@@ -806,7 +806,7 @@ static bool mount_cmd(JCR *jcr)
dir->fsend(_("3905 Unknown wait state %d\n"), dev->blocked());
break;
}
- dev->dunlock();
+ dev->Unlock();
free_dcr(dcr);
} else {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
@@ -834,7 +834,7 @@ static bool unmount_cmd(JCR *jcr)
dcr = find_device(jcr, devname, drive);
if (dcr) {
dev = dcr->dev;
- dev->dlock(); /* Use P to avoid indefinite block */
+ dev->Lock(); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
if (!dev->is_busy()) {
unload_autochanger(dcr, -1);
@@ -898,7 +898,7 @@ static bool unmount_cmd(JCR *jcr)
dev->print_name());
}
}
- dev->dunlock();
+ dev->Unlock();
free_dcr(dcr);
} else {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
@@ -971,7 +971,7 @@ static bool release_cmd(JCR *jcr)
dcr = find_device(jcr, devname, drive);
if (dcr) {
dev = dcr->dev;
- dev->dlock(); /* Use P to avoid indefinite block */
+ dev->Lock(); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
if (!dev->is_busy()) {
unload_autochanger(dcr, -1);
@@ -1009,7 +1009,7 @@ static bool release_cmd(JCR *jcr)
dir->fsend(_("3022 Device \"%s\" released.\n"),
dev->print_name());
}
- dev->dunlock();
+ dev->Unlock();
free_dcr(dcr);
} else {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
@@ -1119,7 +1119,7 @@ static bool changer_cmd(JCR *jcr)
dcr = find_device(jcr, devname, -1);
if (dcr) {
dev = dcr->dev;
- dev->dlock(); /* Use P to avoid indefinite block */
+ dev->Lock(); /* Use P to avoid indefinite block */
if (!dev->device->changer_res) {
dir->fsend(_("3998 Device \"%s\" is not an autochanger.\n"),
dev->print_name());
@@ -1131,7 +1131,7 @@ static bool changer_cmd(JCR *jcr)
} else { /* device not being used */
autochanger_cmd(dcr, dir, cmd);
}
- dev->dunlock();
+ dev->Unlock();
free_dcr(dcr);
} else {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
@@ -1161,7 +1161,7 @@ static bool readlabel_cmd(JCR *jcr)
dcr = find_device(jcr, devname, drive);
if (dcr) {
dev = dcr->dev;
- dev->dlock(); /* Use P to avoid indefinite block */
+ dev->Lock(); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
read_volume_label(jcr, dcr, dev, Slot);
dev->close();
@@ -1173,7 +1173,7 @@ static bool readlabel_cmd(JCR *jcr)
} else { /* device not being used */
read_volume_label(jcr, dcr, dev, Slot);
}
- dev->dunlock();
+ dev->Unlock();
free_dcr(dcr);
} else {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
diff --git a/bacula/src/stored/lock.c b/bacula/src/stored/lock.c
index d20c1bf..73d1a66 100644
--- a/bacula/src/stored/lock.c
+++ b/bacula/src/stored/lock.c
@@ -1,7 +1,7 @@
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
@@ -28,7 +28,7 @@
/*
* Collection of Bacula Storage daemon locking software
*
- * Kern Sibbald, 2000-2007. June 2007
+ * Kern Sibbald, June 2007
*
*/
@@ -51,20 +51,20 @@ const int dbglvl = 500;
* is "marked" in use. When setting and removing the
block, the device is locked, but after dblock is
called the device is unlocked.
- * 2. dlock() simple mutex that locks the device structure. A dlock
+ * 2. Lock() simple mutex that locks the device structure. A Lock
* can be acquired while a device is blocked if it is not
* locked.
- * 3. r_dlock(locked) "recursive" dlock, when means that a dlock (mutex)
+ * 3. rLock(locked) "recursive" Lock, when means that a Lock (mutex)
* will be acquired on the device if it is not blocked
* by some other thread. If the device was blocked by
* the current thread, it will acquire the lock.
* If some other thread has set a block on the device,
* this call will wait until the device is unblocked.
* Can be called with locked true, which means the
- * dlock is already set
+ * Lock is already set
*
* A lock is normally set when modifying the device structure.
- * A r_lock is normally acquired when you want to block the device
+ * A rLock is normally acquired when you want to block the device
* i.e. it will wait until the device is not blocked.
* A block is normally set during long operations like writing to
* the device.
@@ -73,7 +73,7 @@ const int dbglvl = 500;
* A lock cannot be violated. No other thread can touch the
* device while a lock is set.
* When a block is set, every thread accept the thread that set
- * the block will block if r_dlock is called.
+ * the block will block if rLock is called.
* A device can be blocked for multiple reasons, labeling, writing,
* acquiring (opening) the device, waiting for the operator, unmounted,
* ...
@@ -86,29 +86,29 @@ const int dbglvl = 500;
*
* Functions:
*
- * DEVICE::dlock() does P(m_mutex) (in dev.h)
- * DEVICE::dunlock() does V(m_mutex)
+ * DEVICE::Lock() does P(m_mutex) (in dev.h)
+ * DEVICE::Unlock() does V(m_mutex)
*
- * DEVICE::r_dlock(locked) allows locking the device when this thread
+ * DEVICE::rLock(locked) allows locking the device when this thread
* already has the device blocked.
* if (!locked)
- * dlock()
+ * Lock()
* if blocked and not same thread that locked
* pthread_cond_wait
* leaves device locked
*
- * DEVICE::r_dunlock() unlocks but does not unblock
- * same as dunlock();
+ * DEVICE::rUnlock() unlocks but does not unblock
+ * same as Unlock();
*
* DEVICE::dblock(why) does
- * r_dlock(); (recursive device lock)
+ * rLock(); (recursive device lock)
* block_device(this, why)
- * r_dunlock()
+ * rUnlock()
*
* DEVICE::dunblock does
- * dlock()
+ * Lock()
* unblock_device()
- * dunlock()
+ * Unlock()
*
* block_device() does (must be locked and not blocked at entry)
* set blocked status
@@ -126,10 +126,10 @@ const int dbglvl = 500;
* save status
* set new blocked status
* set new pid
- * unlock()
+ * Unlock()
*
* give_back_device_lock() does (must be blocked but not locked)
- * dlock()
+ * Lock()
* reset blocked status
* save previous blocked
* reset pid
@@ -138,40 +138,68 @@ const int dbglvl = 500;
*
*/
-
void DEVICE::dblock(int why)
{
- r_dlock(); /* need recursive lock to block */
+ rLock(false); /* need recursive lock to block */
block_device(this, why);
- r_dunlock();
+ rUnlock();
}
void DEVICE::dunblock(bool locked)
{
if (!locked) {
- dlock();
+ Lock();
}
unblock_device(this);
- dunlock();
+ Unlock();
}
#ifdef SD_DEBUG_LOCK
-void DCR::_dlock(const char *file, int line)
+
+/*
+ * Debug DCR locks N.B.
+ *
+ */
+void DCR::dbg_mLock(const char *file, int line, bool locked)
{
- dev->_dlock(file, line);
- m_dev_locked = true;
+ real_P(r_mutex);
+ if (is_dev_locked()) {
+ real_V(r_mutex);
+ return;
+ }
+ Dmsg3(sd_dbglvl, "mLock %d from %s:%d\n", locked, file, line);
+ dev->dbg_rLock(file,line,locked);
+ inc_dev_lock();
+ real_V(r_mutex);
+ return;
}
-void DCR::_dunlock(const char *file, int line)
-{
- m_dev_locked = false;
- dev->_dunlock(file, line);
+void DCR::dbg_mUnlock(const char *file, int line)
+{
+ Dmsg2(sd_dbglvl, "mUnlock from %s:%d\n", file, line);
+ real_P(r_mutex);
+ if (!is_dev_locked()) {
+ real_P(r_mutex);
+ ASSERT2(0, "Call on dcr mUnlock when not locked");
+ return;
+ }
+ dec_dev_lock();
+ /* When the count goes to zero, unlock it */
+ if (!is_dev_locked()) {
+ dev->dbg_rUnlock(file,line);
+ }
+ real_V(r_mutex);
+ return;
}
-void DEVICE::_dlock(const char *file, int line)
+/*
+ * Debug DEVICE locks N.B.
+ *
+ */
+void DEVICE::dbg_Lock(const char *file, int line)
{
- Dmsg3(sd_dbglvl, "dlock from %s:%d precnt=%d\n", file, line, m_count);
+ Dmsg3(sd_dbglvl, "Lock from %s:%d precnt=%d\n", file, line, m_count);
/* Note, this *really* should be protected by a mutex, but
* since it is only debug code we don't worry too much.
*/
@@ -180,25 +208,161 @@ void DEVICE::_dlock(const char *file, int line)
get_jobid_from_tid(m_pid),
file, line, m_count);
}
- P(m_mutex);
+ bthread_mutex_lock_p(&m_mutex, file, line);
m_pid = pthread_self();
m_count++;
}
-void DEVICE::_dunlock(const char *file, int line)
+void DEVICE::dbg_Unlock(const char *file, int line)
{
m_count--;
- Dmsg3(sd_dbglvl+1, "dunlock from %s:%d postcnt=%d\n", file, line, m_count);
- V(m_mutex);
+ Dmsg3(sd_dbglvl, "Unlock from %s:%d postcnt=%d\n", file, line, m_count);
+ bthread_mutex_unlock_p(&m_mutex, file, line);
+}
+
+void DEVICE::dbg_rUnlock(const char *file, int line)
+{
+ Dmsg2(sd_dbglvl, "rUnlock from %s:%d\n", file, line);
+ dbg_Unlock(file, line);
+}
+
+void DEVICE::dbg_Lock_acquire(const char *file, int line)
+{
+ Dmsg2(sd_dbglvl, "Lock_acquire from %s:%d\n", file, line);
+ bthread_mutex_lock_p(&acquire_mutex, file, line);
+}
+
+void DEVICE::dbg_Unlock_acquire(const char *file, int line)
+{
+ Dmsg2(sd_dbglvl, "Unlock_acquire from %s:%d\n", file, line);
+ bthread_mutex_unlock_p(&acquire_mutex, file, line);
}
-void DEVICE::_r_dunlock(const char *file, int line)
+void DEVICE::dbg_Lock_read_acquire(const char *file, int line)
{
- this->_dunlock(file, line);
+ Dmsg2(sd_dbglvl, "Lock_read_acquire from %s:%d\n", file, line);
+ bthread_mutex_lock_p(&read_acquire_mutex, file, line);
+}
+
+void DEVICE::dbg_Unlock_read_acquire(const char *file, int line)
+{
+ Dmsg2(sd_dbglvl, "Unlock_read_acquire from %s:%d\n", file, line);
+ bthread_mutex_unlock_p(&read_acquire_mutex, file, line);
+}
+
+
+#else
+
+/*
+ * DCR locks N.B.
+ *
+ */
+/* Multiple rLock implementation */
+void DCR::mLock(bool locked)
+{
+ P(r_mutex);
+ if (is_dev_locked()) {
+ V(r_mutex);
+ return;
+ }
+ dev->rLock(locked);
+ inc_dev_lock();
+ V(r_mutex);
+ return;
+}
+
+/* Multiple rUnlock implementation */
+void DCR::mUnlock()
+{
+ P(r_mutex);
+ if (!is_dev_locked()) {
+ V(r_mutex);
+ ASSERT2(0, "Call on dcr mUnlock when not locked");
+ return;
+ }
+ dec_dev_lock();
+ /* When the count goes to zero, unlock it */
+ if (!is_dev_locked()) {
+ dev->rUnlock();
+ }
+ V(r_mutex);
+ return;
+}
+
+/*
+ * DEVICE locks N.B.
+ *
+ */
+
+void DEVICE::rUnlock()
+{
+ Unlock();
+}
+
+void DEVICE::Lock()
+{
+ P(m_mutex);
+}
+
+void DEVICE::Unlock()
+{
+ V(m_mutex);
+}
+
+void DEVICE::Lock_acquire()
+{
+ P(acquire_mutex);
+}
+
+void DEVICE::Unlock_acquire()
+{
+ V(acquire_mutex);
+}
+
+void DEVICE::Lock_read_acquire()
+{
+ P(read_acquire_mutex);
+}
+
+void DEVICE::Unlock_read_acquire()
+{
+ V(read_acquire_mutex);
}
#endif
+/* Main device access control */
+int DEVICE::init_mutex()
+{
+ return pthread_mutex_init(&m_mutex, NULL);
+}
+
+/* Write device acquire mutex */
+int DEVICE::init_acquire_mutex()
+{
+ return pthread_mutex_init(&acquire_mutex, NULL);
+}
+
+/* Read device acquire mutex */
+int DEVICE::init_read_acquire_mutex()
+{
+ return pthread_mutex_init(&read_acquire_mutex, NULL);
+}
+
+/* Set order in which device locks must be acquired */
+void DEVICE::set_mutex_priorities()
+{
+ /* Ensure that we respect this order in P/V operations */
+ bthread_mutex_set_priority(&m_mutex, PRIO_SD_DEV_ACCESS);
+ bthread_mutex_set_priority(&spool_mutex, PRIO_SD_DEV_SPOOL);
+ bthread_mutex_set_priority(&acquire_mutex, PRIO_SD_DEV_ACQUIRE);
+}
+
+int DEVICE::next_vol_timedwait(const struct timespec *timeout)
+{
+ return pthread_cond_timedwait(&wait_next_vol, &m_mutex, timeout);
+}
+
/*
* This is a recursive lock that checks if the device is blocked.
@@ -208,44 +372,50 @@ void DEVICE::_r_dunlock(const char *file, int line)
* and preparing the label.
*/
#ifdef SD_DEBUG_LOCK
-void DEVICE::_r_dlock(const char *file, int line, bool locked)
+void DEVICE::dbg_rLock(const char *file, int line, bool locked)
{
- Dmsg3(sd_dbglvl+1, "r_dlock blked=%s from %s:%d\n", this->print_blocked(),
+ Dmsg3(sd_dbglvl, "rLock blked=%s from %s:%d\n", print_blocked(),
file, line);
+ if (!locked) {
+ /* lockmgr version of P(m_mutex) */
+ bthread_mutex_lock_p(&m_mutex, file, line);
+ m_count++;
+ }
#else
-void DEVICE::r_dlock(bool locked)
+void DEVICE::rLock(bool locked)
{
-#endif
- int stat;
if (!locked) {
- P(m_mutex); /* this->dlock(); */
- m_count++; /* this->dlock() */
+ Lock();
+ m_count++;
}
- if (this->blocked() && !pthread_equal(this->no_wait_id, pthread_self())) {
- this->num_waiting++; /* indicate that I am waiting */
- while (this->blocked()) {
+#endif
+
+ if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
+ num_waiting++; /* indicate that I am waiting */
+ while (blocked()) {
+ int stat;
#ifndef HAVE_WIN32
/* thread id on Win32 may be a struct */
- Dmsg3(sd_dbglvl, "r_dlock blked=%s no_wait=%p me=%p\n", this->print_blocked(),
- this->no_wait_id, pthread_self());
+ Dmsg3(sd_dbglvl, "rLock blked=%s no_wait=%p me=%p\n", print_blocked(),
+ no_wait_id, pthread_self());
#endif
if ((stat = pthread_cond_wait(&this->wait, &m_mutex)) != 0) {
berrno be;
- this->dunlock();
+ this->Unlock();
Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
be.bstrerror(stat));
}
}
- this->num_waiting--; /* no longer waiting */
+ num_waiting--; /* no longer waiting */
}
}
/*
* Block all other threads from using the device
* Device must already be locked. After this call,
- * the device is blocked to any thread calling dev->r_lock(),
+ * the device is blocked to any thread calling dev->rLock(),
* but the device is not locked (i.e. no P on device). Also,
- * the current thread can do slip through the dev->r_lock()
+ * the current thread can do slip through the dev->rLock()
* calls without blocking.
*/
void _block_device(const char *file, int line, DEVICE *dev, int state)
@@ -280,7 +450,6 @@ void _unblock_device(const char *file, int line, DEVICE *dev)
*/
void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
{
-
Dmsg3(sd_dbglvl, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
file, line);
hold->dev_blocked = dev->blocked();
@@ -289,7 +458,7 @@ void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *
dev->set_blocked(state);
Dmsg1(sd_dbglvl, "steal lock. new=%s\n", dev->print_blocked());
dev->no_wait_id = pthread_self();
- dev->dunlock();
+ dev->Unlock();
}
/*
@@ -300,7 +469,7 @@ void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock
{
Dmsg3(sd_dbglvl, "return lock. old=%s from %s:%d\n",
dev->print_blocked(), file, line);
- dev->dlock();
+ dev->Lock();
dev->set_blocked(hold->dev_blocked);
dev->dev_prev_blocked = hold->dev_prev_blocked;
dev->no_wait_id = hold->no_wait_id;
@@ -343,6 +512,7 @@ const char *DEVICE::print_blocked() const
bool DEVICE::is_device_unmounted()
{
bool stat;
+
int blk = blocked();
stat = (blk == BST_UNMOUNTED) ||
(blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);
diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c
index 68b5fed..dc1f38b 100644
--- a/bacula/src/stored/mount.c
+++ b/bacula/src/stored/mount.c
@@ -863,11 +863,11 @@ bool mount_next_read_volume(DCR *dcr)
* End Of Tape -- mount next Volume (if another specified)
*/
if (jcr->NumReadVolumes > 1 && jcr->CurReadVolume < jcr->NumReadVolumes) {
- dev->dlock();
+ dev->Lock();
dev->close();
dev->set_read();
dcr->set_reserved();
- dev->dunlock();
+ dev->Unlock();
if (!acquire_device_for_read(dcr)) {
Jmsg2(jcr, M_FATAL, 0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(),
dcr->VolumeName);
diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c
index 615e117..4e9754a 100644
--- a/bacula/src/stored/reserve.c
+++ b/bacula/src/stored/reserve.c
@@ -144,7 +144,7 @@ void DCR::clear_reserved()
*/
void DCR::unreserve_device()
{
- dev->dlock();
+ dev->Lock();
lock_volumes();
if (is_reserved()) {
clear_reserved();
@@ -163,7 +163,7 @@ void DCR::unreserve_device()
}
}
unlock_volumes();
- dev->dunlock();
+ dev->Unlock();
}
/*
@@ -773,7 +773,7 @@ static bool reserve_device_for_read(DCR *dcr)
return false;
}
- dev->dlock();
+ dev->Lock();
if (dev->is_device_unmounted()) {
Dmsg1(dbglvl, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
@@ -804,7 +804,7 @@ static bool reserve_device_for_read(DCR *dcr)
ok = true;
bail_out:
- dev->dunlock();
+ dev->Unlock();
return ok;
}
@@ -835,7 +835,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
return false;
}
- dev->dlock();
+ dev->Lock();
/* If device is being read, we cannot write it */
if (dev->can_read()) {
@@ -872,7 +872,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
ok = true;
bail_out:
- dev->dunlock();
+ dev->Unlock();
return ok;
}
diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c
index 320d4ed..20f2c08 100644
--- a/bacula/src/stored/status.c
+++ b/bacula/src/stored/status.c
@@ -307,7 +307,7 @@ static void send_blocked_status(DEVICE *dev, STATUS_PKT *sp)
{
DCR *dcr;
bool found_jcr = false;
- dev->dlock();
+ dev->Lock();
foreach_dlist(dcr, dev->attached_dcrs) {
if (dcr->jcr->JobStatus == JS_WaitMount) {
len = Mmsg(msg, _(" Device is BLOCKED waiting for mount of volume \"%s\",\n"
@@ -328,7 +328,7 @@ static void send_blocked_status(DEVICE *dev, STATUS_PKT *sp)
found_jcr = true;
}
}
- dev->dunlock();
+ dev->Unlock();
if (!found_jcr) {
len = Mmsg(msg, _(" Device is BLOCKED waiting for media.\n"));
sendit(msg, len, sp);
@@ -410,7 +410,7 @@ static void send_device_status(DEVICE *dev, STATUS_PKT *sp)
sendit(msg, len, sp);
DCR *dcr = NULL;
bool found = false;
- dev->dlock();
+ dev->Lock();
foreach_dlist(dcr, dev->attached_dcrs) {
if (dcr->jcr) {
if (found) {
@@ -421,7 +421,7 @@ static void send_device_status(DEVICE *dev, STATUS_PKT *sp)
found = true;
}
}
- dev->dunlock();
+ dev->Unlock();
sendit("\n", 1, sp);
len = Mmsg(msg, _("Device parameters:\n"));
diff --git a/bacula/src/stored/wait.c b/bacula/src/stored/wait.c
index 0a7a3d1..87f809f 100644
--- a/bacula/src/stored/wait.c
+++ b/bacula/src/stored/wait.c
@@ -59,7 +59,7 @@ int wait_for_sysop(DCR *dcr)
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
- dev->dlock();
+ dev->Lock();
Dmsg1(dbglvl, "Enter blocked=%s\n", dev->print_blocked());
/*
@@ -206,7 +206,7 @@ int wait_for_sysop(DCR *dcr)
Dmsg1(dbglvl, "set %s\n", dev->print_blocked());
}
Dmsg1(dbglvl, "Exit blocked=%s\n", dev->print_blocked());
- dev->dunlock();
+ dev->Unlock();
return stat;
}
diff --git a/bacula/src/version.h b/bacula/src/version.h
index 01649d8..fa713b2 100644
--- a/bacula/src/version.h
+++ b/bacula/src/version.h
@@ -1,16 +1,16 @@
#undef VERSION
-#define VERSION "5.2.12"
-#define BDATE "12 September 2012"
-#define LSMDATE "12Sep12"
+#define VERSION "5.2.13"
+#define BDATE "30 January 2013"
+#define LSMDATE "30Jan13"
#define PROG_COPYRIGHT "Copyright (C) %d-2012 Free Software Foundation Europe e.V.\n"
-#define BYEAR "2012" /* year for copyright messages in progs */
+#define BYEAR "2013" /* year for copyright messages in progs */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2013 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
diff --git a/regress/all-tape-tests b/regress/all-tape-tests
index 19c4a72..12b62e1 100755
--- a/regress/all-tape-tests
+++ b/regress/all-tape-tests
@@ -27,7 +27,7 @@ rm -f dumps/*
./run tests/relabel-tape
./run tests/restore-by-file-tape
./run tests/small-file-size-tape
-./run tests/t./runcate-bug-tape
+./run tests/truncate-bug-tape
./run tests/verify-vol-tape
# ./run tests/manual-two-vol-tape
echo "End all non-root tape tests"
hooks/post-receive
--
Bacula Community source
|