Created attachment 15815 [details] OmniOS Robust Mutex attr initialization patch Samba using robust mutexes get a runtime error "Device busy" unless we initialize the mutexattr variables before using them. tdb(/var/samba/lock/gencache.tdb): tdb_open_ex: tdb_mutex_init failed for /var/samba/lock/gencache.tdb: Device busy tdb(/var/samba/lock/gencache.tdb): tdb_open_ex: tdb_mutex_init failed for /var/samba/lock/gencache.tdb: Device busy tdb(/var/samba/lock/gencache.tdb): tdb_open_ex: tdb_mutex_init failed for /var/samba/lock/gencache.tdb: Device busy This is probably an OmniOS bug since there is a known Illumos bug about this (and fixed there) but it's an easy fix so... The attached patch fixes this problem.
Created attachment 16555 [details] Handle EBUSY from pthread_mutex_init & mutexattr_t initialization A patch that adds code to handle the case where pthread_mutex_init returns EBUSY - indicating that we are trying to re-init an already initialized robust mutex. This doesn't seem to happen on Linux but happens on some other OS:es (atleast OmniOS) other Posix-compliant Pthread implementations that support robust mutexes... There are conflicting information in Linux system man pages about pthread_mutex_init regarding return values, (man 3 pthread_mutex_init vs man 3posix pthread_mutex_init) https://linux.die.net/man/3/pthread_mutex_init It seems the TDB tdb_open_ex code calls tdb_new_database which calls tdb_mutex_init, and then tdb_open_ex later on again calls tdb_mutex_init which causes the code to fail with EBUSY. The "pthread_mutexattr_t ma = { 0 };" is to fix a bug in Illumos causing another error when initializing robust mutexes. Might be wrapped in an "#ifdef __sun__" check, or use memset(&ma, 0, sizeof(ma));.
Created attachment 16556 [details] Patch to fix TDB header/mutex file write sequence This patch changes how TDB files are initialized (the header+mutex area part). The original code seems to write out a TDB header, then if Mutexes are enabled, will overwrite that with robust shared mutexes via tdb_mutex_init which mmaps the same region ant pthread_mutex_init()s a bunch of mutexes, and then appends the TDB header again... The new code skips the first overwritten tdb header if mutexes are enabled. This most almost always works - but since robust mutexes are used the pthread_mutex_init() code will have to read the data stored and see if it is a valid mutex or not. If by some chance the tdb header would contain the same byte sequence the mutex implementation looks for then things will break. Better to use zeroed out memory I think...