aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/balloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3/balloc.c')
-rw-r--r--fs/ext3/balloc.c84
1 files changed, 44 insertions, 40 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index a2038928f9a3..1e036b79384c 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1743,8 +1743,11 @@ allocated:
1743 1743
1744 *errp = 0; 1744 *errp = 0;
1745 brelse(bitmap_bh); 1745 brelse(bitmap_bh);
1746 dquot_free_block(inode, *count-num); 1746
1747 *count = num; 1747 if (num < *count) {
1748 dquot_free_block(inode, *count-num);
1749 *count = num;
1750 }
1748 1751
1749 trace_ext3_allocate_blocks(inode, goal, num, 1752 trace_ext3_allocate_blocks(inode, goal, num,
1750 (unsigned long long)ret_block); 1753 (unsigned long long)ret_block);
@@ -1970,7 +1973,7 @@ static ext3_grpblk_t ext3_trim_all_free(struct super_block *sb,
1970 sbi = EXT3_SB(sb); 1973 sbi = EXT3_SB(sb);
1971 1974
1972 /* Walk through the whole group */ 1975 /* Walk through the whole group */
1973 while (start < max) { 1976 while (start <= max) {
1974 start = bitmap_search_next_usable_block(start, bitmap_bh, max); 1977 start = bitmap_search_next_usable_block(start, bitmap_bh, max);
1975 if (start < 0) 1978 if (start < 0)
1976 break; 1979 break;
@@ -1980,7 +1983,7 @@ static ext3_grpblk_t ext3_trim_all_free(struct super_block *sb,
1980 * Allocate contiguous free extents by setting bits in the 1983 * Allocate contiguous free extents by setting bits in the
1981 * block bitmap 1984 * block bitmap
1982 */ 1985 */
1983 while (next < max 1986 while (next <= max
1984 && claim_block(sb_bgl_lock(sbi, group), 1987 && claim_block(sb_bgl_lock(sbi, group),
1985 next, bitmap_bh)) { 1988 next, bitmap_bh)) {
1986 next++; 1989 next++;
@@ -2091,73 +2094,74 @@ err_out:
2091 */ 2094 */
2092int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) 2095int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
2093{ 2096{
2094 ext3_grpblk_t last_block, first_block, free_blocks; 2097 ext3_grpblk_t last_block, first_block;
2095 unsigned long first_group, last_group; 2098 unsigned long group, first_group, last_group;
2096 unsigned long group, ngroups;
2097 struct ext3_group_desc *gdp; 2099 struct ext3_group_desc *gdp;
2098 struct ext3_super_block *es = EXT3_SB(sb)->s_es; 2100 struct ext3_super_block *es = EXT3_SB(sb)->s_es;
2099 uint64_t start, len, minlen, trimmed; 2101 uint64_t start, minlen, end, trimmed = 0;
2102 ext3_fsblk_t first_data_blk =
2103 le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block);
2100 ext3_fsblk_t max_blks = le32_to_cpu(es->s_blocks_count); 2104 ext3_fsblk_t max_blks = le32_to_cpu(es->s_blocks_count);
2101 int ret = 0; 2105 int ret = 0;
2102 2106
2103 start = (range->start >> sb->s_blocksize_bits) + 2107 start = range->start >> sb->s_blocksize_bits;
2104 le32_to_cpu(es->s_first_data_block); 2108 end = start + (range->len >> sb->s_blocksize_bits) - 1;
2105 len = range->len >> sb->s_blocksize_bits;
2106 minlen = range->minlen >> sb->s_blocksize_bits; 2109 minlen = range->minlen >> sb->s_blocksize_bits;
2107 trimmed = 0;
2108 2110
2109 if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb))) 2111 if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
2112 unlikely(start >= max_blks))
2110 return -EINVAL; 2113 return -EINVAL;
2111 if (start >= max_blks) 2114 if (end >= max_blks)
2112 return -EINVAL; 2115 end = max_blks - 1;
2113 if (start + len > max_blks) 2116 if (end <= first_data_blk)
2114 len = max_blks - start; 2117 goto out;
2118 if (start < first_data_blk)
2119 start = first_data_blk;
2115 2120
2116 ngroups = EXT3_SB(sb)->s_groups_count;
2117 smp_rmb(); 2121 smp_rmb();
2118 2122
2119 /* Determine first and last group to examine based on start and len */ 2123 /* Determine first and last group to examine based on start and len */
2120 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) start, 2124 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) start,
2121 &first_group, &first_block); 2125 &first_group, &first_block);
2122 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) (start + len), 2126 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) end,
2123 &last_group, &last_block); 2127 &last_group, &last_block);
2124 last_group = (last_group > ngroups - 1) ? ngroups - 1 : last_group;
2125 last_block = EXT3_BLOCKS_PER_GROUP(sb);
2126 2128
2127 if (first_group > last_group) 2129 /* end now represents the last block to discard in this group */
2128 return -EINVAL; 2130 end = EXT3_BLOCKS_PER_GROUP(sb) - 1;
2129 2131
2130 for (group = first_group; group <= last_group; group++) { 2132 for (group = first_group; group <= last_group; group++) {
2131 gdp = ext3_get_group_desc(sb, group, NULL); 2133 gdp = ext3_get_group_desc(sb, group, NULL);
2132 if (!gdp) 2134 if (!gdp)
2133 break; 2135 break;
2134 2136
2135 free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
2136 if (free_blocks < minlen)
2137 continue;
2138
2139 /* 2137 /*
2140 * For all the groups except the last one, last block will 2138 * For all the groups except the last one, last block will
2141 * always be EXT3_BLOCKS_PER_GROUP(sb), so we only need to 2139 * always be EXT3_BLOCKS_PER_GROUP(sb)-1, so we only need to
2142 * change it for the last group in which case first_block + 2140 * change it for the last group, note that last_block is
2143 * len < EXT3_BLOCKS_PER_GROUP(sb). 2141 * already computed earlier by ext3_get_group_no_and_offset()
2144 */ 2142 */
2145 if (first_block + len < EXT3_BLOCKS_PER_GROUP(sb)) 2143 if (group == last_group)
2146 last_block = first_block + len; 2144 end = last_block;
2147 len -= last_block - first_block;
2148 2145
2149 ret = ext3_trim_all_free(sb, group, first_block, 2146 if (le16_to_cpu(gdp->bg_free_blocks_count) >= minlen) {
2150 last_block, minlen); 2147 ret = ext3_trim_all_free(sb, group, first_block,
2151 if (ret < 0) 2148 end, minlen);
2152 break; 2149 if (ret < 0)
2150 break;
2151 trimmed += ret;
2152 }
2153 2153
2154 trimmed += ret; 2154 /*
2155 * For every group except the first one, we are sure
2156 * that the first block to discard will be block #0.
2157 */
2155 first_block = 0; 2158 first_block = 0;
2156 } 2159 }
2157 2160
2158 if (ret >= 0) 2161 if (ret > 0)
2159 ret = 0; 2162 ret = 0;
2160 range->len = trimmed * sb->s_blocksize;
2161 2163
2164out:
2165 range->len = trimmed * sb->s_blocksize;
2162 return ret; 2166 return ret;
2163} 2167}