Buglet in tdb/common/freelist.c:tdb_allocate_ofs

Richard Sharpe realrichardsharpe at gmail.com
Tue Jan 20 21:17:40 GMT 2009


There is a small buglet tdb/common/freelist.c:tdb_allocate_ofs that
causes 48 bytes to be wasted every now and then. You can see it below.

00074f70: 3900 4242 5800 0000 c813 0700 7000 0000  9.BBX.......p...
00074f80: 0a00 0000 3000 0000 980e 8766 9919 0126  ....0......f...&
00074f90: 4749 4420 3530 3933 3900 532d 312d 352d  GID 50939.S-1-5-
00074fa0: 3231 2d31 3333 3535 3634 3937 362d 3138  21-1335564976-18
00074fb0: 3933 3136 3134 3134 2d31 3834 3639 3532  93161414-1846952
00074fc0: 3630 342d 3735 3431 3800 4242 4242 4242  604-75418.BBBBBB
00074fd0: 4242 4242 4242 4242 4242 4242 4242 4242  BBBBBBBBBBBBBBBB
00074fe0: 4242 4242 4242 4242 4242 4242 4242 4242  BBBBBBBBBBBBBBBB
00074ff0: 4242 4242 4242 4242 4242 4242 8800 0000  BBBBBBBBBBBB....

It looks to me like it occurs when we are allocating a new record from
the only entry on the freelist and the the free space is at the end of
the file. If there is not 52 bytes more than we need, we take the
whole lot, even though we are going to expand the file on the next
allocation.

The problem is in this piece of code:

        /* found it - now possibly split it up  */
        if (rec->rec_len > length + MIN_REC_SIZE) {
                /* Length of left piece */
                length = TDB_ALIGN(length, TDB_ALIGNMENT);

                /* Right piece to go on free list */
                newrec.rec_len = rec->rec_len - (sizeof(*rec) + length);
                newrec_ptr = rec_ptr + sizeof(*rec) + length;

                /* And left record is shortened */
                rec->rec_len = length;
        } else {
                newrec_ptr = 0;
        }

Perhaps the test should also check to see if the candidate record is
near the end of the file.


-- 
Regards,
Richard Sharpe


More information about the samba-technical mailing list