Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

Location:
vendor/current/lib/tdb/common
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/lib/tdb/common/check.c

    r414 r740  
    2929{
    3030        struct tdb_header hdr;
    31 
    32         if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), DOCONV()) == -1)
     31        uint32_t h1, h2;
     32
     33        if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1)
    3334                return false;
    3435        if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0)
     
    3940                goto corrupt;
    4041
    41         if (hdr.rwlocks != 0)
     42        if (hdr.rwlocks != 0 && hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC)
     43                goto corrupt;
     44
     45        tdb_header_hash(tdb, &h1, &h2);
     46        if (hdr.magic1_hash && hdr.magic2_hash &&
     47            (hdr.magic1_hash != h1 || hdr.magic2_hash != h2))
    4248                goto corrupt;
    4349
     
    302308}
    303309
    304 int tdb_check(struct tdb_context *tdb,
     310/* Slow, but should be very rare. */
     311size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off)
     312{
     313        size_t len;
     314
     315        for (len = 0; off + len < tdb->map_size; len++) {
     316                char c;
     317                if (tdb->methods->tdb_read(tdb, off, &c, 1, 0))
     318                        return 0;
     319                if (c != 0 && c != 0x42)
     320                        break;
     321        }
     322        return len;
     323}
     324
     325_PUBLIC_ int tdb_check(struct tdb_context *tdb,
    305326              int (*check)(TDB_DATA key, TDB_DATA data, void *private_data),
    306327              void *private_data)
     
    311332        struct tdb_record rec;
    312333        bool found_recovery = false;
    313 
    314         if (tdb_lockall(tdb) == -1)
    315                 return -1;
     334        tdb_len_t dead;
     335        bool locked;
     336
     337        /* Read-only databases use no locking at all: it's best-effort.
     338         * We may have a write lock already, so skip that case too. */
     339        if (tdb->read_only || tdb->allrecord_lock.count != 0) {
     340                locked = false;
     341        } else {
     342                if (tdb_lockall_read(tdb) == -1)
     343                        return -1;
     344                locked = true;
     345        }
    316346
    317347        /* Make sure we know true size of the underlying file. */
     
    370400                                goto free;
    371401                        break;
     402                /* If we crash after ftruncate, we can get zeroes or fill. */
     403                case TDB_RECOVERY_INVALID_MAGIC:
     404                case 0x42424242:
     405                        if (recovery_start == off) {
     406                                found_recovery = true;
     407                                break;
     408                        }
     409                        dead = tdb_dead_space(tdb, off);
     410                        if (dead < sizeof(rec))
     411                                goto corrupt;
     412
     413                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     414                                 "Dead space at %d-%d (of %u)\n",
     415                                 off, off + dead, tdb->map_size));
     416                        rec.rec_len = dead - sizeof(rec);
     417                        break;
    372418                case TDB_RECOVERY_MAGIC:
    373                 case 0: /* Used for invalid (or in-progress) recovery area. */
    374419                        if (recovery_start != off) {
    375420                                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     
    380425                        found_recovery = true;
    381426                        break;
    382                 default:
     427                default: ;
     428                corrupt:
    383429                        tdb->ecode = TDB_ERR_CORRUPT;
    384430                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     
    406452        if (recovery_start != 0 && !found_recovery) {
    407453                TDB_LOG((tdb, TDB_DEBUG_ERROR,
    408                          "Expected %s recovery area, got %s\n",
    409                          recovery_start ? "a" : "no",
    410                          found_recovery ? "one" : "none"));
     454                         "Expected a recovery area at %u\n",
     455                         recovery_start));
    411456                goto free;
    412457        }
    413458
    414459        free(hashes);
    415         tdb_unlockall(tdb);
     460        if (locked) {
     461                tdb_unlockall_read(tdb);
     462        }
    416463        return 0;
    417464
     
    419466        free(hashes);
    420467unlock:
    421         tdb_unlockall(tdb);
     468        if (locked) {
     469                tdb_unlockall_read(tdb);
     470        }
    422471        return -1;
    423472}
  • vendor/current/lib/tdb/common/dump.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    8181}
    8282
    83 void tdb_dump_all(struct tdb_context *tdb)
     83_PUBLIC_ void tdb_dump_all(struct tdb_context *tdb)
    8484{
    8585        int i;
     
    9191}
    9292
    93 int tdb_printfreelist(struct tdb_context *tdb)
     93_PUBLIC_ int tdb_printfreelist(struct tdb_context *tdb)
    9494{
    9595        int ret;
  • vendor/current/lib/tdb/common/error.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 enum TDB_ERROR tdb_error(struct tdb_context *tdb)
     30_PUBLIC_ enum TDB_ERROR tdb_error(struct tdb_context *tdb)
    3131{
    3232        return tdb->ecode;
     
    4747
    4848/* Error string for the last tdb error */
    49 const char *tdb_errorstr(struct tdb_context *tdb)
     49_PUBLIC_ const char *tdb_errorstr(struct tdb_context *tdb)
    5050{
    5151        uint32_t i;
  • vendor/current/lib/tdb/common/freelist.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    9999
    100100/* Add an element into the freelist. Merge adjacent records if
    101    neccessary. */
     101   necessary. */
    102102int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec)
    103103{
     
    144144                struct tdb_record l;
    145145                tdb_off_t leftsize;
    146                
     146
    147147                /* Read in tailer and jump back to header */
    148148                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
     
    335335                        break;
    336336                }
    337                
     337
    338338                /* this multiplier means we only extremely rarely
    339339                   search more than 50 or so records. At 50 records we
     
    368368   return the size of the freelist - used to decide if we should repack
    369369*/
    370 int tdb_freelist_size(struct tdb_context *tdb)
     370_PUBLIC_ int tdb_freelist_size(struct tdb_context *tdb)
    371371{
    372372        tdb_off_t ptr;
  • vendor/current/lib/tdb/common/freelistcheck.c

    r414 r740  
    4444}
    4545
    46 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
     46_PUBLIC_ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
    4747{
    4848        struct tdb_context *mem_tdb = NULL;
  • vendor/current/lib/tdb/common/io.c

    r597 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    477477        tdb_oob,
    478478        tdb_expand_file,
    479         tdb_brlock
    480479};
    481480
  • vendor/current/lib/tdb/common/lock.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 #define TDB_MARK_LOCK 0x80000000
    31 
    32 void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr)
     30_PUBLIC_ void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr)
    3331{
    3432        tdb->interrupt_sig_ptr = ptr;
     33}
     34
     35static int fcntl_lock(struct tdb_context *tdb,
     36                      int rw, off_t off, off_t len, bool waitflag)
     37{
     38        struct flock fl;
     39
     40        fl.l_type = rw;
     41        fl.l_whence = SEEK_SET;
     42        fl.l_start = off;
     43        fl.l_len = len;
     44        fl.l_pid = 0;
     45
     46        if (waitflag)
     47                return fcntl(tdb->fd, F_SETLKW, &fl);
     48        else
     49                return fcntl(tdb->fd, F_SETLK, &fl);
     50}
     51
     52static int fcntl_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len)
     53{
     54        struct flock fl;
     55#if 0 /* Check they matched up locks and unlocks correctly. */
     56        char line[80];
     57        FILE *locks;
     58        bool found = false;
     59
     60        locks = fopen("/proc/locks", "r");
     61
     62        while (fgets(line, 80, locks)) {
     63                char *p;
     64                int type, start, l;
     65
     66                /* eg. 1: FLOCK  ADVISORY  WRITE 2440 08:01:2180826 0 EOF */
     67                p = strchr(line, ':') + 1;
     68                if (strncmp(p, " POSIX  ADVISORY  ", strlen(" POSIX  ADVISORY  ")))
     69                        continue;
     70                p += strlen(" FLOCK  ADVISORY  ");
     71                if (strncmp(p, "READ  ", strlen("READ  ")) == 0)
     72                        type = F_RDLCK;
     73                else if (strncmp(p, "WRITE ", strlen("WRITE ")) == 0)
     74                        type = F_WRLCK;
     75                else
     76                        abort();
     77                p += 6;
     78                if (atoi(p) != getpid())
     79                        continue;
     80                p = strchr(strchr(p, ' ') + 1, ' ') + 1;
     81                start = atoi(p);
     82                p = strchr(p, ' ') + 1;
     83                if (strncmp(p, "EOF", 3) == 0)
     84                        l = 0;
     85                else
     86                        l = atoi(p) - start + 1;
     87
     88                if (off == start) {
     89                        if (len != l) {
     90                                fprintf(stderr, "Len %u should be %u: %s",
     91                                        (int)len, l, line);
     92                                abort();
     93                        }
     94                        if (type != rw) {
     95                                fprintf(stderr, "Type %s wrong: %s",
     96                                        rw == F_RDLCK ? "READ" : "WRITE", line);
     97                                abort();
     98                        }
     99                        found = true;
     100                        break;
     101                }
     102        }
     103
     104        if (!found) {
     105                fprintf(stderr, "Unlock on %u@%u not found!\n",
     106                        (int)off, (int)len);
     107                abort();
     108        }
     109
     110        fclose(locks);
     111#endif
     112
     113        fl.l_type = F_UNLCK;
     114        fl.l_whence = SEEK_SET;
     115        fl.l_start = off;
     116        fl.l_len = len;
     117        fl.l_pid = 0;
     118
     119        return fcntl(tdb->fd, F_SETLKW, &fl);
     120}
     121
     122/* list -1 is the alloc list, otherwise a hash chain. */
     123static tdb_off_t lock_offset(int list)
     124{
     125        return FREELIST_TOP + 4*list;
    35126}
    36127
     
    43134   note that a len of zero means lock to end of file
    44135*/
    45 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
    46                int rw_type, int lck_type, int probe, size_t len)
    47 {
    48         struct flock fl;
     136int tdb_brlock(struct tdb_context *tdb,
     137               int rw_type, tdb_off_t offset, size_t len,
     138               enum tdb_lock_flags flags)
     139{
    49140        int ret;
    50141
    51142        if (tdb->flags & TDB_NOLOCK) {
     143                return 0;
     144        }
     145
     146        if (flags & TDB_LOCK_MARK_ONLY) {
    52147                return 0;
    53148        }
     
    58153        }
    59154
    60         fl.l_type = rw_type;
    61         fl.l_whence = SEEK_SET;
    62         fl.l_start = offset;
    63         fl.l_len = len;
    64         fl.l_pid = 0;
    65 
    66155        do {
    67                 ret = fcntl(tdb->fd,lck_type,&fl);
    68 
     156                ret = fcntl_lock(tdb, rw_type, offset, len,
     157                                 flags & TDB_LOCK_WAIT);
    69158                /* Check for a sigalarm break. */
    70159                if (ret == -1 && errno == EINTR &&
     
    80169                 * EAGAIN is an expected return from non-blocking
    81170                 * locks. */
    82                 if (!probe && lck_type != F_SETLK) {
    83                         TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
    84                                  tdb->fd, offset, rw_type, lck_type, (int)len));
     171                if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) {
     172                        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
     173                                 tdb->fd, offset, rw_type, flags, (int)len));
    85174                }
    86175                return -1;
     
    89178}
    90179
     180int tdb_brunlock(struct tdb_context *tdb,
     181                 int rw_type, tdb_off_t offset, size_t len)
     182{
     183        int ret;
     184
     185        if (tdb->flags & TDB_NOLOCK) {
     186                return 0;
     187        }
     188
     189        do {
     190                ret = fcntl_unlock(tdb, rw_type, offset, len);
     191        } while (ret == -1 && errno == EINTR);
     192
     193        if (ret == -1) {
     194                TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
     195                         tdb->fd, offset, rw_type, (int)len));
     196        }
     197        return ret;
     198}
    91199
    92200/*
     
    96204  made. For those OSes we may loop for a while. 
    97205*/
    98 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
     206int tdb_allrecord_upgrade(struct tdb_context *tdb)
    99207{
    100208        int count = 1000;
     209
     210        if (tdb->allrecord_lock.count != 1) {
     211                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     212                         "tdb_allrecord_upgrade failed: count %u too high\n",
     213                         tdb->allrecord_lock.count));
     214                return -1;
     215        }
     216
     217        if (tdb->allrecord_lock.off != 1) {
     218                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     219                         "tdb_allrecord_upgrade failed: already upgraded?\n"));
     220                return -1;
     221        }
     222
    101223        while (count--) {
    102224                struct timeval tv;
    103                 if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) {
     225                if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0,
     226                               TDB_LOCK_WAIT|TDB_LOCK_PROBE) == 0) {
     227                        tdb->allrecord_lock.ltype = F_WRLCK;
     228                        tdb->allrecord_lock.off = 0;
    104229                        return 0;
    105230                }
     
    112237                select(0, NULL, NULL, NULL, &tv);
    113238        }
    114         TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset));
     239        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_allrecord_upgrade failed\n"));
    115240        return -1;
    116241}
    117242
    118 
    119 /* lock a list in the database. list -1 is the alloc list */
    120 static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
     243static struct tdb_lock_type *find_nestlock(struct tdb_context *tdb,
     244                                           tdb_off_t offset)
     245{
     246        unsigned int i;
     247
     248        for (i=0; i<tdb->num_lockrecs; i++) {
     249                if (tdb->lockrecs[i].off == offset) {
     250                        return &tdb->lockrecs[i];
     251                }
     252        }
     253        return NULL;
     254}
     255
     256/* lock an offset in the database. */
     257int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     258                  enum tdb_lock_flags flags)
    121259{
    122260        struct tdb_lock_type *new_lck;
    123         int i;
    124         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    125 
    126         ltype &= ~TDB_MARK_LOCK;
    127 
    128         /* a global lock allows us to avoid per chain locks */
    129         if (tdb->global_lock.count &&
    130             (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
    131                 return 0;
    132         }
    133 
    134         if (tdb->global_lock.count) {
    135                 tdb->ecode = TDB_ERR_LOCK;
    136                 return -1;
    137         }
    138 
    139         if (list < -1 || list >= (int)tdb->header.hash_size) {
    140                 tdb->ecode = TDB_ERR_LOCK;
    141                 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n",
    142                            list, ltype));
     261
     262        if (offset >= lock_offset(tdb->header.hash_size)) {
     263                tdb->ecode = TDB_ERR_LOCK;
     264                TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid offset %u for ltype=%d\n",
     265                         offset, ltype));
    143266                return -1;
    144267        }
     
    146269                return 0;
    147270
    148         for (i=0; i<tdb->num_lockrecs; i++) {
    149                 if (tdb->lockrecs[i].list == list) {
    150                         if (tdb->lockrecs[i].count == 0) {
    151                                 /*
    152                                  * Can't happen, see tdb_unlock(). It should
    153                                  * be an assert.
    154                                  */
    155                                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: "
    156                                          "lck->count == 0 for list %d", list));
    157                         }
    158                         /*
    159                          * Just increment the in-memory struct, posix locks
    160                          * don't stack.
    161                          */
    162                         tdb->lockrecs[i].count++;
    163                         return 0;
    164                 }
     271        new_lck = find_nestlock(tdb, offset);
     272        if (new_lck) {
     273                /*
     274                 * Just increment the in-memory struct, posix locks
     275                 * don't stack.
     276                 */
     277                new_lck->count++;
     278                return 0;
    165279        }
    166280
     
    176290        /* Since fcntl locks don't nest, we do a lock for the first one,
    177291           and simply bump the count for future ones */
    178         if (!mark_lock &&
    179             tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op,
    180                                      0, 1)) {
    181                 return -1;
    182         }
    183 
    184         tdb->num_locks++;
    185 
    186         tdb->lockrecs[tdb->num_lockrecs].list = list;
     292        if (tdb_brlock(tdb, ltype, offset, 1, flags)) {
     293                return -1;
     294        }
     295
     296        tdb->lockrecs[tdb->num_lockrecs].off = offset;
    187297        tdb->lockrecs[tdb->num_lockrecs].count = 1;
    188298        tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
    189         tdb->num_lockrecs += 1;
     299        tdb->num_lockrecs++;
    190300
    191301        return 0;
     302}
     303
     304static int tdb_lock_and_recover(struct tdb_context *tdb)
     305{
     306        int ret;
     307
     308        /* We need to match locking order in transaction commit. */
     309        if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, TDB_LOCK_WAIT)) {
     310                return -1;
     311        }
     312
     313        if (tdb_brlock(tdb, F_WRLCK, OPEN_LOCK, 1, TDB_LOCK_WAIT)) {
     314                tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0);
     315                return -1;
     316        }
     317
     318        ret = tdb_transaction_recover(tdb);
     319
     320        tdb_brunlock(tdb, F_WRLCK, OPEN_LOCK, 1);
     321        tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0);
     322
     323        return ret;
     324}
     325
     326static bool have_data_locks(const struct tdb_context *tdb)
     327{
     328        unsigned int i;
     329
     330        for (i = 0; i < tdb->num_lockrecs; i++) {
     331                if (tdb->lockrecs[i].off >= lock_offset(-1))
     332                        return true;
     333        }
     334        return false;
     335}
     336
     337static int tdb_lock_list(struct tdb_context *tdb, int list, int ltype,
     338                         enum tdb_lock_flags waitflag)
     339{
     340        int ret;
     341        bool check = false;
     342
     343        /* a allrecord lock allows us to avoid per chain locks */
     344        if (tdb->allrecord_lock.count &&
     345            (ltype == tdb->allrecord_lock.ltype || ltype == F_RDLCK)) {
     346                return 0;
     347        }
     348
     349        if (tdb->allrecord_lock.count) {
     350                tdb->ecode = TDB_ERR_LOCK;
     351                ret = -1;
     352        } else {
     353                /* Only check when we grab first data lock. */
     354                check = !have_data_locks(tdb);
     355                ret = tdb_nest_lock(tdb, lock_offset(list), ltype, waitflag);
     356
     357                if (ret == 0 && check && tdb_needs_recovery(tdb)) {
     358                        tdb_nest_unlock(tdb, lock_offset(list), ltype, false);
     359
     360                        if (tdb_lock_and_recover(tdb) == -1) {
     361                                return -1;
     362                        }
     363                        return tdb_lock_list(tdb, list, ltype, waitflag);
     364                }
     365        }
     366        return ret;
    192367}
    193368
     
    196371{
    197372        int ret;
    198         ret = _tdb_lock(tdb, list, ltype, F_SETLKW);
     373
     374        ret = tdb_lock_list(tdb, list, ltype, TDB_LOCK_WAIT);
    199375        if (ret) {
    200376                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
     
    207383int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype)
    208384{
    209         return _tdb_lock(tdb, list, ltype, F_SETLK);
    210 }
    211 
    212 
    213 /* unlock the database: returns void because it's too late for errors. */
    214         /* changed to return int it may be interesting to know there
    215            has been an error  --simo */
    216 int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
     385        return tdb_lock_list(tdb, list, ltype, TDB_LOCK_NOWAIT);
     386}
     387
     388
     389int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     390                    bool mark_lock)
    217391{
    218392        int ret = -1;
    219         int i;
    220         struct tdb_lock_type *lck = NULL;
    221         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    222 
    223         ltype &= ~TDB_MARK_LOCK;
    224 
    225         /* a global lock allows us to avoid per chain locks */
    226         if (tdb->global_lock.count &&
    227             (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
    228                 return 0;
    229         }
    230 
    231         if (tdb->global_lock.count) {
    232                 tdb->ecode = TDB_ERR_LOCK;
    233                 return -1;
    234         }
     393        struct tdb_lock_type *lck;
    235394
    236395        if (tdb->flags & TDB_NOLOCK)
     
    238397
    239398        /* Sanity checks */
    240         if (list < -1 || list >= (int)tdb->header.hash_size) {
    241                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
     399        if (offset >= lock_offset(tdb->header.hash_size)) {
     400                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: offset %u invalid (%d)\n", offset, tdb->header.hash_size));
    242401                return ret;
    243402        }
    244403
    245         for (i=0; i<tdb->num_lockrecs; i++) {
    246                 if (tdb->lockrecs[i].list == list) {
    247                         lck = &tdb->lockrecs[i];
    248                         break;
    249                 }
    250         }
    251 
     404        lck = find_nestlock(tdb, offset);
    252405        if ((lck == NULL) || (lck->count == 0)) {
    253406                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n"));
     
    270423                ret = 0;
    271424        } else {
    272                 ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
    273                                                F_SETLKW, 0, 1);
    274         }
    275         tdb->num_locks--;
     425                ret = tdb_brunlock(tdb, ltype, offset, 1);
     426        }
    276427
    277428        /*
     
    279430         * last array element.
    280431         */
    281 
    282         if (tdb->num_lockrecs > 1) {
    283                 *lck = tdb->lockrecs[tdb->num_lockrecs-1];
    284         }
    285         tdb->num_lockrecs -= 1;
     432        *lck = tdb->lockrecs[--tdb->num_lockrecs];
    286433
    287434        /*
     
    299446}
    300447
     448int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
     449{
     450        /* a global lock allows us to avoid per chain locks */
     451        if (tdb->allrecord_lock.count &&
     452            (ltype == tdb->allrecord_lock.ltype || ltype == F_RDLCK)) {
     453                return 0;
     454        }
     455
     456        if (tdb->allrecord_lock.count) {
     457                tdb->ecode = TDB_ERR_LOCK;
     458                return -1;
     459        }
     460
     461        return tdb_nest_unlock(tdb, lock_offset(list), ltype, false);
     462}
     463
    301464/*
    302465  get the transaction lock
    303466 */
    304 int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
    305 {
    306         if (tdb->global_lock.count) {
    307                 return 0;
    308         }
    309         if (tdb->transaction_lock_count > 0) {
    310                 tdb->transaction_lock_count++;
    311                 return 0;
    312         }
    313 
    314         if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype,
    315                                      F_SETLKW, 0, 1) == -1) {
    316                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
    317                 tdb->ecode = TDB_ERR_LOCK;
    318                 return -1;
    319         }
    320         tdb->transaction_lock_count++;
    321         return 0;
     467int tdb_transaction_lock(struct tdb_context *tdb, int ltype,
     468                         enum tdb_lock_flags lockflags)
     469{
     470        return tdb_nest_lock(tdb, TRANSACTION_LOCK, ltype, lockflags);
    322471}
    323472
     
    325474  release the transaction lock
    326475 */
    327 int tdb_transaction_unlock(struct tdb_context *tdb)
    328 {
    329         int ret;
    330         if (tdb->global_lock.count) {
    331                 return 0;
    332         }
    333         if (tdb->transaction_lock_count > 1) {
    334                 tdb->transaction_lock_count--;
    335                 return 0;
    336         }
    337         ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
    338         if (ret == 0) {
    339                 tdb->transaction_lock_count = 0;
    340         }
    341         return ret;
    342 }
    343 
    344 
    345 
    346 
    347 /* lock/unlock entire database */
    348 static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
    349 {
    350         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    351 
    352         ltype &= ~TDB_MARK_LOCK;
    353 
     476int tdb_transaction_unlock(struct tdb_context *tdb, int ltype)
     477{
     478        return tdb_nest_unlock(tdb, TRANSACTION_LOCK, ltype, false);
     479}
     480
     481/* Returns 0 if all done, -1 if error, 1 if ok. */
     482static int tdb_allrecord_check(struct tdb_context *tdb, int ltype,
     483                               enum tdb_lock_flags flags, bool upgradable)
     484{
    354485        /* There are no locks on read-only dbs */
    355486        if (tdb->read_only || tdb->traverse_read) {
     
    358489        }
    359490
    360         if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) {
    361                 tdb->global_lock.count++;
    362                 return 0;
    363         }
    364 
    365         if (tdb->global_lock.count) {
     491        if (tdb->allrecord_lock.count && tdb->allrecord_lock.ltype == ltype) {
     492                tdb->allrecord_lock.count++;
     493                return 0;
     494        }
     495
     496        if (tdb->allrecord_lock.count) {
    366497                /* a global lock of a different type exists */
    367498                tdb->ecode = TDB_ERR_LOCK;
    368499                return -1;
    369500        }
    370        
    371         if (tdb->num_locks != 0) {
     501
     502        if (tdb_have_extra_locks(tdb)) {
    372503                /* can't combine global and chain locks */
    373504                tdb->ecode = TDB_ERR_LOCK;
     
    375506        }
    376507
    377         if (!mark_lock &&
    378             tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op,
    379                                      0, 4*tdb->header.hash_size)) {
    380                 if (op == F_SETLKW) {
    381                         TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
    382                 }
    383                 return -1;
    384         }
    385 
    386         tdb->global_lock.count = 1;
    387         tdb->global_lock.ltype = ltype;
    388 
     508        if (upgradable && ltype != F_RDLCK) {
     509                /* tdb error: you can't upgrade a write lock! */
     510                tdb->ecode = TDB_ERR_LOCK;
     511                return -1;
     512        }
     513        return 1;
     514}
     515
     516/* We only need to lock individual bytes, but Linux merges consecutive locks
     517 * so we lock in contiguous ranges. */
     518static int tdb_chainlock_gradual(struct tdb_context *tdb,
     519                                 int ltype, enum tdb_lock_flags flags,
     520                                 size_t off, size_t len)
     521{
     522        int ret;
     523        enum tdb_lock_flags nb_flags = (flags & ~TDB_LOCK_WAIT);
     524
     525        if (len <= 4) {
     526                /* Single record.  Just do blocking lock. */
     527                return tdb_brlock(tdb, ltype, off, len, flags);
     528        }
     529
     530        /* First we try non-blocking. */
     531        ret = tdb_brlock(tdb, ltype, off, len, nb_flags);
     532        if (ret == 0) {
     533                return 0;
     534        }
     535
     536        /* Try locking first half, then second. */
     537        ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2);
     538        if (ret == -1)
     539                return -1;
     540
     541        ret = tdb_chainlock_gradual(tdb, ltype, flags,
     542                                    off + len / 2, len - len / 2);
     543        if (ret == -1) {
     544                tdb_brunlock(tdb, ltype, off, len / 2);
     545                return -1;
     546        }
    389547        return 0;
    390548}
    391549
     550/* lock/unlock entire database.  It can only be upgradable if you have some
     551 * other way of guaranteeing exclusivity (ie. transaction write lock).
     552 * We do the locking gradually to avoid being starved by smaller locks. */
     553int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
     554                       enum tdb_lock_flags flags, bool upgradable)
     555{
     556        switch (tdb_allrecord_check(tdb, ltype, flags, upgradable)) {
     557        case -1:
     558                return -1;
     559        case 0:
     560                return 0;
     561        }
     562
     563        /* We cover two kinds of locks:
     564         * 1) Normal chain locks.  Taken for almost all operations.
     565         * 3) Individual records locks.  Taken after normal or free
     566         *    chain locks.
     567         *
     568         * It is (1) which cause the starvation problem, so we're only
     569         * gradual for that. */
     570        if (tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP,
     571                                  tdb->header.hash_size * 4) == -1) {
     572                return -1;
     573        }
     574
     575        /* Grab individual record locks. */
     576        if (tdb_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0,
     577                       flags) == -1) {
     578                tdb_brunlock(tdb, ltype, FREELIST_TOP,
     579                             tdb->header.hash_size * 4);
     580                return -1;
     581        }
     582
     583        tdb->allrecord_lock.count = 1;
     584        /* If it's upgradable, it's actually exclusive so we can treat
     585         * it as a write lock. */
     586        tdb->allrecord_lock.ltype = upgradable ? F_WRLCK : ltype;
     587        tdb->allrecord_lock.off = upgradable;
     588
     589        if (tdb_needs_recovery(tdb)) {
     590                bool mark = flags & TDB_LOCK_MARK_ONLY;
     591                tdb_allrecord_unlock(tdb, ltype, mark);
     592                if (mark) {
     593                        tdb->ecode = TDB_ERR_LOCK;
     594                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     595                                 "tdb_lockall_mark cannot do recovery\n"));
     596                        return -1;
     597                }
     598                if (tdb_lock_and_recover(tdb) == -1) {
     599                        return -1;
     600                }
     601                return tdb_allrecord_lock(tdb, ltype, flags, upgradable);
     602        }
     603
     604        return 0;
     605}
     606
    392607
    393608
    394609/* unlock entire db */
    395 static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
    396 {
    397         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    398 
    399         ltype &= ~TDB_MARK_LOCK;
    400 
     610int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock)
     611{
    401612        /* There are no locks on read-only dbs */
    402613        if (tdb->read_only || tdb->traverse_read) {
     
    405616        }
    406617
    407         if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) {
    408                 tdb->ecode = TDB_ERR_LOCK;
    409                 return -1;
    410         }
    411 
    412         if (tdb->global_lock.count > 1) {
    413                 tdb->global_lock.count--;
    414                 return 0;
    415         }
    416 
    417         if (!mark_lock &&
    418             tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW,
    419                                      0, 4*tdb->header.hash_size)) {
     618        if (tdb->allrecord_lock.count == 0) {
     619                tdb->ecode = TDB_ERR_LOCK;
     620                return -1;
     621        }
     622
     623        /* Upgradable locks are marked as write locks. */
     624        if (tdb->allrecord_lock.ltype != ltype
     625            && (!tdb->allrecord_lock.off || ltype != F_RDLCK)) {
     626                tdb->ecode = TDB_ERR_LOCK;
     627                return -1;
     628        }
     629
     630        if (tdb->allrecord_lock.count > 1) {
     631                tdb->allrecord_lock.count--;
     632                return 0;
     633        }
     634
     635        if (!mark_lock && tdb_brunlock(tdb, ltype, FREELIST_TOP, 0)) {
    420636                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
    421637                return -1;
    422638        }
    423639
    424         tdb->global_lock.count = 0;
    425         tdb->global_lock.ltype = 0;
     640        tdb->allrecord_lock.count = 0;
     641        tdb->allrecord_lock.ltype = 0;
    426642
    427643        return 0;
     
    429645
    430646/* lock entire database with write lock */
    431 int tdb_lockall(struct tdb_context *tdb)
     647_PUBLIC_ int tdb_lockall(struct tdb_context *tdb)
    432648{
    433649        tdb_trace(tdb, "tdb_lockall");
    434         return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
     650        return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false);
    435651}
    436652
    437653/* lock entire database with write lock - mark only */
    438 int tdb_lockall_mark(struct tdb_context *tdb)
     654_PUBLIC_ int tdb_lockall_mark(struct tdb_context *tdb)
    439655{
    440656        tdb_trace(tdb, "tdb_lockall_mark");
    441         return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);
     657        return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_MARK_ONLY, false);
    442658}
    443659
    444660/* unlock entire database with write lock - unmark only */
    445 int tdb_lockall_unmark(struct tdb_context *tdb)
     661_PUBLIC_ int tdb_lockall_unmark(struct tdb_context *tdb)
    446662{
    447663        tdb_trace(tdb, "tdb_lockall_unmark");
    448         return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
     664        return tdb_allrecord_unlock(tdb, F_WRLCK, true);
    449665}
    450666
    451667/* lock entire database with write lock - nonblocking varient */
    452 int tdb_lockall_nonblock(struct tdb_context *tdb)
    453 {
    454         int ret = _tdb_lockall(tdb, F_WRLCK, F_SETLK);
     668_PUBLIC_ int tdb_lockall_nonblock(struct tdb_context *tdb)
     669{
     670        int ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_NOWAIT, false);
    455671        tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret);
    456672        return ret;
     
    458674
    459675/* unlock entire database with write lock */
    460 int tdb_unlockall(struct tdb_context *tdb)
     676_PUBLIC_ int tdb_unlockall(struct tdb_context *tdb)
    461677{
    462678        tdb_trace(tdb, "tdb_unlockall");
    463         return _tdb_unlockall(tdb, F_WRLCK);
     679        return tdb_allrecord_unlock(tdb, F_WRLCK, false);
    464680}
    465681
    466682/* lock entire database with read lock */
    467 int tdb_lockall_read(struct tdb_context *tdb)
     683_PUBLIC_ int tdb_lockall_read(struct tdb_context *tdb)
    468684{
    469685        tdb_trace(tdb, "tdb_lockall_read");
    470         return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
     686        return tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
    471687}
    472688
    473689/* lock entire database with read lock - nonblock varient */
    474 int tdb_lockall_read_nonblock(struct tdb_context *tdb)
    475 {
    476         int ret = _tdb_lockall(tdb, F_RDLCK, F_SETLK);
     690_PUBLIC_ int tdb_lockall_read_nonblock(struct tdb_context *tdb)
     691{
     692        int ret = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_NOWAIT, false);
    477693        tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret);
    478694        return ret;
     
    480696
    481697/* unlock entire database with read lock */
    482 int tdb_unlockall_read(struct tdb_context *tdb)
     698_PUBLIC_ int tdb_unlockall_read(struct tdb_context *tdb)
    483699{
    484700        tdb_trace(tdb, "tdb_unlockall_read");
    485         return _tdb_unlockall(tdb, F_RDLCK);
     701        return tdb_allrecord_unlock(tdb, F_RDLCK, false);
    486702}
    487703
    488704/* lock/unlock one hash chain. This is meant to be used to reduce
    489705   contention - it cannot guarantee how many records will be locked */
    490 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
     706_PUBLIC_ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
    491707{
    492708        int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
     
    498714   to reduce contention - it cannot guarantee how many records will be
    499715   locked */
    500 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
     716_PUBLIC_ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
    501717{
    502718        int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
     
    506722
    507723/* mark a chain as locked without actually locking it. Warning! use with great caution! */
    508 int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
    509 {
    510         int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
     724_PUBLIC_ int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
     725{
     726        int ret = tdb_nest_lock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))),
     727                                F_WRLCK, TDB_LOCK_MARK_ONLY);
    511728        tdb_trace_1rec(tdb, "tdb_chainlock_mark", key);
    512729        return ret;
     
    514731
    515732/* unmark a chain as locked without actually locking it. Warning! use with great caution! */
    516 int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
     733_PUBLIC_ int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
    517734{
    518735        tdb_trace_1rec(tdb, "tdb_chainlock_unmark", key);
    519         return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
    520 }
    521 
    522 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
     736        return tdb_nest_unlock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))),
     737                               F_WRLCK, true);
     738}
     739
     740_PUBLIC_ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
    523741{
    524742        tdb_trace_1rec(tdb, "tdb_chainunlock", key);
     
    526744}
    527745
    528 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
     746_PUBLIC_ int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
    529747{
    530748        int ret;
     
    534752}
    535753
    536 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
     754_PUBLIC_ int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
    537755{
    538756        tdb_trace_1rec(tdb, "tdb_chainunlock_read", key);
     
    540758}
    541759
    542 
    543 
    544760/* record lock stops delete underneath */
    545761int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
    546762{
    547         if (tdb->global_lock.count) {
    548                 return 0;
    549         }
    550         return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0;
     763        if (tdb->allrecord_lock.count) {
     764                return 0;
     765        }
     766        return off ? tdb_brlock(tdb, F_RDLCK, off, 1, TDB_LOCK_WAIT) : 0;
    551767}
    552768
     
    562778                if (i->off == off)
    563779                        return -1;
    564         return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1);
    565 }
    566 
    567 /*
    568   Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
    569   an error to fail to get the lock here.
    570 */
     780        if (tdb->allrecord_lock.count) {
     781                if (tdb->allrecord_lock.ltype == F_WRLCK) {
     782                        return 0;
     783                }
     784                return -1;
     785        }
     786        return tdb_brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
     787}
     788
    571789int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
    572790{
    573         return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1);
     791        if (tdb->allrecord_lock.count) {
     792                return 0;
     793        }
     794        return tdb_brunlock(tdb, F_WRLCK, off, 1);
    574795}
    575796
     
    580801        uint32_t count = 0;
    581802
    582         if (tdb->global_lock.count) {
     803        if (tdb->allrecord_lock.count) {
    583804                return 0;
    584805        }
     
    589810                if (i->off == off)
    590811                        count++;
    591         return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0);
    592 }
     812        return (count == 1 ? tdb_brunlock(tdb, F_RDLCK, off, 1) : 0);
     813}
     814
     815bool tdb_have_extra_locks(struct tdb_context *tdb)
     816{
     817        unsigned int extra = tdb->num_lockrecs;
     818
     819        /* A transaction holds the lock for all records. */
     820        if (!tdb->transaction && tdb->allrecord_lock.count) {
     821                return true;
     822        }
     823
     824        /* We always hold the active lock if CLEAR_IF_FIRST. */
     825        if (find_nestlock(tdb, ACTIVE_LOCK)) {
     826                extra--;
     827        }
     828
     829        /* In a transaction, we expect to hold the transaction lock */
     830        if (tdb->transaction && find_nestlock(tdb, TRANSACTION_LOCK)) {
     831                extra--;
     832        }
     833
     834        return extra;
     835}
     836
     837/* The transaction code uses this to remove all locks. */
     838void tdb_release_transaction_locks(struct tdb_context *tdb)
     839{
     840        unsigned int i, active = 0;
     841
     842        if (tdb->allrecord_lock.count != 0) {
     843                tdb_brunlock(tdb, tdb->allrecord_lock.ltype, FREELIST_TOP, 0);
     844                tdb->allrecord_lock.count = 0;
     845        }
     846
     847        for (i=0;i<tdb->num_lockrecs;i++) {
     848                struct tdb_lock_type *lck = &tdb->lockrecs[i];
     849
     850                /* Don't release the active lock!  Copy it to first entry. */
     851                if (lck->off == ACTIVE_LOCK) {
     852                        tdb->lockrecs[active++] = *lck;
     853                } else {
     854                        tdb_brunlock(tdb, lck->ltype, lck->off, 1);
     855                }
     856        }
     857        tdb->num_lockrecs = active;
     858        if (tdb->num_lockrecs == 0) {
     859                SAFE_FREE(tdb->lockrecs);
     860        }
     861}
  • vendor/current/lib/tdb/common/open.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    3131static struct tdb_context *tdbs = NULL;
    3232
    33 
    34 /* This is based on the hash algorithm from gdbm */
    35 static unsigned int default_tdb_hash(TDB_DATA *key)
    36 {
    37         uint32_t value; /* Used to compute the hash value.  */
    38         uint32_t   i;   /* Used to cycle through random values. */
    39 
    40         /* Set the initial value from the key size. */
    41         for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
    42                 value = (value + (key->dptr[i] << (i*5 % 24)));
    43 
    44         return (1103515243 * value + 12345); 
    45 }
    46 
     33/* We use two hashes to double-check they're using the right hash function. */
     34void tdb_header_hash(struct tdb_context *tdb,
     35                     uint32_t *magic1_hash, uint32_t *magic2_hash)
     36{
     37        TDB_DATA hash_key;
     38        uint32_t tdb_magic = TDB_MAGIC;
     39
     40        hash_key.dptr = discard_const_p(unsigned char, TDB_MAGIC_FOOD);
     41        hash_key.dsize = sizeof(TDB_MAGIC_FOOD);
     42        *magic1_hash = tdb->hash_fn(&hash_key);
     43
     44        hash_key.dptr = (unsigned char *)CONVERT(tdb_magic);
     45        hash_key.dsize = sizeof(tdb_magic);
     46        *magic2_hash = tdb->hash_fn(&hash_key);
     47
     48        /* Make sure at least one hash is non-zero! */
     49        if (*magic1_hash == 0 && *magic2_hash == 0)
     50                *magic1_hash = 1;
     51}
    4752
    4853/* initialise a new database with a specified hash size */
     
    5257        size_t size;
    5358        int ret = -1;
    54         ssize_t written;
    5559
    5660        /* We make it up in memory, then write it out if not internal */
     
    6468        newdb->version = TDB_VERSION;
    6569        newdb->hash_size = hash_size;
     70
     71        tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);
     72
     73        /* Make sure older tdbs (which don't check the magic hash fields)
     74         * will refuse to open this TDB. */
     75        if (tdb->flags & TDB_INCOMPATIBLE_HASH)
     76                newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC;
     77
    6678        if (tdb->flags & TDB_INTERNAL) {
    6779                tdb->map_size = size;
     
    8496        memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
    8597        /* we still have "ret == -1" here */
    86         written = write(tdb->fd, newdb, size);
    87         if (written == size) {
     98        if (tdb_write_all(tdb->fd, newdb, size))
    8899                ret = 0;
    89         } else if (written != -1) {
    90                 /* call write once again, this usually should return -1 and
    91                  * set errno appropriately */
    92                 size -= written;
    93                 written = write(tdb->fd, newdb+written, size);
    94                 if (written == size) {
    95                 ret = 0;
    96                 } else if (written >= 0) {
    97                         /* a second incomplete write - we give up.
    98                          * guessing the errno... */
    99                         errno = ENOSPC;
    100                 }
    101         }
    102100
    103101  fail:
     
    112110{
    113111        struct tdb_context *i;
    114        
     112
    115113        for (i = tdbs; i; i = i->next) {
    116114                if (i->device == device && i->inode == ino) {
     
    132130
    133131   @param name may be NULL for internal databases. */
    134 struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
     132_PUBLIC_ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
    135133                      int open_flags, mode_t mode)
    136134{
     
    144142}
    145143
    146 
    147 struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
     144static bool check_header_hash(struct tdb_context *tdb,
     145                              bool default_hash, uint32_t *m1, uint32_t *m2)
     146{
     147        tdb_header_hash(tdb, m1, m2);
     148        if (tdb->header.magic1_hash == *m1 &&
     149            tdb->header.magic2_hash == *m2) {
     150                return true;
     151        }
     152
     153        /* If they explicitly set a hash, always respect it. */
     154        if (!default_hash)
     155                return false;
     156
     157        /* Otherwise, try the other inbuilt hash. */
     158        if (tdb->hash_fn == tdb_old_hash)
     159                tdb->hash_fn = tdb_jenkins_hash;
     160        else
     161                tdb->hash_fn = tdb_old_hash;
     162        return check_header_hash(tdb, false, m1, m2);
     163}
     164
     165_PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
    148166                                int open_flags, mode_t mode,
    149167                                const struct tdb_logging_context *log_ctx,
     
    156174        uint32_t vertest;
    157175        unsigned v;
     176        const char *hash_alg;
     177        uint32_t magic1, magic2;
    158178
    159179        if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
     
    177197                tdb->log.log_private = NULL;
    178198        }
    179         tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
     199
     200        if (name == NULL && (tdb_flags & TDB_INTERNAL)) {
     201                name = "__TDB_INTERNAL__";
     202        }
     203
     204        if (name == NULL) {
     205                tdb->name = discard_const_p(char, "__NULL__");
     206                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: called with name == NULL\n"));
     207                tdb->name = NULL;
     208                errno = EINVAL;
     209                goto fail;
     210        }
     211
     212        /* now make a copy of the name, as the caller memory might went away */
     213        if (!(tdb->name = (char *)strdup(name))) {
     214                /*
     215                 * set the name as the given string, so that tdb_name() will
     216                 * work in case of an error.
     217                 */
     218                tdb->name = discard_const_p(char, name);
     219                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't strdup(%s)\n",
     220                         name));
     221                tdb->name = NULL;
     222                errno = ENOMEM;
     223                goto fail;
     224        }
     225
     226        if (hash_fn) {
     227                tdb->hash_fn = hash_fn;
     228                hash_alg = "the user defined";
     229        } else {
     230                /* This controls what we use when creating a tdb. */
     231                if (tdb->flags & TDB_INCOMPATIBLE_HASH) {
     232                        tdb->hash_fn = tdb_jenkins_hash;
     233                } else {
     234                        tdb->hash_fn = tdb_old_hash;
     235                }
     236                hash_alg = "either default";
     237        }
    180238
    181239        /* cache the page size */
     
    193251                goto fail;
    194252        }
    195        
     253
    196254        if (hash_size == 0)
    197255                hash_size = DEFAULT_HASH_SIZE;
     
    212270        }
    213271
     272        if (getenv("TDB_NO_FSYNC")) {
     273                tdb->flags |= TDB_NOSYNC;
     274        }
     275
    214276        /*
    215277         * TDB_ALLOW_NESTING is the default behavior.
     
    242304
    243305        /* ensure there is only one process initialising at once */
    244         if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
    245                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n",
     306        if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
     307                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get open lock on %s: %s\n",
    246308                         name, strerror(errno)));
    247309                goto fail;      /* errno set by tdb_brlock */
     
    251313        if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
    252314            (!tdb->read_only) &&
    253             (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {
     315            (locked = (tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE) == 0))) {
    254316                open_flags |= O_CREAT;
    255317                if (ftruncate(tdb->fd, 0) == -1) {
     
    290352                goto fail;
    291353
    292         if (tdb->header.rwlocks != 0) {
     354        if (tdb->header.rwlocks != 0 &&
     355            tdb->header.rwlocks != TDB_HASH_RWLOCK_MAGIC) {
    293356                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
     357                goto fail;
     358        }
     359
     360        if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) {
     361                /* older TDB without magic hash references */
     362                tdb->hash_fn = tdb_old_hash;
     363        } else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) {
     364                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
     365                         "%s was not created with %s hash function we are using\n"
     366                         "magic1_hash[0x%08X %s 0x%08X] "
     367                         "magic2_hash[0x%08X %s 0x%08X]\n",
     368                         name, hash_alg,
     369                         tdb->header.magic1_hash,
     370                         (tdb->header.magic1_hash == magic1) ? "==" : "!=",
     371                         magic1,
     372                         tdb->header.magic2_hash,
     373                         (tdb->header.magic2_hash == magic2) ? "==" : "!=",
     374                         magic2));
     375                errno = EINVAL;
    294376                goto fail;
    295377        }
     
    304386        }
    305387
    306         if (!(tdb->name = (char *)strdup(name))) {
    307                 errno = ENOMEM;
    308                 goto fail;
    309         }
    310 
    311388        tdb->map_size = st.st_size;
    312389        tdb->device = st.st_dev;
     
    314391        tdb_mmap(tdb);
    315392        if (locked) {
    316                 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
     393                if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) {
    317394                        TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
    318                                  "failed to take ACTIVE_LOCK on %s: %s\n",
     395                                 "failed to release ACTIVE_LOCK on %s: %s\n",
    319396                                 name, strerror(errno)));
    320397                        goto fail;
     
    329406        if (tdb_flags & TDB_CLEAR_IF_FIRST) {
    330407                /* leave this lock in place to indicate it's in use */
    331                 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)
     408                if (tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
    332409                        goto fail;
     410                }
    333411        }
    334412
     
    357435        /* Internal (memory-only) databases skip all the code above to
    358436         * do with disk files, and resume here by releasing their
    359          * global lock and hooking into the active list. */
    360         if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1)
    361                 goto fail;
     437         * open lock and hooking into the active list. */
     438        if (tdb_nest_unlock(tdb, OPEN_LOCK, F_WRLCK, false) == -1) {
     439                goto fail;
     440        }
    362441        tdb->next = tdbs;
    363442        tdbs = tdb;
     
    379458                        tdb_munmap(tdb);
    380459        }
    381         SAFE_FREE(tdb->name);
    382460        if (tdb->fd != -1)
    383461                if (close(tdb->fd) != 0)
    384462                        TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
     463        SAFE_FREE(tdb->lockrecs);
     464        SAFE_FREE(tdb->name);
    385465        SAFE_FREE(tdb);
    386466        errno = save_errno;
     
    393473 */
    394474
    395 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
     475_PUBLIC_ void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
    396476{
    397477        tdb->max_dead_records = max_dead;
     
    403483 * @returns -1 for error; 0 for success.
    404484 **/
    405 int tdb_close(struct tdb_context *tdb)
     485_PUBLIC_ int tdb_close(struct tdb_context *tdb)
    406486{
    407487        struct tdb_context **i;
    408488        int ret = 0;
    409489
     490        if (tdb->transaction) {
     491                tdb_transaction_cancel(tdb);
     492        }
    410493        tdb_trace(tdb, "tdb_close");
    411         if (tdb->transaction) {
    412                 _tdb_transaction_cancel(tdb);
    413         }
    414494
    415495        if (tdb->map_ptr) {
     
    444524
    445525/* register a loging function */
    446 void tdb_set_logging_function(struct tdb_context *tdb,
    447                               const struct tdb_logging_context *log_ctx)
     526_PUBLIC_ void tdb_set_logging_function(struct tdb_context *tdb,
     527                                       const struct tdb_logging_context *log_ctx)
    448528{
    449529        tdb->log = *log_ctx;
    450530}
    451531
    452 void *tdb_get_logging_private(struct tdb_context *tdb)
     532_PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb)
    453533{
    454534        return tdb->log.log_private;
     
    466546        }
    467547
    468         if (tdb->num_locks != 0 || tdb->global_lock.count) {
     548        if (tdb_have_extra_locks(tdb)) {
    469549                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
    470550                goto fail;
     
    501581#endif /* fake pread or pwrite */
    502582
    503         if (active_lock &&
    504             (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
     583        /* We may still think we hold the active lock. */
     584        tdb->num_lockrecs = 0;
     585        SAFE_FREE(tdb->lockrecs);
     586
     587        if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
    505588                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
    506589                goto fail;
     
    516599/* reopen a tdb - this can be used after a fork to ensure that we have an independent
    517600   seek pointer from our parent and to re-establish locks */
    518 int tdb_reopen(struct tdb_context *tdb)
     601_PUBLIC_ int tdb_reopen(struct tdb_context *tdb)
    519602{
    520603        return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST);
     
    522605
    523606/* reopen all tdb's */
    524 int tdb_reopen_all(int parent_longlived)
     607_PUBLIC_ int tdb_reopen_all(int parent_longlived)
    525608{
    526609        struct tdb_context *tdb;
  • vendor/current/lib/tdb/common/tdb.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 TDB_DATA tdb_null;
     30_PUBLIC_ TDB_DATA tdb_null;
    3131
    3232/*
     
    3434  the TDB_SEQNUM flag
    3535*/
    36 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
     36_PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
    3737{
    3838        tdb_off_t seqnum=0;
    39        
     39
    4040        if (!(tdb->flags & TDB_SEQNUM)) {
    4141                return;
     
    6060        }
    6161
    62         if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
     62        if (tdb_nest_lock(tdb, TDB_SEQNUM_OFS, F_WRLCK,
     63                          TDB_LOCK_WAIT|TDB_LOCK_PROBE) != 0) {
    6364                return;
    6465        }
     
    6667        tdb_increment_seqnum_nonblock(tdb);
    6768
    68         tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
     69        tdb_nest_unlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, false);
    6970}
    7071
     
    8081{
    8182        tdb_off_t rec_ptr;
    82        
     83
    8384        /* read in the hash top */
    8485        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    154155                }
    155156        }
    156          
    157157
    158158        /* must be long enough key, data and tailer */
     
    171171                return tdb_rec_write(tdb, rec_ptr, &rec);
    172172        }
    173  
     173
    174174        return 0;
    175175}
     
    200200}
    201201
    202 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
     202_PUBLIC_ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
    203203{
    204204        TDB_DATA ret = _tdb_fetch(tdb, key);
     
    213213 * should be fast and should not block on other syscalls.
    214214 *
    215  * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
     215 * DON'T CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
    216216 *
    217217 * For mmapped tdb's that do not have a transaction open it points the parsing
     
    222222 * This is interesting for all readers of potentially large data structures in
    223223 * the tdb records, ldb indexes being one example.
     224 *
     225 * Return -1 if the record was not found.
    224226 */
    225227
    226 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
     228_PUBLIC_ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
    227229                     int (*parser)(TDB_DATA key, TDB_DATA data,
    228230                                   void *private_data),
     
    238240
    239241        if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
     242                /* record not found */
    240243                tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1);
    241244                tdb->ecode = TDB_ERR_NOEXIST;
    242                 return 0;
     245                return -1;
    243246        }
    244247        tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0);
     
    261264{
    262265        struct tdb_record rec;
    263        
     266
    264267        if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
    265268                return 0;
     
    268271}
    269272
    270 int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
     273_PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
    271274{
    272275        uint32_t hash = tdb->hash_fn(&key);
     
    319322        tdb_off_t rec_ptr;
    320323        struct tdb_record rec;
    321        
     324
    322325        /* read in the hash top */
    323326        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    348351                return -1;
    349352        }
    350        
     353
    351354        /* read in the hash top */
    352355        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    427430}
    428431
    429 int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
     432_PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
    430433{
    431434        uint32_t hash = tdb->hash_fn(&key);
     
    444447{
    445448        tdb_off_t rec_ptr;
    446        
     449
    447450        /* read in the hash top */
    448451        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    597600   return 0 on success, -1 on failure
    598601*/
    599 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
     602_PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
    600603{
    601604        uint32_t hash;
     
    620623
    621624/* Append to an entry. Create if not exist. */
    622 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
     625_PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
    623626{
    624627        uint32_t hash;
     
    659662        ret = _tdb_store(tdb, key, dbuf, 0, hash);
    660663        tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf);
    661        
     664
    662665failed:
    663666        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
     
    671674  useful for external logging functions
    672675*/
    673 const char *tdb_name(struct tdb_context *tdb)
     676_PUBLIC_ const char *tdb_name(struct tdb_context *tdb)
    674677{
    675678        return tdb->name;
     
    681684  of the fd
    682685*/
    683 int tdb_fd(struct tdb_context *tdb)
     686_PUBLIC_ int tdb_fd(struct tdb_context *tdb)
    684687{
    685688        return tdb->fd;
     
    690693  useful for external tdb routines that wish to log tdb errors
    691694*/
    692 tdb_log_func tdb_log_fn(struct tdb_context *tdb)
     695_PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
    693696{
    694697        return tdb->log.log_fn;
     
    706709  test of a possible tdb change.
    707710*/
    708 int tdb_get_seqnum(struct tdb_context *tdb)
     711_PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb)
    709712{
    710713        tdb_off_t seqnum=0;
     
    714717}
    715718
    716 int tdb_hash_size(struct tdb_context *tdb)
     719_PUBLIC_ int tdb_hash_size(struct tdb_context *tdb)
    717720{
    718721        return tdb->header.hash_size;
    719722}
    720723
    721 size_t tdb_map_size(struct tdb_context *tdb)
     724_PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb)
    722725{
    723726        return tdb->map_size;
    724727}
    725728
    726 int tdb_get_flags(struct tdb_context *tdb)
     729_PUBLIC_ int tdb_get_flags(struct tdb_context *tdb)
    727730{
    728731        return tdb->flags;
    729732}
    730733
    731 void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
     734_PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
    732735{
    733736        if ((flags & TDB_ALLOW_NESTING) &&
     
    749752}
    750753
    751 void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
     754_PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
    752755{
    753756        if ((flags & TDB_ALLOW_NESTING) &&
     
    773776  enable sequence number handling on an open tdb
    774777*/
    775 void tdb_enable_seqnum(struct tdb_context *tdb)
     778_PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb)
    776779{
    777780        tdb->flags |= TDB_SEQNUM;
     
    805808/*
    806809  wipe the entire database, deleting all records. This can be done
    807   very fast by using a global lock. The entire data portion of the
     810  very fast by using a allrecord lock. The entire data portion of the
    808811  file becomes a single entry in the freelist.
    809812
    810813  This code carefully steps around the recovery area, leaving it alone
    811814 */
    812 int tdb_wipe_all(struct tdb_context *tdb)
     815_PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
    813816{
    814817        int i;
     
    917920  repack a tdb
    918921 */
    919 int tdb_repack(struct tdb_context *tdb)
     922_PUBLIC_ int tdb_repack(struct tdb_context *tdb)
    920923{
    921924        struct tdb_context *tmp_db;
     
    987990}
    988991
     992/* Even on files, we can get partial writes due to signals. */
     993bool tdb_write_all(int fd, const void *buf, size_t count)
     994{
     995        while (count) {
     996                ssize_t ret;
     997                ret = write(fd, buf, count);
     998                if (ret < 0)
     999                        return false;
     1000                buf = (const char *)buf + ret;
     1001                count -= ret;
     1002        }
     1003        return true;
     1004}
     1005
    9891006#ifdef TDB_TRACE
    9901007static void tdb_trace_write(struct tdb_context *tdb, const char *str)
    9911008{
    992         if (write(tdb->tracefd, str, strlen(str)) != strlen(str)) {
     1009        if (!tdb_write_alltdb->tracefd, str, strlen(str)) {
    9931010                close(tdb->tracefd);
    9941011                tdb->tracefd = -1;
  • vendor/current/lib/tdb/common/tdb_private.h

    r414 r740  
    55
    66   Copyright (C) Andrew Tridgell              2005
    7    
     7
    88     ** NOTE! The following LGPL license applies to the tdb
    99     ** library. This does NOT imply that all of Samba is released
    1010     ** under the LGPL
    11    
     11
    1212   This library is free software; you can redistribute it and/or
    1313   modify it under the terms of the GNU Lesser General Public
     
    5050#define TDB_DEAD_MAGIC (0xFEE1DEAD)
    5151#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
     52#define TDB_RECOVERY_INVALID_MAGIC (0x0)
     53#define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U)
    5254#define TDB_ALIGNMENT 4
    5355#define DEFAULT_HASH_SIZE 131
     
    102104
    103105/* lock offsets */
    104 #define GLOBAL_LOCK      0
     106#define OPEN_LOCK        0
    105107#define ACTIVE_LOCK      4
    106108#define TRANSACTION_LOCK 8
     
    147149        tdb_off_t recovery_start; /* offset of transaction recovery region */
    148150        tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */
    149         tdb_off_t reserved[29];
     151        uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */
     152        uint32_t magic2_hash; /* hash of TDB_MAGIC. */
     153        tdb_off_t reserved[27];
    150154};
    151155
    152156struct tdb_lock_type {
    153         int list;
     157        uint32_t off;
    154158        uint32_t count;
    155159        uint32_t ltype;
     
    163167};
    164168
     169enum tdb_lock_flags {
     170        /* WAIT == F_SETLKW, NOWAIT == F_SETLK */
     171        TDB_LOCK_NOWAIT = 0,
     172        TDB_LOCK_WAIT = 1,
     173        /* If set, don't log an error on failure. */
     174        TDB_LOCK_PROBE = 2,
     175        /* If set, don't actually lock at all. */
     176        TDB_LOCK_MARK_ONLY = 4,
     177};
    165178
    166179struct tdb_methods {
     
    170183        int (*tdb_oob)(struct tdb_context *, tdb_off_t , int );
    171184        int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t );
    172         int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t);
    173185};
    174186
     
    181193        int traverse_read; /* read-only traversal */
    182194        int traverse_write; /* read-write traversal */
    183         struct tdb_lock_type global_lock;
     195        struct tdb_lock_type allrecord_lock; /* .offset == upgradable */
    184196        int num_lockrecs;
    185197        struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */
     
    194206        unsigned int (*hash_fn)(TDB_DATA *key);
    195207        int open_flags; /* flags used in the open - needed by reopen */
    196         unsigned int num_locks; /* number of chain locks held */
    197208        const struct tdb_methods *methods;
    198209        struct tdb_transaction *transaction;
    199210        int page_size;
    200211        int max_dead_records;
    201         int transaction_lock_count;
    202212#ifdef TDB_TRACE
    203213        int tracefd;
     
    214224int tdb_lock(struct tdb_context *tdb, int list, int ltype);
    215225int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
     226int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     227                  enum tdb_lock_flags flags);
     228int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     229                    bool mark_lock);
    216230int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
    217 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
    218 int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
    219 int tdb_transaction_unlock(struct tdb_context *tdb);
    220 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
     231int tdb_brlock(struct tdb_context *tdb,
     232               int rw_type, tdb_off_t offset, size_t len,
     233               enum tdb_lock_flags flags);
     234int tdb_brunlock(struct tdb_context *tdb,
     235                 int rw_type, tdb_off_t offset, size_t len);
     236bool tdb_have_extra_locks(struct tdb_context *tdb);
     237void tdb_release_transaction_locks(struct tdb_context *tdb);
     238int tdb_transaction_lock(struct tdb_context *tdb, int ltype,
     239                         enum tdb_lock_flags lockflags);
     240int tdb_transaction_unlock(struct tdb_context *tdb, int ltype);
     241int tdb_recovery_area(struct tdb_context *tdb,
     242                      const struct tdb_methods *methods,
     243                      tdb_off_t *recovery_offset,
     244                      struct tdb_record *rec);
     245int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
     246                       enum tdb_lock_flags flags, bool upgradable);
     247int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock);
     248int tdb_allrecord_upgrade(struct tdb_context *tdb);
    221249int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
    222250int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
     
    230258int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
    231259int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
    232 int _tdb_transaction_cancel(struct tdb_context *tdb);
     260bool tdb_needs_recovery(struct tdb_context *tdb);
    233261int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
    234262int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
     
    246274int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
    247275                      struct tdb_record *rec);
    248 
    249 
     276bool tdb_write_all(int fd, const void *buf, size_t count);
     277int tdb_transaction_recover(struct tdb_context *tdb);
     278void tdb_header_hash(struct tdb_context *tdb,
     279                     uint32_t *magic1_hash, uint32_t *magic2_hash);
     280unsigned int tdb_old_hash(TDB_DATA *key);
     281size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off);
  • vendor/current/lib/tdb/common/transaction.c

    r414 r740  
    99     ** library. This does NOT imply that all of Samba is released
    1010     ** under the LGPL
    11    
     11
    1212   This library is free software; you can redistribute it and/or
    1313   modify it under the terms of the GNU Lesser General Public
     
    6060    existing transaction record. If the inner transaction is cancelled
    6161    then a subsequent commit will fail
    62  
     62
    6363  - keep a mirrored copy of the tdb hash chain heads to allow for the
    6464    fast hash heads scan on traverse, updating the mirrored copy in
     
    7777
    7878  - check for a valid recovery record on open of the tdb, while the
    79     global lock is held. Automatically recover from the transaction
     79    open lock is held. Automatically recover from the transaction
    8080    recovery area if needed, then continue with the open as
    8181    usual. This allows for smooth crash recovery with no administrator
     
    136136        tdb_off_t magic_offset;
    137137
    138         /* set when the GLOBAL_LOCK has been taken */
    139         bool global_lock_taken;
    140 
    141138        /* old file size before transaction */
    142139        tdb_len_t old_map_size;
    143140
    144         /* we should re-pack on commit */
    145         bool need_repack;
     141        /* did we expand in this transaction */
     142        bool expanded;
    146143};
    147144
     
    189186                }
    190187        }
    191        
     188
    192189        /* now copy it out of this block */
    193190        memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len);
     
    296293                }
    297294        }
    298        
     295
    299296        /* overwrite part of an existing block */
    300297        if (buf == NULL) {
     
    407404        }
    408405
    409         tdb->transaction->need_repack = true;
    410 
    411         return 0;
    412 }
    413 
    414 /*
    415   brlock during a transaction - ignore them
    416 */
    417 static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
    418                               int rw_type, int lck_type, int probe, size_t len)
    419 {
     406        tdb->transaction->expanded = true;
     407
    420408        return 0;
    421409}
     
    427415        transaction_oob,
    428416        transaction_expand_file,
    429         transaction_brlock
    430417};
    431418
     
    435422  transaction is allowed to be pending per tdb_context
    436423*/
    437 int tdb_transaction_start(struct tdb_context *tdb)
     424static int _tdb_transaction_start(struct tdb_context *tdb,
     425                                  enum tdb_lock_flags lockflags)
    438426{
    439427        /* some sanity checks */
     
    456444        }
    457445
    458         if (tdb->num_locks != 0 || tdb->global_lock.count) {
     446        if (tdb_have_extra_locks(tdb)) {
    459447                /* the caller must not have any locks when starting a
    460448                   transaction as otherwise we'll be screwed by lack
     
    487475           discussed with Volker, there are a number of ways we could
    488476           make this async, which we will probably do in the future */
    489         if (tdb_transaction_lock(tdb, F_WRLCK) == -1) {
     477        if (tdb_transaction_lock(tdb, F_WRLCK, lockflags) == -1) {
    490478                SAFE_FREE(tdb->transaction->blocks);
    491479                SAFE_FREE(tdb->transaction);
    492                 return -1;
    493         }
    494        
     480                if ((lockflags & TDB_LOCK_WAIT) == 0) {
     481                        tdb->ecode = TDB_ERR_NOLOCK;
     482                }
     483                return -1;
     484        }
     485
    495486        /* get a read lock from the freelist to the end of file. This
    496487           is upgraded to a write lock during the commit */
    497         if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
     488        if (tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, true) == -1) {
    498489                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n"));
    499                 tdb->ecode = TDB_ERR_LOCK;
    500                 goto fail;
     490                goto fail_allrecord_lock;
    501491        }
    502492
     
    529519        tdb_trace(tdb, "tdb_transaction_start");
    530520        return 0;
    531        
     521
    532522fail:
    533         tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
    534         tdb_transaction_unlock(tdb);
     523        tdb_allrecord_unlock(tdb, F_RDLCK, false);
     524fail_allrecord_lock:
     525        tdb_transaction_unlock(tdb, F_WRLCK);
    535526        SAFE_FREE(tdb->transaction->blocks);
    536527        SAFE_FREE(tdb->transaction->hash_heads);
     
    539530}
    540531
     532_PUBLIC_ int tdb_transaction_start(struct tdb_context *tdb)
     533{
     534        return _tdb_transaction_start(tdb, TDB_LOCK_WAIT);
     535}
     536
     537_PUBLIC_ int tdb_transaction_start_nonblock(struct tdb_context *tdb)
     538{
     539        return _tdb_transaction_start(tdb, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
     540}
    541541
    542542/*
     
    549549        }
    550550
     551#ifdef HAVE_FDATASYNC
     552        if (fdatasync(tdb->fd) != 0) {
     553#else
    551554        if (fsync(tdb->fd) != 0) {
     555#endif
    552556                tdb->ecode = TDB_ERR_IO;
    553557                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
     
    570574
    571575
    572 int _tdb_transaction_cancel(struct tdb_context *tdb)
     576static int _tdb_transaction_cancel(struct tdb_context *tdb)
    573577{       
    574578        int i, ret = 0;
     
    597601        if (tdb->transaction->magic_offset) {
    598602                const struct tdb_methods *methods = tdb->transaction->io_methods;
    599                 uint32_t zero = 0;
     603                const uint32_t invalid = TDB_RECOVERY_INVALID_MAGIC;
    600604
    601605                /* remove the recovery marker */
    602                 if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &zero, 4) == -1 ||
     606                if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 ||
    603607                transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) {
    604608                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n"));
     
    607611        }
    608612
    609         if (tdb->transaction->global_lock_taken) {
    610                 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
    611                 tdb->transaction->global_lock_taken = false;
    612         }
    613 
    614         /* remove any global lock created during the transaction */
    615         if (tdb->global_lock.count != 0) {
    616                 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
    617                 tdb->global_lock.count = 0;
    618         }
    619 
    620         /* remove any locks created during the transaction */
    621         if (tdb->num_locks != 0) {
    622                 for (i=0;i<tdb->num_lockrecs;i++) {
    623                         tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
    624                                    F_UNLCK,F_SETLKW, 0, 1);
    625                 }
    626                 tdb->num_locks = 0;
    627                 tdb->num_lockrecs = 0;
    628                 SAFE_FREE(tdb->lockrecs);
    629         }
     613        /* This also removes the OPEN_LOCK, if we have it. */
     614        tdb_release_transaction_locks(tdb);
    630615
    631616        /* restore the normal io methods */
    632617        tdb->methods = tdb->transaction->io_methods;
    633618
    634         tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
    635         tdb_transaction_unlock(tdb);
    636619        SAFE_FREE(tdb->transaction->hash_heads);
    637620        SAFE_FREE(tdb->transaction);
    638        
     621
    639622        return ret;
    640623}
     
    643626  cancel the current transaction
    644627*/
    645 int tdb_transaction_cancel(struct tdb_context *tdb)
     628_PUBLIC_ int tdb_transaction_cancel(struct tdb_context *tdb)
    646629{
    647630        tdb_trace(tdb, "tdb_transaction_cancel");
     
    676659}
    677660
     661int tdb_recovery_area(struct tdb_context *tdb,
     662                      const struct tdb_methods *methods,
     663                      tdb_off_t *recovery_offset,
     664                      struct tdb_record *rec)
     665{
     666        if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, recovery_offset) == -1) {
     667                return -1;
     668        }
     669
     670        if (*recovery_offset == 0) {
     671                rec->rec_len = 0;
     672                return 0;
     673        }
     674
     675        if (methods->tdb_read(tdb, *recovery_offset, rec, sizeof(*rec),
     676                              DOCONV()) == -1) {
     677                return -1;
     678        }
     679
     680        /* ignore invalid recovery regions: can happen in crash */
     681        if (rec->magic != TDB_RECOVERY_MAGIC &&
     682            rec->magic != TDB_RECOVERY_INVALID_MAGIC) {
     683                *recovery_offset = 0;
     684                rec->rec_len = 0;
     685        }
     686        return 0;
     687}
     688
    678689/*
    679690  allocate the recovery area, or use an existing recovery area if it is
     
    689700        tdb_off_t recovery_head;
    690701
    691         if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
     702        if (tdb_recovery_area(tdb, methods, &recovery_head, &rec) == -1) {
    692703                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n"));
    693                 return -1;
    694         }
    695 
    696         rec.rec_len = 0;
    697 
    698         if (recovery_head != 0 &&
    699             methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
    700                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
    701704                return -1;
    702705        }
     
    794797        memset(rec, 0, sizeof(*rec));
    795798
    796         rec->magic    = 0;
     799        rec->magic    = TDB_RECOVERY_INVALID_MAGIC;
    797800        rec->data_len = recovery_size;
    798801        rec->rec_len  = recovery_max_size;
    799802        rec->key_len  = old_map_size;
    800         CONVERT(rec);
     803        CONVERT(*rec);
    801804
    802805        /* build the recovery data into a single blob to allow us to do a single
     
    816819                        length = tdb->transaction->last_block_size;
    817820                }
    818                
     821
    819822                if (offset >= old_map_size) {
    820823                        continue;
     
    845848        tailer = sizeof(*rec) + recovery_max_size;
    846849        memcpy(p, &tailer, 4);
    847         CONVERT(p);
     850        if (DOCONV()) {
     851                tdb_convert(p, 4);
     852        }
    848853
    849854        /* write the recovery data to the recovery area */
     
    929934
    930935        methods = tdb->transaction->io_methods;
    931        
     936
    932937        /* if there are any locks pending then the caller has not
    933938           nested their locks properly, so fail the transaction */
    934         if (tdb->num_locks || tdb->global_lock.count) {
     939        if (tdb_have_extra_locks(tdb)) {
    935940                tdb->ecode = TDB_ERR_LOCK;
    936941                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: locks pending on commit\n"));
     
    940945
    941946        /* upgrade the main transaction lock region to a write lock */
    942         if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
     947        if (tdb_allrecord_upgrade(tdb) == -1) {
    943948                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to upgrade hash locks\n"));
    944                 tdb->ecode = TDB_ERR_LOCK;
    945949                _tdb_transaction_cancel(tdb);
    946950                return -1;
    947951        }
    948952
    949         /* get the global lock - this prevents new users attaching to the database
     953        /* get the open lock - this prevents new users attaching to the database
    950954           during the commit */
    951         if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
    952                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get global lock\n"));
    953                 tdb->ecode = TDB_ERR_LOCK;
     955        if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
     956                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get open lock\n"));
    954957                _tdb_transaction_cancel(tdb);
    955958                return -1;
    956959        }
    957 
    958         tdb->transaction->global_lock_taken = true;
    959960
    960961        if (!(tdb->flags & TDB_NOSYNC)) {
     
    983984        }
    984985
    985         /* Keep the global lock until the actual commit */
     986        /* Keep the open lock until the actual commit */
    986987
    987988        return 0;
     
    991992   prepare to commit the current transaction
    992993*/
    993 int tdb_transaction_prepare_commit(struct tdb_context *tdb)
    994 {       
     994_PUBLIC_ int tdb_transaction_prepare_commit(struct tdb_context *tdb)
     995{
    995996        tdb_trace(tdb, "tdb_transaction_prepare_commit");
    996997        return _tdb_transaction_prepare_commit(tdb);
    997998}
    998999
     1000/* A repack is worthwhile if the largest is less than half total free. */
     1001static bool repack_worthwhile(struct tdb_context *tdb)
     1002{
     1003        tdb_off_t ptr;
     1004        struct tdb_record rec;
     1005        tdb_len_t total = 0, largest = 0;
     1006
     1007        if (tdb_ofs_read(tdb, FREELIST_TOP, &ptr) == -1) {
     1008                return false;
     1009        }
     1010
     1011        while (ptr != 0 && tdb_rec_free_read(tdb, ptr, &rec) == 0) {
     1012                total += rec.rec_len;
     1013                if (rec.rec_len > largest) {
     1014                        largest = rec.rec_len;
     1015                }
     1016                ptr = rec.next;
     1017        }
     1018
     1019        return total > largest * 2;
     1020}
     1021
    9991022/*
    10001023  commit the current transaction
    10011024*/
    1002 int tdb_transaction_commit(struct tdb_context *tdb)
    1003 {       
     1025_PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb)
     1026{
    10041027        const struct tdb_methods *methods;
    10051028        int i;
    1006         bool need_repack;
     1029        bool need_repack = false;
    10071030
    10081031        if (tdb->transaction == NULL) {
     
    10571080                if (methods->tdb_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) {
    10581081                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
    1059                        
     1082
    10601083                        /* we've overwritten part of the data and
    10611084                           possibly expanded the file, so we need to
     
    10711094                SAFE_FREE(tdb->transaction->blocks[i]);
    10721095        }
     1096
     1097        /* Do this before we drop lock or blocks. */
     1098        if (tdb->transaction->expanded) {
     1099                need_repack = repack_worthwhile(tdb);
     1100        }
    10731101
    10741102        SAFE_FREE(tdb->transaction->blocks);
     
    10951123#endif
    10961124
    1097         need_repack = tdb->transaction->need_repack;
    1098 
    10991125        /* use a transaction cancel to free memory and remove the
    11001126           transaction locks */
     
    11111137/*
    11121138  recover from an aborted transaction. Must be called with exclusive
    1113   database write access already established (including the global
     1139  database write access already established (including the open
    11141140  lock to prevent new processes attaching)
    11151141*/
     
    12121238                return -1;                     
    12131239        }
    1214        
    1215         /* reduce the file size to the old size */
    1216         tdb_munmap(tdb);
    1217         if (ftruncate(tdb->fd, recovery_eof) != 0) {
    1218                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
    1219                 tdb->ecode = TDB_ERR_IO;
    1220                 return -1;                     
    1221         }
    1222         tdb->map_size = recovery_eof;
    1223         tdb_mmap(tdb);
    12241240
    12251241        if (transaction_sync(tdb, 0, recovery_eof) == -1) {
     
    12351251        return 0;
    12361252}
     1253
     1254/* Any I/O failures we say "needs recovery". */
     1255bool tdb_needs_recovery(struct tdb_context *tdb)
     1256{
     1257        tdb_off_t recovery_head;
     1258        struct tdb_record rec;
     1259
     1260        /* find the recovery area */
     1261        if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
     1262                return true;
     1263        }
     1264
     1265        if (recovery_head == 0) {
     1266                /* we have never allocated a recovery record */
     1267                return false;
     1268        }
     1269
     1270        /* read the recovery record */
     1271        if (tdb->methods->tdb_read(tdb, recovery_head, &rec,
     1272                                   sizeof(rec), DOCONV()) == -1) {
     1273                return true;
     1274        }
     1275
     1276        return (rec.magic == TDB_RECOVERY_MAGIC);
     1277}
  • vendor/current/lib/tdb/common/traverse.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    4545                           hashes are used. In that case we spend most of our
    4646                           time in tdb_brlock(), locking empty hash chains.
    47                            
     47
    4848                           To avoid this, we do an unlocked pre-check to see
    4949                           if the hash chain is empty before starting to look
     
    5353                           lock, so instead we get the lock and re-fetch the
    5454                           value below.
    55                            
     55
    5656                           Notice that not doing this optimisation on the
    5757                           first hash chain is critical. We must guarantee
     
    6363                           could miss them anyway without this trick, so the
    6464                           semantics don't change.
    65                            
     65
    6666                           With a non-indexed ldb search this trick gains us a
    6767                           factor of around 80 in speed on a linux 2.6.x
     
    213213  a write style traverse - temporarily marks the db read only
    214214*/
    215 int tdb_traverse_read(struct tdb_context *tdb,
     215_PUBLIC_ int tdb_traverse_read(struct tdb_context *tdb,
    216216                      tdb_traverse_func fn, void *private_data)
    217217{
     
    221221        /* we need to get a read lock on the transaction lock here to
    222222           cope with the lock ordering semantics of solaris10 */
    223         if (tdb_transaction_lock(tdb, F_RDLCK)) {
     223        if (tdb_transaction_lock(tdb, F_RDLCK, TDB_LOCK_WAIT)) {
    224224                return -1;
    225225        }
     
    230230        tdb->traverse_read--;
    231231
    232         tdb_transaction_unlock(tdb);
     232        tdb_transaction_unlock(tdb, F_RDLCK);
    233233
    234234        return ret;
     
    242242  alignment restrictions malloc gives you.
    243243*/
    244 int tdb_traverse(struct tdb_context *tdb,
     244_PUBLIC_ int tdb_traverse(struct tdb_context *tdb,
    245245                 tdb_traverse_func fn, void *private_data)
    246246{
     
    252252        }
    253253
    254         if (tdb_transaction_lock(tdb, F_WRLCK)) {
     254        if (tdb_transaction_lock(tdb, F_WRLCK, TDB_LOCK_WAIT)) {
    255255                return -1;
    256256        }
     
    261261        tdb->traverse_write--;
    262262
    263         tdb_transaction_unlock(tdb);
     263        tdb_transaction_unlock(tdb, F_WRLCK);
    264264
    265265        return ret;
     
    268268
    269269/* find the first entry in the database and return its key */
    270 TDB_DATA tdb_firstkey(struct tdb_context *tdb)
     270_PUBLIC_ TDB_DATA tdb_firstkey(struct tdb_context *tdb)
    271271{
    272272        TDB_DATA key;
     
    299299
    300300/* find the next entry in the database, returning its key */
    301 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
     301_PUBLIC_ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
    302302{
    303303        uint32_t oldhash;
Note: See TracChangeset for help on using the changeset viewer.