]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/dircmd.c
- Modify DVD code so that it keeps a state flag that indicates
[bacula/bacula] / bacula / src / stored / dircmd.c
index 258773ed20a553999d292a397f25da13f1697b82..398607c3a7fe1f1d50d8a9431f5fa1b646fd2b0c 100644 (file)
@@ -8,7 +8,8 @@
  *
  *    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
@@ -23,7 +24,7 @@
 
    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 ammended with additional clauses defined in the
+   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,
@@ -45,6 +46,7 @@ extern struct s_res resources[];
 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";
@@ -71,7 +73,7 @@ static bool mount_cmd(JCR *jcr);
 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,
@@ -190,6 +192,10 @@ void *handle_connection_request(void *arg)
          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) {
@@ -232,7 +238,7 @@ static bool setdebug_cmd(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;
@@ -281,7 +287,7 @@ static bool cancel_cmd(JCR *cjcr)
 }
 
 /*
- * Label a tape
+ * Label a Volume
  *
  */
 static bool label_cmd(JCR *jcr)
@@ -302,20 +308,24 @@ static bool do_label(JCR *jcr, int relabel)
    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;
       }
    }
@@ -324,19 +334,21 @@ static bool do_label(JCR *jcr, int relabel)
       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_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);
@@ -373,17 +385,15 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
 
    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:
@@ -393,11 +403,12 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
       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;
       }
@@ -405,6 +416,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
          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:
@@ -427,6 +439,9 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
    }
 
 bail_out:
+   if (!dev->is_open()) {
+      free_volume(dev);
+   }
    give_back_device_lock(dev, &hold);
    return;
 }
@@ -451,7 +466,7 @@ static bool read_label(DCR *dcr)
    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:
@@ -464,19 +479,18 @@ static bool read_label(DCR *dcr)
    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"
@@ -496,7 +510,7 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname)
          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());
@@ -508,9 +522,11 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname)
             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 */
       }
@@ -518,11 +534,9 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname)
 
    if (found) {
       jcr->dcr = new_dcr(jcr, device->dev);
-//    UnlockRes();
       jcr->dcr->device = device;
       return jcr->dcr->dev;
    }
-// UnlockRes();
    return NULL;
 }
 
@@ -536,9 +550,10 @@ static bool mount_cmd(JCR *jcr)
    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 */
@@ -557,7 +572,7 @@ static bool mount_cmd(JCR *jcr)
          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;
@@ -574,7 +589,7 @@ static bool mount_cmd(JCR *jcr)
             }
             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"),
@@ -585,7 +600,7 @@ static bool mount_cmd(JCR *jcr)
             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;
 
@@ -598,18 +613,14 @@ static bool mount_cmd(JCR *jcr)
             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;
@@ -617,12 +628,22 @@ static bool mount_cmd(JCR *jcr)
                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;
 
@@ -650,9 +671,10 @@ static bool unmount_cmd(JCR *jcr)
    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()) {
@@ -719,9 +741,10 @@ static bool release_cmd(JCR *jcr)
    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()) {
@@ -787,19 +810,17 @@ static bool autochanger_cmd(JCR *jcr)
       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);
@@ -826,9 +847,11 @@ static bool readlabel_cmd(JCR *jcr)
    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()) {
@@ -837,7 +860,7 @@ static bool readlabel_cmd(JCR *jcr)
          /* 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);
@@ -876,8 +899,8 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int 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"),
@@ -904,12 +927,10 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName)
    }
 
    /* 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;
 }