aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/alloc.c
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-06-22 18:52:36 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-07-10 20:31:55 -0400
commit59a5e416d1ab543a5248a2b34d83202c4d55d132 (patch)
tree3e97ce48774d26e8a927edd839dd54a7d68f8c7d /fs/ocfs2/alloc.c
parent2b604351bc99b4e4504758cbac369b660b71de0b (diff)
ocfs2: plug truncate into cached dealloc routines
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r--fs/ocfs2/alloc.c102
1 files changed, 27 insertions, 75 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 873bb99fc2ff..26e867087e95 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -50,6 +50,8 @@
50#include "buffer_head_io.h" 50#include "buffer_head_io.h"
51 51
52static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc); 52static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
53static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
54 struct ocfs2_extent_block *eb);
53 55
54/* 56/*
55 * Structures which describe a path through a btree, and functions to 57 * Structures which describe a path through a btree, and functions to
@@ -3161,6 +3163,15 @@ out:
3161 return ret; 3163 return ret;
3162} 3164}
3163 3165
3166static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
3167 struct ocfs2_extent_block *eb)
3168{
3169 return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
3170 le16_to_cpu(eb->h_suballoc_slot),
3171 le64_to_cpu(eb->h_blkno),
3172 le16_to_cpu(eb->h_suballoc_bit));
3173}
3174
3164/* This function will figure out whether the currently last extent 3175/* This function will figure out whether the currently last extent
3165 * block will be deleted, and if it will, what the new last extent 3176 * block will be deleted, and if it will, what the new last extent
3166 * block will be so we can update his h_next_leaf_blk field, as well 3177 * block will be so we can update his h_next_leaf_blk field, as well
@@ -3442,27 +3453,10 @@ delete:
3442 BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos)); 3453 BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
3443 BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno)); 3454 BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
3444 3455
3445 if (le16_to_cpu(eb->h_suballoc_slot) == 0) { 3456 ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
3446 /* 3457 /* An error here is not fatal. */
3447 * This code only understands how to 3458 if (ret < 0)
3448 * lock the suballocator in slot 0, 3459 mlog_errno(ret);
3449 * which is fine because allocation is
3450 * only ever done out of that
3451 * suballocator too. A future version
3452 * might change that however, so avoid
3453 * a free if we don't know how to
3454 * handle it. This way an fs incompat
3455 * bit will not be necessary.
3456 */
3457 ret = ocfs2_free_extent_block(handle,
3458 tc->tc_ext_alloc_inode,
3459 tc->tc_ext_alloc_bh,
3460 eb);
3461
3462 /* An error here is not fatal. */
3463 if (ret < 0)
3464 mlog_errno(ret);
3465 }
3466 } else { 3460 } else {
3467 deleted_eb = 0; 3461 deleted_eb = 0;
3468 } 3462 }
@@ -3965,6 +3959,8 @@ bail:
3965 if (handle) 3959 if (handle)
3966 ocfs2_commit_trans(osb, handle); 3960 ocfs2_commit_trans(osb, handle);
3967 3961
3962 ocfs2_run_deallocs(osb, &tc->tc_dealloc);
3963
3968 ocfs2_free_path(path); 3964 ocfs2_free_path(path);
3969 3965
3970 /* This will drop the ext_alloc cluster lock for us */ 3966 /* This will drop the ext_alloc cluster lock for us */
@@ -3975,23 +3971,18 @@ bail:
3975} 3971}
3976 3972
3977/* 3973/*
3978 * Expects the inode to already be locked. This will figure out which 3974 * Expects the inode to already be locked.
3979 * inodes need to be locked and will put them on the returned truncate
3980 * context.
3981 */ 3975 */
3982int ocfs2_prepare_truncate(struct ocfs2_super *osb, 3976int ocfs2_prepare_truncate(struct ocfs2_super *osb,
3983 struct inode *inode, 3977 struct inode *inode,
3984 struct buffer_head *fe_bh, 3978 struct buffer_head *fe_bh,
3985 struct ocfs2_truncate_context **tc) 3979 struct ocfs2_truncate_context **tc)
3986{ 3980{
3987 int status, metadata_delete, i; 3981 int status;
3988 unsigned int new_i_clusters; 3982 unsigned int new_i_clusters;
3989 struct ocfs2_dinode *fe; 3983 struct ocfs2_dinode *fe;
3990 struct ocfs2_extent_block *eb; 3984 struct ocfs2_extent_block *eb;
3991 struct ocfs2_extent_list *el;
3992 struct buffer_head *last_eb_bh = NULL; 3985 struct buffer_head *last_eb_bh = NULL;
3993 struct inode *ext_alloc_inode = NULL;
3994 struct buffer_head *ext_alloc_bh = NULL;
3995 3986
3996 mlog_entry_void(); 3987 mlog_entry_void();
3997 3988
@@ -4011,12 +4002,9 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
4011 mlog_errno(status); 4002 mlog_errno(status);
4012 goto bail; 4003 goto bail;
4013 } 4004 }
4005 ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
4014 4006
4015 metadata_delete = 0;
4016 if (fe->id2.i_list.l_tree_depth) { 4007 if (fe->id2.i_list.l_tree_depth) {
4017 /* If we have a tree, then the truncate may result in
4018 * metadata deletes. Figure this out from the
4019 * rightmost leaf block.*/
4020 status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk), 4008 status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
4021 &last_eb_bh, OCFS2_BH_CACHED, inode); 4009 &last_eb_bh, OCFS2_BH_CACHED, inode);
4022 if (status < 0) { 4010 if (status < 0) {
@@ -4031,43 +4019,10 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
4031 status = -EIO; 4019 status = -EIO;
4032 goto bail; 4020 goto bail;
4033 } 4021 }
4034 el = &(eb->h_list);
4035
4036 i = 0;
4037 if (ocfs2_is_empty_extent(&el->l_recs[0]))
4038 i = 1;
4039 /*
4040 * XXX: Should we check that next_free_rec contains
4041 * the extent?
4042 */
4043 if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
4044 metadata_delete = 1;
4045 } 4022 }
4046 4023
4047 (*tc)->tc_last_eb_bh = last_eb_bh; 4024 (*tc)->tc_last_eb_bh = last_eb_bh;
4048 4025
4049 if (metadata_delete) {
4050 mlog(0, "Will have to delete metadata for this trunc. "
4051 "locking allocator.\n");
4052 ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
4053 if (!ext_alloc_inode) {
4054 status = -ENOMEM;
4055 mlog_errno(status);
4056 goto bail;
4057 }
4058
4059 mutex_lock(&ext_alloc_inode->i_mutex);
4060 (*tc)->tc_ext_alloc_inode = ext_alloc_inode;
4061
4062 status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
4063 if (status < 0) {
4064 mlog_errno(status);
4065 goto bail;
4066 }
4067 (*tc)->tc_ext_alloc_bh = ext_alloc_bh;
4068 (*tc)->tc_ext_alloc_locked = 1;
4069 }
4070
4071 status = 0; 4026 status = 0;
4072bail: 4027bail:
4073 if (status < 0) { 4028 if (status < 0) {
@@ -4081,16 +4036,13 @@ bail:
4081 4036
4082static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) 4037static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
4083{ 4038{
4084 if (tc->tc_ext_alloc_inode) { 4039 /*
4085 if (tc->tc_ext_alloc_locked) 4040 * The caller is responsible for completing deallocation
4086 ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1); 4041 * before freeing the context.
4087 4042 */
4088 mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex); 4043 if (tc->tc_dealloc.c_first_suballocator != NULL)
4089 iput(tc->tc_ext_alloc_inode); 4044 mlog(ML_NOTICE,
4090 } 4045 "Truncate completion has non-empty dealloc context\n");
4091
4092 if (tc->tc_ext_alloc_bh)
4093 brelse(tc->tc_ext_alloc_bh);
4094 4046
4095 if (tc->tc_last_eb_bh) 4047 if (tc->tc_last_eb_bh)
4096 brelse(tc->tc_last_eb_bh); 4048 brelse(tc->tc_last_eb_bh);