]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/dev.c
Extend idea of Prefer Mounted Volumes to mean a volume about
[bacula/bacula] / bacula / src / stored / dev.c
index 47d8e6741f12f3488d3782a502d94367afe961eb..4c9e0d20c0780f9b6bac11901125e8b223e95bc9 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2007 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.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *
  *   dev.c  -- low level operations on device (storage device)
@@ -5,7 +32,7 @@
  *              Kern Sibbald, MM
  *
  *     NOTE!!!! None of these routines are reentrant. You must
- *        use lock_device() and unlock_device() at a higher level,
+ *        use dev->r_dlock() 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
  *
  *   Version $Id$
  */
-/*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2000-2007 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.
-   This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
-   License as published by the Free Software Foundation plus additions
-   that are listed in the file LICENSE.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Bacula® is a registered trademark of John Walker.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
-*/
 
 /*
  * Handling I/O errors and end of tape conditions are a bit tricky.
@@ -254,6 +254,7 @@ init_dev(JCR *jcr, DEVRES *device)
    dev->clear_opened();
    dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link));
    Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev->is_tape(), dev->dev_name);
+   dev->initiated = true;
    
    return dev;
 }
@@ -782,18 +783,21 @@ bool DEVICE::rewind(DCR *dcr)
 
 void DEVICE::block(int why)
 {
-   lock_device(this);
+   r_dlock();              /* need recursive lock to block */
    block_device(this, why);
-   unlock();
+   r_dunlock();
 }
 
-void DEVICE::unblock()
-{  
-   lock();   
+void DEVICE::unblock(bool locked)
+{
+   if (!locked) {
+      dlock();
+   }
    unblock_device(this);
-   unlock();
+   dunlock();
 }
 
+
 const char *DEVICE::print_blocked() const 
 {
    switch (m_blocked) {
@@ -850,9 +854,9 @@ void DEVICE::set_ateot()
 bool DEVICE::eod(DCR *dcr)
 {
    struct mtop mt_com;
-   struct mtget mt_stat;
    bool ok = true;
    boffset_t pos;
+   int32_t os_file;
 
    if (m_fd < 0) {
       dev_errno = EBADF;
@@ -893,7 +897,7 @@ bool DEVICE::eod(DCR *dcr)
    if (has_cap(CAP_FASTFSF) && !has_cap(CAP_EOM)) {
       Dmsg0(100,"Using FAST FSF for EOM\n");
       /* If unknown position, rewind */
-      if (!dev_get_os_pos(this, &mt_stat)) {
+      if (get_os_tape_file() < 0) {
         if (!rewind(NULL)) {
           return false;
         }
@@ -926,16 +930,17 @@ bool DEVICE::eod(DCR *dcr)
          return false;
       }
 
-      if (!dev_get_os_pos(this, &mt_stat)) {
+      os_file = get_os_tape_file();
+      if (os_file < 0) {
          berrno be;
          clrerror(-1);
          Mmsg2(errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
             print_name(), be.strerror());
          return false;
       }
-      Dmsg2(100, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
+      Dmsg1(100, "EOD file=%d\n", os_file);
       set_ateof();
-      file = mt_stat.mt_fileno;
+      file = os_file;
    } else {
 #else
    {
@@ -960,12 +965,12 @@ bool DEVICE::eod(DCR *dcr)
           * Avoid infinite loop by ensuring we advance.
           */
          if (!at_eot() && file_num == (int)file) {
-            struct mtget mt_stat;
             Dmsg1(100, "fsf did not advance from file %d\n", file_num);
             set_ateof();
-            if (dev_get_os_pos(this, &mt_stat)) {
-               Dmsg2(100, "Adjust file from %d to %d\n", file_num, mt_stat.mt_fileno);
-               file = mt_stat.mt_fileno;
+            os_file = get_os_tape_file();
+            if (os_file >= 0) {
+               Dmsg2(100, "Adjust file from %d to %d\n", file_num, os_file);
+               file = os_file;
             }       
             break;
          }
@@ -977,13 +982,13 @@ bool DEVICE::eod(DCR *dcr)
     * the second EOF.
     */
    if (has_cap(CAP_BSFATEOM)) {
-      struct mtget mt_stat;
       /* Backup over EOF */
       ok = bsf(1);
       /* If BSF worked and fileno is known (not -1), set file */
-      if (dev_get_os_pos(this, &mt_stat)) {
-         Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", file , mt_stat.mt_fileno);
-         file = mt_stat.mt_fileno;
+      os_file = get_os_tape_file();
+      if (os_file >= 0) {
+         Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", file , os_file);
+         file = os_file;
       } else {
          file++;                       /* wing it -- not correct on all OSes */
       }
@@ -1255,7 +1260,7 @@ bool DEVICE::offline_or_rewind()
  */
 bool DEVICE::fsf(int num)
 {
-   struct mtget mt_stat;
+   int32_t os_file;
    struct mtop mt_com;
    int stat = 0;
 
@@ -1292,7 +1297,7 @@ bool DEVICE::fsf(int num)
       mt_com.mt_op = MTFSF;
       mt_com.mt_count = num;
       stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
-      if (stat < 0 || !dev_get_os_pos(this, &mt_stat)) {
+      if (stat < 0 || (os_file=get_os_tape_file()) < 0) {
          berrno be;
          set_eot();
          Dmsg0(200, "Set ST_EOT\n");
@@ -1302,9 +1307,9 @@ bool DEVICE::fsf(int num)
          Dmsg1(200, "%s", errmsg);
          return false;
       }
-      Dmsg2(200, "fsf file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
+      Dmsg1(200, "fsf file=%d\n", os_file);
       set_ateof();
-      file = mt_stat.mt_fileno;
+      file = os_file;
       return true;
 
    /*
@@ -1701,7 +1706,6 @@ bool DEVICE::weof(int num)
 void DEVICE::clrerror(int func)
 {
    const char *msg = NULL;
-   struct mtget mt_stat;
    char buf[100];
 
    dev_errno = errno;         /* save errno */
@@ -1804,16 +1808,12 @@ void DEVICE::clrerror(int func)
     */
 
    /* On some systems such as NetBSD, this clears all errors */
-   tape_ioctl(m_fd, MTIOCGET, (char *)&mt_stat);
+   get_os_tape_file();
 
-/* Found on Linux */
+/* Found on Solaris */
 #ifdef MTIOCLRERR
 {
-   struct mtop mt_com;
-   mt_com.mt_op = MTIOCLRERR;
-   mt_com.mt_count = 1;
-   /* Clear any error condition on the tape */
-   tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   tape_ioctl(m_fd, MTIOCLRERR);
    Dmsg0(200, "Did MTIOCLRERR\n");
 }
 #endif
@@ -1843,6 +1843,21 @@ void DEVICE::clrerror(int func)
 #endif
 }
 
+
+/*
+ * Clear volume header
+ */
+void DEVICE::clear_volhdr()
+{
+   /* If we have an unused volume associated with this drive, free it */
+   if (vol && !is_busy()) {
+      free_volume(this);
+   }
+   Dmsg1(100, "Clear volhdr vol=%s\n", VolHdr.VolumeName);
+   memset(&VolHdr, 0, sizeof(VolHdr));
+}
+
+
 /*
  * Close the device
  */
@@ -1878,9 +1893,8 @@ void DEVICE::close()
    EndFile = EndBlock = 0;
    openmode = 0;
    Slot = -1;             /* unknown slot */
-   free_volume(this);
+   clear_volhdr();
    memset(&VolCatInfo, 0, sizeof(VolCatInfo));
-   memset(&VolHdr, 0, sizeof(VolHdr));
    if (tid) {
       stop_thread_timer(tid);
       tid = 0;
@@ -2259,6 +2273,18 @@ const char *DEVICE::name() const
    return device->hdr.name;
 }
 
+/* Returns file position on tape or -1 */
+int32_t DEVICE::get_os_tape_file()
+{
+   struct mtget mt_stat;
+
+   if (has_cap(CAP_MTIOCGET) &&
+       tape_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) {
+      return mt_stat.mt_fileno;
+   }
+   return -1;
+}
+
 char *
 dev_vol_name(DEVICE *dev)
 {
@@ -2427,8 +2453,7 @@ void set_os_device_parameters(DCR *dcr)
          dev->clrerror(MTSETBSIZ);
       }
    }
-/* Turn this on later when fully tested */
-#if defined(xxxMTIOCSETEOTMODEL) 
+#if defined(MTIOCSETEOTMODEL) 
    uint32_t neof;
    if (dev->has_cap(CAP_TWOEOF)) {
       neof = 2;