1 From: Tao Ma <tao.ma@oracle.com>
2 Date: Wed, 12 Nov 2008 08:26:58 +0800
3 Subject: ocfs2: Add clusters free in dealloc_ctxt.
6 Now in ocfs2 xattr set, the whole process are divided into many small
7 parts and they are wrapped into diffrent transactions and it make the
8 set doesn't look like a real transaction. So we want to integrate it
11 In some cases we will allocate some clusters and free some in just one
12 transaction. e.g, one xattr is larger than inline size, so it and its
13 value root is stored within the inode while the value is outside in a
14 cluster. Then we try to update it with a smaller value(larger than the
15 size of root but smaller than inline size), we may need to free the
16 outside cluster while allocate a new bucket(one cluster) since now the
17 inode may be full. The old solution will lock the global_bitmap(if the
18 local alloc failed in stress test) and then the truncate log. This will
19 cause a ABBA lock with truncate log flush.
21 This patch add the clusters free in dealloc_ctxt, so that we can record
22 the free clusters during the transaction and then free it after we
23 release the global_bitmap in xattr set.
25 Signed-off-by: Tao Ma <tao.ma@oracle.com>
26 Signed-off-by: Mark Fasheh <mfasheh@suse.com>
28 fs/ocfs2/alloc.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++----
29 fs/ocfs2/alloc.h | 4 ++
30 2 files changed, 103 insertions(+), 7 deletions(-)
32 Index: linux-2.6.27-ocfs2/fs/ocfs2/alloc.c
33 ===================================================================
34 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/alloc.c
35 +++ linux-2.6.27-ocfs2/fs/ocfs2/alloc.c
36 @@ -5809,7 +5809,10 @@ int ocfs2_truncate_log_init(struct ocfs2
40 - * Describes a single block free from a suballocator
41 + * Describe a single bit freed from a suballocator. For the block
42 + * suballocators, it represents one block. For the global cluster
43 + * allocator, it represents some clusters and free_bit indicates
46 struct ocfs2_cached_block_free {
47 struct ocfs2_cached_block_free *free_next;
48 @@ -5824,10 +5827,10 @@ struct ocfs2_per_slot_free_list {
49 struct ocfs2_cached_block_free *f_first;
52 -static int ocfs2_free_cached_items(struct ocfs2_super *osb,
55 - struct ocfs2_cached_block_free *head)
56 +static int ocfs2_free_cached_blocks(struct ocfs2_super *osb,
59 + struct ocfs2_cached_block_free *head)
63 @@ -5902,6 +5905,82 @@ out:
67 +int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
68 + u64 blkno, unsigned int bit)
71 + struct ocfs2_cached_block_free *item;
73 + item = kmalloc(sizeof(*item), GFP_NOFS);
80 + mlog(0, "Insert clusters: (bit %u, blk %llu)\n",
81 + bit, (unsigned long long)blkno);
83 + item->free_blk = blkno;
84 + item->free_bit = bit;
85 + item->free_next = ctxt->c_global_allocator;
87 + ctxt->c_global_allocator = item;
91 +static int ocfs2_free_cached_clusters(struct ocfs2_super *osb,
92 + struct ocfs2_cached_block_free *head)
94 + struct ocfs2_cached_block_free *tmp;
95 + struct inode *tl_inode = osb->osb_tl_inode;
99 + mutex_lock(&tl_inode->i_mutex);
102 + if (ocfs2_truncate_log_needs_flush(osb)) {
103 + ret = __ocfs2_flush_truncate_log(osb);
110 + handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
111 + if (IS_ERR(handle)) {
112 + ret = PTR_ERR(handle);
117 + ret = ocfs2_truncate_log_append(osb, handle, head->free_blk,
120 + ocfs2_commit_trans(osb, handle);
122 + head = head->free_next;
131 + mutex_unlock(&tl_inode->i_mutex);
134 + /* Premature exit may have left some dangling items. */
136 + head = head->free_next;
143 int ocfs2_run_deallocs(struct ocfs2_super *osb,
144 struct ocfs2_cached_dealloc_ctxt *ctxt)
146 @@ -5917,8 +5996,10 @@ int ocfs2_run_deallocs(struct ocfs2_supe
148 mlog(0, "Free items: (type %u, slot %d)\n",
149 fl->f_inode_type, fl->f_slot);
150 - ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
151 - fl->f_slot, fl->f_first);
152 + ret2 = ocfs2_free_cached_blocks(osb,
159 @@ -5929,6 +6010,17 @@ int ocfs2_run_deallocs(struct ocfs2_supe
163 + if (ctxt->c_global_allocator) {
164 + ret2 = ocfs2_free_cached_clusters(osb,
165 + ctxt->c_global_allocator);
171 + ctxt->c_global_allocator = NULL;
177 Index: linux-2.6.27-ocfs2/fs/ocfs2/alloc.h
178 ===================================================================
179 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/alloc.h
180 +++ linux-2.6.27-ocfs2/fs/ocfs2/alloc.h
181 @@ -167,11 +167,15 @@ int __ocfs2_flush_truncate_log(struct oc
183 struct ocfs2_cached_dealloc_ctxt {
184 struct ocfs2_per_slot_free_list *c_first_suballocator;
185 + struct ocfs2_cached_block_free *c_global_allocator;
187 static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
189 c->c_first_suballocator = NULL;
190 + c->c_global_allocator = NULL;
192 +int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
193 + u64 blkno, unsigned int bit);
194 int ocfs2_run_deallocs(struct ocfs2_super *osb,
195 struct ocfs2_cached_dealloc_ctxt *ctxt);