free_pool_memory(alert);
}
dcr->dev_locked = false; /* set no longer locked */
- unlock_device(dev);
+ dev->unlock();
if (jcr->read_dcr == dcr) {
jcr->read_dcr = NULL;
}
Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
dev->num_writers = 0;
}
- unlock_device(dev);
+ dev->unlock();
}
/* Detach this dcr only if attached */
lock_device(out_dev);
if (out_dev->open(out_jcr->dcr, OPEN_READ_WRITE) < 0) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
- unlock_device(out_dev);
+ out_dev->unlock();
exit(1);
}
- unlock_device(out_dev);
+ out_dev->unlock();
if (!acquire_device_for_append(out_jcr->dcr)) {
free_jcr(in_jcr);
exit(1);
bail_out:
if (!dcr->dev_locked) { /* did we lock dev above? */
- unlock_device(dev); /* unlock it now */
+ dev->unlock(); /* unlock it now */
}
return stat;
}
-/*
- *
- * Bacula Tape manipulation program
- *
- * Has various tape manipulation commands -- mostly for
- * use in determining how tapes really work.
- *
- * Kern Sibbald, April MM
- *
- * Note, this program reads stored.conf, and will only
- * talk to devices that are configured.
- *
- * Version $Id$
- *
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ 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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Bacula Tape manipulation program
+ *
+ * Has various tape manipulation commands -- mostly for
+ * use in determining how tapes really work.
+ *
+ * Kern Sibbald, April MM
+ *
+ * Note, this program reads stored.conf, and will only
+ * talk to devices that are configured.
+ *
+ * Version $Id$
+ *
+ */
#include "bacula.h"
#include "stored.h"
static bool open_the_device()
{
DEV_BLOCK *block;
+ bool ok = true;
block = new_block(dev);
lock_device(dev);
Dmsg1(200, "Opening device %s\n", dcr->VolumeName);
if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
- unlock_device(dev);
- free_block(block);
- return false;
+ ok = false;
+ goto bail_out;
}
Pmsg1(000, _("open device %s: OK\n"), dev->print_name());
dev->set_append(); /* put volume in append mode */
- unlock_device(dev);
+
+bail_out:
+ dev->unlock();
free_block(block);
- return true;
+ return ok;
}
if (!fixup_device_block_write_error(jcr->dcr)) {
Pmsg1(000, _("Cannot fixup device error. %s\n"), dev->bstrerror());
ok = false;
- unlock_device(dev);
+ dev->unlock();
return 0;
}
BlockNumber = 0; /* start counting for second tape */
}
- unlock_device(dev);
+ dev->unlock();
return 1; /* end of tape reached */
}
last_file = this_file;
last_block_num = this_block_num;
- unlock_device(dev);
+ dev->unlock();
return 1;
}
* Kern Sibbald, MM
*
* NOTE!!!! None of these routines are reentrant. You must
- * use lock_device() and unlock_device() at a higher level,
+ * use lock_device() 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
#endif
}
+
+/*
+ * Clear volume header
+ */
+void DEVICE::clear_volhdr()
+{
+ free_volume(this);
+ 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;
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;
#undef DCR /* used by Bacula */
-/* #define NEW_LOCK 1 */
-
-#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
-#define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state))
-#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
-
#define lock_device(d) _lock_device(__FILE__, __LINE__, (d))
#define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d))
#define block_device(d, s) _block_device(__FILE__, __LINE__, (d), s)
void lock() { P(m_mutex); }
void unlock() { V(m_mutex); }
+ void clear_volhdr(); /* in dev.c */
void block(int why); /* in dev.c */
void unblock(); /* in dev.c */
void close(); /* in dev.c */
block_device(dev, BST_DOING_ACQUIRE);
/* Unlock, but leave BLOCKED */
- unlock_device(dev);
+ dev->unlock();
bstrncpy(PrevVolName, dev->VolCatInfo.VolCatName, sizeof(PrevVolName));
bstrncpy(dev->VolHdr.PrevVolumeName, PrevVolName, sizeof(dev->VolHdr.PrevVolumeName));
Dmsg1(129, "open dev %s OK\n", dev->print_name());
bail_out:
- unlock_device(dev);
+ dev->unlock();
return ok;
}
}
-
-#ifdef xxx
-void dev_lock(DEVICE *dev)
-{
- int errstat;
- if ((errstat=rwl_writelock(&dev->lock))) {
- Emsg1(M_ABORT, 0, _("Device write lock failure. ERR=%s\n"), strerror(errstat));
- }
-}
-
-void dev_unlock(DEVICE *dev)
-{
- int errstat;
- if ((errstat=rwl_writeunlock(&dev->lock))) {
- Emsg1(M_ABORT, 0, _("Device write unlock failure. ERR=%s\n"), strerror(errstat));
- }
-}
-#endif
-
/*
* When dev_blocked is set, all threads EXCEPT thread with id no_wait_id
* must wait. The no_wait_id thread is out obtaining a new volume
-/*
- * This file handles accepting Director Commands
- *
- * Most Director commands are handled here, with the
- * exception of the Job command command and subsequent
- * subcommands that are handled
- * in job.c.
- *
- * N.B. in this file, in general we must use P(dev->mutex) rather
- * than lock_device(dev) so that we can examine the blocked
- * state rather than blocking ourselves because a Job
- * thread has the device blocked. In some "safe" cases,
- * we can do things to a blocked device. CAREFUL!!!!
- *
- * File daemon commands are handled in fdcmd.c
- *
- * Kern Sibbald, May MMI
- *
- * Version $Id$
- *
- */
/*
Bacula® - The Network Backup Solution
bail_out:
if (!dev->is_open()) {
- free_volume(dev);
+ dev->clear_volhdr();
}
give_back_device_lock(dev, &hold);
return;
}
Dmsg1(150, "Label type=%d\n", dev->label_type);
if (!dev->rewind(dcr)) {
- free_volume(dev);
- memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
+ dev->clear_volhdr();
Dmsg2(30, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->print_errmsg());
if (!forge_on) {
goto bail_out;
return true;
bail_out:
- free_volume(dev);
- memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
+ dev->clear_volhdr();
dev->clear_append(); /* remove append since this is PRE_LABEL */
return false;
}
ASSERT(dev != NULL);
- free_volume(dev); /* release any old volume */
- memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
+ dev->clear_volhdr(); /* release any old volume */
bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
dev->VolHdr.VerNum = BaculaTapeVersion;
dev->EndBlock = dev->EndFile = 0;
memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
memset(&dcr->VolCatInfo, 0, sizeof(dcr->VolCatInfo));
- free_volume(dev);
- memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
+ dev->clear_volhdr();
/* Force re-read of label */
dev->clear_labeled();
dev->clear_read();
*/
lock_reservations();
P(vol_list_lock);
+ /*
+ * First, if this dcr already is attached to any device,
+ * remove any old volumes attached to this device as they
+ * are no longer used (there should at max be one).
+ */
if (dcr->dev) {
again:
foreach_dlist(vol, vol_list) {
if (vol && vol->dev == dcr->dev) {
vol_list->remove(vol);
if (vol->vol_name) {
+ Dmsg1(100, "new_vol free vol=%s\n", vol->vol_name);
free(vol->vol_name);
}
free(vol);
vol->dev = dcr->dev;
vol->dcr = dcr;
Dmsg2(100, "New Vol=%s dev=%s\n", VolumeName, dcr->dev->print_name());
+ /*
+ * Now try to insert the new Volume
+ */
nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
if (nvol != vol) {
+ Dmsg2(100, "Found vol=%s same dcr=%d\n", nvol->vol_name, dcr==nvol->dcr);
+ /*
+ * At this point, a Volume with this name already is in the
+ * list, free our temp structure
+ */
free(vol->vol_name);
free(vol);
vol = NULL;
if (dcr->dev) {
DEVICE *dev = nvol->dev;
+ /* ***FIXME*** don't we need a mutex here? */
if (!dev->is_busy()) {
Dmsg3(100, "Swap vol=%s from dev=%s to %s\n", VolumeName,
dev->print_name(), dcr->dev->print_name());
nvol->dev = dcr->dev;
dev->VolHdr.VolumeName[0] = 0;
} else {
- Dmsg3(100, "!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
+ Dmsg3(100, "Logic ERROR!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
dev->print_name(), dcr->dev->print_name());
}
}
fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
free(vol.vol_name);
V(vol_list_lock);
+ Dmsg2(100, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
return fvol;
}
{
VOLRES vol, *fvol;
- P(vol_list_lock);
if (dev->VolHdr.VolumeName[0] == 0) {
+ return false;
+ }
+
+ P(vol_list_lock);
+#ifdef xxx
Dmsg1(100, "free_volume: no vol on dev %s\n", dev->print_name());
/*
* Our device has no VolumeName listed, but
}
goto bail_out;
}
+#endif
Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
free(fvol);
}
free(vol.vol_name);
- dev->VolHdr.VolumeName[0] = 0;
-bail_out:
+// dev->VolHdr.VolumeName[0] = 0;
+//bail_out:
V(vol_list_lock);
return fvol != NULL;
}
P(vol_list_lock);
for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
+ /*
+ * Releease this volume, but only if we inserted it (same dcr) and
+ * it is not attached to a device or the Volume in the device is
+ * different.
+ * I wonder if this is right, kes ...
+ */
if (vol->dcr == dcr && (vol->dev == NULL ||
strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
vol_list->remove(vol);
static const char *spool_name = "*spool*";
+/*
+ * NB! This routine locks the device, but if committing will
+ * not unlock it. If not committing, it will be unlocked.
+ */
static bool despool_data(DCR *dcr, bool commit)
{
DEVICE *rdev;
char ec1[50];
Dmsg0(100, "Despooling data\n");
- /* Commit means that the job is done, so we commit, otherwise, we
+ /*
+ * Commit means that the job is done, so we commit, otherwise, we
* are despooling because of user spool size max or some error
* (e.g. filesystem full).
*/
/* If doing a commit, leave the device locked -- unlocked in release_device() */
if (!commit) {
dcr->dev_locked = false;
- unlock_device(dcr->dev);
+ dcr->dev->unlock();
}
return ok;
}
foreach_res(device, R_DEVICE) {
Dmsg1(10, "Term device %s\n", device->device_name);
if (device->dev) {
- free_volume(device->dev);
+ device->dev->clear_volhdr();
device->dev->term();
device->dev = NULL;
} else {
*/
#undef VERSION
-#define VERSION "2.1.6"
-#define BDATE "02 April 2007"
-#define LSMDATE "02Apr07"
+#define VERSION "2.1.7"
+#define BDATE "04 April 2007"
+#define LSMDATE "04Apr07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */