diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 8 | ||||
-rw-r--r-- | fs/ext4/inode.c | 131 |
3 files changed, 108 insertions, 34 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6c7924d9e358..38e661b0ea88 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1072,6 +1072,7 @@ extern void ext4_set_inode_flags(struct inode *); | |||
1072 | extern void ext4_get_inode_flags(struct ext4_inode_info *); | 1072 | extern void ext4_get_inode_flags(struct ext4_inode_info *); |
1073 | extern void ext4_set_aops(struct inode *inode); | 1073 | extern void ext4_set_aops(struct inode *inode); |
1074 | extern int ext4_writepage_trans_blocks(struct inode *); | 1074 | extern int ext4_writepage_trans_blocks(struct inode *); |
1075 | extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks); | ||
1075 | extern int ext4_block_truncate_page(handle_t *handle, | 1076 | extern int ext4_block_truncate_page(handle_t *handle, |
1076 | struct address_space *mapping, loff_t from); | 1077 | struct address_space *mapping, loff_t from); |
1077 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); | 1078 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); |
@@ -1227,6 +1228,8 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations; | |||
1227 | /* extents.c */ | 1228 | /* extents.c */ |
1228 | extern int ext4_ext_tree_init(handle_t *handle, struct inode *); | 1229 | extern int ext4_ext_tree_init(handle_t *handle, struct inode *); |
1229 | extern int ext4_ext_writepage_trans_blocks(struct inode *, int); | 1230 | extern int ext4_ext_writepage_trans_blocks(struct inode *, int); |
1231 | extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, | ||
1232 | int chunk); | ||
1230 | extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | 1233 | extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, |
1231 | ext4_lblk_t iblock, | 1234 | ext4_lblk_t iblock, |
1232 | unsigned long max_blocks, struct buffer_head *bh_result, | 1235 | unsigned long max_blocks, struct buffer_head *bh_result, |
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index eb8bc3afe6e9..b455c685a98b 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -51,6 +51,14 @@ | |||
51 | EXT4_XATTR_TRANS_BLOCKS - 2 + \ | 51 | EXT4_XATTR_TRANS_BLOCKS - 2 + \ |
52 | 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) | 52 | 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) |
53 | 53 | ||
54 | /* | ||
55 | * Define the number of metadata blocks we need to account to modify data. | ||
56 | * | ||
57 | * This include super block, inode block, quota blocks and xattr blocks | ||
58 | */ | ||
59 | #define EXT4_META_TRANS_BLOCKS(sb) (EXT4_XATTR_TRANS_BLOCKS + \ | ||
60 | 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) | ||
61 | |||
54 | /* Delete operations potentially hit one directory's namespace plus an | 62 | /* Delete operations potentially hit one directory's namespace plus an |
55 | * entire inode, plus arbitrary amounts of bitmap/indirection data. Be | 63 | * entire inode, plus arbitrary amounts of bitmap/indirection data. Be |
56 | * generous. We can grow the delete transaction later if necessary. */ | 64 | * generous. We can grow the delete transaction later if necessary. */ |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5e17d5f22a7e..a27129065144 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4354,56 +4354,119 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
4354 | return 0; | 4354 | return 0; |
4355 | } | 4355 | } |
4356 | 4356 | ||
4357 | static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, | ||
4358 | int chunk) | ||
4359 | { | ||
4360 | int indirects; | ||
4361 | |||
4362 | /* if nrblocks are contiguous */ | ||
4363 | if (chunk) { | ||
4364 | /* | ||
4365 | * With N contiguous data blocks, it need at most | ||
4366 | * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks | ||
4367 | * 2 dindirect blocks | ||
4368 | * 1 tindirect block | ||
4369 | */ | ||
4370 | indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); | ||
4371 | return indirects + 3; | ||
4372 | } | ||
4373 | /* | ||
4374 | * if nrblocks are not contiguous, worse case, each block touch | ||
4375 | * a indirect block, and each indirect block touch a double indirect | ||
4376 | * block, plus a triple indirect block | ||
4377 | */ | ||
4378 | indirects = nrblocks * 2 + 1; | ||
4379 | return indirects; | ||
4380 | } | ||
4381 | |||
4382 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) | ||
4383 | { | ||
4384 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) | ||
4385 | return ext4_indirect_trans_blocks(inode, nrblocks, 0); | ||
4386 | return ext4_ext_index_trans_blocks(inode, nrblocks, 0); | ||
4387 | } | ||
4357 | /* | 4388 | /* |
4358 | * How many blocks doth make a writepage()? | 4389 | * Account for index blocks, block groups bitmaps and block group |
4390 | * descriptor blocks if modify datablocks and index blocks | ||
4391 | * worse case, the indexs blocks spread over different block groups | ||
4359 | * | 4392 | * |
4360 | * With N blocks per page, it may be: | 4393 | * If datablocks are discontiguous, they are possible to spread over |
4361 | * N data blocks | 4394 | * different block groups too. If they are contiugous, with flexbg, |
4362 | * 2 indirect block | 4395 | * they could still across block group boundary. |
4363 | * 2 dindirect | ||
4364 | * 1 tindirect | ||
4365 | * N+5 bitmap blocks (from the above) | ||
4366 | * N+5 group descriptor summary blocks | ||
4367 | * 1 inode block | ||
4368 | * 1 superblock. | ||
4369 | * 2 * EXT4_SINGLEDATA_TRANS_BLOCKS for the quote files | ||
4370 | * | 4396 | * |
4371 | * 3 * (N + 5) + 2 + 2 * EXT4_SINGLEDATA_TRANS_BLOCKS | 4397 | * Also account for superblock, inode, quota and xattr blocks |
4398 | */ | ||
4399 | int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) | ||
4400 | { | ||
4401 | int groups, gdpblocks; | ||
4402 | int idxblocks; | ||
4403 | int ret = 0; | ||
4404 | |||
4405 | /* | ||
4406 | * How many index blocks need to touch to modify nrblocks? | ||
4407 | * The "Chunk" flag indicating whether the nrblocks is | ||
4408 | * physically contiguous on disk | ||
4409 | * | ||
4410 | * For Direct IO and fallocate, they calls get_block to allocate | ||
4411 | * one single extent at a time, so they could set the "Chunk" flag | ||
4412 | */ | ||
4413 | idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk); | ||
4414 | |||
4415 | ret = idxblocks; | ||
4416 | |||
4417 | /* | ||
4418 | * Now let's see how many group bitmaps and group descriptors need | ||
4419 | * to account | ||
4420 | */ | ||
4421 | groups = idxblocks; | ||
4422 | if (chunk) | ||
4423 | groups += 1; | ||
4424 | else | ||
4425 | groups += nrblocks; | ||
4426 | |||
4427 | gdpblocks = groups; | ||
4428 | if (groups > EXT4_SB(inode->i_sb)->s_groups_count) | ||
4429 | groups = EXT4_SB(inode->i_sb)->s_groups_count; | ||
4430 | if (groups > EXT4_SB(inode->i_sb)->s_gdb_count) | ||
4431 | gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count; | ||
4432 | |||
4433 | /* bitmaps and block group descriptor blocks */ | ||
4434 | ret += groups + gdpblocks; | ||
4435 | |||
4436 | /* Blocks for super block, inode, quota and xattr blocks */ | ||
4437 | ret += EXT4_META_TRANS_BLOCKS(inode->i_sb); | ||
4438 | |||
4439 | return ret; | ||
4440 | } | ||
4441 | |||
4442 | /* | ||
4443 | * Calulate the total number of credits to reserve to fit | ||
4444 | * the modification of a single pages into a single transaction | ||
4372 | * | 4445 | * |
4373 | * With ordered or writeback data it's the same, less the N data blocks. | 4446 | * This could be called via ext4_write_begin() or later |
4447 | * ext4_da_writepages() in delalyed allocation case. | ||
4374 | * | 4448 | * |
4375 | * If the inode's direct blocks can hold an integral number of pages then a | 4449 | * In both case it's possible that we could allocating multiple |
4376 | * page cannot straddle two indirect blocks, and we can only touch one indirect | 4450 | * chunks of blocks. We need to consider the worse case, when |
4377 | * and dindirect block, and the "5" above becomes "3". | 4451 | * one new block per extent. |
4378 | * | 4452 | * |
4379 | * This still overestimates under most circumstances. If we were to pass the | 4453 | * For Direct IO and fallocate, the journal credits reservation |
4380 | * start and end offsets in here as well we could do block_to_path() on each | 4454 | * is based on one single extent allocation, so they could use |
4381 | * block and work out the exact number of indirects which are touched. Pah. | 4455 | * EXT4_DATA_TRANS_BLOCKS to get the needed credit to log a single |
4456 | * chunk of allocation needs. | ||
4382 | */ | 4457 | */ |
4383 | |||
4384 | int ext4_writepage_trans_blocks(struct inode *inode) | 4458 | int ext4_writepage_trans_blocks(struct inode *inode) |
4385 | { | 4459 | { |
4386 | int bpp = ext4_journal_blocks_per_page(inode); | 4460 | int bpp = ext4_journal_blocks_per_page(inode); |
4387 | int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3; | ||
4388 | int ret; | 4461 | int ret; |
4389 | 4462 | ||
4390 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | 4463 | ret = ext4_meta_trans_blocks(inode, bpp, 0); |
4391 | return ext4_ext_writepage_trans_blocks(inode, bpp); | ||
4392 | 4464 | ||
4465 | /* Account for data blocks for journalled mode */ | ||
4393 | if (ext4_should_journal_data(inode)) | 4466 | if (ext4_should_journal_data(inode)) |
4394 | ret = 3 * (bpp + indirects) + 2; | 4467 | ret += bpp; |
4395 | else | ||
4396 | ret = 2 * (bpp + indirects) + 2; | ||
4397 | |||
4398 | #ifdef CONFIG_QUOTA | ||
4399 | /* We know that structure was already allocated during DQUOT_INIT so | ||
4400 | * we will be updating only the data blocks + inodes */ | ||
4401 | ret += 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); | ||
4402 | #endif | ||
4403 | |||
4404 | return ret; | 4468 | return ret; |
4405 | } | 4469 | } |
4406 | |||
4407 | /* | 4470 | /* |
4408 | * The caller must have previously called ext4_reserve_inode_write(). | 4471 | * The caller must have previously called ext4_reserve_inode_write(). |
4409 | * Give this, we know that the caller already has write access to iloc->bh. | 4472 | * Give this, we know that the caller already has write access to iloc->bh. |