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

Commit 59a5e416 authored by Mark Fasheh's avatar Mark Fasheh
Browse files

ocfs2: plug truncate into cached dealloc routines

parent 2b604351
Loading
Loading
Loading
Loading
+27 −75
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@
#include "buffer_head_io.h"

static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
					 struct ocfs2_extent_block *eb);

/*
 * Structures which describe a path through a btree, and functions to
@@ -3161,6 +3163,15 @@ static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
	return ret;
}

static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
					 struct ocfs2_extent_block *eb)
{
	return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
					 le16_to_cpu(eb->h_suballoc_slot),
					 le64_to_cpu(eb->h_blkno),
					 le16_to_cpu(eb->h_suballoc_bit));
}

/* This function will figure out whether the currently last extent
 * block will be deleted, and if it will, what the new last extent
 * block will be so we can update his h_next_leaf_blk field, as well
@@ -3442,27 +3453,10 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
			BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
			BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));

			if (le16_to_cpu(eb->h_suballoc_slot) == 0) {
				/*
				 * This code only understands how to
				 * lock the suballocator in slot 0,
				 * which is fine because allocation is
				 * only ever done out of that
				 * suballocator too. A future version
				 * might change that however, so avoid
				 * a free if we don't know how to
				 * handle it. This way an fs incompat
				 * bit will not be necessary.
				 */
				ret = ocfs2_free_extent_block(handle,
							      tc->tc_ext_alloc_inode,
							      tc->tc_ext_alloc_bh,
							      eb);

			ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
			/* An error here is not fatal. */
			if (ret < 0)
				mlog_errno(ret);
			}
		} else {
			deleted_eb = 0;
		}
@@ -3965,6 +3959,8 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
	if (handle)
		ocfs2_commit_trans(osb, handle);

	ocfs2_run_deallocs(osb, &tc->tc_dealloc);

	ocfs2_free_path(path);

	/* This will drop the ext_alloc cluster lock for us */
@@ -3975,23 +3971,18 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
}

/*
 * Expects the inode to already be locked. This will figure out which
 * inodes need to be locked and will put them on the returned truncate
 * context.
 * Expects the inode to already be locked.
 */
int ocfs2_prepare_truncate(struct ocfs2_super *osb,
			   struct inode *inode,
			   struct buffer_head *fe_bh,
			   struct ocfs2_truncate_context **tc)
{
	int status, metadata_delete, i;
	int status;
	unsigned int new_i_clusters;
	struct ocfs2_dinode *fe;
	struct ocfs2_extent_block *eb;
	struct ocfs2_extent_list *el;
	struct buffer_head *last_eb_bh = NULL;
	struct inode *ext_alloc_inode = NULL;
	struct buffer_head *ext_alloc_bh = NULL;

	mlog_entry_void();

@@ -4011,12 +4002,9 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
		mlog_errno(status);
		goto bail;
	}
	ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);

	metadata_delete = 0;
	if (fe->id2.i_list.l_tree_depth) {
		/* If we have a tree, then the truncate may result in
		 * metadata deletes. Figure this out from the
		 * rightmost leaf block.*/
		status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
					  &last_eb_bh, OCFS2_BH_CACHED, inode);
		if (status < 0) {
@@ -4031,43 +4019,10 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
			status = -EIO;
			goto bail;
		}
		el = &(eb->h_list);

		i = 0;
		if (ocfs2_is_empty_extent(&el->l_recs[0]))
			i = 1;
		/*
		 * XXX: Should we check that next_free_rec contains
		 * the extent?
		 */
		if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
			metadata_delete = 1;
	}

	(*tc)->tc_last_eb_bh = last_eb_bh;

	if (metadata_delete) {
		mlog(0, "Will have to delete metadata for this trunc. "
		     "locking allocator.\n");
		ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
		if (!ext_alloc_inode) {
			status = -ENOMEM;
			mlog_errno(status);
			goto bail;
		}

		mutex_lock(&ext_alloc_inode->i_mutex);
		(*tc)->tc_ext_alloc_inode = ext_alloc_inode;

		status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
		if (status < 0) {
			mlog_errno(status);
			goto bail;
		}
		(*tc)->tc_ext_alloc_bh = ext_alloc_bh;
		(*tc)->tc_ext_alloc_locked = 1;
	}

	status = 0;
bail:
	if (status < 0) {
@@ -4081,16 +4036,13 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,

static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
{
	if (tc->tc_ext_alloc_inode) {
		if (tc->tc_ext_alloc_locked)
			ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);

		mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
		iput(tc->tc_ext_alloc_inode);
	}

	if (tc->tc_ext_alloc_bh)
		brelse(tc->tc_ext_alloc_bh);
	/*
	 * The caller is responsible for completing deallocation
	 * before freeing the context.
	 */
	if (tc->tc_dealloc.c_first_suballocator != NULL)
		mlog(ML_NOTICE,
		     "Truncate completion has non-empty dealloc context\n");

	if (tc->tc_last_eb_bh)
		brelse(tc->tc_last_eb_bh);
+1 −2
Original line number Diff line number Diff line
@@ -83,8 +83,7 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,
		       struct ocfs2_cached_dealloc_ctxt *ctxt);

struct ocfs2_truncate_context {
	struct inode *tc_ext_alloc_inode;
	struct buffer_head *tc_ext_alloc_bh;
	struct ocfs2_cached_dealloc_ctxt tc_dealloc;
	int tc_ext_alloc_locked; /* is it cluster locked? */
	/* these get destroyed once it's passed to ocfs2_commit_truncate. */
	struct buffer_head *tc_last_eb_bh;
+1 −0
Original line number Diff line number Diff line
@@ -1498,6 +1498,7 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
	ocfs2_journal_dirty(handle, wc->w_di_bh);

	ocfs2_commit_trans(osb, handle);

	ocfs2_free_write_ctxt(wc);

	return copied;
+0 −13
Original line number Diff line number Diff line
@@ -1708,19 +1708,6 @@ int ocfs2_free_dinode(handle_t *handle,
					inode_alloc_bh, bit, bg_blkno, 1);
}

int ocfs2_free_extent_block(handle_t *handle,
			    struct inode *eb_alloc_inode,
			    struct buffer_head *eb_alloc_bh,
			    struct ocfs2_extent_block *eb)
{
	u64 blk = le64_to_cpu(eb->h_blkno);
	u16 bit = le16_to_cpu(eb->h_suballoc_bit);
	u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);

	return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
					bit, bg_blkno, 1);
}

int ocfs2_free_clusters(handle_t *handle,
		       struct inode *bitmap_inode,
		       struct buffer_head *bitmap_bh,
+0 −4
Original line number Diff line number Diff line
@@ -96,10 +96,6 @@ int ocfs2_free_dinode(handle_t *handle,
		      struct inode *inode_alloc_inode,
		      struct buffer_head *inode_alloc_bh,
		      struct ocfs2_dinode *di);
int ocfs2_free_extent_block(handle_t *handle,
			    struct inode *eb_alloc_inode,
			    struct buffer_head *eb_alloc_bh,
			    struct ocfs2_extent_block *eb);
int ocfs2_free_clusters(handle_t *handle,
			struct inode *bitmap_inode,
			struct buffer_head *bitmap_bh,