diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-10-24 20:33:40 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:17 -0500 |
commit | 784b816a9198dc3782c97cde8ddcf52fecdf1797 (patch) | |
tree | 8b6629535ab822a069449118d8925d479d58fdd3 /fs/ocfs2/xattr.c | |
parent | 6dde41d9e7ba62f84cd7e91c0e993500af32ceb6 (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.c | 165 |
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 | */ | ||
177 | static 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 */ | ||
201 | static 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 | |||
171 | static inline const char *ocfs2_xattr_prefix(int name_index) | 213 | static 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 | ||
3100 | static 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 | ||
3356 | out: | 3371 | out: |
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 | ||
3429 | out: | 3431 | out: |
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 | } |