1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

Fix the "too many fcntl locks" scalability problem raised by tridge.

I've now tested this in daemon mode and also on xinetd and I'm pretty
sure it's working.
Jeremy.
(This used to be commit 14dee03801)
This commit is contained in:
Jeremy Allison 2004-02-19 01:55:24 +00:00
parent 5e39e9f313
commit 8eec62ebfb
4 changed files with 62 additions and 35 deletions

View File

@ -405,10 +405,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
done correctly in the process. */
reset_globals_after_fork();
/* tdb needs special fork handling */
/* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */
if (tdb_reopen_all() == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
return False;
smb_panic("tdb_reopen_all failed.");
}
return True;
@ -809,9 +809,27 @@ void build_options(BOOL screen);
if (is_daemon)
pidfile_create("smbd");
/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
if (!message_init())
exit(1);
if (!session_init())
exit(1);
if (conn_tdb_ctx() == NULL)
exit(1);
if (!locking_init(0))
exit(1);
if (!share_info_db_init())
exit(1);
namecache_enable();
if (!init_registry())
exit(1);
if (!print_backend_init())
exit(1);
@ -832,17 +850,6 @@ void build_options(BOOL screen);
* everything after this point is run after the fork()
*/
namecache_enable();
if (!locking_init(0))
exit(1);
if (!share_info_db_init())
exit(1);
if (!init_registry())
exit(1);
/* Initialise the password backed before the global_sam_sid
to ensure that we fetch from ldap before we make a domain sid up */
@ -891,4 +898,3 @@ void build_options(BOOL screen);
exit_server("normal exit");
return(0);
}

View File

@ -28,6 +28,22 @@
#include "includes.h"
static TDB_CONTEXT *tdb;
BOOL session_init(void)
{
if (tdb)
return True;
tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
O_RDWR | O_CREAT, 0644, smbd_tdb_log);
if (!tdb) {
DEBUG(1,("session_init: failed to open sessionid tdb\n"));
return False;
}
return True;
}
/* called when a session is created */
BOOL session_claim(user_struct *vuser)
{
@ -52,14 +68,8 @@ BOOL session_claim(user_struct *vuser)
return True;
}
if (!tdb) {
tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
O_RDWR | O_CREAT, 0644, smbd_tdb_log);
if (!tdb) {
DEBUG(1,("session_claim: failed to open sessionid tdb\n"));
return False;
}
}
if (!session_init())
return False;
ZERO_STRUCT(sessionid);
@ -190,7 +200,7 @@ void session_yield(user_struct *vuser)
static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state)
{
if (!tdb) {
if (!session_init()) {
DEBUG(3, ("No tdb opened\n"));
return False;
}
@ -238,4 +248,3 @@ int list_sessions(struct sessionid **session_list)
*session_list = sesslist.sessions;
return sesslist.count;
}

View File

@ -1705,7 +1705,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
{
TDB_CONTEXT *tdb;
struct stat st;
int rev = 0, locked;
int rev = 0, locked = 0;
unsigned char *vp;
u32 vertest;
@ -1763,8 +1763,8 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
}
/* we need to zero database if we are the only one with it open */
if ((locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))
&& (tdb_flags & TDB_CLEAR_IF_FIRST)) {
if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
(locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) {
open_flags |= O_CREAT;
if (ftruncate(tdb->fd, 0) == -1) {
TDB_LOG((tdb, 0, "tdb_open_ex: "
@ -1837,10 +1837,19 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
name, strerror(errno)));
goto fail;
}
}
/* leave this lock in place to indicate it's in use */
if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
goto fail;
/* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
we didn't get the initial exclusive lock as we need to let all other
users know we're using it. */
if (tdb_flags & TDB_CLEAR_IF_FIRST) {
/* leave this lock in place to indicate it's in use */
if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
goto fail;
}
internal:
/* Internal (memory-only) databases skip all the code above to
@ -2018,12 +2027,14 @@ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , cons
}
/* reopen a tdb - this is used after a fork to ensure that we have an independent
/* reopen a tdb - this can be used after a fork to ensure that we have an independent
seek pointer from our parent and to re-establish locks */
int tdb_reopen(TDB_CONTEXT *tdb)
{
struct stat st;
if (tdb->flags & TDB_INTERNAL)
return 0; /* Nothing to do. */
if (tdb_munmap(tdb) != 0) {
TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
goto fail;
@ -2044,7 +2055,7 @@ int tdb_reopen(TDB_CONTEXT *tdb)
goto fail;
}
tdb_mmap(tdb);
if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) {
if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) {
TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n"));
goto fail;
}
@ -2062,7 +2073,10 @@ int tdb_reopen_all(void)
TDB_CONTEXT *tdb;
for (tdb=tdbs; tdb; tdb = tdb->next) {
if (tdb_reopen(tdb) != 0) return -1;
/* Ensure no clear-if-first. */
tdb->flags &= ~TDB_CLEAR_IF_FIRST;
if (tdb_reopen(tdb) != 0)
return -1;
}
return 0;

View File

@ -826,5 +826,3 @@ void tdb_search_list_free(TDB_LIST_NODE* node)
node = next_node;
};
}