diff options
-rw-r--r-- | fs/ocfs2/alloc.c | 102 | ||||
-rw-r--r-- | fs/ocfs2/alloc.h | 3 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 1 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.c | 13 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.h | 4 |
5 files changed, 29 insertions, 94 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 | ||
52 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc); | 52 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc); |
53 | static 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 | ||
3166 | static 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 | */ |
3982 | int ocfs2_prepare_truncate(struct ocfs2_super *osb, | 3976 | int 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; |
4072 | bail: | 4027 | bail: |
4073 | if (status < 0) { | 4028 | if (status < 0) { |
@@ -4081,16 +4036,13 @@ bail: | |||
4081 | 4036 | ||
4082 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) | 4037 | static 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); |
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 01db0adc2150..cb02e53b593c 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h | |||
@@ -83,8 +83,7 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb, | |||
83 | struct ocfs2_cached_dealloc_ctxt *ctxt); | 83 | struct ocfs2_cached_dealloc_ctxt *ctxt); |
84 | 84 | ||
85 | struct ocfs2_truncate_context { | 85 | struct ocfs2_truncate_context { |
86 | struct inode *tc_ext_alloc_inode; | 86 | struct ocfs2_cached_dealloc_ctxt tc_dealloc; |
87 | struct buffer_head *tc_ext_alloc_bh; | ||
88 | int tc_ext_alloc_locked; /* is it cluster locked? */ | 87 | int tc_ext_alloc_locked; /* is it cluster locked? */ |
89 | /* these get destroyed once it's passed to ocfs2_commit_truncate. */ | 88 | /* these get destroyed once it's passed to ocfs2_commit_truncate. */ |
90 | struct buffer_head *tc_last_eb_bh; | 89 | struct buffer_head *tc_last_eb_bh; |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index e8d16ae12ef0..510bf84c9cf5 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1498,6 +1498,7 @@ int ocfs2_write_end_nolock(struct address_space *mapping, | |||
1498 | ocfs2_journal_dirty(handle, wc->w_di_bh); | 1498 | ocfs2_journal_dirty(handle, wc->w_di_bh); |
1499 | 1499 | ||
1500 | ocfs2_commit_trans(osb, handle); | 1500 | ocfs2_commit_trans(osb, handle); |
1501 | |||
1501 | ocfs2_free_write_ctxt(wc); | 1502 | ocfs2_free_write_ctxt(wc); |
1502 | 1503 | ||
1503 | return copied; | 1504 | return copied; |
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 6788f2f1a667..82bf12f887a6 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -1708,19 +1708,6 @@ int ocfs2_free_dinode(handle_t *handle, | |||
1708 | inode_alloc_bh, bit, bg_blkno, 1); | 1708 | inode_alloc_bh, bit, bg_blkno, 1); |
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | int ocfs2_free_extent_block(handle_t *handle, | ||
1712 | struct inode *eb_alloc_inode, | ||
1713 | struct buffer_head *eb_alloc_bh, | ||
1714 | struct ocfs2_extent_block *eb) | ||
1715 | { | ||
1716 | u64 blk = le64_to_cpu(eb->h_blkno); | ||
1717 | u16 bit = le16_to_cpu(eb->h_suballoc_bit); | ||
1718 | u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit); | ||
1719 | |||
1720 | return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh, | ||
1721 | bit, bg_blkno, 1); | ||
1722 | } | ||
1723 | |||
1724 | int ocfs2_free_clusters(handle_t *handle, | 1711 | int ocfs2_free_clusters(handle_t *handle, |
1725 | struct inode *bitmap_inode, | 1712 | struct inode *bitmap_inode, |
1726 | struct buffer_head *bitmap_bh, | 1713 | struct buffer_head *bitmap_bh, |
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index 7bc4819db4db..f212dc01a84b 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h | |||
@@ -96,10 +96,6 @@ int ocfs2_free_dinode(handle_t *handle, | |||
96 | struct inode *inode_alloc_inode, | 96 | struct inode *inode_alloc_inode, |
97 | struct buffer_head *inode_alloc_bh, | 97 | struct buffer_head *inode_alloc_bh, |
98 | struct ocfs2_dinode *di); | 98 | struct ocfs2_dinode *di); |
99 | int ocfs2_free_extent_block(handle_t *handle, | ||
100 | struct inode *eb_alloc_inode, | ||
101 | struct buffer_head *eb_alloc_bh, | ||
102 | struct ocfs2_extent_block *eb); | ||
103 | int ocfs2_free_clusters(handle_t *handle, | 99 | int ocfs2_free_clusters(handle_t *handle, |
104 | struct inode *bitmap_inode, | 100 | struct inode *bitmap_inode, |
105 | struct buffer_head *bitmap_bh, | 101 | struct buffer_head *bitmap_bh, |