all Volumes from other drives. "update slots all-drives"?
For 1.37:
+- update volume=xxx --- add status=Full
- After rename
04-Jul 13:01 MainSD: Rufus.2005-07-04_01.05.02 Warning: Director wanted Volume
"DLT-13Feb04".
General:
Changes to 1.37.28:
+05Jul05
+- Add code to ensure that reserved but unused volumes
+ are freed.
+- Correct how Volumes are mounted and handled so that the SD
+ does not get stuck if multiple volumes are used (recycling,
+ relabling, ...)
+- Correct bug where you could relabel a volume while it
+ was being acquired -- created chaos.
04Jul05
- Correct seg fault caused by open() calling sequence change.
03Jul05
Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
dbuf_size -= TAPE_BSIZE;
}
- Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
+ Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
if (dbuf_size != start_size) {
Qmsg1(bs->jcr, M_WARNING, 0,
_("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
wid->wd->interval = wait;
register_watchdog(wid->wd);
- Dmsg4(50, "Start bsock timer %p tid=%p for %d secs at %d\n", wid,
+ Dmsg4(950, "Start bsock timer %p tid=%p for %d secs at %d\n", wid,
wid->tid, wait, time(NULL));
return wid;
Dmsg0(900, "stop_bsock_timer called with NULL btimer_id\n");
return;
}
- Dmsg3(50, "Stop bsock timer %p tid=%p at %d.\n", wid, wid->tid, time(NULL));
+ Dmsg3(950, "Stop bsock timer %p tid=%p at %d.\n", wid, wid->tid, time(NULL));
stop_btimer(wid);
}
if (dcr->jcr) {
dcr->jcr->dcr = NULL;
}
+ free_unused_volume(dcr); /* free unused vols attached to this dcr */
free(dcr);
}
* OK if next volume matches current volume
* otherwise mount desired volume obtained from
* dir_find_next_appendable_volume
+ * dev->VolHdr.VolumeName is what is in the drive
+ * dcr->VolumeName is what we pass into the routines, or
+ * get back from the subroutines.
*/
bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
!(dir_find_next_appendable_volume(dcr) &&
strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
- Dmsg0(190, "Wrong tape mounted.\n");
+ Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
+ dcr->VolumeName);
+ /* Release volume reserved by dir_find_next_appendable_volume() */
+ if (dcr->VolumeName[0]) {
+ free_unused_volume(dcr);
+ }
if (dev->num_writers != 0 || dev->reserved_device) {
Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
goto get_out;
if (dev->num_writers == 0) {
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
}
- }
+ }
} else {
/* Not already in append mode, so mount the device */
Dmsg0(190, "Not in append mode, try mount.\n");
*q++ = *p++;
}
*q = 0;
- new_volume(dev->VolHdr.VolumeName, dev);
+ new_volume(dcr, dev->VolHdr.VolumeName);
Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
Mmsg2(jcr->errmsg, "Wanted ANSI Volume \"%s\" got \"%s\"\n", VolName, dev->VolHdr.VolumeName);
return VOL_NAME_ERROR;
}
if (found) {
Dmsg0(400, "dir_find_next_appendable_volume return true\n");
- new_volume(dcr->VolumeName, NULL); /* reserve volume */
+ new_volume(dcr, dcr->VolumeName); /* reserve volume */
return true;
}
+ dcr->VolumeName[0] = 0;
return false;
}
}
/* First pass, we *know* there are no appendable volumes, so no need to call */
if (!first && dir_find_next_appendable_volume(dcr)) { /* get suggested volume */
- unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
- (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
+ unmounted = is_device_unmounted(dev);
/*
* If we have a valid volume name and we are not
* removable media, return now, or if we have a
init_device_wait_timers(dcr);
continue;
}
- unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
- (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
+ unmounted = is_device_unmounted(dev);
if (unmounted) {
continue; /* continue to wait */
}
stat = wait_for_sysop(dcr); ; /* wait on device */
if (dev->poll) {
Dmsg1(400, "Poll timeout in mount vol on device %s\n", dev->print_name());
- Dmsg1(400, "Blocked=%s\n", edit_blocked_reason(dev));
+ Dmsg1(400, "Blocked=%s\n", dev->print_blocked());
return true;
}
bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev) { return NULL; }
+VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
bool free_volume(DEVICE *dev) { return true; }
+void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev) { return NULL; }
+VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
bool free_volume(DEVICE *dev) { return true; }
+void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
block->buf = get_memory(block->buf_len);
empty_block(block);
block->BlockVer = BLOCK_VER; /* default write version */
- Dmsg1(350, "Returning new block=%x\n", block);
+ Dmsg1(650, "Returning new block=%x\n", block);
return block;
}
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
int generate_job_event(JCR *jcr, const char *event) { return 1; }
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev) { return NULL; }
+VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
bool free_volume(DEVICE *dev) { return true; }
+void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
int generate_job_event(JCR *jcr, const char *event) { return 1; }
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev) { return NULL; }
+VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
bool free_volume(DEVICE *dev) { return true; }
+void free_unused_volume(DCR *dcr) { }
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
{
dcr->VolCatInfo.Slot = volnum;
}
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev) { return NULL; }
+VOLRES *new_volume(DCR *dcr, const char *VolumeName) { return NULL; }
bool free_volume(DEVICE *dev) { return true; }
+void free_unused_volume(DCR *dcr) { }
V(mutex);
}
+const char *DEVICE::print_blocked() const
+{
+ switch (dev_blocked) {
+ case BST_NOT_BLOCKED:
+ return "BST_NOT_BLOCKED";
+ case BST_UNMOUNTED:
+ return "BST_UNMOUNTED";
+ case BST_WAITING_FOR_SYSOP:
+ return "BST_WAITING_FOR_SYSOP";
+ case BST_DOING_ACQUIRE:
+ return "BST_DOING_ACQUIRE";
+ case BST_WRITING_LABEL:
+ return "BST_WRITING_LABEL";
+ case BST_UNMOUNTED_WAITING_FOR_SYSOP:
+ return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
+ case BST_MOUNT:
+ return "BST_MOUNT";
+ default:
+ return "unknown blocked code";
+ }
+}
+
/*
* Called to indicate that we have just read an
* EOF from the device.
int is_mounted() const { return state & ST_MOUNTED; }
int have_media() const { return state & ST_MEDIA; }
int is_short_block() const { return state & ST_SHORT; }
- int is_busy() const { return state & ST_READ || num_writers || reserved_device; }
+ int is_busy() const { return (state & ST_READ) || num_writers || reserved_device; }
int at_eof() const { return state & ST_EOF; }
int at_eot() const { return state & ST_EOT; }
int at_weot() const { return state & ST_WEOT; }
void set_blocked(int block) { dev_blocked = block; };
int get_blocked() const { return dev_blocked; };
+ const char *print_blocked() const; /* in dev.c */
+ bool is_blocked() const { return dev_blocked != BST_NOT_BLOCKED; };
};
/* Note, these return int not bool! */
dlink link;
char *vol_name;
DEVICE *dev;
+ DCR *dcr;
};
/*
* Check if the device is blocked or not
*/
-bool device_is_unmounted(DEVICE *dev)
+bool is_device_unmounted(DEVICE *dev)
{
bool stat;
int blocked = dev->dev_blocked;
return stat;
}
-const char *edit_blocked_reason(DEVICE *dev)
-{
- switch (dev->dev_blocked) {
- case BST_NOT_BLOCKED:
- return "not blocked";
- case BST_UNMOUNTED:
- return "user unmounted device";
- case BST_WAITING_FOR_SYSOP:
- return "waiting for operator action";
- case BST_DOING_ACQUIRE:
- return "opening, validating, or positioning tape";
- case BST_WRITING_LABEL:
- return "labeling tape";
- case BST_UNMOUNTED_WAITING_FOR_SYSOP:
- return "closed by user during mount request";
- case BST_MOUNT:
- return "mount request";
- default:
- return "unknown blocked code";
- }
-}
-
void _unlock_device(const char *file, int line, DEVICE *dev)
{
Dmsg2(500, "unlock from %s:%d\n", file, line);
*/
void _unblock_device(const char *file, int line, DEVICE *dev)
{
- Dmsg3(500, "unblock %d from %s:%d\n", dev->dev_blocked, file, line);
+ Dmsg3(500, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
ASSERT(dev->dev_blocked);
dev->set_blocked(BST_NOT_BLOCKED);
dev->no_wait_id = 0;
*/
void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
{
- Dmsg4(500, "steal lock. old=%d new=%d from %s:%d\n", dev->dev_blocked, state,
+
+ Dmsg3(400, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
file, line);
hold->dev_blocked = dev->get_blocked();
hold->dev_prev_blocked = dev->dev_prev_blocked;
hold->no_wait_id = dev->no_wait_id;
dev->set_blocked(state);
+ Dmsg1(400, "steal lock. new=%s\n", dev->print_blocked());
dev->no_wait_id = pthread_self();
V(dev->mutex);
}
*/
void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
{
- Dmsg4(500, "return lock. old=%d new=%d from %s:%d\n",
- dev->dev_blocked, hold->dev_blocked, file, line);
+ Dmsg3(400, "return lock. old=%s from %s:%d\n",
+ dev->print_blocked(), file, line);
P(dev->mutex);
dev->dev_blocked = hold->dev_blocked;
dev->dev_prev_blocked = hold->dev_prev_blocked;
dev->no_wait_id = hold->no_wait_id;
- if (dev->dev_blocked == BST_NOT_BLOCKED && dev->num_waiting > 0) {
+ Dmsg1(400, "return lock. new=%s\n", dev->print_blocked());
+ if (dev->num_waiting > 0) {
+ Dmsg0(400, "Broadcase\n");
pthread_cond_broadcast(&dev->wait); /* wake them up */
}
}
unbash_spaces(mtype);
dev = find_device(jcr, dev_name);
if (dev) {
- /******FIXME**** compare MediaTypes */
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
+ Dmsg0(400, "Can relabel. Device is not open\n");
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
force_close_device(dev);
/* Under certain "safe" conditions, we can steal the lock */
} else if (dev->can_steal_lock()) {
+ Dmsg0(400, "Can relabel. can_steal_lock\n");
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
- } else if (dev->is_busy()) {
+ } else if (dev->is_busy() || dev->is_blocked()) {
send_dir_busy_message(dir, dev);
} else { /* device not being used */
+ Dmsg0(400, "Can relabel. device not used\n");
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
}
V(dev->mutex);
dcr->dev = dev;
steal_device_lock(dev, &hold, BST_WRITING_LABEL);
+ Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name());
/* Note, try_autoload_device() opens the device */
if (!try_autoload_device(jcr, slot, newname)) {
bnet_fsend(dir, _("3922 Cannot relabel an ANSI/IBM labeled Volume.\n"));
break;
}
+ free_volume(dev); /* release old volume name */
/* Fall through wanted! */
case VOL_IO_ERROR:
case VOL_NO_LABEL:
break;
case BST_DOING_ACQUIRE:
- bnet_fsend(dir, _("3001 Device %s is mounted; doing acquire.\n"),
+ bnet_fsend(dir, _("3001 Device %s is doing acquire.\n"),
dev->print_name());
break;
bool want_ansi_label;
Dmsg3(100, "Enter read_volume_label device=%s vol=%s dev_Vol=%s\n",
- dev->name(), VolName, dev->VolHdr.VolumeName);
+ dev->print_name(), VolName, dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:
+ "*NULL*");
if (!dev->is_open()) {
Emsg0(M_ABORT, 0, _("BAD call to read_dev_volume_label\n"));
}
dev->set_labeled(); /* set has Bacula label */
- new_volume(dev->VolHdr.VolumeName, dev);
+ new_volume(dcr, dev->VolHdr.VolumeName);
/* Compare Volume Names */
Dmsg2(30, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
unser_string(dev->VolHdr.ProgDate);
ser_end(rec->data, SER_LENGTH_Volume_Label);
- Dmsg0(90, "ser_read_vol\n");
+ Dmsg0(90, "unser_vol_label\n");
if (debug_level >= 90) {
dump_volume_label(dev);
}
if (dev->is_open()) {
offline_or_rewind_dev(dev);
}
- Dmsg0(190, "===== release_volume ---");
+ Dmsg0(190, "===== release_volume ===\n");
}
/*
void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
void set_new_volume_parameters(DCR *dcr);
void set_new_file_parameters(DCR *dcr);
-bool device_is_unmounted(DEVICE *dev);
+bool is_device_unmounted(DEVICE *dev);
void dev_lock(DEVICE *dev);
void dev_unlock(DEVICE *dev);
-const char *edit_blocked_reason(DEVICE *dev);
/* From dircmd.c */
void *handle_connection_request(void *arg);
/* From reserve.c */
void release_volume(DCR *dcr);
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev);
+VOLRES *new_volume(DCR *dcr, const char *VolumeName);
VOLRES *find_volume(const char *VolumeName);
bool free_volume(DEVICE *dev);
+void free_unused_volume(DCR *dcr);
void create_volume_list();
void free_volume_list();
void list_volumes(BSOCK *user);
* Return: VOLRES entry on success
* NULL if the Volume is already in the list
*/
-VOLRES *new_volume(const char *VolumeName, DEVICE *dev)
+VOLRES *new_volume(DCR *dcr, const char *VolumeName)
{
VOLRES *vol, *nvol;
vol = (VOLRES *)malloc(sizeof(VOLRES));
memset(vol, 0, sizeof(VOLRES));
vol->vol_name = bstrdup(VolumeName);
- vol->dev = dev;
+ vol->dev = dcr->dev;
+ vol->dcr = dcr;
P(vol_list_lock);
nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
V(vol_list_lock);
if (nvol != vol) {
free(vol->vol_name);
free(vol);
- if (dev) {
- nvol->dev = dev;
+ if (dcr->dev) {
+ nvol->dev = dcr->dev;
}
return NULL;
}
return fvol != NULL;
}
+/* Free volume reserved by this dcr but not attached to a dev */
+void free_unused_volume(DCR *dcr)
+{
+ VOLRES *vol;
+ P(vol_list_lock);
+ for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
+ if (vol->dcr == dcr && (vol->dev == NULL ||
+ strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
+ vol_list->remove(vol);
+ free(vol->vol_name);
+ free(vol);
+ break;
+ }
+ }
+ V(vol_list_lock);
+}
+
/*
* List Volumes -- this should be moved to status.c
*/
return;
}
for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
- Dmsg1(000, "Unreleased Volume=%s\n", vol->vol_name);
+ Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
+ vol->dcr, vol->dev);
}
delete vol_list;
vol_list = NULL;
dev->block(BST_DOING_ACQUIRE);
- if (device_is_unmounted(dev)) {
+ if (is_device_unmounted(dev)) {
Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
dev->print_name());
goto bail_out;
}
- if (device_is_unmounted(dev)) {
+ if (is_device_unmounted(dev)) {
Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
Dmsg1(100, "%s", jcr->errmsg);
goto bail_out;
JCR *jcr = dcr->jcr;
P(dev->mutex);
- unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
- (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
+ Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked());
+ unmounted = is_device_unmounted(dev);
dev->poll = false;
/*
}
if (!unmounted) {
+ Dmsg1(400, "blocked=%s\n", dev->print_blocked());
dev->dev_prev_blocked = dev->dev_blocked;
dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */
}
start = time(NULL);
/* Wait required time */
stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout);
- Dmsg1(400, "Wokeup from sleep on device stat=%d\n", stat);
+ Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
+ dev->print_blocked());
now = time(NULL);
dev->rem_wait_sec -= (now - start);
/*
* Check if user unmounted the device while we were waiting
*/
- unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
- (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
+ unmounted = is_device_unmounted(dev);
if (stat != ETIMEDOUT) { /* we blocked the device */
break; /* on error return */
if (!unmounted && dev->vol_poll_interval &&
(now - first_start >= dev->vol_poll_interval)) {
- Dmsg1(400, "In wait blocked=%s\n", edit_blocked_reason(dev));
+ Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked());
dev->poll = true; /* returning a poll event */
break;
}
/*
* Check if user mounted the device while we were waiting
*/
- if (dev->dev_blocked == BST_MOUNT) { /* mount request ? */
+ if (dev->get_blocked() == BST_MOUNT) { /* mount request ? */
stat = 0;
break;
}
if (!unmounted) {
dev->set_blocked(dev->dev_prev_blocked); /* restore entry state */
+ Dmsg1(400, "set %s\n", dev->print_blocked());
}
+ Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked());
V(dev->mutex);
return stat;
}
/* */
#undef VERSION
#define VERSION "1.37.28"
-#define BDATE "04 July 2005"
-#define LSMDATE "04Jul05"
+#define BDATE "05 July 2005"
+#define LSMDATE "05Jul05"
/* Debug flags */
#undef DEBUG