]> git.sur5r.net Git - bacula/bacula/commitdiff
- Modify open() for tape so nonblocking really works.
authorKern Sibbald <kern@sibbald.com>
Wed, 3 Aug 2005 19:01:43 +0000 (19:01 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 3 Aug 2005 19:01:43 +0000 (19:01 +0000)
- Use fcntl() to reset blocking status rather than close()
  and reopen the drive.
- Make sure dev->open() is always called so that any change
  in read/write permissions will occur.
- Open drives initially in daemon in read-only mode.
- Ensure that each time the VolHdr.VolumeName is zapped
  or changed that free_volume() is called on the old name.

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

bacula/kes-1.37
bacula/src/stored/acquire.c
bacula/src/stored/ansi_label.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/version.h

index e8a4053796695644fa8ff1d3c995ee16b8d3be61..ba38515cca67eb0cd2985883c86db6f77ace4971 100644 (file)
@@ -3,7 +3,18 @@
 
 General:
 
-Changes to 1.37.32:
+Changes to 1.37.34:
+03Aug03
+- Modify open() for tape so nonblocking really works.  
+- Use fcntl() to reset blocking status rather than close()
+  and reopen the drive.
+- Make sure dev->open() is always called so that any change
+  in read/write permissions will occur.
+- Open drives initially in daemon in read-only mode.
+- Ensure that each time the VolHdr.VolumeName is zapped
+  or changed that free_volume() is called on the old name.
+
+Changes to 1.37.33:
 03Aug03
 - Require 5 arguments to mtx-changer except list and slots
 - Turn -EPIPE status returns from bpipe to ETIME
@@ -11,6 +22,8 @@ Changes to 1.37.32:
 - Do not term_dev() during initialization in SD if the device
   could not be opened.  In the case of a tape drive, there may
   be no tape in the drive.
+
+Changes to 1.32.32:
 02Aug05
 - Correct PostgreSQL database scripts as suggested by a user.
 - Add additional info to FATAL message generated when a device
index e9daa80c1d243c3e57ae0182301917d306bd2fd5..6e82b61dbf0a4e4ff1fb16f28336101e9abaf964 100644 (file)
@@ -187,31 +187,29 @@ DCR *acquire_device_for_read(DCR *dcr)
        * reading. If it is a file, it opens it.
        * If it is a tape, it checks the volume name
        */
-      for ( ; !dev->is_open(); ) {
-         Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
-         if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
-            if (dev->dev_errno == EIO) {   /* no tape loaded */
-              Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
-                    dev->print_name(), dcr->VolumeName, strerror_dev(dev));
-               goto default_path;
-            }
-            
+      Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
+      if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
+         if (dev->dev_errno == EIO) {   /* no tape loaded */
+           Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
+                 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+            goto default_path;
+         }
+         
 #ifdef xxx_needed
-            /* If we have a dvd that requires mount, 
-             * we need to try to open the label, so the info can be reported
-             * if a wrong volume has been mounted.   
-             */
-            if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
-               break;
-            }  
+         /* If we have a dvd that requires mount, 
+          * we need to try to open the label, so the info can be reported
+          * if a wrong volume has been mounted.   
+          */
+         if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
+            break;
+         }  
 #endif
-            
-            Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
-                dev->print_name(), dcr->VolumeName, strerror_dev(dev));
-            goto get_out;
-         }
-         Dmsg1(100, "opened dev %s OK\n", dev->print_name());
+         
+         Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
+             dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+         goto get_out;
       }
+      Dmsg1(100, "opened dev %s OK\n", dev->print_name());
       
       /* Read Volume Label */
       
index fa643b9c5f7c4e3fe54935bf61dd342f82e1f8a0..ef2e6561a9c977d87d6ac6aef5741c2a8f5f9b38 100644 (file)
@@ -123,7 +123,11 @@ int read_ansi_ibm_label(DCR *dcr)
          if (VolName && *VolName && *VolName != '*') { 
             if (!same_label_names(VolName, &label[4])) {
                char *p = &label[4];
-               char *q = dev->VolHdr.VolumeName;
+               char *q;  
+
+               free_volume(dev);
+               /* Store new Volume name */
+               q = dev->VolHdr.VolumeName;
                for (int i=0; *p != ' ' && i < 6; i++) {
                   *q++ = *p++;
                }
index f0321a15f37e53e6493de294b1318c66a3261656..a8ea31197bf19226789a0b949d6b6d8e6f4cf149 100644 (file)
@@ -276,7 +276,7 @@ DEVICE::open(DCR *dcr, int omode)
    state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
    label_type = B_BACULA_LABEL;
    if (is_tape() || is_fifo()) {
-      open_tape_device(omode);
+      open_tape_device(dcr, omode);
    } else if (is_dvd()) {
       Dmsg1(100, "call open_dvd_device mode=%s\n", mode_to_str(omode));
       open_dvd_device(dcr, omode);
@@ -311,7 +311,20 @@ void DEVICE::set_mode(int new_mode)
    }
 }
 
-void DEVICE::open_tape_device(int omode) 
+/*
+ * 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) 
 {
    int nonblocking = 0;;
    file_size = 0;
@@ -333,14 +346,14 @@ void DEVICE::open_tape_device(int omode)
       tid = start_thread_timer(pthread_self(), timeout);
    }
    /* If busy retry each second for max_open_wait seconds */
-open_again:
-   Dmsg1(500, "Try open %s\n", print_name());
+   Dmsg3(100, "Try open %s mode=%s nonblocking=%d\n", print_name(),
+      mode_to_str(omode), nonblocking);
    /* Use system open() */
-   while ((fd = ::open(dev_name, mode, MODE_RW+nonblocking)) < 0) {
+   while ((fd = ::open(dev_name, mode+nonblocking, MODE_RW)) < 0) {
       berrno be;
-      Dmsg2(500, "Open error errno=%d ERR=%s\n", errno, be.strerror());
+      Dmsg2(100, "Open error errno=%d ERR=%s\n", errno, be.strerror());
       if (errno == EINTR || errno == EAGAIN) {
-         Dmsg0(500, "Continue open\n");
+         Dmsg0(100, "Continue open\n");
          continue;
       }
       /* Busy wait for specified time (default = 5 mins) */
@@ -352,7 +365,7 @@ open_again:
       /* IO error (no volume) try 10 times every 6 seconds */
       if (errno == EIO && ioerrcnt-- > 0) {
          bmicrosleep(5, 0);
-         Dmsg0(500, "Continue open\n");
+         Dmsg0(100, "Continue open\n");
          continue;
       }
       dev_errno = errno;
@@ -366,12 +379,21 @@ open_again:
       Emsg0(M_FATAL, 0, errmsg);
       break;
    }
-   if (fd >= 0) {
-      /* If opened in non-block mode, close it an open it normally */
+   /* Really an if, but we use a break for an error exit */
+   while (fd >= 0) {
+      /* If opened in non-block mode, make it block now */
       if (nonblocking) {
+         int oflags;
          nonblocking = 0;
-         ::close(fd);                /* use system close() */
-         goto open_again;
+         /* Try to reset blocking */
+         if ((oflags = fcntl(fd, F_GETFL, 0)) < 0 ||
+             fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) < 0) {
+            berrno be;
+            Jmsg1(dcr->jcr, M_ERROR, 0, "fcntl error. ERR=%s\n", be.strerror());
+            ::close(fd);                   /* use system close() */
+            fd = -1;
+            break;
+         }
       }
       openmode = omode;              /* save open mode */
       Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode));
@@ -381,6 +403,7 @@ open_again:
       update_pos_dev(this);                /* update position */
       set_os_device_parameters(this);      /* do system dependent stuff */
       Dmsg0(500, "Open OK\n");
+      break;
    }
    /* Stop any open() timer we started */
    if (tid) {
@@ -1706,6 +1729,7 @@ static void do_close(DEVICE *dev)
    dev->part_start = 0;
    dev->EndFile = dev->EndBlock = 0;
    memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
+   free_volume(dev);
    memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
    if (dev->tid) {
       stop_thread_timer(dev->tid);
index 57c4bb5b77b442767c4802864925ee0a910719cf..f96a8291bbf975a1ad556954ce6779c6ffdd522a 100644 (file)
@@ -196,7 +196,7 @@ 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 */
+   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) */
@@ -335,7 +335,7 @@ public:
 
 private:
    void set_mode(int omode); /* in dev.c */
-   void open_tape_device(int omode); /* in dev.c */
+   void open_tape_device(DCR *dcr, int omode); /* in dev.c */
    void open_file_device(int omode); /* in dev.c */
    void open_dvd_device(DCR *dcr, int omode); /* in dev.c */
 
index 3cd95bf32d9bf94633c7e71b6b153ed17cb774f0..5b98bc8de789a786124041af2f08a643dc2b0bb0 100644 (file)
@@ -265,7 +265,7 @@ bool first_open_device(DCR *dcr)
     if (dev_cap(dev, CAP_STREAM)) {
        mode = OPEN_WRITE_ONLY;
     } else {
-       mode = OPEN_READ_WRITE;
+       mode = OPEN_READ_ONLY;
     }
    Dmsg0(129, "Opening device.\n");
    dev->open_nowait = true;
index a7b1102f5ac1a0c169dbf67e07adb63c918a8fda..993c3d10e604b195ca69ed0c4536ef49ca7a5739 100644 (file)
@@ -917,12 +917,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 (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;
-      }
+   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;
 }
index 5b39ff7fdab85ca78d82803254a2029191e24cea..d5319dffb5edc8bb819b71ea35aef53eb2bafceb 100644 (file)
@@ -301,6 +301,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po
 
    Dmsg1(100, "Label type=%d\n", dev->label_type);
    if (!rewind_dev(dev)) {
+      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));
       if (!forge_on) {
@@ -356,6 +357,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po
    return true;
 
 bail_out:
+   free_volume(dev);
    memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
    dev->clear_append();               /* remove append since this is PRE_LABEL */
    return false;
@@ -529,6 +531,7 @@ void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName)
 
    ASSERT(dev != NULL);
 
+   free_volume(dev);         /* release any old volume */
    memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
 
    bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
index f6a1bb755e9a6c81e76840c47a8244d74146fc26..b5d36d79ec295631383b4d541d270bd4b9c8b406 100644 (file)
@@ -1,6 +1,6 @@
 /* */
 #undef  VERSION
-#define VERSION "1.37.33"
+#define VERSION "1.37.34"
 #define BDATE   "03 August 2005"
 #define LSMDATE "03Aug05"