The Samba-Bugzilla – Attachment 827 Details for
Bug 2107
smbd processes take more and more memory on print server
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch for fix memory bloating caused by print_queue_update() messages
printing-3-0-9.patch (text/plain), 18.33 KB, created by
Gerald (Jerry) Carter (dead mail address)
on 2004-12-07 19:53:13 UTC
(
hide
)
Description:
patch for fix memory bloating caused by print_queue_update() messages
Filename:
MIME Type:
Creator:
Gerald (Jerry) Carter (dead mail address)
Created:
2004-12-07 19:53:13 UTC
Size:
18.33 KB
patch
obsolete
>Only in samba-3.0.9/source: build-samba >Only in samba-3.0.9/source/include: build_env.h >Only in samba-3.0.9/source/include: stamp-h >diff -ruBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.9-orig/source/param/loadparm.c samba-3.0.9/source/param/loadparm.c >--- samba-3.0.9-orig/source/param/loadparm.c 2004-11-15 21:03:16.000000000 -0600 >+++ samba-3.0.9/source/param/loadparm.c 2004-12-07 18:09:53.773049300 -0600 >@@ -1375,7 +1375,7 @@ > /* Discovered by 2 days of pain by Don McCall @ HP :-). */ > Globals.max_xmit = 0x4104; > Globals.max_mux = 50; /* This is *needed* for profile support. */ >- Globals.lpqcachetime = 10; >+ Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */ > Globals.bDisableSpoolss = False; > Globals.iMaxSmbdProcesses = 0;/* no limit specified */ > Globals.pwordlevel = 0; >diff -ruBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.9-orig/source/printing/printing.c samba-3.0.9/source/printing/printing.c >--- samba-3.0.9-orig/source/printing/printing.c 2004-11-15 21:03:15.000000000 -0600 >+++ samba-3.0.9/source/printing/printing.c 2004-12-07 19:11:28.550472369 -0600 >@@ -43,10 +43,12 @@ > jobids are assigned when a job starts spooling. > */ > >-/*************************************************************************** >- Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32 >- bit RPC jobids.... JRA. >-***************************************************************************/ >+struct print_queue_update_context { >+ char* sharename; >+ enum printing_types printing_type; >+ char* lpqcommand; >+}; >+ > > static TDB_CONTEXT *rap_tdb; > static uint16 next_rap_jobid; >@@ -55,6 +57,11 @@ > uint32 jobid; > }; > >+/*************************************************************************** >+ Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32 >+ bit RPC jobids.... JRA. >+***************************************************************************/ >+ > uint16 pjobid_to_rap(const char* sharename, uint32 jobid) > { > uint16 rap_jobid; >@@ -837,7 +844,7 @@ > in the tdb. > ****************************************************************************/ > >-static void set_updating_pid(const fstring sharename, BOOL delete) >+static void set_updating_pid(const fstring sharename, BOOL updating) > { > fstring keystr; > TDB_DATA key; >@@ -854,7 +861,11 @@ > key.dptr = keystr; > key.dsize = strlen(keystr); > >- if (delete) { >+ DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n", >+ updating ? "" : "not ", >+ sharename )); >+ >+ if ( !updating ) { > tdb_delete(pdb->tdb, key); > release_print_db(pdb); > return; >@@ -978,11 +989,69 @@ > } > } > >-struct print_queue_update_context { >- fstring sharename; >- enum printing_types printing_type; >- pstring lpqcommand; >-}; >+/**************************************************************************** >+ Check if the print queue has been updated recently enough. >+****************************************************************************/ >+ >+static BOOL print_cache_expired(const char *sharename, BOOL check_pending) >+{ >+ fstring key; >+ time_t last_qscan_time, time_now = time(NULL); >+ struct tdb_print_db *pdb = get_print_db_byname(sharename); >+ BOOL result = False; >+ >+ if (!pdb) >+ return False; >+ >+ snprintf(key, sizeof(key), "CACHE/%s", sharename); >+ last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key); >+ >+ /* >+ * Invalidate the queue for 3 reasons. >+ * (1). last queue scan time == -1. >+ * (2). Current time - last queue scan time > allowed cache time. >+ * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default). >+ * This last test picks up machines for which the clock has been moved >+ * forward, an lpq scan done and then the clock moved back. Otherwise >+ * that last lpq scan would stay around for a loooong loooong time... :-). JRA. >+ */ >+ >+ if (last_qscan_time == ((time_t)-1) >+ || (time_now - last_qscan_time) >= lp_lpqcachetime() >+ || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) >+ { >+ time_t msg_pending_time; >+ >+ DEBUG(4, ("print_cache_expired: cache expired for queue %s " >+ "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n", >+ sharename, (int)last_qscan_time, (int)time_now, >+ (int)lp_lpqcachetime() )); >+ >+ /* check if another smbd has already sent a message to update the >+ queue. Give the pending message one minute to clear and >+ then send another message anyways. Make sure to check for >+ clocks that have been run forward and then back again. */ >+ >+ snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename); >+ >+ if ( check_pending >+ && tdb_fetch_uint32( pdb->tdb, key, (uint32*)&msg_pending_time ) >+ && msg_pending_time > 0 >+ && msg_pending_time <= time_now >+ && (time_now - msg_pending_time) < 60 ) >+ { >+ DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n", >+ sharename)); >+ goto done; >+ } >+ >+ result = True; >+ } >+ >+done: >+ release_print_db(pdb); >+ return result; >+} > > /**************************************************************************** > main work for updating the lpq cahe for a printer queue >@@ -1003,6 +1072,14 @@ > fstring keystr, cachestr; > struct tdb_print_db *pdb = get_print_db_byname(sharename); > >+ DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n", >+ sharename, current_printif->type, lpq_command)); >+ >+ if ( !print_cache_expired(sharename, False) ) { >+ DEBUG(5,("print_queue_update_internal: print cache for %s is still ok\n", sharename)); >+ return; >+ } >+ > /* > * Update the cache time FIRST ! Stops others even > * attempting to get the lock and doing this >@@ -1019,8 +1096,8 @@ > current_printif->type, > lpq_command, &queue, &status); > >- DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ? >- "s" : "", sharename)); >+ DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n", >+ qcount, (qcount != 1) ? "s" : "", sharename)); > > /* Sort the queue by submission time otherwise they are displayed > in hash order. */ >@@ -1084,14 +1161,14 @@ > > SAFE_FREE(tstruct.queue); > >- DEBUG(10,("print_queue_update: printer %s INFO/total_jobs = %d\n", >+ DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n", > sharename, tstruct.total_jobs )); > > tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs); > > get_queue_status(sharename, &old_status); > if (old_status.qcount != qcount) >- DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n", >+ DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n", > old_status.qcount, qcount, sharename)); > > /* store the new queue status structure */ >@@ -1112,6 +1189,20 @@ > slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename); > tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL)); > >+ /* clear the msg pending record for this queue */ >+ >+ snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename); >+ >+ if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) { >+ /* log a message but continue on */ >+ >+ DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n", >+ sharename)); >+ } >+ >+ release_print_db( pdb ); >+ >+ return; > } > > /**************************************************************************** >@@ -1128,6 +1219,8 @@ > struct printif *current_printif = get_printer_fns( snum ); > > fstrcpy(sharename, lp_const_servicename(snum)); >+ >+ DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename)); > pdb = get_print_db_byname(sharename); > if (!pdb) > return; >@@ -1147,7 +1240,7 @@ > slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename); > /* 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", sharename)); >+ DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename)); > release_print_db(pdb); > return; > } >@@ -1172,7 +1265,7 @@ > */ > > /* Tell others we're doing the update. */ >- set_updating_pid(sharename, False); >+ set_updating_pid(sharename, True); > > /* > * Allow others to enter and notice we're doing >@@ -1192,26 +1285,38 @@ > print_queue_update_internal( sharename, current_printif, lpq_command ); > > /* Delete our pid from the db. */ >- set_updating_pid(sharename, True); >+ set_updating_pid(sharename, False); > release_print_db(pdb); > } > > /**************************************************************************** > this is the receive function of the background lpq updater > ****************************************************************************/ >-static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t len) >+static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msglen) > { >- struct print_queue_update_context *ctx; >+ struct print_queue_update_context ctx; >+ fstring sharename; >+ pstring lpqcommand; >+ size_t len; > >- if (len != sizeof(struct print_queue_update_context)) { >- DEBUG(1, ("Got invalid print queue update message\n")); >+ len = tdb_unpack( buf, msglen, "fdP", >+ sharename, >+ &ctx.printing_type, >+ lpqcommand ); >+ >+ if ( len == -1 ) { >+ DEBUG(0,("print_queue_receive: Got invalid print queue update message\n")); > return; > } > >- ctx = (struct print_queue_update_context*)buf; >- print_queue_update_internal(ctx->sharename, >- get_printer_fns_from_type(ctx->printing_type), >- ctx->lpqcommand ); >+ ctx.sharename = sharename; >+ ctx.lpqcommand = lpqcommand; >+ >+ print_queue_update_internal(ctx.sharename, >+ get_printer_fns_from_type(ctx.printing_type), >+ ctx.lpqcommand ); >+ >+ return; > } > > static pid_t background_lpq_updater_pid = -1; >@@ -1277,27 +1382,84 @@ > static void print_queue_update(int snum) > { > struct print_queue_update_context ctx; >+ fstring key; >+ fstring sharename; >+ pstring lpqcommand; >+ char *buffer = NULL; >+ size_t len = 0; >+ size_t newlen; >+ struct tdb_print_db *pdb; > > /* > * Make sure that the background queue process exists. > * Otherwise just do the update ourselves > */ > >- if ( background_lpq_updater_pid != -1 ) { >- fstrcpy(ctx.sharename, lp_const_servicename(snum)); >+ if ( background_lpq_updater_pid == -1 ) { >+ print_queue_update_with_lock( snum ); >+ return; >+ } >+ >+ fstrcpy( sharename, lp_const_servicename(snum)); >+ > ctx.printing_type = lp_printing(snum); > >- pstrcpy(ctx.lpqcommand, lp_lpqcommand(snum)); >- pstring_sub( ctx.lpqcommand, "%p", PRINTERNAME(snum) ); >- standard_sub_snum( snum, ctx.lpqcommand, sizeof(ctx.lpqcommand) ); >+ pstrcpy( lpqcommand, lp_lpqcommand(snum)); >+ pstring_sub( lpqcommand, "%p", PRINTERNAME(snum) ); >+ standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) ); >+ >+ ctx.sharename = smb_xstrdup( sharename ); >+ ctx.lpqcommand = smb_xstrdup( lpqcommand ); >+ >+ /* get the length */ >+ >+ len = tdb_pack( buffer, len, "fdP", >+ ctx.sharename, >+ ctx.printing_type, >+ ctx.lpqcommand ); >+ >+ buffer = smb_xmalloc( sizeof(char)*len ); >+ >+ /* now pack the buffer */ >+ newlen = tdb_pack( buffer, len, "fdP", >+ ctx.sharename, >+ ctx.printing_type, >+ ctx.lpqcommand ); >+ >+ SMB_ASSERT( newlen == len ); >+ >+ DEBUG(10,("print_queue_update: Sending message -> printer = %s, " >+ "type = %d, lpq command = [%s]\n", >+ ctx.sharename, ctx.printing_type, ctx.lpqcommand )); >+ >+ /* here we set a msg pending record for other smbd processes >+ to throttle the number of duplicate print_queue_update msgs >+ sent. */ >+ >+ pdb = get_print_db_byname(sharename); >+ snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename); >+ >+ if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) { >+ /* log a message but continue on */ >+ >+ DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n", >+ sharename)); >+ } >+ >+ release_print_db( pdb ); >+ >+ /* finally send the message */ > > become_root(); > message_send_pid(background_lpq_updater_pid, >- MSG_PRINTER_UPDATE, &ctx, sizeof(ctx), >- False); >+ MSG_PRINTER_UPDATE, buffer, len, False); > unbecome_root(); >- } else >- print_queue_update_with_lock( snum ); >+ >+ SAFE_FREE( ctx.sharename ); >+ SAFE_FREE( ctx.lpqcommand ); >+ SAFE_FREE( buffer ); >+ >+ return; > } > > /**************************************************************************** >@@ -1897,45 +2059,6 @@ > } > > /**************************************************************************** >- Check if the print queue has been updated recently enough. >-****************************************************************************/ >- >-static BOOL print_cache_expired(int snum) >-{ >- fstring key; >- time_t last_qscan_time, time_now = time(NULL); >- const char *printername = lp_const_servicename(snum); >- struct tdb_print_db *pdb = get_print_db_byname(printername); >- >- if (!pdb) >- return False; >- >- slprintf(key, sizeof(key), "CACHE/%s", printername); >- last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key); >- >- /* >- * Invalidate the queue for 3 reasons. >- * (1). last queue scan time == -1. >- * (2). Current time - last queue scan time > allowed cache time. >- * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default). >- * This last test picks up machines for which the clock has been moved >- * forward, an lpq scan done and then the clock moved back. Otherwise >- * that last lpq scan would stay around for a loooong loooong time... :-). JRA. >- */ >- >- if (last_qscan_time == ((time_t)-1) || (time_now - last_qscan_time) >= lp_lpqcachetime() || >- last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) { >- DEBUG(3, ("print cache expired for queue %s \ >-(last_qscan_time = %d, time now = %d, qcachetime = %d)\n", printername, >- (int)last_qscan_time, (int)time_now, (int)lp_lpqcachetime() )); >- release_print_db(pdb); >- return True; >- } >- release_print_db(pdb); >- return False; >-} >- >-/**************************************************************************** > Get the queue status - do not update if db is out of date. > ****************************************************************************/ > >@@ -1979,7 +2102,7 @@ > int len; > > /* make sure the database is up to date */ >- if (print_cache_expired(snum)) >+ if (print_cache_expired(lp_const_servicename(snum), True)) > print_queue_update(snum); > > /* also fetch the queue status */ >@@ -2294,7 +2417,7 @@ > pjob_store(sharename, jobid, pjob); > > /* make sure the database is up to date */ >- if (print_cache_expired(snum)) >+ if (print_cache_expired(lp_const_servicename(snum), True)) > print_queue_update(snum); > > return True; >@@ -2326,7 +2449,7 @@ > const char* sharename = lp_servicename(snum); > > /* make sure the database is up to date */ >- if (print_cache_expired(snum)) >+ if (print_cache_expired(lp_const_servicename(snum), True)) > print_queue_update(snum); > > *pcount = 0; >@@ -2447,7 +2570,7 @@ > > /* make sure the database is up to date */ > >- if (print_cache_expired(snum)) >+ if (print_cache_expired(lp_const_servicename(snum), True)) > print_queue_update(snum); > > /* return if we are done */ >@@ -2547,7 +2670,7 @@ > } > > /* make sure the database is up to date */ >- if (print_cache_expired(snum)) >+ if (print_cache_expired(lp_const_servicename(snum), True)) > print_queue_update(snum); > > /* Send a printer notify message */ >Only in samba-3.0.9/source/script: gen-8bit-gap.sh >Only in samba-3.0.9/source: smbadduser >diff -ruBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.9-orig/source/smbd/lanman.c samba-3.0.9/source/smbd/lanman.c >--- samba-3.0.9-orig/source/smbd/lanman.c 2004-11-15 21:03:14.000000000 -0600 >+++ samba-3.0.9/source/smbd/lanman.c 2004-12-07 18:45:38.677852265 -0600 >@@ -760,17 +760,9 @@ > return(True); > } > >- snum = lp_servicenumber(QueueName); >- if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { >- int pnum = lp_servicenumber(PRINTERS_NAME); >- if (pnum >= 0) { >- lp_add_printer(QueueName,pnum); >- snum = lp_servicenumber(QueueName); >- } >- } >- >- if (snum < 0 || !VALID_SNUM(snum)) >- return(False); >+ snum = find_service(QueueName); >+ if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) >+ return False; > > if (uLevel==52) { > count = get_printerdrivernumber(snum); >@@ -1502,6 +1494,8 @@ > data_len = fixed_len = string_len = 0; > for (i=0;i<count;i++) { > fstring servicename_dos; >+ if (!(lp_browseable(i) && lp_snum_ok(i))) >+ continue; > push_ascii_fstring(servicename_dos, lp_servicename(i)); > if( lp_browseable( i ) > && lp_snum_ok( i ) >@@ -1530,6 +1524,8 @@ > for( i = 0; i < count; i++ ) > { > fstring servicename_dos; >+ if (!(lp_browseable(i) && lp_snum_ok(i))) >+ continue; > push_ascii_fstring(servicename_dos, lp_servicename(i)); > if( lp_browseable( i ) > && lp_snum_ok( i ) >@@ -2143,6 +2139,12 @@ > goto out; > } > >+ snum = lp_servicenumber( sharename); >+ if (snum == -1) { >+ errcode = NERR_DestNotFound; >+ goto out; >+ } >+ > errcode = NERR_notsupported; > > switch (function) { >@@ -2968,6 +2970,7 @@ > if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) > return False; > >+ snum = lp_servicenumber( sharename); > if (snum < 0 || !VALID_SNUM(snum)) return(False); > > count = print_queue_status(snum,&queue,&status); >@@ -3038,20 +3041,18 @@ > DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); > > /* check it's a supported variant */ >- if (strcmp(str1,"zWrLeh") != 0) return False; >- if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ >- if (!check_printjob_info(&desc,uLevel,str2)) return False; >+ if (strcmp(str1,"zWrLeh") != 0) >+ return False; > >- snum = lp_servicenumber(name); >- if (snum < 0 && pcap_printername_ok(name,NULL)) { >- int pnum = lp_servicenumber(PRINTERS_NAME); >- if (pnum >= 0) { >- lp_add_printer(name,pnum); >- snum = lp_servicenumber(name); >- } >- } >+ if (uLevel > 2) >+ return False; /* defined only for uLevel 0,1,2 */ > >- if (snum < 0 || !VALID_SNUM(snum)) return(False); >+ if (!check_printjob_info(&desc,uLevel,str2)) >+ return False; >+ >+ snum = find_service(name); >+ if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) >+ return False; > > count = print_queue_status(snum,&queue,&status); > if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); >@@ -3154,16 +3155,8 @@ > if (strcmp(str1,"zWrLh") != 0) return False; > if (!check_printdest_info(&desc,uLevel,str2)) return False; > >- snum = lp_servicenumber(PrinterName); >- if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { >- int pnum = lp_servicenumber(PRINTERS_NAME); >- if (pnum >= 0) { >- lp_add_printer(PrinterName,pnum); >- snum = lp_servicenumber(PrinterName); >- } >- } >- >- if (snum < 0) { >+ snum = find_service(PrinterName); >+ if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { > *rdata_len = 0; > desc.errcode = NERR_DestNotFound; > desc.neededlen = 0;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 2107
:
823
|
824
| 827 |
837