*
* 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. In some "safe" cases,
+ * 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
Copyright (C) 2001-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
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., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
*/
extern char my_name[];
extern time_t daemon_start_time;
extern struct s_last_job last_job;
+extern bool init_done;
/* Static variables */
static char derrmsg[] = "3900 Invalid command\n";
static bool unmount_cmd(JCR *jcr);
static bool autochanger_cmd(JCR *sjcr);
static bool do_label(JCR *jcr, int relabel);
-static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name);
+static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
char *newname, char *poolname,
break; /* connection terminated */
}
Dmsg1(199, "<dird: %s\n", bs->msg);
+ /* Ensure that device initialization is complete */
+ while (!init_done) {
+ bmicrosleep(1, 0);
+ }
found = false;
for (i=0; cmds[i].cmd; i++) {
if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
}
}
bail_out:
+ generate_daemon_event(jcr, "JobEnd");
dequeue_messages(jcr); /* send any queued messages */
bnet_sig(bs, BNET_TERMINATE);
free_jcr(jcr);
Dmsg1(10, "setdebug_cmd: %s", dir->msg);
if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) {
- bnet_fsend(dir, "3991 Bad setdebug command: %s\n", dir->msg);
+ bnet_fsend(dir, _("3991 Bad setdebug command: %s\n"), dir->msg);
return 0;
}
debug_level = level;
if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
if (!(jcr=get_jcr_by_full_name(Job))) {
- bnet_fsend(dir, _("3992 Job %s not found.\n"), Job);
+ bnet_fsend(dir, _("3902 Job %s not found.\n"), Job);
} else {
P(jcr->mutex);
oldStatus = jcr->JobStatus;
free_jcr(jcr);
}
} else {
- bnet_fsend(dir, _("3993 Error scanning cancel command.\n"));
+ bnet_fsend(dir, _("3903 Error scanning cancel command.\n"));
}
bnet_sig(dir, BNET_EOD);
return 1;
}
/*
- * Label a tape
+ * Label a Volume
*
*/
static bool label_cmd(JCR *jcr)
DEVICE *dev;
bool ok = false;
int slot;
+ int drive;
newname = get_memory(dir->msglen+1);
oldname = get_memory(dir->msglen+1);
poolname = get_memory(dir->msglen+1);
mtype = get_memory(dir->msglen+1);
if (relabel) {
- if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s MediaType=%127s Slot=%d",
- dev_name.c_str(), oldname, newname, poolname, mtype, &slot) == 6) {
+ if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s "
+ "MediaType=%127s Slot=%d drive=%d",
+ dev_name.c_str(), oldname, newname, poolname, mtype,
+ &slot, &drive) == 7) {
ok = true;
}
} else {
*oldname = 0;
- if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s MediaType=%127s Slot=%d",
- dev_name.c_str(), newname, poolname, mtype, &slot) == 5) {
+ if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s "
+ "MediaType=%127s Slot=%d drive=%d",
+ dev_name.c_str(), newname, poolname, mtype, &slot, &drive) == 6) {
ok = true;
}
}
unbash_spaces(oldname);
unbash_spaces(poolname);
unbash_spaces(mtype);
- dev = find_device(jcr, dev_name);
+ dev = find_device(jcr, dev_name, drive);
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_dev(dev);
+ 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)) {
goto bail_out; /* error */
}
/* See what we have for a Volume */
- if (dev->is_dvd()) {
- label_status = read_dev_volume_label_guess(dcr, 1);
- } else {
- label_status = read_dev_volume_label(dcr);
- }
+ label_status = read_dev_volume_label(dcr);
switch(label_status) {
case VOL_NAME_ERROR:
if (!relabel) {
bnet_fsend(dir, _(
"3920 Cannot label Volume because it is already labeled: \"%s\"\n"),
- dev->VolHdr.VolName);
+ dev->VolHdr.VolumeName);
break;
}
+
/* Relabel request. If oldname matches, continue */
- if (strcmp(oldname, dev->VolHdr.VolName) != 0) {
+ if (strcmp(oldname, dev->VolHdr.VolumeName) != 0) {
bnet_fsend(dir, _("3921 Wrong volume mounted.\n"));
break;
}
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:
}
bail_out:
+ if (!dev->is_open()) {
+ free_volume(dev);
+ }
give_back_device_lock(dev, &hold);
return;
}
dev->clear_labeled(); /* force read of label */
switch (read_dev_volume_label(dcr)) {
case VOL_OK:
- bnet_fsend(dir, _("3001 Mounted Volume: %s\n"), dev->VolHdr.VolName);
+ bnet_fsend(dir, _("3001 Mounted Volume: %s\n"), dev->VolHdr.VolumeName);
ok = true;
break;
default:
return ok;
}
-static DEVICE *find_device(JCR *jcr, POOL_MEM &devname)
+static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive)
{
DEVRES *device;
AUTOCHANGER *changer;
bool found = false;
unbash_spaces(devname);
- LockRes();
foreach_res(device, R_DEVICE) {
/* Find resource, and make sure we were able to open it */
if (fnmatch(device->hdr.name, devname.c_str(), 0) == 0) {
if (!device->dev) {
- device->dev = init_dev(jcr, NULL, device);
+ device->dev = init_dev(jcr, device);
}
if (!device->dev) {
Jmsg(jcr, M_WARNING, 0, _("\n"
foreach_alist(device, changer->device) {
Dmsg1(100, "Try changer device %s\n", device->hdr.name);
if (!device->dev) {
- device->dev = init_dev(jcr, NULL, device);
+ device->dev = init_dev(jcr, device);
}
if (!device->dev) {
Dmsg1(100, "Device %s could not be opened. Skipped\n", devname.c_str());
if (!device->dev->autoselect) {
continue; /* device is not available */
}
- Dmsg1(20, "Found changer device %s\n", device->hdr.name);
- found = true;
- break;
+ if (drive < 0 || drive == (int)device->dev->drive_index) {
+ Dmsg1(20, "Found changer device %s\n", device->hdr.name);
+ found = true;
+ break;
+ }
}
break; /* we found it but could not open a device */
}
if (found) {
jcr->dcr = new_dcr(jcr, device->dev);
- UnlockRes();
jcr->dcr->device = device;
return jcr->dcr->dev;
}
- UnlockRes();
return NULL;
}
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
DCR *dcr;
+ int drive;
- if (sscanf(dir->msg, "mount %127s", devname.c_str()) == 1) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) {
+ dev = find_device(jcr, devname, drive);
dcr = jcr->dcr;
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
case BST_UNMOUNTED_WAITING_FOR_SYSOP:
case BST_UNMOUNTED:
/* We freed the device, so reopen it and wake any waiting threads */
- if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
+ if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
break;
}
if (dev->is_labeled()) {
bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
- dev->print_name(), dev->VolHdr.VolName);
+ dev->print_name(), dev->VolHdr.VolumeName);
} else {
bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
"If this is not a blank tape, try unmounting and remounting the Volume.\n"),
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;
if (dev->is_open()) {
if (dev->is_labeled()) {
bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
- dev->print_name(), dev->VolHdr.VolName);
+ dev->print_name(), dev->VolHdr.VolumeName);
} else {
bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
"If this is not a blank tape, try unmounting and remounting the Volume.\n"),
dev->print_name());
}
- } else {
- if (!dev->is_tape()) {
- /* Nothing to do */
- break;
- }
- if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
+ } else if (dev->is_tape()) {
+ if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
break;
read_label(dcr);
if (dev->is_labeled()) {
bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
- dev->print_name(), dev->VolHdr.VolName);
+ dev->print_name(), dev->VolHdr.VolumeName);
} else {
bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
"If this is not a blank tape, try unmounting and remounting the Volume.\n"),
dev->print_name());
}
+ } else if (dev->is_dvd()) {
+ if (mount_dev(dev, 1)) {
+ bnet_fsend(dir, _("3002 Device %s is mounted.\n"),
+ dev->print_name());
+ } else {
+ bnet_fsend(dir, _("3907 %s"), strerror_dev(dev));
+ }
+ } else { /* must be file */
+ bnet_fsend(dir, _("3906 File device %s is always mounted.\n"),
+ dev->print_name());
}
break;
POOL_MEM devname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
+ int drive;
- if (sscanf(dir->msg, "unmount %127s", devname.c_str()) == 1) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "unmount %127s drive=%d", devname.c_str(), &drive) == 2) {
+ dev = find_device(jcr, devname, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
offline_or_rewind_dev(dev);
- force_close_dev(dev);
+ force_close_device(dev);
dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
bnet_fsend(dir, _("3001 Device %s unmounted.\n"),
dev->print_name());
dev->dev_blocked = BST_UNMOUNTED;
dev->no_wait_id = 0;
offline_or_rewind_dev(dev);
- force_close_dev(dev);
+ force_close_device(dev);
bnet_fsend(dir, _("3002 Device %s unmounted.\n"),
dev->print_name());
}
POOL_MEM devname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
+ int drive;
- if (sscanf(dir->msg, "release %127s", devname.c_str()) == 1) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "release %127s drive=%d", devname.c_str(), &drive) == 2) {
+ dev = find_device(jcr, devname, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
ok = true;
}
if (ok) {
- dev = find_device(jcr, devname);
+ dev = find_device(jcr, devname, -1);
dcr = jcr->dcr;
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_tape()) {
bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"),
dev->print_name());
- } else if (!dev->is_open()) {
- autochanger_cmd(dcr, dir, cmd);
/* Under certain "safe" conditions, we can steal the lock */
- } else if (dev->can_steal_lock()) {
+ } else if (!dev->is_open() || dev->can_steal_lock()) {
autochanger_cmd(dcr, dir, cmd);
- } else if (dev->is_busy()) {
+ } else if (dev->is_busy() || dev->is_blocked()) {
send_dir_busy_message(dir, dev);
} else { /* device not being used */
autochanger_cmd(dcr, dir, cmd);
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
int Slot;
+ int drive;
- if (sscanf(dir->msg, "readlabel %127s Slot=%d", devname.c_str(), &Slot) == 2) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "readlabel %127s Slot=%d drive=%d", devname.c_str(),
+ &Slot, &drive) == 3) {
+ dev = find_device(jcr, devname, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
read_volume_label(jcr, dev, Slot);
- force_close_dev(dev);
+ force_close_device(dev);
/* Under certain "safe" conditions, we can steal the lock */
} else if (dev->can_steal_lock()) {
read_volume_label(jcr, dev, Slot);
- } else if (dev->is_busy()) {
+ } else if (dev->is_busy() || dev->is_blocked()) {
send_dir_busy_message(dir, dev);
} else { /* device not being used */
read_volume_label(jcr, dev, Slot);
switch (read_dev_volume_label(dcr)) {
case VOL_OK:
/* DO NOT add quotes around the Volume name. It is scanned in the DIR */
- bnet_fsend(dir, _("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolName, Slot);
- Dmsg1(100, "Volume: %s\n", dev->VolHdr.VolName);
+ bnet_fsend(dir, _("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolumeName, Slot);
+ Dmsg1(100, "Volume: %s\n", dev->VolHdr.VolumeName);
break;
default:
bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device %s because:\n%s"),
}
/* Ensure that the device is open -- autoload_device() closes it */
- for ( ; !dev->is_open(); ) {
- if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) {
- bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
- dev->print_name(), dev->strerror());
- return false;
- }
+ if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
+ bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
+ dev->print_name(), dev->strerror());
+ return false;
}
return true;
}