On Fri, 2007-08-17 at 11:56 -0400, Josef Sipek wrote:
> On Thu, Aug 16, 2007 at 09:45:34AM +0200, Peter Zijlstra wrote:

> > Index: linux-2.6/fs/ext2/super.c
> > ===================================================================
> > --- linux-2.6.orig/fs/ext2/super.c
> > +++ linux-2.6/fs/ext2/super.c
> > @@ -725,6 +725,7 @@ static int ext2_fill_super(struct super_
> >     int db_count;
> >     int i, j;
> >     __le32 features;
> > +   int err;
> >  
> >     sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
> >     if (!sbi)
> > @@ -996,12 +997,16 @@ static int ext2_fill_super(struct super_
> >     sbi->s_rsv_window_head.rsv_goal_size = 0;
> >     ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);
> >  
> > -   percpu_counter_init(&sbi->s_freeblocks_counter,
> > +   err = percpu_counter_init(&sbi->s_freeblocks_counter,
> >                             ext2_count_free_blocks(sb));
> > -   percpu_counter_init(&sbi->s_freeinodes_counter,
> > +   err |= percpu_counter_init(&sbi->s_freeinodes_counter,
> >                             ext2_count_free_inodes(sb));
> > -   percpu_counter_init(&sbi->s_dirs_counter,
> > +   err |= percpu_counter_init(&sbi->s_dirs_counter,
> >                             ext2_count_dirs(sb));
> > +   if (err) {
> > +           printk(KERN_ERR "EXT2-fs: insufficient memory\n");
> > +           goto failed_mount3;
> > +   }
> 
> Can percpu_counter_init fail with only one error code? If not, the error
> code potentially used in future at failed_mount3 could be nonsensical
> because of the bitwise or-ing.

The actual value of err is irrelevant, it is not used after this not
zero check.

But how about this:
---
Subject: lib: percpu_counter_init error handling

alloc_percpu can fail, propagate that error.

Signed-off-by: Peter Zijlstra <[EMAIL PROTECTED]>
---
 fs/ext2/super.c                |   15 ++++++++++++---
 fs/ext3/super.c                |   21 +++++++++++++++------
 fs/ext4/super.c                |   21 +++++++++++++++------
 include/linux/percpu_counter.h |    5 +++--
 lib/percpu_counter.c           |    8 +++++++-
 5 files changed, 52 insertions(+), 18 deletions(-)

Index: linux-2.6/fs/ext2/super.c
===================================================================
--- linux-2.6.orig/fs/ext2/super.c
+++ linux-2.6/fs/ext2/super.c
@@ -725,6 +725,7 @@ static int ext2_fill_super(struct super_
        int db_count;
        int i, j;
        __le32 features;
+       int err;
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
@@ -996,12 +997,20 @@ static int ext2_fill_super(struct super_
        sbi->s_rsv_window_head.rsv_goal_size = 0;
        ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);
 
-       percpu_counter_init(&sbi->s_freeblocks_counter,
+       err = percpu_counter_init(&sbi->s_freeblocks_counter,
                                ext2_count_free_blocks(sb));
-       percpu_counter_init(&sbi->s_freeinodes_counter,
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_freeinodes_counter,
                                ext2_count_free_inodes(sb));
-       percpu_counter_init(&sbi->s_dirs_counter,
+       }
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_dirs_counter,
                                ext2_count_dirs(sb));
+       }
+       if (err) {
+               printk(KERN_ERR "EXT2-fs: insufficient memory\n");
+               goto failed_mount3;
+       }
        /*
         * set up enough so that it can read an inode
         */
Index: linux-2.6/fs/ext3/super.c
===================================================================
--- linux-2.6.orig/fs/ext3/super.c
+++ linux-2.6/fs/ext3/super.c
@@ -1485,6 +1485,7 @@ static int ext3_fill_super (struct super
        int i;
        int needs_recovery;
        __le32 features;
+       int err;
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
@@ -1745,12 +1746,20 @@ static int ext3_fill_super (struct super
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
 
-       percpu_counter_init(&sbi->s_freeblocks_counter,
-               ext3_count_free_blocks(sb));
-       percpu_counter_init(&sbi->s_freeinodes_counter,
-               ext3_count_free_inodes(sb));
-       percpu_counter_init(&sbi->s_dirs_counter,
-               ext3_count_dirs(sb));
+       err = percpu_counter_init(&sbi->s_freeblocks_counter,
+                       ext3_count_free_blocks(sb));
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_freeinodes_counter,
+                               ext3_count_free_inodes(sb));
+       }
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_dirs_counter,
+                               ext3_count_dirs(sb));
+       }
+       if (err) {
+               printk(KERN_ERR "EXT3-fs: insufficient memory\n");
+               goto failed_mount3;
+       }
 
        /* per fileystem reservation list head & lock */
        spin_lock_init(&sbi->s_rsv_window_lock);
Index: linux-2.6/fs/ext4/super.c
===================================================================
--- linux-2.6.orig/fs/ext4/super.c
+++ linux-2.6/fs/ext4/super.c
@@ -1576,6 +1576,7 @@ static int ext4_fill_super (struct super
        int needs_recovery;
        __le32 features;
        __u64 blocks_count;
+       int err;
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
@@ -1857,12 +1858,20 @@ static int ext4_fill_super (struct super
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
 
-       percpu_counter_init(&sbi->s_freeblocks_counter,
-               ext4_count_free_blocks(sb));
-       percpu_counter_init(&sbi->s_freeinodes_counter,
-               ext4_count_free_inodes(sb));
-       percpu_counter_init(&sbi->s_dirs_counter,
-               ext4_count_dirs(sb));
+       err = percpu_counter_init(&sbi->s_freeblocks_counter,
+                       ext4_count_free_blocks(sb));
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_freeinodes_counter,
+                               ext4_count_free_inodes(sb));
+       }
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_dirs_counter,
+                               ext4_count_dirs(sb));
+       }
+       if (err) {
+               printk(KERN_ERR "EXT4-fs: insufficient memory\n");
+               goto failed_mount3;
+       }
 
        /* per fileystem reservation list head & lock */
        spin_lock_init(&sbi->s_rsv_window_lock);
Index: linux-2.6/include/linux/percpu_counter.h
===================================================================
--- linux-2.6.orig/include/linux/percpu_counter.h
+++ linux-2.6/include/linux/percpu_counter.h
@@ -30,7 +30,7 @@ struct percpu_counter {
 #define FBC_BATCH      (NR_CPUS*4)
 #endif
 
-void percpu_counter_init(struct percpu_counter *fbc, s64 amount);
+int percpu_counter_init(struct percpu_counter *fbc, s64 amount);
 void percpu_counter_destroy(struct percpu_counter *fbc);
 void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
 void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch);
@@ -78,9 +78,10 @@ struct percpu_counter {
        s64 count;
 };
 
-static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
 {
        fbc->count = amount;
+       return 0;
 }
 
 static inline void percpu_counter_destroy(struct percpu_counter *fbc)
Index: linux-2.6/lib/percpu_counter.c
===================================================================
--- linux-2.6.orig/lib/percpu_counter.c
+++ linux-2.6/lib/percpu_counter.c
@@ -68,21 +68,27 @@ s64 __percpu_counter_sum(struct percpu_c
 }
 EXPORT_SYMBOL(__percpu_counter_sum);
 
-void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
 {
        spin_lock_init(&fbc->lock);
        fbc->count = amount;
        fbc->counters = alloc_percpu(s32);
+       if (!fbc->counters)
+               return -ENOMEM;
 #ifdef CONFIG_HOTPLUG_CPU
        mutex_lock(&percpu_counters_lock);
        list_add(&fbc->list, &percpu_counters);
        mutex_unlock(&percpu_counters_lock);
 #endif
+       return 0;
 }
 EXPORT_SYMBOL(percpu_counter_init);
 
 void percpu_counter_destroy(struct percpu_counter *fbc)
 {
+       if (!fbc->counters)
+               return;
+
        free_percpu(fbc->counters);
 #ifdef CONFIG_HOTPLUG_CPU
        mutex_lock(&percpu_counters_lock);

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to