X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fdircmd.c;h=d1ef1d4d306c109cebe00d5b25607b592300dfd5;hb=225546018b76820eec2005e861c7908d0cec9642;hp=f3ce023113d1add4217428b5c879d1fbb9c13fe0;hpb=dd1681a2be75da5d6256cefc8d8ebdbf6c6afed9;p=bacula%2Fbacula diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index f3ce023113..d1ef1d4d30 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2001-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. +*/ /* * This file handles accepting Director Commands * @@ -7,7 +34,7 @@ * 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 + * than dev->r_lock() 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!!!! @@ -19,20 +46,6 @@ * Version $Id$ * */ -/* - Copyright (C) 2001-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - 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 - the file LICENSE for additional details. - - */ #include "bacula.h" #include "stored.h" @@ -49,7 +62,7 @@ extern bool init_done; /* Static variables */ static char derrmsg[] = "3900 Invalid command\n"; static char OKsetdebug[] = "3000 OK setdebug=%d\n"; -static char illegal_cmd[] = "3997 Illegal command for a Director with Monitor directive enabled\n"; +static char invalid_cmd[] = "3997 Invalid command for a Director with Monitor directive enabled.\n"; /* Imported functions */ extern void terminate_child(); @@ -62,6 +75,7 @@ extern bool qstatus_cmd(JCR *jcr); /* Forward referenced functions */ static bool label_cmd(JCR *jcr); +static bool die_cmd(JCR *jcr); static bool relabel_cmd(JCR *jcr); static bool readlabel_cmd(JCR *jcr); static bool release_cmd(JCR *jcr); @@ -94,6 +108,7 @@ static struct s_cmds cmds[] = { {"autochanger", changer_cmd, 0}, {"bootstrap", bootstrap_cmd, 0}, {"cancel", cancel_cmd, 0}, + {".die", die_cmd, 0}, {"label", label_cmd, 0}, /* label a tape */ {"mount", mount_cmd, 0}, {"readlabel", readlabel_cmd, 0}, @@ -135,7 +150,7 @@ void *handle_connection_request(void *arg) int bnet_stat = 0; char name[MAX_NAME_LENGTH]; - if (bnet_recv(bs) <= 0) { + if (bs->recv() <= 0) { Emsg0(M_ERROR, 0, _("Connection request failed.\n")); bnet_close(bs); return NULL; @@ -155,6 +170,7 @@ void *handle_connection_request(void *arg) */ Dmsg1(110, "Conn: %s", bs->msg); if (sscanf(bs->msg, "Hello Start Job %127s", name) == 1) { + Dmsg0(110, "Got a FD connection\n"); handle_filed_connection(bs, name); return NULL; } @@ -162,10 +178,10 @@ void *handle_connection_request(void *arg) /* * This is a connection from the Director, so setup a JCR */ - Dmsg0(110, "Start Dir Job\n"); + Dmsg0(110, "Got a DIR connection\n"); jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */ jcr->dir_bsock = bs; /* save Director bsock */ - jcr->dir_bsock->jcr = jcr; + jcr->dir_bsock->set_jcr(jcr); jcr->dcrs = New(alist(10, not_owned_by_alist)); /* Initialize FD start condition variable */ int errstat = pthread_cond_init(&jcr->job_start_wait, NULL); @@ -187,7 +203,7 @@ void *handle_connection_request(void *arg) for (quit=false; !quit;) { /* Read command */ - if ((bnet_stat = bnet_recv(bs)) <= 0) { + if ((bnet_stat = bs->recv()) <= 0) { break; /* connection terminated */ } Dmsg1(199, "msg); @@ -199,9 +215,9 @@ void *handle_connection_request(void *arg) for (i=0; cmds[i].cmd; i++) { if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) { if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) { - Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd); - bnet_fsend(bs, illegal_cmd); - bnet_sig(bs, BNET_EOD); + Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd); + bnet_fsend(bs, invalid_cmd); + bs->signal(BNET_EOD); break; } Dmsg1(200, "Do command: %s\n", cmds[i].cmd); @@ -226,6 +242,24 @@ bail_out: return NULL; } + +/* + * Force SD to die, and hopefully dump itself. Turned on only + * in development version. + */ +static bool die_cmd(JCR *jcr) +{ +#ifdef DEVELOPER + JCR *djcr = NULL; + int a; + Pmsg0(000, "I have been requested to die ..."); + a = djcr->JobId; /* ref NULL pointer */ +#endif + return 0; +} + + + /* * Set debug level as requested by the Director * @@ -273,12 +307,15 @@ static bool cancel_cmd(JCR *cjcr) /* If thread waiting on mount, wake him */ if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->waiting_for_mount()) { pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol); + Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId); pthread_cond_broadcast(&wait_device_release); } if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->waiting_for_mount()) { pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol); + Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId); pthread_cond_broadcast(&wait_device_release); } + Jmsg(jcr, M_INFO, 0, _("Job %s marked to be canceled.\n"), jcr->Job); bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job); free_jcr(jcr); } @@ -341,7 +378,7 @@ static bool do_label(JCR *jcr, int relabel) dcr = find_device(jcr, dev_name, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->dlock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { Dmsg1(400, "Can %slabel. Device is not open\n", relabel?"re":""); label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); @@ -356,7 +393,7 @@ static bool do_label(JCR *jcr, int relabel) Dmsg0(400, "Can relabel. device not used\n"); label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); } - V(dev->mutex); + dev->dunlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -461,7 +498,7 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, dev->is_dvd()?1:0, newname, dev->print_name()); break; case VOL_NO_MEDIA: - bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror()); + bnet_fsend(dir, _("3914 Failed to label Volume (no media): ERR=%s\n"), dev->bstrerror()); break; default: bnet_fsend(dir, _("3913 Cannot label Volume. " @@ -471,7 +508,7 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, bail_out: if (!dev->is_open()) { - free_volume(dev); + dev->clear_volhdr(); } give_back_device_lock(dev, &hold); return; @@ -605,16 +642,17 @@ static bool mount_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ - Dmsg1(100, "mount cmd blocked=%d\n", dev->dev_blocked); - switch (dev->dev_blocked) { /* device blocked? */ + dev->dlock(); /* Use P to avoid indefinite block */ + Dmsg1(100, "mount cmd blocked=%d\n", dev->blocked()); + switch (dev->blocked()) { /* device blocked? */ case BST_WAITING_FOR_SYSOP: /* Someone is waiting, wake him */ Dmsg0(100, "Waiting for mount. Attempting to wake thread\n"); - dev->dev_blocked = BST_MOUNT; + dev->set_blocked(BST_MOUNT); bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev->print_name()); pthread_cond_broadcast(&dev->wait_next_vol); + Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId); pthread_cond_broadcast(&wait_device_release); break; @@ -628,7 +666,7 @@ static bool mount_cmd(JCR *jcr) if (dev->open(dcr, OPEN_READ_ONLY) < 0) { bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), dev->bstrerror()); - if (dev->dev_blocked == BST_UNMOUNTED) { + if (dev->blocked() == BST_UNMOUNTED) { /* We blocked the device, so unblock it */ Dmsg0(100, "Unmounted. Unblocking device\n"); unblock_device(dev); @@ -636,14 +674,14 @@ static bool mount_cmd(JCR *jcr) break; } read_dev_volume_label(dcr); - if (dev->dev_blocked == BST_UNMOUNTED) { + if (dev->blocked() == BST_UNMOUNTED) { /* We blocked the device, so unblock it */ Dmsg0(100, "Unmounted. Unblocking device\n"); read_label(dcr); /* this should not be necessary */ unblock_device(dev); } else { Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n"); - dev->dev_blocked = BST_MOUNT; + dev->set_blocked(BST_MOUNT); } if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), @@ -654,6 +692,7 @@ static bool mount_cmd(JCR *jcr) dev->print_name()); } pthread_cond_broadcast(&dev->wait_next_vol); + Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId); pthread_cond_broadcast(&wait_device_release); break; @@ -696,7 +735,7 @@ static bool mount_cmd(JCR *jcr) dev->print_name()); } } else if (dev->is_dvd()) { - if (mount_dvd(dev, 1)) { + if (dev->mount(1)) { bnet_fsend(dir, _("3002 Device %s is mounted.\n"), dev->print_name()); } else { @@ -709,10 +748,10 @@ static bool mount_cmd(JCR *jcr) break; default: - bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked); + bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->blocked()); break; } - V(dev->mutex); + dev->dunlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -741,13 +780,13 @@ static bool unmount_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->dlock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { if (!dev->is_busy()) { - unload_autochanger(jcr->dcr, -1); + unload_autochanger(dcr, -1); } if (dev->is_dvd()) { - if (unmount_dvd(dev, 0)) { + if (dev->unmount(0)) { bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev->print_name()); } else { @@ -758,25 +797,26 @@ static bool unmount_cmd(JCR *jcr) bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), dev->print_name()); } - } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) { + } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, - dev->dev_blocked); - if (!unload_autochanger(jcr->dcr, -1)) { + dev->blocked()); + if (!unload_autochanger(dcr, -1)) { + /* ***FIXME**** what is this ???? */ dev->close(); } - if (dev->is_dvd() && !unmount_dvd(dev, 0)) { + if (dev->is_dvd() && !dev->unmount(0)) { bnet_fsend(dir, _("3907 %s"), dev->bstrerror()); } else { - dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP; + dev->set_blocked(BST_UNMOUNTED_WAITING_FOR_SYSOP); bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev->print_name()); } - } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { + } else if (dev->blocked() == BST_DOING_ACQUIRE) { bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_WRITING_LABEL) { + } else if (dev->blocked() == BST_WRITING_LABEL) { bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev->print_name()); @@ -790,19 +830,19 @@ static bool unmount_cmd(JCR *jcr) * we simply do it by hand. Gross, but a solution. */ /* block_device(dev, BST_UNMOUNTED); replace with 2 lines below */ - dev->dev_blocked = BST_UNMOUNTED; + dev->set_blocked(BST_UNMOUNTED); dev->no_wait_id = 0; - if (!unload_autochanger(jcr->dcr, -1)) { + if (!unload_autochanger(dcr, -1)) { dev->close(); } - if (dev->is_dvd() && !unmount_dvd(dev, 0)) { + if (dev->is_dvd() && !dev->unmount(0)) { bnet_fsend(dir, _("3907 %s"), dev->bstrerror()); } else { bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev->print_name()); } } - V(dev->mutex); + dev->dunlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -836,36 +876,46 @@ static bool release_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->dlock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { + if (!dev->is_busy()) { + unload_autochanger(dcr, -1); + } Dmsg0(90, "Device already released\n"); bnet_fsend(dir, _("3921 Device %s already released.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP || - dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) { + } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) { + Dmsg2(90, "%d waiter dev_block=%d.\n", dev->num_waiting, + dev->blocked()); + unload_autochanger(dcr, -1); + bnet_fsend(dir, _("3922 Device %s waiting for sysop.\n"), + dev->print_name()); + + } else if (dev->blocked() == BST_UNMOUNTED_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, - dev->dev_blocked); + dev->blocked()); bnet_fsend(dir, _("3922 Device %s waiting for mount.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { + } else if (dev->blocked() == BST_DOING_ACQUIRE) { bnet_fsend(dir, _("3923 Device %s is busy in acquire.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_WRITING_LABEL) { + } else if (dev->blocked() == BST_WRITING_LABEL) { bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), dev->print_name()); } else if (dev->is_busy()) { send_dir_busy_message(dir, dev); } else { /* device not being used */ - Dmsg0(90, "Device not in use, unmounting\n"); - release_volume(jcr->dcr); + Dmsg0(90, "Device not in use, releaseing\n"); + unload_autochanger(dcr, -1); + release_volume(dcr); bnet_fsend(dir, _("3022 Device %s released.\n"), dev->print_name()); } - V(dev->mutex); + dev->dunlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -917,7 +967,7 @@ static bool changer_cmd(JCR *jcr) dcr = find_device(jcr, devname, -1); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->dlock(); /* Use P to avoid indefinite block */ if (!dev->device->changer_res) { bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev->print_name()); @@ -929,7 +979,7 @@ static bool changer_cmd(JCR *jcr) } else { /* device not being used */ autochanger_cmd(dcr, dir, cmd); } - V(dev->mutex); + dev->dunlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -940,7 +990,7 @@ static bool changer_cmd(JCR *jcr) bnet_fsend(dir, _("3908 Error scanning autocharger drives/list/slots command: %s\n"), jcr->errmsg); } - bnet_sig(dir, BNET_EOD); + dir->signal(BNET_EOD); return true; } @@ -961,7 +1011,7 @@ static bool readlabel_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->dlock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { read_volume_label(jcr, dev, Slot); dev->close(); @@ -973,7 +1023,7 @@ static bool readlabel_cmd(JCR *jcr) } else { /* device not being used */ read_volume_label(jcr, dev, Slot); } - V(dev->mutex); + dev->dunlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -983,7 +1033,7 @@ static bool readlabel_cmd(JCR *jcr) pm_strcpy(jcr->errmsg, dir->msg); bnet_fsend(dir, _("3909 Error scanning readlabel command: %s\n"), jcr->errmsg); } - bnet_sig(dir, BNET_EOD); + dir->signal(BNET_EOD); return true; } @@ -1041,7 +1091,7 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName) static void send_dir_busy_message(BSOCK *dir, DEVICE *dev) { if (dev->is_blocked()) { - switch (dev->dev_blocked) { + switch (dev->blocked()) { case BST_UNMOUNTED: bnet_fsend(dir, _("3931 Device %s is BLOCKED. user unmounted.\n"), dev->print_name());