Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 bugfixes from Ted Ts'o:
"Fixes for 3.11-rc2, sent at 5pm, in the professoinal style. :-)"

I'm not sure I like this new level of "professionalism".
9-5, people, 9-5.

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: call ext4_es_lru_add() after handling cache miss
ext4: yield during large unlinks
ext4: make the extent_status code more robust against ENOMEM failures
ext4: simplify calculation of blocks to free on error
ext4: fix error handling in ext4_ext_truncate()

+60 -21
+19 -4
fs/ext4/extents.c
··· 2835 2835 err = -EIO; 2836 2836 break; 2837 2837 } 2838 + /* Yield here to deal with large extent trees. 2839 + * Should be a no-op if we did IO above. */ 2840 + cond_resched(); 2838 2841 if (WARN_ON(i + 1 > depth)) { 2839 2842 err = -EIO; 2840 2843 break; ··· 4264 4261 /* not a good idea to call discard here directly, 4265 4262 * but otherwise we'd need to call it every free() */ 4266 4263 ext4_discard_preallocations(inode); 4267 - ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex), 4268 - ext4_ext_get_actual_len(&newex), fb_flags); 4264 + ext4_free_blocks(handle, inode, NULL, newblock, 4265 + EXT4_C2B(sbi, allocated_clusters), fb_flags); 4269 4266 goto out2; 4270 4267 } 4271 4268 ··· 4385 4382 } 4386 4383 4387 4384 out3: 4388 - trace_ext4_ext_map_blocks_exit(inode, flags, map, err ? err : allocated); 4389 - 4385 + trace_ext4_ext_map_blocks_exit(inode, flags, map, 4386 + err ? err : allocated); 4387 + ext4_es_lru_add(inode); 4390 4388 return err ? err : allocated; 4391 4389 } 4392 4390 ··· 4409 4405 4410 4406 last_block = (inode->i_size + sb->s_blocksize - 1) 4411 4407 >> EXT4_BLOCK_SIZE_BITS(sb); 4408 + retry: 4412 4409 err = ext4_es_remove_extent(inode, last_block, 4413 4410 EXT_MAX_BLOCKS - last_block); 4411 + if (err == ENOMEM) { 4412 + cond_resched(); 4413 + congestion_wait(BLK_RW_ASYNC, HZ/50); 4414 + goto retry; 4415 + } 4416 + if (err) { 4417 + ext4_std_error(inode->i_sb, err); 4418 + return; 4419 + } 4414 4420 err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); 4421 + ext4_std_error(inode->i_sb, err); 4415 4422 } 4416 4423 4417 4424 static void ext4_falloc_update_inode(struct inode *inode,
+39 -12
fs/ext4/extents_status.c
··· 148 148 ext4_lblk_t end); 149 149 static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, 150 150 int nr_to_scan); 151 + static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, 152 + struct ext4_inode_info *locked_ei); 151 153 152 154 int __init ext4_init_es(void) 153 155 { ··· 667 665 err = __es_remove_extent(inode, lblk, end); 668 666 if (err != 0) 669 667 goto error; 668 + retry: 670 669 err = __es_insert_extent(inode, &newes); 670 + if (err == -ENOMEM && __ext4_es_shrink(EXT4_SB(inode->i_sb), 1, 671 + EXT4_I(inode))) 672 + goto retry; 673 + if (err == -ENOMEM && !ext4_es_is_delayed(&newes)) 674 + err = 0; 671 675 672 676 error: 673 677 write_unlock(&EXT4_I(inode)->i_es_lock); ··· 752 744 struct extent_status orig_es; 753 745 ext4_lblk_t len1, len2; 754 746 ext4_fsblk_t block; 755 - int err = 0; 747 + int err; 756 748 749 + retry: 750 + err = 0; 757 751 es = __es_tree_search(&tree->root, lblk); 758 752 if (!es) 759 753 goto out; ··· 790 780 if (err) { 791 781 es->es_lblk = orig_es.es_lblk; 792 782 es->es_len = orig_es.es_len; 783 + if ((err == -ENOMEM) && 784 + __ext4_es_shrink(EXT4_SB(inode->i_sb), 1, 785 + EXT4_I(inode))) 786 + goto retry; 793 787 goto out; 794 788 } 795 789 } else { ··· 903 889 return -1; 904 890 } 905 891 906 - static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) 892 + static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, 893 + struct ext4_inode_info *locked_ei) 907 894 { 908 - struct ext4_sb_info *sbi = container_of(shrink, 909 - struct ext4_sb_info, s_es_shrinker); 910 895 struct ext4_inode_info *ei; 911 896 struct list_head *cur, *tmp; 912 897 LIST_HEAD(skiped); 913 - int nr_to_scan = sc->nr_to_scan; 914 898 int ret, nr_shrunk = 0; 915 - 916 - ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); 917 - trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret); 918 - 919 - if (!nr_to_scan) 920 - return ret; 921 899 922 900 spin_lock(&sbi->s_es_lru_lock); 923 901 ··· 939 933 continue; 940 934 } 941 935 942 - if (ei->i_es_lru_nr == 0) 936 + if (ei->i_es_lru_nr == 0 || ei == locked_ei) 943 937 continue; 944 938 945 939 write_lock(&ei->i_es_lock); ··· 957 951 /* Move the newer inodes into the tail of the LRU list. */ 958 952 list_splice_tail(&skiped, &sbi->s_es_lru); 959 953 spin_unlock(&sbi->s_es_lru_lock); 954 + 955 + if (locked_ei && nr_shrunk == 0) 956 + nr_shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan); 957 + 958 + return nr_shrunk; 959 + } 960 + 961 + static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) 962 + { 963 + struct ext4_sb_info *sbi = container_of(shrink, 964 + struct ext4_sb_info, s_es_shrinker); 965 + int nr_to_scan = sc->nr_to_scan; 966 + int ret, nr_shrunk; 967 + 968 + ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); 969 + trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret); 970 + 971 + if (!nr_to_scan) 972 + return ret; 973 + 974 + nr_shrunk = __ext4_es_shrink(sbi, nr_to_scan, NULL); 960 975 961 976 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); 962 977 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
+2 -5
fs/ext4/inode.c
··· 514 514 "logical block %lu\n", inode->i_ino, flags, map->m_len, 515 515 (unsigned long) map->m_lblk); 516 516 517 - ext4_es_lru_add(inode); 518 - 519 517 /* Lookup extent status tree firstly */ 520 518 if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) { 519 + ext4_es_lru_add(inode); 521 520 if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) { 522 521 map->m_pblk = ext4_es_pblock(&es) + 523 522 map->m_lblk - es.es_lblk; ··· 1528 1529 "logical block %lu\n", inode->i_ino, map->m_len, 1529 1530 (unsigned long) map->m_lblk); 1530 1531 1531 - ext4_es_lru_add(inode); 1532 - 1533 1532 /* Lookup extent status tree firstly */ 1534 1533 if (ext4_es_lookup_extent(inode, iblock, &es)) { 1535 - 1534 + ext4_es_lru_add(inode); 1536 1535 if (ext4_es_is_hole(&es)) { 1537 1536 retval = 0; 1538 1537 down_read((&EXT4_I(inode)->i_data_sem));