diff options
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r-- | fs/ocfs2/alloc.c | 106 |
1 files changed, 99 insertions, 7 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 0cc2deb9394c..4614614084dd 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -5800,7 +5800,10 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) | |||
5800 | */ | 5800 | */ |
5801 | 5801 | ||
5802 | /* | 5802 | /* |
5803 | * Describes a single block free from a suballocator | 5803 | * Describe a single bit freed from a suballocator. For the block |
5804 | * suballocators, it represents one block. For the global cluster | ||
5805 | * allocator, it represents some clusters and free_bit indicates | ||
5806 | * clusters number. | ||
5804 | */ | 5807 | */ |
5805 | struct ocfs2_cached_block_free { | 5808 | struct ocfs2_cached_block_free { |
5806 | struct ocfs2_cached_block_free *free_next; | 5809 | struct ocfs2_cached_block_free *free_next; |
@@ -5815,10 +5818,10 @@ struct ocfs2_per_slot_free_list { | |||
5815 | struct ocfs2_cached_block_free *f_first; | 5818 | struct ocfs2_cached_block_free *f_first; |
5816 | }; | 5819 | }; |
5817 | 5820 | ||
5818 | static int ocfs2_free_cached_items(struct ocfs2_super *osb, | 5821 | static int ocfs2_free_cached_blocks(struct ocfs2_super *osb, |
5819 | int sysfile_type, | 5822 | int sysfile_type, |
5820 | int slot, | 5823 | int slot, |
5821 | struct ocfs2_cached_block_free *head) | 5824 | struct ocfs2_cached_block_free *head) |
5822 | { | 5825 | { |
5823 | int ret; | 5826 | int ret; |
5824 | u64 bg_blkno; | 5827 | u64 bg_blkno; |
@@ -5893,6 +5896,82 @@ out: | |||
5893 | return ret; | 5896 | return ret; |
5894 | } | 5897 | } |
5895 | 5898 | ||
5899 | int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, | ||
5900 | u64 blkno, unsigned int bit) | ||
5901 | { | ||
5902 | int ret = 0; | ||
5903 | struct ocfs2_cached_block_free *item; | ||
5904 | |||
5905 | item = kmalloc(sizeof(*item), GFP_NOFS); | ||
5906 | if (item == NULL) { | ||
5907 | ret = -ENOMEM; | ||
5908 | mlog_errno(ret); | ||
5909 | return ret; | ||
5910 | } | ||
5911 | |||
5912 | mlog(0, "Insert clusters: (bit %u, blk %llu)\n", | ||
5913 | bit, (unsigned long long)blkno); | ||
5914 | |||
5915 | item->free_blk = blkno; | ||
5916 | item->free_bit = bit; | ||
5917 | item->free_next = ctxt->c_global_allocator; | ||
5918 | |||
5919 | ctxt->c_global_allocator = item; | ||
5920 | return ret; | ||
5921 | } | ||
5922 | |||
5923 | static int ocfs2_free_cached_clusters(struct ocfs2_super *osb, | ||
5924 | struct ocfs2_cached_block_free *head) | ||
5925 | { | ||
5926 | struct ocfs2_cached_block_free *tmp; | ||
5927 | struct inode *tl_inode = osb->osb_tl_inode; | ||
5928 | handle_t *handle; | ||
5929 | int ret = 0; | ||
5930 | |||
5931 | mutex_lock(&tl_inode->i_mutex); | ||
5932 | |||
5933 | while (head) { | ||
5934 | if (ocfs2_truncate_log_needs_flush(osb)) { | ||
5935 | ret = __ocfs2_flush_truncate_log(osb); | ||
5936 | if (ret < 0) { | ||
5937 | mlog_errno(ret); | ||
5938 | break; | ||
5939 | } | ||
5940 | } | ||
5941 | |||
5942 | handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE); | ||
5943 | if (IS_ERR(handle)) { | ||
5944 | ret = PTR_ERR(handle); | ||
5945 | mlog_errno(ret); | ||
5946 | break; | ||
5947 | } | ||
5948 | |||
5949 | ret = ocfs2_truncate_log_append(osb, handle, head->free_blk, | ||
5950 | head->free_bit); | ||
5951 | |||
5952 | ocfs2_commit_trans(osb, handle); | ||
5953 | tmp = head; | ||
5954 | head = head->free_next; | ||
5955 | kfree(tmp); | ||
5956 | |||
5957 | if (ret < 0) { | ||
5958 | mlog_errno(ret); | ||
5959 | break; | ||
5960 | } | ||
5961 | } | ||
5962 | |||
5963 | mutex_unlock(&tl_inode->i_mutex); | ||
5964 | |||
5965 | while (head) { | ||
5966 | /* Premature exit may have left some dangling items. */ | ||
5967 | tmp = head; | ||
5968 | head = head->free_next; | ||
5969 | kfree(tmp); | ||
5970 | } | ||
5971 | |||
5972 | return ret; | ||
5973 | } | ||
5974 | |||
5896 | int ocfs2_run_deallocs(struct ocfs2_super *osb, | 5975 | int ocfs2_run_deallocs(struct ocfs2_super *osb, |
5897 | struct ocfs2_cached_dealloc_ctxt *ctxt) | 5976 | struct ocfs2_cached_dealloc_ctxt *ctxt) |
5898 | { | 5977 | { |
@@ -5908,8 +5987,10 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb, | |||
5908 | if (fl->f_first) { | 5987 | if (fl->f_first) { |
5909 | mlog(0, "Free items: (type %u, slot %d)\n", | 5988 | mlog(0, "Free items: (type %u, slot %d)\n", |
5910 | fl->f_inode_type, fl->f_slot); | 5989 | fl->f_inode_type, fl->f_slot); |
5911 | ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type, | 5990 | ret2 = ocfs2_free_cached_blocks(osb, |
5912 | fl->f_slot, fl->f_first); | 5991 | fl->f_inode_type, |
5992 | fl->f_slot, | ||
5993 | fl->f_first); | ||
5913 | if (ret2) | 5994 | if (ret2) |
5914 | mlog_errno(ret2); | 5995 | mlog_errno(ret2); |
5915 | if (!ret) | 5996 | if (!ret) |
@@ -5920,6 +6001,17 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb, | |||
5920 | kfree(fl); | 6001 | kfree(fl); |
5921 | } | 6002 | } |
5922 | 6003 | ||
6004 | if (ctxt->c_global_allocator) { | ||
6005 | ret2 = ocfs2_free_cached_clusters(osb, | ||
6006 | ctxt->c_global_allocator); | ||
6007 | if (ret2) | ||
6008 | mlog_errno(ret2); | ||
6009 | if (!ret) | ||
6010 | ret = ret2; | ||
6011 | |||
6012 | ctxt->c_global_allocator = NULL; | ||
6013 | } | ||
6014 | |||
5923 | return ret; | 6015 | return ret; |
5924 | } | 6016 | } |
5925 | 6017 | ||