diff options
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e1d638af6ac3..2563df89fc2a 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -82,13 +82,14 @@ struct ocfs2_xattr_set_ctxt { | |||
82 | 82 | ||
83 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) | 83 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) |
84 | #define OCFS2_XATTR_INLINE_SIZE 80 | 84 | #define OCFS2_XATTR_INLINE_SIZE 80 |
85 | #define OCFS2_XATTR_HEADER_GAP 4 | ||
85 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ | 86 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ |
86 | - sizeof(struct ocfs2_xattr_header) \ | 87 | - sizeof(struct ocfs2_xattr_header) \ |
87 | - sizeof(__u32)) | 88 | - OCFS2_XATTR_HEADER_GAP) |
88 | #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ | 89 | #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ |
89 | - sizeof(struct ocfs2_xattr_block) \ | 90 | - sizeof(struct ocfs2_xattr_block) \ |
90 | - sizeof(struct ocfs2_xattr_header) \ | 91 | - sizeof(struct ocfs2_xattr_header) \ |
91 | - sizeof(__u32)) | 92 | - OCFS2_XATTR_HEADER_GAP) |
92 | 93 | ||
93 | static struct ocfs2_xattr_def_value_root def_xv = { | 94 | static struct ocfs2_xattr_def_value_root def_xv = { |
94 | .xv.xr_list.l_count = cpu_to_le16(1), | 95 | .xv.xr_list.l_count = cpu_to_le16(1), |
@@ -274,10 +275,12 @@ static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket, | |||
274 | bucket->bu_blocks, bucket->bu_bhs, 0, | 275 | bucket->bu_blocks, bucket->bu_bhs, 0, |
275 | NULL); | 276 | NULL); |
276 | if (!rc) { | 277 | if (!rc) { |
278 | spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
277 | rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb, | 279 | rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb, |
278 | bucket->bu_bhs, | 280 | bucket->bu_bhs, |
279 | bucket->bu_blocks, | 281 | bucket->bu_blocks, |
280 | &bucket_xh(bucket)->xh_check); | 282 | &bucket_xh(bucket)->xh_check); |
283 | spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
281 | if (rc) | 284 | if (rc) |
282 | mlog_errno(rc); | 285 | mlog_errno(rc); |
283 | } | 286 | } |
@@ -310,9 +313,11 @@ static void ocfs2_xattr_bucket_journal_dirty(handle_t *handle, | |||
310 | { | 313 | { |
311 | int i; | 314 | int i; |
312 | 315 | ||
316 | spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
313 | ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb, | 317 | ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb, |
314 | bucket->bu_bhs, bucket->bu_blocks, | 318 | bucket->bu_bhs, bucket->bu_blocks, |
315 | &bucket_xh(bucket)->xh_check); | 319 | &bucket_xh(bucket)->xh_check); |
320 | spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
316 | 321 | ||
317 | for (i = 0; i < bucket->bu_blocks; i++) | 322 | for (i = 0; i < bucket->bu_blocks; i++) |
318 | ocfs2_journal_dirty(handle, bucket->bu_bhs[i]); | 323 | ocfs2_journal_dirty(handle, bucket->bu_bhs[i]); |
@@ -542,8 +547,12 @@ int ocfs2_calc_xattr_init(struct inode *dir, | |||
542 | * when blocksize = 512, may reserve one more cluser for | 547 | * when blocksize = 512, may reserve one more cluser for |
543 | * xattr bucket, otherwise reserve one metadata block | 548 | * xattr bucket, otherwise reserve one metadata block |
544 | * for them is ok. | 549 | * for them is ok. |
550 | * If this is a new directory with inline data, | ||
551 | * we choose to reserve the entire inline area for | ||
552 | * directory contents and force an external xattr block. | ||
545 | */ | 553 | */ |
546 | if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || | 554 | if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || |
555 | (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) || | ||
547 | (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) { | 556 | (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) { |
548 | ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); | 557 | ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); |
549 | if (ret) { | 558 | if (ret) { |
@@ -1507,7 +1516,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1507 | last += 1; | 1516 | last += 1; |
1508 | } | 1517 | } |
1509 | 1518 | ||
1510 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 1519 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; |
1511 | if (free < 0) | 1520 | if (free < 0) |
1512 | return -EIO; | 1521 | return -EIO; |
1513 | 1522 | ||
@@ -2190,7 +2199,7 @@ static int ocfs2_xattr_can_be_in_inode(struct inode *inode, | |||
2190 | last += 1; | 2199 | last += 1; |
2191 | } | 2200 | } |
2192 | 2201 | ||
2193 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 2202 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; |
2194 | if (free < 0) | 2203 | if (free < 0) |
2195 | return 0; | 2204 | return 0; |
2196 | 2205 | ||
@@ -2592,8 +2601,9 @@ static int __ocfs2_xattr_set_handle(struct inode *inode, | |||
2592 | 2601 | ||
2593 | if (!ret) { | 2602 | if (!ret) { |
2594 | /* Update inode ctime. */ | 2603 | /* Update inode ctime. */ |
2595 | ret = ocfs2_journal_access(ctxt->handle, inode, xis->inode_bh, | 2604 | ret = ocfs2_journal_access_di(ctxt->handle, inode, |
2596 | OCFS2_JOURNAL_ACCESS_WRITE); | 2605 | xis->inode_bh, |
2606 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2597 | if (ret) { | 2607 | if (ret) { |
2598 | mlog_errno(ret); | 2608 | mlog_errno(ret); |
2599 | goto out; | 2609 | goto out; |
@@ -4729,13 +4739,6 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4729 | vb.vb_xv = (struct ocfs2_xattr_value_root *) | 4739 | vb.vb_xv = (struct ocfs2_xattr_value_root *) |
4730 | (vb.vb_bh->b_data + offset % blocksize); | 4740 | (vb.vb_bh->b_data + offset % blocksize); |
4731 | 4741 | ||
4732 | ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, | ||
4733 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
4734 | if (ret) { | ||
4735 | mlog_errno(ret); | ||
4736 | goto out; | ||
4737 | } | ||
4738 | |||
4739 | /* | 4742 | /* |
4740 | * From here on out we have to dirty the bucket. The generic | 4743 | * From here on out we have to dirty the bucket. The generic |
4741 | * value calls only modify one of the bucket's bhs, but we need | 4744 | * value calls only modify one of the bucket's bhs, but we need |
@@ -4748,12 +4751,18 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4748 | ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); | 4751 | ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); |
4749 | if (ret) { | 4752 | if (ret) { |
4750 | mlog_errno(ret); | 4753 | mlog_errno(ret); |
4751 | goto out_dirty; | 4754 | goto out; |
4755 | } | ||
4756 | |||
4757 | ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, | ||
4758 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
4759 | if (ret) { | ||
4760 | mlog_errno(ret); | ||
4761 | goto out; | ||
4752 | } | 4762 | } |
4753 | 4763 | ||
4754 | xe->xe_value_size = cpu_to_le64(len); | 4764 | xe->xe_value_size = cpu_to_le64(len); |
4755 | 4765 | ||
4756 | out_dirty: | ||
4757 | ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); | 4766 | ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); |
4758 | 4767 | ||
4759 | out: | 4768 | out: |
@@ -4786,19 +4795,33 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | |||
4786 | char *val, | 4795 | char *val, |
4787 | int value_len) | 4796 | int value_len) |
4788 | { | 4797 | { |
4789 | int offset; | 4798 | int ret, offset, block_off; |
4790 | struct ocfs2_xattr_value_root *xv; | 4799 | struct ocfs2_xattr_value_root *xv; |
4791 | struct ocfs2_xattr_entry *xe = xs->here; | 4800 | struct ocfs2_xattr_entry *xe = xs->here; |
4801 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); | ||
4802 | void *base; | ||
4792 | 4803 | ||
4793 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); | 4804 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); |
4794 | 4805 | ||
4795 | offset = le16_to_cpu(xe->xe_name_offset) + | 4806 | ret = ocfs2_xattr_bucket_get_name_value(inode, xh, |
4796 | OCFS2_XATTR_SIZE(xe->xe_name_len); | 4807 | xe - xh->xh_entries, |
4808 | &block_off, | ||
4809 | &offset); | ||
4810 | if (ret) { | ||
4811 | mlog_errno(ret); | ||
4812 | goto out; | ||
4813 | } | ||
4797 | 4814 | ||
4798 | xv = (struct ocfs2_xattr_value_root *)(xs->base + offset); | 4815 | base = bucket_block(xs->bucket, block_off); |
4816 | xv = (struct ocfs2_xattr_value_root *)(base + offset + | ||
4817 | OCFS2_XATTR_SIZE(xe->xe_name_len)); | ||
4799 | 4818 | ||
4800 | return __ocfs2_xattr_set_value_outside(inode, handle, | 4819 | ret = __ocfs2_xattr_set_value_outside(inode, handle, |
4801 | xv, val, value_len); | 4820 | xv, val, value_len); |
4821 | if (ret) | ||
4822 | mlog_errno(ret); | ||
4823 | out: | ||
4824 | return ret; | ||
4802 | } | 4825 | } |
4803 | 4826 | ||
4804 | static int ocfs2_rm_xattr_cluster(struct inode *inode, | 4827 | static int ocfs2_rm_xattr_cluster(struct inode *inode, |
@@ -5061,8 +5084,8 @@ try_again: | |||
5061 | xh_free_start = le16_to_cpu(xh->xh_free_start); | 5084 | xh_free_start = le16_to_cpu(xh->xh_free_start); |
5062 | header_size = sizeof(struct ocfs2_xattr_header) + | 5085 | header_size = sizeof(struct ocfs2_xattr_header) + |
5063 | count * sizeof(struct ocfs2_xattr_entry); | 5086 | count * sizeof(struct ocfs2_xattr_entry); |
5064 | max_free = OCFS2_XATTR_BUCKET_SIZE - | 5087 | max_free = OCFS2_XATTR_BUCKET_SIZE - header_size - |
5065 | le16_to_cpu(xh->xh_name_value_len) - header_size; | 5088 | le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP; |
5066 | 5089 | ||
5067 | mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size " | 5090 | mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size " |
5068 | "of %u which exceed block size\n", | 5091 | "of %u which exceed block size\n", |
@@ -5095,7 +5118,7 @@ try_again: | |||
5095 | need = 0; | 5118 | need = 0; |
5096 | } | 5119 | } |
5097 | 5120 | ||
5098 | free = xh_free_start - header_size; | 5121 | free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP; |
5099 | /* | 5122 | /* |
5100 | * We need to make sure the new name/value pair | 5123 | * We need to make sure the new name/value pair |
5101 | * can exist in the same block. | 5124 | * can exist in the same block. |
@@ -5128,7 +5151,8 @@ try_again: | |||
5128 | } | 5151 | } |
5129 | 5152 | ||
5130 | xh_free_start = le16_to_cpu(xh->xh_free_start); | 5153 | xh_free_start = le16_to_cpu(xh->xh_free_start); |
5131 | free = xh_free_start - header_size; | 5154 | free = xh_free_start - header_size |
5155 | - OCFS2_XATTR_HEADER_GAP; | ||
5132 | if (xh_free_start % blocksize < need) | 5156 | if (xh_free_start % blocksize < need) |
5133 | free -= xh_free_start % blocksize; | 5157 | free -= xh_free_start % blocksize; |
5134 | 5158 | ||