Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 555936bf authored by Tao Ma's avatar Tao Ma Committed by Joel Becker
Browse files

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: default avatarTao Ma <tao.ma@oracle.com>
parent 853a3a14
Loading
Loading
Loading
Loading
+100 −50
Original line number Diff line number Diff line
@@ -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,7 +5050,7 @@ 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,
static int __ocfs2_split_extent(handle_t *handle,
				struct ocfs2_extent_tree *et,
				struct ocfs2_path *path,
				int split_index,
@@ -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,
static int ocfs2_change_extent_flag(handle_t *handle,
				    struct ocfs2_extent_tree *et,
			      handle_t *handle, u32 cpos, u32 len, u32 phys,
				    u32 cpos, u32 len, u32 phys,
				    struct ocfs2_alloc_context *meta_ac,
			      struct ocfs2_cached_dealloc_ctxt *dealloc)
				    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,22 +5176,44 @@ 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,
	ret = __ocfs2_split_extent(handle, et, left_path,
				  index, &split_rec, meta_ac,
				  dealloc);
	if (ret)
@@ -5218,6 +5222,52 @@ int ocfs2_mark_extent_written(struct inode *inode,
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,