+/*
+ 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)
* 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.
dev->errmsg = get_pool_memory(PM_EMSG);
*dev->errmsg = 0;
- if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) {
+ if ((errstat = pthread_mutex_init(&dev->m_mutex, NULL)) != 0) {
berrno be;
dev->dev_errno = errstat;
Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
}
+#ifdef xxx
if ((errstat = rwl_init(&dev->lock)) != 0) {
berrno be;
dev->dev_errno = errstat;
Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
}
+#endif
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;
}
Dmsg0(050, "Rewind after open\n");
mt_com.mt_op = MTREW;
mt_com.mt_count = 1;
- if (ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ /* rewind only if dev is a tape */
+ if (is_tape() && (ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0)) {
berrno be;
dev_errno = errno; /* set error status from rewind */
::close(m_fd);
void DEVICE::block(int why)
{
- lock_device(this);
+ r_dlock(); /* need recursive lock to block */
block_device(this, why);
- V(mutex);
+ r_dunlock();
}
-void DEVICE::unblock()
-{
- P(mutex);
+void DEVICE::unblock(bool locked)
+{
+ if (!locked) {
+ dlock();
+ }
unblock_device(this);
- V(mutex);
+ dunlock();
}
+
const char *DEVICE::print_blocked() const
{
- switch (dev_blocked) {
+ switch (m_blocked) {
case BST_NOT_BLOCKED:
return "BST_NOT_BLOCKED";
case BST_UNMOUNTED:
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;
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;
}
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
{
* 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;
}
* 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 */
}
*/
bool DEVICE::fsf(int num)
{
- struct mtget mt_stat;
+ int32_t os_file;
struct mtop mt_com;
int stat = 0;
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");
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;
/*
void DEVICE::clrerror(int func)
{
const char *msg = NULL;
- struct mtget mt_stat;
char buf[100];
dev_errno = errno; /* save errno */
*/
/* 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
#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
*/
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;
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)
{
free_pool_memory(errmsg);
errmsg = NULL;
}
- pthread_mutex_destroy(&mutex);
+ pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&wait);
pthread_cond_destroy(&wait_next_vol);
pthread_mutex_destroy(&spool_mutex);
- rwl_destroy(&lock);
+// rwl_destroy(&lock);
if (attached_dcrs) {
delete attached_dcrs;
attached_dcrs = NULL;
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;