]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Correct error string numbers in dird/catreq.c
authorKern Sibbald <kern@sibbald.com>
Wed, 9 Apr 2008 14:59:59 +0000 (14:59 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 9 Apr 2008 14:59:59 +0000 (14:59 +0000)
kes  Restructure reserving, acquiring, and mounting volumes. Calls to
     autochanger are deferred for mount.c -- simplifes the code.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6779 91ce42f0-d328-0410-95d8-f526ca767f89

13 files changed:
bacula/src/dird/catreq.c
bacula/src/dird/ua_prune.c
bacula/src/stored/acquire.c
bacula/src/stored/askdir.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dvd.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/protos.h
bacula/src/stored/reserve.c
bacula/src/version.h
bacula/technotes-2.3

index ee1d059c0643261d66a32ae4b8b9f6528202e8d4..e04a1e7b43eed92c83d5878fcc2fb1834ec25fca 100644 (file)
@@ -331,7 +331,7 @@ void catalog_request(JCR *jcr, BSOCK *bs)
       if (!db_create_jobmedia_record(jcr, jcr->db, &jm)) {
          Jmsg(jcr, M_FATAL, 0, _("Catalog error creating JobMedia record. %s"),
             db_strerror(jcr->db));
-         bs->fsend(_("1991 Update JobMedia error\n"));
+         bs->fsend(_("1992 Create JobMedia error\n"));
       } else {
          Dmsg0(400, "JobMedia record created\n");
          bs->fsend(OK_create);
@@ -377,7 +377,7 @@ void catalog_update(JCR *jcr, BSOCK *bs)
    if (!jcr->db) {
       omsg = get_memory(bs->msglen+1);
       pm_strcpy(omsg, bs->msg);
-      bs->fsend(_("1991 Invalid Catalog Update: %s"), omsg);    
+      bs->fsend(_("1994 Invalid Catalog Update: %s"), omsg);    
       Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog Update; DB not open: %s"), omsg);
       free_memory(omsg);
       goto bail_out;
index 7299155d16f3df14f3c706b56f3b281c337d36dc..546477f9b0be63ae8a155aef47b7553afbd9cf04 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2008 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.
@@ -169,11 +169,11 @@ int prunecmd(UAContext *ua, const char *cmd)
    case 3:  /* prune stats */
       dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
       if (!dir->stats_retention) {
-        return false;
+         return false;
       }
       retention = dir->stats_retention;
       if (!confirm_retention(ua, &retention, "Statistics")) {
-        return false;
+         return false;
       }
       prune_stats(ua, retention);
       return true;
@@ -195,7 +195,7 @@ int prune_stats(UAContext *ua, utime_t retention)
 
    db_lock(ua->db);
    Mmsg(query, "DELETE FROM JobStat WHERE JobTDate < %s", 
-       edit_uint64(now - retention, ed1));
+        edit_uint64(now - retention, ed1));
    db_sql_query(ua->db, query.c_str(), NULL, NULL);
    db_unlock(ua->db);
 
@@ -468,6 +468,8 @@ int get_prune_list_for_volume(UAContext *ua, MEDIA_DBR *mr, del_ctx *del)
    int i;          
    utime_t now, period;
    char ed1[50], ed2[50];
+   JCR *jcr;
+   bool skip;
 
    if (mr->Enabled == 2) {
       return 0;                    /* cannot prune Archived volumes */
@@ -495,10 +497,18 @@ int get_prune_list_for_volume(UAContext *ua, MEDIA_DBR *mr, del_ctx *del)
       goto bail_out;
    }
 
+   /* Do not prune any job currently running */
    for (i=0; i < del->num_ids; i++) {
-      if (ua->jcr->JobId == del->JobId[i]) {
-         Dmsg2(150, "skip same job JobId[%d]=%d\n", i, (int)del->JobId[i]);
-         del->JobId[i] = 0;
+      skip = false;
+      foreach_jcr(jcr) {
+         if (jcr->JobId == del->JobId[i]) {
+            Dmsg2(150, "skip same job JobId[%d]=%d\n", i, (int)del->JobId[i]);
+            del->JobId[i] = 0;
+            skip = true;
+            break;
+         }
+      }
+      if (skip) {
          continue;
       }
       Dmsg2(150, "accept JobId[%d]=%d\n", i, (int)del->JobId[i]);
index b930e64974140918dab509c5a32e9d4186c1cf3b..4ab57d2178f9bd741a4426bc68ca9cb988188d8d 100644 (file)
@@ -39,6 +39,7 @@
 /* Forward referenced functions */
 static void attach_dcr_to_dev(DCR *dcr);
 static bool is_suitable_volume_mounted(DCR *dcr);
+static bool is_tape_position_ok(JCR *jcr, DEVICE *dev);
 
 
 /*********************************************************************
@@ -315,10 +316,7 @@ get_out:
  */
 DCR *acquire_device_for_append(DCR *dcr)
 {
-   bool do_mount = false;
-   bool release = false;
-   bool have_vol;
-   DEVICE * volatile dev = dcr->dev;
+   DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
 
    init_device_wait_timers(dcr);
@@ -340,92 +338,23 @@ DCR *acquire_device_for_append(DCR *dcr)
     * have_vol defines whether or not mount_next_write_volume should
     *   ask the Director again about what Volume to use.
     */
-   have_vol = is_suitable_volume_mounted(dcr);
-   if (dev->can_append()) {
-      Dmsg0(100, "device already in append.\n");
+   if (dev->can_append() && is_suitable_volume_mounted(dcr) &&
+       strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
+      Dmsg0(190, "device already in append.\n");
       /*
-       * Device already in append mode
-       *
-       * Check if we have the right Volume mounted
-       *   OK if current volume info OK
-       *   OK if next volume matches current volume
-       *   otherwise mount desired volume obtained from
-       *    dir_find_next_appendable_volume
-       *  dev->VolHdr.VolumeName is what is in the drive
-       *  dcr->VolumeName is what we pass into the routines, or
-       *    get back from the subroutines.
+       * At this point, the correct tape is already mounted, so
+       *   we do not need to do mount_next_write_volume(), unless
+       *   we need to recycle the tape.
        */
-      /* If we do not have a volume, see if we can find one */
-      if (!have_vol) {
-         Dmsg0(100, "call dir_find_next_appendable_volume\n");
-         have_vol = dir_find_next_appendable_volume(dcr);
-         dev = dcr->dev;
-         Dmsg2(100, "devVol=%s dcrVol=%s\n", dev->VolHdr.VolumeName, dcr->VolumeName);
-      }
-      if (have_vol) {
-         do_mount = true;
-         /* Make sure it is what we we have on the drive */
-         if (dev->VolHdr.VolumeName[0]) {
-            Dmsg2(100, "devVol=%s dcrVol=%s\n", dev->VolHdr.VolumeName, dcr->VolumeName);
-            /* If we already have the volume, mount/release are not needed */
-            do_mount = strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) != 0;
-            if (do_mount) {
-               release = true;
-               Dmsg0(100, "Set release\n");
-            }
-         }
-      }
-      if (have_vol && !do_mount) {
-         /*
-          * At this point, the correct tape is already mounted, so
-          *   we do not need to do mount_next_write_volume(), unless
-          *   we need to recycle the tape.
-          */
-         Dmsg2(100, "devVol=%s dcrVol=%s\n", dev->VolHdr.VolumeName, dcr->VolumeName);
-         do_mount = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
-         Dmsg2(190, "jid=%u Correct tape mounted. recycle=%d\n", 
-               (uint32_t)jcr->JobId, do_mount);
-         if (dev->num_writers == 0) {
-            memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
-         }
-
-         /*
-          *      Insanity check 
-          *
-          * Check to see if the tape position as defined by the OS is
-          *  the same as our concept.  If it is not, we bail out, because
-          *  it means the user has probably manually rewound the tape.
-          * Note, we check only if num_writers == 0, but this code will
-          *  also work fine for any number of writers. If num_writers > 0,
-          *  we probably should cancel all jobs using this device, or 
-          *  perhaps even abort the SD, or at a minimum, mark the tape
-          *  in error.  Another strategy with num_writers == 0, would be
-          *  to rewind the tape and do a new eod() request.
-          */
-         if (dev->is_tape() && dev->num_writers == 0) {
-            int32_t file = dev->get_os_tape_file();
-            if (file >= 0 && file != (int32_t)dev->get_file()) {
-               Jmsg(jcr, M_FATAL, 0, _("Invalid tape position on volume \"%s\"" 
-                    " on device %s. Expected %d, got %d\n"), 
-                    dev->VolHdr.VolumeName, dev->print_name(), dev->get_file(), file);
-               goto get_out;
-            }
-         }
-      }
+       if (dev->num_writers == 0) {
+          memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+       }
+       if (!is_tape_position_ok(jcr, dev)) {
+          goto get_out;
+       }
    } else {
-      /* Not already in append mode, so mount the device */
-      Dmsg2(190, "jid=%u Not in append mode, try mount have_vol=%d\n", 
-            (uint32_t)jcr->JobId, have_vol);
-
-      ASSERT(dev->num_writers == 0);
-      do_mount = true;
-   }
-
-   if (do_mount || !have_vol) {
       Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
-      Dmsg2(100, "devVol=%s dcrVol=%s\n", dev->VolHdr.VolumeName, dcr->VolumeName);
-      bool mounted = mount_next_write_volume(dcr, have_vol, release);
-      if (!mounted) {
+      if (!dcr->mount_next_write_volume()) {
          if (!job_canceled(jcr)) {
             /* Reduce "noise" -- don't print if job canceled */
             Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
@@ -469,13 +398,39 @@ get_out:
    return NULL;
 }
 
+/*
+ *      Insanity check 
+ *
+ * Check to see if the tape position as defined by the OS is
+ *  the same as our concept.  If it is not, we bail out, because
+ *  it means the user has probably manually rewound the tape.
+ * Note, we check only if num_writers == 0, but this code will
+ *  also work fine for any number of writers. If num_writers > 0,
+ *  we probably should cancel all jobs using this device, or 
+ *  perhaps even abort the SD, or at a minimum, mark the tape
+ *  in error.  Another strategy with num_writers == 0, would be
+ *  to rewind the tape and do a new eod() request.
+ */
+static bool is_tape_position_ok(JCR *jcr, DEVICE *dev)
+{
+   if (dev->is_tape() && dev->num_writers == 0) {
+      int32_t file = dev->get_os_tape_file();
+      if (file >= 0 && file != (int32_t)dev->get_file()) {
+         Jmsg(jcr, M_FATAL, 0, _("Invalid tape position on volume \"%s\"" 
+              " on device %s. Expected %d, got %d\n"), 
+              dev->VolHdr.VolumeName, dev->print_name(), dev->get_file(), file);
+         return false;
+      }
+   }
+   return true;
+}
 
 static bool is_suitable_volume_mounted(DCR *dcr)
 {
    DEVICE *dev = dcr->dev;
 
    /* Volume mounted? */
-   if (dev->VolHdr.VolumeName[0] == 0) {
+   if (dev->VolHdr.VolumeName[0] == 0 || dcr->swap_dev || dcr->unload_device) {
       return false;                      /* no */
    }
    bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
@@ -500,6 +455,7 @@ bool release_device(DCR *dcr)
    if (!dcr->is_dev_locked()) {
       dev->r_dlock();
    }
+   lock_volumes();
    Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
 
    /* if device is reserved, job never started, so release the reserve here */
@@ -554,6 +510,7 @@ bool release_device(DCR *dcr)
        */
       volume_unused(dcr);
    }
+   unlock_volumes();
 
    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
    if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
@@ -712,7 +669,7 @@ static void attach_dcr_to_dev(DCR *dcr)
 void detach_dcr_from_dev(DCR *dcr)
 {
    DEVICE *dev = dcr->dev;
-   Dmsg0(500, "Enter detach_dcr_from_dev\n");
+   Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
 
    /* Detach this dcr only if attached */
    if (dcr->attached_to_dev && dev) {
index 96ba8d1de0e628fa20eaf1834082ff8c7478083b..8d993457e09215f295894dd4a16cf6a600b57aeb 100644 (file)
@@ -258,7 +258,7 @@ bool dir_find_next_appendable_volume(DCR *dcr)
        dcr->reserved_device, dcr->VolumeName);
 
     /*
-     * Try the fourty oldest or most available volumes.  Note,
+     * Try the forty oldest or most available volumes.  Note,
      *   the most available could already be mounted on another
      *   drive, so we continue looking for a not in use Volume.
      */
index 7162dde092a9f0bcc612bb429d176f096a086844..be8d1847472feda75397ed2a7288c01b44747125 100644 (file)
@@ -426,6 +426,7 @@ public:
    dlink dev_link;                    /* link to attach to dev */
    JCR *jcr;                          /* pointer to JCR */
    DEVICE * volatile dev;             /* pointer to device */
+   DEVICE * volatile swap_dev;        /* Swap vol from this device */
    DEVRES *device;                    /* pointer to device resource */
    DEV_BLOCK *block;                  /* pointer to block */
    DEV_RECORD *rec;                   /* pointer to record */
@@ -444,6 +445,7 @@ public:
    bool attached_to_dev;              /* set when attached to dev */
    bool volume_in_use;                /* set in dir_find_next_appendable_volume() */
    bool keep_dcr;                     /* do not free dcr in release_dcr */
+   bool unload_device;                /* set if device must be unloaded */
    uint32_t VolFirstIndex;            /* First file index this Volume */
    uint32_t VolLastIndex;             /* Last file index this Volume */
    uint32_t FileIndex;                /* Current File Index */
@@ -468,6 +470,8 @@ public:
    void dlock() { dev->dlock(); m_dev_locked = true; }
    void dunlock() { m_dev_locked = false; dev->dunlock(); }
    void dblock(int why) { dev->dblock(why); }
+   bool mount_next_write_volume();
+   void mark_volume_in_error();
 
 };
 
index 50ab5dab1a48a968170c556a107aa92f95bc5e0b..0d84404ea744bfc414c97cab5f1dcdcb8d7c4b4e 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2008 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.
@@ -123,7 +123,8 @@ bool fixup_device_block_write_error(DCR *dcr)
         bstrftime(dt, sizeof(dt), time(NULL)));
 
    /* Called with have_vol=false, release=true */
-   if (!mount_next_write_volume(dcr, false, true)) {
+   dcr->unload_device = true;
+   if (!dcr->mount_next_write_volume()) {
       free_block(label_blk);
       dcr->block = block;
       dev->dlock();  
index f798098bd0d468df169d3c1e1425df66adfca459..0cfa2a5c091304b0ce3d59e7bc17389072debafd 100644 (file)
@@ -266,7 +266,7 @@ bool dvd_write_part(DCR *dcr)
       Dmsg1(100, "%s\n", dev->errmsg);
       dev->dev_errno = EIO;
       if (!dev->truncating) {
-         mark_volume_in_error(dcr);
+         dcr->mark_volume_in_error();
       }
       sm_check(__FILE__, __LINE__, false);
       return false;
index ccf657c5ea1e5a4272b82118083b06a76f6f05d8..9f47dbe88f886e1611363dd0f0e5afe57643e2ae 100644 (file)
@@ -212,14 +212,16 @@ int read_dev_volume_label(DCR *dcr)
    }
 
    dev->set_labeled();               /* set has Bacula label */
-   Dmsg0(100, "Call reserve_volume\n");
+   Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
+   Dmsg2(100, "=== dcr->dev=%p dev=%p\n", dcr->dev, dev);
    if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
       Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"),
            dev->VolHdr.VolumeName, dev->print_name());
       stat = VOL_NAME_ERROR;
       goto bail_out;
    }
-   dev = dcr->dev;                    /* may have changed in reserve volume */
+   Dmsg2(100, "=== dcr->dev=%p dev=%p\n", dcr->dev, dev);
+// dev = dcr->dev;                    /* may have changed in reserve volume */
 
    /* Compare Volume Names */
    Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
@@ -236,6 +238,7 @@ int read_dev_volume_label(DCR *dcr)
       }
       Dmsg0(150, "return VOL_NAME_ERROR\n");
       stat = VOL_NAME_ERROR;
+      volume_unused(dcr);             /* mark volume "released" */
       goto bail_out;
    }
    Dmsg1(130, "Copy vol_name=%s\n", dev->VolHdr.VolumeName);
@@ -251,6 +254,7 @@ int read_dev_volume_label(DCR *dcr)
          stat = read_ansi_ibm_label(dcr);            
          /* If we want a label and didn't find it, return error */
          if (stat != VOL_OK) {
+            volume_unused(dcr);       /* mark volume "released" */
             goto bail_out;
          }
       }
@@ -259,7 +263,6 @@ int read_dev_volume_label(DCR *dcr)
    return VOL_OK;
 
 bail_out:
-   volume_unused(dcr);                /* mark volume "released" */
    empty_block(block);
    dev->rewind(dcr);
    Dmsg1(150, "return %d\n", stat);
index 08381715bdb4563fd4e910d17ccb9ea26c4c099d..79edb8affb9babf4d9d2bc2708b037c27caa730d 100644 (file)
@@ -40,6 +40,7 @@
 
 static void mark_volume_not_inchanger(DCR *dcr);
 static int try_autolabel(DCR *dcr, bool opened);
+static bool is_eod_valid(DCR *dcr);
 
 enum {
    try_next_vol = 1,
@@ -60,21 +61,20 @@ enum {
  *  impossible to get the requested Volume.
  *
  */
-bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release)
+bool DCR::mount_next_write_volume()
 {
    int retry = 0;
    bool ask = false, recycle, autochanger;
    int vol_label_status;
-   DEVICE *dev = dcr->dev;
-   JCR *jcr = dcr->jcr;
-   DEV_BLOCK *block = dcr->block;
    int mode;
+   DCR *dcr = this;
 
-   Dmsg2(150, "Enter mount_next_volume(release=%d) dev=%s\n", release,
+   Dmsg2(150, "Enter mount_next_volume(release=%d) dev=%s\n", unload_device,
       dev->print_name());
 
    init_device_wait_timers(dcr);
-
+   lock_volumes();
+   
    /*
     * Attempt to mount the next volume. If something non-fatal goes
     *  wrong, we come back here to re-try (new op messages, re-read
@@ -85,21 +85,23 @@ mount_next_vol:
    /* Ignore retry if this is poll request */
    if (!dev->poll && retry++ > 4) {
       /* Last ditch effort before giving up, force operator to respond */
-      dcr->VolCatInfo.Slot = 0;
+      VolCatInfo.Slot = 0;
       if (!dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
          Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
               dev->print_name());
-         return false;
+         goto bail_out;
       }
    }
    if (job_canceled(jcr)) {
       Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId);
-      return false;
+      goto bail_out;
    }
    recycle = false;
-   if (release) {
+   if (unload_device) {
       Dmsg0(150, "mount_next_volume release=1\n");
       release_volume(dcr);
+      unload_autochanger(dcr, -1);
+      unload_device = false;
       ask = true;                     /* ask operator to mount tape */
    }
 
@@ -108,22 +110,18 @@ mount_next_vol:
     *    in dcr->VolCatInfo
     */
    Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
-   if (!have_vol) {
-      while (!dir_find_next_appendable_volume(dcr)) {
-         Dmsg0(200, "not dir_find_next\n");
-         if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
-            return false;
-          }
-          Dmsg0(200, "Again dir_find_next_append...\n");
+   while (!dir_find_next_appendable_volume(dcr)) {
+      Dmsg0(200, "not dir_find_next\n");
+      if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
+         goto bail_out;
        }
-   } else {
-      have_vol = false;               /* set false for next pass if any */
+       Dmsg0(200, "Again dir_find_next_append...\n");
    }
    if (job_canceled(jcr)) {
-      return false;
+      goto bail_out;
    }
    Dmsg3(150, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
-         dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot, dcr->VolCatInfo.VolCatParts);
+         VolCatInfo.VolCatName, VolCatInfo.Slot, VolCatInfo.VolCatParts);
    
    /*
     * Get next volume and ready it for append
@@ -136,12 +134,18 @@ mount_next_vol:
     * and move the tape to the end of data.
     *
     */
+   if (swap_dev) {
+      dev->vol = swap_dev->vol;      /* take its volume */
+      swap_dev->vol = NULL;
+      unload_dev(dcr, swap_dev);
+      swap_dev = NULL;
+   }
    if (autoload_device(dcr, 1, NULL) > 0) {
       autochanger = true;
       ask = false;
    } else {
       autochanger = false;
-      dcr->VolCatInfo.Slot = 0;
+      VolCatInfo.Slot = 0;
    }
    Dmsg1(200, "autoload_dev returns %d\n", autochanger);
    /*
@@ -150,7 +154,7 @@ mount_next_vol:
     *   and read the label. If there is no tape in the drive,
     *   we will fail, recurse and ask the operator the next time.
     */
-   if (!release && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
+   if (!unload_device && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
       Dmsg0(150, "(1)Ask=0\n");
       ask = false;                 /* don't ask SYSOP this time */
    }
@@ -160,16 +164,17 @@ mount_next_vol:
       ask = false;
    }
    Dmsg2(150, "Ask=%d autochanger=%d\n", ask, autochanger);
-   release = true;                /* release next time if we "recurse" */
+   unload_device = true;     /* release next time if we "recurse" */
 
    if (ask && !dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
       Dmsg0(150, "Error return ask_sysop ...\n");
-      return false;          /* error return */
+      goto bail_out;          /* error return */
    }
    if (job_canceled(jcr)) {
-      return false;
+      goto bail_out;
    }
-   Dmsg2(150, "want vol=%s dev=%s\n", dcr->VolumeName, dev->VolHdr.VolumeName);
+   Dmsg3(150, "want vol=%s devvol=%s dev=%s\n", VolumeName, 
+      dev->VolHdr.VolumeName, dev->print_name());
 
    if (dev->poll && dev->has_cap(CAP_CLOSEONPOLL)) {
       dev->close();
@@ -214,7 +219,7 @@ mount_next_vol:
       } else {
          Jmsg(jcr, M_ERROR, 0, _("Could not open device %s: ERR=%s\n"),
             dev->print_name(), dev->print_errmsg());
-         return false;
+         goto bail_out;
       }
    }
 
@@ -228,25 +233,25 @@ read_volume:
     */
    if (dev->has_cap(CAP_STREAM)) {
       vol_label_status = VOL_OK;
-      create_volume_label(dev, dcr->VolumeName, "Default", false /* not DVD */);
+      create_volume_label(dev, VolumeName, "Default", false /* not DVD */);
       dev->VolHdr.LabelType = PRE_LABEL;
    } else {
       vol_label_status = read_dev_volume_label(dcr);
    }
    if (job_canceled(jcr)) {
-      return false;
+      goto bail_out;
    }
 
-   Dmsg2(150, "Want dirVol=%s dirStat=%s\n", dcr->VolumeName,
-      dcr->VolCatInfo.VolCatStatus);
+   Dmsg2(150, "Want dirVol=%s dirStat=%s\n", VolumeName,
+      VolCatInfo.VolCatStatus);
    /*
     * At this point, dev->VolCatInfo has what is in the drive, if anything,
     *          and   dcr->VolCatInfo has what the Director wants.
     */
    switch (vol_label_status) {
    case VOL_OK:
-      Dmsg1(150, "Vol OK name=%s\n", dcr->VolumeName);
-      dev->VolCatInfo = dcr->VolCatInfo;       /* structure assignment */
+      Dmsg1(150, "Vol OK name=%s\n", VolumeName);
+      dev->VolCatInfo = VolCatInfo;       /* structure assignment */
       recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
       break;                    /* got a Volume */
    case VOL_NAME_ERROR:
@@ -256,16 +261,16 @@ read_volume:
       /* If not removable, Volume is broken */
       if (!dev->is_removable()) {
          Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
-            dcr->VolumeName, dev->print_name());
-         mark_volume_in_error(dcr);
+            VolumeName, dev->print_name());
+         dcr->mark_volume_in_error();
          goto mount_next_vol;
       }
 
-      Dmsg1(150, "Vol NAME Error Name=%s\n", dcr->VolumeName);
+      Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName);
       /* If polling and got a previous bad name, ignore it */
       if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
          ask = true;
-         Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", dcr->VolumeName);
+         Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", VolumeName);
          goto mount_next_vol;
       }
       /*
@@ -274,17 +279,17 @@ read_volume:
        *  this volume is really OK. If not, put back the desired
        *  volume name, mark it not in changer and continue.
        */
-      dcrVolCatInfo = dcr->VolCatInfo;      /* structure assignment */
+      dcrVolCatInfo = VolCatInfo;      /* structure assignment */
       devVolCatInfo = dev->VolCatInfo;      /* structure assignment */
       /* Check if this is a valid Volume in the pool */
-      bstrncpy(VolumeName, dcr->VolumeName, sizeof(VolumeName));
-      bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
+      bstrncpy(VolumeName, VolumeName, sizeof(VolumeName));
+      bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
          POOL_MEM vol_info_msg;
          pm_strcpy(vol_info_msg, jcr->dir_bsock->msg);  /* save error message */
          /* Restore desired volume name, note device info out of sync */
          /* This gets the info regardless of the Pool */
-         bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
+         bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
          if (autochanger && !dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
             /*
              * If we get here, we know we cannot write on the Volume,
@@ -302,16 +307,16 @@ read_volume:
              vol_info_msg.c_str());
          ask = true;
          /* Restore saved DCR before continuing */
-         bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
-         dcr->VolCatInfo = dcrVolCatInfo;  /* structure assignment */
+         bstrncpy(VolumeName, VolumeName, sizeof(VolumeName));
+         VolCatInfo = dcrVolCatInfo;  /* structure assignment */
          goto mount_next_vol;
       }
       /*
        * This was not the volume we expected, but it is OK with
        * the Director, so use it.
        */
-      Dmsg1(150, "want new name=%s\n", dcr->VolumeName);
-      dev->VolCatInfo = dcr->VolCatInfo;   /* structure assignment */
+      Dmsg1(150, "want new name=%s\n", VolumeName);
+      dev->VolCatInfo = VolCatInfo;   /* structure assignment */
       recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
       break;                /* got a Volume */
    /*
@@ -320,8 +325,8 @@ read_volume:
    case VOL_IO_ERROR:
       if (dev->is_dvd()) {
          Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
-         mark_volume_in_error(dcr);
-         return false;       /* we could not write on DVD */
+         dcr->mark_volume_in_error();
+         goto bail_out;       /* we could not write on DVD */
       }
       /* Fall through wanted */
    case VOL_NO_LABEL:
@@ -331,7 +336,7 @@ read_volume:
       case try_read_vol:
          goto read_volume;
       case try_error:
-         return false;
+         goto bail_out;
       case try_default:
          break;
       }
@@ -368,7 +373,7 @@ read_volume:
     */
    if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
       if (!rewrite_volume_label(dcr, recycle)) {
-         mark_volume_in_error(dcr);
+         dcr->mark_volume_in_error();
          goto mount_next_vol;
       }
    } else {
@@ -379,95 +384,23 @@ read_volume:
        */
       Dmsg0(200, "Device previously written, moving to end of data\n");
       Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
-         dcr->VolumeName);
+         VolumeName);
+
       if (!dev->eod(dcr)) {
          Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device %s: ERR=%s\n"),
             dev->print_name(), dev->bstrerror());
-         mark_volume_in_error(dcr);
+         dcr->mark_volume_in_error();
          goto mount_next_vol;
       }
-      if (dev->is_dvd()) {
-         char ed1[50], ed2[50];
-         if (dev->VolCatInfo.VolCatBytes == dev->part_start + dev->part_size) {
-            Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
-                 " part=%d size=%s\n"), dcr->VolumeName, 
-                 dev->part, edit_uint64(dev->VolCatInfo.VolCatBytes,ed1));
-         } else {
-            Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on DVD Volume \"%s\" because: "
-                 "The sizes do not match! Volume=%s Catalog=%s\n"),
-                 dcr->VolumeName,
-                 edit_uint64(dev->part_start + dev->part_size, ed1),
-                 edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
-            mark_volume_in_error(dcr);
-            goto mount_next_vol;
-         }
-      } else if (dev->is_tape()) {
-         /*
-          * Check if we are positioned on the tape at the same place
-          * that the database says we should be.
-          */
-         if (dev->VolCatInfo.VolCatFiles == dev->get_file()) {
-            Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
-                 dcr->VolumeName, dev->get_file());
-         } else {
-            Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on tape Volume \"%s\" because:\n"
-                 "The number of files mismatch! Volume=%u Catalog=%u\n"),
-                 dcr->VolumeName, dev->get_file(), dev->VolCatInfo.VolCatFiles);
-            mark_volume_in_error(dcr);
-            goto mount_next_vol;
-         }
-      } else if (dev->is_file()) {
-         char ed1[50], ed2[50];
-         boffset_t pos;
-         pos = dev->lseek(dcr, (boffset_t)0, SEEK_END);
-         if (dev->VolCatInfo.VolCatBytes == (uint64_t)pos) {
-            Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
-                 " size=%s\n"), dcr->VolumeName, 
-                 edit_uint64(dev->VolCatInfo.VolCatBytes, ed1));
-         } else {
-            Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on disk Volume \"%s\" because: "
-                 "The sizes do not match! Volume=%s Catalog=%s\n"),
-                 dcr->VolumeName,
-                 edit_uint64(pos, ed1),
-                 edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
-            mark_volume_in_error(dcr);
-            goto mount_next_vol;
-         }
+      if (!is_eod_valid(dcr)) {
+         goto mount_next_vol;
       }
+
       dev->VolCatInfo.VolCatMounts++;      /* Update mounts */
       Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
       if (!dir_update_volume_info(dcr, false, false)) {
-         return false;
-      }
-      
-      /*
-       * DVD : check if the last part was removed or truncated, or if a written
-       * part was overwritten.   
-       * We need to do it after dir_update_volume_info, so we have the EndBlock
-       * info. (nb: I don't understand why VolCatFiles is set (used to check
-       * tape file number), but not EndBlock)
-       * Maybe could it be changed "dev->is_file()" (would remove the fixme above)   
-       *
-       * Disabled: I had problems with this code... 
-       * (maybe is it related to the seek bug ?)   
-       */
-#ifdef xxx
-      if (dev->is_dvd()) {
-         Dmsg2(150, "DVD/File sanity check addr=%u vs endblock=%u\n", (unsigned int)dev->file_addr, (unsigned int)dev->VolCatInfo.EndBlock);
-         if (dev->file_addr == dev->VolCatInfo.EndBlock+1) {
-            Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file address=%u.\n"),
-                 dcr->VolumeName, (unsigned int)dev->file_addr);
-         }
-         else {
-            Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on Volume \"%s\" because:\n"
-                                    "The EOD file address is wrong: Volume file address=%u != Catalog Endblock=%u(+1)\n"
-                                    "Perhaps You removed the DVD last part in spool directory.\n"),
-                 dcr->VolumeName, (unsigned int)dev->file_addr, (unsigned int)dev->VolCatInfo.EndBlock);
-            mark_volume_in_error(dcr);
-            goto mount_next_vol;
-         }
+         goto bail_out;
       }
-#endif
       
       /* Return an empty block */
       empty_block(block);             /* we used it for reading so set for write */
@@ -476,9 +409,76 @@ read_volume:
    Dmsg1(150, "set APPEND, normal return from mount_next_write_volume. dev=%s\n",
       dev->print_name());
 
+   unlock_volumes();
+   return true;
+
+bail_out:
+   unlock_volumes();
+   return false;
+}
+
+
+/*
+ * Check if the current position on the volume corresponds to
+ *  what is in the catalog.
+ */
+static bool is_eod_valid(DCR *dcr)
+{
+   DEVICE *dev = dcr->dev;
+   JCR *jcr = dcr->jcr;
+
+   if (dev->is_dvd()) {
+      char ed1[50], ed2[50];
+      if (dev->VolCatInfo.VolCatBytes == dev->part_start + dev->part_size) {
+         Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
+              " part=%d size=%s\n"), dcr->VolumeName, 
+              dev->part, edit_uint64(dev->VolCatInfo.VolCatBytes,ed1));
+      } else {
+         Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on DVD Volume \"%s\" because: "
+              "The sizes do not match! Volume=%s Catalog=%s\n"),
+              dcr->VolumeName,
+              edit_uint64(dev->part_start + dev->part_size, ed1),
+              edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
+         dcr->mark_volume_in_error();
+         return false;
+      }
+   } else if (dev->is_tape()) {
+      /*
+       * Check if we are positioned on the tape at the same place
+       * that the database says we should be.
+       */
+      if (dev->VolCatInfo.VolCatFiles == dev->get_file()) {
+         Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
+              dcr->VolumeName, dev->get_file());
+      } else {
+         Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on tape Volume \"%s\" because:\n"
+              "The number of files mismatch! Volume=%u Catalog=%u\n"),
+              dcr->VolumeName, dev->get_file(), dev->VolCatInfo.VolCatFiles);
+         dcr->mark_volume_in_error();
+         return false;
+      }
+   } else if (dev->is_file()) {
+      char ed1[50], ed2[50];
+      boffset_t pos;
+      pos = dev->lseek(dcr, (boffset_t)0, SEEK_END);
+      if (dev->VolCatInfo.VolCatBytes == (uint64_t)pos) {
+         Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
+              " size=%s\n"), dcr->VolumeName, 
+              edit_uint64(dev->VolCatInfo.VolCatBytes, ed1));
+      } else {
+         Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on disk Volume \"%s\" because: "
+              "The sizes do not match! Volume=%s Catalog=%s\n"),
+              dcr->VolumeName,
+              edit_uint64(pos, ed1),
+              edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
+         dcr->mark_volume_in_error();
+         return false;
+      }
+   }
    return true;
 }
 
+
 /*
  * If permitted, we label the device, make sure we can do
  *   it by checking that the VolCatBytes is zero => not labeled,
@@ -516,7 +516,7 @@ static int try_autolabel(DCR *dcr, bool opened)
              dcr->pool_name, false, /* no relabel */ false /* defer DVD label */)) {
          Dmsg0(150, "!write_vol_label\n");
          if (opened) { 
-            mark_volume_in_error(dcr);
+            dcr->mark_volume_in_error();
          }
          return try_next_vol;
       }
@@ -538,7 +538,7 @@ static int try_autolabel(DCR *dcr, bool opened)
    if (!dev->is_removable()) {
       Jmsg(dcr->jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
          dcr->VolumeName, dev->print_name());
-      mark_volume_in_error(dcr);
+      dcr->mark_volume_in_error();
       return try_next_vol;
    }
    return try_default;
@@ -548,16 +548,15 @@ static int try_autolabel(DCR *dcr, bool opened)
 /*
  * Mark volume in error in catalog
  */
-void mark_volume_in_error(DCR *dcr)
+void DCR::mark_volume_in_error()
 {
-   DEVICE *dev = dcr->dev;
-   Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
-        dcr->VolumeName);
-   dev->VolCatInfo = dcr->VolCatInfo;     /* structure assignment */
+   Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
+        VolumeName);
+   dev->VolCatInfo = VolCatInfo;     /* structure assignment */
    bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
    Dmsg0(150, "dir_update_vol_info. Set Error.\n");
-   dir_update_volume_info(dcr, false, false);
-   volume_unused(dcr);
+   dir_update_volume_info(this, false, false);
+   volume_unused(this);
 }
 
 /*
index b6aca7b9ff63a1b065e8c964833ae7fff5cd96aa..2d0d37814f21b1feba7afa189ca05df8030e8650 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-20087 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.
@@ -185,9 +185,7 @@ BSR     *find_next_bsr(BSR *root_bsr, DEVICE *dev);
 bool     is_this_bsr_done(BSR *bsr, DEV_RECORD *rec);
 
 /* From mount.c */
-bool     mount_next_write_volume(DCR *dcr, bool have_vol, bool release);
 bool     mount_next_read_volume(DCR *dcr);
-void     mark_volume_in_error(DCR *dcr);
 
 /* From parse_bsr.c */
 BSR     *parse_bsr(JCR *jcr, char *lf);
index 90a81e6dd3cbdb3c83628e6b5666ecf750af2bbd..2880fb500f4c6e930627ceedc6d145ddad6b3e4c 100644 (file)
@@ -320,7 +320,8 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
 
    ASSERT(dev != NULL);
 
-   Dmsg1(dbglvl, "enter reserve_volume %s\n", VolumeName);
+   Dmsg2(dbglvl, "enter reserve_volume=%s drive=%s\n", VolumeName, 
+      dcr->dev->print_name());
    /* 
     * We lock the reservations system here to ensure
     *  when adding a new volume that no newly scheduled
@@ -355,8 +356,9 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
             goto get_out;
          }
          Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name);
-         unload_autochanger(dcr, -1);   /* unload the volume */
          free_volume(dev);
+         dcr->unload_device = true;     /* have to unload current volume */
+//       unload_autochanger(dcr, -1);   /* unload the volume */
          debug_list_volumes("reserve_vol free");
       }
    }
@@ -381,40 +383,22 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
        * Clear dev pointer so that free_vol_item() doesn't 
        *  take away our volume. 
        */
-      nvol->dev = NULL;                   /* don't zap dev entry */
+      nvol->dev = NULL;                  /* don't zap dev entry */
       free_vol_item(nvol);
 
       /* Check if we are trying to use the Volume on a different drive */
       if (dev != vol->dev) {
          /* Caller wants to switch Volume to another device */
-#ifdef xxx
-         Dmsg2(dbglvl, "==== Swap from dev=%s to %s\n",
-               dev->print_name(), vol->dev->print_name());
-         vol->dev->vol = NULL;            /* take vol from old drive */
-         switch_device(dcr, vol->dev);
-         dev = vol->dev;
-         bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
-#else  
          if (!vol->dev->is_busy()) {
-            vol->dev->vol = NULL;         /* take vol from old drive */
-            if (vol->dev->Slot > 0) {
-               Dmsg1(dbglvl, "Unload dev=%s\n", vol->dev->print_name());
-               unload_dev(dcr, vol->dev);
-            }
-            /* OK to move it -- I'm not sure this will work */
-            Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
-               vol->dev->print_name(), dev->print_name());
-            vol->dev->VolHdr.VolumeName[0] = 0;
-            vol->dev = dev;               /* point vol at new drive */
-            dev->vol = vol;               /* point dev at vol */
-            dev->VolHdr.VolumeName[0] = 0;
+            dcr->swap_dev = vol->dev;   /* remember to get this vol */
+            Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", 
+               VolumeName, vol->dev->print_name(), dev->print_name());
          } else {
             Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
-            vol = NULL;                /* device busy */
+            vol = NULL;                 /* device busy */
             goto get_out;
          }
-#endif
       }
    }
    dev->vol = vol;
@@ -487,6 +471,7 @@ VOLRES *find_volume(DCR *dcr)
 void unreserve_device(DCR *dcr)
 {
    DEVICE *dev = dcr->dev;
+   lock_volumes();
    if (dcr->reserved_device) {
       dcr->reserved_device = false;
       dcr->reserved_volume = false;
@@ -504,6 +489,7 @@ void unreserve_device(DCR *dcr)
          volume_unused(dcr);
       }
    }
+   unlock_volumes();
 }
 
 /*  
index 58c829d6080adc21bf927537c62b415c73ac4214..95579a4335d65fb798e27e7bfff9eac889bbed70 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "2.3.16"
-#define BDATE   "07 April 2008"
-#define LSMDATE "07Apr08"
+#define BDATE   "09 April 2008"
+#define LSMDATE "09Apr08"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2008"       /* year for copyright messages in progs */
index e034899c83e55bdb11aef03c06d32dcfae80925d..724940a656687b543a788ec4f1c96e4f8e3b41ce 100644 (file)
@@ -24,6 +24,15 @@ Add long term statistics job table
 
 
 General:
+09Apr08
+kes  Correct error string numbers in dird/catreq.c
+kes  Restructure reserving, acquiring, and mounting volumes. Calls to
+     autochanger are deferred for mount.c -- simplifes the code.
+08Apr08
+kes  Do not prune any running job. It just fails the job.
+kes  Lock the volumes when changing dev->reserved_device and marking
+     the volume unused otherwise the device can get reserved by
+     another job before the volume is released, thus blocking it.
 06Apr08
 kes  Correctly detect Ubuntu systems, and add ubuntu platform directory.
 kes  Fix bug #1063, reuse of freed ptr in list nextvol.