diff options
author | Tao Ma <tao.ma@oracle.com> | 2008-08-18 17:38:54 +0800 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2008-10-13 16:57:03 -0700 |
commit | a394425643e1e9c3a624d629fc8ba5633d8474c6 (patch) | |
tree | bf7ae7087452f22530448070cbccee921ba985ef /fs/ocfs2/xattr.c | |
parent | 012255961c9ecfe22b7a1df47ac26ab37818cb1e (diff) | |
download | linux-a394425643e1e9c3a624d629fc8ba5633d8474c6.tar.bz2 |
ocfs2: Delete all xattr buckets during inode removal
In inode removal, we need to iterate all the buckets, remove any
externally-stored EA values and delete the xattr buckets.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 5e8fae948882..9ec7136b3ad7 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -131,6 +131,9 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, struct ocfs2_xattr_info *xi, struct ocfs2_xattr_search *xs); +static int ocfs2_delete_xattr_index_block(struct inode *inode, + struct buffer_head *xb_bh); + static inline struct xattr_handler *ocfs2_xattr_handler(int name_index) { struct xattr_handler *handler = NULL; @@ -1511,13 +1514,14 @@ static int ocfs2_xattr_block_remove(struct inode *inode, struct buffer_head *blk_bh) { struct ocfs2_xattr_block *xb; - struct ocfs2_xattr_header *header; int ret = 0; xb = (struct ocfs2_xattr_block *)blk_bh->b_data; - header = &(xb->xb_attrs.xb_header); - - ret = ocfs2_remove_value_outside(inode, blk_bh, header); + if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { + struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header); + ret = ocfs2_remove_value_outside(inode, blk_bh, header); + } else + ret = ocfs2_delete_xattr_index_block(inode, blk_bh); return ret; } @@ -4738,3 +4742,75 @@ out: mlog_exit(ret); return ret; } + +static int ocfs2_delete_xattr_in_bucket(struct inode *inode, + struct ocfs2_xattr_bucket *bucket, + void *para) +{ + int ret = 0; + struct ocfs2_xattr_header *xh = bucket->xh; + u16 i; + struct ocfs2_xattr_entry *xe; + + for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { + xe = &xh->xh_entries[i]; + if (ocfs2_xattr_is_local(xe)) + continue; + + ret = ocfs2_xattr_bucket_value_truncate(inode, + bucket->bhs[0], + i, 0); + if (ret) { + mlog_errno(ret); + break; + } + } + + return ret; +} + +static int ocfs2_delete_xattr_index_block(struct inode *inode, + struct buffer_head *xb_bh) +{ + struct ocfs2_xattr_block *xb = + (struct ocfs2_xattr_block *)xb_bh->b_data; + struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list; + int ret = 0; + u32 name_hash = UINT_MAX, e_cpos, num_clusters; + u64 p_blkno; + + if (le16_to_cpu(el->l_next_free_rec) == 0) + return 0; + + while (name_hash > 0) { + ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, + &e_cpos, &num_clusters, el); + if (ret) { + mlog_errno(ret); + goto out; + } + + ret = ocfs2_iterate_xattr_buckets(inode, p_blkno, num_clusters, + ocfs2_delete_xattr_in_bucket, + NULL); + if (ret) { + mlog_errno(ret); + goto out; + } + + ret = ocfs2_rm_xattr_cluster(inode, xb_bh, + p_blkno, e_cpos, num_clusters); + if (ret) { + mlog_errno(ret); + break; + } + + if (e_cpos == 0) + break; + + name_hash = e_cpos - 1; + } + +out: + return ret; +} |