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.c94
1 files changed, 45 insertions, 49 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index a2038928f9a3..baac1b129fba 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -11,17 +11,9 @@
11 * David S. Miller (davem@caip.rutgers.edu), 1995 11 * David S. Miller (davem@caip.rutgers.edu), 1995
12 */ 12 */
13 13
14#include <linux/time.h>
15#include <linux/capability.h>
16#include <linux/fs.h>
17#include <linux/slab.h>
18#include <linux/jbd.h>
19#include <linux/ext3_fs.h>
20#include <linux/ext3_jbd.h>
21#include <linux/quotaops.h> 14#include <linux/quotaops.h>
22#include <linux/buffer_head.h>
23#include <linux/blkdev.h> 15#include <linux/blkdev.h>
24#include <trace/events/ext3.h> 16#include "ext3.h"
25 17
26/* 18/*
27 * balloc.c contains the blocks allocation and deallocation routines 19 * balloc.c contains the blocks allocation and deallocation routines
@@ -1743,8 +1735,11 @@ allocated:
1743 1735
1744 *errp = 0; 1736 *errp = 0;
1745 brelse(bitmap_bh); 1737 brelse(bitmap_bh);
1746 dquot_free_block(inode, *count-num); 1738
1747 *count = num; 1739 if (num < *count) {
1740 dquot_free_block(inode, *count-num);
1741 *count = num;
1742 }
1748 1743
1749 trace_ext3_allocate_blocks(inode, goal, num, 1744 trace_ext3_allocate_blocks(inode, goal, num,
1750 (unsigned long long)ret_block); 1745 (unsigned long long)ret_block);
@@ -1970,7 +1965,7 @@ static ext3_grpblk_t ext3_trim_all_free(struct super_block *sb,
1970 sbi = EXT3_SB(sb); 1965 sbi = EXT3_SB(sb);
1971 1966
1972 /* Walk through the whole group */ 1967 /* Walk through the whole group */
1973 while (start < max) { 1968 while (start <= max) {
1974 start = bitmap_search_next_usable_block(start, bitmap_bh, max); 1969 start = bitmap_search_next_usable_block(start, bitmap_bh, max);
1975 if (start < 0) 1970 if (start < 0)
1976 break; 1971 break;
@@ -1980,7 +1975,7 @@ static ext3_grpblk_t ext3_trim_all_free(struct super_block *sb,
1980 * Allocate contiguous free extents by setting bits in the 1975 * Allocate contiguous free extents by setting bits in the
1981 * block bitmap 1976 * block bitmap
1982 */ 1977 */
1983 while (next < max 1978 while (next <= max
1984 && claim_block(sb_bgl_lock(sbi, group), 1979 && claim_block(sb_bgl_lock(sbi, group),
1985 next, bitmap_bh)) { 1980 next, bitmap_bh)) {
1986 next++; 1981 next++;
@@ -2091,73 +2086,74 @@ err_out:
2091 */ 2086 */
2092int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) 2087int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
2093{ 2088{
2094 ext3_grpblk_t last_block, first_block, free_blocks; 2089 ext3_grpblk_t last_block, first_block;
2095 unsigned long first_group, last_group; 2090 unsigned long group, first_group, last_group;
2096 unsigned long group, ngroups;
2097 struct ext3_group_desc *gdp; 2091 struct ext3_group_desc *gdp;
2098 struct ext3_super_block *es = EXT3_SB(sb)->s_es; 2092 struct ext3_super_block *es = EXT3_SB(sb)->s_es;
2099 uint64_t start, len, minlen, trimmed; 2093 uint64_t start, minlen, end, trimmed = 0;
2094 ext3_fsblk_t first_data_blk =
2095 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); 2096 ext3_fsblk_t max_blks = le32_to_cpu(es->s_blocks_count);
2101 int ret = 0; 2097 int ret = 0;
2102 2098
2103 start = (range->start >> sb->s_blocksize_bits) + 2099 start = range->start >> sb->s_blocksize_bits;
2104 le32_to_cpu(es->s_first_data_block); 2100 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; 2101 minlen = range->minlen >> sb->s_blocksize_bits;
2107 trimmed = 0;
2108 2102
2109 if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb))) 2103 if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
2104 unlikely(start >= max_blks))
2110 return -EINVAL; 2105 return -EINVAL;
2111 if (start >= max_blks) 2106 if (end >= max_blks)
2112 return -EINVAL; 2107 end = max_blks - 1;
2113 if (start + len > max_blks) 2108 if (end <= first_data_blk)
2114 len = max_blks - start; 2109 goto out;
2110 if (start < first_data_blk)
2111 start = first_data_blk;
2115 2112
2116 ngroups = EXT3_SB(sb)->s_groups_count;
2117 smp_rmb(); 2113 smp_rmb();
2118 2114
2119 /* Determine first and last group to examine based on start and len */ 2115 /* Determine first and last group to examine based on start and len */
2120 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) start, 2116 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) start,
2121 &first_group, &first_block); 2117 &first_group, &first_block);
2122 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) (start + len), 2118 ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) end,
2123 &last_group, &last_block); 2119 &last_group, &last_block);
2124 last_group = (last_group > ngroups - 1) ? ngroups - 1 : last_group;
2125 last_block = EXT3_BLOCKS_PER_GROUP(sb);
2126 2120
2127 if (first_group > last_group) 2121 /* end now represents the last block to discard in this group */
2128 return -EINVAL; 2122 end = EXT3_BLOCKS_PER_GROUP(sb) - 1;
2129 2123
2130 for (group = first_group; group <= last_group; group++) { 2124 for (group = first_group; group <= last_group; group++) {
2131 gdp = ext3_get_group_desc(sb, group, NULL); 2125 gdp = ext3_get_group_desc(sb, group, NULL);
2132 if (!gdp) 2126 if (!gdp)
2133 break; 2127 break;
2134 2128
2135 free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
2136 if (free_blocks < minlen)
2137 continue;
2138
2139 /* 2129 /*
2140 * For all the groups except the last one, last block will 2130 * For all the groups except the last one, last block will
2141 * always be EXT3_BLOCKS_PER_GROUP(sb), so we only need to 2131 * 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 + 2132 * change it for the last group, note that last_block is
2143 * len < EXT3_BLOCKS_PER_GROUP(sb). 2133 * already computed earlier by ext3_get_group_no_and_offset()
2144 */ 2134 */
2145 if (first_block + len < EXT3_BLOCKS_PER_GROUP(sb)) 2135 if (group == last_group)
2146 last_block = first_block + len; 2136 end = last_block;
2147 len -= last_block - first_block;
2148 2137
2149 ret = ext3_trim_all_free(sb, group, first_block, 2138 if (le16_to_cpu(gdp->bg_free_blocks_count) >= minlen) {
2150 last_block, minlen); 2139 ret = ext3_trim_all_free(sb, group, first_block,
2151 if (ret < 0) 2140 end, minlen);
2152 break; 2141 if (ret < 0)
2142 break;
2143 trimmed += ret;
2144 }
2153 2145
2154 trimmed += ret; 2146 /*
2147 * For every group except the first one, we are sure
2148 * that the first block to discard will be block #0.
2149 */
2155 first_block = 0; 2150 first_block = 0;
2156 } 2151 }
2157 2152
2158 if (ret >= 0) 2153 if (ret > 0)
2159 ret = 0; 2154 ret = 0;
2160 range->len = trimmed * sb->s_blocksize;
2161 2155
2156out:
2157 range->len = trimmed * sb->s_blocksize;
2162 return ret; 2158 return ret;
2163} 2159}