aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/xattr.c
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-10-24 20:33:40 -0400
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:34:17 -0500
commit784b816a9198dc3782c97cde8ddcf52fecdf1797 (patch)
tree8b6629535ab822a069449118d8925d479d58fdd3 /fs/ocfs2/xattr.c
parent6dde41d9e7ba62f84cd7e91c0e993500af32ceb6 (diff)
ocfs2: Improve ocfs2_read_xattr_bucket().
The ocfs2_read_xattr_bucket() function would read an xattr bucket into a list of buffer heads. However, we have a nice ocfs2_xattr_bucket structure. Let's have it fill that out instead. In addition, ocfs2_read_xattr_bucket() would initialize buffer heads for a bucket that's never been on disk before. That's confusing. Let's call that functionality ocfs2_init_xattr_bucket(). The functions ocfs2_cp_xattr_bucket() and ocfs2_half_xattr_bucket() are updated to use the ocfs2_xattr_bucket structure rather than raw bh lists. That way they can use the new read/init calls. In addition, they drop the wasted read of an existing target bucket. Signed-off-by: Joel Becker <joel.becker@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r--fs/ocfs2/xattr.c165
1 files changed, 79 insertions, 86 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 3478ad177b7f..fa13fa488786 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -168,6 +168,48 @@ static void ocfs2_xattr_bucket_relse(struct inode *inode,
168 } 168 }
169} 169}
170 170
171/*
172 * A bucket that has never been written to disk doesn't need to be
173 * read. We just need the buffer_heads. Don't call this for
174 * buckets that are already on disk. ocfs2_read_xattr_bucket() initializes
175 * them fully.
176 */
177static int ocfs2_init_xattr_bucket(struct inode *inode,
178 struct ocfs2_xattr_bucket *bucket,
179 u64 xb_blkno)
180{
181 int i, rc = 0;
182 int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
183
184 for (i = 0; i < blks; i++) {
185 bucket->bu_bhs[i] = sb_getblk(inode->i_sb, xb_blkno + i);
186 if (!bucket->bu_bhs[i]) {
187 rc = -EIO;
188 mlog_errno(rc);
189 break;
190 }
191
192 ocfs2_set_new_buffer_uptodate(inode, bucket->bu_bhs[i]);
193 }
194
195 if (rc)
196 ocfs2_xattr_bucket_relse(inode, bucket);
197 return rc;
198}
199
200/* Read the xattr bucket at xb_blkno */
201static int ocfs2_read_xattr_bucket(struct inode *inode,
202 struct ocfs2_xattr_bucket *bucket,
203 u64 xb_blkno)
204{
205 int rc, blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
206
207 rc = ocfs2_read_blocks(inode, xb_blkno, blks, bucket->bu_bhs, 0);
208 if (rc)
209 ocfs2_xattr_bucket_relse(inode, bucket);
210 return rc;
211}
212
171static inline const char *ocfs2_xattr_prefix(int name_index) 213static inline const char *ocfs2_xattr_prefix(int name_index)
172{ 214{
173 struct xattr_handler *handler = NULL; 215 struct xattr_handler *handler = NULL;
@@ -3097,31 +3139,6 @@ out:
3097 return ret; 3139 return ret;
3098} 3140}
3099 3141
3100static int ocfs2_read_xattr_bucket(struct inode *inode,
3101 u64 blkno,
3102 struct buffer_head **bhs,
3103 int new)
3104{
3105 int ret = 0;
3106 u16 i, blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
3107
3108 if (!new)
3109 return ocfs2_read_blocks(inode, blkno,
3110 blk_per_bucket, bhs, 0);
3111
3112 for (i = 0; i < blk_per_bucket; i++) {
3113 bhs[i] = sb_getblk(inode->i_sb, blkno + i);
3114 if (bhs[i] == NULL) {
3115 ret = -EIO;
3116 mlog_errno(ret);
3117 break;
3118 }
3119 ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
3120 }
3121
3122 return ret;
3123}
3124
3125/* 3142/*
3126 * Find the suitable pos when we divide a bucket into 2. 3143 * Find the suitable pos when we divide a bucket into 2.
3127 * We have to make sure the xattrs with the same hash value exist 3144 * We have to make sure the xattrs with the same hash value exist
@@ -3184,7 +3201,7 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
3184 int ret, i; 3201 int ret, i;
3185 int count, start, len, name_value_len = 0, xe_len, name_offset = 0; 3202 int count, start, len, name_value_len = 0, xe_len, name_offset = 0;
3186 u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); 3203 u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
3187 struct buffer_head **s_bhs, **t_bhs = NULL; 3204 struct ocfs2_xattr_bucket s_bucket, t_bucket;
3188 struct ocfs2_xattr_header *xh; 3205 struct ocfs2_xattr_header *xh;
3189 struct ocfs2_xattr_entry *xe; 3206 struct ocfs2_xattr_entry *xe;
3190 int blocksize = inode->i_sb->s_blocksize; 3207 int blocksize = inode->i_sb->s_blocksize;
@@ -3192,37 +3209,34 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
3192 mlog(0, "move some of xattrs from bucket %llu to %llu\n", 3209 mlog(0, "move some of xattrs from bucket %llu to %llu\n",
3193 (unsigned long long)blk, (unsigned long long)new_blk); 3210 (unsigned long long)blk, (unsigned long long)new_blk);
3194 3211
3195 s_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS); 3212 memset(&s_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
3196 if (!s_bhs) 3213 memset(&t_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
3197 return -ENOMEM;
3198 3214
3199 ret = ocfs2_read_xattr_bucket(inode, blk, s_bhs, 0); 3215 ret = ocfs2_read_xattr_bucket(inode, &s_bucket, blk);
3200 if (ret) { 3216 if (ret) {
3201 mlog_errno(ret); 3217 mlog_errno(ret);
3202 goto out; 3218 goto out;
3203 } 3219 }
3204 3220
3205 ret = ocfs2_journal_access(handle, inode, s_bhs[0], 3221 ret = ocfs2_journal_access(handle, inode, s_bucket.bu_bhs[0],
3206 OCFS2_JOURNAL_ACCESS_WRITE); 3222 OCFS2_JOURNAL_ACCESS_WRITE);
3207 if (ret) { 3223 if (ret) {
3208 mlog_errno(ret); 3224 mlog_errno(ret);
3209 goto out; 3225 goto out;
3210 } 3226 }
3211 3227
3212 t_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS); 3228 /*
3213 if (!t_bhs) { 3229 * Even if !new_bucket_head, we're overwriting t_bucket. Thus,
3214 ret = -ENOMEM; 3230 * there's no need to read it.
3215 goto out; 3231 */
3216 } 3232 ret = ocfs2_init_xattr_bucket(inode, &t_bucket, new_blk);
3217
3218 ret = ocfs2_read_xattr_bucket(inode, new_blk, t_bhs, new_bucket_head);
3219 if (ret) { 3233 if (ret) {
3220 mlog_errno(ret); 3234 mlog_errno(ret);
3221 goto out; 3235 goto out;
3222 } 3236 }
3223 3237
3224 for (i = 0; i < blk_per_bucket; i++) { 3238 for (i = 0; i < blk_per_bucket; i++) {
3225 ret = ocfs2_journal_access(handle, inode, t_bhs[i], 3239 ret = ocfs2_journal_access(handle, inode, t_bucket.bu_bhs[i],
3226 new_bucket_head ? 3240 new_bucket_head ?
3227 OCFS2_JOURNAL_ACCESS_CREATE : 3241 OCFS2_JOURNAL_ACCESS_CREATE :
3228 OCFS2_JOURNAL_ACCESS_WRITE); 3242 OCFS2_JOURNAL_ACCESS_WRITE);
@@ -3232,7 +3246,7 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
3232 } 3246 }
3233 } 3247 }
3234 3248
3235 xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data; 3249 xh = bucket_xh(&s_bucket);
3236 count = le16_to_cpu(xh->xh_count); 3250 count = le16_to_cpu(xh->xh_count);
3237 start = ocfs2_xattr_find_divide_pos(xh); 3251 start = ocfs2_xattr_find_divide_pos(xh);
3238 3252
@@ -3245,9 +3259,9 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
3245 * that of the last entry in the previous bucket. 3259 * that of the last entry in the previous bucket.
3246 */ 3260 */
3247 for (i = 0; i < blk_per_bucket; i++) 3261 for (i = 0; i < blk_per_bucket; i++)
3248 memset(t_bhs[i]->b_data, 0, blocksize); 3262 memset(bucket_block(&t_bucket, i), 0, blocksize);
3249 3263
3250 xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data; 3264 xh = bucket_xh(&t_bucket);
3251 xh->xh_free_start = cpu_to_le16(blocksize); 3265 xh->xh_free_start = cpu_to_le16(blocksize);
3252 xh->xh_entries[0].xe_name_hash = xe->xe_name_hash; 3266 xh->xh_entries[0].xe_name_hash = xe->xe_name_hash;
3253 le32_add_cpu(&xh->xh_entries[0].xe_name_hash, 1); 3267 le32_add_cpu(&xh->xh_entries[0].xe_name_hash, 1);
@@ -3257,10 +3271,11 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
3257 3271
3258 /* copy the whole bucket to the new first. */ 3272 /* copy the whole bucket to the new first. */
3259 for (i = 0; i < blk_per_bucket; i++) 3273 for (i = 0; i < blk_per_bucket; i++)
3260 memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize); 3274 memcpy(bucket_block(&t_bucket, i), bucket_block(&s_bucket, i),
3275 blocksize);
3261 3276
3262 /* update the new bucket. */ 3277 /* update the new bucket. */
3263 xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data; 3278 xh = bucket_xh(&t_bucket);
3264 3279
3265 /* 3280 /*
3266 * Calculate the total name/value len and xh_free_start for 3281 * Calculate the total name/value len and xh_free_start for
@@ -3325,7 +3340,7 @@ set_num_buckets:
3325 xh->xh_num_buckets = 0; 3340 xh->xh_num_buckets = 0;
3326 3341
3327 for (i = 0; i < blk_per_bucket; i++) { 3342 for (i = 0; i < blk_per_bucket; i++) {
3328 ocfs2_journal_dirty(handle, t_bhs[i]); 3343 ocfs2_journal_dirty(handle, t_bucket.bu_bhs[i]);
3329 if (ret) 3344 if (ret)
3330 mlog_errno(ret); 3345 mlog_errno(ret);
3331 } 3346 }
@@ -3342,29 +3357,20 @@ set_num_buckets:
3342 if (start == count) 3357 if (start == count)
3343 goto out; 3358 goto out;
3344 3359
3345 xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data; 3360 xh = bucket_xh(&s_bucket);
3346 memset(&xh->xh_entries[start], 0, 3361 memset(&xh->xh_entries[start], 0,
3347 sizeof(struct ocfs2_xattr_entry) * (count - start)); 3362 sizeof(struct ocfs2_xattr_entry) * (count - start));
3348 xh->xh_count = cpu_to_le16(start); 3363 xh->xh_count = cpu_to_le16(start);
3349 xh->xh_free_start = cpu_to_le16(name_offset); 3364 xh->xh_free_start = cpu_to_le16(name_offset);
3350 xh->xh_name_value_len = cpu_to_le16(name_value_len); 3365 xh->xh_name_value_len = cpu_to_le16(name_value_len);
3351 3366
3352 ocfs2_journal_dirty(handle, s_bhs[0]); 3367 ocfs2_journal_dirty(handle, s_bucket.bu_bhs[0]);
3353 if (ret) 3368 if (ret)
3354 mlog_errno(ret); 3369 mlog_errno(ret);
3355 3370
3356out: 3371out:
3357 if (s_bhs) { 3372 ocfs2_xattr_bucket_relse(inode, &s_bucket);
3358 for (i = 0; i < blk_per_bucket; i++) 3373 ocfs2_xattr_bucket_relse(inode, &t_bucket);
3359 brelse(s_bhs[i]);
3360 }
3361 kfree(s_bhs);
3362
3363 if (t_bhs) {
3364 for (i = 0; i < blk_per_bucket; i++)
3365 brelse(t_bhs[i]);
3366 }
3367 kfree(t_bhs);
3368 3374
3369 return ret; 3375 return ret;
3370} 3376}
@@ -3384,7 +3390,7 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
3384 int ret, i; 3390 int ret, i;
3385 int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); 3391 int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
3386 int blocksize = inode->i_sb->s_blocksize; 3392 int blocksize = inode->i_sb->s_blocksize;
3387 struct buffer_head **s_bhs, **t_bhs = NULL; 3393 struct ocfs2_xattr_bucket s_bucket, t_bucket;
3388 3394
3389 BUG_ON(s_blkno == t_blkno); 3395 BUG_ON(s_blkno == t_blkno);
3390 3396
@@ -3392,28 +3398,23 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
3392 (unsigned long long)s_blkno, (unsigned long long)t_blkno, 3398 (unsigned long long)s_blkno, (unsigned long long)t_blkno,
3393 t_is_new); 3399 t_is_new);
3394 3400
3395 s_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket, 3401 memset(&s_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
3396 GFP_NOFS); 3402 memset(&t_bucket, 0, sizeof(struct ocfs2_xattr_bucket));
3397 if (!s_bhs)
3398 return -ENOMEM;
3399 3403
3400 ret = ocfs2_read_xattr_bucket(inode, s_blkno, s_bhs, 0); 3404 ret = ocfs2_read_xattr_bucket(inode, &s_bucket, s_blkno);
3401 if (ret) 3405 if (ret)
3402 goto out; 3406 goto out;
3403 3407
3404 t_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket, 3408 /*
3405 GFP_NOFS); 3409 * Even if !t_is_new, we're overwriting t_bucket. Thus,
3406 if (!t_bhs) { 3410 * there's no need to read it.
3407 ret = -ENOMEM; 3411 */
3408 goto out; 3412 ret = ocfs2_init_xattr_bucket(inode, &t_bucket, t_blkno);
3409 }
3410
3411 ret = ocfs2_read_xattr_bucket(inode, t_blkno, t_bhs, t_is_new);
3412 if (ret) 3413 if (ret)
3413 goto out; 3414 goto out;
3414 3415
3415 for (i = 0; i < blk_per_bucket; i++) { 3416 for (i = 0; i < blk_per_bucket; i++) {
3416 ret = ocfs2_journal_access(handle, inode, t_bhs[i], 3417 ret = ocfs2_journal_access(handle, inode, t_bucket.bu_bhs[i],
3417 t_is_new ? 3418 t_is_new ?
3418 OCFS2_JOURNAL_ACCESS_CREATE : 3419 OCFS2_JOURNAL_ACCESS_CREATE :
3419 OCFS2_JOURNAL_ACCESS_WRITE); 3420 OCFS2_JOURNAL_ACCESS_WRITE);
@@ -3422,22 +3423,14 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
3422 } 3423 }
3423 3424
3424 for (i = 0; i < blk_per_bucket; i++) { 3425 for (i = 0; i < blk_per_bucket; i++) {
3425 memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize); 3426 memcpy(bucket_block(&t_bucket, i), bucket_block(&s_bucket, i),
3426 ocfs2_journal_dirty(handle, t_bhs[i]); 3427 blocksize);
3428 ocfs2_journal_dirty(handle, t_bucket.bu_bhs[i]);
3427 } 3429 }
3428 3430
3429out: 3431out:
3430 if (s_bhs) { 3432 ocfs2_xattr_bucket_relse(inode, &s_bucket);
3431 for (i = 0; i < blk_per_bucket; i++) 3433 ocfs2_xattr_bucket_relse(inode, &t_bucket);
3432 brelse(s_bhs[i]);
3433 }
3434 kfree(s_bhs);
3435
3436 if (t_bhs) {
3437 for (i = 0; i < blk_per_bucket; i++)
3438 brelse(t_bhs[i]);
3439 }
3440 kfree(t_bhs);
3441 3434
3442 return ret; 3435 return ret;
3443} 3436}