~davewalker/ubuntu/natty/ocfs2-tools/bug_363877

« back to all changes in this revision

Viewing changes to libocfs2/xattr.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Rodriguez
  • Date: 2011-01-14 12:46:49 UTC
  • mfrom: (1.1.10 upstream) (0.1.10 sid)
  • Revision ID: james.westby@ubuntu.com-20110114124649-vbe5qz211f3zxwuf
Tags: 1.6.3-1ubuntu1
* Merge from debian unstable (LP: #703008).  Remaining changes:
  - Fix configure tests for ld --as-needed.
  - Fix build failure with ld --no-add-needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
        xb->xb_fs_generation    = bswap_32(xb->xb_fs_generation);
94
94
        xb->xb_blkno            = bswap_64(xb->xb_blkno);
95
95
        xb->xb_flags            = bswap_16(xb->xb_flags);
 
96
        xb->xb_suballoc_loc     = bswap_64(xb->xb_suballoc_loc);
96
97
}
97
98
 
98
99
static void ocfs2_swap_xattr_header(struct ocfs2_xattr_header *xh)
354
355
                return OCFS2_ET_INVALID_ARGUMENT;
355
356
 
356
357
        if (el->l_tree_depth) {
357
 
                ret = ocfs2_xattr_find_leaf(fs, xb, name_hash, &eb_buf);
 
358
                ret = ocfs2_tree_find_leaf(fs, el, xb->xb_blkno, (char *)xb,
 
359
                                           name_hash, &eb_buf);
358
360
                if (ret)
359
361
                        goto out;
360
362
 
451
453
                goto out;
452
454
 
453
455
        xh = (struct ocfs2_xattr_header *)bucket;
454
 
        if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super))) {
 
456
        if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super)) &&
 
457
            !(fs->fs_flags & OCFS2_FLAG_NO_ECC_CHECKS)) {
455
458
                ret = ocfs2_block_check_validate(bucket,
456
459
                                                 OCFS2_XATTR_BUCKET_SIZE,
457
460
                                                 &xh->xh_check);
504
507
        ocfs2_free(&bucket);
505
508
        return ret;
506
509
}
 
510
 
 
511
struct xattr_iterate_ctxt {
 
512
        ocfs2_cached_inode *ci;
 
513
        int (*func)(ocfs2_cached_inode *ci,
 
514
                    char *xe_buf,
 
515
                    uint64_t xe_blkno,
 
516
                    struct ocfs2_xattr_entry *xe,
 
517
                    char *value_buf,
 
518
                    uint64_t value_blkno,
 
519
                    void *value,
 
520
                    int  in_bucket,
 
521
                    void *priv_data);
 
522
        errcode_t errcode;
 
523
        void *priv_data;
 
524
};
 
525
 
 
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,
 
529
                                       int is_bucket)
 
530
{
 
531
        int i, value_offset, block_offset;
 
532
        struct ocfs2_xattr_entry *xe = NULL;
 
533
        int iret = 0;
 
534
        char *value_buf;
 
535
        void *value;
 
536
 
 
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;
 
545
 
 
546
                if (ctxt->func) {
 
547
                        iret = ctxt->func(ctxt->ci, xattr_buf, xe_blkno, xe,
 
548
                                          value_buf, xe_blkno + block_offset,
 
549
                                          value, is_bucket,
 
550
                                          ctxt->priv_data);
 
551
                        if (iret & (OCFS2_XATTR_ABORT | OCFS2_XATTR_ERROR))
 
552
                                break;
 
553
                }
 
554
        }
 
555
 
 
556
        return iret;
 
557
}
 
558
 
 
559
static int ocfs2_xattr_iterate_ibody(struct xattr_iterate_ctxt *ctxt)
 
560
{
 
561
        struct ocfs2_xattr_header *xh = NULL;
 
562
        struct ocfs2_dinode *di = ctxt->ci->ci_inode;
 
563
 
 
564
        if (!(di->i_dyn_features & OCFS2_INLINE_XATTR_FL))
 
565
                return 0;
 
566
 
 
567
        xh = (struct ocfs2_xattr_header *)((char *)di +
 
568
                ctxt->ci->ci_fs->fs_blocksize - di->i_xattr_inline_size);
 
569
 
 
570
        return ocfs2_xattr_iterate_entries(ctxt, (char *)di, di->i_blkno,
 
571
                                           xh, 0);
 
572
}
 
573
 
 
574
static int ocfs2_xattr_iterate_bucket(struct xattr_iterate_ctxt *ctxt,
 
575
                                      uint64_t blkno, uint32_t clusters)
 
576
{
 
577
        int i, iret = 0 ;
 
578
        char *bucket = NULL;
 
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;
 
584
 
 
585
        ctxt->errcode = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
 
586
        if (ctxt->errcode)
 
587
                goto out;
 
588
 
 
589
        for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
 
590
                ctxt->errcode = ocfs2_read_xattr_bucket(fs, blkno, bucket);
 
591
                if (ctxt->errcode)
 
592
                        goto out;
 
593
 
 
594
                xh = (struct ocfs2_xattr_header *)bucket;
 
595
                /*
 
596
                 * The real bucket num in this series of blocks is stored
 
597
                 * in the 1st bucket.
 
598
                 */
 
599
                if (i == 0)
 
600
                        num_buckets = xh->xh_num_buckets;
 
601
                iret = ocfs2_xattr_iterate_entries(ctxt, bucket, blkno, xh, 1);
 
602
        }
 
603
 
 
604
out:
 
605
        if (bucket)
 
606
                ocfs2_free(&bucket);
 
607
 
 
608
        if (ctxt->errcode)
 
609
                iret |= OCFS2_XATTR_ERROR;
 
610
 
 
611
        return iret;
 
612
}
 
613
 
 
614
static int ocfs2_xattr_iterate_index_block(struct xattr_iterate_ctxt *ctxt,
 
615
                                           struct ocfs2_xattr_block *xb)
 
616
{
 
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;
 
621
        int iret = 0;
 
622
 
 
623
        if (!el->l_next_free_rec)
 
624
                return 0;
 
625
 
 
626
        while (name_hash > 0) {
 
627
                ctxt->errcode = ocfs2_xattr_get_rec(fs, xb,
 
628
                                                    name_hash, &p_blkno,
 
629
                                                    &e_cpos, &num_clusters);
 
630
                if (ctxt->errcode)
 
631
                        break;
 
632
 
 
633
                iret = ocfs2_xattr_iterate_bucket(ctxt, p_blkno, num_clusters);
 
634
                if (iret & (OCFS2_XATTR_ERROR | OCFS2_XATTR_ABORT))
 
635
                        break;
 
636
 
 
637
                if (e_cpos == 0)
 
638
                        break;
 
639
 
 
640
                name_hash = e_cpos - 1;
 
641
        }
 
642
 
 
643
        if (ctxt->errcode)
 
644
                iret |= OCFS2_XATTR_ERROR;
 
645
        return iret;
 
646
}
 
647
 
 
648
static int ocfs2_xattr_iterate_block(struct xattr_iterate_ctxt *ctxt)
 
649
{
 
650
        char *blk = NULL;
 
651
        ocfs2_filesys *fs = ctxt->ci->ci_fs;
 
652
        struct ocfs2_dinode *di = ctxt->ci->ci_inode;
 
653
        struct ocfs2_xattr_block *xb;
 
654
        int iret = 0;
 
655
 
 
656
        if (!di->i_xattr_loc)
 
657
                return 0;
 
658
 
 
659
        ctxt->errcode = ocfs2_malloc_block(fs->fs_io, &blk);
 
660
        if (ctxt->errcode)
 
661
                goto out;
 
662
 
 
663
        ctxt->errcode = ocfs2_read_xattr_block(fs, di->i_xattr_loc, blk);
 
664
        if (ctxt->errcode)
 
665
                goto out;
 
666
 
 
667
        xb = (struct ocfs2_xattr_block *)blk;
 
668
        if (xb->xb_flags & OCFS2_XATTR_INDEXED)
 
669
                iret = ocfs2_xattr_iterate_index_block(ctxt, xb);
 
670
        else {
 
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);
 
674
        }
 
675
 
 
676
out:
 
677
        if (blk)
 
678
                ocfs2_free(&blk);
 
679
 
 
680
        if (ctxt->errcode)
 
681
                iret |= OCFS2_XATTR_ERROR;
 
682
 
 
683
        return iret;
 
684
}
 
685
 
 
686
 
 
687
/*
 
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.
 
691
 *
 
692
 * If you modify an xattr, you must restart your iteration - there is
 
693
 * no guarantee it is in a consistent state.
 
694
 */
 
695
errcode_t ocfs2_xattr_iterate(ocfs2_cached_inode *ci,
 
696
                              int (*func)(ocfs2_cached_inode *ci,
 
697
                                          char *xe_buf,
 
698
                                          uint64_t xe_blkno,
 
699
                                          struct ocfs2_xattr_entry *xe,
 
700
                                          char *value_buf,
 
701
                                          uint64_t value_blkno,
 
702
                                          void *value,
 
703
                                          int in_bucket,
 
704
                                          void *priv_data),
 
705
                              void *priv_data)
 
706
{
 
707
        errcode_t ret = 0;
 
708
        int iret = 0;
 
709
        struct xattr_iterate_ctxt ctxt;
 
710
 
 
711
        if (!ocfs2_support_xattr(OCFS2_RAW_SB(ci->ci_fs->fs_super)) ||
 
712
            (!(ci->ci_inode->i_dyn_features & OCFS2_HAS_XATTR_FL)))
 
713
                return 0;
 
714
 
 
715
        ctxt.ci = ci;
 
716
        ctxt.func = func;
 
717
        ctxt.priv_data = priv_data;
 
718
        ctxt.errcode = 0;
 
719
 
 
720
        iret = ocfs2_xattr_iterate_ibody(&ctxt);
 
721
        if (!(iret & (OCFS2_XATTR_ABORT | OCFS2_XATTR_ERROR)))
 
722
                iret = ocfs2_xattr_iterate_block(&ctxt);
 
723
 
 
724
        if (iret & OCFS2_XATTR_ERROR)
 
725
                ret = ctxt.errcode;
 
726
 
 
727
        return ret;
 
728
}