aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r--fs/ocfs2/alloc.c150
1 files changed, 100 insertions, 50 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 75e65df34b69..14b9106849ca 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -5032,9 +5032,8 @@ out:
5032} 5032}
5033 5033
5034/* 5034/*
5035 * Mark part or all of the extent record at split_index in the leaf 5035 * Split part or all of the extent record at split_index in the leaf
5036 * pointed to by path as written. This removes the unwritten 5036 * pointed to by path. Merge with the contiguous extent record if needed.
5037 * extent flag.
5038 * 5037 *
5039 * Care is taken to handle contiguousness so as to not grow the tree. 5038 * Care is taken to handle contiguousness so as to not grow the tree.
5040 * 5039 *
@@ -5051,13 +5050,13 @@ out:
5051 * have been brought into cache (and pinned via the journal), so the 5050 * have been brought into cache (and pinned via the journal), so the
5052 * extra overhead is not expressed in terms of disk reads. 5051 * extra overhead is not expressed in terms of disk reads.
5053 */ 5052 */
5054static int __ocfs2_mark_extent_written(handle_t *handle, 5053static int __ocfs2_split_extent(handle_t *handle,
5055 struct ocfs2_extent_tree *et, 5054 struct ocfs2_extent_tree *et,
5056 struct ocfs2_path *path, 5055 struct ocfs2_path *path,
5057 int split_index, 5056 int split_index,
5058 struct ocfs2_extent_rec *split_rec, 5057 struct ocfs2_extent_rec *split_rec,
5059 struct ocfs2_alloc_context *meta_ac, 5058 struct ocfs2_alloc_context *meta_ac,
5060 struct ocfs2_cached_dealloc_ctxt *dealloc) 5059 struct ocfs2_cached_dealloc_ctxt *dealloc)
5061{ 5060{
5062 int ret = 0; 5061 int ret = 0;
5063 struct ocfs2_extent_list *el = path_leaf_el(path); 5062 struct ocfs2_extent_list *el = path_leaf_el(path);
@@ -5066,12 +5065,6 @@ static int __ocfs2_mark_extent_written(handle_t *handle,
5066 struct ocfs2_merge_ctxt ctxt; 5065 struct ocfs2_merge_ctxt ctxt;
5067 struct ocfs2_extent_list *rightmost_el; 5066 struct ocfs2_extent_list *rightmost_el;
5068 5067
5069 if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) {
5070 ret = -EIO;
5071 mlog_errno(ret);
5072 goto out;
5073 }
5074
5075 if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) || 5068 if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
5076 ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) < 5069 ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
5077 (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) { 5070 (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
@@ -5141,42 +5134,31 @@ out:
5141} 5134}
5142 5135
5143/* 5136/*
5144 * Mark the already-existing extent at cpos as written for len clusters. 5137 * Change the flags of the already-existing extent at cpos for len clusters.
5138 *
5139 * new_flags: the flags we want to set.
5140 * clear_flags: the flags we want to clear.
5141 * phys: the new physical offset we want this new extent starts from.
5145 * 5142 *
5146 * If the existing extent is larger than the request, initiate a 5143 * If the existing extent is larger than the request, initiate a
5147 * split. An attempt will be made at merging with adjacent extents. 5144 * split. An attempt will be made at merging with adjacent extents.
5148 * 5145 *
5149 * The caller is responsible for passing down meta_ac if we'll need it. 5146 * The caller is responsible for passing down meta_ac if we'll need it.
5150 */ 5147 */
5151int ocfs2_mark_extent_written(struct inode *inode, 5148static int ocfs2_change_extent_flag(handle_t *handle,
5152 struct ocfs2_extent_tree *et, 5149 struct ocfs2_extent_tree *et,
5153 handle_t *handle, u32 cpos, u32 len, u32 phys, 5150 u32 cpos, u32 len, u32 phys,
5154 struct ocfs2_alloc_context *meta_ac, 5151 struct ocfs2_alloc_context *meta_ac,
5155 struct ocfs2_cached_dealloc_ctxt *dealloc) 5152 struct ocfs2_cached_dealloc_ctxt *dealloc,
5153 int new_flags, int clear_flags)
5156{ 5154{
5157 int ret, index; 5155 int ret, index;
5158 u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys); 5156 struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
5157 u64 start_blkno = ocfs2_clusters_to_blocks(sb, phys);
5159 struct ocfs2_extent_rec split_rec; 5158 struct ocfs2_extent_rec split_rec;
5160 struct ocfs2_path *left_path = NULL; 5159 struct ocfs2_path *left_path = NULL;
5161 struct ocfs2_extent_list *el; 5160 struct ocfs2_extent_list *el;
5162 5161 struct ocfs2_extent_rec *rec;
5163 mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
5164 inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
5165
5166 if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
5167 ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
5168 "that are being written to, but the feature bit "
5169 "is not set in the super block.",
5170 (unsigned long long)OCFS2_I(inode)->ip_blkno);
5171 ret = -EROFS;
5172 goto out;
5173 }
5174
5175 /*
5176 * XXX: This should be fixed up so that we just re-insert the
5177 * next extent records.
5178 */
5179 ocfs2_et_extent_map_truncate(et, 0);
5180 5162
5181 left_path = ocfs2_new_path_from_et(et); 5163 left_path = ocfs2_new_path_from_et(et);
5182 if (!left_path) { 5164 if (!left_path) {
@@ -5194,30 +5176,98 @@ int ocfs2_mark_extent_written(struct inode *inode,
5194 5176
5195 index = ocfs2_search_extent_list(el, cpos); 5177 index = ocfs2_search_extent_list(el, cpos);
5196 if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) { 5178 if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
5197 ocfs2_error(inode->i_sb, 5179 ocfs2_error(sb,
5198 "Inode %llu has an extent at cpos %u which can no " 5180 "Owner %llu has an extent at cpos %u which can no "
5199 "longer be found.\n", 5181 "longer be found.\n",
5200 (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos); 5182 (unsigned long long)
5183 ocfs2_metadata_cache_owner(et->et_ci), cpos);
5201 ret = -EROFS; 5184 ret = -EROFS;
5202 goto out; 5185 goto out;
5203 } 5186 }
5204 5187
5188 ret = -EIO;
5189 rec = &el->l_recs[index];
5190 if (new_flags && (rec->e_flags & new_flags)) {
5191 mlog(ML_ERROR, "Owner %llu tried to set %d flags on an "
5192 "extent that already had them",
5193 (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
5194 new_flags);
5195 goto out;
5196 }
5197
5198 if (clear_flags && !(rec->e_flags & clear_flags)) {
5199 mlog(ML_ERROR, "Owner %llu tried to clear %d flags on an "
5200 "extent that didn't have them",
5201 (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
5202 clear_flags);
5203 goto out;
5204 }
5205
5205 memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec)); 5206 memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
5206 split_rec.e_cpos = cpu_to_le32(cpos); 5207 split_rec.e_cpos = cpu_to_le32(cpos);
5207 split_rec.e_leaf_clusters = cpu_to_le16(len); 5208 split_rec.e_leaf_clusters = cpu_to_le16(len);
5208 split_rec.e_blkno = cpu_to_le64(start_blkno); 5209 split_rec.e_blkno = cpu_to_le64(start_blkno);
5209 split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags; 5210 split_rec.e_flags = rec->e_flags;
5210 split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN; 5211 if (new_flags)
5211 5212 split_rec.e_flags |= new_flags;
5212 ret = __ocfs2_mark_extent_written(handle, et, left_path, 5213 if (clear_flags)
5213 index, &split_rec, meta_ac, 5214 split_rec.e_flags &= ~clear_flags;
5214 dealloc); 5215
5216 ret = __ocfs2_split_extent(handle, et, left_path,
5217 index, &split_rec, meta_ac,
5218 dealloc);
5215 if (ret) 5219 if (ret)
5216 mlog_errno(ret); 5220 mlog_errno(ret);
5217 5221
5218out: 5222out:
5219 ocfs2_free_path(left_path); 5223 ocfs2_free_path(left_path);
5220 return ret; 5224 return ret;
5225
5226}
5227
5228/*
5229 * Mark the already-existing extent at cpos as written for len clusters.
5230 * This removes the unwritten extent flag.
5231 *
5232 * If the existing extent is larger than the request, initiate a
5233 * split. An attempt will be made at merging with adjacent extents.
5234 *
5235 * The caller is responsible for passing down meta_ac if we'll need it.
5236 */
5237int ocfs2_mark_extent_written(struct inode *inode,
5238 struct ocfs2_extent_tree *et,
5239 handle_t *handle, u32 cpos, u32 len, u32 phys,
5240 struct ocfs2_alloc_context *meta_ac,
5241 struct ocfs2_cached_dealloc_ctxt *dealloc)
5242{
5243 int ret;
5244
5245 mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n",
5246 inode->i_ino, cpos, len, phys);
5247
5248 if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
5249 ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
5250 "that are being written to, but the feature bit "
5251 "is not set in the super block.",
5252 (unsigned long long)OCFS2_I(inode)->ip_blkno);
5253 ret = -EROFS;
5254 goto out;
5255 }
5256
5257 /*
5258 * XXX: This should be fixed up so that we just re-insert the
5259 * next extent records.
5260 */
5261 ocfs2_et_extent_map_truncate(et, 0);
5262
5263 ret = ocfs2_change_extent_flag(handle, et, cpos,
5264 len, phys, meta_ac, dealloc,
5265 0, OCFS2_EXT_UNWRITTEN);
5266 if (ret)
5267 mlog_errno(ret);
5268
5269out:
5270 return ret;
5221} 5271}
5222 5272
5223static int ocfs2_split_tree(handle_t *handle, struct ocfs2_extent_tree *et, 5273static int ocfs2_split_tree(handle_t *handle, struct ocfs2_extent_tree *et,