]> git.sur5r.net Git - bacula/bacula/commitdiff
- Implement unloading a volume in a different drive if it
authorKern Sibbald <kern@sibbald.com>
Thu, 18 Aug 2005 12:15:10 +0000 (12:15 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 18 Aug 2005 12:15:10 +0000 (12:15 +0000)
  is needed in the current drive.
- Implement search for unused autochanger drive.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2327 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/kes-1.37
bacula/src/stored/autochanger.c
bacula/src/stored/reserve.c

index b7534f6af346e87816ae6e63548e1a1327743f33..8b8ea4dabf2260513251d1da469019e83c8d1a26 100644 (file)
@@ -5,6 +5,9 @@ General:
 
 Changes to 1.37.36:
 18Aug05
+- Implement unloading a volume in a different drive if it
+  is needed in the current drive.
+- Implement search for unused autochanger drive.
 - Implement search for exact Volume in reservation before
   other searches.
 - Fix picking up drive in Dir so that it is not done in
index 97aee96e646e9b57908d069a626ede2043a7294e..cf78a72c1884b3bbe67ec4627db0de80184b88f2 100644 (file)
@@ -27,6 +27,7 @@
 /* Forward referenced functions */
 static void lock_changer(DCR *dcr);
 static void unlock_changer(DCR *dcr);
+static bool unload_other_drive(DCR *dcr, int slot);
 
 /*
  * Called here to do an autoload using the autochanger, if
@@ -75,11 +76,17 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir)
 
       loaded = get_autochanger_loaded_slot(dcr);
 
-      /* If tape we want is not loaded, load it. */
       if (loaded != slot) {
+        /* Unload anything in our drive */
         if (!unload_autochanger(dcr, loaded)) {
            goto bail_out;
         }
+           
+        /* Make sure desired slot is unloaded */
+        if (!unload_other_drive(dcr, slot)) {
+           goto bail_out;
+        }
+
         /*
          * Load the desired cassette
          */
@@ -248,6 +255,88 @@ bool unload_autochanger(DCR *dcr, int loaded)
    return ok;
 }
 
+/*
+ * Unload the slot if mounted in a different drive
+ */
+static bool unload_other_drive(DCR *dcr, int slot)
+{
+   DEVICE *dev, *save_dev;
+   JCR *jcr = dcr->jcr;
+   int save_slot;
+   uint32_t timeout = dcr->device->max_changer_wait;
+   bool ok = true;
+   AUTOCHANGER *changer = dcr->dev->device->changer_res;
+   DEVRES *device;
+   bool found = false;
+
+   if (!changer) {
+      return false;
+   }
+   if (changer->device->size() == 1) {
+      return true;
+   }
+      
+   foreach_alist(device, changer->device) {
+      if (device->dev && device->dev->Slot == slot) {
+        found = true;
+        dev = device->dev;
+        break;
+      }
+   }
+   if (!found) {
+      return true;
+   }
+   if (dev->is_busy()) {
+      Jmsg(jcr, M_WARNING, 0, _("Volume %s is in use by device %s\n"),
+          dcr->VolumeName, dev->print_name());
+      Dmsg2(200, "Volume %s is in use by device %s\n",
+          dcr->VolumeName, dev->print_name());
+      
+      return false;
+   }
+
+   offline_or_rewind_dev(dev);
+   /* We are going to load a new tape, so close the device */
+   force_close_device(dev);
+
+   POOLMEM *changer_cmd = get_pool_memory(PM_FNAME);
+   Jmsg(jcr, M_INFO, 0,
+        _("3307 Issuing autochanger \"unload slot %d, drive %d\" command.\n"),
+       slot, dev->drive_index);
+
+   Dmsg2(200, "Issuing autochanger \"unload slot %d, drive %d\" command.\n",
+       slot, dev->drive_index);
+
+   save_slot = dcr->VolCatInfo.Slot;
+   save_dev = dcr->dev;
+   dcr->dev = dev;
+   dcr->VolCatInfo.Slot = slot;
+   changer_cmd = edit_device_codes(dcr, changer_cmd, 
+                dcr->device->changer_command, "unload");
+   lock_changer(dcr);
+   Dmsg1(200, "Run program=%s\n", changer_cmd);
+   int stat = run_program(changer_cmd, timeout, NULL);
+   unlock_changer(dcr);
+   dcr->VolCatInfo.Slot = save_slot;
+   dcr->dev = save_dev;
+   if (stat != 0) {
+      berrno be;
+      be.set_errno(stat);
+      Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"),
+             slot, dev->drive_index, be.strerror());
+
+      Dmsg3(200, "Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n",
+             slot, dev->drive_index, be.strerror());
+      ok = false;
+   } else {
+      dev->Slot = 0;           /* nothing loaded */
+      Dmsg0(200, "Slot unloaded\n");
+   }
+   free_pool_memory(changer_cmd);
+   return ok;
+}
+
+
 
 /*
  * List the Volumes that are in the autoloader possibly
index 50576144ebfa3c5f4c7c6e6c3921e4041a28a35c..d11a64c9729b8123d776c220167dcaa50287fab4 100644 (file)
@@ -56,6 +56,8 @@ public:
    bool PreferMountedVols;
    bool exact_match;
    bool have_volume;
+   bool do_not_wait;
+   bool available_autochanger;
    char VolumeName[MAX_NAME_LENGTH];
 };
 
@@ -327,25 +329,41 @@ static bool use_storage_cmd(JCR *jcr)
     */
    if (ok) {
       /*
-       * Make up to two passes. The first with PreferMountedVols possibly
-       *   set to true.  In that case, we look only for an available 
-       *   drive with something mounted. If that fails, then we
-       *   do a second pass with PerferMountedVols set false.
+       * First look for an exact match of Volume name as the
+       *  tape may already be mounted.
        */
+      rctx.do_not_wait = true;
       rctx.exact_match = true;
       if ((ok = find_suitable_device_for_job(jcr, rctx))) {
         goto done;
       }
       rctx.exact_match = false;
+
+      /* Now search if an unused autochanger slot is available */
+      rctx.available_autochanger = true;
+      if ((ok = find_suitable_device_for_job(jcr, rctx))) {
+        goto done;
+      }
+      rctx.available_autochanger = false;
+
+
+      /*
+       * Make up to two passes. The first with PreferMountedVols possibly
+       *   set to true.  In that case, we look only for an available 
+       *   drive with something mounted. If that fails, then we
+       *   do a second pass with PerferMountedVols set false.
+       */
       rctx.PreferMountedVols = jcr->PreferMountedVols;
-      ok = find_suitable_device_for_job(jcr, rctx);
-      if (ok) {
+      if (!rctx.PreferMountedVols) {
+        rctx.do_not_wait = false;
+      }
+      if ((ok = find_suitable_device_for_job(jcr, rctx))) {
         goto done;
       }
       if (rctx.PreferMountedVols) {
         rctx.PreferMountedVols = false;
-        ok = find_suitable_device_for_job(jcr, rctx);
-        if (ok) {
+        rctx.do_not_wait = false;
+        if ((ok = find_suitable_device_for_job(jcr, rctx))) {
            goto done;
         }
       }
@@ -432,7 +450,7 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
        *  if there is some device for which we can wait, then
        *  wait and try again until the wait time expires
        */
-      if (!can_wait || !wait_for_device(jcr, first)) {
+      if (rctx.do_not_wait || !can_wait || !wait_for_device(jcr, first)) {
         break;
       }
       first = false;                 /* first wait complete */
@@ -447,7 +465,6 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
    if (dcr) {
       free_dcr(dcr);
    }
-
    return ok;
 }
 
@@ -463,19 +480,21 @@ static int search_res_for_device(RCTX &rctx)
    int stat;
 
    Dmsg1(100, "Search res for %s\n", rctx.device_name);
-   foreach_res(rctx.device, R_DEVICE) {
-      Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
-      /* Find resource, and make sure we were able to open it */
-      if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
-        stat = reserve_device(rctx);
-        if (stat != 1) {
-           return stat;
+   if (!rctx.available_autochanger) {
+      foreach_res(rctx.device, R_DEVICE) {
+         Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
+        /* Find resource, and make sure we were able to open it */
+        if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
+           stat = reserve_device(rctx);
+           if (stat != 1) {
+              return stat;
+           }
+            Dmsg1(220, "Got: %s", dir->msg);
+           bash_spaces(rctx.device_name);
+           ok = bnet_fsend(dir, OK_device, rctx.device_name);
+            Dmsg1(100, ">dird dev: %s", dir->msg);
+           return ok ? 1 : -1;
         }
-         Dmsg1(220, "Got: %s", dir->msg);
-        bash_spaces(rctx.device_name);
-        ok = bnet_fsend(dir, OK_device, rctx.device_name);
-         Dmsg1(100, ">dird dev: %s", dir->msg);
-        return ok ? 1 : -1;
       }
    }
    foreach_res(changer, R_AUTOCHANGER) {
@@ -695,6 +714,15 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx)
       return 0;
    }
 
+   /* Check for unused autochanger drive */
+   if (rctx.available_autochanger && dev->num_writers == 0 &&
+       dev->VolHdr.VolumeName[0] == 0) {
+      /* Device is available but not yet reserved, reserve it for us */
+      bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
+      bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
+      return 1;                      /* reserve drive */
+   }
+
    /*
     * Handle the case that there are no writers
     */