ocfs2: Abstract extent split process.
ocfs2_mark_extent_written actually does the following things: 1. check the parameters. 2. initialize the left_path and split_rec. 3. call __ocfs2_mark_extent_written. it will do: 1) check the flags of unwritten 2) do the real split work. The whole process is packed tightly somehow. So this patch will abstract 2 different functions so that future b-tree operation can work with it. 1. __ocfs2_split_extent will accept path and split_rec and do the real split work. 2. ocfs2_change_extent_flag will accept a new flag and initialize path and split_rec. So now ocfs2_mark_extent_written will do: 1. check the parameters. 2. call ocfs2_change_extent_flag. 1) initalize the left_path and split_rec. 2) check whether the new flags conflict with the old one. 3) call __ocfs2_split_extent to do the split. Signed-off-by: Tao Ma <tao.ma@oracle.com>
This commit is contained in:
parent
853a3a1439
commit
555936bfcb
148
fs/ocfs2/alloc.c
148
fs/ocfs2/alloc.c
|
@ -5032,9 +5032,8 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Mark part or all of the extent record at split_index in the leaf
|
||||
* pointed to by path as written. This removes the unwritten
|
||||
* extent flag.
|
||||
* Split part or all of the extent record at split_index in the leaf
|
||||
* pointed to by path. Merge with the contiguous extent record if needed.
|
||||
*
|
||||
* Care is taken to handle contiguousness so as to not grow the tree.
|
||||
*
|
||||
|
@ -5051,13 +5050,13 @@ out:
|
|||
* have been brought into cache (and pinned via the journal), so the
|
||||
* extra overhead is not expressed in terms of disk reads.
|
||||
*/
|
||||
static int __ocfs2_mark_extent_written(handle_t *handle,
|
||||
struct ocfs2_extent_tree *et,
|
||||
struct ocfs2_path *path,
|
||||
int split_index,
|
||||
struct ocfs2_extent_rec *split_rec,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc)
|
||||
static int __ocfs2_split_extent(handle_t *handle,
|
||||
struct ocfs2_extent_tree *et,
|
||||
struct ocfs2_path *path,
|
||||
int split_index,
|
||||
struct ocfs2_extent_rec *split_rec,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ocfs2_extent_list *el = path_leaf_el(path);
|
||||
|
@ -5066,12 +5065,6 @@ static int __ocfs2_mark_extent_written(handle_t *handle,
|
|||
struct ocfs2_merge_ctxt ctxt;
|
||||
struct ocfs2_extent_list *rightmost_el;
|
||||
|
||||
if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) {
|
||||
ret = -EIO;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
|
||||
((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
|
||||
(le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
|
||||
|
@ -5141,42 +5134,31 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Mark the already-existing extent at cpos as written for len clusters.
|
||||
* Change the flags of the already-existing extent at cpos for len clusters.
|
||||
*
|
||||
* new_flags: the flags we want to set.
|
||||
* clear_flags: the flags we want to clear.
|
||||
* phys: the new physical offset we want this new extent starts from.
|
||||
*
|
||||
* If the existing extent is larger than the request, initiate a
|
||||
* split. An attempt will be made at merging with adjacent extents.
|
||||
*
|
||||
* The caller is responsible for passing down meta_ac if we'll need it.
|
||||
*/
|
||||
int ocfs2_mark_extent_written(struct inode *inode,
|
||||
struct ocfs2_extent_tree *et,
|
||||
handle_t *handle, u32 cpos, u32 len, u32 phys,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc)
|
||||
static int ocfs2_change_extent_flag(handle_t *handle,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 cpos, u32 len, u32 phys,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc,
|
||||
int new_flags, int clear_flags)
|
||||
{
|
||||
int ret, index;
|
||||
u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
|
||||
struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
|
||||
u64 start_blkno = ocfs2_clusters_to_blocks(sb, phys);
|
||||
struct ocfs2_extent_rec split_rec;
|
||||
struct ocfs2_path *left_path = NULL;
|
||||
struct ocfs2_extent_list *el;
|
||||
|
||||
mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
|
||||
inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
|
||||
|
||||
if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
|
||||
ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
|
||||
"that are being written to, but the feature bit "
|
||||
"is not set in the super block.",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
ret = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This should be fixed up so that we just re-insert the
|
||||
* next extent records.
|
||||
*/
|
||||
ocfs2_et_extent_map_truncate(et, 0);
|
||||
struct ocfs2_extent_rec *rec;
|
||||
|
||||
left_path = ocfs2_new_path_from_et(et);
|
||||
if (!left_path) {
|
||||
|
@ -5194,30 +5176,98 @@ int ocfs2_mark_extent_written(struct inode *inode,
|
|||
|
||||
index = ocfs2_search_extent_list(el, cpos);
|
||||
if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
|
||||
ocfs2_error(inode->i_sb,
|
||||
"Inode %llu has an extent at cpos %u which can no "
|
||||
ocfs2_error(sb,
|
||||
"Owner %llu has an extent at cpos %u which can no "
|
||||
"longer be found.\n",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
|
||||
(unsigned long long)
|
||||
ocfs2_metadata_cache_owner(et->et_ci), cpos);
|
||||
ret = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = -EIO;
|
||||
rec = &el->l_recs[index];
|
||||
if (new_flags && (rec->e_flags & new_flags)) {
|
||||
mlog(ML_ERROR, "Owner %llu tried to set %d flags on an "
|
||||
"extent that already had them",
|
||||
(unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
|
||||
new_flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (clear_flags && !(rec->e_flags & clear_flags)) {
|
||||
mlog(ML_ERROR, "Owner %llu tried to clear %d flags on an "
|
||||
"extent that didn't have them",
|
||||
(unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
|
||||
clear_flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
|
||||
split_rec.e_cpos = cpu_to_le32(cpos);
|
||||
split_rec.e_leaf_clusters = cpu_to_le16(len);
|
||||
split_rec.e_blkno = cpu_to_le64(start_blkno);
|
||||
split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
|
||||
split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
|
||||
split_rec.e_flags = rec->e_flags;
|
||||
if (new_flags)
|
||||
split_rec.e_flags |= new_flags;
|
||||
if (clear_flags)
|
||||
split_rec.e_flags &= ~clear_flags;
|
||||
|
||||
ret = __ocfs2_mark_extent_written(handle, et, left_path,
|
||||
index, &split_rec, meta_ac,
|
||||
dealloc);
|
||||
ret = __ocfs2_split_extent(handle, et, left_path,
|
||||
index, &split_rec, meta_ac,
|
||||
dealloc);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
|
||||
out:
|
||||
ocfs2_free_path(left_path);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the already-existing extent at cpos as written for len clusters.
|
||||
* This removes the unwritten extent flag.
|
||||
*
|
||||
* If the existing extent is larger than the request, initiate a
|
||||
* split. An attempt will be made at merging with adjacent extents.
|
||||
*
|
||||
* The caller is responsible for passing down meta_ac if we'll need it.
|
||||
*/
|
||||
int ocfs2_mark_extent_written(struct inode *inode,
|
||||
struct ocfs2_extent_tree *et,
|
||||
handle_t *handle, u32 cpos, u32 len, u32 phys,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n",
|
||||
inode->i_ino, cpos, len, phys);
|
||||
|
||||
if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
|
||||
ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
|
||||
"that are being written to, but the feature bit "
|
||||
"is not set in the super block.",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
ret = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This should be fixed up so that we just re-insert the
|
||||
* next extent records.
|
||||
*/
|
||||
ocfs2_et_extent_map_truncate(et, 0);
|
||||
|
||||
ret = ocfs2_change_extent_flag(handle, et, cpos,
|
||||
len, phys, meta_ac, dealloc,
|
||||
0, OCFS2_EXT_UNWRITTEN);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ocfs2_split_tree(handle_t *handle, struct ocfs2_extent_tree *et,
|
||||
|
|
Loading…
Reference in New Issue