/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2011 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
+ modify it under the terms of version three of the GNU Affero General Public
License as published by the Free Software Foundation and included
in the file LICENSE.
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
+ You should have received a copy of the GNU Affero 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.
*
* Split from reserve.c October 2008
*
- * Version $Id: reserve.c 7380 2008-07-14 10:42:59Z kerns $
- *
*/
#include "bacula.h"
#include "stored.h"
-const int dbglvl = 50;
+const int dbglvl = 150;
static dlist *vol_list = NULL;
static brwlock_t vol_list_lock;
static dlist *read_vol_list = NULL;
-static pthread_mutex_t read_vol_lock = PTHREAD_MUTEX_INITIALIZER;
+static bthread_mutex_t read_vol_lock = BTHREAD_MUTEX_PRIORITY(PRIO_SD_READ_VOL_LIST);
/* Forward referenced functions */
static void free_vol_item(VOLRES *vol);
static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName);
+static void debug_list_volumes(const char *imsg);
/*
* For append volumes the key is the VolumeName.
void init_vol_list_lock()
{
int errstat;
- if ((errstat=rwl_init(&vol_list_lock)) != 0) {
+ if ((errstat=rwl_init(&vol_list_lock, PRIO_SD_VOL_LIST)) != 0) {
berrno be;
Emsg1(M_ABORT, 0, _("Unable to initialize volume list lock. ERR=%s\n"),
be.bstrerror(errstat));
rwl_destroy(&vol_list_lock);
}
-
-
/*
* This allows a given thread to recursively call to lock_volumes()
*/
-void _lock_volumes()
+void _lock_volumes(const char *file, int line)
{
int errstat;
vol_list_lock_count++;
- if ((errstat=rwl_writelock(&vol_list_lock)) != 0) {
+ if ((errstat=rwl_writelock_p(&vol_list_lock, file, line)) != 0) {
berrno be;
Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
errstat, be.bstrerror(errstat));
}
}
-void lock_read_volumes()
+void lock_read_volumes(const char *file="**Unknown", int line=0)
{
- P(read_vol_lock);
+ bthread_mutex_lock_p(&read_vol_lock, file, line);
}
void unlock_read_volumes()
{
- V(read_vol_lock);
+ bthread_mutex_unlock(&read_vol_lock);
}
/*
if (fvol) {
Dmsg3(dbglvl, "remove_read_vol=%s JobId=%d found=%d\n", VolumeName, jcr->JobId, fvol!=NULL);
}
- debug_list_volumes("remove_read_volume");
if (fvol) {
read_vol_list->remove(fvol);
free_vol_item(fvol);
debug_nolock = false
};
-void debug_list_volumes(const char *imsg)
+static void debug_list_volumes(const char *imsg)
{
VOLRES *vol;
POOL_MEM msg(PM_MESSAGE);
VOLRES *vol, *nvol;
DEVICE * volatile dev = dcr->dev;
+ if (job_canceled(dcr->jcr)) {
+ return NULL;
+ }
ASSERT(dev != NULL);
Dmsg2(dbglvl, "enter reserve_volume=%s drive=%s\n", VolumeName,
goto get_out;
}
Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name);
- free_volume(dev);
- Dmsg0(50, "set_unload\n");
- dev->set_unload(); /* have to unload current volume */
+ /* If old Volume is still mounted, must unload it */
+ if (strcmp(vol->vol_name, dev->VolHdr.VolumeName) == 0) {
+ Dmsg0(50, "set_unload\n");
+ dev->set_unload(); /* have to unload current volume */
+ }
+ free_volume(dev); /* Release old volume entry */
debug_list_volumes("reserve_vol free");
}
}
nvol->dev = NULL; /* don't zap dev entry */
free_vol_item(nvol);
+ if (vol->dev) {
+ Dmsg2(dbglvl, "dev=%s vol->dev=%s\n", dev->print_name(), vol->dev->print_name());
+ }
+
/*
* Check if we are trying to use the Volume on a different drive
* dev is our device
vol->dev = dev; /* point the Volume at our drive */
dev->vol = vol; /* point our drive at the Volume */
} else {
- Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n",
+ Dmsg5(dbglvl, "==== Swap not possible Vol busy=%d swap=%d vol=%s from dev=%s to %s\n",
+ vol->dev->is_busy(), vol->is_swapping(),
VolumeName, vol->dev->print_name(), dev->print_name());
+ if (vol->is_swapping() && dev->swap_dev) {
+ Dmsg2(dbglvl, "Swap vol=%s dev=%s\n", vol->vol_name, dev->swap_dev->print_name());
+ } else {
+ Dmsg1(dbglvl, "swap_dev=%p\n", dev->swap_dev);
+ }
+ debug_list_volumes("failed swap");
vol = NULL; /* device busy */
goto get_out;
}
VOLRES vol, *fvol;
if (read_vol_list->empty()) {
+ Dmsg0(dbglvl, "find_read_vol: read_vol_list empty.\n");
return NULL;
}
/* Do not lock reservations here */
{
VOLRES *vol;
- if (dev->vol == NULL) {
+ lock_volumes();
+ vol = dev->vol;
+ if (vol == NULL) {
Dmsg1(dbglvl, "No vol on dev %s\n", dev->print_name());
+ unlock_volumes();
return false;
}
- lock_volumes();
- vol = dev->vol;
/* Don't free a volume while it is being swapped */
if (!vol->is_swapping()) {
- Dmsg1(dbglvl, "=== clear in_use vol=%s\n", dev->vol->vol_name);
+ Dmsg1(dbglvl, "=== clear in_use vol=%s\n", vol->vol_name);
dev->vol = NULL;
vol_list->remove(vol);
Dmsg2(dbglvl, "=== remove volume %s dev=%s\n", vol->vol_name, dev->print_name());
free_vol_item(vol);
debug_list_volumes("free_volume");
+ } else {
+ Dmsg1(dbglvl, "=== cannot clear swapping vol=%s\n", vol->vol_name);
}
unlock_volumes();
return true;
{
VOLRES *vol;
- lock_read_volumes();
vol = find_read_volume(VolumeName);
- unlock_read_volumes();
if (vol) {
Dmsg1(100, "Found in read list; cannot write vol=%s\n", VolumeName);
return false;
bool rtn = true;
VOLRES *vol;
+ if (job_canceled(jcr)) {
+ return false;
+ }
lock_volumes();
vol = find_volume(VolumeName);
if (!vol) {