]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Modify insertion of read Volumes in SD to be done before the
authorKern Sibbald <kern@sibbald.com>
Sat, 11 Apr 2009 12:35:04 +0000 (12:35 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 11 Apr 2009 12:35:04 +0000 (12:35 +0000)
     drive reservation. This ensures that a Volume to be read will not
     be reserved for writing.

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

22 files changed:
bacula/Patchnotes [moved from bacula/Patchnotes-2.5 with 71% similarity]
bacula/patches/2.4.x/2.4.4-bat-install.patch [moved from bacula/patches/2.4.4-bat-install.patch with 100% similarity]
bacula/patches/2.4.x/2.4.4-jobname-edit.patch [moved from bacula/patches/2.4.4-jobname-edit.patch with 100% similarity]
bacula/patches/2.4.x/2.4.4-label-failure.patch [moved from bacula/patches/2.4.4-label-failure.patch with 100% similarity]
bacula/patches/2.4.x/2.4.4-reload.patch [moved from bacula/patches/2.4.4-reload.patch with 100% similarity]
bacula/patches/2.4.x/2.4.4-sd-deadlock.patch [moved from bacula/patches/2.4.4-sd-deadlock.patch with 100% similarity]
bacula/patches/2.4.x/2.4.4-time_t_64bit.patch [moved from bacula/patches/2.4.4-time_t_64bit.patch with 100% similarity]
bacula/patches/2.4.x/2.4.4-tray-sizing.patch [moved from bacula/patches/2.4.4-tray-sizing.patch with 100% similarity]
bacula/patches/3.0.0-read-vol-list.patch [new file with mode: 0644]
bacula/src/dird/migrate.c
bacula/src/dird/msgchan.c
bacula/src/dird/protos.h
bacula/src/dird/vbackup.c
bacula/src/stored/acquire.c
bacula/src/stored/fd_cmds.c
bacula/src/stored/job.c
bacula/src/stored/mac.c
bacula/src/stored/parse_bsr.c
bacula/src/stored/read.c
bacula/src/stored/vol_mgr.c
bacula/src/version.h
bacula/technotes

similarity index 71%
rename from bacula/Patchnotes-2.5
rename to bacula/Patchnotes
index 3c12a6fbe33c03ffa551b52ecec67c8d6836c2c0..304387cdf78ca26dcbea6bd8137c15fd5db01fc8 100644 (file)
@@ -2,3 +2,4 @@
 
 
 Patches Committed:
+3.0.0-read-vol-list.patch
diff --git a/bacula/patches/3.0.0-read-vol-list.patch b/bacula/patches/3.0.0-read-vol-list.patch
new file mode 100644 (file)
index 0000000..de1cfea
--- /dev/null
@@ -0,0 +1,282 @@
+
+ This patch can be applied to version 3.0.0. It ensures that the list
+ of volumes to be read is created very early when starting the Job in
+ the SD (before the drive reservation) so that any Volume to be read
+ cannot also be chosen to append.
+
+ Apply it to version 3.0.0 with:
+
+ cd <bacula-source>
+ patch -p0 <3.0.0-read-vol-list.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+
+Index: src/dird/msgchan.c
+===================================================================
+--- src/dird/msgchan.c (revision 8699)
++++ src/dird/msgchan.c (working copy)
+@@ -144,10 +144,12 @@
+ }
+ #endif
++static char OKbootstrap[] = "3000 OK bootstrap\n";
++
+ /*
+  * Start a job with the Storage daemon
+  */
+-bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore)
++bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore, bool send_bsr)
+ {
+    bool ok = true;
+    STORE *storage;
+@@ -196,7 +198,7 @@
+                   &jcr->VolSessionTime, &auth_key) != 3) {
+           Dmsg1(100, "BadJob=%s\n", sd->msg);
+           Jmsg(jcr, M_FATAL, 0, _("Storage daemon rejected Job command: %s\n"), sd->msg);
+-          return 0;
++          return false;
+        } else {
+           jcr->sd_auth_key = bstrdup(auth_key);
+           Dmsg1(150, "sd_auth_key=%s\n", jcr->sd_auth_key);
+@@ -204,9 +206,14 @@
+    } else {
+       Jmsg(jcr, M_FATAL, 0, _("<stored: bad response to Job command: %s\n"),
+          sd->bstrerror());
+-      return 0;
++      return false;
+    }
++   if (send_bsr && (!send_bootstrap_file(jcr, sd) ||
++       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR))) {
++      return false;
++   }
++
+    /*
+     * We have two loops here. The first comes from the 
+     *  Storage = associated with the Job, and we need 
+Index: src/dird/migrate.c
+===================================================================
+--- src/dird/migrate.c (revision 8699)
++++ src/dird/migrate.c (working copy)
+@@ -55,7 +55,6 @@
+ static const int dbglevel = 10;
+-static char OKbootstrap[] = "3000 OK bootstrap\n";
+ static int get_job_to_migrate(JCR *jcr);
+ struct idpkt;
+ static bool regex_find_jobids(JCR *jcr, idpkt *ids, const char *query1,
+@@ -353,15 +352,11 @@
+            ((STORE *)jcr->rstorage->first())->name());
+       return false;
+    }
+-   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage)) {
++   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage, /*send_bsr*/true)) {
+       return false;
+    }
+    Dmsg0(150, "Storage daemon connection OK\n");
+-   if (!send_bootstrap_file(jcr, sd) ||
+-       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
+-      return false;
+-   }
+    /*    
+     * We re-update the job start record so that the start
+Index: src/dird/protos.h
+===================================================================
+--- src/dird/protos.h  (revision 8699)
++++ src/dird/protos.h  (working copy)
+@@ -155,7 +155,8 @@
+ /* msgchan.c */
+ extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
+                               int max_retry_time, int verbose);
+-extern bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore);
++extern bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore,
++              bool send_bsr=false);
+ extern bool start_storage_daemon_message_thread(JCR *jcr);
+ extern int bget_dirmsg(BSOCK *bs);
+ extern void wait_for_storage_daemon_termination(JCR *jcr);
+Index: src/dird/vbackup.c
+===================================================================
+--- src/dird/vbackup.c (revision 8699)
++++ src/dird/vbackup.c (working copy)
+@@ -50,8 +50,6 @@
+ static const int dbglevel = 10;
+-static char OKbootstrap[] = "3000 OK bootstrap\n";
+-
+ static bool create_bootstrap_file(JCR *jcr, POOLMEM *jobids);
+ void vbackup_cleanup(JCR *jcr, int TermCode);
+@@ -217,16 +215,11 @@
+    /*
+     * Now start a job with the Storage daemon
+     */
+-   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage)) {
++   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage, /*send_bsr*/true)) {
+       return false;
+    }
+    Dmsg0(100, "Storage daemon connection OK\n");
+-   if (!send_bootstrap_file(jcr, sd) ||
+-       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
+-      return false;
+-   }
+-
+    /*    
+     * We re-update the job start record so that the start
+     *  time is set after the run before job.  This avoids 
+Index: src/stored/fd_cmds.c
+===================================================================
+--- src/stored/fd_cmds.c       (revision 8699)
++++ src/stored/fd_cmds.c       (working copy)
+@@ -388,6 +388,8 @@
+    if (debug_level >= 10) {
+       dump_bsr(jcr->bsr, true);
+    }
++   /* If we got a bootstrap, we are reading, so create read volume list */
++   create_restore_volume_list(jcr);
+    ok = true;
+ bail_out:
+Index: src/stored/read.c
+===================================================================
+--- src/stored/read.c  (revision 8699)
++++ src/stored/read.c  (working copy)
+@@ -1,7 +1,7 @@
+ /*
+    Bacula® - The Network Backup Solution
+-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
++   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+    The main author of Bacula is Kern Sibbald, with contributions from
+    many others, a complete list can be found in the file AUTHORS.
+@@ -62,11 +62,8 @@
+       return false;
+    }
+-
+-   create_restore_volume_list(jcr);
+    if (jcr->NumReadVolumes == 0) {
+       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
+-      free_restore_volume_list(jcr);
+       fd->fsend(FD_error);
+       return false;
+    }
+@@ -76,7 +73,6 @@
+    /* Ready device for reading */
+    if (!acquire_device_for_read(dcr)) {
+-      free_restore_volume_list(jcr);
+       fd->fsend(FD_error);
+       return false;
+    }
+@@ -92,7 +88,6 @@
+       ok = false;
+    }
+-   free_restore_volume_list(jcr);
+    Dmsg0(30, "Done reading.\n");
+    return ok;
+ }
+Index: src/stored/parse_bsr.c
+===================================================================
+--- src/stored/parse_bsr.c     (revision 8699)
++++ src/stored/parse_bsr.c     (working copy)
+@@ -1,7 +1,7 @@
+ /*
+    Bacula® - The Network Backup Solution
+-   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
++   Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
+    The main author of Bacula is Kern Sibbald, with contributions from
+    many others, a complete list can be found in the file AUTHORS.
+Index: src/stored/mac.c
+===================================================================
+--- src/stored/mac.c   (revision 8699)
++++ src/stored/mac.c   (working copy)
+@@ -84,8 +84,6 @@
+    }
+    Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr);
+-
+-   create_restore_volume_list(jcr);
+    if (jcr->NumReadVolumes == 0) {
+       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for %s.\n"), Type);
+       goto bail_out;
+@@ -161,11 +159,8 @@
+       }
+    }
+-   free_restore_volume_list(jcr);
+-
+    dir_send_job_status(jcr);          /* update director */
+-
+    Dmsg0(30, "Done reading.\n");
+    jcr->end_time = time(NULL);
+    dequeue_messages(jcr);             /* send any queued messages */
+Index: src/stored/vol_mgr.c
+===================================================================
+--- src/stored/vol_mgr.c       (revision 8699)
++++ src/stored/vol_mgr.c       (working copy)
+@@ -529,6 +529,7 @@
+    VOLRES vol, *fvol;
+    if (read_vol_list->empty()) {
++      Dmsg0(dbglvl, "find_read_vol: read_vol_list empty.\n");
+       return NULL;
+    }
+    /* Do not lock reservations here */
+Index: src/stored/job.c
+===================================================================
+--- src/stored/job.c   (revision 8699)
++++ src/stored/job.c   (working copy)
+@@ -371,6 +371,8 @@
+       free_bsr(jcr->bsr);
+       jcr->bsr = NULL;
+    }
++   /* Free any restore volume list created */
++   free_restore_volume_list(jcr);
+    if (jcr->RestoreBootstrap) {
+       unlink(jcr->RestoreBootstrap);
+       free_pool_memory(jcr->RestoreBootstrap);
+Index: src/stored/acquire.c
+===================================================================
+--- src/stored/acquire.c       (revision 8699)
++++ src/stored/acquire.c       (working copy)
+@@ -187,7 +187,7 @@
+    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
+       Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n", 
+          dcr->VolumeName, jcr->errmsg);
+-      Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
++      Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
+    }
+    dev->set_load();                /* set to load volume */
+    
+@@ -241,7 +241,7 @@
+           *  error messages when nothing is mounted.
+           */
+          if (tape_previously_mounted) {
+-            Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
++            Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
+          }
+          goto default_path;
+       case VOL_NAME_ERROR:
+@@ -257,7 +257,7 @@
+          dev->set_load();
+          /* Fall through */
+       default:
+-         Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
++         Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
+ default_path:
+          Dmsg0(50, "default path\n");
+          tape_previously_mounted = true;
index fc49cb74ef23fa7d18e07152343f56636b8007f9..4521cf02aabc37f91d0606606361269703782960 100644 (file)
@@ -55,7 +55,6 @@
 
 static const int dbglevel = 10;
 
-static char OKbootstrap[] = "3000 OK bootstrap\n";
 static int get_job_to_migrate(JCR *jcr);
 struct idpkt;
 static bool regex_find_jobids(JCR *jcr, idpkt *ids, const char *query1,
@@ -353,15 +352,11 @@ bool do_migration(JCR *jcr)
            ((STORE *)jcr->rstorage->first())->name());
       return false;
    }
-   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage)) {
+   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage, /*send_bsr*/true)) {
       return false;
    }
    Dmsg0(150, "Storage daemon connection OK\n");
 
-   if (!send_bootstrap_file(jcr, sd) ||
-       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
-      return false;
-   }
 
    /*    
     * We re-update the job start record so that the start
index f9cc3a2113b940e27f808bca7c7fa0b8156c281d..1955ccc093c46993cd0f9ab26bc47a81a42196ee 100644 (file)
@@ -144,10 +144,12 @@ bool update_device_res(JCR *jcr, DEVICE *dev)
 }
 #endif
 
+static char OKbootstrap[] = "3000 OK bootstrap\n";
+
 /*
  * Start a job with the Storage daemon
  */
-bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore)
+bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore, bool send_bsr)
 {
    bool ok = true;
    STORE *storage;
@@ -196,7 +198,7 @@ bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore)
                   &jcr->VolSessionTime, &auth_key) != 3) {
           Dmsg1(100, "BadJob=%s\n", sd->msg);
           Jmsg(jcr, M_FATAL, 0, _("Storage daemon rejected Job command: %s\n"), sd->msg);
-          return 0;
+          return false;
        } else {
           jcr->sd_auth_key = bstrdup(auth_key);
           Dmsg1(150, "sd_auth_key=%s\n", jcr->sd_auth_key);
@@ -204,7 +206,12 @@ bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore)
    } else {
       Jmsg(jcr, M_FATAL, 0, _("<stored: bad response to Job command: %s\n"),
          sd->bstrerror());
-      return 0;
+      return false;
+   }
+
+   if (send_bsr && (!send_bootstrap_file(jcr, sd) ||
+       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR))) {
+      return false;
    }
 
    /*
index 26e5d7194443bd8967e168c14061be9fe623135f..dc66f8d3c521d1b6ae1857f6fef00218d2bbba3e 100644 (file)
@@ -155,7 +155,8 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf);
 /* msgchan.c */
 extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
                               int max_retry_time, int verbose);
-extern bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore);
+extern bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore,
+              bool send_bsr=false);
 extern bool start_storage_daemon_message_thread(JCR *jcr);
 extern int bget_dirmsg(BSOCK *bs);
 extern void wait_for_storage_daemon_termination(JCR *jcr);
index 9ae9c65d063372c217c394c5f745d751eb17ebf4..45a1f7e06522e6bbe41fc02365ca9c16840ea3b2 100644 (file)
@@ -50,8 +50,6 @@
 
 static const int dbglevel = 10;
 
-static char OKbootstrap[] = "3000 OK bootstrap\n";
-
 static bool create_bootstrap_file(JCR *jcr, POOLMEM *jobids);
 void vbackup_cleanup(JCR *jcr, int TermCode);
 
@@ -217,16 +215,11 @@ _("This Job is not an Accurate backup so is not equivalent to a Full backup.\n")
    /*
     * Now start a job with the Storage daemon
     */
-   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage)) {
+   if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage, /*send_bsr*/true)) {
       return false;
    }
    Dmsg0(100, "Storage daemon connection OK\n");
 
-   if (!send_bootstrap_file(jcr, sd) ||
-       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
-      return false;
-   }
-
    /*    
     * We re-update the job start record so that the start
     *  time is set after the run before job.  This avoids 
index 06c280efd8087189b289c070de27be7b733fc8c1..50e767b6114d85a2a7d6ae5bd0e8ecfd852b6486 100644 (file)
@@ -187,7 +187,7 @@ bool acquire_device_for_read(DCR *dcr)
    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
       Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n", 
          dcr->VolumeName, jcr->errmsg);
-      Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+      Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
    }
    dev->set_load();                /* set to load volume */
    
@@ -241,7 +241,7 @@ bool acquire_device_for_read(DCR *dcr)
           *  error messages when nothing is mounted.
           */
          if (tape_previously_mounted) {
-            Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+            Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
          }
          goto default_path;
       case VOL_NAME_ERROR:
@@ -257,7 +257,7 @@ bool acquire_device_for_read(DCR *dcr)
          dev->set_load();
          /* Fall through */
       default:
-         Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+         Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
 default_path:
          Dmsg0(50, "default path\n");
          tape_previously_mounted = true;
index 993bf1a8720b37863a7c0e994398640db87fef5f..88223497b662e1316c31969f43ae89982ac270aa 100644 (file)
@@ -388,6 +388,8 @@ bool get_bootstrap_file(JCR *jcr, BSOCK *sock)
    if (debug_level >= 10) {
       dump_bsr(jcr->bsr, true);
    }
+   /* If we got a bootstrap, we are reading, so create read volume list */
+   create_restore_volume_list(jcr);
    ok = true;
 
 bail_out:
index 8b5add3f589f093f66478e39ec508b9dafccc635..de9b2bb50cd4d1a11cf6a52d46ea44784b209c03 100644 (file)
@@ -371,6 +371,8 @@ void stored_free_jcr(JCR *jcr)
       free_bsr(jcr->bsr);
       jcr->bsr = NULL;
    }
+   /* Free any restore volume list created */
+   free_restore_volume_list(jcr);
    if (jcr->RestoreBootstrap) {
       unlink(jcr->RestoreBootstrap);
       free_pool_memory(jcr->RestoreBootstrap);
index b7768a811f8cea93735a08a25cb9d796622c2873..ce2c3707976f378984b7dd076b3a0e790fd4c430 100644 (file)
@@ -84,8 +84,6 @@ bool do_mac(JCR *jcr)
    }
    Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr);
 
-
-   create_restore_volume_list(jcr);
    if (jcr->NumReadVolumes == 0) {
       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for %s.\n"), Type);
       goto bail_out;
@@ -161,11 +159,8 @@ ok_out:
       }
    }
 
-   free_restore_volume_list(jcr);
-
    dir_send_job_status(jcr);          /* update director */
 
-
    Dmsg0(30, "Done reading.\n");
    jcr->end_time = time(NULL);
    dequeue_messages(jcr);             /* send any queued messages */
index 3798435217333ad585587f122d2a4a69a691a7ac..f5e0108de2f178c2fc0bd0a35a225ac65e158e85 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
index aa0ae705678794ce70fffa1fd48a80af06c4628c..7d50550902977492e368dd333474ad4c0f2d2467 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -62,11 +62,8 @@ bool do_read_data(JCR *jcr)
       return false;
    }
 
-
-   create_restore_volume_list(jcr);
    if (jcr->NumReadVolumes == 0) {
       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
-      free_restore_volume_list(jcr);
       fd->fsend(FD_error);
       return false;
    }
@@ -76,7 +73,6 @@ bool do_read_data(JCR *jcr)
 
    /* Ready device for reading */
    if (!acquire_device_for_read(dcr)) {
-      free_restore_volume_list(jcr);
       fd->fsend(FD_error);
       return false;
    }
@@ -92,7 +88,6 @@ bool do_read_data(JCR *jcr)
       ok = false;
    }
 
-   free_restore_volume_list(jcr);
    Dmsg0(30, "Done reading.\n");
    return ok;
 }
index 54b00b81480a6d2b8608b6d03745872d8af2f7e4..4e239fcd7c20edd7c4b6c456f4e337817cab146b 100644 (file)
@@ -529,6 +529,7 @@ static VOLRES *find_read_volume(const char *VolumeName)
    VOLRES vol, *fvol;
 
    if (read_vol_list->empty()) {
+      Dmsg0(dbglvl, "find_read_vol: read_vol_list empty.\n");
       return NULL;
    }
    /* Do not lock reservations here */
index 451395303d41f5149576f3df41e745f6ca2e5199..d73cbb05b4720440c320b938efec4b40f6b9b206 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "3.0.0"
-#define BDATE   "06 April 2009"
-#define LSMDATE "06Apr09"
+#define BDATE   "11 April 2009"
+#define LSMDATE "11Apr09"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2009 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2009"       /* year for copyright messages in progs */
index 6ee0b779f608b865c330ae8bdf602708a6dc058f..c6a118c0ce90a6838a27e7257750a8a22d4f2813 100644 (file)
@@ -2,6 +2,12 @@
           
 General:
 
+11Apr09
+kes  Modify insertion of read Volumes in SD to be done before the
+     drive reservation. This ensures that a Volume to be read will not
+     be reserved for writing.
+
+Release Version 3.0.0
 06Apr09
 kes  Change default plugins dir to /usr/lib.
 05Apr09