aboutsummaryrefslogtreecommitdiffstats
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorChristoph Lameter <cl@linux.com>2010-12-06 12:16:28 -0500
committerTejun Heo <tj@kernel.org>2010-12-17 09:07:19 -0500
commitc7b92516a9c68fa5403879225a5a19974a801ef6 (patch)
tree1f72ebd85bca40806024ac6b8f5caab068b7c15d /fs/buffer.c
parent5309665dcc1143d659d82568da8d00f0e08a58f9 (diff)
fs: Use this_cpu_xx operations in buffer.c
Optimize various per cpu area operations through these new percpu operations. These operations avoid address calculations through the use of segment prefixes and multiple memory references through RMW instructions etc. Reduces code size: Before: christoph@linux-2.6$ size fs/buffer.o text data bss dec hex filename 19169 80 28 19277 4b4d fs/buffer.o After: christoph@linux-2.6$ size fs/buffer.o text data bss dec hex filename 19138 80 28 19246 4b2e fs/buffer.o V3->V4: - Move the use of this_cpu_inc_return into a later patch so that this one can go in without percpu infrastructure changes. Cc: Wu Fengguang <fengguang.wu@intel.com> Cc: Christoph Hellwig <hch@lst.de> Acked-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Christoph Lameter <cl@linux.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index 5930e382959b..137d9de00e24 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1270,12 +1270,10 @@ static inline void check_irqs_on(void)
1270static void bh_lru_install(struct buffer_head *bh) 1270static void bh_lru_install(struct buffer_head *bh)
1271{ 1271{
1272 struct buffer_head *evictee = NULL; 1272 struct buffer_head *evictee = NULL;
1273 struct bh_lru *lru;
1274 1273
1275 check_irqs_on(); 1274 check_irqs_on();
1276 bh_lru_lock(); 1275 bh_lru_lock();
1277 lru = &__get_cpu_var(bh_lrus); 1276 if (__this_cpu_read(bh_lrus.bhs[0]) != bh) {
1278 if (lru->bhs[0] != bh) {
1279 struct buffer_head *bhs[BH_LRU_SIZE]; 1277 struct buffer_head *bhs[BH_LRU_SIZE];
1280 int in; 1278 int in;
1281 int out = 0; 1279 int out = 0;
@@ -1283,7 +1281,8 @@ static void bh_lru_install(struct buffer_head *bh)
1283 get_bh(bh); 1281 get_bh(bh);
1284 bhs[out++] = bh; 1282 bhs[out++] = bh;
1285 for (in = 0; in < BH_LRU_SIZE; in++) { 1283 for (in = 0; in < BH_LRU_SIZE; in++) {
1286 struct buffer_head *bh2 = lru->bhs[in]; 1284 struct buffer_head *bh2 =
1285 __this_cpu_read(bh_lrus.bhs[in]);
1287 1286
1288 if (bh2 == bh) { 1287 if (bh2 == bh) {
1289 __brelse(bh2); 1288 __brelse(bh2);
@@ -1298,7 +1297,7 @@ static void bh_lru_install(struct buffer_head *bh)
1298 } 1297 }
1299 while (out < BH_LRU_SIZE) 1298 while (out < BH_LRU_SIZE)
1300 bhs[out++] = NULL; 1299 bhs[out++] = NULL;
1301 memcpy(lru->bhs, bhs, sizeof(bhs)); 1300 memcpy(__this_cpu_ptr(&bh_lrus.bhs), bhs, sizeof(bhs));
1302 } 1301 }
1303 bh_lru_unlock(); 1302 bh_lru_unlock();
1304 1303
@@ -1313,23 +1312,22 @@ static struct buffer_head *
1313lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) 1312lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
1314{ 1313{
1315 struct buffer_head *ret = NULL; 1314 struct buffer_head *ret = NULL;
1316 struct bh_lru *lru;
1317 unsigned int i; 1315 unsigned int i;
1318 1316
1319 check_irqs_on(); 1317 check_irqs_on();
1320 bh_lru_lock(); 1318 bh_lru_lock();
1321 lru = &__get_cpu_var(bh_lrus);
1322 for (i = 0; i < BH_LRU_SIZE; i++) { 1319 for (i = 0; i < BH_LRU_SIZE; i++) {
1323 struct buffer_head *bh = lru->bhs[i]; 1320 struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]);
1324 1321
1325 if (bh && bh->b_bdev == bdev && 1322 if (bh && bh->b_bdev == bdev &&
1326 bh->b_blocknr == block && bh->b_size == size) { 1323 bh->b_blocknr == block && bh->b_size == size) {
1327 if (i) { 1324 if (i) {
1328 while (i) { 1325 while (i) {
1329 lru->bhs[i] = lru->bhs[i - 1]; 1326 __this_cpu_write(bh_lrus.bhs[i],
1327 __this_cpu_read(bh_lrus.bhs[i - 1]));
1330 i--; 1328 i--;
1331 } 1329 }
1332 lru->bhs[0] = bh; 1330 __this_cpu_write(bh_lrus.bhs[0], bh);
1333 } 1331 }
1334 get_bh(bh); 1332 get_bh(bh);
1335 ret = bh; 1333 ret = bh;
@@ -3205,20 +3203,21 @@ static void recalc_bh_state(void)
3205 3203
3206 if (__get_cpu_var(bh_accounting).ratelimit++ < 4096) 3204 if (__get_cpu_var(bh_accounting).ratelimit++ < 4096)
3207 return; 3205 return;
3208 __get_cpu_var(bh_accounting).ratelimit = 0; 3206 __this_cpu_write(bh_accounting.ratelimit, 0);
3209 for_each_online_cpu(i) 3207 for_each_online_cpu(i)
3210 tot += per_cpu(bh_accounting, i).nr; 3208 tot += per_cpu(bh_accounting, i).nr;
3211 buffer_heads_over_limit = (tot > max_buffer_heads); 3209 buffer_heads_over_limit = (tot > max_buffer_heads);
3212} 3210}
3213 3211
3214struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) 3212struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
3215{ 3213{
3216 struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags); 3214 struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
3217 if (ret) { 3215 if (ret) {
3218 INIT_LIST_HEAD(&ret->b_assoc_buffers); 3216 INIT_LIST_HEAD(&ret->b_assoc_buffers);
3219 get_cpu_var(bh_accounting).nr++; 3217 preempt_disable();
3218 __this_cpu_inc(bh_accounting.nr);
3220 recalc_bh_state(); 3219 recalc_bh_state();
3221 put_cpu_var(bh_accounting); 3220 preempt_enable();
3222 } 3221 }
3223 return ret; 3222 return ret;
3224} 3223}
@@ -3228,9 +3227,10 @@ void free_buffer_head(struct buffer_head *bh)
3228{ 3227{
3229 BUG_ON(!list_empty(&bh->b_assoc_buffers)); 3228 BUG_ON(!list_empty(&bh->b_assoc_buffers));
3230 kmem_cache_free(bh_cachep, bh); 3229 kmem_cache_free(bh_cachep, bh);
3231 get_cpu_var(bh_accounting).nr--; 3230 preempt_disable();
3231 __this_cpu_dec(bh_accounting.nr);
3232 recalc_bh_state(); 3232 recalc_bh_state();
3233 put_cpu_var(bh_accounting); 3233 preempt_enable();
3234} 3234}
3235EXPORT_SYMBOL(free_buffer_head); 3235EXPORT_SYMBOL(free_buffer_head);
3236 3236
@@ -3243,9 +3243,8 @@ static void buffer_exit_cpu(int cpu)
3243 brelse(b->bhs[i]); 3243 brelse(b->bhs[i]);
3244 b->bhs[i] = NULL; 3244 b->bhs[i] = NULL;
3245 } 3245 }
3246 get_cpu_var(bh_accounting).nr += per_cpu(bh_accounting, cpu).nr; 3246 this_cpu_add(bh_accounting.nr, per_cpu(bh_accounting, cpu).nr);
3247 per_cpu(bh_accounting, cpu).nr = 0; 3247 per_cpu(bh_accounting, cpu).nr = 0;
3248 put_cpu_var(bh_accounting);
3249} 3248}
3250 3249
3251static int buffer_cpu_notify(struct notifier_block *self, 3250static int buffer_cpu_notify(struct notifier_block *self,