]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Joel Becker <joel.becker@oracle.com> |
2 | Date: Mon, 27 Oct 2008 15:18:29 -0700 | |
3 | Subject: ocfs2: Use buckets in ocfs2_xattr_create_index_block(). | |
4 | Patch-mainline: 2.6.29 | |
5 | ||
6 | Use the ocfs2_xattr_bucket abstraction in | |
7 | ocfs2_xattr_create_index_block() and its helpers. We get more efficient | |
8 | reads, a lot less buffer_head munging, and nicer code to boot. While | |
9 | we're at it, ocfs2_xattr_update_xattr_search() becomes void. | |
10 | ||
11 | Signed-off-by: Joel Becker <joel.becker@oracle.com> | |
12 | Signed-off-by: Mark Fasheh <mfasheh@suse.com> | |
13 | --- | |
14 | fs/ocfs2/xattr.c | 114 +++++++++++++++-------------------------------------- | |
15 | 1 files changed, 32 insertions(+), 82 deletions(-) | |
16 | ||
17 | diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c | |
18 | index 46986c6..76969b9 100644 | |
19 | --- a/fs/ocfs2/xattr.c | |
20 | +++ b/fs/ocfs2/xattr.c | |
21 | @@ -2649,32 +2649,34 @@ static void swap_xe(void *a, void *b, int size) | |
22 | /* | |
23 | * When the ocfs2_xattr_block is filled up, new bucket will be created | |
24 | * and all the xattr entries will be moved to the new bucket. | |
25 | + * The header goes at the start of the bucket, and the names+values are | |
26 | + * filled from the end. This is why *target starts as the last buffer. | |
27 | * Note: we need to sort the entries since they are not saved in order | |
28 | * in the ocfs2_xattr_block. | |
29 | */ | |
30 | static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |
31 | struct buffer_head *xb_bh, | |
32 | - struct buffer_head *xh_bh, | |
33 | - struct buffer_head *data_bh) | |
34 | + struct ocfs2_xattr_bucket *bucket) | |
35 | { | |
36 | int i, blocksize = inode->i_sb->s_blocksize; | |
37 | + int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | |
38 | u16 offset, size, off_change; | |
39 | struct ocfs2_xattr_entry *xe; | |
40 | struct ocfs2_xattr_block *xb = | |
41 | (struct ocfs2_xattr_block *)xb_bh->b_data; | |
42 | struct ocfs2_xattr_header *xb_xh = &xb->xb_attrs.xb_header; | |
43 | - struct ocfs2_xattr_header *xh = | |
44 | - (struct ocfs2_xattr_header *)xh_bh->b_data; | |
45 | + struct ocfs2_xattr_header *xh = bucket_xh(bucket); | |
46 | u16 count = le16_to_cpu(xb_xh->xh_count); | |
47 | - char *target = xh_bh->b_data, *src = xb_bh->b_data; | |
48 | + char *src = xb_bh->b_data; | |
49 | + char *target = bucket_block(bucket, blks - 1); | |
50 | ||
51 | mlog(0, "cp xattr from block %llu to bucket %llu\n", | |
52 | (unsigned long long)xb_bh->b_blocknr, | |
53 | - (unsigned long long)xh_bh->b_blocknr); | |
54 | + (unsigned long long)bucket_blkno(bucket)); | |
55 | + | |
56 | + for (i = 0; i < blks; i++) | |
57 | + memset(bucket_block(bucket, i), 0, blocksize); | |
58 | ||
59 | - memset(xh_bh->b_data, 0, blocksize); | |
60 | - if (data_bh) | |
61 | - memset(data_bh->b_data, 0, blocksize); | |
62 | /* | |
63 | * Since the xe_name_offset is based on ocfs2_xattr_header, | |
64 | * there is a offset change corresponding to the change of | |
65 | @@ -2686,8 +2688,6 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |
66 | size = blocksize - offset; | |
67 | ||
68 | /* copy all the names and values. */ | |
69 | - if (data_bh) | |
70 | - target = data_bh->b_data; | |
71 | memcpy(target + offset, src + offset, size); | |
72 | ||
73 | /* Init new header now. */ | |
74 | @@ -2697,7 +2697,7 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |
75 | xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE - size); | |
76 | ||
77 | /* copy all the entries. */ | |
78 | - target = xh_bh->b_data; | |
79 | + target = bucket_block(bucket, 0); | |
80 | offset = offsetof(struct ocfs2_xattr_header, xh_entries); | |
81 | size = count * sizeof(struct ocfs2_xattr_entry); | |
82 | memcpy(target + offset, (char *)xb_xh + offset, size); | |
83 | @@ -2723,42 +2723,24 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, | |
84 | * While if the entry is in index b-tree, "bucket" indicates the | |
85 | * real place of the xattr. | |
86 | */ | |
87 | -static int ocfs2_xattr_update_xattr_search(struct inode *inode, | |
88 | - struct ocfs2_xattr_search *xs, | |
89 | - struct buffer_head *old_bh, | |
90 | - struct buffer_head *new_bh) | |
91 | +static void ocfs2_xattr_update_xattr_search(struct inode *inode, | |
92 | + struct ocfs2_xattr_search *xs, | |
93 | + struct buffer_head *old_bh) | |
94 | { | |
95 | - int ret = 0; | |
96 | char *buf = old_bh->b_data; | |
97 | struct ocfs2_xattr_block *old_xb = (struct ocfs2_xattr_block *)buf; | |
98 | struct ocfs2_xattr_header *old_xh = &old_xb->xb_attrs.xb_header; | |
99 | - int i, blocksize = inode->i_sb->s_blocksize; | |
100 | - u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | |
101 | + int i; | |
102 | ||
103 | - xs->bucket->bu_bhs[0] = new_bh; | |
104 | - get_bh(new_bh); | |
105 | xs->header = bucket_xh(xs->bucket); | |
106 | - | |
107 | - xs->base = new_bh->b_data; | |
108 | + xs->base = bucket_block(xs->bucket, 0); | |
109 | xs->end = xs->base + inode->i_sb->s_blocksize; | |
110 | ||
111 | - if (!xs->not_found) { | |
112 | - if (OCFS2_XATTR_BUCKET_SIZE != blocksize) { | |
113 | - ret = ocfs2_read_blocks(inode, | |
114 | - bucket_blkno(xs->bucket) + 1, | |
115 | - blk_per_bucket - 1, &xs->bucket->bu_bhs[1], | |
116 | - 0); | |
117 | - if (ret) { | |
118 | - mlog_errno(ret); | |
119 | - return ret; | |
120 | - } | |
121 | - | |
122 | - } | |
123 | - i = xs->here - old_xh->xh_entries; | |
124 | - xs->here = &xs->header->xh_entries[i]; | |
125 | - } | |
126 | + if (xs->not_found) | |
127 | + return; | |
128 | ||
129 | - return ret; | |
130 | + i = xs->here - old_xh->xh_entries; | |
131 | + xs->here = &xs->header->xh_entries[i]; | |
132 | } | |
133 | ||
134 | static int ocfs2_xattr_create_index_block(struct inode *inode, | |
135 | @@ -2771,18 +2753,17 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |
136 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | |
137 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | |
138 | struct ocfs2_alloc_context *data_ac; | |
139 | - struct buffer_head *xh_bh = NULL, *data_bh = NULL; | |
140 | struct buffer_head *xb_bh = xs->xattr_bh; | |
141 | struct ocfs2_xattr_block *xb = | |
142 | (struct ocfs2_xattr_block *)xb_bh->b_data; | |
143 | struct ocfs2_xattr_tree_root *xr; | |
144 | u16 xb_flags = le16_to_cpu(xb->xb_flags); | |
145 | - u16 bpb = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | |
146 | ||
147 | mlog(0, "create xattr index block for %llu\n", | |
148 | (unsigned long long)xb_bh->b_blocknr); | |
149 | ||
150 | BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); | |
151 | + BUG_ON(!xs->bucket); | |
152 | ||
153 | ret = ocfs2_reserve_clusters(osb, 1, &data_ac); | |
154 | if (ret) { | |
155 | @@ -2798,10 +2779,10 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |
156 | down_write(&oi->ip_alloc_sem); | |
157 | ||
158 | /* | |
159 | - * 3 more credits, one for xattr block update, one for the 1st block | |
160 | - * of the new xattr bucket and one for the value/data. | |
161 | + * We need more credits. One for the xattr block update and one | |
162 | + * for each block of the new xattr bucket. | |
163 | */ | |
164 | - credits += 3; | |
165 | + credits += 1 + ocfs2_blocks_per_xattr_bucket(inode->i_sb); | |
166 | handle = ocfs2_start_trans(osb, credits); | |
167 | if (IS_ERR(handle)) { | |
168 | ret = PTR_ERR(handle); | |
169 | @@ -2832,51 +2813,23 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |
170 | mlog(0, "allocate 1 cluster from %llu to xattr block\n", | |
171 | (unsigned long long)blkno); | |
172 | ||
173 | - xh_bh = sb_getblk(inode->i_sb, blkno); | |
174 | - if (!xh_bh) { | |
175 | - ret = -EIO; | |
176 | + ret = ocfs2_init_xattr_bucket(xs->bucket, blkno); | |
177 | + if (ret) { | |
178 | mlog_errno(ret); | |
179 | goto out_commit; | |
180 | } | |
181 | ||
182 | - ocfs2_set_new_buffer_uptodate(inode, xh_bh); | |
183 | - | |
184 | - ret = ocfs2_journal_access(handle, inode, xh_bh, | |
185 | - OCFS2_JOURNAL_ACCESS_CREATE); | |
186 | + ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, | |
187 | + OCFS2_JOURNAL_ACCESS_CREATE); | |
188 | if (ret) { | |
189 | mlog_errno(ret); | |
190 | goto out_commit; | |
191 | } | |
192 | ||
193 | - if (bpb > 1) { | |
194 | - data_bh = sb_getblk(inode->i_sb, blkno + bpb - 1); | |
195 | - if (!data_bh) { | |
196 | - ret = -EIO; | |
197 | - mlog_errno(ret); | |
198 | - goto out_commit; | |
199 | - } | |
200 | - | |
201 | - ocfs2_set_new_buffer_uptodate(inode, data_bh); | |
202 | - | |
203 | - ret = ocfs2_journal_access(handle, inode, data_bh, | |
204 | - OCFS2_JOURNAL_ACCESS_CREATE); | |
205 | - if (ret) { | |
206 | - mlog_errno(ret); | |
207 | - goto out_commit; | |
208 | - } | |
209 | - } | |
210 | - | |
211 | - ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xh_bh, data_bh); | |
212 | - | |
213 | - ocfs2_journal_dirty(handle, xh_bh); | |
214 | - if (data_bh) | |
215 | - ocfs2_journal_dirty(handle, data_bh); | |
216 | + ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xs->bucket); | |
217 | + ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); | |
218 | ||
219 | - ret = ocfs2_xattr_update_xattr_search(inode, xs, xb_bh, xh_bh); | |
220 | - if (ret) { | |
221 | - mlog_errno(ret); | |
222 | - goto out_commit; | |
223 | - } | |
224 | + ocfs2_xattr_update_xattr_search(inode, xs, xb_bh); | |
225 | ||
226 | /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */ | |
227 | memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize - | |
228 | @@ -2911,9 +2864,6 @@ out: | |
229 | if (data_ac) | |
230 | ocfs2_free_alloc_context(data_ac); | |
231 | ||
232 | - brelse(xh_bh); | |
233 | - brelse(data_bh); | |
234 | - | |
235 | return ret; | |
236 | } | |
237 | ||
238 | -- | |
239 | 1.5.6 | |
240 |