]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/reserve.c
Second cut of drive switching during backup
[bacula/bacula] / bacula / src / stored / reserve.c
index 9c7960e684cfe06fe5b5afdc8c527ef1d69ffaca..1aafd357f047cf937c00ae1ef08d333a6d7472bc 100644 (file)
@@ -53,6 +53,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
 static bool use_storage_cmd(JCR *jcr);
 static void queue_reserve_message(JCR *jcr);
 static void pop_reserve_messages(JCR *jcr);
+void switch_device(DCR *dcr, DEVICE *dev);
 
 /* Requests from the Director daemon */
 static char use_storage[]  = "use storage=%127s media_type=%127s "
@@ -310,7 +311,7 @@ static void free_vol_item(VOLRES *vol)
 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
 {
    VOLRES *vol, *nvol;
-   DEVICE *dev = dcr->dev;
+   DEVICE * volatile dev = dcr->dev;
 
    ASSERT(dev != NULL);
 
@@ -337,8 +338,15 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
        */
       if (strcmp(vol->vol_name, VolumeName) == 0) {
          Dmsg1(dbglvl, "=== OK, vol=%s on device. set not released.\n", VolumeName);
+         vol->released = false;         /* retake vol if released previously */
          goto get_out;                  /* Volume already on this device */
       } else {
+         /* Don't release a volume if it is in use */
+         if (!vol->released) {
+            Dmsg1(dbglvl, "Cannot free vol=%s. It is not released.\n", vol->vol_name);
+            vol = NULL;                  /* vol in use */
+            goto get_out;
+         }
          Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name);
          unload_autochanger(dcr, -1);   /* unload the volume */
          free_volume(dev);
@@ -372,6 +380,9 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
       /* Check if we are trying to use the Volume on a different drive */
       if (dev != vol->dev) {
          /* Caller wants to switch Volume to another device */
+         switch_device(dcr, vol->dev);
+         dev = vol->dev;
+#ifdef xxx
          if (!vol->dev->is_busy()) {
             /* OK to move it -- I'm not sure this will work */
             Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
@@ -382,11 +393,12 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
             dev->vol = vol;               /* point dev at vol */
             dev->VolHdr.VolumeName[0] = 0;
          } else {
-            Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n", 
+            Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
             vol = NULL;                /* device busy */
             goto get_out;
          }
+#endif
       }
    }
    dev->vol = vol;
@@ -423,7 +435,7 @@ void switch_device(DCR *dcr, DEVICE *dev)
    dcr->VolCatInfo.Slot = save_dcr.VolCatInfo.Slot;
    bstrncpy(dcr->pool_name, save_dcr.pool_name, sizeof(dcr->pool_name));
    bstrncpy(dcr->pool_type, save_dcr.pool_type, sizeof(dcr->pool_type));
-   bstrncpy(dcr->dev_name, save_dcr.dev_name, sizeof(dcr->dev_name));
+   bstrncpy(dcr->dev_name, dev->dev_name, sizeof(dcr->dev_name));
 
    dev->reserved_device++;
    dcr->reserved_device = true;
@@ -471,9 +483,10 @@ void unreserve_device(DCR *dcr)
          Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
          dev->num_writers = 0;
       }
+      if (dev->reserved_device == 0 && dev->num_writers == 0) {
+         volume_unused(dcr);
+      }
    }
-
-   volume_unused(dcr);
 }
 
 /*  
@@ -496,11 +509,13 @@ bool volume_unused(DCR *dcr)
       return false;
    }
 
+#ifdef xxx
    if (dev->is_busy()) {
       Dmsg1(dbglvl, "vol_unused: busy on %s\n", dev->print_name());
       debug_list_volumes("dev busy cannot unreserve_volume");
       return false;
    }
+#endif
 #ifdef xxx
    if (dev->num_writers > 0 || dev->reserved_device > 0) {
       ASSERT(0);
@@ -516,7 +531,7 @@ bool volume_unused(DCR *dcr)
    Dmsg3(dbglvl, "=== mark released vol=%s num_writers=%d reserved=%d\n",
       dev->vol->vol_name, dev->num_writers, dev->reserved_device);
    dev->vol->released = true;
-   if (dev->is_tape() || dev->is_autochanger()) {
+   if (dev->is_tape()) { // || dev->is_autochanger()) {
       return true;
    } else {
       /*
@@ -1142,7 +1157,14 @@ static int reserve_device(RCTX &rctx)
                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
       Dmsg3(dbglvl, "Vol=%s num_writers=%d, have_vol=%d\n", 
          rctx.VolumeName, dcr->dev->num_writers, rctx.have_volume);
-      if (!rctx.have_volume) {
+      if (rctx.have_volume) {
+         if (reserve_volume(dcr, rctx.VolumeName)) {
+            Dmsg1(dbglvl, "Reserved vol=%s\n", rctx.VolumeName);
+         } else {
+            Dmsg1(dbglvl, "Could not reserve vol=%s\n", rctx.VolumeName);
+            goto bail_out;
+         }
+      } else {
          dcr->any_volume = true;
          Dmsg0(dbglvl, "no vol, call find_next_appendable_vol.\n");
          if (dir_find_next_appendable_volume(dcr)) {
@@ -1151,6 +1173,8 @@ static int reserve_device(RCTX &rctx)
             Dmsg1(dbglvl, "looking for Volume=%s\n", rctx.VolumeName);
          } else {
             Dmsg0(dbglvl, "No next volume found\n");
+            rctx.have_volume = false;
+            rctx.VolumeName[0] = 0;
             /*
              * If there is at least one volume that is valid and in use,
              *   but we get here, check if we are running with prefers
@@ -1161,13 +1185,13 @@ static int reserve_device(RCTX &rctx)
             if (dcr->volume_in_use && !rctx.PreferMountedVols) {
                rctx.PreferMountedVols = true;
                if (dcr->VolumeName[0]) {
-                  volume_unused(dcr);
+                  unreserve_device(dcr);
                }
                goto bail_out;
             }
             /*
              * Note. Under some circumstances, the Director can hand us
-             *  a Volume name that is no the same as the one on the current
+             *  a Volume name that is not the same as the one on the current
              *  drive, and in that case, the call above to find the next
              *  volume will fail because in attempting to reserve the Volume
              *  the code will realize that we already have a tape mounted,
@@ -1178,12 +1202,10 @@ static int reserve_device(RCTX &rctx)
              */
             if (dcr->dev->num_writers != 0) {
                if (dcr->VolumeName[0]) {
-                  volume_unused(dcr);
+                  unreserve_device(dcr);
                }
                goto bail_out;
             }
-            rctx.have_volume = false;
-            rctx.VolumeName[0] = 0;
          }
       }
    } else {
@@ -1214,7 +1236,6 @@ static int reserve_device(RCTX &rctx)
 bail_out:
    rctx.have_volume = false;
    rctx.VolumeName[0] = 0;
-// free_dcr(dcr);
    Dmsg0(dbglvl, "Not OK.\n");
    return 0;
 }