*
* Kern Sibbald, August MMII
*
- * Version $Id$
*/
#include "bacula.h" /* pull in global headers */
/* Forward referenced functions */
static void attach_dcr_to_dev(DCR *dcr);
+static void detach_dcr_from_dev(DCR *dcr);
static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
* This job is done, so release the device. From a Unix standpoint,
* the device remains open.
*
- * Note, if we are spooling, we may enter with the device locked.
- * However, in all cases, unlock the device when leaving.
+ * Note, if we are spooling, we may enter with the device blocked.
+ * However, in all cases, unblock the device when leaving.
*
*/
bool release_device(DCR *dcr)
bool ok = true;
char tbuf[100];
- /* lock only if not already locked by this thread */
- if (!dcr->is_dev_locked()) {
- dev->r_dlock();
+ dev->dlock();
+ if (!dev->is_blocked()) {
+ block_device(dev, BST_RELEASING);
+ } else if (dev->blocked() == BST_DESPOOLING) {
+ dev->set_blocked(BST_RELEASING);
}
lock_volumes();
Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
*/
volume_unused(dcr);
}
- unlock_volumes();
Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
dev->print_name());
- debug_list_volumes("acquire:release_device()");
-
/* If no writers, close if file or !CAP_ALWAYS_OPEN */
if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
(uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
pthread_cond_broadcast(&wait_device_release);
- dev->dunlock();
+ unlock_volumes();
+ dev->dunblock(true);
if (dcr->keep_dcr) {
detach_dcr_from_dev(dcr);
} else {
- if (jcr->read_dcr == dcr) {
- jcr->read_dcr = NULL;
- }
- if (jcr->dcr == dcr) {
- jcr->dcr = NULL;
- }
free_dcr(dcr);
}
Dmsg2(100, "===== Device %s released by JobId=%u\n", dev->print_name(),
DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev)
{
if (!dcr) {
+ int errstat;
dcr = (DCR *)malloc(sizeof(DCR));
memset(dcr, 0, sizeof(DCR));
dcr->tid = pthread_self();
dcr->spool_fd = -1;
+ if ((errstat = pthread_mutex_init(&dcr->m_mutex, NULL)) != 0) {
+ berrno be;
+ dev->dev_errno = errstat;
+ Mmsg1(dev->errmsg, _("Unable to init 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 */
static void attach_dcr_to_dev(DCR *dcr)
{
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
+ DEVICE *dev;
+ JCR *jcr;
+ P(dcr->m_mutex);
+ dev = dcr->dev;
+ jcr = dcr->jcr;
if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
- if (!dcr->attached_to_dev && dev->initiated && jcr && jcr->get_JobType() != JT_SYSTEM) {
+ if (!dcr->attached_to_dev && dev->initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
dev->attached_dcrs->append(dcr); /* attach dcr to device */
dcr->attached_to_dev = true;
Dmsg1(500, "JobId=%u attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
}
+ V(dcr->m_mutex);
}
-void detach_dcr_from_dev(DCR *dcr)
+/*
+ * DCR is locked before calling this routine
+ */
+static void locked_detach_dcr_from_dev(DCR *dcr)
{
DEVICE *dev = dcr->dev;
Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
/* Detach this dcr only if attached */
if (dcr->attached_to_dev && dev) {
- dev->dlock();
dcr->unreserve_device();
+ dev->dlock();
dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
- dcr->attached_to_dev = false;
// remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
dev->dunlock();
}
+ dcr->attached_to_dev = false;
+}
+
+
+static void detach_dcr_from_dev(DCR *dcr)
+{
+ P(dcr->m_mutex);
+ locked_detach_dcr_from_dev(dcr);
+ V(dcr->m_mutex);
}
/*
*/
void free_dcr(DCR *dcr)
{
- JCR *jcr = dcr->jcr;
+ JCR *jcr;
- detach_dcr_from_dev(dcr);
+ P(dcr->m_mutex);
+ jcr = dcr->jcr;
+ locked_detach_dcr_from_dev(dcr);
if (dcr->block) {
free_block(dcr->block);
if (jcr && jcr->dcr == dcr) {
jcr->dcr = NULL;
}
+ if (jcr && jcr->read_dcr == dcr) {
+ jcr->read_dcr = NULL;
+ }
+ V(dcr->m_mutex);
+ pthread_mutex_destroy(&dcr->m_mutex);
free(dcr);
}