diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-05 19:24:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-05 19:24:54 -0400 |
commit | 1c4c7159ed2468f3ac4ce5a7f08d79663d381a93 (patch) | |
tree | bca0b61fc4a04711e0322dd9eb4a2f3c55ddf4c5 | |
parent | d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff) | |
parent | 7444a072c387a93ebee7066e8aee776954ab0e41 (diff) |
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bugfixes from Ted Ts'o:
"Bug fixes (all for stable kernels) for ext4:
- address corner cases for indirect blocks->extent migration
- fix reserved block accounting invalidate_page when
page_size != block_size (i.e., ppc or 1k block size file systems)
- fix deadlocks when a memcg is under heavy memory pressure
- fix fencepost error in lazytime optimization"
* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: replace open coded nofail allocation in ext4_free_blocks()
ext4: correctly migrate a file with a hole at the beginning
ext4: be more strict when migrating to non-extent based file
ext4: fix reservation release on invalidatepage for delalloc fs
ext4: avoid deadlocks in the writeback path by using sb_getblk_gfp
bufferhead: Add _gfp version for sb_getblk()
ext4: fix fencepost error in lazytime optimization
-rw-r--r-- | fs/ext4/extents.c | 6 | ||||
-rw-r--r-- | fs/ext4/inode.c | 22 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 16 | ||||
-rw-r--r-- | fs/ext4/migrate.c | 17 | ||||
-rw-r--r-- | include/linux/buffer_head.h | 7 |
5 files changed, 47 insertions, 21 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index aadb72828834..2553aa8b608d 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -504,7 +504,7 @@ __read_extent_tree_block(const char *function, unsigned int line, | |||
504 | struct buffer_head *bh; | 504 | struct buffer_head *bh; |
505 | int err; | 505 | int err; |
506 | 506 | ||
507 | bh = sb_getblk(inode->i_sb, pblk); | 507 | bh = sb_getblk_gfp(inode->i_sb, pblk, __GFP_MOVABLE | GFP_NOFS); |
508 | if (unlikely(!bh)) | 508 | if (unlikely(!bh)) |
509 | return ERR_PTR(-ENOMEM); | 509 | return ERR_PTR(-ENOMEM); |
510 | 510 | ||
@@ -1089,7 +1089,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
1089 | err = -EIO; | 1089 | err = -EIO; |
1090 | goto cleanup; | 1090 | goto cleanup; |
1091 | } | 1091 | } |
1092 | bh = sb_getblk(inode->i_sb, newblock); | 1092 | bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); |
1093 | if (unlikely(!bh)) { | 1093 | if (unlikely(!bh)) { |
1094 | err = -ENOMEM; | 1094 | err = -ENOMEM; |
1095 | goto cleanup; | 1095 | goto cleanup; |
@@ -1283,7 +1283,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1283 | if (newblock == 0) | 1283 | if (newblock == 0) |
1284 | return err; | 1284 | return err; |
1285 | 1285 | ||
1286 | bh = sb_getblk(inode->i_sb, newblock); | 1286 | bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); |
1287 | if (unlikely(!bh)) | 1287 | if (unlikely(!bh)) |
1288 | return -ENOMEM; | 1288 | return -ENOMEM; |
1289 | lock_buffer(bh); | 1289 | lock_buffer(bh); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 41f8e55afcd1..cecf9aa10811 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1323,7 +1323,7 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
1323 | unsigned int offset, | 1323 | unsigned int offset, |
1324 | unsigned int length) | 1324 | unsigned int length) |
1325 | { | 1325 | { |
1326 | int to_release = 0; | 1326 | int to_release = 0, contiguous_blks = 0; |
1327 | struct buffer_head *head, *bh; | 1327 | struct buffer_head *head, *bh; |
1328 | unsigned int curr_off = 0; | 1328 | unsigned int curr_off = 0; |
1329 | struct inode *inode = page->mapping->host; | 1329 | struct inode *inode = page->mapping->host; |
@@ -1344,14 +1344,23 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
1344 | 1344 | ||
1345 | if ((offset <= curr_off) && (buffer_delay(bh))) { | 1345 | if ((offset <= curr_off) && (buffer_delay(bh))) { |
1346 | to_release++; | 1346 | to_release++; |
1347 | contiguous_blks++; | ||
1347 | clear_buffer_delay(bh); | 1348 | clear_buffer_delay(bh); |
1349 | } else if (contiguous_blks) { | ||
1350 | lblk = page->index << | ||
1351 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
1352 | lblk += (curr_off >> inode->i_blkbits) - | ||
1353 | contiguous_blks; | ||
1354 | ext4_es_remove_extent(inode, lblk, contiguous_blks); | ||
1355 | contiguous_blks = 0; | ||
1348 | } | 1356 | } |
1349 | curr_off = next_off; | 1357 | curr_off = next_off; |
1350 | } while ((bh = bh->b_this_page) != head); | 1358 | } while ((bh = bh->b_this_page) != head); |
1351 | 1359 | ||
1352 | if (to_release) { | 1360 | if (contiguous_blks) { |
1353 | lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 1361 | lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); |
1354 | ext4_es_remove_extent(inode, lblk, to_release); | 1362 | lblk += (curr_off >> inode->i_blkbits) - contiguous_blks; |
1363 | ext4_es_remove_extent(inode, lblk, contiguous_blks); | ||
1355 | } | 1364 | } |
1356 | 1365 | ||
1357 | /* If we have released all the blocks belonging to a cluster, then we | 1366 | /* If we have released all the blocks belonging to a cluster, then we |
@@ -4344,7 +4353,12 @@ static void ext4_update_other_inodes_time(struct super_block *sb, | |||
4344 | int inode_size = EXT4_INODE_SIZE(sb); | 4353 | int inode_size = EXT4_INODE_SIZE(sb); |
4345 | 4354 | ||
4346 | oi.orig_ino = orig_ino; | 4355 | oi.orig_ino = orig_ino; |
4347 | ino = (orig_ino & ~(inodes_per_block - 1)) + 1; | 4356 | /* |
4357 | * Calculate the first inode in the inode table block. Inode | ||
4358 | * numbers are one-based. That is, the first inode in a block | ||
4359 | * (assuming 4k blocks and 256 byte inodes) is (n*16 + 1). | ||
4360 | */ | ||
4361 | ino = ((orig_ino - 1) & ~(inodes_per_block - 1)) + 1; | ||
4348 | for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { | 4362 | for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { |
4349 | if (ino == orig_ino) | 4363 | if (ino == orig_ino) |
4350 | continue; | 4364 | continue; |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index f6aedf88da43..34b610ea5030 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -4816,18 +4816,12 @@ do_more: | |||
4816 | /* | 4816 | /* |
4817 | * blocks being freed are metadata. these blocks shouldn't | 4817 | * blocks being freed are metadata. these blocks shouldn't |
4818 | * be used until this transaction is committed | 4818 | * be used until this transaction is committed |
4819 | * | ||
4820 | * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed | ||
4821 | * to fail. | ||
4819 | */ | 4822 | */ |
4820 | retry: | 4823 | new_entry = kmem_cache_alloc(ext4_free_data_cachep, |
4821 | new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); | 4824 | GFP_NOFS|__GFP_NOFAIL); |
4822 | if (!new_entry) { | ||
4823 | /* | ||
4824 | * We use a retry loop because | ||
4825 | * ext4_free_blocks() is not allowed to fail. | ||
4826 | */ | ||
4827 | cond_resched(); | ||
4828 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
4829 | goto retry; | ||
4830 | } | ||
4831 | new_entry->efd_start_cluster = bit; | 4825 | new_entry->efd_start_cluster = bit; |
4832 | new_entry->efd_group = block_group; | 4826 | new_entry->efd_group = block_group; |
4833 | new_entry->efd_count = count_clusters; | 4827 | new_entry->efd_count = count_clusters; |
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b52374e42102..6163ad21cb0e 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
@@ -620,6 +620,7 @@ int ext4_ind_migrate(struct inode *inode) | |||
620 | struct ext4_inode_info *ei = EXT4_I(inode); | 620 | struct ext4_inode_info *ei = EXT4_I(inode); |
621 | struct ext4_extent *ex; | 621 | struct ext4_extent *ex; |
622 | unsigned int i, len; | 622 | unsigned int i, len; |
623 | ext4_lblk_t start, end; | ||
623 | ext4_fsblk_t blk; | 624 | ext4_fsblk_t blk; |
624 | handle_t *handle; | 625 | handle_t *handle; |
625 | int ret; | 626 | int ret; |
@@ -633,6 +634,14 @@ int ext4_ind_migrate(struct inode *inode) | |||
633 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) | 634 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) |
634 | return -EOPNOTSUPP; | 635 | return -EOPNOTSUPP; |
635 | 636 | ||
637 | /* | ||
638 | * In order to get correct extent info, force all delayed allocation | ||
639 | * blocks to be allocated, otherwise delayed allocation blocks may not | ||
640 | * be reflected and bypass the checks on extent header. | ||
641 | */ | ||
642 | if (test_opt(inode->i_sb, DELALLOC)) | ||
643 | ext4_alloc_da_blocks(inode); | ||
644 | |||
636 | handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); | 645 | handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); |
637 | if (IS_ERR(handle)) | 646 | if (IS_ERR(handle)) |
638 | return PTR_ERR(handle); | 647 | return PTR_ERR(handle); |
@@ -650,11 +659,13 @@ int ext4_ind_migrate(struct inode *inode) | |||
650 | goto errout; | 659 | goto errout; |
651 | } | 660 | } |
652 | if (eh->eh_entries == 0) | 661 | if (eh->eh_entries == 0) |
653 | blk = len = 0; | 662 | blk = len = start = end = 0; |
654 | else { | 663 | else { |
655 | len = le16_to_cpu(ex->ee_len); | 664 | len = le16_to_cpu(ex->ee_len); |
656 | blk = ext4_ext_pblock(ex); | 665 | blk = ext4_ext_pblock(ex); |
657 | if (len > EXT4_NDIR_BLOCKS) { | 666 | start = le32_to_cpu(ex->ee_block); |
667 | end = start + len - 1; | ||
668 | if (end >= EXT4_NDIR_BLOCKS) { | ||
658 | ret = -EOPNOTSUPP; | 669 | ret = -EOPNOTSUPP; |
659 | goto errout; | 670 | goto errout; |
660 | } | 671 | } |
@@ -662,7 +673,7 @@ int ext4_ind_migrate(struct inode *inode) | |||
662 | 673 | ||
663 | ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); | 674 | ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); |
664 | memset(ei->i_data, 0, sizeof(ei->i_data)); | 675 | memset(ei->i_data, 0, sizeof(ei->i_data)); |
665 | for (i=0; i < len; i++) | 676 | for (i = start; i <= end; i++) |
666 | ei->i_data[i] = cpu_to_le32(blk++); | 677 | ei->i_data[i] = cpu_to_le32(blk++); |
667 | ext4_mark_inode_dirty(handle, inode); | 678 | ext4_mark_inode_dirty(handle, inode); |
668 | errout: | 679 | errout: |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 73b45225a7ca..e6797ded700e 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
@@ -317,6 +317,13 @@ sb_getblk(struct super_block *sb, sector_t block) | |||
317 | return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE); | 317 | return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE); |
318 | } | 318 | } |
319 | 319 | ||
320 | |||
321 | static inline struct buffer_head * | ||
322 | sb_getblk_gfp(struct super_block *sb, sector_t block, gfp_t gfp) | ||
323 | { | ||
324 | return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, gfp); | ||
325 | } | ||
326 | |||
320 | static inline struct buffer_head * | 327 | static inline struct buffer_head * |
321 | sb_find_get_block(struct super_block *sb, sector_t block) | 328 | sb_find_get_block(struct super_block *sb, sector_t block) |
322 | { | 329 | { |