504
507
ocfs2_free(&bucket);
511
struct xattr_iterate_ctxt {
512
ocfs2_cached_inode *ci;
513
int (*func)(ocfs2_cached_inode *ci,
516
struct ocfs2_xattr_entry *xe,
518
uint64_t value_blkno,
526
static int ocfs2_xattr_iterate_entries(struct xattr_iterate_ctxt *ctxt,
527
char *xattr_buf, uint64_t xe_blkno,
528
struct ocfs2_xattr_header *xh,
531
int i, value_offset, block_offset;
532
struct ocfs2_xattr_entry *xe = NULL;
537
for (i = 0 ; i < xh->xh_count; i++) {
538
xe = &xh->xh_entries[i];
539
value_offset = xe->xe_name_offset +
540
OCFS2_XATTR_SIZE(xe->xe_name_len);
541
block_offset = value_offset / ctxt->ci->ci_fs->fs_blocksize;
542
value_buf = xattr_buf +
543
block_offset * ctxt->ci->ci_fs->fs_blocksize;
544
value = (char *)xh + value_offset;
547
iret = ctxt->func(ctxt->ci, xattr_buf, xe_blkno, xe,
548
value_buf, xe_blkno + block_offset,
551
if (iret & (OCFS2_XATTR_ABORT | OCFS2_XATTR_ERROR))
559
static int ocfs2_xattr_iterate_ibody(struct xattr_iterate_ctxt *ctxt)
561
struct ocfs2_xattr_header *xh = NULL;
562
struct ocfs2_dinode *di = ctxt->ci->ci_inode;
564
if (!(di->i_dyn_features & OCFS2_INLINE_XATTR_FL))
567
xh = (struct ocfs2_xattr_header *)((char *)di +
568
ctxt->ci->ci_fs->fs_blocksize - di->i_xattr_inline_size);
570
return ocfs2_xattr_iterate_entries(ctxt, (char *)di, di->i_blkno,
574
static int ocfs2_xattr_iterate_bucket(struct xattr_iterate_ctxt *ctxt,
575
uint64_t blkno, uint32_t clusters)
579
struct ocfs2_xattr_header *xh;
580
ocfs2_filesys *fs = ctxt->ci->ci_fs;
581
int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
582
uint32_t bpc = ocfs2_xattr_buckets_per_cluster(fs);
583
uint32_t num_buckets = clusters * bpc;
585
ctxt->errcode = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
589
for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
590
ctxt->errcode = ocfs2_read_xattr_bucket(fs, blkno, bucket);
594
xh = (struct ocfs2_xattr_header *)bucket;
596
* The real bucket num in this series of blocks is stored
600
num_buckets = xh->xh_num_buckets;
601
iret = ocfs2_xattr_iterate_entries(ctxt, bucket, blkno, xh, 1);
609
iret |= OCFS2_XATTR_ERROR;
614
static int ocfs2_xattr_iterate_index_block(struct xattr_iterate_ctxt *ctxt,
615
struct ocfs2_xattr_block *xb)
617
ocfs2_filesys *fs = ctxt->ci->ci_fs;
618
struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
619
uint32_t name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0;
620
uint64_t p_blkno = 0;
623
if (!el->l_next_free_rec)
626
while (name_hash > 0) {
627
ctxt->errcode = ocfs2_xattr_get_rec(fs, xb,
629
&e_cpos, &num_clusters);
633
iret = ocfs2_xattr_iterate_bucket(ctxt, p_blkno, num_clusters);
634
if (iret & (OCFS2_XATTR_ERROR | OCFS2_XATTR_ABORT))
640
name_hash = e_cpos - 1;
644
iret |= OCFS2_XATTR_ERROR;
648
static int ocfs2_xattr_iterate_block(struct xattr_iterate_ctxt *ctxt)
651
ocfs2_filesys *fs = ctxt->ci->ci_fs;
652
struct ocfs2_dinode *di = ctxt->ci->ci_inode;
653
struct ocfs2_xattr_block *xb;
656
if (!di->i_xattr_loc)
659
ctxt->errcode = ocfs2_malloc_block(fs->fs_io, &blk);
663
ctxt->errcode = ocfs2_read_xattr_block(fs, di->i_xattr_loc, blk);
667
xb = (struct ocfs2_xattr_block *)blk;
668
if (xb->xb_flags & OCFS2_XATTR_INDEXED)
669
iret = ocfs2_xattr_iterate_index_block(ctxt, xb);
671
struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
672
iret = ocfs2_xattr_iterate_entries(ctxt, blk,
673
di->i_xattr_loc, header, 0);
681
iret |= OCFS2_XATTR_ERROR;
688
* Iterate the xattr entries on inode 'ci'. If 'func' returns
689
* OCFS2_XATTR_ABORT or OCFS2_XATTR_ERROR, stop iteration.
690
* If OCFS2_XATTR_ERROR, return an error from ocfs2_xattr_iterate.
692
* If you modify an xattr, you must restart your iteration - there is
693
* no guarantee it is in a consistent state.
695
errcode_t ocfs2_xattr_iterate(ocfs2_cached_inode *ci,
696
int (*func)(ocfs2_cached_inode *ci,
699
struct ocfs2_xattr_entry *xe,
701
uint64_t value_blkno,
709
struct xattr_iterate_ctxt ctxt;
711
if (!ocfs2_support_xattr(OCFS2_RAW_SB(ci->ci_fs->fs_super)) ||
712
(!(ci->ci_inode->i_dyn_features & OCFS2_HAS_XATTR_FL)))
717
ctxt.priv_data = priv_data;
720
iret = ocfs2_xattr_iterate_ibody(&ctxt);
721
if (!(iret & (OCFS2_XATTR_ABORT | OCFS2_XATTR_ERROR)))
722
iret = ocfs2_xattr_iterate_block(&ctxt);
724
if (iret & OCFS2_XATTR_ERROR)