All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: zhejiang <zhe.jiang@intel.com>
Cc: linux-kernel@vger.kernel.org, yanmin_zhang@linux.intel.com
Subject: Re: [PATCH]Avoid the overflow when calculate the proportion of bdi quota
Date: Fri, 14 Dec 2007 10:49:36 +0100	[thread overview]
Message-ID: <1197625776.6895.36.camel@twins> (raw)
In-Reply-To: <1197622070.6895.33.camel@twins>


On Fri, 2007-12-14 at 09:47 +0100, Peter Zijlstra wrote:

> How about something like this:
> 
> diff --git a/lib/proportions.c b/lib/proportions.c
> index 332d8c5..4afb330 100644
> --- a/lib/proportions.c
> +++ b/lib/proportions.c
> @@ -190,6 +190,8 @@ prop_adjust_shift(int *pl_shift, unsigned long *pl_period, int new_shift)
>   * PERCPU
>   */
>  
> +#define PROP_BATCH (8*(1+ilog2(nr_cpu_ids)))
> +
>  int prop_local_init_percpu(struct prop_local_percpu *pl)
>  {
>  	spin_lock_init(&pl->lock);
> @@ -203,6 +205,16 @@ void prop_local_destroy_percpu(struct prop_local_percpu *pl)
>  	percpu_counter_destroy(&pl->events);
>  }
>  
> +static unsigned long prop_percpu_read(struct prop_local_percpu *pl)
> +{
> +	unsigned long val = percpu_counter_read(&pl->events);
> +
> +	if (val < (nr_cpu_ids * PROP_BATCH))
> +		val = percpu_counter_sum(&pl->events);
> +
> +	return val;
> +}
> +
>  /*
>   * Catch up with missed period expirations.
>   *
> @@ -241,7 +253,7 @@ void prop_norm_percpu(struct prop_global *pg, struct prop_local_percpu *pl)
>  	 * can never result in a negative number.
>  	 */
>  	while (pl->period != global_period) {
> -		unsigned long val = percpu_counter_read(&pl->events);
> +		unsigned long val = prop_percpu_read(pl);
>  		unsigned long half = (val + 1) >> 1;
>  
>  		/*
> @@ -252,7 +264,7 @@ void prop_norm_percpu(struct prop_global *pg, struct prop_local_percpu *pl)
>  		if (!val)
>  			break;
>  
> -		percpu_counter_add(&pl->events, -half);
> +		__percpu_counter_add(&pl->events, -half, PROP_BATCH);
>  		pl->period += period;
>  	}
>  	pl->period = global_period;
> @@ -267,7 +279,7 @@ void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
>  	struct prop_global *pg = prop_get_global(pd);
>  
>  	prop_norm_percpu(pg, pl);
> -	percpu_counter_add(&pl->events, 1);
> +	__percpu_counter_add(&pl->events, 1, PROP_BATCH);
>  	percpu_counter_add(&pg->events, 1);
>  	prop_put_global(pd, pg);
>  }
> 

Might as well stack something like this on top:

Index: linux-2.6/lib/proportions.c
===================================================================
--- linux-2.6.orig/lib/proportions.c
+++ linux-2.6/lib/proportions.c
@@ -242,31 +242,19 @@ void prop_norm_percpu(struct prop_global
 
 	spin_lock_irqsave(&pl->lock, flags);
 	prop_adjust_shift(&pl->shift, &pl->period, pg->shift);
+
 	/*
 	 * For each missed period, we half the local counter.
 	 * basically:
 	 *   pl->events >> (global_period - pl->period);
-	 *
-	 * but since the distributed nature of percpu counters make division
-	 * rather hard, use a regular subtraction loop. This is safe, because
-	 * the events will only every be incremented, hence the subtraction
-	 * can never result in a negative number.
 	 */
-	while (pl->period != global_period) {
-		unsigned long val = prop_local_read_percpu(pl);
-		unsigned long half = (val + 1) >> 1;
-
-		/*
-		 * Half of zero won't be much less, break out.
-		 * This limits the loop to shift iterations, even
-		 * if we missed a million.
-		 */
-		if (!val)
-			break;
-
-		__percpu_counter_add(&pl->events, -half, PROP_BATCH);
-		pl->period += period;
-	}
+	period = (global_period - pl->period) >> (pg->shift - 1);
+	if (period < BITS_PER_LONG) {
+		s64 val = (u64)prop_local_read_percpu(pl);
+		__percpu_counter_add(&pl->events, -val + (val >> period), PROP_BATCH);
+	} else
+		percpu_counter_set(&pl->events, 0);
+
 	pl->period = global_period;
 	spin_unlock_irqrestore(&pl->lock, flags);
 }



  reply	other threads:[~2007-12-14  9:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-13  3:30 [PATCH]Avoid the overflow when calculate the proportion of bdi quota zhejiang
2007-12-13 21:54 ` Peter Zijlstra
2007-12-14  8:26   ` zhejiang
2007-12-14  8:47     ` Peter Zijlstra
2007-12-14  9:49       ` Peter Zijlstra [this message]
2007-12-14 16:01     ` [PATCH] lib: proportion: fix underflow in prop_norm_percpu() Peter Zijlstra
2007-12-17  1:55       ` Jiang zhe
2007-12-17  5:24       ` Jiang zhe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1197625776.6895.36.camel@twins \
    --to=peterz@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=yanmin_zhang@linux.intel.com \
    --cc=zhe.jiang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.