diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 13:00:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 13:00:14 -0400 |
commit | 9a7259d5c8978bbeb5fdcf64b168f8470d8208a6 (patch) | |
tree | 5c255d4b18622de06c2637c0c4069a384e99466d /fs/ext3 | |
parent | e9c0f1529c9022afbab16a442382aa9a84a79c41 (diff) | |
parent | e703c206135acb458adb705ec44bcc5d2615b37d (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull ext3, UDF, and quota fixes from Jan Kara:
"A couple of ext3 & UDF fixes and also one improvement in quota
locking."
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
ext3: fix start and len arguments handling in ext3_trim_fs()
udf: Fix deadlock in udf_release_file()
udf: Fix file entry logicalBlocksRecorded
udf: Fix handling of i_blocks
quota: Make quota code not call tty layer with dqptr_sem held
udf: Init/maintain file entry checkpoint field
ext3: Update ctime in ext3_splice_branch() only when needed
ext3: Don't call dquot_free_block() if we don't update anything
udf: Remove unnecessary OOM messages
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/balloc.c | 84 | ||||
-rw-r--r-- | fs/ext3/inode.c | 9 |
2 files changed, 50 insertions, 43 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 | */ |
2092 | int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) | 2095 | int 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 | ||
2164 | out: | ||
2165 | range->len = trimmed * sb->s_blocksize; | ||
2162 | return ret; | 2166 | return ret; |
2163 | } | 2167 | } |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 2d0afeca0b47..6d3418662b54 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -756,6 +756,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, | |||
756 | struct ext3_block_alloc_info *block_i; | 756 | struct ext3_block_alloc_info *block_i; |
757 | ext3_fsblk_t current_block; | 757 | ext3_fsblk_t current_block; |
758 | struct ext3_inode_info *ei = EXT3_I(inode); | 758 | struct ext3_inode_info *ei = EXT3_I(inode); |
759 | struct timespec now; | ||
759 | 760 | ||
760 | block_i = ei->i_block_alloc_info; | 761 | block_i = ei->i_block_alloc_info; |
761 | /* | 762 | /* |
@@ -795,9 +796,11 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, | |||
795 | } | 796 | } |
796 | 797 | ||
797 | /* We are done with atomic stuff, now do the rest of housekeeping */ | 798 | /* We are done with atomic stuff, now do the rest of housekeeping */ |
798 | 799 | now = CURRENT_TIME_SEC; | |
799 | inode->i_ctime = CURRENT_TIME_SEC; | 800 | if (!timespec_equal(&inode->i_ctime, &now) || !where->bh) { |
800 | ext3_mark_inode_dirty(handle, inode); | 801 | inode->i_ctime = now; |
802 | ext3_mark_inode_dirty(handle, inode); | ||
803 | } | ||
801 | /* ext3_mark_inode_dirty already updated i_sync_tid */ | 804 | /* ext3_mark_inode_dirty already updated i_sync_tid */ |
802 | atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); | 805 | atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); |
803 | 806 | ||