]> git.sur5r.net Git - bacula/bacula/commitdiff
Backport new lock calls + debug for SD
authorKern Sibbald <kern@sibbald.com>
Tue, 29 Jan 2013 19:23:39 +0000 (20:23 +0100)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:51:07 +0000 (14:51 +0200)
16 files changed:
bacula/src/baconfig.h
bacula/src/lib/message.c
bacula/src/lib/message.h
bacula/src/stored/acquire.c
bacula/src/stored/bcopy.c
bacula/src/stored/block.c
bacula/src/stored/btape.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/lock.c
bacula/src/stored/mount.c
bacula/src/stored/reserve.c
bacula/src/stored/status.c
bacula/src/stored/wait.c

index 6a7a69c6028937e3147512e0aeef2515eb92d2f6..58661cb3afe99d04ca0fc4c11d091f2d10566913 100644 (file)
    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 */
index 53f72c98a33195847992e3fa152bfed5ae5c32db..3ae4d37c0565516dab4e9b203f6207e20d47e973 100644 (file)
@@ -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 */
index 20cad236c5bf567f2317ed036ea49ca147839ef0..fd6141e11bc585c634464998a0bc63744f1d58a4 100644 (file)
@@ -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;
 
index 97936b9dc23dc3636d912534093389d0841cb3cb..c8db2956d8b150330f0ca99d9f07fea117e9711b 100644 (file)
@@ -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);
 }
 
index b512950636a62eb711b0ebf20ab5a9bf6a5beaa0..8db3259c8acd60e9918e3fd6318e1afa4dc73df3 100644 (file)
@@ -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);
index b80c4a0737cafcf2e9a6660e30083bafe8b42cb2..e731320b880b2a459c8916bfad46c32c18dded34 100644 (file)
@@ -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;
 }
index 967887290d4de97d85527c210001ec3654b60246..a3f751c96475f3165f7d39c3cb2bbfe86b2acad2 100644 (file)
@@ -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;
 }
 
index 7c6d57bcf84ae6e930c1db6e0166ff18d3f4d565..3d4e44bc584ef0230f16f9f5177c647020798318 100644 (file)
@@ -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;
index 29d2bfd9ee800b25e472be394dfd0c584150ba75..4824ef2670f8d92d0f49643915d070ac8fda0661 100644 (file)
@@ -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 */
index f06b5cd189ddae472414cb48fa8cfa4823ac576c..1f4084d64d7e3084ca3b6ebca6bc25ee0b368558 100644 (file)
@@ -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;
 }
 
index 6a02f9d861c307db16b1117bb9616ae61aade30d..a463802c8cad427050eae8da9fff26a7be75188d 100644 (file)
@@ -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());
index d20c1bf20f6bcec3dc73565da385ece763990369..73d1a669df2bef9bda2595c3e3c1aea8508aeb8a 100644 (file)
@@ -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);
index 68b5fedd9750b4b76a7331beb08f9aef1779e4c8..dc1f38bc1927d543d64b4b373caf0cdc37b9c2a8 100644 (file)
@@ -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);
index 615e117c99f417b16344abd63c71b55df5a62daf..4e9754ad3a78405c0b998990b11739eabcbb872e 100644 (file)
@@ -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;
 }
 
index 320d4ed976572f179cf56992173eb5d38f9fd2c8..20f2c086c31c1ece5cfa19d96542a77a276d4b6d 100644 (file)
@@ -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"));
index 0a7a3d1bf1aaa2605e59388ba8c8d90834247910..87f809facbfdf24bce52f16b8a5ff8f01c2d0107 100644 (file)
@@ -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;
 }