]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/device.c
Big backport from Enterprise
[bacula/bacula] / bacula / src / stored / device.c
index 3743bcee90555b87eb4dc18262e6811fe838fad8..27be8c1950357c43d9984c45869d78cc31f7fb16 100644 (file)
@@ -1,17 +1,20 @@
 /*
-   Bacula® - The Network Backup Solution
+   Bacula(R) - The Network Backup Solution
 
-   Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2017 Kern Sibbald
 
-   The main author of Bacula is Kern Sibbald, with contributions from many
-   others, a complete list can be found in the file AUTHORS.
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
 
    You may use this file and others of this release according to the
    license defined in the LICENSE file, which includes the Affero General
    Public License, v3.0 ("AGPLv3") and some additional permissions and
    terms pursuant to its AGPLv3 Section 7.
 
-   Bacula® is a registered trademark of Kern Sibbald.
+   This notice must be preserved when any source code is
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  *
  */
 
 #include "bacula.h"                   /* pull in global headers */
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#else
-#define statvfs statfs
-#endif
-/* statvfs.h defines ST_APPEND, which is also used by Bacula */
-#undef ST_APPEND
-
 #include "stored.h"                   /* pull in Storage Deamon headers */
 
-
 /* Forward referenced functions */
 
 /*
@@ -81,8 +75,9 @@
 bool fixup_device_block_write_error(DCR *dcr, int retries)
 {
    char PrevVolName[MAX_NAME_LENGTH];
-   DEV_BLOCK *label_blk;
-   DEV_BLOCK *block;
+   DEV_BLOCK *block = dcr->block;
+   DEV_BLOCK *ameta_block = dcr->ameta_block;
+   DEV_BLOCK *adata_block = dcr->adata_block;
    char b1[30], b2[30];
    time_t wait_time;
    char dt[MAX_TIME_LENGTH];
@@ -90,15 +85,17 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
    DEVICE *dev;
    int blocked;              /* save any previous blocked status */
    bool ok = false;
+   bool save_adata = dcr->dev->adata;
 
+   Enter(100);
+   if (save_adata) {
+      dcr->set_ameta();      /* switch to working with ameta */
+   }
    dev = dcr->dev;
    blocked = dev->blocked();
-   block = dcr->block;
 
    wait_time = time(NULL);
 
-   Dmsg0(100, "=== Enter fixup_device_block_write_error\n");
-
    /*
     * If we are blocked at entry, unblock it, and set our own block status
     */
@@ -113,8 +110,7 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
    bstrncpy(PrevVolName, dev->getVolCatName(), sizeof(PrevVolName));
    bstrncpy(dev->VolHdr.PrevVolumeName, PrevVolName, sizeof(dev->VolHdr.PrevVolumeName));
 
-   label_blk = new_block(dev);
-   dcr->block = label_blk;
+   dev->new_dcr_blocks(dcr);
 
    /* Inform User about end of medium */
    Jmsg(jcr, M_INFO, 0, _("End of medium on Volume \"%s\" Bytes=%s Blocks=%s at %s.\n"),
@@ -126,12 +122,16 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
    dev->set_unload();
 
    /* Clear DCR Start/End Block/File positions */
-   dcr->StartBlock = dcr->EndBlock = 0;
-   dcr->StartFile  = dcr->EndFile = 0;
+   dcr->VolFirstIndex = dcr->VolLastIndex = 0;
+   dcr->StartAddr = dcr->EndAddr = 0;
+   dcr->VolMediaId = 0;
+   dcr->WroteVol = false;
 
    if (!dcr->mount_next_write_volume()) {
-      free_block(label_blk);
+      dev->free_dcr_blocks(dcr);
       dcr->block = block;
+      dcr->ameta_block = ameta_block;
+      dcr->adata_block = adata_block;
       dev->Lock();
       goto bail_out;
    }
@@ -141,7 +141,9 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
    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 */
+   if (!dir_update_volume_info(dcr, false, false)) { /* send Volume info to Director */
+      goto bail_out;
+   }
 
    Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"),
       dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL)));
@@ -157,12 +159,16 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
       berrno be;
       Pmsg1(0, _("write_block_to_device Volume label failed. ERR=%s"),
         be.bstrerror(dev->dev_errno));
-      free_block(label_blk);
+      dev->free_dcr_blocks(dcr);
       dcr->block = block;
+      dcr->ameta_block = ameta_block;
+      dcr->adata_block = adata_block;
       goto bail_out;
    }
-   free_block(label_blk);
+   dev->free_dcr_blocks(dcr);
    dcr->block = block;
+   dcr->ameta_block = ameta_block;
+   dcr->adata_block = adata_block;
 
    /* Clear NewVol now because dir_get_volume_info() already done */
    jcr->dcr->NewVol = false;
@@ -172,6 +178,9 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
 
    /* Write overflow block to device */
    Dmsg0(190, "Write overflow block to dev\n");
+   if (save_adata) {
+      dcr->set_adata();      /* try to write block we entered with */
+   }
    if (!dcr->write_block_to_dev()) {
       berrno be;
       Dmsg1(0, _("write_block_to_device overflow block failed. ERR=%s"),
@@ -187,6 +196,9 @@ bool fixup_device_block_write_error(DCR *dcr, int retries)
    ok = true;
 
 bail_out:
+   if (save_adata) {
+      dcr->set_ameta();   /* Do unblock ... on ameta */
+   }
    /*
     * At this point, the device is locked and blocked.
     * Unblock the device, restore any entry blocked condition, then
@@ -196,6 +208,9 @@ bail_out:
    if (blocked != BST_NOT_BLOCKED) {
       block_device(dev, blocked);
    }
+   if (save_adata) {
+      dcr->set_adata();      /* switch back to what we entered with */
+   }
    return ok;                               /* device locked */
 }
 
@@ -204,14 +219,17 @@ void set_start_vol_position(DCR *dcr)
    DEVICE *dev = dcr->dev;
    /* Set new start position */
    if (dev->is_tape()) {
-      dcr->StartBlock = dev->block_num;
-      dcr->StartFile = dev->file;
+      dcr->StartAddr = dcr->EndAddr = dev->get_full_addr();
    } else {
+      if (dev->adata) {
+         dev = dcr->ameta_dev;
+      }
       /*
-       * Note: we only update the DCR values for blocks
+       * Note: we only update the DCR values for ameta blocks
+       *  because all the indexing (JobMedia) is done with
+       *  ameta blocks/records, which may point to adata.
        */
-      dcr->StartBlock = dcr->EndBlock = (uint32_t)dev->file_addr;
-      dcr->StartFile  = dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+      dcr->StartAddr = dcr->EndAddr = dev->get_full_addr();
    }
 }
 
@@ -229,7 +247,7 @@ void set_new_volume_parameters(DCR *dcr)
          int retries = 5;
          wait_for_device(dcr, retries);
       }
-      if (dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
+      if (dir_get_volume_info(dcr, dcr->VolumeName, GET_VOL_INFO_FOR_WRITE)) {
          dcr->dev->clear_wait();
       } else {
          Dmsg1(40, "getvolinfo failed. No new Vol: %s", jcr->errmsg);
@@ -292,15 +310,9 @@ bool first_open_device(DCR *dcr)
       goto bail_out;
    }
 
-    int mode;
-    if (dev->has_cap(CAP_STREAM)) {
-       mode = OPEN_WRITE_ONLY;
-    } else {
-       mode = OPEN_READ_ONLY;
-    }
    Dmsg0(129, "Opening device.\n");
-   if (!dev->open(dcr, mode)) {
-      Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
+   if (!dev->open_device(dcr, OPEN_READ_ONLY)) {
+      Jmsg1(NULL, M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
       ok = false;
       goto bail_out;
    }
@@ -310,124 +322,3 @@ bail_out:
    dev->rUnlock();
    return ok;
 }
-
-/*
- * Make sure device is open, if not do so
- */
-bool open_dev(DCR *dcr)
-{
-   DEVICE *dev = dcr->dev;
-   /* Open device */
-   int mode;
-   if (dev->has_cap(CAP_STREAM)) {
-      mode = OPEN_WRITE_ONLY;
-   } else {
-      mode = OPEN_READ_WRITE;
-   }
-   if (!dev->open(dcr, mode)) {
-      /* If polling, ignore the error */
-      /* If DVD, also ignore the error, very often you cannot open the device
-       * (when there is no DVD, or when the one inserted is a wrong one) */
-      if (!dev->poll && !dev->is_dvd() && !dev->is_removable()) {
-         Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
-            dev->print_name(), dev->bstrerror());
-         Pmsg2(000, _("Unable to open archive %s: ERR=%s\n"),
-            dev->print_name(), dev->bstrerror());
-      }
-      return false;
-   }
-   return true;
-}
-
-/*
- */
-void DEVICE::updateVolCatBytes(uint64_t bytes)
-{
-   DEVICE *dev;
-   Lock_VolCatInfo();
-   dev = this;
-   dev->VolCatInfo.VolCatAmetaBytes += bytes;
-   dev->VolCatInfo.VolCatBytes += bytes;
-   setVolCatInfo(false);
-   Unlock_VolCatInfo();
-}
-
-void DEVICE::updateVolCatBlocks(uint32_t blocks)
-{
-   DEVICE *dev;
-   Lock_VolCatInfo();
-   dev = this;
-   dev->VolCatInfo.VolCatAmetaBlocks += blocks;
-   dev->VolCatInfo.VolCatBlocks += blocks;
-   setVolCatInfo(false);
-   Unlock_VolCatInfo();
-}
-
-void DEVICE::updateVolCatWrites(uint32_t writes)
-{
-   DEVICE *dev;
-   Lock_VolCatInfo();
-   dev = this;
-   dev->VolCatInfo.VolCatAmetaWrites += writes;
-   dev->VolCatInfo.VolCatWrites += writes;
-   setVolCatInfo(false);
-   Unlock_VolCatInfo();
-}
-
-void DEVICE::updateVolCatReads(uint32_t reads)
-{
-   DEVICE *dev;
-   Lock_VolCatInfo();
-   dev = this;
-   dev->VolCatInfo.VolCatAmetaReads += reads;
-   dev->VolCatInfo.VolCatReads += reads;
-   setVolCatInfo(false);
-   Unlock_VolCatInfo();
-}
-
-void DEVICE::updateVolCatReadBytes(uint64_t bytes)
-{
-   DEVICE *dev;
-   Lock_VolCatInfo();
-   dev = this;
-   dev->VolCatInfo.VolCatAmetaRBytes += bytes;
-   dev->VolCatInfo.VolCatRBytes += bytes;
-   setVolCatInfo(false);
-   Unlock_VolCatInfo();
-}
-
-void DEVICE::set_nospace()
-{
-   state |= ST_NOSPACE;
-}
-
-void DEVICE::clear_nospace()
-{
-   state &= ~ST_NOSPACE;
-}
-
-/* Put device in append mode */
-void DEVICE::set_append()
-{
-   state &= ~(ST_NOSPACE|ST_READ|ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
-   state |= ST_APPEND;
-}
-
-/* Clear append mode */
-void DEVICE::clear_append()
-{
-   state &= ~ST_APPEND;
-}
-
-/* Put device in read mode */
-void DEVICE::set_read()
-{
-   state &= ~(ST_APPEND|ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
-   state |= ST_READ;
-}
-
-/* Clear read mode */
-void DEVICE::clear_read()
-{
-   state &= ~ST_READ;
-}