]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Correct seg fault when switching tape drives during restore.
authorKern Sibbald <kern@sibbald.com>
Mon, 6 Aug 2007 18:20:26 +0000 (18:20 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 6 Aug 2007 18:20:26 +0000 (18:20 +0000)
kes  Commit uid_gid_name.c (replacement for idcache.c), but will not
     be used until after 2.2.0 release.

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

bacula/src/filed/restore.c
bacula/src/lib/uid_gid_name.c [new file with mode: 0644]
bacula/src/stored/acquire.c
bacula/src/stored/dev.h
bacula/src/stored/read.c
bacula/src/stored/read_record.c
bacula/src/version.h
bacula/technotes-2.1

index acfaafbe5d2f36683431d3223baaff8a46c2aad1..c505971de867124164067428a853a9b451c2528e 100644 (file)
@@ -654,7 +654,7 @@ void do_restore(JCR *jcr)
          }
          Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
               rctx.stream);
-         Dmsg2(0, "None of above!!! stream=%d data=%s\n", rctx.stream,sd->msg);
+         Dmsg2(0, "Unknown stream=%d data=%s\n", rctx.stream, sd->msg);
          break;
       } /* end switch(stream) */
 
diff --git a/bacula/src/lib/uid_gid_name.c b/bacula/src/lib/uid_gid_name.c
new file mode 100644 (file)
index 0000000..7f7d665
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2007 Kern Sibbald
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation, which is 
+   listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * Written by Kern Sibbald, July 2005 to replace idcache.c
+ * 
+ *  Program to convert uid and gid into names, and cache the results
+ *   for preformance reasons.
+ */
+
+#include "bacula.h"
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct guitem {
+   dlink link;
+   char *name;
+   union {
+      uid_t uid;
+      gid_t gid;
+   };
+};
+
+class guid_list {
+public:
+   dlist *uid_list;
+   dlist *gid_list;
+
+   char *uid_to_name(uid_t uid, char *name, int maxlen);
+   char *gid_to_name(gid_t gid, char *name, int maxlen);
+};
+
+guid_list *new_guid_list()
+{
+   guid_list *list;
+   guitem *item = NULL;
+   list = (guid_list *)malloc(sizeof(guid_list));
+   list->uid_list = New(dlist(item, &item->link));
+   list->gid_list = New(dlist(item, &item->link));
+   return list;
+}
+
+void free_guid_list(guid_list *list)
+{
+   guitem *item;
+   foreach_dlist(item, list->uid_list) {
+      free(item->name);
+   }
+   foreach_dlist(item, list->gid_list) {
+      free(item->name);
+   }
+   delete list->uid_list;
+   delete list->gid_list;
+   free(list);
+}
+
+static int uid_compare(void *item1, void *item2)
+{
+   guitem *i1 = (guitem *)item1;
+   guitem *i2 = (guitem *)item2;
+   if (i1->uid < i2->uid) {
+      return -1;
+   } else if (i1->uid > i2->uid) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
+
+static int gid_compare(void *item1, void *item2)
+{
+   guitem *i1 = (guitem *)item1;
+   guitem *i2 = (guitem *)item2;
+   if (i1->gid < i2->gid) {
+      return -1;
+   } else if (i1->gid > i2->gid) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
+
+
+static void get_uidname(uid_t uid, guitem *item)
+{
+#ifndef HAVE_WIN32
+   struct passwd *pwbuf;
+   P(mutex);
+   pwbuf = getpwuid(uid);
+   if (pwbuf != NULL && strcmp(pwbuf->pw_name, "????????") != 0) {
+      item->name = bstrdup(pwbuf->pw_name);
+   }
+   V(mutex);
+#endif
+}
+
+static void get_gidname(gid_t gid, guitem *item)
+{
+#ifndef HAVE_WIN32
+   struct group *grbuf;
+   P(mutex);
+   grbuf = getgrgid(gid);
+   if (grbuf != NULL && strcmp(grbuf->gr_name, "????????") != 0) {
+      item->name = bstrdup(grbuf->gr_name);
+   }
+   V(mutex);
+#endif
+}
+
+
+char *guid_list::uid_to_name(uid_t uid, char *name, int maxlen)
+{
+   guitem sitem, *item, *fitem;
+   sitem.uid = uid;
+   char buf[50];
+
+   item = (guitem *)uid_list->binary_search(&sitem, uid_compare);
+   Dmsg2(900, "uid=%d item=%p\n", uid, item);
+   if (!item) {
+      item = (guitem *)malloc(sizeof(guitem));
+      item->uid = uid;
+      item->name = NULL;
+      get_uidname(uid, item);
+      if (!item->name) {
+         item->name = bstrdup(edit_int64(uid, buf));
+         Dmsg2(900, "set uid=%d name=%s\n", uid, item->name);
+      }
+      fitem = (guitem *)uid_list->binary_insert(item, uid_compare);
+      if (fitem != item) {               /* item already there this shouldn't happen */
+         free(item);
+         item = fitem;   
+      }
+   }
+   bstrncpy(name, item->name, maxlen);
+   return name;
+}
+
+char *guid_list::gid_to_name(gid_t gid, char *name, int maxlen)
+{
+   guitem sitem, *item, *fitem;
+   sitem.gid = gid;
+   char buf[50];
+
+   item = (guitem *)uid_list->binary_search(&sitem, gid_compare);
+   if (!item) {
+      item = (guitem *)malloc(sizeof(guitem));
+      item->gid = gid;
+      item->name = NULL;
+      get_gidname(gid, item);
+      if (!item->name) {
+         item->name = bstrdup(edit_int64(gid, buf));
+      }
+      fitem = (guitem *)gid_list->binary_insert(item, gid_compare);
+      if (fitem != item) {               /* item already there this shouldn't happen */
+         free(item);
+         item = fitem;   
+      }
+   }
+
+   bstrncpy(name, item->name, maxlen);
+   return name;
+}
+
+#ifdef TEST_PROGRAM
+
+int main()
+{
+   int i;
+   guid_list *list;
+   char ed1[50], ed2[50];
+   list = new_guid_list();
+   for (i=0; i<1001; i++) {
+      printf("uid=%d name=%s  gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
+         i, list->gid_to_name(i, ed2, sizeof(ed2)));
+      printf("uid=%d name=%s  gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
+         i, list->gid_to_name(i, ed2, sizeof(ed2)));
+   }
+    
+   free_guid_list(list);
+   sm_dump(false);
+
+   return 0;
+}
+#endif
index f1efa711888fe7af1e0c19d5e9de93daa33a0d26..5736d70334c5fc084c967f19e41905e9525f327e 100644 (file)
@@ -62,7 +62,7 @@ bool acquire_device_for_read(DCR *dcr)
    int vol_label_status;
    int retry = 0;
    
-   Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
+   Dmsg1(950, "jcr->dcr=%p\n", jcr->dcr);
    dev->dblock(BST_DOING_ACQUIRE);
 
    if (dev->num_writers > 0) {
@@ -97,6 +97,12 @@ bool acquire_device_for_read(DCR *dcr)
     *  same as the current drive, we attempt to find the same
     *  device that was used to write the orginal volume.  If
     *  found, we switch to using that device.
+    *
+    *  N.B. A lot of routines rely on the dcr pointer not changing
+    *    read_records.c even has multiple dcrs cached, so we take care
+    *    here to release all important parts of the dcr and re-acquire
+    *    them such as the block pointer (size may change), but we do
+    *    not release the dcr.
     */
    Dmsg2(50, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
    if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
@@ -107,9 +113,11 @@ bool acquire_device_for_read(DCR *dcr)
       Jmsg3(jcr, M_INFO, 0, _("Changing device. Want Media Type=\"%s\" have=\"%s\"\n"
                               "  device=%s\n"), 
             dcr->media_type, dev->device->media_type, dev->print_name());
+      Dmsg3(50, "Changing device. Want Media Type=\"%s\" have=\"%s\"\n"
+                              "  device=%s\n", 
+            dcr->media_type, dev->device->media_type, dev->print_name());
 
       dev->dunblock(DEV_UNLOCKED);
-      detach_dcr_from_dev(dcr);    /* release old device */
 
       lock_reservations();
       memset(&rctx, 0, sizeof(RCTX));
@@ -125,30 +133,35 @@ bool acquire_device_for_read(DCR *dcr)
       bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
       store->append = false;
       rctx.store = store;
+      dcr->keep_dcr = true;                  /* do not free the dcr */
+      release_device(dcr);
+      dcr->keep_dcr = false;
       
       /*
-       * Note, if search_for_device() succeeds, we get a new dcr,
-       *  which we do not use except for the dev info.
+       * Search for a new device
        */
       stat = search_res_for_device(rctx);
       release_reserve_messages(jcr);         /* release queued messages */
       unlock_reservations();
-      dev->dblock(BST_DOING_ACQUIRE); 
+
       if (stat == 1) {
+         dev = dcr->dev;                     /* get new device pointer */
+         dev->dblock(BST_DOING_ACQUIRE); 
          dcr->VolumeName[0] = 0;
          Jmsg(jcr, M_INFO, 0, _("Media Type change.  New device %s chosen.\n"),
             dev->print_name());
+         Dmsg1(50, "Media Type change.  New device %s chosen.\n", dev->print_name());
+
          bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
          bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
          dcr->VolCatInfo.Slot = vol->Slot;
          bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
          bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
-      } else if (stat == 0) {   /* device busy */
-         Pmsg1(000, "Device %s is busy.\n", vol->device);
       } else {
          /* error */
          Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
             vol->VolumeName);
+         Dmsg1(50, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
          goto get_out;
       }
    }
@@ -193,11 +206,10 @@ bool acquire_device_for_read(DCR *dcr)
               dev->print_name(), dcr->VolumeName, dev->bstrerror());
          goto default_path;
       }
-      Dmsg1(100, "opened dev %s OK\n", dev->print_name());
+      Dmsg1(50, "opened dev %s OK\n", dev->print_name());
       
       /* Read Volume Label */
-      
-      Dmsg0(200, "calling read-vol-label\n");
+      Dmsg0(50, "calling read-vol-label\n");
       vol_label_status = read_dev_volume_label(dcr);
       switch (vol_label_status) {
       case VOL_OK:
@@ -275,13 +287,13 @@ default_path:
 
 get_out:
    dev->dlock();
-   if (dcr->reserved_device) {
+   if (dcr && dcr->reserved_device) {
       dev->reserved_device--;
-      Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
+      Dmsg2(50, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
       dcr->reserved_device = false;
    }
    dev->dunblock(DEV_LOCKED);
-   Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
+   Dmsg1(950, "jcr->dcr=%p\n", jcr->dcr);
    return ok;
 }
 
@@ -551,13 +563,17 @@ bool release_device(DCR *dcr)
    Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
    pthread_cond_broadcast(&wait_device_release);
    dev->dunlock();
-   if (jcr->read_dcr == dcr) {
-      jcr->read_dcr = NULL;
-   }
-   if (jcr->dcr == dcr) {
-      jcr->dcr = NULL;
+   if (dcr->keep_dcr) {
+      detach_dcr_from_dev(dcr);
+   } else {
+      if (jcr->read_dcr == dcr) {
+         jcr->read_dcr = NULL;
+      }
+      if (jcr->dcr == dcr) {
+         jcr->dcr = NULL;
+      }
+      free_dcr(dcr);
    }
-   free_dcr(dcr);
    Dmsg2(100, "===== Device %s released by JobId=%u\n", dev->print_name(),
          (uint32_t)jcr->JobId);
    return ok;
index 5babdf67b28e9246981ec44848e1f7bc72aaa447..39f4306b5dfb0d9b1d4ef983f67244b7b2bd34c7 100644 (file)
@@ -439,6 +439,7 @@ public:
    bool any_volume;                   /* Any OK for dir_find_next... */
    bool attached_to_dev;              /* set when attached to dev */
    bool volume_in_use;                /* set in dir_find_next_appendable_volume() */
+   bool keep_dcr;                     /* do not free dcr in release_dcr */
    uint32_t VolFirstIndex;            /* First file index this Volume */
    uint32_t VolLastIndex;             /* Last file index this Volume */
    uint32_t FileIndex;                /* Current File Index */
index 90a7c04645ef061cd33c80cc9b23ef86fd2e4bf1..da554ddb8410ca99dd5a9759af06829137e41cc5 100644 (file)
@@ -1,14 +1,7 @@
-/*
- * Read code for Storage daemon
- *
- *     Kern Sibbald, November MM
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2007 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.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ * Read code for Storage daemon
+ *
+ *     Kern Sibbald, November MM
+ *
+ *   Version $Id$
+ */
 
 #include "bacula.h"
 #include "stored.h"
@@ -67,7 +67,7 @@ bool do_read_data(JCR *jcr)
    if (jcr->NumReadVolumes == 0) {
       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
       free_restore_volume_list(jcr);
-      bnet_fsend(fd, FD_error);
+      fd->fsend(FD_error);
       return false;
    }
 
@@ -77,16 +77,16 @@ bool do_read_data(JCR *jcr)
    /* Ready device for reading */
    if (!acquire_device_for_read(dcr)) {
       free_restore_volume_list(jcr);
-      bnet_fsend(fd, FD_error);
+      fd->fsend(FD_error);
       return false;
    }
 
    /* Tell File daemon we will send data */
-   bnet_fsend(fd, OK_data);
+   fd->fsend(OK_data);
    ok = read_records(dcr, record_cb, mount_next_read_volume);
 
    /* Send end of data to FD */
-   bnet_sig(fd, BNET_EOD);
+   fd->signal(BNET_EOD);
 
    if (!release_device(jcr->read_dcr)) {
       ok = false;
@@ -117,11 +117,11 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
       rec->data_len);
 
    /* Send record header to File daemon */
-   if (!bnet_fsend(fd, rec_header, rec->VolSessionId, rec->VolSessionTime,
+   if (!fd->fsend(rec_header, rec->VolSessionId, rec->VolSessionTime,
           rec->FileIndex, rec->Stream, rec->data_len)) {
       Pmsg1(000, _(">filed: Error Hdr=%s\n"), fd->msg);
       Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
-         bnet_strerror(fd));
+         fd->bstrerror());
       return false;
    } else {
       Dmsg1(400, ">filed: Hdr=%s\n", fd->msg);
@@ -130,13 +130,13 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
 
    /* Send data record to File daemon */
    save_msg = fd->msg;          /* save fd message pointer */
-   fd->msg = rec->data;         /* pass data directly to bnet_send */
+   fd->msg = rec->data;         /* pass data directly to the FD */
    fd->msglen = rec->data_len;
    Dmsg1(400, ">filed: send %d bytes data.\n", fd->msglen);
-   if (!bnet_send(fd)) {
-      Pmsg1(000, _("Error sending to FD. ERR=%s\n"), bnet_strerror(fd));
+   if (!fd->send()) {
+      Pmsg1(000, _("Error sending to FD. ERR=%s\n"), fd->bstrerror());
       Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
-         bnet_strerror(fd));
+         fd->bstrerror());
 
       ok = false;
    }
index 6c2b52fe3cfd642dbbc3de776e3350c913777ae6..69707e247d91152f229fd7bf33881cf2c60c53f6 100644 (file)
@@ -1,22 +1,7 @@
-/*
- *
- *  This routine provides a routine that will handle all
- *    the gory little details of reading a record from a Bacula
- *    archive. It uses a callback to pass you each record in turn,
- *    as well as a callback for mounting the next tape.  It takes
- *    care of reading blocks, applying the bsr, ...
- *    Note, this routine is really the heart of the restore routines,
- *    and we are *really* bit pushing here so be careful about making
- *    any modifications.
- *
- *    Kern E. Sibbald, August MMII
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2007 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.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ *
+ *  This routine provides a routine that will handle all
+ *    the gory little details of reading a record from a Bacula
+ *    archive. It uses a callback to pass you each record in turn,
+ *    as well as a callback for mounting the next tape.  It takes
+ *    care of reading blocks, applying the bsr, ...
+ *    Note, this routine is really the heart of the restore routines,
+ *    and we are *really* bit pushing here so be careful about making
+ *    any modifications.
+ *
+ *    Kern E. Sibbald, August MMII
+ *
+ *   Version $Id$
+ */
 
 #include "bacula.h"
 #include "stored.h"
@@ -103,9 +103,10 @@ bool read_records(DCR *dcr,
             jcr->mount_next_volume = false;
             /*  
              * The Device can change at the end of a tape, so refresh it
-             *   from the dcr.
+             *   and the block from the dcr.
              */
             dev = dcr->dev;
+            block = dcr->block;
             /*
              * We just have a new tape up, now read the label (first record)
              *  and pass it off to the callback routine, then continue
index 4715735305f6b320244cc6d984f39509832d5927..684687652f998673135053fc0fe1133d12853911 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "2.1.29"
-#define BDATE   "04 August 2007"
-#define LSMDATE "04Aug07"
+#define BDATE   "06 August 2007"
+#define LSMDATE "06Aug07"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2007"       /* year for copyright messages in progs */
index 0fae8c96de30b28a374c4df5a8c76ef019ffc9cf..78cbe3058d5d9d24ccbc86723736e67eb990b58b 100644 (file)
@@ -1,6 +1,10 @@
               Technical notes on version 2.1
 
 General:
+06Aug07
+kes  Correct seg fault when switching tape drives during restore.
+kes  Commit uid_gid_name.c (replacement for idcache.c), but will not
+     be used until after 2.2.0 release.
 04Aug07
 kes  Remove fnmatch() in SD that permitted wild card specifications.
      This fixes bug #914.