The branch, master has been updated via a7fdd4f tdb: Slightly simplify transaction_write via fcb345f tdb: Make tdb_release_transaction_locks use tdb_allrecord_unlock via 5929e38 tdb: Don't segfault if tdb_open_ex for check failed via 3534e4e tdb: Factor out the retry loop from tdb_allrecord_upgrade via 1f93f08 tdb: Simplify fcntl_lock() a bit via 542400a tdb: Use tdb_null in freelistcheck via 68559b7 tdb: Enhance lock tracking a bit from 31e4d6d s3:smbd: preserve file type mode bits in file_set_dosmode()
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit a7fdd4f7c2e64eedf12cb46c3435edbec772a4ab Author: Volker Lendecke <v...@samba.org> Date: Tue Feb 19 12:23:36 2013 +0100 tdb: Slightly simplify transaction_write realloc(NULL, ...) is equivalent to malloc. We are already using this realloc property for tdb->lockrecs. It should not make any difference in speed, it just makes for a little simpler code. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Tue Feb 19 17:30:13 CET 2013 on sn-devel-104 commit fcb345f5d6be9659a0f8a5afe62a937010a33d5c Author: Volker Lendecke <v...@samba.org> Date: Sat Feb 16 22:08:52 2013 +0100 tdb: Make tdb_release_transaction_locks use tdb_allrecord_unlock The transaction code uses tdb_alrecord_lock/upgrade, so it should also use the tdb_allrecord_unlock function just for symmetry reasons Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 5929e38b6cdbd4f9721293a19f079ceae1af76b0 Author: Volker Lendecke <v...@samba.org> Date: Sat Feb 16 22:07:41 2013 +0100 tdb: Don't segfault if tdb_open_ex for check failed Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 3534e4e8d5bebfaaaef5886dcea219a7e4047fc7 Author: Volker Lendecke <v...@samba.org> Date: Sat Feb 16 16:49:56 2013 +0100 tdb: Factor out the retry loop from tdb_allrecord_upgrade For the mutex code we will have to lock the hashchain and the record lock area independently. So we will have to call the loop twice. And, it's a small refactoring for the better anyway I think. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 1f93f0836484ccc1abe335f5bd2cfd35df0b7631 Author: Volker Lendecke <v...@samba.org> Date: Sat Feb 16 14:17:57 2013 +0100 tdb: Simplify fcntl_lock() a bit All arguments but the cmd are the same. To me this looks a bit better and saves some bytes in the object code. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 542400a966039178effd6c8da932ed3a8d749131 Author: Volker Lendecke <v...@samba.org> Date: Sat Feb 16 13:39:28 2013 +0100 tdb: Use tdb_null in freelistcheck Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 68559b787e7c9a83e055493bde638ec02e1097d1 Author: Volker Lendecke <v...@samba.org> Date: Thu Feb 14 16:10:31 2013 +0100 tdb: Enhance lock tracking a bit lock-tracking.c mirrors the in-kernel fcntl structures to detect unexpected use of fcntl calls. During my mutex work I changed our fcntl use so that we unlock the allrecord_lock in two pieces: The range covering the hash locks and the range covering the data area for the individual traverse record locks. Splitting locks is not covered by lock-tracking.c. This patch extends lock-tracking.c with this little piece. It's still far from complete to track the full range of fcntl semantics. It is not strictly needed right now, but it does not hurt either. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/tdb/common/freelistcheck.c | 5 +-- lib/tdb/common/lock.c | 69 +++++++++++++++++++++++++-------------- lib/tdb/common/transaction.c | 10 +----- lib/tdb/test/lock-tracking.c | 11 ++++++ lib/tdb/tools/tdbtorture.c | 1 + 5 files changed, 60 insertions(+), 36 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/tdb/common/freelistcheck.c b/lib/tdb/common/freelistcheck.c index 3be7cfd..c6bfeaa 100644 --- a/lib/tdb/common/freelistcheck.c +++ b/lib/tdb/common/freelistcheck.c @@ -35,12 +35,11 @@ static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr) { - TDB_DATA key, data; + TDB_DATA key; - memset(&data, '\0', sizeof(data)); key.dptr = (unsigned char *)&rec_ptr; key.dsize = sizeof(rec_ptr); - return tdb_store(mem_tdb, key, data, TDB_INSERT); + return tdb_store(mem_tdb, key, tdb_null, TDB_INSERT); } _PUBLIC_ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) diff --git a/lib/tdb/common/lock.c b/lib/tdb/common/lock.c index dadc69e..b59dfbc 100644 --- a/lib/tdb/common/lock.c +++ b/lib/tdb/common/lock.c @@ -36,6 +36,7 @@ static int fcntl_lock(struct tdb_context *tdb, int rw, off_t off, off_t len, bool waitflag) { struct flock fl; + int cmd; fl.l_type = rw; fl.l_whence = SEEK_SET; @@ -43,10 +44,9 @@ static int fcntl_lock(struct tdb_context *tdb, fl.l_len = len; fl.l_pid = 0; - if (waitflag) - return fcntl(tdb->fd, F_SETLKW, &fl); - else - return fcntl(tdb->fd, F_SETLK, &fl); + cmd = waitflag ? F_SETLKW : F_SETLK; + + return fcntl(tdb->fd, cmd, &fl); } static int fcntl_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len) @@ -198,14 +198,42 @@ int tdb_brunlock(struct tdb_context *tdb, } /* - upgrade a read lock to a write lock. This needs to be handled in a - special way as some OSes (such as solaris) have too conservative - deadlock detection and claim a deadlock when progress can be - made. For those OSes we may loop for a while. + * Do a tdb_brlock in a loop. Some OSes (such as solaris) have too + * conservative deadlock detection and claim a deadlock when progress can be + * made. For those OSes we may loop for a while. + */ + +static int tdb_brlock_retry(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len, + enum tdb_lock_flags flags) +{ + int count = 1000; + + while (count--) { + struct timeval tv; + int ret; + + ret = tdb_brlock(tdb, rw_type, offset, len, flags); + if (ret == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + return -1; +} + +/* + upgrade a read lock to a write lock. */ int tdb_allrecord_upgrade(struct tdb_context *tdb) { - int count = 1000; + int ret; if (tdb->allrecord_lock.count != 1) { TDB_LOG((tdb, TDB_DEBUG_ERROR, @@ -220,21 +248,12 @@ int tdb_allrecord_upgrade(struct tdb_context *tdb) return -1; } - while (count--) { - struct timeval tv; - if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, - TDB_LOCK_WAIT|TDB_LOCK_PROBE) == 0) { - tdb->allrecord_lock.ltype = F_WRLCK; - tdb->allrecord_lock.off = 0; - return 0; - } - if (errno != EDEADLK) { - break; - } - /* sleep for as short a time as we can - more portable than usleep() */ - tv.tv_sec = 0; - tv.tv_usec = 1; - select(0, NULL, NULL, NULL, &tv); + ret = tdb_brlock_retry(tdb, F_WRLCK, FREELIST_TOP, 0, + TDB_LOCK_WAIT|TDB_LOCK_PROBE); + if (ret == 0) { + tdb->allrecord_lock.ltype = F_WRLCK; + tdb->allrecord_lock.off = 0; + return 0; } TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_allrecord_upgrade failed\n")); return -1; @@ -860,7 +879,7 @@ void tdb_release_transaction_locks(struct tdb_context *tdb) unsigned int i, active = 0; if (tdb->allrecord_lock.count != 0) { - tdb_brunlock(tdb, tdb->allrecord_lock.ltype, FREELIST_TOP, 0); + tdb_allrecord_unlock(tdb, tdb->allrecord_lock.ltype, false); tdb->allrecord_lock.count = 0; } diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c index 42289fd..a2498ec 100644 --- a/lib/tdb/common/transaction.c +++ b/lib/tdb/common/transaction.c @@ -249,14 +249,8 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off, if (tdb->transaction->num_blocks <= blk) { uint8_t **new_blocks; /* expand the blocks array */ - if (tdb->transaction->blocks == NULL) { - new_blocks = (uint8_t **)malloc( - (blk+1)*sizeof(uint8_t *)); - } else { - new_blocks = (uint8_t **)realloc( - tdb->transaction->blocks, - (blk+1)*sizeof(uint8_t *)); - } + new_blocks = (uint8_t **)realloc(tdb->transaction->blocks, + (blk+1)*sizeof(uint8_t *)); if (new_blocks == NULL) { tdb->ecode = TDB_ERR_OOM; goto fail; diff --git a/lib/tdb/test/lock-tracking.c b/lib/tdb/test/lock-tracking.c index 90a07f8..b2f092c 100644 --- a/lib/tdb/test/lock-tracking.c +++ b/lib/tdb/test/lock-tracking.c @@ -65,6 +65,17 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) } break; } + if (((*l)->off == fl->l_start) + && ((*l)->len == 0) + && (ret == 0)) { + /* + * Remove a piece from the start of the + * allrecord_lock + */ + old = *l; + (*l)->off += fl->l_len; + break; + } } if (!old && !suppress_lockcheck) { diag("Unknown unlock %u@%u - %i", diff --git a/lib/tdb/tools/tdbtorture.c b/lib/tdb/tools/tdbtorture.c index 04bbb7d..760ad59 100644 --- a/lib/tdb/tools/tdbtorture.c +++ b/lib/tdb/tools/tdbtorture.c @@ -439,6 +439,7 @@ done: O_RDWR, 0, &log_ctx, NULL); if (!db) { fatal("db open failed\n"); + exit(1); } if (tdb_check(db, NULL, NULL) == -1) { printf("db check failed\n"); -- Samba Shared Repository