#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))
--- /dev/null
+/*
+ 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
{"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},
#include "bacula.h"
#include "stored.h"
+#include "lintape.h"
#ifndef O_NONBLOCK
#define O_NONBLOCK 0
*/
} 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();
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;
+}
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;
};