From 3665777a5bc7ffa92f64ba17daf4cc66c3607198 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Oct 2002 22:53:18 +0000 Subject: Add a timeout to tdb_lock_bystring(). Ensure we never have more than MAX_PRINT_JOBS in a queue. Jeremy. (This used to be commit 9fe3c0b90d4bff2217e3cb5a34b4683ca314c06e) --- source3/groupdb/mapping.c | 2 +- source3/include/local.h | 3 ++ source3/include/printing.h | 2 +- source3/lib/account_pol.c | 2 +- source3/param/loadparm.c | 14 ++++++++- source3/passdb/secrets.c | 60 +++++++------------------------------- source3/printing/nt_printing.c | 4 +-- source3/printing/printing.c | 14 ++++----- source3/rpc_server/srv_srvsvc_nt.c | 2 +- source3/tdb/tdb.c | 4 +++ source3/tdb/tdb.h | 2 +- source3/tdb/tdbutil.c | 49 +++++++++++++++++++++++++++---- 12 files changed, 89 insertions(+), 69 deletions(-) diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 5641431246..0f05316949 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -223,7 +223,7 @@ static BOOL init_group_mapping(void) local_pid = sys_getpid(); /* handle a Samba upgrade */ - tdb_lock_bystring(tdb, vstring); + tdb_lock_bystring(tdb, vstring, 0); /* Cope with byte-reversed older versions of the db. */ vers_id = tdb_fetch_int32(tdb, vstring); diff --git a/source3/include/local.h b/source3/include/local.h index 5096e13fc3..2be9c1e101 100644 --- a/source3/include/local.h +++ b/source3/include/local.h @@ -210,4 +210,7 @@ /* this enables the "rabbit pellet" fix for SMBwritebraw */ #define RABBIT_PELLET_FIX 1 +/* Max number of jobs per print queue. */ +#define PRINT_MAX_JOBID 10000 + #endif diff --git a/source3/include/printing.h b/source3/include/printing.h index 9774a6acd9..38ff7eac36 100644 --- a/source3/include/printing.h +++ b/source3/include/printing.h @@ -65,7 +65,7 @@ extern struct printif generic_printif; extern struct printif cups_printif; #endif /* HAVE_CUPS */ -#define PRINT_MAX_JOBID 10000 +/* PRINT_MAX_JOBID is now defined in local.h */ #define UNIX_JOB_START PRINT_MAX_JOBID #define NEXT_JOBID(j) ((j+1) % PRINT_MAX_JOBID > 0 ? (j+1) % PRINT_MAX_JOBID : 1) diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c index b5f205c508..6f51c916d7 100644 --- a/source3/lib/account_pol.c +++ b/source3/lib/account_pol.c @@ -45,7 +45,7 @@ BOOL init_account_policy(void) local_pid = sys_getpid(); /* handle a Samba upgrade */ - tdb_lock_bystring(tdb, vstring); + tdb_lock_bystring(tdb, vstring,0); if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); tdb_store_uint32(tdb, vstring, DATABASE_VERSION); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 18cba172c0..ba0866883f 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -1798,7 +1798,6 @@ FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode) FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections) FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase) FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace) -FN_LOCAL_INTEGER(lp_maxprintjobs, iMaxPrintJobs) FN_LOCAL_INTEGER(lp_printing, iPrinting) FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit) FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy) @@ -4070,3 +4069,16 @@ const char *get_called_name(void) return local_machine; } + +/******************************************************************* + Return the max print jobs per queue. +********************************************************************/ + +int lp_maxprintjobs(int snum) +{ + int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs; + if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID) + maxjobs = PRINT_MAX_JOBID - 1; + + return maxjobs; +} diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 4b2c76d8b0..ad56fcedd1 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -215,7 +215,7 @@ BOOL secrets_lock_trust_account_password(char *domain, BOOL dolock) return False; if (dolock) - return (tdb_lock_bystring(tdb, trust_keystr(domain)) == 0); + return (tdb_lock_bystring(tdb, trust_keystr(domain),0) == 0); else tdb_unlock_bystring(tdb, trust_keystr(domain)); return True; @@ -579,69 +579,31 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num return status; } -static SIG_ATOMIC_T gotalarm; +/******************************************************************************* + Lock the secrets tdb based on a string - this is used as a primitive form of mutex + between smbd instances. +*******************************************************************************/ -/*************************************************************** - Signal function to tell us we timed out. -****************************************************************/ - -static void gotalarm_sig(void) -{ - gotalarm = 1; -} - -/* - lock the secrets tdb based on a string - this is used as a primitive form of mutex - between smbd instances. -*/ BOOL secrets_named_mutex(const char *name, unsigned int timeout) { - TDB_DATA key; int ret; if (!message_init()) return False; - key.dptr = (char *)name; - key.dsize = strlen(name)+1; - - /* Allow tdb_chainlock to be interrupted by an alarm. */ - gotalarm = 0; - tdb_set_lock_alarm(&gotalarm); - - if (timeout) { - CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - alarm(timeout); - } - - ret = tdb_chainlock(tdb, key); - - /* Prevent tdb_chainlock from being interrupted by an alarm. */ - tdb_set_lock_alarm(NULL); - - if (timeout) { - alarm(0); - CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); - if (gotalarm) - return False; - } - + ret = tdb_lock_bystring(tdb, name, timeout); if (ret == 0) DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name )); return (ret == 0); } -/* - unlock a named mutex -*/ +/******************************************************************************* + Unlock a named mutex. +*******************************************************************************/ + void secrets_named_mutex_release(char *name) { - TDB_DATA key; - - key.dptr = name; - key.dsize = strlen(name)+1; - - tdb_chainunlock(tdb, key); + tdb_unlock_bystring(tdb, name); DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name )); } diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 58eba9d87e..fcb493a614 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -287,7 +287,7 @@ BOOL nt_printing_init(void) local_pid = sys_getpid(); /* handle a Samba upgrade */ - tdb_lock_bystring(tdb_drivers, vstring); + tdb_lock_bystring(tdb_drivers, vstring, 0); { int32 vers_id; @@ -362,7 +362,7 @@ uint32 update_c_setprinter(BOOL initialize) int32 c_setprinter; int32 printer_count = 0; - tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); + tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0); /* Traverse the tdb, counting the printers */ tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count); diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 6474c92c69..91851a37f8 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -257,7 +257,7 @@ BOOL print_backend_init(void) pdb = get_print_db_byname(lp_const_servicename(snum)); if (!pdb) continue; - if (tdb_lock_bystring(pdb->tdb, sversion) == -1) { + if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) { DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) )); return False; } @@ -883,7 +883,8 @@ static void print_queue_update(int snum) /* Lock the queue for the database update */ slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name); - if (tdb_lock_bystring(pdb->tdb, keystr) == -1) { + /* Only wait 10 seconds for this. */ + if (tdb_lock_bystring(pdb->tdb, keystr, 10) == -1) { DEBUG(0,("print_queue_update: Failed to lock printer %s database\n", printer_name)); release_print_db(pdb); return; @@ -1380,9 +1381,8 @@ static int get_queue_status(int snum, print_status_struct *status) data = tdb_fetch(pdb->tdb, key); release_print_db(pdb); if (data.dptr) { - if (data.dsize == sizeof(print_status_struct)) { + if (data.dsize == sizeof(print_status_struct)) memcpy(status, data.dptr, sizeof(print_status_struct)); - } SAFE_FREE(data.dptr); } return status->qcount; @@ -1465,7 +1465,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE } /* Insure the maximum queue size is not violated */ - if (lp_maxprintjobs(snum) && (njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) { + if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) { DEBUG(3, ("print_job_start: number of jobs (%d) larger than max printjobs per queue (%d).\n", njobs, lp_maxprintjobs(snum) )); release_print_db(pdb); @@ -1473,8 +1473,8 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE return (uint32)-1; } - /* Lock the database */ - if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob") == -1) { + /* Lock the database - only wait 20 seconds. */ + if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) { DEBUG(0,("print_job_start: failed to lock printing database %s\n", printername )); release_print_db(pdb); return (uint32)-1; diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 69945b50b8..ecde51df9f 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -145,7 +145,7 @@ BOOL share_info_db_init(void) local_pid = sys_getpid(); /* handle a Samba upgrade */ - tdb_lock_bystring(share_tdb, vstring); + tdb_lock_bystring(share_tdb, vstring, 0); /* Cope with byte-reversed older versions of the db. */ vers_id = tdb_fetch_int32(share_tdb, vstring); diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index 4143ac7781..c57d23cb6f 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -208,6 +208,10 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", tdb->fd, offset, rw_type, lck_type)); } + /* Was it an alarm timeout ? */ + if (errno == EINTR && palarm_fired && *palarm_fired) + return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); + /* Otherwise - generic lock error. */ /* errno set by fcntl */ return TDB_ERRCODE(TDB_ERR_LOCK, -1); } diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h index 42b88aeb16..dda89d0355 100644 --- a/source3/tdb/tdb.h +++ b/source3/tdb/tdb.h @@ -44,7 +44,7 @@ extern "C" { /* error codes */ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, - TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST, TDB_ERR_NOLOCK }; + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT }; #ifndef u32 #define u32 unsigned diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index 1a3a8bb9a5..e7650033b8 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -24,18 +24,57 @@ /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/**************************************************************************** + Lock a chain with timeout (in seconds). +****************************************************************************/ + +int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +{ + /* Allow tdb_chainlock to be interrupted by an alarm. */ + int ret; + gotalarm = 0; + tdb_set_lock_alarm(&gotalarm); + + if (timeout) { + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(timeout); + } + + ret = tdb_chainlock(tdb, key); + + if (timeout) { + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + if (gotalarm) + return -1; + } + + return ret; +} + /**************************************************************************** - Lock a chain by string. + Lock a chain by string. Return -1 if timeout or lock failed. ****************************************************************************/ -int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval) +int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval, unsigned int timeout) { TDB_DATA key; key.dptr = keyval; key.dsize = strlen(keyval)+1; - return tdb_chainlock(tdb, key); + return tdb_chainlock_with_timeout(tdb, key, timeout); } /**************************************************************************** @@ -230,7 +269,7 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, char *keystr, int32 *oldval, int int32 val; int32 ret = -1; - if (tdb_lock_bystring(tdb, keystr) == -1) + if (tdb_lock_bystring(tdb, keystr,0) == -1) return -1; if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { @@ -271,7 +310,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, char *keystr, uint32 *oldval, ui uint32 val; BOOL ret = False; - if (tdb_lock_bystring(tdb, keystr) == -1) + if (tdb_lock_bystring(tdb, keystr,0) == -1) return False; if (!tdb_fetch_uint32(tdb, keystr, &val)) { -- cgit