diff options
Diffstat (limited to 'fs/ext3/balloc.c')
-rw-r--r-- | fs/ext3/balloc.c | 94 |
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 | */ |
2092 | int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) | 2087 | int 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 | ||
2156 | out: | ||
2157 | range->len = trimmed * sb->s_blocksize; | ||
2162 | return ret; | 2158 | return ret; |
2163 | } | 2159 | } |