aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext2/super.c25
-rw-r--r--fs/ext3/super.c36
-rw-r--r--fs/file_table.c2
-rw-r--r--include/linux/percpu_counter.h38
-rw-r--r--lib/percpu_counter.c10
5 files changed, 58 insertions, 53 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index a6c4d6e02324..ee4ba759581e 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -834,9 +834,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
834 printk ("EXT2-fs: not enough memory\n"); 834 printk ("EXT2-fs: not enough memory\n");
835 goto failed_mount; 835 goto failed_mount;
836 } 836 }
837 percpu_counter_init(&sbi->s_freeblocks_counter);
838 percpu_counter_init(&sbi->s_freeinodes_counter);
839 percpu_counter_init(&sbi->s_dirs_counter);
840 bgl_lock_init(&sbi->s_blockgroup_lock); 837 bgl_lock_init(&sbi->s_blockgroup_lock);
841 sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts), 838 sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts),
842 GFP_KERNEL); 839 GFP_KERNEL);
@@ -863,6 +860,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
863 sbi->s_gdb_count = db_count; 860 sbi->s_gdb_count = db_count;
864 get_random_bytes(&sbi->s_next_generation, sizeof(u32)); 861 get_random_bytes(&sbi->s_next_generation, sizeof(u32));
865 spin_lock_init(&sbi->s_next_gen_lock); 862 spin_lock_init(&sbi->s_next_gen_lock);
863
864 percpu_counter_init(&sbi->s_freeblocks_counter,
865 ext2_count_free_blocks(sb));
866 percpu_counter_init(&sbi->s_freeinodes_counter,
867 ext2_count_free_inodes(sb));
868 percpu_counter_init(&sbi->s_dirs_counter,
869 ext2_count_dirs(sb));
866 /* 870 /*
867 * set up enough so that it can read an inode 871 * set up enough so that it can read an inode
868 */ 872 */
@@ -874,24 +878,18 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
874 if (!sb->s_root) { 878 if (!sb->s_root) {
875 iput(root); 879 iput(root);
876 printk(KERN_ERR "EXT2-fs: get root inode failed\n"); 880 printk(KERN_ERR "EXT2-fs: get root inode failed\n");
877 goto failed_mount2; 881 goto failed_mount3;
878 } 882 }
879 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { 883 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
880 dput(sb->s_root); 884 dput(sb->s_root);
881 sb->s_root = NULL; 885 sb->s_root = NULL;
882 printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n"); 886 printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
883 goto failed_mount2; 887 goto failed_mount3;
884 } 888 }
885 if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 889 if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
886 ext2_warning(sb, __FUNCTION__, 890 ext2_warning(sb, __FUNCTION__,
887 "mounting ext3 filesystem as ext2"); 891 "mounting ext3 filesystem as ext2");
888 ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); 892 ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
889 percpu_counter_mod(&sbi->s_freeblocks_counter,
890 ext2_count_free_blocks(sb));
891 percpu_counter_mod(&sbi->s_freeinodes_counter,
892 ext2_count_free_inodes(sb));
893 percpu_counter_mod(&sbi->s_dirs_counter,
894 ext2_count_dirs(sb));
895 return 0; 893 return 0;
896 894
897cantfind_ext2: 895cantfind_ext2:
@@ -899,7 +897,10 @@ cantfind_ext2:
899 printk("VFS: Can't find an ext2 filesystem on dev %s.\n", 897 printk("VFS: Can't find an ext2 filesystem on dev %s.\n",
900 sb->s_id); 898 sb->s_id);
901 goto failed_mount; 899 goto failed_mount;
902 900failed_mount3:
901 percpu_counter_destroy(&sbi->s_freeblocks_counter);
902 percpu_counter_destroy(&sbi->s_freeinodes_counter);
903 percpu_counter_destroy(&sbi->s_dirs_counter);
903failed_mount2: 904failed_mount2:
904 for (i = 0; i < db_count; i++) 905 for (i = 0; i < db_count; i++)
905 brelse(sbi->s_group_desc[i]); 906 brelse(sbi->s_group_desc[i]);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 1a198b3985c9..a60cc6ec130f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1580,9 +1580,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1580 goto failed_mount; 1580 goto failed_mount;
1581 } 1581 }
1582 1582
1583 percpu_counter_init(&sbi->s_freeblocks_counter);
1584 percpu_counter_init(&sbi->s_freeinodes_counter);
1585 percpu_counter_init(&sbi->s_dirs_counter);
1586 bgl_lock_init(&sbi->s_blockgroup_lock); 1583 bgl_lock_init(&sbi->s_blockgroup_lock);
1587 1584
1588 for (i = 0; i < db_count; i++) { 1585 for (i = 0; i < db_count; i++) {
@@ -1602,6 +1599,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1602 sbi->s_gdb_count = db_count; 1599 sbi->s_gdb_count = db_count;
1603 get_random_bytes(&sbi->s_next_generation, sizeof(u32)); 1600 get_random_bytes(&sbi->s_next_generation, sizeof(u32));
1604 spin_lock_init(&sbi->s_next_gen_lock); 1601 spin_lock_init(&sbi->s_next_gen_lock);
1602
1603 percpu_counter_init(&sbi->s_freeblocks_counter,
1604 ext3_count_free_blocks(sb));
1605 percpu_counter_init(&sbi->s_freeinodes_counter,
1606 ext3_count_free_inodes(sb));
1607 percpu_counter_init(&sbi->s_dirs_counter,
1608 ext3_count_dirs(sb));
1609
1605 /* per fileystem reservation list head & lock */ 1610 /* per fileystem reservation list head & lock */
1606 spin_lock_init(&sbi->s_rsv_window_lock); 1611 spin_lock_init(&sbi->s_rsv_window_lock);
1607 sbi->s_rsv_window_root = RB_ROOT; 1612 sbi->s_rsv_window_root = RB_ROOT;
@@ -1640,16 +1645,16 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1640 if (!test_opt(sb, NOLOAD) && 1645 if (!test_opt(sb, NOLOAD) &&
1641 EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { 1646 EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
1642 if (ext3_load_journal(sb, es, journal_devnum)) 1647 if (ext3_load_journal(sb, es, journal_devnum))
1643 goto failed_mount2; 1648 goto failed_mount3;
1644 } else if (journal_inum) { 1649 } else if (journal_inum) {
1645 if (ext3_create_journal(sb, es, journal_inum)) 1650 if (ext3_create_journal(sb, es, journal_inum))
1646 goto failed_mount2; 1651 goto failed_mount3;
1647 } else { 1652 } else {
1648 if (!silent) 1653 if (!silent)
1649 printk (KERN_ERR 1654 printk (KERN_ERR
1650 "ext3: No journal on filesystem on %s\n", 1655 "ext3: No journal on filesystem on %s\n",
1651 sb->s_id); 1656 sb->s_id);
1652 goto failed_mount2; 1657 goto failed_mount3;
1653 } 1658 }
1654 1659
1655 /* We have now updated the journal if required, so we can 1660 /* We have now updated the journal if required, so we can
@@ -1672,7 +1677,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1672 (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) { 1677 (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
1673 printk(KERN_ERR "EXT3-fs: Journal does not support " 1678 printk(KERN_ERR "EXT3-fs: Journal does not support "
1674 "requested data journaling mode\n"); 1679 "requested data journaling mode\n");
1675 goto failed_mount3; 1680 goto failed_mount4;
1676 } 1681 }
1677 default: 1682 default:
1678 break; 1683 break;
@@ -1695,13 +1700,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1695 if (!sb->s_root) { 1700 if (!sb->s_root) {
1696 printk(KERN_ERR "EXT3-fs: get root inode failed\n"); 1701 printk(KERN_ERR "EXT3-fs: get root inode failed\n");
1697 iput(root); 1702 iput(root);
1698 goto failed_mount3; 1703 goto failed_mount4;
1699 } 1704 }
1700 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { 1705 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
1701 dput(sb->s_root); 1706 dput(sb->s_root);
1702 sb->s_root = NULL; 1707 sb->s_root = NULL;
1703 printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n"); 1708 printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n");
1704 goto failed_mount3; 1709 goto failed_mount4;
1705 } 1710 }
1706 1711
1707 ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); 1712 ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
@@ -1724,13 +1729,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1724 test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": 1729 test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
1725 "writeback"); 1730 "writeback");
1726 1731
1727 percpu_counter_mod(&sbi->s_freeblocks_counter,
1728 ext3_count_free_blocks(sb));
1729 percpu_counter_mod(&sbi->s_freeinodes_counter,
1730 ext3_count_free_inodes(sb));
1731 percpu_counter_mod(&sbi->s_dirs_counter,
1732 ext3_count_dirs(sb));
1733
1734 lock_kernel(); 1732 lock_kernel();
1735 return 0; 1733 return 0;
1736 1734
@@ -1740,8 +1738,12 @@ cantfind_ext3:
1740 sb->s_id); 1738 sb->s_id);
1741 goto failed_mount; 1739 goto failed_mount;
1742 1740
1743failed_mount3: 1741failed_mount4:
1744 journal_destroy(sbi->s_journal); 1742 journal_destroy(sbi->s_journal);
1743failed_mount3:
1744 percpu_counter_destroy(&sbi->s_freeblocks_counter);
1745 percpu_counter_destroy(&sbi->s_freeinodes_counter);
1746 percpu_counter_destroy(&sbi->s_dirs_counter);
1745failed_mount2: 1747failed_mount2:
1746 for (i = 0; i < db_count; i++) 1748 for (i = 0; i < db_count; i++)
1747 brelse(sbi->s_group_desc[i]); 1749 brelse(sbi->s_group_desc[i]);
diff --git a/fs/file_table.c b/fs/file_table.c
index bcea1998b4de..506d5307108d 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -300,5 +300,5 @@ void __init files_init(unsigned long mempages)
300 if (files_stat.max_files < NR_FILE) 300 if (files_stat.max_files < NR_FILE)
301 files_stat.max_files = NR_FILE; 301 files_stat.max_files = NR_FILE;
302 files_defer_init(); 302 files_defer_init();
303 percpu_counter_init(&nr_files); 303 percpu_counter_init(&nr_files, 0);
304} 304}
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index 66b5de404f22..f5aa593ccf32 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -10,13 +10,14 @@
10#include <linux/smp.h> 10#include <linux/smp.h>
11#include <linux/threads.h> 11#include <linux/threads.h>
12#include <linux/percpu.h> 12#include <linux/percpu.h>
13#include <linux/types.h>
13 14
14#ifdef CONFIG_SMP 15#ifdef CONFIG_SMP
15 16
16struct percpu_counter { 17struct percpu_counter {
17 spinlock_t lock; 18 spinlock_t lock;
18 long count; 19 s64 count;
19 long *counters; 20 s32 *counters;
20}; 21};
21 22
22#if NR_CPUS >= 16 23#if NR_CPUS >= 16
@@ -25,11 +26,11 @@ struct percpu_counter {
25#define FBC_BATCH (NR_CPUS*4) 26#define FBC_BATCH (NR_CPUS*4)
26#endif 27#endif
27 28
28static inline void percpu_counter_init(struct percpu_counter *fbc) 29static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
29{ 30{
30 spin_lock_init(&fbc->lock); 31 spin_lock_init(&fbc->lock);
31 fbc->count = 0; 32 fbc->count = amount;
32 fbc->counters = alloc_percpu(long); 33 fbc->counters = alloc_percpu(s32);
33} 34}
34 35
35static inline void percpu_counter_destroy(struct percpu_counter *fbc) 36static inline void percpu_counter_destroy(struct percpu_counter *fbc)
@@ -37,10 +38,10 @@ static inline void percpu_counter_destroy(struct percpu_counter *fbc)
37 free_percpu(fbc->counters); 38 free_percpu(fbc->counters);
38} 39}
39 40
40void percpu_counter_mod(struct percpu_counter *fbc, long amount); 41void percpu_counter_mod(struct percpu_counter *fbc, s32 amount);
41long percpu_counter_sum(struct percpu_counter *fbc); 42s64 percpu_counter_sum(struct percpu_counter *fbc);
42 43
43static inline long percpu_counter_read(struct percpu_counter *fbc) 44static inline s64 percpu_counter_read(struct percpu_counter *fbc)
44{ 45{
45 return fbc->count; 46 return fbc->count;
46} 47}
@@ -48,13 +49,14 @@ static inline long percpu_counter_read(struct percpu_counter *fbc)
48/* 49/*
49 * It is possible for the percpu_counter_read() to return a small negative 50 * It is possible for the percpu_counter_read() to return a small negative
50 * number for some counter which should never be negative. 51 * number for some counter which should never be negative.
52 *
51 */ 53 */
52static inline long percpu_counter_read_positive(struct percpu_counter *fbc) 54static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
53{ 55{
54 long ret = fbc->count; 56 s64 ret = fbc->count;
55 57
56 barrier(); /* Prevent reloads of fbc->count */ 58 barrier(); /* Prevent reloads of fbc->count */
57 if (ret > 0) 59 if (ret >= 0)
58 return ret; 60 return ret;
59 return 1; 61 return 1;
60} 62}
@@ -62,12 +64,12 @@ static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
62#else 64#else
63 65
64struct percpu_counter { 66struct percpu_counter {
65 long count; 67 s64 count;
66}; 68};
67 69
68static inline void percpu_counter_init(struct percpu_counter *fbc) 70static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
69{ 71{
70 fbc->count = 0; 72 fbc->count = amount;
71} 73}
72 74
73static inline void percpu_counter_destroy(struct percpu_counter *fbc) 75static inline void percpu_counter_destroy(struct percpu_counter *fbc)
@@ -75,24 +77,24 @@ static inline void percpu_counter_destroy(struct percpu_counter *fbc)
75} 77}
76 78
77static inline void 79static inline void
78percpu_counter_mod(struct percpu_counter *fbc, long amount) 80percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
79{ 81{
80 preempt_disable(); 82 preempt_disable();
81 fbc->count += amount; 83 fbc->count += amount;
82 preempt_enable(); 84 preempt_enable();
83} 85}
84 86
85static inline long percpu_counter_read(struct percpu_counter *fbc) 87static inline s64 percpu_counter_read(struct percpu_counter *fbc)
86{ 88{
87 return fbc->count; 89 return fbc->count;
88} 90}
89 91
90static inline long percpu_counter_read_positive(struct percpu_counter *fbc) 92static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
91{ 93{
92 return fbc->count; 94 return fbc->count;
93} 95}
94 96
95static inline long percpu_counter_sum(struct percpu_counter *fbc) 97static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
96{ 98{
97 return percpu_counter_read_positive(fbc); 99 return percpu_counter_read_positive(fbc);
98} 100}
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 7a87003f8e8f..850449080e1c 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -5,10 +5,10 @@
5#include <linux/percpu_counter.h> 5#include <linux/percpu_counter.h>
6#include <linux/module.h> 6#include <linux/module.h>
7 7
8void percpu_counter_mod(struct percpu_counter *fbc, long amount) 8void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
9{ 9{
10 long count; 10 long count;
11 long *pcount; 11 s32 *pcount;
12 int cpu = get_cpu(); 12 int cpu = get_cpu();
13 13
14 pcount = per_cpu_ptr(fbc->counters, cpu); 14 pcount = per_cpu_ptr(fbc->counters, cpu);
@@ -29,15 +29,15 @@ EXPORT_SYMBOL(percpu_counter_mod);
29 * Add up all the per-cpu counts, return the result. This is a more accurate 29 * Add up all the per-cpu counts, return the result. This is a more accurate
30 * but much slower version of percpu_counter_read_positive() 30 * but much slower version of percpu_counter_read_positive()
31 */ 31 */
32long percpu_counter_sum(struct percpu_counter *fbc) 32s64 percpu_counter_sum(struct percpu_counter *fbc)
33{ 33{
34 long ret; 34 s64 ret;
35 int cpu; 35 int cpu;
36 36
37 spin_lock(&fbc->lock); 37 spin_lock(&fbc->lock);
38 ret = fbc->count; 38 ret = fbc->count;
39 for_each_possible_cpu(cpu) { 39 for_each_possible_cpu(cpu) {
40 long *pcount = per_cpu_ptr(fbc->counters, cpu); 40 s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
41 ret += *pcount; 41 ret += *pcount;
42 } 42 }
43 spin_unlock(&fbc->lock); 43 spin_unlock(&fbc->lock);