aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Banks <gnb@sgi.com>2009-01-13 05:26:34 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-03-18 17:38:41 -0400
commit8bbfa9f3889b643fc7de82c0c761ef17097f8faf (patch)
treeb214924c3fa4a440a1cd2dc036630e8d7e605256
parent5cb031b0afddad73ea4191c9f0b76d20ca447dc0 (diff)
knfsd: remove the nfsd thread busy histogram
Stop gathering the data that feeds the 'th' line in /proc/net/rpc/nfsd because the questionable data provided is not worth the scalability impact of calculating it. Instead, always report zeroes. The current approach suffers from three major issues: 1. update_thread_usage() increments buckets by call service time or call arrival time...in jiffies. On lightly loaded machines, call service times are usually < 1 jiffy; on heavily loaded machines call arrival times will be << 1 jiffy. So a large portion of the updates to the buckets are rounded down to zero, and the histogram is undercounting. 2. As seen previously on the nfs mailing list, the format in which the histogram is presented is cryptic, difficult to explain, and difficult to use. 3. Updating the histogram requires taking a global spinlock and dirtying the global variables nfsd_last_call, nfsd_busy, and nfsdstats *twice* on every RPC call, which is a significant scaling limitation. Testing on a 4 CPU 4 NIC Altix using 4 IRIX clients each doing 1K streaming reads at full line rate, shows the stats update code (inlined into nfsd()) takes about 1.7% of each CPU. This patch drops the contribution from nfsd() into the profile noise. This patch is a forward-ported version of knfsd-remove-nfsd-threadstats which has been shipping in the SGI "Enhanced NFS" product since 2006. In that time, exactly one customer has noticed that the threadstats were missing. It has been previously posted: http://article.gmane.org/gmane.linux.nfs/10376 and more recently requested to be posted again. Signed-off-by: Greg Banks <gnb@sgi.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/nfsd/nfssvc.c28
1 files changed, 0 insertions, 28 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 07e4f5d7baa8..c3eb0759fd57 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -40,9 +40,6 @@
40extern struct svc_program nfsd_program; 40extern struct svc_program nfsd_program;
41static int nfsd(void *vrqstp); 41static int nfsd(void *vrqstp);
42struct timeval nfssvc_boot; 42struct timeval nfssvc_boot;
43static atomic_t nfsd_busy;
44static unsigned long nfsd_last_call;
45static DEFINE_SPINLOCK(nfsd_call_lock);
46 43
47/* 44/*
48 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members 45 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
@@ -227,7 +224,6 @@ int nfsd_create_serv(void)
227 nfsd_max_blksize /= 2; 224 nfsd_max_blksize /= 2;
228 } 225 }
229 226
230 atomic_set(&nfsd_busy, 0);
231 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 227 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
232 AF_INET, 228 AF_INET,
233 nfsd_last_thread, nfsd, THIS_MODULE); 229 nfsd_last_thread, nfsd, THIS_MODULE);
@@ -376,26 +372,6 @@ nfsd_svc(unsigned short port, int nrservs)
376 return error; 372 return error;
377} 373}
378 374
379static inline void
380update_thread_usage(int busy_threads)
381{
382 unsigned long prev_call;
383 unsigned long diff;
384 int decile;
385
386 spin_lock(&nfsd_call_lock);
387 prev_call = nfsd_last_call;
388 nfsd_last_call = jiffies;
389 decile = busy_threads*10/nfsdstats.th_cnt;
390 if (decile>0 && decile <= 10) {
391 diff = nfsd_last_call - prev_call;
392 if ( (nfsdstats.th_usage[decile-1] += diff) >= NFSD_USAGE_WRAP)
393 nfsdstats.th_usage[decile-1] -= NFSD_USAGE_WRAP;
394 if (decile == 10)
395 nfsdstats.th_fullcnt++;
396 }
397 spin_unlock(&nfsd_call_lock);
398}
399 375
400/* 376/*
401 * This is the NFS server kernel thread 377 * This is the NFS server kernel thread
@@ -464,8 +440,6 @@ nfsd(void *vrqstp)
464 continue; 440 continue;
465 } 441 }
466 442
467 update_thread_usage(atomic_read(&nfsd_busy));
468 atomic_inc(&nfsd_busy);
469 443
470 /* Lock the export hash tables for reading. */ 444 /* Lock the export hash tables for reading. */
471 exp_readlock(); 445 exp_readlock();
@@ -474,8 +448,6 @@ nfsd(void *vrqstp)
474 448
475 /* Unlock export hash tables */ 449 /* Unlock export hash tables */
476 exp_readunlock(); 450 exp_readunlock();
477 update_thread_usage(atomic_read(&nfsd_busy));
478 atomic_dec(&nfsd_busy);
479 } 451 }
480 452
481 /* Clear signals before calling svc_exit_thread() */ 453 /* Clear signals before calling svc_exit_thread() */