From: Kern Sibbald Date: Tue, 29 Jan 2013 19:23:39 +0000 (+0100) Subject: Backport new lock calls + debug for SD X-Git-Url: https://git.sur5r.net/?p=bacula%2Fbacula;a=commitdiff_plain;h=55593b396948f86a7a05827573755ef47f531faa Backport new lock calls + debug for SD --- diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 6a7a69c602..58661cb3af 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/lib/message.c b/bacula/src/lib/message.c index 53f72c98a3..3ae4d37c05 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 20cad236c5..fd6141e11b 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/stored/acquire.c b/bacula/src/stored/acquire.c index 97936b9dc2..c8db2956d8 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 b512950636..8db3259c8a 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 b80c4a0737..e731320b88 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 967887290d..a3f751c964 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 7c6d57bcf8..3d4e44bc58 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 29d2bfd9ee..4824ef2670 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -455,16 +455,33 @@ 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 */ + int init_adata_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 +521,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 +529,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 +568,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 +585,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 f06b5cd189..1f4084d64d 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 6a02f9d861..a463802c8c 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 d20c1bf20f..73d1a669df 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 68b5fedd97..dc1f38bc19 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 615e117c99..4e9754ad3a 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 320d4ed976..20f2c086c3 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 0a7a3d1bf1..87f809facb 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; }