Lines Matching refs:tdb

145 #define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t))  argument
155 #define TDB_LOG(x) tdb->log.log_fn x
167 #define BUCKET(hash) ((hash) % tdb->header.hash_size)
169 #define DOCONV() (tdb->flags & TDB_CONVERT)
262 static int tdb_munmap(struct tdb_context *tdb);
263 static void tdb_mmap(struct tdb_context *tdb);
264 static int tdb_lock(struct tdb_context *tdb, int list, int ltype);
265 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
266 static int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
267 static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int pro…
268 static int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
269 static int tdb_transaction_unlock(struct tdb_context *tdb);
270 static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
271 static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
272 static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
273 static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
274 static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
276 static int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
277 static tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec);
278 static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
279 static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
280 static int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
281 static int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
282 static int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
283 static int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
284 static int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec);
285 static unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
286 static int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
291 static tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
293 static void tdb_io_init(struct tdb_context *tdb);
294 static int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
295 static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
301 enum TDB_ERROR tdb_error(struct tdb_context *tdb) in tdb_error() argument
303 return tdb->ecode; in tdb_error()
320 const char *tdb_errorstr(struct tdb_context *tdb) in tdb_errorstr() argument
324 if (tdb->ecode == emap[i].ecode) in tdb_errorstr()
341 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, in tdb_brlock() argument
347 if (tdb->flags & TDB_NOLOCK) { in tdb_brlock()
351 if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { in tdb_brlock()
352 tdb->ecode = TDB_ERR_RDONLY; in tdb_brlock()
363 ret = fcntl(tdb->fd,lck_type,&fl); in tdb_brlock()
372 tdb->ecode = TDB_ERR_LOCK; in tdb_brlock()
373 …TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%… in tdb_brlock()
374 tdb->fd, offset, rw_type, lck_type, (int)len)); in tdb_brlock()
388 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) in tdb_brlock_upgrade() argument
393 if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { in tdb_brlock_upgrade()
404 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset)); in tdb_brlock_upgrade()
410 static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) in _tdb_lock() argument
419 if (tdb->global_lock.count && in _tdb_lock()
420 ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { in _tdb_lock()
424 if (tdb->global_lock.count) { in _tdb_lock()
428 if (list < -1 || list >= (int)tdb->header.hash_size) { in _tdb_lock()
429 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", in _tdb_lock()
433 if (tdb->flags & TDB_NOLOCK) in _tdb_lock()
436 for (i=0; i<tdb->num_lockrecs; i++) { in _tdb_lock()
437 if (tdb->lockrecs[i].list == list) { in _tdb_lock()
438 if (tdb->lockrecs[i].count == 0) { in _tdb_lock()
443 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: " in _tdb_lock()
450 tdb->lockrecs[i].count++; in _tdb_lock()
456 tdb->lockrecs, in _tdb_lock()
457 sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1)); in _tdb_lock()
462 tdb->lockrecs = new_lck; in _tdb_lock()
467 tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op, in _tdb_lock()
472 tdb->num_locks++; in _tdb_lock()
474 tdb->lockrecs[tdb->num_lockrecs].list = list; in _tdb_lock()
475 tdb->lockrecs[tdb->num_lockrecs].count = 1; in _tdb_lock()
476 tdb->lockrecs[tdb->num_lockrecs].ltype = ltype; in _tdb_lock()
477 tdb->num_lockrecs += 1; in _tdb_lock()
483 int tdb_lock(struct tdb_context *tdb, int list, int ltype) in tdb_lock() argument
486 ret = _tdb_lock(tdb, list, ltype, F_SETLKW); in tdb_lock()
488 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d " in tdb_lock()
495 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype) in tdb_lock_nonblock() argument
497 return _tdb_lock(tdb, list, ltype, F_SETLK); in tdb_lock_nonblock()
504 int tdb_unlock(struct tdb_context *tdb, int list, int ltype) in tdb_unlock() argument
514 if (tdb->global_lock.count && in tdb_unlock()
515 ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { in tdb_unlock()
519 if (tdb->global_lock.count) { in tdb_unlock()
523 if (tdb->flags & TDB_NOLOCK) in tdb_unlock()
527 if (list < -1 || list >= (int)tdb->header.hash_size) { in tdb_unlock()
528 …TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); in tdb_unlock()
532 for (i=0; i<tdb->num_lockrecs; i++) { in tdb_unlock()
533 if (tdb->lockrecs[i].list == list) { in tdb_unlock()
534 lck = &tdb->lockrecs[i]; in tdb_unlock()
540 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); in tdb_unlock()
559 ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, in tdb_unlock()
562 tdb->num_locks--; in tdb_unlock()
569 if (tdb->num_lockrecs > 1) { in tdb_unlock()
570 *lck = tdb->lockrecs[tdb->num_lockrecs-1]; in tdb_unlock()
572 tdb->num_lockrecs -= 1; in tdb_unlock()
579 if (tdb->num_lockrecs == 0) { in tdb_unlock()
580 SAFE_FREE(tdb->lockrecs); in tdb_unlock()
584 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); in tdb_unlock()
591 int tdb_transaction_lock(struct tdb_context *tdb, int ltype) in tdb_transaction_lock() argument
593 if (tdb->have_transaction_lock || tdb->global_lock.count) { in tdb_transaction_lock()
596 if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, in tdb_transaction_lock()
598 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n")); in tdb_transaction_lock()
599 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_lock()
602 tdb->have_transaction_lock = 1; in tdb_transaction_lock()
609 int tdb_transaction_unlock(struct tdb_context *tdb) in tdb_transaction_unlock() argument
612 if (!tdb->have_transaction_lock) { in tdb_transaction_unlock()
615 ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); in tdb_transaction_unlock()
617 tdb->have_transaction_lock = 0; in tdb_transaction_unlock()
626 static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op) in _tdb_lockall() argument
633 if (tdb->read_only || tdb->traverse_read) in _tdb_lockall()
636 if (tdb->global_lock.count && tdb->global_lock.ltype == (u32)ltype) { in _tdb_lockall()
637 tdb->global_lock.count++; in _tdb_lockall()
641 if (tdb->global_lock.count) { in _tdb_lockall()
646 if (tdb->num_locks != 0) { in _tdb_lockall()
652 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op, in _tdb_lockall()
653 0, 4*tdb->header.hash_size)) { in _tdb_lockall()
655 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno))); in _tdb_lockall()
660 tdb->global_lock.count = 1; in _tdb_lockall()
661 tdb->global_lock.ltype = ltype; in _tdb_lockall()
669 static int _tdb_unlockall(struct tdb_context *tdb, int ltype) in _tdb_unlockall() argument
676 if (tdb->read_only || tdb->traverse_read) { in _tdb_unlockall()
680 if (tdb->global_lock.ltype != (u32)ltype || in _tdb_unlockall()
681 tdb->global_lock.count == 0) { in _tdb_unlockall()
685 if (tdb->global_lock.count > 1) { in _tdb_unlockall()
686 tdb->global_lock.count--; in _tdb_unlockall()
691 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, in _tdb_unlockall()
692 0, 4*tdb->header.hash_size)) { in _tdb_unlockall()
693 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno))); in _tdb_unlockall()
697 tdb->global_lock.count = 0; in _tdb_unlockall()
698 tdb->global_lock.ltype = 0; in _tdb_unlockall()
704 int tdb_lockall(struct tdb_context *tdb) in tdb_lockall() argument
706 return _tdb_lockall(tdb, F_WRLCK, F_SETLKW); in tdb_lockall()
710 int tdb_lockall_mark(struct tdb_context *tdb) in tdb_lockall_mark() argument
712 return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW); in tdb_lockall_mark()
716 int tdb_lockall_unmark(struct tdb_context *tdb) in tdb_lockall_unmark() argument
718 return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK); in tdb_lockall_unmark()
722 int tdb_lockall_nonblock(struct tdb_context *tdb) in tdb_lockall_nonblock() argument
724 return _tdb_lockall(tdb, F_WRLCK, F_SETLK); in tdb_lockall_nonblock()
728 int tdb_unlockall(struct tdb_context *tdb) in tdb_unlockall() argument
730 return _tdb_unlockall(tdb, F_WRLCK); in tdb_unlockall()
734 int tdb_lockall_read(struct tdb_context *tdb) in tdb_lockall_read() argument
736 return _tdb_lockall(tdb, F_RDLCK, F_SETLKW); in tdb_lockall_read()
740 int tdb_lockall_read_nonblock(struct tdb_context *tdb) in tdb_lockall_read_nonblock() argument
742 return _tdb_lockall(tdb, F_RDLCK, F_SETLK); in tdb_lockall_read_nonblock()
746 int tdb_unlockall_read(struct tdb_context *tdb) in tdb_unlockall_read() argument
748 return _tdb_unlockall(tdb, F_RDLCK); in tdb_unlockall_read()
753 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) in tdb_chainlock() argument
755 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); in tdb_chainlock()
761 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) in tdb_chainlock_nonblock() argument
763 return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); in tdb_chainlock_nonblock()
767 int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) in tdb_chainlock_mark() argument
769 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); in tdb_chainlock_mark()
773 int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) in tdb_chainlock_unmark() argument
775 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); in tdb_chainlock_unmark()
778 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) in tdb_chainunlock() argument
780 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); in tdb_chainunlock()
783 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) in tdb_chainlock_read() argument
785 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); in tdb_chainlock_read()
788 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) in tdb_chainunlock_read() argument
790 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); in tdb_chainunlock_read()
796 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) in tdb_lock_record() argument
798 return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0; in tdb_lock_record()
806 int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) in tdb_write_lock_record() argument
809 for (i = &tdb->travlocks; i; i = i->next) in tdb_write_lock_record()
812 return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1); in tdb_write_lock_record()
819 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) in tdb_write_unlock_record() argument
821 return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1); in tdb_write_unlock_record()
825 int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) in tdb_unlock_record() argument
832 for (i = &tdb->travlocks; i; i = i->next) in tdb_unlock_record()
835 return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0); in tdb_unlock_record()
845 static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) in tdb_oob() argument
848 if (len <= tdb->map_size) in tdb_oob()
850 if (tdb->flags & TDB_INTERNAL) { in tdb_oob()
853 tdb->ecode = TDB_ERR_IO; in tdb_oob()
854 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n", in tdb_oob()
855 (int)len, (int)tdb->map_size)); in tdb_oob()
860 if (fstat(tdb->fd, &st) == -1) { in tdb_oob()
867 tdb->ecode = TDB_ERR_IO; in tdb_oob()
868 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n", in tdb_oob()
875 if (tdb_munmap(tdb) == -1) in tdb_oob()
877 tdb->map_size = st.st_size; in tdb_oob()
878 tdb_mmap(tdb); in tdb_oob()
883 static int tdb_write(struct tdb_context *tdb, tdb_off_t off, in tdb_write() argument
890 if (tdb->read_only || tdb->traverse_read) { in tdb_write()
891 tdb->ecode = TDB_ERR_RDONLY; in tdb_write()
895 if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) in tdb_write()
898 if (tdb->map_ptr) { in tdb_write()
899 memcpy(off + (char *)tdb->map_ptr, buf, len); in tdb_write()
900 } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { in tdb_write()
902 tdb->ecode = TDB_ERR_IO; in tdb_write()
903 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n", in tdb_write()
921 static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, in tdb_read() argument
924 if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) { in tdb_read()
928 if (tdb->map_ptr) { in tdb_read()
929 memcpy(buf, off + (char *)tdb->map_ptr, len); in tdb_read()
931 ssize_t ret = pread(tdb->fd, buf, len, off); in tdb_read()
934 tdb->ecode = TDB_ERR_IO; in tdb_read()
935 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d " in tdb_read()
938 (int)tdb->map_size)); in tdb_read()
954 static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) in tdb_next_hash_chain() argument
957 if (tdb->map_ptr) { in tdb_next_hash_chain()
958 for (;h < tdb->header.hash_size;h++) { in tdb_next_hash_chain()
959 if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { in tdb_next_hash_chain()
965 for (;h < tdb->header.hash_size;h++) { in tdb_next_hash_chain()
966 if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { in tdb_next_hash_chain()
975 int tdb_munmap(struct tdb_context *tdb) in tdb_munmap() argument
977 if (tdb->flags & TDB_INTERNAL) in tdb_munmap()
981 if (tdb->map_ptr) { in tdb_munmap()
982 int ret = munmap(tdb->map_ptr, tdb->real_map_size); in tdb_munmap()
985 tdb->real_map_size = 0; in tdb_munmap()
988 tdb->map_ptr = NULL; in tdb_munmap()
992 void tdb_mmap(struct tdb_context *tdb) in tdb_mmap() argument
994 if (tdb->flags & TDB_INTERNAL) in tdb_mmap()
998 if (!(tdb->flags & TDB_NOMMAP)) { in tdb_mmap()
999 tdb->map_ptr = mmap(NULL, tdb->map_size, in tdb_mmap()
1000 PROT_READ|(tdb->read_only? 0:PROT_WRITE), in tdb_mmap()
1001 MAP_SHARED|MAP_FILE, tdb->fd, 0); in tdb_mmap()
1007 if (tdb->map_ptr == MAP_FAILED) { in tdb_mmap()
1008 tdb->real_map_size = 0; in tdb_mmap()
1009 tdb->map_ptr = NULL; in tdb_mmap()
1010 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", in tdb_mmap()
1011 tdb->map_size, strerror(errno))); in tdb_mmap()
1013 tdb->real_map_size = tdb->map_size; in tdb_mmap()
1015 tdb->map_ptr = NULL; in tdb_mmap()
1018 tdb->map_ptr = NULL; in tdb_mmap()
1024 static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) in tdb_expand_file() argument
1028 if (tdb->read_only || tdb->traverse_read) { in tdb_expand_file()
1029 tdb->ecode = TDB_ERR_RDONLY; in tdb_expand_file()
1033 if (ftruncate(tdb->fd, size+addition) == -1) { in tdb_expand_file()
1035 if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { in tdb_expand_file()
1036 TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", in tdb_expand_file()
1048 int ret = pwrite(tdb->fd, buf, n, size); in tdb_expand_file()
1050 TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n", in tdb_expand_file()
1063 int tdb_expand(struct tdb_context *tdb, tdb_off_t size) in tdb_expand() argument
1068 if (tdb_lock(tdb, -1, F_WRLCK) == -1) { in tdb_expand()
1069 TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n")); in tdb_expand()
1074 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); in tdb_expand()
1078 size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size; in tdb_expand()
1080 if (!(tdb->flags & TDB_INTERNAL)) in tdb_expand()
1081 tdb_munmap(tdb); in tdb_expand()
1090 if (!(tdb->flags & TDB_INTERNAL)) { in tdb_expand()
1091 if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0) in tdb_expand()
1095 tdb->map_size += size; in tdb_expand()
1097 if (tdb->flags & TDB_INTERNAL) { in tdb_expand()
1098 char *new_map_ptr = (char *)realloc(tdb->map_ptr, in tdb_expand()
1099 tdb->map_size); in tdb_expand()
1101 tdb->map_size -= size; in tdb_expand()
1104 tdb->map_ptr = new_map_ptr; in tdb_expand()
1113 tdb_mmap(tdb); in tdb_expand()
1121 offset = tdb->map_size - size; in tdb_expand()
1122 if (tdb_free(tdb, offset, &rec) == -1) in tdb_expand()
1125 tdb_unlock(tdb, -1, F_WRLCK); in tdb_expand()
1128 tdb_unlock(tdb, -1, F_WRLCK); in tdb_expand()
1133 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) in tdb_ofs_read() argument
1135 return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); in tdb_ofs_read()
1138 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) in tdb_ofs_write() argument
1141 return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); in tdb_ofs_write()
1146 unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) in tdb_alloc_read() argument
1157 tdb->ecode = TDB_ERR_OOM; in tdb_alloc_read()
1158 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n", in tdb_alloc_read()
1162 if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { in tdb_alloc_read()
1171 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, in tdb_parse_data() argument
1182 if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { in tdb_parse_data()
1187 if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) { in tdb_parse_data()
1190 data.dptr = offset + (unsigned char *)tdb->map_ptr; in tdb_parse_data()
1194 if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) { in tdb_parse_data()
1204 int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) in tdb_rec_read() argument
1206 if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) in tdb_rec_read()
1210 tdb->ecode = TDB_ERR_CORRUPT; in tdb_rec_read()
1211 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); in tdb_rec_read()
1214 return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); in tdb_rec_read()
1217 int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) in tdb_rec_write() argument
1220 return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); in tdb_rec_write()
1235 void tdb_io_init(struct tdb_context *tdb) in tdb_io_init() argument
1237 tdb->methods = &io_methods; in tdb_io_init()
1348 static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, in transaction_read() argument
1354 for (el=tdb->transaction->elements_last;el;el=el->prev) { in transaction_read()
1368 if (transaction_read(tdb, off, buf, partial, cv) != 0) { in transaction_read()
1388 if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) { in transaction_read()
1396 return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv); in transaction_read()
1399 TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len)); in transaction_read()
1400 tdb->ecode = TDB_ERR_IO; in transaction_read()
1401 tdb->transaction->transaction_error = 1; in transaction_read()
1409 static int transaction_write(struct tdb_context *tdb, tdb_off_t off, in transaction_write() argument
1421 off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { in transaction_write()
1423 memcpy(&tdb->transaction->hash_heads[chain], buf, len); in transaction_write()
1427 for (el=tdb->transaction->elements_last;el;el=el->prev) { in transaction_write()
1445 if (transaction_write(tdb, off, buf, partial) != 0) { in transaction_write()
1462 if (len != 0 && transaction_write(tdb, off, buf, len) != 0) { in transaction_write()
1471 (off+len < tdb->transaction->old_map_size || in transaction_write()
1472 off > tdb->transaction->old_map_size)) { in transaction_write()
1478 tdb->ecode = TDB_ERR_OOM; in transaction_write()
1479 tdb->transaction->transaction_error = 1; in transaction_write()
1495 tdb->ecode = TDB_ERR_OOM; in transaction_write()
1496 tdb->transaction->transaction_error = 1; in transaction_write()
1500 el->prev = tdb->transaction->elements_last; in transaction_write()
1506 tdb->ecode = TDB_ERR_OOM; in transaction_write()
1507 tdb->transaction->transaction_error = 1; in transaction_write()
1518 tdb->transaction->elements = el; in transaction_write()
1520 tdb->transaction->elements_last = el; in transaction_write()
1524 TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len)); in transaction_write()
1525 tdb->ecode = TDB_ERR_IO; in transaction_write()
1526 tdb->transaction->transaction_error = 1; in transaction_write()
1533 static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain) in transaction_next_hash_chain() argument
1536 for (;h < tdb->header.hash_size;h++) { in transaction_next_hash_chain()
1538 if (0 != tdb->transaction->hash_heads[h+1]) { in transaction_next_hash_chain()
1548 static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, in transaction_oob() argument
1551 if (len <= tdb->map_size) { in transaction_oob()
1560 static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, in transaction_expand_file() argument
1565 if (transaction_write(tdb, size, NULL, addition) != 0) { in transaction_expand_file()
1575 static int transaction_brlock(struct tdb_context *tdb EXT2FS_ATTR((unused)), in transaction_brlock()
1599 int tdb_transaction_start(struct tdb_context *tdb) in tdb_transaction_start() argument
1602 if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { in tdb_transaction_start()
1603 …TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only o… in tdb_transaction_start()
1604 tdb->ecode = TDB_ERR_EINVAL; in tdb_transaction_start()
1609 if (tdb->transaction != NULL) { in tdb_transaction_start()
1610 tdb->transaction->nesting++; in tdb_transaction_start()
1611 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", in tdb_transaction_start()
1612 tdb->transaction->nesting)); in tdb_transaction_start()
1616 if (tdb->num_locks != 0 || tdb->global_lock.count) { in tdb_transaction_start()
1620 …TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\… in tdb_transaction_start()
1621 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_start()
1625 if (tdb->travlocks.next != NULL) { in tdb_transaction_start()
1629 …TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a travers… in tdb_transaction_start()
1630 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_start()
1634 tdb->transaction = (struct tdb_transaction *) in tdb_transaction_start()
1636 if (tdb->transaction == NULL) { in tdb_transaction_start()
1637 tdb->ecode = TDB_ERR_OOM; in tdb_transaction_start()
1644 if (tdb_transaction_lock(tdb, F_WRLCK) == -1) { in tdb_transaction_start()
1645 SAFE_FREE(tdb->transaction); in tdb_transaction_start()
1651 if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { in tdb_transaction_start()
1652 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); in tdb_transaction_start()
1653 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_start()
1659 tdb->transaction->hash_heads = (u32 *) in tdb_transaction_start()
1660 calloc(tdb->header.hash_size+1, sizeof(u32)); in tdb_transaction_start()
1661 if (tdb->transaction->hash_heads == NULL) { in tdb_transaction_start()
1662 tdb->ecode = TDB_ERR_OOM; in tdb_transaction_start()
1665 if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, in tdb_transaction_start()
1666 TDB_HASHTABLE_SIZE(tdb), 0) != 0) { in tdb_transaction_start()
1667 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); in tdb_transaction_start()
1668 tdb->ecode = TDB_ERR_IO; in tdb_transaction_start()
1674 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); in tdb_transaction_start()
1675 tdb->transaction->old_map_size = tdb->map_size; in tdb_transaction_start()
1679 tdb->transaction->io_methods = tdb->methods; in tdb_transaction_start()
1680 tdb->methods = &transaction_methods; in tdb_transaction_start()
1684 if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, in tdb_transaction_start()
1685 TDB_HASHTABLE_SIZE(tdb)) != 0) { in tdb_transaction_start()
1686 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n")); in tdb_transaction_start()
1687 tdb->ecode = TDB_ERR_IO; in tdb_transaction_start()
1688 tdb->methods = tdb->transaction->io_methods; in tdb_transaction_start()
1695 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); in tdb_transaction_start()
1696 tdb_transaction_unlock(tdb); in tdb_transaction_start()
1697 SAFE_FREE(tdb->transaction->hash_heads); in tdb_transaction_start()
1698 SAFE_FREE(tdb->transaction); in tdb_transaction_start()
1706 int tdb_transaction_cancel(struct tdb_context *tdb) in tdb_transaction_cancel() argument
1708 if (tdb->transaction == NULL) { in tdb_transaction_cancel()
1709 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); in tdb_transaction_cancel()
1713 if (tdb->transaction->nesting != 0) { in tdb_transaction_cancel()
1714 tdb->transaction->transaction_error = 1; in tdb_transaction_cancel()
1715 tdb->transaction->nesting--; in tdb_transaction_cancel()
1719 tdb->map_size = tdb->transaction->old_map_size; in tdb_transaction_cancel()
1722 while (tdb->transaction->elements) { in tdb_transaction_cancel()
1723 struct tdb_transaction_el *el = tdb->transaction->elements; in tdb_transaction_cancel()
1724 tdb->transaction->elements = el->next; in tdb_transaction_cancel()
1730 if (tdb->global_lock.count != 0) { in tdb_transaction_cancel()
1731 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size); in tdb_transaction_cancel()
1732 tdb->global_lock.count = 0; in tdb_transaction_cancel()
1736 if (tdb->num_locks != 0) { in tdb_transaction_cancel()
1738 for (i=0;i<tdb->num_lockrecs;i++) { in tdb_transaction_cancel()
1739 tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list, in tdb_transaction_cancel()
1742 tdb->num_locks = 0; in tdb_transaction_cancel()
1743 tdb->num_lockrecs = 0; in tdb_transaction_cancel()
1744 SAFE_FREE(tdb->lockrecs); in tdb_transaction_cancel()
1748 tdb->methods = tdb->transaction->io_methods; in tdb_transaction_cancel()
1750 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); in tdb_transaction_cancel()
1751 tdb_transaction_unlock(tdb); in tdb_transaction_cancel()
1752 SAFE_FREE(tdb->transaction->hash_heads); in tdb_transaction_cancel()
1753 SAFE_FREE(tdb->transaction); in tdb_transaction_cancel()
1761 static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) in transaction_sync() argument
1763 if (fsync(tdb->fd) != 0) { in transaction_sync()
1764 tdb->ecode = TDB_ERR_IO; in transaction_sync()
1765 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); in transaction_sync()
1769 if (tdb->map_ptr) { in transaction_sync()
1770 tdb_off_t moffset = offset & ~(tdb->page_size-1); in transaction_sync()
1771 if (msync(moffset + (char *)tdb->map_ptr, in transaction_sync()
1773 tdb->ecode = TDB_ERR_IO; in transaction_sync()
1774 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n", in transaction_sync()
1787 static tdb_len_t tdb_recovery_size(struct tdb_context *tdb) in tdb_recovery_size() argument
1793 for (el=tdb->transaction->elements;el;el=el->next) { in tdb_recovery_size()
1794 if (el->offset >= tdb->transaction->old_map_size) { in tdb_recovery_size()
1807 static int tdb_recovery_allocate(struct tdb_context *tdb, in tdb_recovery_allocate() argument
1813 const struct tdb_methods *methods = tdb->transaction->io_methods; in tdb_recovery_allocate()
1816 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { in tdb_recovery_allocate()
1817 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); in tdb_recovery_allocate()
1824 methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { in tdb_recovery_allocate()
1825 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); in tdb_recovery_allocate()
1829 *recovery_size = tdb_recovery_size(tdb); in tdb_recovery_allocate()
1844 if (tdb_free(tdb, recovery_head, &rec) == -1) { in tdb_recovery_allocate()
1845 … TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n")); in tdb_recovery_allocate()
1851 *recovery_size = tdb_recovery_size(tdb); in tdb_recovery_allocate()
1854 *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); in tdb_recovery_allocate()
1855 *recovery_offset = tdb->map_size; in tdb_recovery_allocate()
1858 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, in tdb_recovery_allocate()
1859 (tdb->map_size - tdb->transaction->old_map_size) + in tdb_recovery_allocate()
1861 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n")); in tdb_recovery_allocate()
1866 methods->tdb_oob(tdb, tdb->map_size + 1, 1); in tdb_recovery_allocate()
1870 tdb->transaction->old_map_size = tdb->map_size; in tdb_recovery_allocate()
1875 if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, in tdb_recovery_allocate()
1877 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); in tdb_recovery_allocate()
1888 static int transaction_setup_recovery(struct tdb_context *tdb, in transaction_setup_recovery() argument
1894 const struct tdb_methods *methods = tdb->transaction->io_methods; in transaction_setup_recovery()
1897 tdb_off_t old_map_size = tdb->transaction->old_map_size; in transaction_setup_recovery()
1903 if (tdb_recovery_allocate(tdb, &recovery_size, in transaction_setup_recovery()
1910 tdb->ecode = TDB_ERR_OOM; in transaction_setup_recovery()
1926 for (el=tdb->transaction->elements;el;el=el->next) { in transaction_setup_recovery()
1930 if (el->offset + el->length > tdb->transaction->old_map_size) { in transaction_setup_recovery()
1931 …TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region b… in transaction_setup_recovery()
1933 tdb->ecode = TDB_ERR_CORRUPT; in transaction_setup_recovery()
1944 if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) { in transaction_setup_recovery()
1946 tdb->ecode = TDB_ERR_IO; in transaction_setup_recovery()
1958 if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { in transaction_setup_recovery()
1959 …TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n")); in transaction_setup_recovery()
1961 tdb->ecode = TDB_ERR_IO; in transaction_setup_recovery()
1968 if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { in transaction_setup_recovery()
1980 if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { in transaction_setup_recovery()
1981 …TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n")… in transaction_setup_recovery()
1982 tdb->ecode = TDB_ERR_IO; in transaction_setup_recovery()
1987 if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { in transaction_setup_recovery()
1997 int tdb_transaction_commit(struct tdb_context *tdb) in tdb_transaction_commit() argument
2003 if (tdb->transaction == NULL) { in tdb_transaction_commit()
2004 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); in tdb_transaction_commit()
2008 if (tdb->transaction->transaction_error) { in tdb_transaction_commit()
2009 tdb->ecode = TDB_ERR_IO; in tdb_transaction_commit()
2010 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2011 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); in tdb_transaction_commit()
2015 if (tdb->transaction->nesting != 0) { in tdb_transaction_commit()
2016 tdb->transaction->nesting--; in tdb_transaction_commit()
2021 if (tdb->transaction->elements == NULL) { in tdb_transaction_commit()
2022 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2026 methods = tdb->transaction->io_methods; in tdb_transaction_commit()
2030 if (tdb->num_locks || tdb->global_lock.count) { in tdb_transaction_commit()
2031 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_commit()
2032 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n")); in tdb_transaction_commit()
2033 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2038 if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { in tdb_transaction_commit()
2039 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n")); in tdb_transaction_commit()
2040 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_commit()
2041 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2047 if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { in tdb_transaction_commit()
2048 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n")); in tdb_transaction_commit()
2049 tdb->ecode = TDB_ERR_LOCK; in tdb_transaction_commit()
2050 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2054 if (!(tdb->flags & TDB_NOSYNC)) { in tdb_transaction_commit()
2056 if (transaction_setup_recovery(tdb, &magic_offset) == -1) { in tdb_transaction_commit()
2057 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n")); in tdb_transaction_commit()
2058 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); in tdb_transaction_commit()
2059 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2065 if (tdb->map_size != tdb->transaction->old_map_size) { in tdb_transaction_commit()
2066 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, in tdb_transaction_commit()
2067 tdb->map_size - in tdb_transaction_commit()
2068 tdb->transaction->old_map_size) == -1) { in tdb_transaction_commit()
2069 tdb->ecode = TDB_ERR_IO; in tdb_transaction_commit()
2070 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n")); in tdb_transaction_commit()
2071 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); in tdb_transaction_commit()
2072 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2075 tdb->map_size = tdb->transaction->old_map_size; in tdb_transaction_commit()
2076 methods->tdb_oob(tdb, tdb->map_size + 1, 1); in tdb_transaction_commit()
2080 while (tdb->transaction->elements) { in tdb_transaction_commit()
2081 struct tdb_transaction_el *el = tdb->transaction->elements; in tdb_transaction_commit()
2083 if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { in tdb_transaction_commit()
2084 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); in tdb_transaction_commit()
2089 tdb->methods = methods; in tdb_transaction_commit()
2090 tdb_transaction_recover(tdb); in tdb_transaction_commit()
2092 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2093 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); in tdb_transaction_commit()
2095 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); in tdb_transaction_commit()
2098 tdb->transaction->elements = el->next; in tdb_transaction_commit()
2103 if (!(tdb->flags & TDB_NOSYNC)) { in tdb_transaction_commit()
2105 if (transaction_sync(tdb, 0, tdb->map_size) == -1) { in tdb_transaction_commit()
2110 if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { in tdb_transaction_commit()
2111 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n")); in tdb_transaction_commit()
2116 if (transaction_sync(tdb, magic_offset, 4) == -1) { in tdb_transaction_commit()
2121 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); in tdb_transaction_commit()
2135 utime(tdb->name, NULL); in tdb_transaction_commit()
2140 tdb_transaction_cancel(tdb); in tdb_transaction_commit()
2150 int tdb_transaction_recover(struct tdb_context *tdb) in tdb_transaction_recover() argument
2158 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { in tdb_transaction_recover()
2159 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); in tdb_transaction_recover()
2160 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2170 if (tdb->methods->tdb_read(tdb, recovery_head, &rec, in tdb_transaction_recover()
2172 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); in tdb_transaction_recover()
2173 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2182 if (tdb->read_only) { in tdb_transaction_recover()
2183 …TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")… in tdb_transaction_recover()
2184 tdb->ecode = TDB_ERR_CORRUPT; in tdb_transaction_recover()
2192 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); in tdb_transaction_recover()
2193 tdb->ecode = TDB_ERR_OOM; in tdb_transaction_recover()
2198 if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, in tdb_transaction_recover()
2200 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); in tdb_transaction_recover()
2201 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2216 if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { in tdb_transaction_recover()
2218 …TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n… in tdb_transaction_recover()
2219 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2227 if (transaction_sync(tdb, 0, tdb->map_size) == -1) { in tdb_transaction_recover()
2228 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); in tdb_transaction_recover()
2229 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2235 if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { in tdb_transaction_recover()
2236 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); in tdb_transaction_recover()
2237 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2243 if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), in tdb_transaction_recover()
2245 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); in tdb_transaction_recover()
2246 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2251 tdb_munmap(tdb); in tdb_transaction_recover()
2252 if (ftruncate(tdb->fd, recovery_eof) != 0) { in tdb_transaction_recover()
2253 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n")); in tdb_transaction_recover()
2254 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2257 tdb->map_size = recovery_eof; in tdb_transaction_recover()
2258 tdb_mmap(tdb); in tdb_transaction_recover()
2260 if (transaction_sync(tdb, 0, recovery_eof) == -1) { in tdb_transaction_recover()
2261 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); in tdb_transaction_recover()
2262 tdb->ecode = TDB_ERR_IO; in tdb_transaction_recover()
2266 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", in tdb_transaction_recover()
2276 static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec) in tdb_rec_free_read() argument
2278 if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) in tdb_rec_free_read()
2284 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n", in tdb_rec_free_read()
2287 if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) in tdb_rec_free_read()
2293 tdb->ecode = TDB_ERR_CORRUPT; in tdb_rec_free_read()
2294 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", in tdb_rec_free_read()
2298 if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) in tdb_rec_free_read()
2306 static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) in remove_from_freelist() argument
2312 while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { in remove_from_freelist()
2315 return tdb_ofs_write(tdb, last_ptr, &next); in remove_from_freelist()
2320 TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off)); in remove_from_freelist()
2326 static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, in update_tailer() argument
2333 return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), in update_tailer()
2339 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) in tdb_free() argument
2344 if (tdb_lock(tdb, -1, F_WRLCK) != 0) in tdb_free()
2348 if (update_tailer(tdb, offset, rec) != 0) { in tdb_free()
2349 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); in tdb_free()
2355 if (right + sizeof(*rec) <= tdb->map_size) { in tdb_free()
2358 if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { in tdb_free()
2359 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right)); in tdb_free()
2365 if (remove_from_freelist(tdb, right, r.next) == -1) { in tdb_free()
2366 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right)); in tdb_free()
2376 if (left > TDB_DATA_START(tdb->header.hash_size)) { in tdb_free()
2381 if (tdb_ofs_read(tdb, left, &leftsize) == -1) { in tdb_free()
2382 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left)); in tdb_free()
2394 if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { in tdb_free()
2395 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); in tdb_free()
2401 if (remove_from_freelist(tdb, left, l.next) == -1) { in tdb_free()
2402 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left)); in tdb_free()
2412 if (update_tailer(tdb, offset, rec) == -1) { in tdb_free()
2413 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); in tdb_free()
2420 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || in tdb_free()
2421 tdb_rec_write(tdb, offset, rec) == -1 || in tdb_free()
2422 tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { in tdb_free()
2423 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset)); in tdb_free()
2428 tdb_unlock(tdb, -1, F_WRLCK); in tdb_free()
2432 tdb_unlock(tdb, -1, F_WRLCK); in tdb_free()
2441 static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr, in tdb_allocate_ofs() argument
2465 if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { in tdb_allocate_ofs()
2474 if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { in tdb_allocate_ofs()
2482 if (update_tailer(tdb, rec_ptr, rec) == -1) { in tdb_allocate_ofs()
2487 if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { in tdb_allocate_ofs()
2502 tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec) in tdb_allocate() argument
2510 if (tdb_lock(tdb, -1, F_WRLCK) == -1) in tdb_allocate()
2520 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) in tdb_allocate()
2533 if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) { in tdb_allocate()
2558 if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { in tdb_allocate()
2562 newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); in tdb_allocate()
2563 tdb_unlock(tdb, -1, F_WRLCK); in tdb_allocate()
2569 if (tdb_expand(tdb, length + sizeof(*rec)) == 0) in tdb_allocate()
2572 tdb_unlock(tdb, -1, F_WRLCK); in tdb_allocate()
2596 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) in tdb_validate_freelist() argument
2605 mem_tdb = tdb_open("flval", tdb->header.hash_size, in tdb_validate_freelist()
2611 if (tdb_lock(tdb, -1, F_WRLCK) == -1) { in tdb_validate_freelist()
2625 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) { in tdb_validate_freelist()
2640 if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) { in tdb_validate_freelist()
2655 tdb_unlock(tdb, -1, F_WRLCK); in tdb_validate_freelist()
2662 static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, in tdb_next_lock() argument
2668 for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { in tdb_next_lock()
2698 tdb->methods->next_hash_chain(tdb, &tlock->hash); in tdb_next_lock()
2699 if (tlock->hash == tdb->header.hash_size) { in tdb_next_lock()
2704 if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1) in tdb_next_lock()
2709 if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash), in tdb_next_lock()
2714 if (tdb_unlock_record(tdb, tlock->off) != 0) in tdb_next_lock()
2720 if (tdb_rec_read(tdb, tlock->off, rec) == -1) in tdb_next_lock()
2728 if (tdb_rec_read(tdb, tlock->off, rec) == -1) in tdb_next_lock()
2733 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n")); in tdb_next_lock()
2739 if (tdb_lock_record(tdb, tlock->off) != 0) in tdb_next_lock()
2747 if (!(tdb->read_only || tdb->traverse_read) && in tdb_next_lock()
2748 tdb_do_delete(tdb, current, rec) != 0) in tdb_next_lock()
2751 tdb_unlock(tdb, tlock->hash, tlock->lock_rw); in tdb_next_lock()
2759 if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) in tdb_next_lock()
2760 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n")); in tdb_next_lock()
2769 static int tdb_traverse_internal(struct tdb_context *tdb, in tdb_traverse_internal() argument
2780 tl->next = tdb->travlocks.next; in tdb_traverse_internal()
2783 tdb->travlocks.next = tl; in tdb_traverse_internal()
2786 while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) { in tdb_traverse_internal()
2789 key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), in tdb_traverse_internal()
2793 if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) in tdb_traverse_internal()
2795 if (tdb_unlock_record(tdb, tl->off) != 0) in tdb_traverse_internal()
2796 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); in tdb_traverse_internal()
2804 if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { in tdb_traverse_internal()
2809 if (fn && fn(tdb, key, dbuf, private_data)) { in tdb_traverse_internal()
2812 if (tdb_unlock_record(tdb, tl->off) != 0) { in tdb_traverse_internal()
2813 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; in tdb_traverse_internal()
2822 tdb->travlocks.next = tl->next; in tdb_traverse_internal()
2833 int tdb_traverse_read(struct tdb_context *tdb, in tdb_traverse_read() argument
2841 if (tdb_transaction_lock(tdb, F_RDLCK)) { in tdb_traverse_read()
2845 tdb->traverse_read++; in tdb_traverse_read()
2846 ret = tdb_traverse_internal(tdb, fn, private_data, &tl); in tdb_traverse_read()
2847 tdb->traverse_read--; in tdb_traverse_read()
2849 tdb_transaction_unlock(tdb); in tdb_traverse_read()
2858 int tdb_traverse(struct tdb_context *tdb, in tdb_traverse() argument
2864 if (tdb->read_only || tdb->traverse_read) { in tdb_traverse()
2865 return tdb_traverse_read(tdb, fn, private_data); in tdb_traverse()
2868 if (tdb_transaction_lock(tdb, F_WRLCK)) { in tdb_traverse()
2872 ret = tdb_traverse_internal(tdb, fn, private_data, &tl); in tdb_traverse()
2874 tdb_transaction_unlock(tdb); in tdb_traverse()
2881 TDB_DATA tdb_firstkey(struct tdb_context *tdb) in tdb_firstkey() argument
2887 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) in tdb_firstkey()
2889 tdb->travlocks.off = tdb->travlocks.hash = 0; in tdb_firstkey()
2890 tdb->travlocks.lock_rw = F_RDLCK; in tdb_firstkey()
2893 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) in tdb_firstkey()
2897 key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); in tdb_firstkey()
2900 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) in tdb_firstkey()
2901 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); in tdb_firstkey()
2906 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) in tdb_nextkey() argument
2914 if (tdb->travlocks.off) { in tdb_nextkey()
2915 if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw)) in tdb_nextkey()
2917 if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 in tdb_nextkey()
2918 || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), in tdb_nextkey()
2922 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { in tdb_nextkey()
2926 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) { in tdb_nextkey()
2930 tdb->travlocks.off = 0; in tdb_nextkey()
2936 if (!tdb->travlocks.off) { in tdb_nextkey()
2938tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw… in tdb_nextkey()
2939 if (!tdb->travlocks.off) in tdb_nextkey()
2941 tdb->travlocks.hash = BUCKET(rec.full_hash); in tdb_nextkey()
2942 if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { in tdb_nextkey()
2943 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); in tdb_nextkey()
2947 oldhash = tdb->travlocks.hash; in tdb_nextkey()
2951 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { in tdb_nextkey()
2953 key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), in tdb_nextkey()
2956 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) in tdb_nextkey()
2957 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); in tdb_nextkey()
2960 if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0) in tdb_nextkey()
2961 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); in tdb_nextkey()
2967 static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash, in tdb_dump_record() argument
2973 if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, in tdb_dump_record()
2986 if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { in tdb_dump_record()
2998 static int tdb_dump_chain(struct tdb_context *tdb, int i) in tdb_dump_chain() argument
3004 if (tdb_lock(tdb, i, F_WRLCK) != 0) in tdb_dump_chain()
3007 if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) in tdb_dump_chain()
3008 return tdb_unlock(tdb, i, F_WRLCK); in tdb_dump_chain()
3014 rec_ptr = tdb_dump_record(tdb, i, rec_ptr); in tdb_dump_chain()
3017 return tdb_unlock(tdb, i, F_WRLCK); in tdb_dump_chain()
3020 void tdb_dump_all(struct tdb_context *tdb) in tdb_dump_all() argument
3023 for (i = 0; i < (int)tdb->header.hash_size; i++) { in tdb_dump_all()
3024 tdb_dump_chain(tdb, i); in tdb_dump_all()
3027 tdb_dump_chain(tdb, -1); in tdb_dump_all()
3030 int tdb_printfreelist(struct tdb_context *tdb) in tdb_printfreelist() argument
3037 if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) in tdb_printfreelist()
3043 if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { in tdb_printfreelist()
3044 tdb_unlock(tdb, -1, F_WRLCK); in tdb_printfreelist()
3050 if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, in tdb_printfreelist()
3052 tdb_unlock(tdb, -1, F_WRLCK); in tdb_printfreelist()
3058 tdb_unlock(tdb, -1, F_WRLCK); in tdb_printfreelist()
3072 return tdb_unlock(tdb, -1, F_WRLCK); in tdb_printfreelist()
3081 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) in tdb_increment_seqnum_nonblock() argument
3085 if (!(tdb->flags & TDB_SEQNUM)) { in tdb_increment_seqnum_nonblock()
3092 if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) in tdb_increment_seqnum_nonblock()
3095 (void) tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); in tdb_increment_seqnum_nonblock()
3102 static void tdb_increment_seqnum(struct tdb_context *tdb) in tdb_increment_seqnum() argument
3104 if (!(tdb->flags & TDB_SEQNUM)) { in tdb_increment_seqnum()
3108 if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) { in tdb_increment_seqnum()
3112 tdb_increment_seqnum_nonblock(tdb); in tdb_increment_seqnum()
3114 tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1); in tdb_increment_seqnum()
3125 static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, in tdb_find() argument
3131 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) in tdb_find()
3136 if (tdb_rec_read(tdb, rec_ptr, r) == -1) in tdb_find()
3141 && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r), in tdb_find()
3152 tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, in tdb_find_lock_hash() argument
3157 if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) in tdb_find_lock_hash()
3159 if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) in tdb_find_lock_hash()
3160 tdb_unlock(tdb, BUCKET(hash), locktype); in tdb_find_lock_hash()
3169 static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) in tdb_update_hash() argument
3175 if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) in tdb_update_hash()
3180 tdb->ecode = TDB_SUCCESS; /* Not really an error */ in tdb_update_hash()
3184 if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, in tdb_update_hash()
3191 return tdb_rec_write(tdb, rec_ptr, &rec); in tdb_update_hash()
3203 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) in tdb_fetch() argument
3211 hash = tdb->hash_fn(&key); in tdb_fetch()
3212 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) in tdb_fetch()
3215 ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, in tdb_fetch()
3218 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); in tdb_fetch()
3238 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, in tdb_parse_record() argument
3249 hash = tdb->hash_fn(&key); in tdb_parse_record()
3251 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { in tdb_parse_record()
3255 ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, in tdb_parse_record()
3258 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); in tdb_parse_record()
3269 static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) in tdb_exists_hash() argument
3273 if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) in tdb_exists_hash()
3275 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); in tdb_exists_hash()
3279 int tdb_exists(struct tdb_context *tdb, TDB_DATA key) in tdb_exists() argument
3281 u32 hash = tdb->hash_fn(&key); in tdb_exists()
3282 return tdb_exists_hash(tdb, key, hash); in tdb_exists()
3286 int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec) in tdb_do_delete() argument
3291 if (tdb->read_only || tdb->traverse_read) return -1; in tdb_do_delete()
3293 if (tdb_write_lock_record(tdb, rec_ptr) == -1) { in tdb_do_delete()
3296 return tdb_rec_write(tdb, rec_ptr, rec); in tdb_do_delete()
3298 if (tdb_write_unlock_record(tdb, rec_ptr) != 0) in tdb_do_delete()
3302 if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) in tdb_do_delete()
3305 if (tdb_rec_read(tdb, i, &lastrec) == -1) in tdb_do_delete()
3311 if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) in tdb_do_delete()
3315 if (tdb_free(tdb, rec_ptr, rec) == -1) in tdb_do_delete()
3320 static int tdb_count_dead(struct tdb_context *tdb, u32 hash) in tdb_count_dead() argument
3327 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) in tdb_count_dead()
3331 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) in tdb_count_dead()
3345 static int tdb_purge_dead(struct tdb_context *tdb, u32 hash) in tdb_purge_dead() argument
3351 if (tdb_lock(tdb, -1, F_WRLCK) == -1) { in tdb_purge_dead()
3356 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) in tdb_purge_dead()
3362 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) { in tdb_purge_dead()
3369 && tdb_do_delete(tdb, rec_ptr, &rec) == -1) { in tdb_purge_dead()
3376 tdb_unlock(tdb, -1, F_WRLCK); in tdb_purge_dead()
3381 static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) in tdb_delete_hash() argument
3387 if (tdb->max_dead_records != 0) { in tdb_delete_hash()
3394 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) in tdb_delete_hash()
3397 if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) { in tdb_delete_hash()
3402 tdb_purge_dead(tdb, hash); in tdb_delete_hash()
3405 if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { in tdb_delete_hash()
3406 tdb_unlock(tdb, BUCKET(hash), F_WRLCK); in tdb_delete_hash()
3414 ret = tdb_rec_write(tdb, rec_ptr, &rec); in tdb_delete_hash()
3417 if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, in tdb_delete_hash()
3421 ret = tdb_do_delete(tdb, rec_ptr, &rec); in tdb_delete_hash()
3425 tdb_increment_seqnum(tdb); in tdb_delete_hash()
3428 if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) in tdb_delete_hash()
3429 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n")); in tdb_delete_hash()
3433 int tdb_delete(struct tdb_context *tdb, TDB_DATA key) in tdb_delete() argument
3435 u32 hash = tdb->hash_fn(&key); in tdb_delete()
3436 return tdb_delete_hash(tdb, key, hash); in tdb_delete()
3442 static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash, in tdb_find_dead() argument
3448 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) in tdb_find_dead()
3453 if (tdb_rec_read(tdb, rec_ptr, r) == -1) in tdb_find_dead()
3473 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) in tdb_store() argument
3481 if (tdb->read_only || tdb->traverse_read) { in tdb_store()
3482 tdb->ecode = TDB_ERR_RDONLY; in tdb_store()
3487 hash = tdb->hash_fn(&key); in tdb_store()
3488 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) in tdb_store()
3493 if (tdb_exists_hash(tdb, key, hash)) { in tdb_store()
3494 tdb->ecode = TDB_ERR_EXISTS; in tdb_store()
3499 if (tdb_update_hash(tdb, key, hash, dbuf) == 0) { in tdb_store()
3502 if (tdb->ecode == TDB_ERR_NOEXIST && in tdb_store()
3510 tdb->ecode = TDB_SUCCESS; in tdb_store()
3516 tdb_delete_hash(tdb, key, hash); in tdb_store()
3522 tdb->ecode = TDB_ERR_OOM; in tdb_store()
3530 if (tdb->max_dead_records != 0) { in tdb_store()
3538 tdb, hash, &rec, in tdb_store()
3546 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 in tdb_store()
3547 || tdb->methods->tdb_write( in tdb_store()
3548 tdb, rec_ptr + sizeof(rec), in tdb_store()
3562 if (tdb_lock(tdb, -1, F_WRLCK) == -1) { in tdb_store()
3566 if ((tdb->max_dead_records != 0) in tdb_store()
3567 && (tdb_purge_dead(tdb, hash) == -1)) { in tdb_store()
3568 tdb_unlock(tdb, -1, F_WRLCK); in tdb_store()
3573 rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec); in tdb_store()
3575 tdb_unlock(tdb, -1, F_WRLCK); in tdb_store()
3582 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) in tdb_store()
3591 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 in tdb_store()
3592 || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 in tdb_store()
3593 || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { in tdb_store()
3602 tdb_increment_seqnum(tdb); in tdb_store()
3606 tdb_unlock(tdb, BUCKET(hash), F_WRLCK); in tdb_store()
3612 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) in tdb_append() argument
3619 hash = tdb->hash_fn(&key); in tdb_append()
3620 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) in tdb_append()
3623 dbuf = tdb_fetch(tdb, key); in tdb_append()
3637 tdb->ecode = TDB_ERR_OOM; in tdb_append()
3644 ret = tdb_store(tdb, key, dbuf, 0); in tdb_append()
3647 tdb_unlock(tdb, BUCKET(hash), F_WRLCK); in tdb_append()
3657 const char *tdb_name(struct tdb_context *tdb) in tdb_name() argument
3659 return tdb->name; in tdb_name()
3667 int tdb_fd(struct tdb_context *tdb) in tdb_fd() argument
3669 return tdb->fd; in tdb_fd()
3676 tdb_log_func tdb_log_fn(struct tdb_context *tdb) in tdb_log_fn() argument
3678 return tdb->log.log_fn; in tdb_log_fn()
3692 int tdb_get_seqnum(struct tdb_context *tdb) in tdb_get_seqnum() argument
3696 if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) in tdb_get_seqnum()
3701 int tdb_hash_size(struct tdb_context *tdb) in tdb_hash_size() argument
3703 return tdb->header.hash_size; in tdb_hash_size()
3706 size_t tdb_map_size(struct tdb_context *tdb) in tdb_map_size() argument
3708 return tdb->map_size; in tdb_map_size()
3711 int tdb_get_flags(struct tdb_context *tdb) in tdb_get_flags() argument
3713 return tdb->flags; in tdb_get_flags()
3720 void tdb_enable_seqnum(struct tdb_context *tdb) in tdb_enable_seqnum() argument
3722 tdb->flags |= TDB_SEQNUM; in tdb_enable_seqnum()
3746 static int tdb_new_database(struct tdb_context *tdb, int hash_size) in tdb_new_database() argument
3759 if (tdb->flags & TDB_INTERNAL) { in tdb_new_database()
3760 tdb->map_size = size; in tdb_new_database()
3761 tdb->map_ptr = (char *)newdb; in tdb_new_database()
3762 memcpy(&tdb->header, newdb, sizeof(tdb->header)); in tdb_new_database()
3767 if (lseek(tdb->fd, 0, SEEK_SET) == -1) in tdb_new_database()
3770 if (ftruncate(tdb->fd, 0) == -1) in tdb_new_database()
3775 memcpy(&tdb->header, newdb, sizeof(tdb->header)); in tdb_new_database()
3778 if (write(tdb->fd, newdb, size) != size) { in tdb_new_database()
3822 static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) …
3823 static void null_log_fn(struct tdb_context *tdb EXT2FS_ATTR((unused)), in null_log_fn()
3835 struct tdb_context *tdb; in tdb_open_ex() local
3841 if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { in tdb_open_ex()
3846 tdb_io_init(tdb); in tdb_open_ex()
3847 tdb->fd = -1; in tdb_open_ex()
3848 tdb->name = NULL; in tdb_open_ex()
3849 tdb->map_ptr = NULL; in tdb_open_ex()
3850 tdb->flags = tdb_flags; in tdb_open_ex()
3851 tdb->open_flags = open_flags; in tdb_open_ex()
3853 tdb->log = *log_ctx; in tdb_open_ex()
3855 tdb->log.log_fn = null_log_fn; in tdb_open_ex()
3856 tdb->log.log_private = NULL; in tdb_open_ex()
3858 tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; in tdb_open_ex()
3861 tdb->page_size = sysconf(_SC_PAGESIZE); in tdb_open_ex()
3862 if (tdb->page_size <= 0) { in tdb_open_ex()
3863 tdb->page_size = 0x2000; in tdb_open_ex()
3867 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", in tdb_open_ex()
3876 tdb->read_only = 1; in tdb_open_ex()
3878 tdb->flags |= TDB_NOLOCK; in tdb_open_ex()
3879 tdb->flags &= ~TDB_CLEAR_IF_FIRST; in tdb_open_ex()
3883 if (tdb->flags & TDB_INTERNAL) { in tdb_open_ex()
3884 tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); in tdb_open_ex()
3885 tdb->flags &= ~TDB_CLEAR_IF_FIRST; in tdb_open_ex()
3886 if (tdb_new_database(tdb, hash_size) != 0) { in tdb_open_ex()
3887 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!")); in tdb_open_ex()
3893 if ((tdb->fd = open(name, open_flags, mode)) == -1) { in tdb_open_ex()
3894 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n", in tdb_open_ex()
3900 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { in tdb_open_ex()
3901 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n", in tdb_open_ex()
3908 (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) { in tdb_open_ex()
3910 if (ftruncate(tdb->fd, 0) == -1) { in tdb_open_ex()
3911 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " in tdb_open_ex()
3918 if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) in tdb_open_ex()
3919 || memcmp(tdb->header.magic_food, TDB_MAGIC_FOOD, in tdb_open_ex()
3921 || (tdb->header.version != TDB_VERSION in tdb_open_ex()
3922 && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { in tdb_open_ex()
3924 if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { in tdb_open_ex()
3928 rev = (tdb->flags & TDB_CONVERT); in tdb_open_ex()
3930 vp = (unsigned char *)&tdb->header.version; in tdb_open_ex()
3933 tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; in tdb_open_ex()
3935 tdb->flags &= ~TDB_CONVERT; in tdb_open_ex()
3937 tdb->flags |= TDB_CONVERT; in tdb_open_ex()
3938 tdb_convert(&tdb->header, sizeof(tdb->header)); in tdb_open_ex()
3940 if (fstat(tdb->fd, &st) == -1) in tdb_open_ex()
3943 if (tdb->header.rwlocks != 0) { in tdb_open_ex()
3944 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); in tdb_open_ex()
3950 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " in tdb_open_ex()
3957 if (!(tdb->name = (char *)strdup(name))) { in tdb_open_ex()
3962 tdb->map_size = st.st_size; in tdb_open_ex()
3963 tdb->device = st.st_dev; in tdb_open_ex()
3964 tdb->inode = st.st_ino; in tdb_open_ex()
3965 tdb->max_dead_records = 0; in tdb_open_ex()
3966 tdb_mmap(tdb); in tdb_open_ex()
3968 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) { in tdb_open_ex()
3969 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " in tdb_open_ex()
3983 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) in tdb_open_ex()
3988 if (tdb_transaction_recover(tdb) == -1) { in tdb_open_ex()
3996 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1) in tdb_open_ex()
3998 tdb->next = tdbs; in tdb_open_ex()
3999 tdbs = tdb; in tdb_open_ex()
4000 return tdb; in tdb_open_ex()
4005 if (!tdb) in tdb_open_ex()
4008 if (tdb->map_ptr) { in tdb_open_ex()
4009 if (tdb->flags & TDB_INTERNAL) in tdb_open_ex()
4010 SAFE_FREE(tdb->map_ptr); in tdb_open_ex()
4012 tdb_munmap(tdb); in tdb_open_ex()
4014 SAFE_FREE(tdb->name); in tdb_open_ex()
4015 if (tdb->fd != -1) in tdb_open_ex()
4016 if (close(tdb->fd) != 0) in tdb_open_ex()
4017 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); in tdb_open_ex()
4018 SAFE_FREE(tdb); in tdb_open_ex()
4028 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead) in tdb_set_max_dead() argument
4030 tdb->max_dead_records = max_dead; in tdb_set_max_dead()
4038 int tdb_close(struct tdb_context *tdb) in tdb_close() argument
4043 if (tdb->transaction) { in tdb_close()
4044 tdb_transaction_cancel(tdb); in tdb_close()
4047 if (tdb->map_ptr) { in tdb_close()
4048 if (tdb->flags & TDB_INTERNAL) in tdb_close()
4049 SAFE_FREE(tdb->map_ptr); in tdb_close()
4051 tdb_munmap(tdb); in tdb_close()
4053 SAFE_FREE(tdb->name); in tdb_close()
4054 if (tdb->fd != -1) in tdb_close()
4055 ret = close(tdb->fd); in tdb_close()
4056 SAFE_FREE(tdb->lockrecs); in tdb_close()
4060 if (*i == tdb) { in tdb_close()
4061 *i = tdb->next; in tdb_close()
4066 memset(tdb, 0, sizeof(*tdb)); in tdb_close()
4067 SAFE_FREE(tdb); in tdb_close()
4073 void tdb_set_logging_function(struct tdb_context *tdb, in tdb_set_logging_function() argument
4076 tdb->log = *log_ctx; in tdb_set_logging_function()
4079 void *tdb_get_logging_private(struct tdb_context *tdb) in tdb_get_logging_private() argument
4081 return tdb->log.log_private; in tdb_get_logging_private()
4086 int tdb_reopen(struct tdb_context *tdb) in tdb_reopen() argument
4090 if (tdb->flags & TDB_INTERNAL) { in tdb_reopen()
4094 if (tdb->num_locks != 0 || tdb->global_lock.count) { in tdb_reopen()
4095 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); in tdb_reopen()
4099 if (tdb->transaction != 0) { in tdb_reopen()
4100 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n")); in tdb_reopen()
4104 if (tdb_munmap(tdb) != 0) { in tdb_reopen()
4105 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); in tdb_reopen()
4108 if (close(tdb->fd) != 0) in tdb_reopen()
4109 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n")); in tdb_reopen()
4110 tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); in tdb_reopen()
4111 if (tdb->fd == -1) { in tdb_reopen()
4112 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); in tdb_reopen()
4115 if ((tdb->flags & TDB_CLEAR_IF_FIRST) && in tdb_reopen()
4116 (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) { in tdb_reopen()
4117 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); in tdb_reopen()
4120 if (fstat(tdb->fd, &st) != 0) { in tdb_reopen()
4121 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); in tdb_reopen()
4124 if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { in tdb_reopen()
4125 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); in tdb_reopen()
4128 tdb_mmap(tdb); in tdb_reopen()
4133 tdb_close(tdb); in tdb_reopen()
4140 struct tdb_context *tdb; in tdb_reopen_all() local
4142 for (tdb=tdbs; tdb; tdb = tdb->next) { in tdb_reopen_all()
4156 tdb->flags &= ~TDB_CLEAR_IF_FIRST; in tdb_reopen_all()
4159 if (tdb_reopen(tdb) != 0) in tdb_reopen_all()
4169 int tdb_flush(struct tdb_context *tdb) in tdb_flush() argument
4171 if (tdb->fd != -1) in tdb_flush()
4172 return fsync(tdb->fd); in tdb_flush()