src/stored/autochanger.c
static bool unload_other_drive(DCR *dcr, int slot, bool writing)
{
   DEVICE *dev = NULL;
   DEVICE *dev_save;
   bool found = false;
   AUTOCHANGER *changer = dcr->dev->device->changer_res;
   DEVRES *device;
   int retries = 0;                /* wait for device retries */
   int loaded;
   int i;

   if (!changer || !changer->device) {
      return false;
   }
   if (changer->device->size() == 1) {
      return true;
   }

   /*
    * We look for the slot number corresponding to the tape
    *   we want in other drives, and if possible, unload
    *   it.
    */
   Dmsg1(dbglvl, "Begin wiffle through devices looking for slot=%d\n", slot);
   /*
    *  foreach_alist(device, changer->device) {
    *
    * The above fails to loop through all devices. It is
    * probably a compiler bug.
    */
   for (i=0; i < changer->device->size(); i++) {
      device = (DEVRES *)changer->device->get(i);
      dev = device->dev;
      if (!dev) {
         Dmsg0(dbglvl, "No dev attached to device\n");
         continue;
      }

      dev_save = dcr->dev;
      dcr->set_dev(dev);
      loaded = get_autochanger_loaded_slot(dcr);
      dcr->set_dev(dev_save);

      if (loaded > 0) {
         Dmsg4(dbglvl, "Want slot=%d, drive=%d loaded=%d dev=%s\n",
            slot, dev->drive_index, loaded, dev->print_name());
         if (loaded == slot) {
            found = true;
            break;
         }
      } else {
         Dmsg4(dbglvl, "After slot=%d drive=%d loaded=%d dev=%s\n",
            slot, dev->drive_index, loaded, dev->print_name());
      }
   }
   Dmsg1(dbglvl, "End wiffle through devices looking for slot=%d\n", slot);
   if (!found) {
      Dmsg1(dbglvl, "Slot=%d not found in another device\n", slot);
      return true;
   } else {
      Dmsg3(dbglvl, "Slot=%d drive=%d found in dev=%s\n", slot, dev->drive_index, dev->print_name());
   }

   /*
    * The Volume we want is on another device.
    * If we want the Volume to read it, and the other device where the
    *   Volume is currently is not open, we simply unload the Volume then
    *   then the subsequent code will load it in the desired drive.
    * If want to write or  the device is open, we attempt to wait for
    *   the Volume to become available.
    */
   if (writing || dev->is_open()) {
      if (dev->is_busy()) {
         Dmsg4(dbglvl, "Vol %s for dev=%s in use dev=%s slot=%d\n",
              dcr->VolumeName, dcr->dev->print_name(),
              dev->print_name(), slot);
      }
      for (int i=0; i < 3; i++) {
         if (dev->is_busy()) {
            Dmsg0(40, "Device is busy. Calling wait_for_device()\n");
            wait_for_device(dcr, retries);
            continue;
         }
         break;
      }
      if (dev->is_busy()) {
         Jmsg(dcr->jcr, M_WARNING, 0, _("Volume \"%s\" wanted on %s is in use by device %s\n"),
              dcr->VolumeName, dcr->dev->print_name(), dev->print_name());
         Dmsg4(dbglvl, "Vol %s for dev=%s is busy dev=%s slot=%d\n",
              dcr->VolumeName, dcr->dev->print_name(), dev->print_name(), dev->get_slot());
         Dmsg2(dbglvl, "num_writ=%d reserv=%d\n", dev->num_writers, dev->num_reserved());
         volume_unused(dcr);
         return false;
      }
   }
   return unload_dev(dcr, dev);
}
/*
 * Unload the slot if mounted in a different drive
 */
Unload the slot if mounted in a different drive
Unload the slot if mounted in a different drive
static bool unload_other_drive(DCR *dcr, int slot, bool writing)
{
   DEVICE *dev = NULL;
   DEVICE *dev_save;
   bool found = false;
   AUTOCHANGER *changer = dcr->dev->device->changer_res;
   DEVRES *device;
   int retries = 0;                
   int loaded;
   int i;
   if (!changer || !changer->device) {
      return false;
   }
   if (changer->device->size() == 1) {
      return true;
   }
   Dmsg1(dbglvl, "Begin wiffle through devices looking for slot=%d\n", slot);
   for (i=0; i < changer->device->size(); i++) {
      device = (DEVRES *)changer->device->get(i);
      dev = device->dev;
      if (!dev) {
         Dmsg0(dbglvl, "No dev attached to device\n");
         continue;
      }
      dev_save = dcr->dev;
      dcr->set_dev(dev);
      loaded = get_autochanger_loaded_slot(dcr);
      dcr->set_dev(dev_save);
      if (loaded > 0) {
         Dmsg4(dbglvl, "Want slot=%d, drive=%d loaded=%d dev=%s\n",
            slot, dev->drive_index, loaded, dev->print_name());
         if (loaded == slot) {
            found = true;
            break;
         }
      } else {
         Dmsg4(dbglvl, "After slot=%d drive=%d loaded=%d dev=%s\n",
            slot, dev->drive_index, loaded, dev->print_name());
      }
   }
   Dmsg1(dbglvl, "End wiffle through devices looking for slot=%d\n", slot);
   if (!found) {
      Dmsg1(dbglvl, "Slot=%d not found in another device\n", slot);
      return true;
   } else {
      Dmsg3(dbglvl, "Slot=%d drive=%d found in dev=%s\n", slot, dev->drive_index, dev->print_name());
   }
   if (writing || dev->is_open()) {
      if (dev->is_busy()) {
         Dmsg4(dbglvl, "Vol %s for dev=%s in use dev=%s slot=%d\n",
              dcr->VolumeName, dcr->dev->print_name(),
              dev->print_name(), slot);
      }
      for (int i=0; i < 3; i++) {
         if (dev->is_busy()) {
            Dmsg0(40, "Device is busy. Calling wait_for_device()\n");
            wait_for_device(dcr, retries);
            continue;
         }
         break;
      }
      if (dev->is_busy()) {
         Jmsg(dcr->jcr, M_WARNING, 0, _("Volume \"%s\" wanted on %s is in use by device %s\n"),
              dcr->VolumeName, dcr->dev->print_name(), dev->print_name());
         Dmsg4(dbglvl, "Vol %s for dev=%s is busy dev=%s slot=%d\n",
              dcr->VolumeName, dcr->dev->print_name(), dev->print_name(), dev->get_slot());
         Dmsg2(dbglvl, "num_writ=%d reserv=%d\n", dev->num_writers, dev->num_reserved());
         volume_unused(dcr);
         return false;
      }
   }
   return unload_dev(dcr, dev);
}
static bool unload_other_drive ( DCR * dcr , int slot , bool writing ) { DEVICE * dev = NULL ; DEVICE * dev_save ; bool found = false ; AUTOCHANGER * changer = dcr -> dev -> device -> changer_res ; DEVRES * device ; int retries = 0 ; int loaded ; int i ; if ( ! changer || ! changer -> device ) { return false ; } if ( changer -> device -> size ( ) == 1 ) { return true ; } Dmsg1 ( dbglvl , " \n " , slot ) ; for ( i = 0 ; i < changer -> device -> size ( ) ; i ++ ) { device = ( DEVRES * ) changer -> device -> get ( i ) ; dev = device -> dev ; if ( ! dev ) { Dmsg0 ( dbglvl , " \n " ) ; continue ; } dev_save = dcr -> dev ; dcr -> set_dev ( dev ) ; loaded = get_autochanger_loaded_slot ( dcr ) ; dcr -> set_dev ( dev_save ) ; if ( loaded > 0 ) { Dmsg4 ( dbglvl , " \n " , slot , dev -> drive_index , loaded , dev -> print_name ( ) ) ; if ( loaded == slot ) { found = true ; break ; } } else { Dmsg4 ( dbglvl , " \n " , slot , dev -> drive_index , loaded , dev -> print_name ( ) ) ; } } Dmsg1 ( dbglvl , " \n " , slot ) ; if ( ! found ) { Dmsg1 ( dbglvl , " \n " , slot ) ; return true ; } else { Dmsg3 ( dbglvl , " \n " , slot , dev -> drive_index , dev -> print_name ( ) ) ; } if ( writing || dev -> is_open ( ) ) { if ( dev -> is_busy ( ) ) { Dmsg4 ( dbglvl , " \n " , dcr -> VolumeName , dcr -> dev -> print_name ( ) , dev -> print_name ( ) , slot ) ; } for ( int i = 0 ; i < 3 ; i ++ ) { if ( dev -> is_busy ( ) ) { Dmsg0 ( 40 , " \n " ) ; wait_for_device ( dcr , retries ) ; continue ; } break ; } if ( dev -> is_busy ( ) ) { Jmsg ( dcr -> jcr , M_WARNING , 0 , _ ( " \" \" \n " ) , dcr -> VolumeName , dcr -> dev -> print_name ( ) , dev -> print_name ( ) ) ; Dmsg4 ( dbglvl , " \n " , dcr -> VolumeName , dcr -> dev -> print_name ( ) , dev -> print_name ( ) , dev -> get_slot ( ) ) ; Dmsg2 ( dbglvl , " \n " , dev -> num_writers , dev -> num_reserved ( ) ) ; volume_unused ( dcr ) ; return false ; } } return unload_dev ( dcr , dev ) ; }
Unload the slot if mounted in a different drive
Unload the slot if mounted in a different drive
/* wait for device retries */ /*
    * We look for the slot number corresponding to the tape
    *   we want in other drives, and if possible, unload
    *   it.
    */ /*
    *  foreach_alist(device, changer->device) {
    *
    * The above fails to loop through all devices. It is
    * probably a compiler bug.
    */ /*
    * The Volume we want is on another device.
    * If we want the Volume to read it, and the other device where the
    *   Volume is currently is not open, we simply unload the Volume then
    *   then the subsequent code will load it in the desired drive.
    * If want to write or  the device is open, we attempt to wait for
    *   the Volume to become available.
    */