]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/dircmd.c
Keep correct errno when FSF fails
[bacula/bacula] / bacula / src / stored / dircmd.c
index fb8312c12847c839d290e75fa232d4a5008bc052..d1ef1d4d306c109cebe00d5b25607b592300dfd5 100644 (file)
@@ -1,28 +1,7 @@
-/*
- *  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
 
-   Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
+   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.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ *  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 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!!!!
+ *
+ *    File daemon commands are handled in fdcmd.c
+ *
+ *     Kern Sibbald, May MMI
+ *
+ *   Version $Id$
+ *
+ */
 
 #include "bacula.h"
 #include "stored.h"
@@ -62,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();
@@ -75,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);
@@ -107,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},
@@ -148,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;
@@ -168,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;
    }
@@ -175,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);
@@ -200,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, "<dird: %s\n", bs->msg);
@@ -212,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);
@@ -239,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
  *
@@ -286,13 +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 marked to be canceled.\n"));
+         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);
       }
@@ -355,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);
@@ -370,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 {
@@ -475,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. "
@@ -485,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;
@@ -619,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;
 
@@ -642,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);
@@ -650,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"),
@@ -668,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;
 
@@ -723,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 {
@@ -755,7 +780,7 @@ 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(dcr, -1);          
@@ -772,9 +797,9 @@ 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);
+               dev->blocked());
             if (!unload_autochanger(dcr, -1)) {
                /* ***FIXME**** what is this ????  */
                dev->close();
@@ -782,16 +807,16 @@ static bool unmount_cmd(JCR *jcr)
             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());
 
@@ -805,7 +830,7 @@ 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(dcr, -1)) {
                dev->close();
@@ -817,7 +842,7 @@ static bool unmount_cmd(JCR *jcr)
                   dev->print_name());
             }
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -851,7 +876,7 @@ 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);
@@ -860,24 +885,24 @@ static bool release_cmd(JCR *jcr)
             bnet_fsend(dir, _("3921 Device %s already released.\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.\n", dev->num_waiting,
-               dev->dev_blocked);
+               dev->blocked());
             unload_autochanger(dcr, -1);
             bnet_fsend(dir, _("3922 Device %s waiting for sysop.\n"), 
                dev->print_name());
 
-         } else if (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
+         } 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());
 
@@ -890,7 +915,7 @@ static bool release_cmd(JCR *jcr)
             bnet_fsend(dir, _("3022 Device %s released.\n"), 
                dev->print_name());
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -942,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());
@@ -954,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 {
@@ -965,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;
 }
 
@@ -986,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();
@@ -998,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 {
@@ -1008,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;
 }
 
@@ -1066,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());