diff options
Diffstat (limited to 'fs/ocfs2/alloc.c')
| -rw-r--r-- | fs/ocfs2/alloc.c | 509 | 
1 files changed, 304 insertions, 205 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 592fae5007d..9d8fcf2f3b9 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -29,8 +29,8 @@  #include <linux/highmem.h>  #include <linux/swap.h>  #include <linux/quotaops.h> +#include <linux/blkdev.h> -#define MLOG_MASK_PREFIX ML_DISK_ALLOC  #include <cluster/masklog.h>  #include "ocfs2.h" @@ -50,6 +50,7 @@  #include "uptodate.h"  #include "xattr.h"  #include "refcounttree.h" +#include "ocfs2_trace.h"  #include "buffer_head_io.h" @@ -565,7 +566,6 @@ static inline int ocfs2_et_sanity_check(struct ocfs2_extent_tree *et)  	return ret;  } -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);  static void ocfs2_adjust_rightmost_records(handle_t *handle, @@ -887,8 +887,7 @@ static int ocfs2_validate_extent_block(struct super_block *sb,  	struct ocfs2_extent_block *eb =  		(struct ocfs2_extent_block *)bh->b_data; -	mlog(0, "Validating extent block %llu\n", -	     (unsigned long long)bh->b_blocknr); +	trace_ocfs2_validate_extent_block((unsigned long long)bh->b_blocknr);  	BUG_ON(!buffer_uptodate(bh)); @@ -966,8 +965,6 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,  	struct buffer_head *eb_bh = NULL;  	u64 last_eb_blk = 0; -	mlog_entry_void(); -  	el = et->et_root_el;  	last_eb_blk = ocfs2_et_get_last_eb_blk(et); @@ -988,7 +985,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,  bail:  	brelse(eb_bh); -	mlog_exit(retval); +	trace_ocfs2_num_free_extents(retval);  	return retval;  } @@ -1011,8 +1008,6 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,  		OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));  	struct ocfs2_extent_block *eb; -	mlog_entry_void(); -  	count = 0;  	while (count < wanted) {  		status = ocfs2_claim_metadata(handle, @@ -1030,7 +1025,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,  		for(i = count;  i < (num_got + count); i++) {  			bhs[i] = sb_getblk(osb->sb, first_blkno);  			if (bhs[i] == NULL) { -				status = -EIO; +				status = -ENOMEM;  				mlog_errno(status);  				goto bail;  			} @@ -1075,8 +1070,8 @@ bail:  			brelse(bhs[i]);  			bhs[i] = NULL;  		} +		mlog_errno(status);  	} -	mlog_exit(status);  	return status;  } @@ -1139,7 +1134,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle,  	}  	el = path_leaf_el(path); -	rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1]; +	rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1];  	ocfs2_adjust_rightmost_records(handle, et, path, rec); @@ -1174,8 +1169,6 @@ static int ocfs2_add_branch(handle_t *handle,  	struct ocfs2_extent_list  *el;  	u32 new_cpos, root_end; -	mlog_entry_void(); -  	BUG_ON(!last_eb_bh || !*last_eb_bh);  	if (eb_bh) { @@ -1201,8 +1194,11 @@ static int ocfs2_add_branch(handle_t *handle,  	 * from new_cpos).  	 */  	if (root_end > new_cpos) { -		mlog(0, "adjust the cluster end from %u to %u\n", -		     root_end, new_cpos); +		trace_ocfs2_adjust_rightmost_branch( +			(unsigned long long) +			ocfs2_metadata_cache_owner(et->et_ci), +			root_end, new_cpos); +  		status = ocfs2_adjust_rightmost_branch(handle, et);  		if (status) {  			mlog_errno(status); @@ -1333,7 +1329,6 @@ bail:  		kfree(new_eb_bhs);  	} -	mlog_exit(status);  	return status;  } @@ -1354,8 +1349,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle,  	struct ocfs2_extent_list  *root_el;  	struct ocfs2_extent_list  *eb_el; -	mlog_entry_void(); -  	status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac,  					   &new_eb_bh);  	if (status < 0) { @@ -1416,7 +1409,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle,  bail:  	brelse(new_eb_bh); -	mlog_exit(status);  	return status;  } @@ -1447,8 +1439,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et,  	struct buffer_head *bh = NULL;  	struct buffer_head *lowest_bh = NULL; -	mlog_entry_void(); -  	*target_bh = NULL;  	el = et->et_root_el; @@ -1504,7 +1494,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et,  bail:  	brelse(bh); -	mlog_exit(status);  	return status;  } @@ -1541,7 +1530,10 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et,  	 * another tree level */  	if (shift) {  		BUG_ON(bh); -		mlog(0, "need to shift tree depth (current = %d)\n", depth); +		trace_ocfs2_grow_tree( +			(unsigned long long) +			ocfs2_metadata_cache_owner(et->et_ci), +			depth);  		/* ocfs2_shift_tree_depth will return us a buffer with  		 * the new extent block (so we can pass that to @@ -1571,7 +1563,6 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et,  	/* call ocfs2_add_branch to add the final part of the tree with  	 * the new data. */ -	mlog(0, "add branch. bh = %p\n", bh);  	ret = ocfs2_add_branch(handle, et, bh, last_eb_bh,  			       meta_ac);  	if (ret < 0) { @@ -1646,8 +1637,9 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,  	}  	insert_index = i; -	mlog(0, "ins %u: index %d, has_empty %d, next_free %d, count %d\n", -	     insert_cpos, insert_index, has_empty, next_free, le16_to_cpu(el->l_count)); +	trace_ocfs2_rotate_leaf(insert_cpos, insert_index, +				has_empty, next_free, +				le16_to_cpu(el->l_count));  	BUG_ON(insert_index < 0);  	BUG_ON(insert_index >= le16_to_cpu(el->l_count)); @@ -2060,7 +2052,7 @@ static void ocfs2_complete_edge_insert(handle_t *handle,  	left_el = path_leaf_el(left_path);  	right_el = path_leaf_el(right_path);  	for(i = left_path->p_tree_depth - 1; i > subtree_index; i--) { -		mlog(0, "Adjust records at index %u\n", i); +		trace_ocfs2_complete_edge_insert(i);  		/*  		 * One nice property of knowing that all of these @@ -2390,7 +2382,9 @@ static int ocfs2_rotate_tree_right(handle_t *handle,  		goto out;  	} -	mlog(0, "Insert: %u, first left path cpos: %u\n", insert_cpos, cpos); +	trace_ocfs2_rotate_tree_right( +		(unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), +		insert_cpos, cpos);  	/*  	 * What we want to do here is: @@ -2419,8 +2413,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle,  	 * rotating subtrees.  	 */  	while (cpos && insert_cpos <= cpos) { -		mlog(0, "Rotating a tree: ins. cpos: %u, left path cpos: %u\n", -		     insert_cpos, cpos); +		trace_ocfs2_rotate_tree_right( +			(unsigned long long) +			ocfs2_metadata_cache_owner(et->et_ci), +			insert_cpos, cpos);  		ret = ocfs2_find_path(et->et_ci, left_path, cpos);  		if (ret) { @@ -2462,10 +2458,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle,  		start = ocfs2_find_subtree_root(et, left_path, right_path); -		mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n", -		     start, -		     (unsigned long long) right_path->p_node[start].bh->b_blocknr, -		     right_path->p_tree_depth); +		trace_ocfs2_rotate_subtree(start, +			(unsigned long long) +			right_path->p_node[start].bh->b_blocknr, +			right_path->p_tree_depth);  		ret = ocfs2_extend_rotate_transaction(handle, start,  						      orig_credits, right_path); @@ -2965,8 +2961,7 @@ static int __ocfs2_rotate_tree_left(handle_t *handle,  		subtree_root = ocfs2_find_subtree_root(et, left_path,  						       right_path); -		mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n", -		     subtree_root, +		trace_ocfs2_rotate_subtree(subtree_root,  		     (unsigned long long)  		     right_path->p_node[subtree_root].bh->b_blocknr,  		     right_path->p_tree_depth); @@ -3990,9 +3985,11 @@ static int ocfs2_append_rec_to_path(handle_t *handle,  			goto out;  		} -		mlog(0, "Append may need a left path update. cpos: %u, " -		     "left_cpos: %u\n", le32_to_cpu(insert_rec->e_cpos), -		     left_cpos); +		trace_ocfs2_append_rec_to_path( +			(unsigned long long) +			ocfs2_metadata_cache_owner(et->et_ci), +			le32_to_cpu(insert_rec->e_cpos), +			left_cpos);  		/*  		 * No need to worry if the append is already in the @@ -4523,7 +4520,7 @@ set_tail_append:  }  /* - * Helper function called at the begining of an insert. + * Helper function called at the beginning of an insert.   *   * This computes a few things that are commonly used in the process of   * inserting into the btree: @@ -4563,7 +4560,7 @@ static int ocfs2_figure_insert_type(struct ocfs2_extent_tree *et,  					      ocfs2_et_get_last_eb_blk(et),  					      &bh);  		if (ret) { -			mlog_exit(ret); +			mlog_errno(ret);  			goto out;  		}  		eb = (struct ocfs2_extent_block *) bh->b_data; @@ -4679,9 +4676,9 @@ int ocfs2_insert_extent(handle_t *handle,  	struct ocfs2_insert_type insert = {0, };  	struct ocfs2_extent_rec rec; -	mlog(0, "add %u clusters at position %u to owner %llu\n", -	     new_clusters, cpos, -	     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci)); +	trace_ocfs2_insert_extent_start( +		(unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), +		cpos, new_clusters);  	memset(&rec, 0, sizeof(rec));  	rec.e_cpos = cpu_to_le32(cpos); @@ -4701,11 +4698,9 @@ int ocfs2_insert_extent(handle_t *handle,  		goto bail;  	} -	mlog(0, "Insert.appending: %u, Insert.Contig: %u, " -	     "Insert.contig_index: %d, Insert.free_records: %d, " -	     "Insert.tree_depth: %d\n", -	     insert.ins_appending, insert.ins_contig, insert.ins_contig_index, -	     free_records, insert.ins_tree_depth); +	trace_ocfs2_insert_extent(insert.ins_appending, insert.ins_contig, +				  insert.ins_contig_index, free_records, +				  insert.ins_tree_depth);  	if (insert.ins_contig == CONTIG_NONE && free_records == 0) {  		status = ocfs2_grow_tree(handle, et, @@ -4727,7 +4722,6 @@ int ocfs2_insert_extent(handle_t *handle,  bail:  	brelse(last_eb_bh); -	mlog_exit(status);  	return status;  } @@ -4747,7 +4741,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,  				struct ocfs2_alloc_context *meta_ac,  				enum ocfs2_alloc_restarted *reason_ret)  { -	int status = 0; +	int status = 0, err = 0; +	int need_free = 0;  	int free_extents;  	enum ocfs2_alloc_restarted reason = RESTART_NONE;  	u32 bit_off, num_bits; @@ -4774,14 +4769,14 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,  	 * 2) we are so fragmented, we've needed to add metadata too  	 *    many times. */  	if (!free_extents && !meta_ac) { -		mlog(0, "we haven't reserved any metadata!\n"); +		err = -1;  		status = -EAGAIN;  		reason = RESTART_META;  		goto leave;  	} else if ((!free_extents)  		   && (ocfs2_alloc_context_bits_left(meta_ac)  		       < ocfs2_extend_meta_needed(et->et_root_el))) { -		mlog(0, "filesystem is really fragmented...\n"); +		err = -2;  		status = -EAGAIN;  		reason = RESTART_META;  		goto leave; @@ -4802,18 +4797,20 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,  					      OCFS2_JOURNAL_ACCESS_WRITE);  	if (status < 0) {  		mlog_errno(status); -		goto leave; +		need_free = 1; +		goto bail;  	}  	block = ocfs2_clusters_to_blocks(osb->sb, bit_off); -	mlog(0, "Allocating %u clusters at block %u for owner %llu\n", -	     num_bits, bit_off, -	     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci)); +	trace_ocfs2_add_clusters_in_btree( +	     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), +	     bit_off, num_bits);  	status = ocfs2_insert_extent(handle, et, *logical_offset, block,  				     num_bits, flags, meta_ac);  	if (status < 0) {  		mlog_errno(status); -		goto leave; +		need_free = 1; +		goto bail;  	}  	ocfs2_journal_dirty(handle, et->et_root_bh); @@ -4822,16 +4819,28 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,  	*logical_offset += num_bits;  	if (clusters_to_add) { -		mlog(0, "need to alloc once more, wanted = %u\n", -		     clusters_to_add); +		err = clusters_to_add;  		status = -EAGAIN;  		reason = RESTART_TRANS;  	} +bail: +	if (need_free) { +		if (data_ac->ac_which == OCFS2_AC_USE_LOCAL) +			ocfs2_free_local_alloc_bits(osb, handle, data_ac, +					bit_off, num_bits); +		else +			ocfs2_free_clusters(handle, +					data_ac->ac_inode, +					data_ac->ac_bh, +					ocfs2_clusters_to_blocks(osb->sb, bit_off), +					num_bits); +	} +  leave: -	mlog_exit(status);  	if (reason_ret)  		*reason_ret = reason; +	trace_ocfs2_add_clusters_in_btree_ret(status, reason, err);  	return status;  } @@ -5040,7 +5049,7 @@ int ocfs2_split_extent(handle_t *handle,  					      ocfs2_et_get_last_eb_blk(et),  					      &last_eb_bh);  		if (ret) { -			mlog_exit(ret); +			mlog_errno(ret);  			goto out;  		} @@ -5057,9 +5066,9 @@ int ocfs2_split_extent(handle_t *handle,  	ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]); -	mlog(0, "index: %d, contig: %u, has_empty: %u, split_covers: %u\n", -	     split_index, ctxt.c_contig_type, ctxt.c_has_empty_extent, -	     ctxt.c_split_covers_rec); +	trace_ocfs2_split_extent(split_index, ctxt.c_contig_type, +				 ctxt.c_has_empty_extent, +				 ctxt.c_split_covers_rec);  	if (ctxt.c_contig_type == CONTIG_NONE) {  		if (ctxt.c_split_covers_rec) @@ -5193,8 +5202,9 @@ int ocfs2_mark_extent_written(struct inode *inode,  {  	int ret; -	mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n", -	     inode->i_ino, cpos, len, phys); +	trace_ocfs2_mark_extent_written( +		(unsigned long long)OCFS2_I(inode)->ip_blkno, +		cpos, len, phys);  	if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {  		ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents " @@ -5513,11 +5523,10 @@ int ocfs2_remove_extent(handle_t *handle,  	BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range); -	mlog(0, "Owner %llu, remove (cpos %u, len %u). Existing index %d " -	     "(cpos %u, len %u)\n", -	     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), -	     cpos, len, index, -	     le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec)); +	trace_ocfs2_remove_extent( +		(unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), +		cpos, len, index, le32_to_cpu(rec->e_cpos), +		ocfs2_rec_clusters(el, rec));  	if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {  		ret = ocfs2_truncate_rec(handle, et, path, index, dealloc, @@ -5662,7 +5671,7 @@ int ocfs2_remove_btree_range(struct inode *inode,  					       &ref_tree, NULL);  		if (ret) {  			mlog_errno(ret); -			goto out; +			goto bail;  		}  		ret = ocfs2_prepare_refcount_change_for_del(inode, @@ -5673,7 +5682,7 @@ int ocfs2_remove_btree_range(struct inode *inode,  							    &extra_blocks);  		if (ret < 0) {  			mlog_errno(ret); -			goto out; +			goto bail;  		}  	} @@ -5681,7 +5690,7 @@ int ocfs2_remove_btree_range(struct inode *inode,  						 extra_blocks);  	if (ret) {  		mlog_errno(ret); -		return ret; +		goto bail;  	}  	mutex_lock(&tl_inode->i_mutex); @@ -5706,7 +5715,7 @@ int ocfs2_remove_btree_range(struct inode *inode,  					   OCFS2_JOURNAL_ACCESS_WRITE);  	if (ret) {  		mlog_errno(ret); -		goto out; +		goto out_commit;  	}  	dquot_free_space_nodirty(inode, @@ -5719,6 +5728,7 @@ int ocfs2_remove_btree_range(struct inode *inode,  	}  	ocfs2_et_update_clusters(et, -len); +	ocfs2_update_inode_fsync_trans(handle, inode, 1);  	ocfs2_journal_dirty(handle, et->et_root_bh); @@ -5741,7 +5751,7 @@ out_commit:  	ocfs2_commit_trans(osb, handle);  out:  	mutex_unlock(&tl_inode->i_mutex); - +bail:  	if (meta_ac)  		ocfs2_free_alloc_context(meta_ac); @@ -5796,9 +5806,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,  	struct ocfs2_dinode *di;  	struct ocfs2_truncate_log *tl; -	mlog_entry("start_blk = %llu, num_clusters = %u\n", -		   (unsigned long long)start_blk, num_clusters); -  	BUG_ON(mutex_trylock(&tl_inode->i_mutex));  	start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk); @@ -5835,10 +5842,9 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,  		goto bail;  	} -	mlog(0, "Log truncate of %u clusters starting at cluster %u to " -	     "%llu (index = %d)\n", num_clusters, start_cluster, -	     (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index); - +	trace_ocfs2_truncate_log_append( +		(unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index, +		start_cluster, num_clusters);  	if (ocfs2_truncate_log_can_coalesce(tl, start_cluster)) {  		/*  		 * Move index back to the record we are coalescing with. @@ -5847,9 +5853,10 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,  		index--;  		num_clusters += le32_to_cpu(tl->tl_recs[index].t_clusters); -		mlog(0, "Coalesce with index %u (start = %u, clusters = %u)\n", -		     index, le32_to_cpu(tl->tl_recs[index].t_start), -		     num_clusters); +		trace_ocfs2_truncate_log_append( +			(unsigned long long)OCFS2_I(tl_inode)->ip_blkno, +			index, le32_to_cpu(tl->tl_recs[index].t_start), +			num_clusters);  	} else {  		tl->tl_recs[index].t_start = cpu_to_le32(start_cluster);  		tl->tl_used = cpu_to_le16(index + 1); @@ -5858,8 +5865,8 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,  	ocfs2_journal_dirty(handle, tl_bh); +	osb->truncated_clusters += num_clusters;  bail: -	mlog_exit(status);  	return status;  } @@ -5878,8 +5885,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,  	struct inode *tl_inode = osb->osb_tl_inode;  	struct buffer_head *tl_bh = osb->osb_tl_bh; -	mlog_entry_void(); -  	di = (struct ocfs2_dinode *) tl_bh->b_data;  	tl = &di->id2.i_dealloc;  	i = le16_to_cpu(tl->tl_used) - 1; @@ -5915,8 +5920,9 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,  		/* if start_blk is not set, we ignore the record as  		 * invalid. */  		if (start_blk) { -			mlog(0, "free record %d, start = %u, clusters = %u\n", -			     i, le32_to_cpu(rec.t_start), num_clusters); +			trace_ocfs2_replay_truncate_records( +				(unsigned long long)OCFS2_I(tl_inode)->ip_blkno, +				i, le32_to_cpu(rec.t_start), num_clusters);  			status = ocfs2_free_clusters(handle, data_alloc_inode,  						     data_alloc_bh, start_blk, @@ -5929,8 +5935,9 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,  		i--;  	} +	osb->truncated_clusters = 0; +  bail: -	mlog_exit(status);  	return status;  } @@ -5947,8 +5954,6 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)  	struct ocfs2_dinode *di;  	struct ocfs2_truncate_log *tl; -	mlog_entry_void(); -  	BUG_ON(mutex_trylock(&tl_inode->i_mutex));  	di = (struct ocfs2_dinode *) tl_bh->b_data; @@ -5960,8 +5965,9 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)  	tl = &di->id2.i_dealloc;  	num_to_flush = le16_to_cpu(tl->tl_used); -	mlog(0, "Flush %u records from truncate log #%llu\n", -	     num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno); +	trace_ocfs2_flush_truncate_log( +		(unsigned long long)OCFS2_I(tl_inode)->ip_blkno, +		num_to_flush);  	if (!num_to_flush) {  		status = 0;  		goto out; @@ -6007,7 +6013,6 @@ out_mutex:  	iput(data_alloc_inode);  out: -	mlog_exit(status);  	return status;  } @@ -6030,22 +6035,19 @@ static void ocfs2_truncate_log_worker(struct work_struct *work)  		container_of(work, struct ocfs2_super,  			     osb_truncate_log_wq.work); -	mlog_entry_void(); -  	status = ocfs2_flush_truncate_log(osb);  	if (status < 0)  		mlog_errno(status);  	else  		ocfs2_init_steal_slots(osb); - -	mlog_exit(status);  }  #define OCFS2_TRUNCATE_LOG_FLUSH_INTERVAL (2 * HZ)  void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb,  				       int cancel)  { -	if (osb->osb_tl_inode) { +	if (osb->osb_tl_inode && +			atomic_read(&osb->osb_tl_disable) == 0) {  		/* We want to push off log flushes while truncates are  		 * still running. */  		if (cancel) @@ -6084,7 +6086,6 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,  	*tl_inode = inode;  	*tl_bh    = bh;  bail: -	mlog_exit(status);  	return status;  } @@ -6104,7 +6105,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,  	*tl_copy = NULL; -	mlog(0, "recover truncate log from slot %d\n", slot_num); +	trace_ocfs2_begin_truncate_log_recovery(slot_num);  	status = ocfs2_get_truncate_log_info(osb, slot_num, &tl_inode, &tl_bh);  	if (status < 0) { @@ -6121,8 +6122,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,  	tl = &di->id2.i_dealloc;  	if (le16_to_cpu(tl->tl_used)) { -		mlog(0, "We'll have %u logs to recover\n", -		     le16_to_cpu(tl->tl_used)); +		trace_ocfs2_truncate_log_recovery_num(le16_to_cpu(tl->tl_used));  		*tl_copy = kmalloc(tl_bh->b_size, GFP_KERNEL);  		if (!(*tl_copy)) { @@ -6155,9 +6155,9 @@ bail:  	if (status < 0 && (*tl_copy)) {  		kfree(*tl_copy);  		*tl_copy = NULL; +		mlog_errno(status);  	} -	mlog_exit(status);  	return status;  } @@ -6172,8 +6172,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,  	struct inode *tl_inode = osb->osb_tl_inode;  	struct ocfs2_truncate_log *tl; -	mlog_entry_void(); -  	if (OCFS2_I(tl_inode)->ip_blkno == le64_to_cpu(tl_copy->i_blkno)) {  		mlog(ML_ERROR, "Asked to recover my own truncate log!\n");  		return -EINVAL; @@ -6181,8 +6179,9 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,  	tl = &tl_copy->id2.i_dealloc;  	num_recs = le16_to_cpu(tl->tl_used); -	mlog(0, "cleanup %u records from %llu\n", num_recs, -	     (unsigned long long)le64_to_cpu(tl_copy->i_blkno)); +	trace_ocfs2_complete_truncate_log_recovery( +		(unsigned long long)le64_to_cpu(tl_copy->i_blkno), +		num_recs);  	mutex_lock(&tl_inode->i_mutex);  	for(i = 0; i < num_recs; i++) { @@ -6217,7 +6216,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,  bail_up:  	mutex_unlock(&tl_inode->i_mutex); -	mlog_exit(status);  	return status;  } @@ -6226,7 +6224,7 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)  	int status;  	struct inode *tl_inode = osb->osb_tl_inode; -	mlog_entry_void(); +	atomic_set(&osb->osb_tl_disable, 1);  	if (tl_inode) {  		cancel_delayed_work(&osb->osb_truncate_log_wq); @@ -6239,8 +6237,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)  		brelse(osb->osb_tl_bh);  		iput(osb->osb_tl_inode);  	} - -	mlog_exit_void();  }  int ocfs2_truncate_log_init(struct ocfs2_super *osb) @@ -6249,8 +6245,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)  	struct inode *tl_inode = NULL;  	struct buffer_head *tl_bh = NULL; -	mlog_entry_void(); -  	status = ocfs2_get_truncate_log_info(osb,  					     osb->slot_num,  					     &tl_inode, @@ -6263,10 +6257,10 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)  	 * until we're sure all is well. */  	INIT_DELAYED_WORK(&osb->osb_truncate_log_wq,  			  ocfs2_truncate_log_worker); +	atomic_set(&osb->osb_tl_disable, 0);  	osb->osb_tl_bh    = tl_bh;  	osb->osb_tl_inode = tl_inode; -	mlog_exit(status);  	return status;  } @@ -6348,8 +6342,8 @@ static int ocfs2_free_cached_blocks(struct ocfs2_super *osb,  		else  			bg_blkno = ocfs2_which_suballoc_group(head->free_blk,  							      head->free_bit); -		mlog(0, "Free bit: (bit %u, blkno %llu)\n", -		     head->free_bit, (unsigned long long)head->free_blk); +		trace_ocfs2_free_cached_blocks( +		     (unsigned long long)head->free_blk, head->free_bit);  		ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,  					       head->free_bit, bg_blkno, 1); @@ -6402,8 +6396,7 @@ int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,  		return ret;  	} -	mlog(0, "Insert clusters: (bit %u, blk %llu)\n", -	     bit, (unsigned long long)blkno); +	trace_ocfs2_cache_cluster_dealloc((unsigned long long)blkno, bit);  	item->free_blk = blkno;  	item->free_bit = bit; @@ -6478,8 +6471,8 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,  		fl = ctxt->c_first_suballocator;  		if (fl->f_first) { -			mlog(0, "Free items: (type %u, slot %d)\n", -			     fl->f_inode_type, fl->f_slot); +			trace_ocfs2_run_deallocs(fl->f_inode_type, +						 fl->f_slot);  			ret2 = ocfs2_free_cached_blocks(osb,  							fl->f_inode_type,  							fl->f_slot, @@ -6556,8 +6549,9 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,  		goto out;  	} -	mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n", -	     type, slot, bit, (unsigned long long)blkno); +	trace_ocfs2_cache_block_dealloc(type, slot, +					(unsigned long long)suballoc, +					(unsigned long long)blkno, bit);  	item->free_bg = suballoc;  	item->free_blk = blkno; @@ -6778,8 +6772,7 @@ int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,  		mlog_errno(ret);  out: -	if (pages) -		kfree(pages); +	kfree(pages);  	return ret;  } @@ -6833,6 +6826,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,  					 struct buffer_head *di_bh)  {  	int ret, i, has_data, num_pages = 0; +	int need_free = 0; +	u32 bit_off, num;  	handle_t *handle;  	u64 uninitialized_var(block);  	struct ocfs2_inode_info *oi = OCFS2_I(inode); @@ -6878,7 +6873,6 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,  	}  	if (has_data) { -		u32 bit_off, num;  		unsigned int page_end;  		u64 phys; @@ -6914,6 +6908,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,  		ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages);  		if (ret) {  			mlog_errno(ret); +			need_free = 1;  			goto out_commit;  		} @@ -6924,6 +6919,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,  		ret = ocfs2_read_inline_data(inode, pages[0], di_bh);  		if (ret) {  			mlog_errno(ret); +			need_free = 1;  			goto out_commit;  		} @@ -6941,6 +6937,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,  	di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);  	spin_unlock(&oi->ip_lock); +	ocfs2_update_inode_fsync_trans(handle, inode, 1);  	ocfs2_dinode_new_extent_list(inode, di);  	ocfs2_journal_dirty(handle, di_bh); @@ -6955,6 +6952,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,  		ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL);  		if (ret) {  			mlog_errno(ret); +			need_free = 1;  			goto out_commit;  		} @@ -6966,6 +6964,18 @@ out_commit:  		dquot_free_space_nodirty(inode,  					  ocfs2_clusters_to_bytes(osb->sb, 1)); +	if (need_free) { +		if (data_ac->ac_which == OCFS2_AC_USE_LOCAL) +			ocfs2_free_local_alloc_bits(osb, handle, data_ac, +					bit_off, num); +		else +			ocfs2_free_clusters(handle, +					data_ac->ac_inode, +					data_ac->ac_bh, +					ocfs2_clusters_to_blocks(osb->sb, bit_off), +					num); +	} +  	ocfs2_commit_trans(osb, handle);  out_unlock: @@ -7003,8 +7013,6 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,  	struct ocfs2_extent_tree et;  	struct ocfs2_cached_dealloc_ctxt dealloc; -	mlog_entry_void(); -  	ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);  	ocfs2_init_dealloc_ctxt(&dealloc); @@ -7039,8 +7047,11 @@ start:  		goto bail;  	} -	mlog(0, "inode->ip_clusters = %u, tree_depth = %u\n", -	     OCFS2_I(inode)->ip_clusters, path->p_tree_depth); +	trace_ocfs2_commit_truncate( +		(unsigned long long)OCFS2_I(inode)->ip_blkno, +		new_highest_cpos, +		OCFS2_I(inode)->ip_clusters, +		path->p_tree_depth);  	/*  	 * By now, el will point to the extent list on the bottom most @@ -7134,65 +7145,6 @@ bail:  	ocfs2_free_path(path); -	mlog_exit(status); -	return status; -} - -/* - * 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; -	unsigned int new_i_clusters; -	struct ocfs2_dinode *fe; -	struct ocfs2_extent_block *eb; -	struct buffer_head *last_eb_bh = NULL; - -	mlog_entry_void(); - -	*tc = NULL; - -	new_i_clusters = ocfs2_clusters_for_bytes(osb->sb, -						  i_size_read(inode)); -	fe = (struct ocfs2_dinode *) fe_bh->b_data; - -	mlog(0, "fe->i_clusters = %u, new_i_clusters = %u, fe->i_size =" -	     "%llu\n", le32_to_cpu(fe->i_clusters), new_i_clusters, -	     (unsigned long long)le64_to_cpu(fe->i_size)); - -	*tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL); -	if (!(*tc)) { -		status = -ENOMEM; -		mlog_errno(status); -		goto bail; -	} -	ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc); - -	if (fe->id2.i_list.l_tree_depth) { -		status = ocfs2_read_extent_block(INODE_CACHE(inode), -						 le64_to_cpu(fe->i_last_eb_blk), -						 &last_eb_bh); -		if (status < 0) { -			mlog_errno(status); -			goto bail; -		} -		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data; -	} - -	(*tc)->tc_last_eb_bh = last_eb_bh; - -	status = 0; -bail: -	if (status < 0) { -		if (*tc) -			ocfs2_free_truncate_context(*tc); -		*tc = NULL; -	} -	mlog_exit_void();  	return status;  } @@ -7212,7 +7164,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,  	if (end > i_size_read(inode))  		end = i_size_read(inode); -	BUG_ON(start >= end); +	BUG_ON(start > end);  	if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) ||  	    !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || @@ -7262,6 +7214,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,  	di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec);  	di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); +	ocfs2_update_inode_fsync_trans(handle, inode, 1);  	ocfs2_journal_dirty(handle, di_bh);  out_commit: @@ -7271,17 +7224,163 @@ out:  	return ret;  } -static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) +static int ocfs2_trim_extent(struct super_block *sb, +			     struct ocfs2_group_desc *gd, +			     u32 start, u32 count)  { -	/* -	 * 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"); +	u64 discard, bcount; + +	bcount = ocfs2_clusters_to_blocks(sb, count); +	discard = le64_to_cpu(gd->bg_blkno) + +			ocfs2_clusters_to_blocks(sb, start); + +	trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); + +	return sb_issue_discard(sb, discard, bcount, GFP_NOFS, 0); +} + +static int ocfs2_trim_group(struct super_block *sb, +			    struct ocfs2_group_desc *gd, +			    u32 start, u32 max, u32 minbits) +{ +	int ret = 0, count = 0, next; +	void *bitmap = gd->bg_bitmap; + +	if (le16_to_cpu(gd->bg_free_bits_count) < minbits) +		return 0; + +	trace_ocfs2_trim_group((unsigned long long)le64_to_cpu(gd->bg_blkno), +			       start, max, minbits); + +	while (start < max) { +		start = ocfs2_find_next_zero_bit(bitmap, max, start); +		if (start >= max) +			break; +		next = ocfs2_find_next_bit(bitmap, max, start); + +		if ((next - start) >= minbits) { +			ret = ocfs2_trim_extent(sb, gd, +						start, next - start); +			if (ret < 0) { +				mlog_errno(ret); +				break; +			} +			count += next - start; +		} +		start = next + 1; + +		if (fatal_signal_pending(current)) { +			count = -ERESTARTSYS; +			break; +		} + +		if ((le16_to_cpu(gd->bg_free_bits_count) - count) < minbits) +			break; +	} + +	if (ret < 0) +		count = ret; + +	return count; +} + +int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range) +{ +	struct ocfs2_super *osb = OCFS2_SB(sb); +	u64 start, len, trimmed, first_group, last_group, group; +	int ret, cnt; +	u32 first_bit, last_bit, minlen; +	struct buffer_head *main_bm_bh = NULL; +	struct inode *main_bm_inode = NULL; +	struct buffer_head *gd_bh = NULL; +	struct ocfs2_dinode *main_bm; +	struct ocfs2_group_desc *gd = NULL; -	brelse(tc->tc_last_eb_bh); +	start = range->start >> osb->s_clustersize_bits; +	len = range->len >> osb->s_clustersize_bits; +	minlen = range->minlen >> osb->s_clustersize_bits; -	kfree(tc); +	if (minlen >= osb->bitmap_cpg || range->len < sb->s_blocksize) +		return -EINVAL; + +	main_bm_inode = ocfs2_get_system_file_inode(osb, +						    GLOBAL_BITMAP_SYSTEM_INODE, +						    OCFS2_INVALID_SLOT); +	if (!main_bm_inode) { +		ret = -EIO; +		mlog_errno(ret); +		goto out; +	} + +	mutex_lock(&main_bm_inode->i_mutex); + +	ret = ocfs2_inode_lock(main_bm_inode, &main_bm_bh, 0); +	if (ret < 0) { +		mlog_errno(ret); +		goto out_mutex; +	} +	main_bm = (struct ocfs2_dinode *)main_bm_bh->b_data; + +	if (start >= le32_to_cpu(main_bm->i_clusters)) { +		ret = -EINVAL; +		goto out_unlock; +	} + +	len = range->len >> osb->s_clustersize_bits; +	if (start + len > le32_to_cpu(main_bm->i_clusters)) +		len = le32_to_cpu(main_bm->i_clusters) - start; + +	trace_ocfs2_trim_fs(start, len, minlen); + +	/* Determine first and last group to examine based on start and len */ +	first_group = ocfs2_which_cluster_group(main_bm_inode, start); +	if (first_group == osb->first_cluster_group_blkno) +		first_bit = start; +	else +		first_bit = start - ocfs2_blocks_to_clusters(sb, first_group); +	last_group = ocfs2_which_cluster_group(main_bm_inode, start + len - 1); +	last_bit = osb->bitmap_cpg; + +	trimmed = 0; +	for (group = first_group; group <= last_group;) { +		if (first_bit + len >= osb->bitmap_cpg) +			last_bit = osb->bitmap_cpg; +		else +			last_bit = first_bit + len; + +		ret = ocfs2_read_group_descriptor(main_bm_inode, +						  main_bm, group, +						  &gd_bh); +		if (ret < 0) { +			mlog_errno(ret); +			break; +		} + +		gd = (struct ocfs2_group_desc *)gd_bh->b_data; +		cnt = ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); +		brelse(gd_bh); +		gd_bh = NULL; +		if (cnt < 0) { +			ret = cnt; +			mlog_errno(ret); +			break; +		} + +		trimmed += cnt; +		len -= osb->bitmap_cpg - first_bit; +		first_bit = 0; +		if (group == osb->first_cluster_group_blkno) +			group = ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); +		else +			group += ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); +	} +	range->len = trimmed * sb->s_blocksize; +out_unlock: +	ocfs2_inode_unlock(main_bm_inode, 0); +	brelse(main_bm_bh); +out_mutex: +	mutex_unlock(&main_bm_inode->i_mutex); +	iput(main_bm_inode); +out: +	return ret;  }  | 
