]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/smartall.c
ebl add Error status in update volume=xxx status=yyyy
[bacula/bacula] / bacula / src / lib / smartall.c
1 /*
2
3                          S M A R T A L L O C
4                         Smart Memory Allocator
5
6         Evolved   over   several  years,  starting  with  the  initial
7         SMARTALLOC code for AutoSketch in 1986, guided  by  the  Blind
8         Watchbreaker,  John  Walker.  Isolated in this general-purpose
9         form in  September  of  1989.   Updated  with  be  more  POSIX
10         compliant  and  to  include Web-friendly HTML documentation in
11         October  of  1998  by  the  same  culprit.    For   additional
12         information and the current version visit the Web page:
13
14                   http://www.fourmilab.ch/smartall/
15
16
17          Version $Id$
18
19 */
20 /*
21    Bacula® - The Network Backup Solution
22
23    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
24
25    The main author of Bacula is Kern Sibbald, with contributions from
26    many others, a complete list can be found in the file AUTHORS.
27    This program is Free Software; you can redistribute it and/or
28    modify it under the terms of version two of the GNU General Public
29    License as published by the Free Software Foundation plus additions
30    that are listed in the file LICENSE.
31
32    This program is distributed in the hope that it will be useful, but
33    WITHOUT ANY WARRANTY; without even the implied warranty of
34    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35    General Public License for more details.
36
37    You should have received a copy of the GNU General Public License
38    along with this program; if not, write to the Free Software
39    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40    02110-1301, USA.
41
42    Bacula® is a registered trademark of John Walker.
43    The licensor of Bacula is the Free Software Foundation Europe
44    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
45    Switzerland, email:ftf@fsfeurope.org.
46 */
47
48 #include "bacula.h"
49 /* Use the real routines here */
50 #undef realloc
51 #undef calloc
52 #undef malloc
53 #undef free
54
55 /* We normally turn off debugging here.
56  *  If you want it, simply #ifdef all the
57  *  following off.
58  */
59 #undef Dmsg1
60 #undef Dmsg2
61 #undef Dmsg3
62 #undef Dmsg4
63 #define Dmsg1(l,f,a1)
64 #define Dmsg2(l,f,a1,a2)
65 #define Dmsg3(l,f,a1,a2,a3)
66 #define Dmsg4(l,f,a1,a2,a3,a4)
67
68
69 uint64_t sm_max_bytes = 0;
70 uint64_t sm_bytes = 0;
71 uint32_t sm_max_buffers = 0;
72 uint32_t sm_buffers = 0;
73
74 #ifdef SMARTALLOC
75
76 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
77
78 extern char my_name[];                /* daemon name */
79
80 typedef unsigned short sm_ushort;
81
82 #define EOS      '\0'              /* End of string sentinel */
83 #define sm_min(a, b) ((a) < (b) ? (a) : (b))
84
85 /*  Queue data structures  */
86
87 /*  Memory allocation control structures and storage.  */
88
89 struct abufhead {
90    struct b_queue abq;         /* Links on allocated queue */
91    unsigned ablen;             /* Buffer length in bytes */
92    const char *abfname;        /* File name pointer */
93    sm_ushort ablineno;         /* Line number of allocation */
94 };
95
96 static struct b_queue abqueue = {    /* Allocated buffer queue */
97    &abqueue, &abqueue
98 };
99
100
101 static bool bufimode = false;   /* Buffers not tracked when True */
102
103 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
104
105
106 /*  SMALLOC  --  Allocate buffer, enqueing on the orphaned buffer
107                  tracking list.  */
108
109 static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
110 {
111    char *buf;
112
113    /* Note:  Unix  MALLOC  actually  permits  a zero length to be
114       passed and allocates a valid block with  zero  user  bytes.
115       Such  a  block  can  later  be expanded with realloc().  We
116       disallow this based on the belief that it's better to  make
117       a  special case and allocate one byte in the rare case this
118       is desired than to miss all the erroneous occurrences where
119       buffer length calculation code results in a zero.  */
120
121    ASSERT(nbytes > 0);
122
123    nbytes += HEAD_SIZE + 1;
124    if ((buf = (char *)malloc(nbytes)) != NULL) {
125       struct abufhead *head = (struct abufhead *)buf;
126       P(mutex);
127       /* Enqueue buffer on allocated list */
128       qinsert(&abqueue, (struct b_queue *) buf);
129       head->ablen = nbytes;
130       head->abfname = bufimode ? NULL : fname;
131       head->ablineno = (sm_ushort) lineno;
132       /* Emplace end-clobber detector at end of buffer */
133       buf[nbytes - 1] = (uint8_t)((((long) buf) & 0xFF) ^ 0xC5);
134       buf += HEAD_SIZE;  /* Increment to user data start */
135       if (++sm_buffers > sm_max_buffers) {
136          sm_max_buffers = sm_buffers;
137       }
138       sm_bytes += nbytes;
139       if (sm_bytes > sm_max_bytes) {
140          sm_max_bytes = sm_bytes;
141       }
142       V(mutex);
143    } else {
144       Emsg0(M_ABORT, 0, _("Out of memory\n"));
145    }
146    Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
147 #if    SMALLOC_SANITY_CHECK > 0
148    if (sm_bytes > SMALLOC_SANITY_CHECK) {
149       Emsg0(M_ABORT, 0, _("Too much memory used."));
150    }
151 #endif
152    return (void *)buf;
153 }
154
155 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
156                     This is to accomodate mem_pool. */
157
158 void sm_new_owner(const char *fname, int lineno, char *buf)
159 {
160    buf -= HEAD_SIZE;  /* Decrement to header */
161    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
162    ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
163    return;
164 }
165
166 /*  SM_FREE  --  Update free pool availability.  FREE is never called
167                  except  through  this interface or by actuallyfree().
168                  free(x)  is  defined  to  generate  a  call  to  this
169                  routine.  */
170
171 void sm_free(const char *file, int line, void *fp)
172 {
173    char *cp = (char *) fp;
174    struct b_queue *qp;
175
176    if (cp == NULL) {
177       Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, line);
178    }
179
180    cp -= HEAD_SIZE;
181    qp = (struct b_queue *) cp;
182    struct abufhead *head = (struct abufhead *)cp;
183
184    P(mutex);
185    Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
186          head->ablen, fp,
187          head->abfname, head->ablineno);
188
189    /* The following assertions will catch virtually every release
190       of an address which isn't an allocated buffer. */
191    if (qp->qnext->qprev != qp) {
192       V(mutex);
193       Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, line);
194    }
195    if (qp->qprev->qnext != qp) {
196       V(mutex);
197       Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
198    }
199
200    /* The following assertion detects storing off the  end  of  the
201       allocated  space in the buffer by comparing the end of buffer
202       checksum with the address of the buffer.  */
203
204    if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) {
205       V(mutex);
206       Emsg2(M_ABORT, 0, _("Buffer overrun called from %s:%d\n"), file, line);
207    }
208    if (sm_buffers > 0) {
209       sm_buffers--;
210       sm_bytes -= head->ablen;
211    }
212
213    qdchain(qp);
214    V(mutex);
215
216    /* Now we wipe the contents of  the  just-released  buffer  with
217       "designer  garbage"  (Duff  Kurland's  phrase) of alternating
218       bits.  This is intended to ruin the day for any miscreant who
219       attempts to access data through a pointer into storage that's
220       been previously released. */
221
222    memset(cp, 0xAA, (int) head->ablen);
223
224    free(cp);
225 }
226
227 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
228                    was available.  */
229
230 void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
231 {
232    void *buf;
233
234    if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
235
236       /* To catch sloppy code that assumes  buffers  obtained  from
237          malloc()  are  zeroed,  we  preset  the buffer contents to
238          "designer garbage" consisting of alternating bits.  */
239
240       memset(buf, 0x55, (int) nbytes);
241    } else {
242       Emsg0(M_ABORT, 0, _("Out of memory\n"));
243    }
244    return buf;
245 }
246
247 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
248
249 void *sm_calloc(const char *fname, int lineno,
250                 unsigned int nelem, unsigned int elsize)
251 {
252    void *buf;
253
254    if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
255       memset(buf, 0, (int) (nelem * elsize));
256    } else {
257       Emsg0(M_ABORT, 0, _("Out of memory\n"));
258    }
259    return buf;
260 }
261
262 /*  SM_REALLOC  --  Adjust the size of a  previously  allocated  buffer.
263                     Note  that  the trick of "resurrecting" a previously
264                     freed buffer with realloc() is NOT supported by this
265                     function.   Further, because of the need to maintain
266                     our control storage, SM_REALLOC must always allocate
267                     a  new  block  and  copy  the data in the old block.
268                     This may result in programs which make heavy use  of
269                     realloc() running much slower than normally.  */
270
271 void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
272 {
273    unsigned osize;
274    void *buf;
275    char *cp = (char *) ptr;
276
277    Dmsg4(400, "sm_realloc %s:%d 0x%x %d\n", fname, lineno, ptr, size);
278    if (size <= 0) {
279       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
280    }
281
282    /*  If  the  old  block  pointer  is  NULL, treat realloc() as a
283       malloc().  SVID is silent  on  this,  but  many  C  libraries
284       permit this.  */
285
286    if (ptr == NULL) {
287       return sm_malloc(fname, lineno, size);
288    }
289
290    /* If the old and new sizes are the same, be a nice guy and just
291       return the buffer passed in.  */
292
293    cp -= HEAD_SIZE;
294    struct abufhead *head = (struct abufhead *)cp;
295    osize = head->ablen - (HEAD_SIZE + 1);
296    if (size == osize) {
297       return ptr;
298    }
299
300    /* Sizes differ.  Allocate a new buffer of the  requested  size.
301       If  we  can't  obtain  such a buffer, act as defined in SVID:
302       return NULL from  realloc()  and  leave  the  buffer  in  PTR
303       intact.  */
304
305 // sm_buffers--;
306 // sm_bytes -= head->ablen;
307
308    if ((buf = smalloc(fname, lineno, size)) != NULL) {
309       memcpy(buf, ptr, (int) sm_min(size, osize));
310       /* If the new buffer is larger than the old, fill the balance
311          of it with "designer garbage". */
312       if (size > osize) {
313          memset(((char *) buf) + osize, 0x55, (int) (size - osize));
314       }
315
316       /* All done.  Free and dechain the original buffer. */
317
318       sm_free(__FILE__, __LINE__, ptr);
319    }
320    Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno);
321    return buf;
322 }
323
324 /*  ACTUALLYMALLOC  --  Call the system malloc() function to obtain
325                         storage which will eventually be released
326                         by system or library routines not compiled
327                         using SMARTALLOC.  */
328
329 void *actuallymalloc(unsigned int size)
330 {
331    return malloc(size);
332 }
333
334 /*  ACTUALLYCALLOC  --  Call the system calloc() function to obtain
335                         storage which will eventually be released
336                         by system or library routines not compiled
337                         using SMARTALLOC.  */
338
339 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
340 {
341    return calloc(nelem, elsize);
342 }
343
344 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
345                          storage which will eventually be released
346                          by system or library routines not compiled
347                          using SMARTALLOC.  */
348
349 void *actuallyrealloc(void *ptr, unsigned int size)
350 {
351    Dmsg2(400, "Actuallyrealloc 0x%x %d\n", ptr, size);
352    return realloc(ptr, size);
353 }
354
355 /*  ACTUALLYFREE  --  Interface to system free() function to release
356                       buffers allocated by low-level routines. */
357
358 void actuallyfree(void *cp)
359 {
360    free(cp);
361 }
362
363 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
364  *               True).
365  *  N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
366  *    as they have all been shut down at this point.
367  */
368 void sm_dump(bool bufdump)
369 {
370    struct abufhead *ap;
371
372    P(mutex);
373
374    ap = (struct abufhead *)abqueue.qnext;
375
376    while (ap != (struct abufhead *) &abqueue) {
377
378       if ((ap == NULL) ||
379           (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
380           (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
381          fprintf(stderr, _(
382             "\nOrphaned buffers exist.  Dump terminated following\n"
383             "  discovery of bad links in chain of orphaned buffers.\n"
384             "  Buffer address with bad links: %lx\n"), (long) ap);
385          break;
386       }
387
388       if (ap->abfname != NULL) {
389          unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
390          char errmsg[500];
391
392          bsnprintf(errmsg, sizeof(errmsg),
393            _("Orphaned buffer:  %6u bytes allocated at line %d of %s %s\n"),
394             memsize, ap->ablineno, my_name, ap->abfname
395          );
396          fprintf(stderr, "%s", errmsg);
397          if (bufdump) {
398             char buf[20];
399             unsigned llen = 0;
400             char *cp = ((char *) ap) + HEAD_SIZE;
401
402             errmsg[0] = EOS;
403             while (memsize) {
404                if (llen >= 16) {
405                   bstrncat(errmsg, "\n", sizeof(errmsg));
406                   llen = 0;
407                   fprintf(stderr, "%s", errmsg);
408                   errmsg[0] = EOS;
409                }
410                bsnprintf(buf, sizeof(buf), " %02X",
411                   (*cp++) & 0xFF);
412                bstrncat(errmsg, buf, sizeof(errmsg));
413                llen++;
414                memsize--;
415             }
416             fprintf(stderr, "%s\n", errmsg);
417          }
418       }
419       ap = (struct abufhead *) ap->abq.qnext;
420    }
421    V(mutex);
422 }
423
424 #undef sm_check
425 /*  SM_CHECK --  Check the buffers and dump if any damage exists. */
426 void sm_check(const char *fname, int lineno, bool bufdump)
427 {
428         if (!sm_check_rtn(fname, lineno, bufdump)) {
429            Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
430               fname, lineno);
431         }
432 }
433
434 #undef sm_check_rtn
435 /*  SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
436 int sm_check_rtn(const char *fname, int lineno, bool bufdump)
437 {
438    struct abufhead *ap;
439    int bad, badbuf = 0;
440
441    P(mutex);
442    ap = (struct abufhead *) abqueue.qnext;
443    while (ap != (struct abufhead *) &abqueue) {
444       bad = 0;
445       if ((ap == NULL) ||
446           (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
447          bad = 0x1;
448       }
449       if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
450          bad |= 0x2;
451       }
452       if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
453            ((((long) ap) & 0xFF) ^ 0xC5)) {
454          bad |= 0x4;
455       }
456       badbuf |= bad;
457       if (bad) {
458          fprintf(stderr,
459             _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
460
461          if (bad & 0x1) {
462             fprintf(stderr, _("  discovery of bad prev link.\n"));
463          }
464          if (bad & 0x2) {
465             fprintf(stderr, _("  discovery of bad next link.\n"));
466          }
467          if (bad & 0x4) {
468             fprintf(stderr, _("  discovery of data overrun.\n"));
469          }
470
471          fprintf(stderr, _("  Buffer address: %lx\n"), (long) ap);
472
473          if (ap->abfname != NULL) {
474             unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
475             char errmsg[80];
476
477             fprintf(stderr,
478               _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
479                memsize, ap->ablineno, my_name, ap->abfname
480             );
481             if (bufdump) {
482                unsigned llen = 0;
483                char *cp = ((char *) ap) + HEAD_SIZE;
484
485                errmsg[0] = EOS;
486                while (memsize) {
487                   if (llen >= 16) {
488                      strcat(errmsg, "\n");
489                      llen = 0;
490                      fprintf(stderr, "%s", errmsg);
491                      errmsg[0] = EOS;
492                   }
493                   if (*cp < 0x20) {
494                      sprintf(errmsg + strlen(errmsg), " %02X",
495                         (*cp++) & 0xFF);
496                   } else {
497                      sprintf(errmsg + strlen(errmsg), " %c ",
498                         (*cp++) & 0xFF);
499                   }
500                   llen++;
501                   memsize--;
502                }
503                fprintf(stderr, "%s\n", errmsg);
504             }
505          }
506       }
507       ap = (struct abufhead *) ap->abq.qnext;
508    }
509    V(mutex);
510    return badbuf ? 0 : 1;
511 }
512
513
514 /*  SM_STATIC  --  Orphaned buffer detection can be disabled  (for  such
515                    items  as buffers allocated during initialisation) by
516                    calling   sm_static(1).    Normal   orphaned   buffer
517                    detection  can be re-enabled with sm_static(0).  Note
518                    that all the other safeguards still apply to  buffers
519                    allocated  when  sm_static(1)  mode is in effect.  */
520
521 void sm_static(int mode)
522 {
523    bufimode = (bool) (mode != 0);
524 }
525
526 /*
527  * Here we overload C++'s global new and delete operators
528  *  so that the memory is allocated through smartalloc.
529  */
530
531 #ifdef xxx
532 void * operator new(size_t size)
533 {
534 // Dmsg1(000, "new called %d\n", size);
535    return sm_malloc(__FILE__, __LINE__, size);
536 }
537
538 void operator delete(void *buf)
539 {
540 // Dmsg1(000, "free called 0x%x\n", buf);
541    sm_free(__FILE__, __LINE__, buf);
542 }
543 #endif
544
545 #endif