]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Handle lin_tape end of device with new 'Use Lintape=yes' Device directive
authorEric Bollengier <eric@baculasystems.com>
Mon, 1 Mar 2021 17:58:39 +0000 (18:58 +0100)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:01 +0000 (09:03 +0100)
  Use MTIOCGET = No
  Use lintape = Yes

bacula/src/stored/dev.h
bacula/src/stored/lintape.h [new file with mode: 0644]
bacula/src/stored/stored_conf.c
bacula/src/stored/tape_dev.c
bacula/src/stored/tape_dev.h

index 39e9c4ad02f67654dee0b81e27e185124bee6935..67dd77111f56437dccf25424d14500f88fdd2a6e 100644 (file)
@@ -149,6 +149,7 @@ typedef struct {
 #define CAP_BLOCKCHECKSUM  (1<<23)    /* Create/test block checksum */
 #define CAP_LSEEK          (1<<24)    /* Has lseek function defined i.e. basically File storage */
 #define CAP_SYNCONCLOSE    (1<<25)    /* Need to call fsync() when releasing/closing the device */
+#define CAP_LINTAPE        (1<<26)    /* If has the Lintape interface */
 
 /* Test state */
 #define dev_state(dev, st_state) ((dev)->state & (st_state))
diff --git a/bacula/src/stored/lintape.h b/bacula/src/stored/lintape.h
new file mode 100644 (file)
index 0000000..d50465d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2020 Kern Sibbald
+
+   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.
+
+   This notice must be preserved when any source code is
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
+*/
+
+#ifndef LIN_TAPE_H
+#define LIN_TAPE_H
+
+#include "bacula.h"
+
+/* Interface to request information to a tape drive
+ * Technical information found on IBM web site
+ *   https://www.ibm.com/support/knowledgecenter/STAKKZ/dd_pr_kc/con_a89p4_lnx_sioc_reqsense.html
+ * TODO: May not work SPARC CPU
+ */
+
+#if defined(HAVE_LINUX_OS)
+
+#ifndef SIOC_REQSENSE
+# define SIOC_REQSENSE _IOR('C', 0x02, lintape_request_sense)
+#endif
+
+struct lintape_request_sense {
+   uint8_t  valid           :1,      /* sense data is valid             */
+            err_code        :7;      /* error code                      */
+   uint8_t  segnum;                  /* segment number                  */
+   uint32_t fm                :1,    /* filemark detected               */
+            eom               :1,    /* end of medium                   */
+            ili               :1,    /* incorrect length indicator      */
+            resvd1            :1,    /* reserved                        */
+            key               :4;    /* sense key                       */
+   int32_t  info;                    /* information bytes               */
+   uint8_t  addlen;                  /* additional sense length         */
+   uint32_t cmdinfo;                 /* command specific information    */
+   uint8_t  asc;                     /* additional sense code           */
+   uint8_t  ascq;                    /* additional sense code qualifier */
+   uint8_t  fru;                     /* field replaceable unit code     */
+   uint32_t sksv              :1,    /* sense key specific valid        */
+            cd                :1,    /* control/data                    */
+            resvd2            :2,    /* reserved                        */
+            bpv               :1,    /* bit pointer valid               */
+            sim               :3;    /* system information message      */
+   uint8_t  field[2];                /* field pointer                   */
+   uint8_t vendor[109];              /* vendor specific (padded to 127) */
+};
+
+#endif  // HAVE_LINUX_OS
+
+#endif  // LIN_TAPE_H
index 6065c82ec661074ab08784abe00d996c16134632..8b2b5842e1b2a2abc449b98b87e2949c5c2175dc 100644 (file)
@@ -153,6 +153,7 @@ static RES_ITEM dev_items[] = {
    {"RequiresMount",         store_bit,  ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
    {"OfflineOnUnmount",      store_bit,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
    {"BlockChecksum",         store_bit,  ITEM(res_dev.cap_bits), CAP_BLOCKCHECKSUM, ITEM_DEFAULT, 1},
+   {"UseLintape",            store_bit,  ITEM(res_dev.cap_bits), CAP_LINTAPE, ITEM_DEFAULT, 0},
    {"Enabled",               store_bool, ITEM(res_dev.enabled), 0, ITEM_DEFAULT, 1},
    {"AutoSelect",            store_bool, ITEM(res_dev.autoselect), 0, ITEM_DEFAULT, 1},
    {"ReadOnly",              store_bool, ITEM(res_dev.read_only), 0, ITEM_DEFAULT, 0},
index 7b323cc1a7256ea0ffc5a3d9014f35399662462b..e71af8b8c35feb2673f91c7494e158d37bba9995 100644 (file)
@@ -57,6 +57,7 @@
 
 #include "bacula.h"
 #include "stored.h"
+#include "lintape.h"
 
 #ifndef O_NONBLOCK
 #define O_NONBLOCK 0
@@ -623,6 +624,9 @@ bool tape_dev::fsf(int num)
              */
             } else if (at_eof() && errno == ENOSPC) {
                stat = 0;
+            /* With IBM Lintape, we need to check the Error sense of the device */
+            } else if (at_eof() && errno == EIO && check_lintape_eod()) {
+               stat = 0;
             } else {
                berrno be;
                set_eot();
@@ -1127,3 +1131,84 @@ void tape_dev::term(DCR *dcr)
    delete_alerts();
    DEVICE::term(dcr);
 }
+
+/* Official documentation
+ * https://www.ibm.com/support/pages/node/652827
+ *
+ * TS3310 TApe Library SCSI Reference, look for "REQUEST SENSE"
+ * https://www.ibm.com/support/pages/system/files/support/ssg/ssgdocs.nsf/0/b321b010cdcf56e58525773b0070c925/$FILE/GA32-0476-01.pdf
+ */
+bool tape_dev::check_lintape_eod()
+{
+#ifdef HAVE_LINUX_OS
+   if (has_cap(CAP_LINTAPE)) {
+      int rc;
+      char buf[128];
+      lintape_request_sense sense;
+      memset(&sense, 0, sizeof(sense));
+
+      rc = d_ioctl(m_fd, SIOC_REQSENSE, (char*)&sense);
+      if (rc != 0) {
+         Dmsg0(150, "Unable to perform SIOC_REQSENSE\n");
+         return false;
+      }
+
+      if (chk_dbglvl(150)) {
+         d_msg(__FILE__, __LINE__, 150,
+               "Information Field Valid Bit-------%d\n"
+               "Error Code------------------------0x%02x\n"
+               "Segment Number--------------------0x%02x\n"
+               "filemark Detected Bit-------------%d\n"
+               "End Of Medium Bit-----------------%d\n"
+               "Illegal Length Indicator Bit------%d\n"
+               "Sense Key-------------------------0x%02x\n"
+               "  Information Bytes---------------0x%02x 0x%02x 0x%02x 0x%02x\n"
+               "Additional Sense Length-----------0x%02x\n"
+               "Command Specific Information------0x%02x 0x%02x 0x%02x 0x%02x\n"
+               "Additional Sense Code-------------0x%02x\n"
+               "Additional Sense Code Qualifier---0x%02x\n"
+               "Field Replaceable Unit Code-------0x%02x\n"
+               "Sense Key Specific Valid Bit------%d\n"
+               "  Command Data Block Bit----------%d\n"
+               "  Bit Pointer Valid Bit-----------%d\n"
+               "    System Information Message----0x%02x\n"
+               "  Field Pointer-------------------0x%02x%02x\n"
+               "Vendor----------------------------%s\n",
+               (int)sense.valid,
+               (int)sense.err_code,
+               (int)sense.segnum,
+               (int)sense.fm,
+               (int)sense.eom,
+               (int)sense.ili,
+               (int)sense.key,
+               sense.valid?(int)(sense.info >> 24) :0,
+               sense.valid?(int)(sense.info >> 16) :0,
+               sense.valid?(int)(sense.info >> 8)  :0,
+               sense.valid?(int)(sense.info & 0xFF):0,
+               (int)sense.addlen,
+               (int)(sense.cmdinfo >> 24), (int)(sense.cmdinfo >> 16),
+               (int)(sense.cmdinfo >> 8), (int)(sense.cmdinfo & 0xFF),
+               (int)sense.asc,
+               (int)sense.ascq,
+               (int)sense.fru,
+               (int)sense.sksv,
+               sense.sksv?(int)sense.cd  :0,
+               sense.sksv?(int)sense.bpv :0,
+               (sense.sksv && sense.bpv)?(int)sense.sim :0,
+               sense.sksv?(int)sense.field[0] :0,
+               sense.sksv?(int)sense.field[1] :0,
+               smartdump((char*)sense.vendor, sizeof(sense.vendor),
+                         buf, sizeof(buf), NULL));
+      }
+      if (sense.err_code) {
+         /* The following values are reported to be correct by Mariusz Czulada
+          * on the bacula-devel list in 2007
+          */
+         return sense.key == 0x08 &&
+                sense.asc == 0x00 &&
+                sense.ascq == 0x05;
+      }
+   }
+#endif
+   return false;
+}
index 0a81dfc499ccdc9f319f804341ddb658c8536581..d5c930f35a02a6a7a5f383de8b78c10810c74ffc 100644 (file)
@@ -69,7 +69,7 @@ public:
    void show_tape_alerts(DCR *dcr, alert_list_type type,
       alert_list_which which, alert_cb alert_callback);
    int delete_alerts();
-
+   bool check_lintape_eod();
    alist *alert_list;
 };