]> git.sur5r.net Git - bacula/bacula/commitdiff
- Simplify code in askdir.c that waits for creating an appendable
authorKern Sibbald <kern@sibbald.com>
Thu, 22 Dec 2005 21:37:01 +0000 (21:37 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 22 Dec 2005 21:37:01 +0000 (21:37 +0000)
  volume so that it can handle multiple returns from the wait
  code.
- Modify the wait code to permit multiple returns.
- Return a zero when autochanger drives is called and
  it is not an autochanger.
- Make rewind_dev() a method taking a DCR as an argument.
  This permits closing and reopening the drive if the
  rewind fails as happens if the drive was loaded while the
  file descriptor was open. This refreshes the file descriptor.
- Remove the ST_OPENED flag and always rely on fd < 0 for knowing
  if the device is open or not.  This should eliminate
  Arnos problem.
- Return error if reserve cannot find at least one suitable device.
- Make wait_for_sysop() return correct state information.
- Fix Win32 state file problem. write was not using compat
  code. This should fix bug #500.

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

13 files changed:
bacula/kes-1.38
bacula/kes-1.39
bacula/src/stored/askdir.c
bacula/src/stored/autochanger.c
bacula/src/stored/btape.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/reserve.c
bacula/src/stored/wait.c

index 068af6f153d9bfb6842d79c63c602c4aeecac21f..2f34e27e09c328f691efa79326b6a7a4ba41455d 100644 (file)
@@ -4,10 +4,28 @@
 General:
 
 Changes to 1.38.3:
-20Dec05
+22Dec05
+- Simplify code in askdir.c that waits for creating an appendable
+  volume so that it can handle multiple returns from the wait
+  code.
+- Modify the wait code to permit multiple returns.
+- Return a zero when "autochanger drives" is called and
+  it is not an autochanger.
+- Make rewind_dev() a method taking a DCR as an argument.
+  This permits closing and reopening the drive if the
+  rewind fails as happens if the drive was loaded while the
+  file descriptor was open. This refreshes the file descriptor.
+- Remove the ST_OPENED flag and always rely on fd < 0 for knowing
+  if the device is open or not.  This should eliminate
+  Arnos problem.
+- Return error if reserve cannot find at least one suitable device.
+- Make wait_for_sysop() return correct state information.
+- Fix Win32 state file problem. write was not using compat
+  code. This should fix bug #500.
+21Dec05
 - Modify gui on command to set only GUI mode and not batch.
 - Modify .messages command to always print messages regardless
-  of the mode.
+  of the mode.                
 - If GUI mode is on, suppress automatic printing of 
   You have messages. 
 - Delete old bnet packet code.
index 0584dc246d78de42af7285f29178ba3862e08b23..ab6b2c0e4a43ad1170e88fbf7810f7ce83b1d2a6 100644 (file)
@@ -4,7 +4,25 @@
 General:
 
 Changes to 1.39.3:
-20Dec05
+22Dec05
+- Simplify code in askdir.c that waits for creating an appendable
+  volume so that it can handle multiple returns from the wait
+  code.
+- Modify the wait code to permit multiple returns.
+- Return a zero when "autochanger drives" is called and
+  it is not an autochanger.
+- Make rewind_dev() a method taking a DCR as an argument.
+  This permits closing and reopening the drive if the
+  rewind fails as happens if the drive was loaded while the
+  file descriptor was open. This refreshes the file descriptor.
+- Remove the ST_OPENED flag and always rely on fd < 0 for knowing
+  if the device is open or not.  This should eliminate
+  Arnos problem.
+- Return error if reserve cannot find at least one suitable device.
+- Make wait_for_sysop() return correct state information.
+- Fix Win32 state file problem. write was not using compat
+  code. This should fix bug #500.
+21Dec05
 - Modify gui on command to set only GUI mode and not batch.
 - Modify .messages command to always print messages regardless
   of the mode.
index 09e05e98e9d59b07a1fa5bae2386a21ae148f62d..b5b4c106b3caed6da2dcbf791c4a33136941e483 100644 (file)
@@ -174,8 +174,8 @@ static bool do_get_volume_info(DCR *dcr)
                &vol.EndFile, &vol.EndBlock, &vol.VolCatParts,
                &vol.LabelType);
     if (n != 21) {
-       Dmsg2(100, "Bad response from Dir fields=%d: %s\n", n, dir->msg);
-       Mmsg(jcr->errmsg, _("Error getting Volume info: %s\n"), dir->msg);
+       Dmsg2(100, "Bad response from Dir fields=%d: %s", n, dir->msg);
+       Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg);
        return false;
     }
     vol.InChanger = InChanger;        /* bool in structure */
@@ -209,8 +209,8 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
     bnet_fsend(dir, Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
        writing==GET_VOL_INFO_FOR_WRITE?1:0);
     Dmsg1(100, ">dird: %s", dir->msg);
-    bool OK = do_get_volume_info(dcr);
-    return OK;
+    bool ok = do_get_volume_info(dcr);
+    return ok;
 }
 
 /*
@@ -240,8 +240,8 @@ bool dir_find_next_appendable_volume(DCR *dcr)
        unbash_spaces(dcr->media_type);
        unbash_spaces(dcr->pool_name);
        Dmsg1(100, ">dird: %s", dir->msg);
-       bool OK = do_get_volume_info(dcr);
-       if (OK) {
+       bool ok = do_get_volume_info(dcr);
+       if (ok) {
           if (dcr->any_volume || !is_volume_in_use(dcr)) {
              found = true;
              break;
@@ -409,12 +409,10 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec)
  */
 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
 {
-   int stat = 0, jstat;
-   bool unmounted;
-   bool first = true;
+   int stat = W_TIMEOUT;
    DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
-   bool OK = false;
+   bool got_vol = false;
 
    Dmsg0(400, "enter dir_ask_sysop_to_create_appendable_volume\n");
    ASSERT(dev->dev_blocked);
@@ -426,38 +424,13 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
          Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
          return false;
       }
-      /* First pass, we *know* there are no appendable volumes, so no need to call */
-      if (!first) {
-         P(dev->mutex);
-         OK = dir_find_next_appendable_volume(dcr);   /* get suggested volume */
-         V(dev->mutex);
-      }
-      if (!first && OK) {
-         unmounted = is_device_unmounted(dev);
-         /*
-          * If we have a valid volume name and we are not
-          *   removable media, return now, or if we have a
-          *   Slot for an autochanger, otherwise wait
-          *   for the operator to mount the media.
-          */
-         if (!unmounted && ((dcr->VolumeName[0] && !dev_cap(dev, CAP_REM) &&
-                dev_cap(dev, CAP_LABEL)) ||
-                 (dcr->VolumeName[0] && dcr->VolCatInfo.Slot))) {
-            Dmsg0(400, "Return 1 from mount without wait.\n");
-            return true;
-         }
-         jstat = JS_WaitMount;
-         if (!dev->poll) {
-            Jmsg(jcr, M_MOUNT, 0, _(
-"Please mount Volume \"%s\" on Storage Device %s for Job %s\n"
-"Use \"mount\" command to release Job.\n"),
-              dcr->VolumeName, dev->print_name(), jcr->Job);
-            Dmsg3(400, "Mount %s on %s for Job %s\n",
-                  dcr->VolumeName, dcr->dev_name, jcr->Job);
-         }
+      P(dev->mutex);
+      got_vol = dir_find_next_appendable_volume(dcr);   /* get suggested volume */
+      V(dev->mutex);
+      if (got_vol) {
+         return true;
       } else {
-         jstat = JS_WaitMedia;
-         if (!dev->poll) {
+         if (stat == W_TIMEOUT || stat == W_MOUNT) {
             Jmsg(jcr, M_MOUNT, 0, _(
 "Job %s waiting. Cannot find any appendable volumes.\n"
 "Please use the \"label\"  command to create a new Volume for:\n"
@@ -470,18 +443,18 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
                dcr->pool_name);
          }
       }
-      first = false;
 
-      jcr->JobStatus = jstat;
+      jcr->JobStatus = JS_WaitMedia;
       dir_send_job_status(jcr);
 
       stat = wait_for_sysop(dcr);
+      Dmsg1(100, "Back from wait_for_sysop stat=%d\n", stat);
       if (dev->poll) {
          Dmsg1(100, "Poll timeout in create append vol on device %s\n", dev->print_name());
          continue;
       }
 
-      if (stat == ETIMEDOUT) {
+      if (stat == W_TIMEOUT) {
          if (!double_dev_wait_time(dev)) {
             Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device %s for Job %s\n"),
                dev->print_name(), jcr->Job);
@@ -491,43 +464,13 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
          }
          continue;
       }
-      if (stat == EINVAL) {
+      if (stat == W_ERROR) {
          berrno be;
-         Mmsg2(dev->errmsg, _("pthread error in mount_next_volume stat=%d ERR=%s\n"),
-               stat, be.strerror(stat));
+         Mmsg0(dev->errmsg, _("pthread error in mount_next_volume.\n"));
          Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
          return false;
       }
-      if (stat != 0) {
-         berrno be;
-         Jmsg(jcr, M_WARNING, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
-            be.strerror(stat));
-      }
       Dmsg1(100, "Someone woke me for device %s\n", dev->print_name());
-
-      /* If no VolumeName, and cannot get one, try again */
-      P(dev->mutex);
-      if (dcr->VolumeName[0] == 0 && !job_canceled(jcr) &&
-          !dir_find_next_appendable_volume(dcr)) {
-         V(dev->mutex);
-         Jmsg(jcr, M_MOUNT, 0, _(
-"Someone woke me up, but I cannot find any appendable\n"
-"volumes for Job=%s.\n"), jcr->Job);
-         /* Restart wait counters after user interaction */
-         init_device_wait_timers(dcr);
-         continue;
-      }
-      V(dev->mutex);
-      unmounted = is_device_unmounted(dev);
-      if (unmounted) {
-         Dmsg0(400, "Device is unmounted. Must wait.\n");
-         continue;                    /* continue to wait */
-      }
-
-      /*
-       * Device mounted, we have a volume, break and return
-       */
-      break;
    }
    set_jcr_job_status(jcr, JS_Running);
    dir_send_job_status(jcr);
@@ -549,7 +492,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
  */
 bool dir_ask_sysop_to_mount_volume(DCR *dcr)
 {
-   int stat = 0;
+   int stat = W_TIMEOUT;
    DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
 
@@ -569,7 +512,13 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr)
       if (dev->is_dvd()) {   
          unmount_dev(dev, 0);
       }
-      if (!dev->poll) {
+      
+      /*
+       * If we are not polling, and the wait timeout or the
+       *   user explicitly did a mount, send him the message.
+       *   Otherwise skip it.
+       */
+      if (!dev->poll && (stat == W_TIMEOUT || stat == W_MOUNT)) {
          Jmsg(jcr, M_MOUNT, 0, _("Please mount Volume \"%s\" on Storage Device %s for Job %s\n"),
               dcr->VolumeName, dev->print_name(), jcr->Job);
          Dmsg3(400, "Mount \"%s\" on device \"%s\" for Job %s\n",
@@ -579,14 +528,15 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr)
       jcr->JobStatus = JS_WaitMount;
       dir_send_job_status(jcr);
 
-      stat = wait_for_sysop(dcr);    ;     /* wait on device */
+      stat = wait_for_sysop(dcr);          /* wait on device */
+      Dmsg1(100, "Back from wait_for_sysop stat=%d\n", stat);
       if (dev->poll) {
          Dmsg1(400, "Poll timeout in mount vol on device %s\n", dev->print_name());
          Dmsg1(400, "Blocked=%s\n", dev->print_blocked());
          return true;
       }
 
-      if (stat == ETIMEDOUT) {
+      if (stat == W_TIMEOUT) {
          if (!double_dev_wait_time(dev)) {
             Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device %s for Job %s\n"),
                dev->print_name(), jcr->Job);
@@ -596,18 +546,12 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr)
          }
          continue;
       }
-      if (stat == EINVAL) {
+      if (stat == W_ERROR) {
          berrno be;
-         Mmsg2(dev->errmsg, _("pthread error in mount_volume stat=%d ERR=%s\n"),
-               stat, be.strerror(stat));
+         Mmsg(dev->errmsg, _("pthread error in mount_volume\n"));
          Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
          return false;
       }
-      if (stat != 0) {
-         berrno be;
-         Jmsg(jcr, M_FATAL, 0, _("pthread error in mount_next_volume stat=%d: ERR=%s\n"), stat,
-            be.strerror(stat));
-      }
       Dmsg1(400, "Someone woke me for device %s\n", dev->print_name());
       break;
    }
index a1ad4c1fdd40f7bfcd9d316bbbcd0d3385127eaf..35127d4a3ac8160b81fd0a833524c2aa126030fd 100644 (file)
@@ -417,6 +417,9 @@ bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd)
 
    if (!dev->is_autochanger() || !dcr->device->changer_name ||
        !dcr->device->changer_command) {
+      if (strcmp(cmd, "drives") == 0) {
+         bnet_fsend(dir, "drives=1\n");
+      }
       bnet_fsend(dir, _("3993 Device %s not an autochanger device.\n"),
          dev->print_name());
       return false;
index 7d745662d9ced46ba949605ac8fca052fdb58861..c4e7d50da22abcedf23fbd1a2a86280501c14096 100644 (file)
@@ -366,7 +366,7 @@ static void labelcmd()
          Pmsg1(0, _("Device open failed. ERR=%s\n"), strerror_dev(dev));
       }
    }
-   rewind_dev(dev);
+   dev->rewind(dcr);
    write_new_volume_label_to_dev(dcr, cmd, "Default");
    Pmsg1(-1, _("Wrote Volume label for volume \"%s\".\n"), cmd);
 }
@@ -431,7 +431,7 @@ static void loadcmd()
  */
 static void rewindcmd()
 {
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
       clrerror_dev(dev, -1);
    } else {
@@ -771,7 +771,7 @@ static int write_read_test()
       "This is an *essential* feature ...\n\n"));
    block = dcr->block;
    rec = new_record();
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
       goto bail_out;
    }
@@ -813,7 +813,7 @@ static int write_read_test()
    if (dev_cap(dev, CAP_TWOEOF)) {
       weofcmd();
    }
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
       goto bail_out;
    } else {
@@ -883,7 +883,7 @@ static int position_test()
       "This is an *essential* feature ...\n\n"));
    empty_block(block);
    rec = new_record();
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
       goto bail_out;
    }
@@ -925,7 +925,7 @@ static int position_test()
    if (dev_cap(dev, CAP_TWOEOF)) {
       weofcmd();
    }
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
       goto bail_out;
    } else {
@@ -1194,7 +1194,7 @@ try_again:
     * a failure.
     */
    bmicrosleep(sleep_time, 0);
-   if (!rewind_dev(dev) || weof_dev(dev,1) < 0) {
+   if (!dev->rewind(dcr) || weof_dev(dev,1) < 0) {
       Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), strerror_dev(dev));
       clrerror_dev(dev, -1);
       Pmsg0(-1, _("\nThe test failed, probably because you need to put\n"
@@ -1823,7 +1823,7 @@ static void fillcmd()
    dev->min_block_size = dev->max_block_size;
    set_volume_name("TestVolume1", 1);
 
-   if (!dev->rewind()) {
+   if (!dev->rewind(dcr)) {
       Pmsg0(000, _("Rewind failed.\n"));
    }
    if (!dev->weof()) {
@@ -2120,7 +2120,7 @@ static void do_unfill()
     *   loose track of where we are (block number unknown).
     */
    Pmsg0(-1, _("Rewinding.\n"));
-   if (!rewind_dev(dev)) {                /* get to a known place on tape */
+   if (!dev->rewind(dcr)) {                /* get to a known place on tape */
       goto bail_out;
    }
    /* Read the first 10000 records */
index 1a3813b051663409c492fcccc2395e7caa13b7a4..acb79b1d2b8959ab39327bf1fdb46d8c53a2c2db 100644 (file)
@@ -237,7 +237,7 @@ init_dev(JCR *jcr, DEVRES *device)
       Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg);
    }
 
-   dev->fd = -1;
+   dev->clear_opened();
    dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link));
    Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev->is_tape(), dev->dev_name);
    
@@ -265,7 +265,6 @@ DEVICE::open(DCR *dcr, int omode)
          return fd;
       } else {
         ::close(fd); /* use system close so correct mode will be used on open */
-        fd = -1;
         clear_opened();
         Dmsg0(100, "Close fd for mode change.\n");
       }
@@ -315,17 +314,6 @@ void DEVICE::set_mode(int new_mode)
 }
 
 /*
- * If the flage open_nowait is set, which is the case
- *   when the daemon is initially trying to open the device,
- *   we open it with O_NONBLOCK set and O_RONLY, which will
- *   allow us to open normal Linux tape drives with no tape
- *   in the drive without blocking.  We then immediately
- *   set blocking status so that if we read from the device they
- *   will be normal blocking reads.
- *
- * If later, we want to write on the device, it will be freed and
- *   reopened, but hopefully there will be a tape in the drive so
- *   we will not block.
  */
 void DEVICE::open_tape_device(DCR *dcr, int omode) 
 {
@@ -380,8 +368,6 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
       set_blocking();   
       Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode));
       dev_errno = 0;
-      set_opened();
-      use_count = 1;
       update_pos_dev(this);                /* update position */
       set_os_device_parameters(this);      /* do system dependent stuff */
    } else {
@@ -431,7 +417,6 @@ void DEVICE::open_file_device(int omode)
    if (VolCatInfo.VolCatName[0] == 0) {
       Mmsg(errmsg, _("Could not open file device %s. No Volume name given.\n"),
          print_name());
-      fd = -1;
       clear_opened();
       return;
    }
@@ -457,13 +442,10 @@ void DEVICE::open_file_device(int omode)
       dev_errno = errno;
       Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), 
             be.strerror());
-      clear_opened();
       Dmsg1(29, "open failed: %s", errmsg);
       Emsg0(M_FATAL, 0, errmsg);
    } else {
       dev_errno = 0;
-      set_opened();
-      use_count = 1;
       update_pos_dev(this);                /* update position */
    }
    Dmsg5(29, "open dev: %s fd=%d opened, part=%d/%d, part_size=%u\n", 
@@ -492,7 +474,6 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
          print_name());
       Mmsg(errmsg, _("Could not open file device %s. No Volume name given.\n"),
          print_name());
-      fd = -1;
       clear_opened();
       return;
    }
@@ -519,7 +500,7 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
             Mmsg(errmsg, _("The media in the device %s is not empty, please blank it before writing anything to it.\n"), print_name());
             Emsg0(M_FATAL, 0, errmsg);
             unmount_dev(this, 1); /* Unmount the device, so the operator can change it. */
-            fd = -1;
+            clear_opened();
             return;
          }
       }
@@ -535,14 +516,14 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
          else {
             Mmsg(errmsg, _("There is no valid media in the device %s.\n"), print_name());
             Emsg0(M_FATAL, 0, errmsg);
-            fd = -1;
+            clear_opened();
             return;
          }
       }
       else {
          Mmsg(errmsg, _("Could not mount device %s.\n"), print_name());
          Emsg0(M_FATAL, 0, errmsg);
-         fd = -1;
+         clear_opened();
          return;
       }
    }
@@ -603,13 +584,10 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
          Dmsg1(29, "open failed: %s", errmsg);
          /* Use system close() */
          ::close(fd);
-         fd = -1;
          clear_opened();
       } else {
          part_size = filestat.st_size;
          dev_errno = 0;
-         set_opened();
-         use_count = 1;
          update_pos_dev(this);                /* update position */
          
          /* NB: It seems this code is wrong... part number is incremented in open_next_part, not here */
@@ -625,77 +603,83 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
             }
          }*/
       }
-   } else {
-      clear_opened();
    }
 }
 
 
-#ifdef debug_tracing
-#undef rewind_dev
-bool _rewind_dev(char *file, int line, DEVICE *dev)
-{
-   Dmsg3(100, "rewind_dev fd=%d called from %s:%d\n", dev->fd, file, line);
-   return rewind_dev(dev);
-}
-#endif
-
 /*
  * Rewind the device.
  *  Returns: true  on success
  *           false on failure
  */
-bool rewind_dev(DEVICE *dev)
+bool DEVICE::rewind(DCR *dcr)
 {
    struct mtop mt_com;
    unsigned int i;
+   bool first = true;
 
-   Dmsg3(29, "rewind_dev res=%d fd=%d %s\n", dev->reserved_device, 
-      dev->fd, dev->print_name());
-   if (dev->fd < 0) {
-      if (!dev->is_dvd()) { /* In case of major error, the fd is not open on DVD, so we don't want to abort. */
-         dev->dev_errno = EBADF;
-         Mmsg1(dev->errmsg, _("Bad call to rewind_dev. Device %s not open\n"),
-            dev->print_name());
-         Emsg0(M_ABORT, 0, dev->errmsg);
+   Dmsg3(29, "rewind res=%d fd=%d %s\n", reserved_device, fd, print_name());
+   if (fd < 0) {
+      if (!is_dvd()) { /* In case of major error, the fd is not open on DVD, so we don't want to abort. */
+         dev_errno = EBADF;
+         Mmsg1(errmsg, _("Bad call to rewind. Device %s not open\n"),
+            print_name());
+         Emsg0(M_ABORT, 0, errmsg);
       }
       return false;
    }
-   dev->state &= ~(ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
-   dev->block_num = dev->file = 0;
-   dev->file_size = 0;
-   dev->file_addr = 0;
-   if (dev->is_tape()) {
+   state &= ~(ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
+   block_num = file = 0;
+   file_size = 0;
+   file_addr = 0;
+   if (is_tape()) {
       mt_com.mt_op = MTREW;
       mt_com.mt_count = 1;
       /* If we get an I/O error on rewind, it is probably because
        * the drive is actually busy. We loop for (about 5 minutes)
        * retrying every 5 seconds.
        */
-      for (i=dev->max_rewind_wait; ; i -= 5) {
-         if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+      for (i=max_rewind_wait; ; i -= 5) {
+         if (ioctl(fd, MTIOCTOP, (char *)&mt_com) < 0) {
             berrno be;
-            clrerror_dev(dev, MTREW);
-            if (i == dev->max_rewind_wait) {
+            clrerror_dev(this, MTREW);
+            if (i == max_rewind_wait) {
                Dmsg1(200, "Rewind error, %s. retrying ...\n", be.strerror());
             }
-            if (dev->dev_errno == EIO && i > 0) {
+            /*
+             * This is a gross hack, because if the user has the
+             *   device mounted (i.e. open), then uses mtx to load
+             *   a tape, the current open file descriptor is invalid.
+             *   So, we close the drive and re-open it.
+             */
+            if (first && dcr) {
+               int open_mode = openmode;
+               ::close(fd);
+               clear_opened();
+               open(dcr, open_mode);
+               if (fd < 0) {
+                  return false;
+               }
+               first = false;
+               continue;
+            }
+            if (dev_errno == EIO && i > 0) {
                Dmsg0(200, "Sleeping 5 seconds.\n");
                bmicrosleep(5, 0);
                continue;
             }
-            Mmsg2(dev->errmsg, _("Rewind error on %s. ERR=%s.\n"),
-               dev->print_name(), be.strerror());
+            Mmsg2(errmsg, _("Rewind error on %s. ERR=%s.\n"),
+               print_name(), be.strerror());
             return false;
          }
          break;
       }
-   } else if (dev->is_file()) {      
-      if (lseek_dev(dev, (off_t)0, SEEK_SET) < 0) {
+   } else if (is_file()) {      
+      if (lseek_dev(this, (off_t)0, SEEK_SET) < 0) {
          berrno be;
-         dev->dev_errno = errno;
-         Mmsg2(dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
-            dev->print_name(), be.strerror());
+         dev_errno = errno;
+         Mmsg2(errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
+            print_name(), be.strerror());
          return false;
       }
    }
@@ -818,7 +802,7 @@ eod_dev(DEVICE *dev)
       Dmsg0(100,"Using FAST FSF for EOM\n");
       /* If unknown position, rewind */
       if (!dev_get_os_pos(dev, &mt_stat)) {
-        if (!rewind_dev(dev)) {
+        if (!dev->rewind(NULL)) {
           return false;
         }
       }
@@ -867,7 +851,7 @@ eod_dev(DEVICE *dev)
       /*
        * Rewind then use FSF until EOT reached
        */
-      if (!rewind_dev(dev)) {
+      if (!dev->rewind(NULL)) {
          return false;
       }
       /*
@@ -1138,7 +1122,7 @@ bool offline_or_rewind_dev(DEVICE *dev)
     *  done, all future references to the drive get and I/O error.
     */
       clrerror_dev(dev, MTREW);
-      return rewind_dev(dev);
+      return dev->rewind(NULL);
    }
 }
 
@@ -1476,8 +1460,8 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block)
    Dmsg4(100, "reposition_dev from %u:%u to %u:%u\n",
       dev->file, dev->block_num, file, block);
    if (file < dev->file) {
-      Dmsg0(100, "Rewind_dev\n");
-      if (!rewind_dev(dev)) {
+      Dmsg0(100, "Rewind\n");
+      if (!dev->rewind(NULL)) {
          return false;
       }
    }
@@ -1700,7 +1684,7 @@ static void do_close(DEVICE *dev)
 
    Dmsg1(100, "really close_dev %s\n", dev->print_name());
    if (dev->fd >= 0) {
-      close(dev->fd);
+      ::close(dev->fd);
    }
 
    if (!unmount_dev(dev, 1)) {
@@ -1722,8 +1706,8 @@ static void do_close(DEVICE *dev)
    }
    
    /* Clean up device packet so it can be reused */
-   dev->fd = -1;
-   dev->state &= ~(ST_OPENED|ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
+   dev->clear_opened();
+   dev->state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
    dev->label_type = B_BACULA_LABEL;
    dev->file = dev->block_num = 0;
    dev->file_size = 0;
@@ -1740,7 +1724,6 @@ static void do_close(DEVICE *dev)
       stop_thread_timer(dev->tid);
       dev->tid = 0;
    }
-   dev->use_count = 0;
    dev->openmode = 0;
 }
 
@@ -1749,20 +1732,7 @@ static void do_close(DEVICE *dev)
  */
 void DEVICE::close()
 {
-   /*if (fd >= 0 && use_count == 1) {*/
-   /* No need to check if fd >= 0: it is checked again
-    * in do_close, and do_close MUST be called for volumes
-    * split in parts, even if fd == -1. 
-    */
-   if (use_count == 1) {
-      do_close(this);
-   } else if (use_count > 0) {
-      use_count--;
-   }
-
-#ifdef FULL_DEBUG
-   ASSERT(use_count >= 0);
-#endif
+   do_close(this);
 }
 
 
index 0adf10fae1739ffd0aab18aa78c7cff43c61e9e6..0ccee75db501a584b8c786dbbb58cdef0dd35597 100644 (file)
 #define steal_device_lock(d, p, s) _steal_device_lock(__FILE__, __LINE__, (d), (p), s)
 #define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p))
 
+/* Return values from wait_for_sysop() */
+enum {
+   W_ERROR = 1,
+   W_TIMEOUT,
+   W_POLL,
+   W_MOUNT,
+   W_WAKE
+};
+
 /* Arguments to open_dev() */
 enum {
    CREATE_READ_WRITE = 1,
@@ -94,7 +103,7 @@ enum {
 #define dev_state(dev, st_state) ((dev)->state & (st_state))
 
 /* Device state bits */
-#define ST_OPENED          (1<<0)     /* set when device opened */
+#define ST_XXXXXX          (1<<0)     /* was ST_OPENED */
 #define ST_TAPE            (1<<1)     /* is a tape device */
 #define ST_FILE            (1<<2)     /* is a file device */
 #define ST_FIFO            (1<<3)     /* is a fifo device */
@@ -121,9 +130,9 @@ enum {
    BST_UNMOUNTED,                     /* User unmounted device */
    BST_WAITING_FOR_SYSOP,             /* Waiting for operator to mount tape */
    BST_DOING_ACQUIRE,                 /* Opening/validating/moving tape */
-   BST_WRITING_LABEL,                  /* Labeling a tape */
-   BST_UNMOUNTED_WAITING_FOR_SYSOP,    /* Closed by user during mount request */
-   BST_MOUNT                           /* Mount request */
+   BST_WRITING_LABEL,                 /* Labeling a tape */
+   BST_UNMOUNTED_WAITING_FOR_SYSOP,   /* User unmounted during wait for op */
+   BST_MOUNT                          /* Mount request */
 };
 
 /* Volume Catalog Information structure definition */
@@ -189,7 +198,6 @@ public:
    /* New access control in process of being implemented */
    brwlock_t lock;                    /* New mutual exclusion lock */
 
-   int use_count;                     /* usage count on this device 0 or 1 */
    int fd;                            /* file descriptor */
    int capabilities;                  /* capabilities mask */
    int state;                         /* state mask */
@@ -197,7 +205,6 @@ public:
    int mode;                          /* read/write modes */
    int openmode;                      /* parameter passed to open_dev (useful to reopen the device) */
    bool autoselect;                   /* Autoselect in autochanger */
-   bool open_nowait;                  /* If set, don't wait on open */
    int label_type;                    /* Bacula/ANSI/IBM label types */
    uint32_t drive_index;              /* Autochanger drive index (base 0) */
    int32_t  Slot;                     /* Slot currently in drive (base 1) */
@@ -258,7 +265,7 @@ public:
    int is_file() const { return state & ST_FILE; }
    int is_fifo() const { return state & ST_FIFO; }
    int is_dvd() const  { return state & ST_DVD; }
-   int is_open() const { return state & ST_OPENED; }
+   int is_open() const { return fd >= 0; }
    int is_offline() const { return state & ST_OFFLINE; }
    int is_labeled() const { return state & ST_LABEL; }
    int is_mounted() const { return state & ST_MOUNTED; }
@@ -290,7 +297,6 @@ public:
    bool weof() { return !weof_dev(this, 1); };
    bool fsr(int num);   /* in dev.c */
    bool fsf(int num);   /* in dev.c */
-   bool rewind() { return rewind_dev(this); };
    const char *strerror() const;
    const char *archive_name() const;
    const char *name() const;
@@ -303,7 +309,6 @@ public:
    void set_labeled() { state |= ST_LABEL; };
    void set_read() { state |= ST_READ; };
    void set_offline() { state |= ST_OFFLINE; };
-   void set_opened() { state |= ST_OPENED; };
    void set_mounted() { state |= ST_MOUNTED; };
    void set_media() { state |= ST_MEDIA; };
    void set_short_block() { state |= ST_SHORT; };
@@ -318,7 +323,7 @@ public:
    void clear_offline() { state &= ~ST_OFFLINE; };
    void clear_eot() { state &= ~ST_EOT; };
    void clear_eof() { state &= ~ST_EOF; };
-   void clear_opened() { state &= ~ST_OPENED; };
+   void clear_opened() { fd = -1; };
    void clear_mounted() { state &= ~ST_MOUNTED; };
    void clear_media() { state &= ~ST_MEDIA; };
    void clear_short_block() { state &= ~ST_SHORT; };
@@ -328,6 +333,7 @@ public:
    void unblock();      /* in dev.c */
    void close();        /* in dev.c */
    int open(DCR *dcr, int mode); /* in dev.c */
+   bool rewind(DCR *dcr);         /* in dev.c */
 
 
    void set_blocked(int block) { dev_blocked = block; };
index d516a6d0e79401fb92dcbd86c7d380eef3841dec..c7407d5d2411f51102022158da453041b51a5cbe 100644 (file)
@@ -262,7 +262,6 @@ bool first_open_device(DCR *dcr)
        mode = OPEN_READ_ONLY;
     }
    Dmsg0(129, "Opening device.\n");
-   dev->open_nowait = true;
    if (dev->open(dcr, mode) < 0) {
       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
       ok = false;
@@ -271,7 +270,6 @@ bool first_open_device(DCR *dcr)
    Dmsg1(129, "open dev %s OK\n", dev->print_name());
 
 bail_out:
-   dev->open_nowait = false;
    unlock_device(dev);
    return ok;
 }
@@ -315,7 +313,6 @@ void close_device(DEVICE *dev)
 }
 
 /*
- * Used when unmounting the device, ignore use_count
  */
 void force_close_device(DEVICE *dev)
 {
@@ -323,12 +320,8 @@ void force_close_device(DEVICE *dev)
       return;
    }
    Dmsg1(29, "Force close_dev %s\n", dev->print_name());
-   dev->use_count = 1;
+   free_volume(dev);
    dev->close();
-
-#ifdef FULL_DEBUG
-   ASSERT(dev->use_count >= 0);
-#endif
 }
 
 
@@ -453,7 +446,6 @@ void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock
    dev->no_wait_id = hold->no_wait_id;
    Dmsg1(400, "return lock. new=%s\n", dev->print_blocked());
    if (dev->num_waiting > 0) {
-      Dmsg0(400, "Broadcast\n");
       pthread_cond_broadcast(&dev->wait); /* wake them up */
    }
 }
index 6d7f826abcac66c9ee74a85f61405b8b93081921..2481b21b99ff3754818b64874779426cc5e0454b 100644 (file)
@@ -191,7 +191,7 @@ void *handle_connection_request(void *arg)
       if ((bnet_stat = bnet_recv(bs)) <= 0) {
          break;               /* connection terminated */
       }
-      Dmsg1(199, "<dird: %s\n", bs->msg);
+      Dmsg1(199, "<dird: %s", bs->msg);
       /* Ensure that device initialization is complete */
       while (!init_done) {
          bmicrosleep(1, 0);
@@ -259,7 +259,7 @@ static bool cancel_cmd(JCR *cjcr)
 
    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
       if (!(jcr=get_jcr_by_full_name(Job))) {
-         bnet_fsend(dir, _("3902 Job %s not found.\n"), Job);
+         bnet_fsend(dir, _("3904 Job %s not found.\n"), Job);
       } else {
          P(jcr->mutex);
          oldStatus = jcr->JobStatus;
@@ -273,12 +273,12 @@ 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);
-             pthread_cond_broadcast(&wait_device_release);
+            pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
+            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);
-             pthread_cond_broadcast(&wait_device_release);
+            pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
+            pthread_cond_broadcast(&wait_device_release);
          }
          bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job);
          free_jcr(jcr);
@@ -573,6 +573,7 @@ static bool mount_cmd(JCR *jcr)
       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? */
          case BST_WAITING_FOR_SYSOP:
             /* Someone is waiting, wake him */
@@ -588,11 +589,9 @@ 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 */
-            dev->open_nowait = true;
             if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
                bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
                   strerror_dev(dev));
-               dev->open_nowait = false;
                if (dev->dev_blocked == BST_UNMOUNTED) {
                   /* We blocked the device, so unblock it */
                   Dmsg0(100, "Unmounted. Unblocking device\n");
@@ -600,7 +599,6 @@ static bool mount_cmd(JCR *jcr)
                }
                break;
             }
-            dev->open_nowait = false;
             read_dev_volume_label(dcr);
             if (dev->dev_blocked == BST_UNMOUNTED) {
                /* We blocked the device, so unblock it */
@@ -644,14 +642,11 @@ static bool mount_cmd(JCR *jcr)
                              dev->print_name());
                }
             } else if (dev->is_tape()) {
-               dev->open_nowait = true;
                if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
                   bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
                      strerror_dev(dev));
-                  dev->open_nowait = false;
                   break;
                }
-               dev->open_nowait = false;
                read_label(dcr);
                if (dev->is_labeled()) {
                   bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
index 6de8a603dbdeb7af5a11a7f72a7da8f4dadf2d9a..ee0d4fbd74392773cd0db984bf0d88b5e96d3a7b 100644 (file)
@@ -98,7 +98,7 @@ int read_dev_volume_label(DCR *dcr)
    dev->clear_read();
    dev->label_type = B_BACULA_LABEL;
 
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       Mmsg(jcr->errmsg, _("Couldn't rewind device %s: ERR=%s\n"), 
          dev->print_name(), strerror_dev(dev));
       Dmsg1(30, "return VOL_NO_MEDIA: %s", jcr->errmsg);
@@ -125,7 +125,7 @@ int read_dev_volume_label(DCR *dcr)
          goto bail_out;
       }
       if (stat != VOL_OK) {           /* Not an ANSI/IBM label, so re-read */
-         rewind_dev(dev);
+         dev->rewind(dcr);
       } else {
          have_ansi_label = true;
       }
@@ -227,7 +227,7 @@ int read_dev_volume_label(DCR *dcr)
    Dmsg0(30, "Leave read_volume_label() VOL_OK\n");
    /* If we are a streaming device, we only get one chance to read */
    if (!dev_cap(dev, CAP_STREAM)) {
-      rewind_dev(dev);
+      dev->rewind(dcr);
       if (have_ansi_label) {
          stat = read_ansi_ibm_label(dcr);            
          /* If we want a label and didn't find it, return error */
@@ -241,7 +241,7 @@ int read_dev_volume_label(DCR *dcr)
 
 bail_out:
    empty_block(block);
-   rewind_dev(dev);
+   dev->rewind(dcr);
    Dmsg1(150, "return %d\n", stat);
    return stat;
 }
@@ -303,7 +303,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po
       goto bail_out;
    }
    Dmsg1(150, "Label type=%d\n", dev->label_type);
-   if (!rewind_dev(dev)) {
+   if (!dev->rewind(dcr)) {
       free_volume(dev);
       memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
       Dmsg2(30, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), strerror_dev(dev));
@@ -322,7 +322,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po
     */
    if (dev->label_type != B_BACULA_LABEL) {
       if (read_ansi_ibm_label(dcr) != VOL_OK) {
-         rewind_dev(dev);
+         dev->rewind(dcr);
          goto bail_out;
       }
    } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
@@ -396,7 +396,7 @@ bool rewrite_volume_label(DCR *dcr, bool recycle)
     *  avoids re-writing the ANSI label, which we do not want to do.
     */
    if (!dev_cap(dev, CAP_STREAM)) {
-      if (!rewind_dev(dev)) {
+      if (!dev->rewind(dcr)) {
          Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s: ERR=%s\n"),
                dev->print_name(), strerror_dev(dev));
       }
@@ -414,7 +414,7 @@ bool rewrite_volume_label(DCR *dcr, bool recycle)
        */
       if (dev->label_type != B_BACULA_LABEL) {
          if (read_ansi_ibm_label(dcr) != VOL_OK) {
-            rewind_dev(dev);
+            dev->rewind(dcr);
             return false;
          }
       } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, dev->VolHdr.VolumeName)) {
index 5e642ff0bb912e96832545287ff5c2db64f74fd2..28ce910ab86672abb5053f9681ab9dc3bd4b1ba1 100644 (file)
@@ -58,6 +58,7 @@ bool mount_next_write_volume(DCR *dcr, bool release)
     *  Volume, ...)
     */
 mount_next_vol:
+   Dmsg1(150, "mount_next_vol retry=%d\n", retry);
    /* Ignore retry if this is poll request */
    if (!dev->poll && retry++ > 4) {
       /* Last ditch effort before giving up, force operator to respond */
@@ -299,6 +300,7 @@ read_volume:
       /* NOTE! Fall-through wanted. */
    case VOL_NO_MEDIA:
    default:
+      Dmsg0(200, "VOL_NO_MEDIA or default.\n");
       /* Send error message */
       if (!dev->poll) {
       } else {
index ab1c3ea02c51ed1e9072dd2a0220363f4b3768d7..eb10b41a11a14adee0968560ed60dfa16fc26c36 100644 (file)
@@ -508,9 +508,11 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
          stat = search_res_for_device(rctx); 
          if (stat == 1) {             /* found available device */
             rctx.suitable_device = true;
+            Dmsg1(100, "Suitable device found=%s\n", device_name);
             ok = true;
             break;
          } else if (stat == 0) {      /* device busy */
+            Dmsg1(100, "Suitable busy device found=%s\n", device_name);
             rctx.suitable_device = true;   /* but it is busy, so continue looking */
          }
          /* otherwise error */
@@ -583,7 +585,7 @@ static int search_res_for_device(RCTX &rctx)
          }
       }
    }
-   return 0;                    /* nothing found */
+   return -1;                    /* nothing found */
 }
 
 /*
index ba7b203ff4d9dbc0cc86b8529309cda05832483f..0e39ba5c6025620b99793b2b5a596dad46bfa2c7 100644 (file)
@@ -32,7 +32,7 @@
 /*
  * Wait for SysOp to mount a tape on a specific device
  *
- *   Returns: status from pthread_cond_timedwait() 
+ *   Returns: W_ERROR, W_TIMEOUT, W_POLL, W_MOUNT, or W_WAKE 
  */
 int wait_for_sysop(DCR *dcr)
 {
@@ -82,8 +82,8 @@ int wait_for_sysop(DCR *dcr)
       timeout.tv_nsec = tv.tv_usec * 1000;
       timeout.tv_sec = tv.tv_sec + add_wait;
 
-      Dmsg3(400, "I'm going to sleep on device %s. HB=%d wait=%d\n", dev->print_name(),
-         (int)me->heartbeat_interval, dev->wait_sec);
+      Dmsg4(400, "I'm going to sleep on device %s. HB=%d wait=%d add_wait=%d\n", 
+         dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait);
       start = time(NULL);
       /* Wait required time */
       stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout);
@@ -108,33 +108,55 @@ int wait_for_sysop(DCR *dcr)
          }
       }
 
-      /*
-       * Check if user unmounted the device while we were waiting
-       */
-      unmounted = is_device_unmounted(dev);
-
-      if (stat != ETIMEDOUT) {     /* we blocked the device */
-         break;                    /* on error return */
+      if (stat == EINVAL) {
+         berrno be;
+         Dmsg1(000, "pthread stat=%d\n", stat);
+         Jmsg1(jcr, M_FATAL, 0, _("pthread timedwait error. ERR=%s\n"), be.strerror(stat));
+         stat = W_ERROR;               /* error */
+         break;
       }
+
+
       if (dev->rem_wait_sec <= 0) {  /* on exceeding wait time return */
          Dmsg0(400, "Exceed wait time.\n");
+         stat = W_TIMEOUT;
          break;
       }
 
+      /*
+       * Check if user unmounted the device while we were waiting
+       */
+      unmounted = is_device_unmounted(dev);
+
       if (!unmounted && dev->vol_poll_interval &&
           (now - first_start >= dev->vol_poll_interval)) {
          Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked());
          dev->poll = true;            /* returning a poll event */
+         stat = W_POLL;
          break;
       }
       /*
        * Check if user mounted the device while we were waiting
        */
       if (dev->get_blocked() == BST_MOUNT) {   /* mount request ? */
-         stat = 0;
+         stat = W_MOUNT;
          break;
       }
 
+      /*
+       * If we did not timeout, then some event happened, so
+       *   return to check if state changed.   
+       */
+      if (stat != 0) {
+         stat = W_WAKE;          /* someone woke us */
+         break;
+      }
+
+      /* 
+       * At this point, we know we woke up because of a timeout,
+       *   that was due to a heartbeat, so we just update
+       *   the wait counters and continue.
+       */
       add_wait = dev->wait_sec - (now - start);
       if (add_wait < 0) {
          add_wait = 0;