diff options
author | Joel Becker <joel.becker@oracle.com> | 2009-08-19 14:09:17 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-02-26 18:41:13 -0500 |
commit | 139ffacebf5fe2cd9e2ae40d325a9661a679ad4f (patch) | |
tree | 4643a671b7712cfe7210cc970252641be17518ce /fs/ocfs2 | |
parent | d3981544d7a4ed276966cdd58fe2f5d6e8a585d9 (diff) |
ocfs2: Set inline xattr entries with ocfs2_xa_set()
ocfs2_xattr_ibody_set() is the only remaining user of
ocfs2_xattr_set_entry(). ocfs2_xattr_set_entry() actually does two
things: it calls ocfs2_xa_set(), and it initializes the inline xattrs.
Initializing the inline space really belongs in its own call.
We lift the initialization to ocfs2_xattr_ibody_init(), called from
ocfs2_xattr_ibody_set() only when necessary. Now
ocfs2_xattr_ibody_set() can call ocfs2_xa_set() directly.
ocfs2_xattr_set_entry() goes away.
Another nice fact is that ocfs2_init_dinode_xa_loc() can trust
i_xattr_inline_size.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/xattr.c | 157 |
1 files changed, 73 insertions, 84 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index fb8568d1e8a1..a2d912a92dd7 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -2137,17 +2137,13 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, | |||
2137 | { | 2137 | { |
2138 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | 2138 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; |
2139 | 2139 | ||
2140 | BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_XATTR_FL)); | ||
2141 | |||
2140 | loc->xl_inode = inode; | 2142 | loc->xl_inode = inode; |
2141 | loc->xl_ops = &ocfs2_xa_block_loc_ops; | 2143 | loc->xl_ops = &ocfs2_xa_block_loc_ops; |
2142 | loc->xl_storage = bh; | 2144 | loc->xl_storage = bh; |
2143 | loc->xl_entry = entry; | 2145 | loc->xl_entry = entry; |
2144 | 2146 | loc->xl_size = le16_to_cpu(di->i_xattr_inline_size); | |
2145 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_XATTR_FL) | ||
2146 | loc->xl_size = le16_to_cpu(di->i_xattr_inline_size); | ||
2147 | else { | ||
2148 | BUG_ON(entry); | ||
2149 | loc->xl_size = OCFS2_SB(inode->i_sb)->s_xattr_inline_size; | ||
2150 | } | ||
2151 | loc->xl_header = | 2147 | loc->xl_header = |
2152 | (struct ocfs2_xattr_header *)(bh->b_data + bh->b_size - | 2148 | (struct ocfs2_xattr_header *)(bh->b_data + bh->b_size - |
2153 | loc->xl_size); | 2149 | loc->xl_size); |
@@ -2184,80 +2180,6 @@ static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc, | |||
2184 | loc->xl_size = OCFS2_XATTR_BUCKET_SIZE; | 2180 | loc->xl_size = OCFS2_XATTR_BUCKET_SIZE; |
2185 | } | 2181 | } |
2186 | 2182 | ||
2187 | |||
2188 | /* | ||
2189 | * ocfs2_xattr_set_entry() | ||
2190 | * | ||
2191 | * Set extended attribute entry into inode or block. | ||
2192 | * | ||
2193 | * If extended attribute value size > OCFS2_XATTR_INLINE_SIZE, | ||
2194 | * We first insert tree root(ocfs2_xattr_value_root) like a normal value, | ||
2195 | * then set value in B tree with set_value_outside(). | ||
2196 | */ | ||
2197 | static int ocfs2_xattr_set_entry(struct inode *inode, | ||
2198 | struct ocfs2_xattr_info *xi, | ||
2199 | struct ocfs2_xattr_search *xs, | ||
2200 | struct ocfs2_xattr_set_ctxt *ctxt, | ||
2201 | int flag) | ||
2202 | { | ||
2203 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
2204 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | ||
2205 | handle_t *handle = ctxt->handle; | ||
2206 | int ret; | ||
2207 | struct ocfs2_xa_loc loc; | ||
2208 | |||
2209 | BUG_ON(!(flag & OCFS2_INLINE_XATTR_FL)); | ||
2210 | BUG_ON(xs->xattr_bh != xs->inode_bh); | ||
2211 | |||
2212 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), xs->inode_bh, | ||
2213 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2214 | if (ret) { | ||
2215 | mlog_errno(ret); | ||
2216 | goto out; | ||
2217 | } | ||
2218 | |||
2219 | ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh, | ||
2220 | xs->not_found ? NULL : xs->here); | ||
2221 | ret = ocfs2_xa_set(&loc, xi, ctxt); | ||
2222 | if (ret) { | ||
2223 | if (ret != -ENOSPC) | ||
2224 | mlog_errno(ret); | ||
2225 | goto out; | ||
2226 | } | ||
2227 | xs->here = loc.xl_entry; | ||
2228 | |||
2229 | if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { | ||
2230 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
2231 | unsigned int xattrsize = osb->s_xattr_inline_size; | ||
2232 | |||
2233 | /* | ||
2234 | * Adjust extent record count or inline data size | ||
2235 | * to reserve space for extended attribute. | ||
2236 | */ | ||
2237 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
2238 | struct ocfs2_inline_data *idata = &di->id2.i_data; | ||
2239 | le16_add_cpu(&idata->id_count, -xattrsize); | ||
2240 | } else if (!(ocfs2_inode_is_fast_symlink(inode))) { | ||
2241 | struct ocfs2_extent_list *el = &di->id2.i_list; | ||
2242 | le16_add_cpu(&el->l_count, -(xattrsize / | ||
2243 | sizeof(struct ocfs2_extent_rec))); | ||
2244 | } | ||
2245 | di->i_xattr_inline_size = cpu_to_le16(xattrsize); | ||
2246 | } | ||
2247 | /* Update xattr flag */ | ||
2248 | spin_lock(&oi->ip_lock); | ||
2249 | oi->ip_dyn_features |= OCFS2_INLINE_XATTR_FL; | ||
2250 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
2251 | spin_unlock(&oi->ip_lock); | ||
2252 | |||
2253 | ret = ocfs2_journal_dirty(handle, xs->inode_bh); | ||
2254 | if (ret < 0) | ||
2255 | mlog_errno(ret); | ||
2256 | |||
2257 | out: | ||
2258 | return ret; | ||
2259 | } | ||
2260 | |||
2261 | /* | 2183 | /* |
2262 | * In xattr remove, if it is stored outside and refcounted, we may have | 2184 | * In xattr remove, if it is stored outside and refcounted, we may have |
2263 | * the chance to split the refcount tree. So need the allocators. | 2185 | * the chance to split the refcount tree. So need the allocators. |
@@ -2653,6 +2575,55 @@ static int ocfs2_xattr_ibody_find(struct inode *inode, | |||
2653 | return 0; | 2575 | return 0; |
2654 | } | 2576 | } |
2655 | 2577 | ||
2578 | static int ocfs2_xattr_ibody_init(struct inode *inode, | ||
2579 | struct buffer_head *di_bh, | ||
2580 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
2581 | { | ||
2582 | int ret; | ||
2583 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
2584 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
2585 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
2586 | unsigned int xattrsize = osb->s_xattr_inline_size; | ||
2587 | |||
2588 | if (!ocfs2_xattr_has_space_inline(inode, di)) { | ||
2589 | ret = -ENOSPC; | ||
2590 | goto out; | ||
2591 | } | ||
2592 | |||
2593 | ret = ocfs2_journal_access_di(ctxt->handle, INODE_CACHE(inode), di_bh, | ||
2594 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2595 | if (ret) { | ||
2596 | mlog_errno(ret); | ||
2597 | goto out; | ||
2598 | } | ||
2599 | |||
2600 | /* | ||
2601 | * Adjust extent record count or inline data size | ||
2602 | * to reserve space for extended attribute. | ||
2603 | */ | ||
2604 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
2605 | struct ocfs2_inline_data *idata = &di->id2.i_data; | ||
2606 | le16_add_cpu(&idata->id_count, -xattrsize); | ||
2607 | } else if (!(ocfs2_inode_is_fast_symlink(inode))) { | ||
2608 | struct ocfs2_extent_list *el = &di->id2.i_list; | ||
2609 | le16_add_cpu(&el->l_count, -(xattrsize / | ||
2610 | sizeof(struct ocfs2_extent_rec))); | ||
2611 | } | ||
2612 | di->i_xattr_inline_size = cpu_to_le16(xattrsize); | ||
2613 | |||
2614 | spin_lock(&oi->ip_lock); | ||
2615 | oi->ip_dyn_features |= OCFS2_INLINE_XATTR_FL|OCFS2_HAS_XATTR_FL; | ||
2616 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
2617 | spin_unlock(&oi->ip_lock); | ||
2618 | |||
2619 | ret = ocfs2_journal_dirty(ctxt->handle, di_bh); | ||
2620 | if (ret < 0) | ||
2621 | mlog_errno(ret); | ||
2622 | |||
2623 | out: | ||
2624 | return ret; | ||
2625 | } | ||
2626 | |||
2656 | /* | 2627 | /* |
2657 | * ocfs2_xattr_ibody_set() | 2628 | * ocfs2_xattr_ibody_set() |
2658 | * | 2629 | * |
@@ -2664,9 +2635,10 @@ static int ocfs2_xattr_ibody_set(struct inode *inode, | |||
2664 | struct ocfs2_xattr_search *xs, | 2635 | struct ocfs2_xattr_search *xs, |
2665 | struct ocfs2_xattr_set_ctxt *ctxt) | 2636 | struct ocfs2_xattr_set_ctxt *ctxt) |
2666 | { | 2637 | { |
2638 | int ret; | ||
2667 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 2639 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
2668 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 2640 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
2669 | int ret; | 2641 | struct ocfs2_xa_loc loc; |
2670 | 2642 | ||
2671 | if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE) | 2643 | if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE) |
2672 | return -ENOSPC; | 2644 | return -ENOSPC; |
@@ -2679,8 +2651,25 @@ static int ocfs2_xattr_ibody_set(struct inode *inode, | |||
2679 | } | 2651 | } |
2680 | } | 2652 | } |
2681 | 2653 | ||
2682 | ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt, | 2654 | if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { |
2683 | (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL)); | 2655 | ret = ocfs2_xattr_ibody_init(inode, xs->inode_bh, ctxt); |
2656 | if (ret) { | ||
2657 | if (ret != -ENOSPC) | ||
2658 | mlog_errno(ret); | ||
2659 | goto out; | ||
2660 | } | ||
2661 | } | ||
2662 | |||
2663 | ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh, | ||
2664 | xs->not_found ? NULL : xs->here); | ||
2665 | ret = ocfs2_xa_set(&loc, xi, ctxt); | ||
2666 | if (ret) { | ||
2667 | if (ret != -ENOSPC) | ||
2668 | mlog_errno(ret); | ||
2669 | goto out; | ||
2670 | } | ||
2671 | xs->here = loc.xl_entry; | ||
2672 | |||
2684 | out: | 2673 | out: |
2685 | up_write(&oi->ip_alloc_sem); | 2674 | up_write(&oi->ip_alloc_sem); |
2686 | 2675 | ||