1 From: Joel Becker <joel.becker@oracle.com>
2 Date: Fri, 24 Oct 2008 17:33:40 -0700
3 Subject: ocfs2: Improve ocfs2_read_xattr_bucket().
6 The ocfs2_read_xattr_bucket() function would read an xattr bucket into a
7 list of buffer heads. However, we have a nice ocfs2_xattr_bucket
8 structure. Let's have it fill that out instead.
10 In addition, ocfs2_read_xattr_bucket() would initialize buffer heads for
11 a bucket that's never been on disk before. That's confusing. Let's
12 call that functionality ocfs2_init_xattr_bucket().
14 The functions ocfs2_cp_xattr_bucket() and ocfs2_half_xattr_bucket() are
15 updated to use the ocfs2_xattr_bucket structure rather than raw bh
16 lists. That way they can use the new read/init calls. In addition,
17 they drop the wasted read of an existing target bucket.
19 Signed-off-by: Joel Becker <joel.becker@oracle.com>
20 Signed-off-by: Mark Fasheh <mfasheh@suse.com>
22 fs/ocfs2/xattr.c | 165 ++++++++++++++++++++++++++----------------------------
23 1 files changed, 79 insertions(+), 86 deletions(-)
25 diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
26 index 3478ad1..fa13fa4 100644
27 --- a/fs/ocfs2/xattr.c
28 +++ b/fs/ocfs2/xattr.c
29 @@ -168,6 +168,48 @@ static void ocfs2_xattr_bucket_relse(struct inode *inode,
34 + * A bucket that has never been written to disk doesn't need to be
35 + * read. We just need the buffer_heads. Don't call this for
36 + * buckets that are already on disk. ocfs2_read_xattr_bucket() initializes
39 +static int ocfs2_init_xattr_bucket(struct inode *inode,
40 + struct ocfs2_xattr_bucket *bucket,
44 + int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
46 + for (i = 0; i < blks; i++) {
47 + bucket->bu_bhs[i] = sb_getblk(inode->i_sb, xb_blkno + i);
48 + if (!bucket->bu_bhs[i]) {
54 + ocfs2_set_new_buffer_uptodate(inode, bucket->bu_bhs[i]);
58 + ocfs2_xattr_bucket_relse(inode, bucket);
62 +/* Read the xattr bucket at xb_blkno */
63 +static int ocfs2_read_xattr_bucket(struct inode *inode,
64 + struct ocfs2_xattr_bucket *bucket,
67 + int rc, blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
69 + rc = ocfs2_read_blocks(inode, xb_blkno, blks, bucket->bu_bhs, 0);
71 + ocfs2_xattr_bucket_relse(inode, bucket);
75 static inline const char *ocfs2_xattr_prefix(int name_index)
77 struct xattr_handler *handler = NULL;
78 @@ -3097,31 +3139,6 @@ out:
82 -static int ocfs2_read_xattr_bucket(struct inode *inode,
84 - struct buffer_head **bhs,
88 - u16 i, blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
91 - return ocfs2_read_blocks(inode, blkno,
92 - blk_per_bucket, bhs, 0);
94 - for (i = 0; i < blk_per_bucket; i++) {
95 - bhs[i] = sb_getblk(inode->i_sb, blkno + i);
96 - if (bhs[i] == NULL) {
101 - ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
108 * Find the suitable pos when we divide a bucket into 2.
109 * We have to make sure the xattrs with the same hash value exist
110 @@ -3184,7 +3201,7 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
112 int count, start, len, name_value_len = 0, xe_len, name_offset = 0;
113 u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
114 - struct buffer_head **s_bhs, **t_bhs = NULL;
115 + struct ocfs2_xattr_bucket s_bucket, t_bucket;
116 struct ocfs2_xattr_header *xh;
117 struct ocfs2_xattr_entry *xe;
118 int blocksize = inode->i_sb->s_blocksize;
119 @@ -3192,37 +3209,34 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
120 mlog(0, "move some of xattrs from bucket %llu to %llu\n",
121 (unsigned long long)blk, (unsigned long long)new_blk);
123 - s_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS);
126 + memset(&s_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
127 + memset(&t_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
129 - ret = ocfs2_read_xattr_bucket(inode, blk, s_bhs, 0);
130 + ret = ocfs2_read_xattr_bucket(inode, &s_bucket, blk);
136 - ret = ocfs2_journal_access(handle, inode, s_bhs[0],
137 + ret = ocfs2_journal_access(handle, inode, s_bucket.bu_bhs[0],
138 OCFS2_JOURNAL_ACCESS_WRITE);
144 - t_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS);
150 - ret = ocfs2_read_xattr_bucket(inode, new_blk, t_bhs, new_bucket_head);
152 + * Even if !new_bucket_head, we're overwriting t_bucket. Thus,
153 + * there's no need to read it.
155 + ret = ocfs2_init_xattr_bucket(inode, &t_bucket, new_blk);
161 for (i = 0; i < blk_per_bucket; i++) {
162 - ret = ocfs2_journal_access(handle, inode, t_bhs[i],
163 + ret = ocfs2_journal_access(handle, inode, t_bucket.bu_bhs[i],
165 OCFS2_JOURNAL_ACCESS_CREATE :
166 OCFS2_JOURNAL_ACCESS_WRITE);
167 @@ -3232,7 +3246,7 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
171 - xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data;
172 + xh = bucket_xh(&s_bucket);
173 count = le16_to_cpu(xh->xh_count);
174 start = ocfs2_xattr_find_divide_pos(xh);
176 @@ -3245,9 +3259,9 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
177 * that of the last entry in the previous bucket.
179 for (i = 0; i < blk_per_bucket; i++)
180 - memset(t_bhs[i]->b_data, 0, blocksize);
181 + memset(bucket_block(&t_bucket, i), 0, blocksize);
183 - xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data;
184 + xh = bucket_xh(&t_bucket);
185 xh->xh_free_start = cpu_to_le16(blocksize);
186 xh->xh_entries[0].xe_name_hash = xe->xe_name_hash;
187 le32_add_cpu(&xh->xh_entries[0].xe_name_hash, 1);
188 @@ -3257,10 +3271,11 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
190 /* copy the whole bucket to the new first. */
191 for (i = 0; i < blk_per_bucket; i++)
192 - memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize);
193 + memcpy(bucket_block(&t_bucket, i), bucket_block(&s_bucket, i),
196 /* update the new bucket. */
197 - xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data;
198 + xh = bucket_xh(&t_bucket);
201 * Calculate the total name/value len and xh_free_start for
202 @@ -3325,7 +3340,7 @@ set_num_buckets:
203 xh->xh_num_buckets = 0;
205 for (i = 0; i < blk_per_bucket; i++) {
206 - ocfs2_journal_dirty(handle, t_bhs[i]);
207 + ocfs2_journal_dirty(handle, t_bucket.bu_bhs[i]);
211 @@ -3342,29 +3357,20 @@ set_num_buckets:
215 - xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data;
216 + xh = bucket_xh(&s_bucket);
217 memset(&xh->xh_entries[start], 0,
218 sizeof(struct ocfs2_xattr_entry) * (count - start));
219 xh->xh_count = cpu_to_le16(start);
220 xh->xh_free_start = cpu_to_le16(name_offset);
221 xh->xh_name_value_len = cpu_to_le16(name_value_len);
223 - ocfs2_journal_dirty(handle, s_bhs[0]);
224 + ocfs2_journal_dirty(handle, s_bucket.bu_bhs[0]);
230 - for (i = 0; i < blk_per_bucket; i++)
236 - for (i = 0; i < blk_per_bucket; i++)
240 + ocfs2_xattr_bucket_relse(inode, &s_bucket);
241 + ocfs2_xattr_bucket_relse(inode, &t_bucket);
245 @@ -3384,7 +3390,7 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
247 int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
248 int blocksize = inode->i_sb->s_blocksize;
249 - struct buffer_head **s_bhs, **t_bhs = NULL;
250 + struct ocfs2_xattr_bucket s_bucket, t_bucket;
252 BUG_ON(s_blkno == t_blkno);
254 @@ -3392,28 +3398,23 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
255 (unsigned long long)s_blkno, (unsigned long long)t_blkno,
258 - s_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
262 + memset(&s_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
263 + memset(&t_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
265 - ret = ocfs2_read_xattr_bucket(inode, s_blkno, s_bhs, 0);
266 + ret = ocfs2_read_xattr_bucket(inode, &s_bucket, s_blkno);
270 - t_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
277 - ret = ocfs2_read_xattr_bucket(inode, t_blkno, t_bhs, t_is_new);
279 + * Even if !t_is_new, we're overwriting t_bucket. Thus,
280 + * there's no need to read it.
282 + ret = ocfs2_init_xattr_bucket(inode, &t_bucket, t_blkno);
286 for (i = 0; i < blk_per_bucket; i++) {
287 - ret = ocfs2_journal_access(handle, inode, t_bhs[i],
288 + ret = ocfs2_journal_access(handle, inode, t_bucket.bu_bhs[i],
290 OCFS2_JOURNAL_ACCESS_CREATE :
291 OCFS2_JOURNAL_ACCESS_WRITE);
292 @@ -3422,22 +3423,14 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
295 for (i = 0; i < blk_per_bucket; i++) {
296 - memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize);
297 - ocfs2_journal_dirty(handle, t_bhs[i]);
298 + memcpy(bucket_block(&t_bucket, i), bucket_block(&s_bucket, i),
300 + ocfs2_journal_dirty(handle, t_bucket.bu_bhs[i]);
305 - for (i = 0; i < blk_per_bucket; i++)
311 - for (i = 0; i < blk_per_bucket; i++)
315 + ocfs2_xattr_bucket_relse(inode, &s_bucket);
316 + ocfs2_xattr_bucket_relse(inode, &t_bucket);