Re: [Ext2-devel] [PATCH 2/2] ext2/3: Support2^32-1blocks(e2fsprogs)

From: Laurent Vivier
Date: Tue Mar 28 2006 - 02:13:27 EST


Le mar 28/03/2006 Ã 00:58, Ravikiran G Thirumalai a Ãcrit :
> On Mon, Mar 27, 2006 at 01:10:49PM -0800, Andrew Morton wrote:
> > Mingming Cao <cmm@xxxxxxxxxx> wrote:
> > >
> > > I am wondering if we have (or plan to have) "long long " type of percpu
> > > counters? Andrew, Kiran, do you know?
> > >
> > > It seems right now the percpu counters are used mostly by ext2/3 for
> > > filesystem free blocks accounting. Right now the counter is "long" type,
> > > which is not enough if we want to extend the filesystem limit from 2**31
> > > to 2**32 on 32 bit machine.
> > >
> > > The patch from Takashi copies the whole percpu_count.h and create a new
> > > percpu_llcounter.h to support longlong type percpu counters. I am
> > > wondering is there any better way for this?
> > >
> >
> > I can't immediately think of anything smarter.
> >
> > One could of course implement a 64-bit percpu counter by simply
> > concatenating two 32-bit counters. That would be a little less efficient,
> > but would introduce less source code and would mean that we don't need to
> > keep two different implemetations in sync. But one would need to do a bit
> > of implementation, see how bad it looks.
>
> Since long long is 64 bits on both 32bit and 64 bit arches, we can just
> change percpu_counter type to long long (or s64) and just have one
> implementation of percpu_counter?
> But reads and writes on 64 bit counters may not be atomic on all 32 bit arches.
> So the implementation might have to be reviewed for that.

As 64bit per cpu counter is used only by ext3 and needed only on 64bit
architecture and when CONFIG_LBD is set, perhaps we can have only one
implementation, 32bit in the case of 32bit arch and 64bit in the case of
64bit arch + LBD, as I did in my 64bit patches for ext3 ?

Cheers,
Laurent
--
Laurent Vivier
Bull, Architect of an Open World (TM)
http://www.bullopensource.org/ext4
Index: linux-2.6.16-lv/include/linux/percpu_counter.h
===================================================================
--- linux-2.6.16-lv.orig/include/linux/percpu_counter.h 2006-03-27 15:47:03.000000000 +0200
+++ linux-2.6.16-lv/include/linux/percpu_counter.h 2006-03-27 15:47:14.000000000 +0200
@@ -16,8 +16,13 @@

struct percpu_counter {
spinlock_t lock;
+#ifdef CONFIG_LBD
+ long long count;
+ long long *counters;
+#else
long count;
long *counters;
+#endif
};

#if NR_CPUS >= 16
@@ -30,7 +35,11 @@ static inline void percpu_counter_init(s
{
spin_lock_init(&fbc->lock);
fbc->count = 0;
+#ifdef CONFIG_LBD
+ fbc->counters = alloc_percpu(long long);
+#else
fbc->counters = alloc_percpu(long);
+#endif
}

static inline void percpu_counter_destroy(struct percpu_counter *fbc)
@@ -38,10 +47,17 @@ static inline void percpu_counter_destro
free_percpu(fbc->counters);
}

+#ifdef CONFIG_LBD
+void percpu_counter_mod(struct percpu_counter *fbc, long long amount);
+long long percpu_counter_sum(struct percpu_counter *fbc);
+
+static inline long long percpu_counter_read(struct percpu_counter *fbc)
+#else
void percpu_counter_mod(struct percpu_counter *fbc, long amount);
long percpu_counter_sum(struct percpu_counter *fbc);

static inline long percpu_counter_read(struct percpu_counter *fbc)
+#endif
{
return fbc->count;
}
@@ -50,9 +66,15 @@ static inline long percpu_counter_read(s
* It is possible for the percpu_counter_read() to return a small negative
* number for some counter which should never be negative.
*/
+#ifdef CONFIG_LBD
+static inline long long percpu_counter_read_positive(struct percpu_counter *fbc)
+{
+ long long ret = fbc->count;
+#else
static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
{
long ret = fbc->count;
+#endif

barrier(); /* Prevent reloads of fbc->count */
if (ret > 0)
@@ -63,7 +85,11 @@ static inline long percpu_counter_read_p
#else

struct percpu_counter {
+#ifdef CONFIG_LBD
+ long long count;
+#else
long count;
+#endif
};

static inline void percpu_counter_init(struct percpu_counter *fbc)
@@ -76,24 +102,40 @@ static inline void percpu_counter_destro
}

static inline void
+#ifdef CONFIG_LBD
+percpu_counter_mod(struct percpu_counter *fbc, long long amount)
+#else
percpu_counter_mod(struct percpu_counter *fbc, long amount)
+#endif
{
preempt_disable();
fbc->count += amount;
preempt_enable();
}

+#ifdef CONFIG_LBD
+static inline long long percpu_counter_read(struct percpu_counter *fbc)
+#else
static inline long percpu_counter_read(struct percpu_counter *fbc)
+#endif
{
return fbc->count;
}

+#ifdef CONFIG_LBD
+static inline long long percpu_counter_read_positive(struct percpu_counter *fbc)
+#else
static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
+#endif
{
return fbc->count;
}

+#ifdef CONFIG_LBD
+static inline long long percpu_counter_sum(struct percpu_counter *fbc)
+#else
static inline long percpu_counter_sum(struct percpu_counter *fbc)
+#endif
{
return percpu_counter_read_positive(fbc);
}
Index: linux-2.6.16-lv/mm/swap.c
===================================================================
--- linux-2.6.16-lv.orig/mm/swap.c 2006-03-27 15:47:03.000000000 +0200
+++ linux-2.6.16-lv/mm/swap.c 2006-03-27 15:47:14.000000000 +0200
@@ -479,10 +479,17 @@ static int cpu_swap_callback(struct noti
#endif /* CONFIG_SMP */

#ifdef CONFIG_SMP
+#ifdef CONFIG_LBD
+void percpu_counter_mod(struct percpu_counter *fbc, long long amount)
+{
+ long long count;
+ long long *pcount;
+#else
void percpu_counter_mod(struct percpu_counter *fbc, long amount)
{
long count;
long *pcount;
+#endif
int cpu = get_cpu();

pcount = per_cpu_ptr(fbc->counters, cpu);
@@ -503,15 +510,26 @@ EXPORT_SYMBOL(percpu_counter_mod);
* Add up all the per-cpu counts, return the result. This is a more accurate
* but much slower version of percpu_counter_read_positive()
*/
+#ifdef CONFIG_LBD
+long long percpu_counter_sum(struct percpu_counter *fbc)
+{
+ long long ret;
+#else
long percpu_counter_sum(struct percpu_counter *fbc)
{
long ret;
+#endif
int cpu;

spin_lock(&fbc->lock);
ret = fbc->count;
for_each_cpu(cpu) {
- long *pcount = per_cpu_ptr(fbc->counters, cpu);
+#ifdef CONFIG_LBD
+ long long *pcount;
+#else
+ long *pcount;
+#endif
+ pcount = per_cpu_ptr(fbc->counters, cpu);
ret += *pcount;
}
spin_unlock(&fbc->lock);

Attachment: signature.asc
Description: Ceci est une partie de message=?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e=2E?=