diff options
-rw-r--r-- | fs/ext2/super.c | 25 | ||||
-rw-r--r-- | fs/ext3/super.c | 36 | ||||
-rw-r--r-- | fs/file_table.c | 2 | ||||
-rw-r--r-- | include/linux/percpu_counter.h | 38 | ||||
-rw-r--r-- | lib/percpu_counter.c | 10 |
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 | ||
897 | cantfind_ext2: | 895 | cantfind_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 | 900 | failed_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); | ||
903 | failed_mount2: | 904 | failed_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 | ||
1743 | failed_mount3: | 1741 | failed_mount4: |
1744 | journal_destroy(sbi->s_journal); | 1742 | journal_destroy(sbi->s_journal); |
1743 | failed_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); | ||
1745 | failed_mount2: | 1747 | failed_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 | ||
16 | struct percpu_counter { | 17 | struct 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 | ||
28 | static inline void percpu_counter_init(struct percpu_counter *fbc) | 29 | static 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 | ||
35 | static inline void percpu_counter_destroy(struct percpu_counter *fbc) | 36 | static 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 | ||
40 | void percpu_counter_mod(struct percpu_counter *fbc, long amount); | 41 | void percpu_counter_mod(struct percpu_counter *fbc, s32 amount); |
41 | long percpu_counter_sum(struct percpu_counter *fbc); | 42 | s64 percpu_counter_sum(struct percpu_counter *fbc); |
42 | 43 | ||
43 | static inline long percpu_counter_read(struct percpu_counter *fbc) | 44 | static 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 | */ |
52 | static inline long percpu_counter_read_positive(struct percpu_counter *fbc) | 54 | static 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 | ||
64 | struct percpu_counter { | 66 | struct percpu_counter { |
65 | long count; | 67 | s64 count; |
66 | }; | 68 | }; |
67 | 69 | ||
68 | static inline void percpu_counter_init(struct percpu_counter *fbc) | 70 | static 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 | ||
73 | static inline void percpu_counter_destroy(struct percpu_counter *fbc) | 75 | static 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 | ||
77 | static inline void | 79 | static inline void |
78 | percpu_counter_mod(struct percpu_counter *fbc, long amount) | 80 | percpu_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 | ||
85 | static inline long percpu_counter_read(struct percpu_counter *fbc) | 87 | static inline s64 percpu_counter_read(struct percpu_counter *fbc) |
86 | { | 88 | { |
87 | return fbc->count; | 89 | return fbc->count; |
88 | } | 90 | } |
89 | 91 | ||
90 | static inline long percpu_counter_read_positive(struct percpu_counter *fbc) | 92 | static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc) |
91 | { | 93 | { |
92 | return fbc->count; | 94 | return fbc->count; |
93 | } | 95 | } |
94 | 96 | ||
95 | static inline long percpu_counter_sum(struct percpu_counter *fbc) | 97 | static 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 | ||
8 | void percpu_counter_mod(struct percpu_counter *fbc, long amount) | 8 | void 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 | */ |
32 | long percpu_counter_sum(struct percpu_counter *fbc) | 32 | s64 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); |