diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-04-18 08:53:18 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-04-18 08:53:33 -0400 |
commit | 6ddafdaab3f809b110ada253d2f2d4910ebd3ac5 (patch) | |
tree | 366bb7513511a05b6e11ab89bfe3b2dbd1d62a03 /fs/ext4/inode.c | |
parent | 3905c54f2bd2c6f937f87307987ca072eabc3e7b (diff) | |
parent | bd8e7dded88a3e1c085c333f19ff31387616f71a (diff) |
Merge branch 'sched/locking' into sched/core
Merge reason: the rq locking changes are stable,
propagate them into the .40 queue.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ad8e303c0d29..f2fa5e8a582c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2502,6 +2502,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
2502 | * for partial write. | 2502 | * for partial write. |
2503 | */ | 2503 | */ |
2504 | set_buffer_new(bh); | 2504 | set_buffer_new(bh); |
2505 | set_buffer_mapped(bh); | ||
2505 | } | 2506 | } |
2506 | return 0; | 2507 | return 0; |
2507 | } | 2508 | } |
@@ -4429,8 +4430,8 @@ void ext4_truncate(struct inode *inode) | |||
4429 | Indirect chain[4]; | 4430 | Indirect chain[4]; |
4430 | Indirect *partial; | 4431 | Indirect *partial; |
4431 | __le32 nr = 0; | 4432 | __le32 nr = 0; |
4432 | int n; | 4433 | int n = 0; |
4433 | ext4_lblk_t last_block; | 4434 | ext4_lblk_t last_block, max_block; |
4434 | unsigned blocksize = inode->i_sb->s_blocksize; | 4435 | unsigned blocksize = inode->i_sb->s_blocksize; |
4435 | 4436 | ||
4436 | trace_ext4_truncate_enter(inode); | 4437 | trace_ext4_truncate_enter(inode); |
@@ -4455,14 +4456,18 @@ void ext4_truncate(struct inode *inode) | |||
4455 | 4456 | ||
4456 | last_block = (inode->i_size + blocksize-1) | 4457 | last_block = (inode->i_size + blocksize-1) |
4457 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); | 4458 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); |
4459 | max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1) | ||
4460 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); | ||
4458 | 4461 | ||
4459 | if (inode->i_size & (blocksize - 1)) | 4462 | if (inode->i_size & (blocksize - 1)) |
4460 | if (ext4_block_truncate_page(handle, mapping, inode->i_size)) | 4463 | if (ext4_block_truncate_page(handle, mapping, inode->i_size)) |
4461 | goto out_stop; | 4464 | goto out_stop; |
4462 | 4465 | ||
4463 | n = ext4_block_to_path(inode, last_block, offsets, NULL); | 4466 | if (last_block != max_block) { |
4464 | if (n == 0) | 4467 | n = ext4_block_to_path(inode, last_block, offsets, NULL); |
4465 | goto out_stop; /* error */ | 4468 | if (n == 0) |
4469 | goto out_stop; /* error */ | ||
4470 | } | ||
4466 | 4471 | ||
4467 | /* | 4472 | /* |
4468 | * OK. This truncate is going to happen. We add the inode to the | 4473 | * OK. This truncate is going to happen. We add the inode to the |
@@ -4493,7 +4498,13 @@ void ext4_truncate(struct inode *inode) | |||
4493 | */ | 4498 | */ |
4494 | ei->i_disksize = inode->i_size; | 4499 | ei->i_disksize = inode->i_size; |
4495 | 4500 | ||
4496 | if (n == 1) { /* direct blocks */ | 4501 | if (last_block == max_block) { |
4502 | /* | ||
4503 | * It is unnecessary to free any data blocks if last_block is | ||
4504 | * equal to the indirect block limit. | ||
4505 | */ | ||
4506 | goto out_unlock; | ||
4507 | } else if (n == 1) { /* direct blocks */ | ||
4497 | ext4_free_data(handle, inode, NULL, i_data+offsets[0], | 4508 | ext4_free_data(handle, inode, NULL, i_data+offsets[0], |
4498 | i_data + EXT4_NDIR_BLOCKS); | 4509 | i_data + EXT4_NDIR_BLOCKS); |
4499 | goto do_indirects; | 4510 | goto do_indirects; |
@@ -4553,6 +4564,7 @@ do_indirects: | |||
4553 | ; | 4564 | ; |
4554 | } | 4565 | } |
4555 | 4566 | ||
4567 | out_unlock: | ||
4556 | up_write(&ei->i_data_sem); | 4568 | up_write(&ei->i_data_sem); |
4557 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | 4569 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); |
4558 | ext4_mark_inode_dirty(handle, inode); | 4570 | ext4_mark_inode_dirty(handle, inode); |
@@ -5398,13 +5410,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, | |||
5398 | /* if nrblocks are contiguous */ | 5410 | /* if nrblocks are contiguous */ |
5399 | if (chunk) { | 5411 | if (chunk) { |
5400 | /* | 5412 | /* |
5401 | * With N contiguous data blocks, it need at most | 5413 | * With N contiguous data blocks, we need at most |
5402 | * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks | 5414 | * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks, |
5403 | * 2 dindirect blocks | 5415 | * 2 dindirect blocks, and 1 tindirect block |
5404 | * 1 tindirect block | ||
5405 | */ | 5416 | */ |
5406 | indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); | 5417 | return DIV_ROUND_UP(nrblocks, |
5407 | return indirects + 3; | 5418 | EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4; |
5408 | } | 5419 | } |
5409 | /* | 5420 | /* |
5410 | * if nrblocks are not contiguous, worse case, each block touch | 5421 | * if nrblocks are not contiguous, worse case, each block touch |