~wb-munzinger/+junk/ocfs2-tools

« back to all changes in this revision

Viewing changes to tunefs.ocfs2/libocfs2ne.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:
577
577
        return ret;
578
578
}
579
579
 
 
580
/* A dirblock we have to add a trailer to */
 
581
struct tunefs_trailer_dirblock {
 
582
        struct list_head db_list;
 
583
        uint64_t db_blkno;
 
584
        char *db_buf;
 
585
 
 
586
        /*
 
587
         * These require a little explanation.  They point to
 
588
         * ocfs2_dir_entry structures inside db_buf.
 
589
         *
 
590
         * db_last is the entry we're going to *keep*.  If the last
 
591
         * entry in the dirblock has enough extra rec_len to allow the
 
592
         * trailer, db_last points to it.  We will shorten its rec_len
 
593
         * and insert the trailer.
 
594
         *
 
595
         * However, if the last entry in the dirblock cannot be
 
596
         * truncated, db_last points to the entry before that - the
 
597
         * last entry we're keeping in this dirblock.
 
598
         *
 
599
         * Examples:
 
600
         *
 
601
         * - The last entry in the dirblock has a name_len of 1 and a
 
602
         *   rec_len of 128.  We can easily change the rec_len to 64 and
 
603
         *   insert the trailer.  db_last points to this entry.
 
604
         *
 
605
         * - The last entry in the dirblock has a name_len of 1 and a
 
606
         *   rec_len of 48.  The previous entry has a name_len of 1 and a
 
607
         *   rec_len of 32.  We have to move the last entry out.  The
 
608
         *   second-to-last entry can have its rec_len truncated to 16, so
 
609
         *   we put it in db_last.
 
610
         */
 
611
        struct ocfs2_dir_entry *db_last;
 
612
};
 
613
 
 
614
void tunefs_trailer_context_free(struct tunefs_trailer_context *tc)
 
615
{
 
616
        struct tunefs_trailer_dirblock *db;
 
617
        struct list_head *n, *pos;
 
618
 
 
619
        if (!list_empty(&tc->d_list))
 
620
                list_del(&tc->d_list);
 
621
 
 
622
        list_for_each_safe(pos, n, &tc->d_dirblocks) {
 
623
                db = list_entry(pos, struct tunefs_trailer_dirblock, db_list);
 
624
                list_del(&db->db_list);
 
625
                ocfs2_free(&db->db_buf);
 
626
                ocfs2_free(&db);
 
627
        }
 
628
 
 
629
        ocfs2_free(&tc);
 
630
}
 
631
 
 
632
/*
 
633
 * We're calculating how many bytes we need to add to make space for
 
634
 * the dir trailers.  But we need to make sure that the added directory
 
635
 * blocks also have room for a trailer.
 
636
 */
 
637
static void add_bytes_needed(ocfs2_filesys *fs,
 
638
                             struct tunefs_trailer_context *tc,
 
639
                             unsigned int rec_len)
 
640
{
 
641
        unsigned int toff = ocfs2_dir_trailer_blk_off(fs);
 
642
        unsigned int block_offset = tc->d_bytes_needed % fs->fs_blocksize;
 
643
 
 
644
        /*
 
645
         * If the current byte offset would put us into a trailer, push
 
646
         * it out to the start of the next block.  Remember, dirents have
 
647
         * to be at least 16 bytes, which is why we check against the
 
648
         * smallest rec_len.
 
649
         */
 
650
        if ((block_offset + rec_len) > (toff - OCFS2_DIR_REC_LEN(1)))
 
651
                tc->d_bytes_needed += fs->fs_blocksize - block_offset;
 
652
 
 
653
        tc->d_bytes_needed += rec_len;
 
654
        tc->d_blocks_needed =
 
655
                ocfs2_blocks_in_bytes(fs, tc->d_bytes_needed);
 
656
}
 
657
 
 
658
static errcode_t walk_dirblock(ocfs2_filesys *fs,
 
659
                               struct tunefs_trailer_context *tc,
 
660
                               struct tunefs_trailer_dirblock *db)
 
661
{
 
662
        errcode_t ret = 0;
 
663
        struct ocfs2_dir_entry *dirent, *prev = NULL;
 
664
        unsigned int real_rec_len;
 
665
        unsigned int offset = 0;
 
666
        unsigned int toff = ocfs2_dir_trailer_blk_off(fs);
 
667
 
 
668
        while (offset < fs->fs_blocksize) {
 
669
                dirent = (struct ocfs2_dir_entry *) (db->db_buf + offset);
 
670
                if (((offset + dirent->rec_len) > fs->fs_blocksize) ||
 
671
                    (dirent->rec_len < 8) ||
 
672
                    ((dirent->rec_len % 4) != 0) ||
 
673
                    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
 
674
                        ret = OCFS2_ET_DIR_CORRUPTED;
 
675
                        break;
 
676
                }
 
677
 
 
678
                real_rec_len = dirent->inode ?
 
679
                        OCFS2_DIR_REC_LEN(dirent->name_len) :
 
680
                        OCFS2_DIR_REC_LEN(1);
 
681
                if ((offset + real_rec_len) <= toff)
 
682
                        goto next;
 
683
 
 
684
                /*
 
685
                 * The first time through, we store off the last dirent
 
686
                 * before the trailer.
 
687
                 */
 
688
                if (!db->db_last)
 
689
                        db->db_last = prev;
 
690
 
 
691
                /* Only live dirents need to be moved */
 
692
                if (dirent->inode) {
 
693
                        verbosef(VL_DEBUG,
 
694
                                 "Will move dirent %.*s out of "
 
695
                                 "directory block %"PRIu64" to make way "
 
696
                                 "for the trailer\n",
 
697
                                 dirent->name_len, dirent->name,
 
698
                                 db->db_blkno);
 
699
                        add_bytes_needed(fs, tc, real_rec_len);
 
700
                }
 
701
 
 
702
next:
 
703
                prev = dirent;
 
704
                offset += dirent->rec_len;
 
705
        }
 
706
 
 
707
        /* There were no dirents across the boundary */
 
708
        if (!db->db_last)
 
709
                db->db_last = prev;
 
710
 
 
711
        return ret;
 
712
}
 
713
 
 
714
static int dirblock_scan_iterate(ocfs2_filesys *fs, uint64_t blkno,
 
715
                                 uint64_t bcount, uint16_t ext_flags,
 
716
                                 void *priv_data)
 
717
{
 
718
        errcode_t ret = 0;
 
719
        struct tunefs_trailer_dirblock *db = NULL;
 
720
        struct tunefs_trailer_context *tc = priv_data;
 
721
 
 
722
        ret = ocfs2_malloc0(sizeof(struct tunefs_trailer_dirblock), &db);
 
723
        if (ret)
 
724
                goto out;
 
725
 
 
726
        ret = ocfs2_malloc_block(fs->fs_io, &db->db_buf);
 
727
        if (ret)
 
728
                goto out;
 
729
 
 
730
        db->db_blkno = blkno;
 
731
 
 
732
        verbosef(VL_DEBUG,
 
733
                 "Reading dinode %"PRIu64" dirblock %"PRIu64" at block "
 
734
                 "%"PRIu64"\n",
 
735
                 tc->d_di->i_blkno, bcount, blkno);
 
736
        ret = ocfs2_read_dir_block(fs, tc->d_di, blkno, db->db_buf);
 
737
        if (ret)
 
738
                goto out;
 
739
 
 
740
        ret = walk_dirblock(fs, tc, db);
 
741
        if (ret)
 
742
                goto out;
 
743
 
 
744
        list_add_tail(&db->db_list, &tc->d_dirblocks);
 
745
        db = NULL;
 
746
 
 
747
out:
 
748
        if (db) {
 
749
                if (db->db_buf)
 
750
                        ocfs2_free(&db->db_buf);
 
751
                ocfs2_free(&db);
 
752
        }
 
753
 
 
754
        if (ret) {
 
755
                tc->d_err = ret;
 
756
                return OCFS2_BLOCK_ABORT;
 
757
        }
 
758
 
 
759
        return 0;
 
760
}
 
761
 
 
762
errcode_t tunefs_prepare_dir_trailer(ocfs2_filesys *fs,
 
763
                                     struct ocfs2_dinode *di,
 
764
                                     struct tunefs_trailer_context **tc_ret)
 
765
{
 
766
        errcode_t ret = 0;
 
767
        struct tunefs_trailer_context *tc = NULL;
 
768
 
 
769
        if (ocfs2_dir_has_trailer(fs, di))
 
770
                goto out;
 
771
 
 
772
        ret = ocfs2_malloc0(sizeof(struct tunefs_trailer_context), &tc);
 
773
        if (ret)
 
774
                goto out;
 
775
 
 
776
        tc->d_blkno = di->i_blkno;
 
777
        tc->d_di = di;
 
778
        INIT_LIST_HEAD(&tc->d_list);
 
779
        INIT_LIST_HEAD(&tc->d_dirblocks);
 
780
 
 
781
        ret = ocfs2_block_iterate_inode(fs, tc->d_di, 0,
 
782
                                        dirblock_scan_iterate, tc);
 
783
        if (!ret)
 
784
                ret = tc->d_err;
 
785
        if (ret)
 
786
                goto out;
 
787
 
 
788
        *tc_ret = tc;
 
789
        tc = NULL;
 
790
 
 
791
out:
 
792
        if (tc)
 
793
                tunefs_trailer_context_free(tc);
 
794
 
 
795
        return ret;
 
796
}
 
797
 
 
798
/*
 
799
 * We are hand-coding the directory expansion because we're going to
 
800
 * build the new directory blocks ourselves.  We can't just use
 
801
 * ocfs2_expand_dir() and ocfs2_link(), because we're moving around
 
802
 * entries.
 
803
 */
 
804
static errcode_t expand_dir_if_needed(ocfs2_filesys *fs,
 
805
                                      struct ocfs2_dinode *di,
 
806
                                      uint64_t blocks_needed)
 
807
{
 
808
        errcode_t ret = 0;
 
809
        uint64_t used_blocks, total_blocks;
 
810
        uint32_t clusters_needed;
 
811
 
 
812
        /* This relies on the fact that i_size of a directory is a
 
813
         * multiple of blocksize */
 
814
        used_blocks = ocfs2_blocks_in_bytes(fs, di->i_size);
 
815
        total_blocks = ocfs2_clusters_to_blocks(fs, di->i_clusters);
 
816
        if ((used_blocks + blocks_needed) <= total_blocks)
 
817
                goto out;
 
818
 
 
819
        clusters_needed =
 
820
                ocfs2_clusters_in_blocks(fs,
 
821
                                         (used_blocks + blocks_needed) -
 
822
                                         total_blocks);
 
823
        ret = ocfs2_extend_allocation(fs, di->i_blkno, clusters_needed);
 
824
        if (ret)
 
825
                goto out;
 
826
 
 
827
        /* Pick up changes to the inode */
 
828
        ret = ocfs2_read_inode(fs, di->i_blkno, (char *)di);
 
829
 
 
830
out:
 
831
        return ret;
 
832
}
 
833
 
 
834
static void shift_dirent(ocfs2_filesys *fs,
 
835
                         struct tunefs_trailer_context *tc,
 
836
                         struct ocfs2_dir_entry *dirent)
 
837
{
 
838
        /* Using the real rec_len */
 
839
        unsigned int rec_len = OCFS2_DIR_REC_LEN(dirent->name_len);
 
840
        unsigned int offset, remain;
 
841
 
 
842
        /*
 
843
         * If the current byte offset would put us into a trailer, push
 
844
         * it out to the start of the next block.  Remember, dirents have
 
845
         * to be at least 16 bytes, which is why we check against the
 
846
         * smallest rec_len.
 
847
         */
 
848
        if (rec_len > (tc->d_next_dirent->rec_len - OCFS2_DIR_REC_LEN(1))) {
 
849
                tc->d_cur_block += fs->fs_blocksize;
 
850
                tc->d_next_dirent = (struct ocfs2_dir_entry *)tc->d_cur_block;
 
851
        }
 
852
 
 
853
        assert(ocfs2_blocks_in_bytes(fs,
 
854
                                     tc->d_cur_block - tc->d_new_blocks) <
 
855
               tc->d_blocks_needed);
 
856
 
 
857
        offset = (char *)(tc->d_next_dirent) - tc->d_cur_block;
 
858
        remain = tc->d_next_dirent->rec_len - rec_len;
 
859
 
 
860
        memcpy(tc->d_cur_block + offset, dirent, rec_len);
 
861
        tc->d_next_dirent->rec_len = rec_len;
 
862
 
 
863
        verbosef(VL_DEBUG,
 
864
                 "Installed dirent %.*s at offset %u of new block "
 
865
                 "%"PRIu64", rec_len %u\n",
 
866
                 tc->d_next_dirent->name_len, tc->d_next_dirent->name,
 
867
                 offset,
 
868
                 ocfs2_blocks_in_bytes(fs, tc->d_cur_block - tc->d_new_blocks),
 
869
                 rec_len);
 
870
 
 
871
 
 
872
        offset += rec_len;
 
873
        tc->d_next_dirent =
 
874
                (struct ocfs2_dir_entry *)(tc->d_cur_block + offset);
 
875
        tc->d_next_dirent->rec_len = remain;
 
876
 
 
877
        verbosef(VL_DEBUG,
 
878
                 "New block %"PRIu64" has its last dirent at %u, with %u "
 
879
                 "bytes left\n",
 
880
                 ocfs2_blocks_in_bytes(fs, tc->d_cur_block - tc->d_new_blocks),
 
881
                 offset, remain);
 
882
}
 
883
 
 
884
static errcode_t fixup_dirblock(ocfs2_filesys *fs,
 
885
                                struct tunefs_trailer_context *tc,
 
886
                                struct tunefs_trailer_dirblock *db)
 
887
{
 
888
        errcode_t ret = 0;
 
889
        struct ocfs2_dir_entry *dirent;
 
890
        unsigned int real_rec_len;
 
891
        unsigned int offset;
 
892
        unsigned int toff = ocfs2_dir_trailer_blk_off(fs);
 
893
 
 
894
        /*
 
895
         * db_last is the last dirent we're *keeping*.  So we need to 
 
896
         * move out every valid dirent *after* db_last.
 
897
         *
 
898
         * tunefs_prepare_dir_trailer() should have calculated this
 
899
         * correctly.
 
900
         */
 
901
        offset = ((char *)db->db_last) - db->db_buf;
 
902
        offset += db->db_last->rec_len;
 
903
        while (offset < fs->fs_blocksize) {
 
904
                dirent = (struct ocfs2_dir_entry *) (db->db_buf + offset);
 
905
                if (((offset + dirent->rec_len) > fs->fs_blocksize) ||
 
906
                    (dirent->rec_len < 8) ||
 
907
                    ((dirent->rec_len % 4) != 0) ||
 
908
                    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
 
909
                        ret = OCFS2_ET_DIR_CORRUPTED;
 
910
                        break;
 
911
                }
 
912
 
 
913
                real_rec_len = dirent->inode ?
 
914
                        OCFS2_DIR_REC_LEN(dirent->name_len) :
 
915
                        OCFS2_DIR_REC_LEN(1);
 
916
 
 
917
                assert((offset + real_rec_len) > toff);
 
918
 
 
919
                /* Only live dirents need to be moved */
 
920
                if (dirent->inode) {
 
921
                        verbosef(VL_DEBUG,
 
922
                                 "Moving dirent %.*s out of directory "
 
923
                                 "block %"PRIu64" to make way for the "
 
924
                                 "trailer\n",
 
925
                                 dirent->name_len, dirent->name,
 
926
                                 db->db_blkno);
 
927
                        shift_dirent(fs, tc, dirent);
 
928
                }
 
929
 
 
930
                offset += dirent->rec_len;
 
931
        }
 
932
 
 
933
        /*
 
934
         * Now that we've moved any dirents out of the way, we need to
 
935
         * fix up db_last and install the trailer.
 
936
         */
 
937
        offset = ((char *)db->db_last) - db->db_buf;
 
938
        verbosef(VL_DEBUG,
 
939
                 "Last valid dirent of directory block %"PRIu64" "
 
940
                 "(\"%.*s\") is %u bytes in.  Setting rec_len to %u and "
 
941
                 "installing the trailer\n",
 
942
                 db->db_blkno, db->db_last->name_len, db->db_last->name,
 
943
                 offset, toff - offset);
 
944
        db->db_last->rec_len = toff - offset;
 
945
        ocfs2_init_dir_trailer(fs, tc->d_di, db->db_blkno, db->db_buf);
 
946
 
 
947
        return ret;
 
948
}
 
949
 
 
950
static errcode_t run_dirblocks(ocfs2_filesys *fs,
 
951
                               struct tunefs_trailer_context *tc)
 
952
{
 
953
        errcode_t ret = 0;
 
954
        struct list_head *pos;
 
955
        struct tunefs_trailer_dirblock *db;
 
956
 
 
957
        list_for_each(pos, &tc->d_dirblocks) {
 
958
                db = list_entry(pos, struct tunefs_trailer_dirblock, db_list);
 
959
                ret = fixup_dirblock(fs, tc, db);
 
960
                if (ret)
 
961
                        break;
 
962
        }
 
963
 
 
964
        return ret;
 
965
}
 
966
 
 
967
static errcode_t write_dirblocks(ocfs2_filesys *fs,
 
968
                                 struct tunefs_trailer_context *tc)
 
969
{
 
970
        errcode_t ret = 0;
 
971
        struct list_head *pos;
 
972
        struct tunefs_trailer_dirblock *db;
 
973
 
 
974
        list_for_each(pos, &tc->d_dirblocks) {
 
975
                db = list_entry(pos, struct tunefs_trailer_dirblock, db_list);
 
976
                ret = ocfs2_write_dir_block(fs, tc->d_di, db->db_blkno,
 
977
                                            db->db_buf);
 
978
                if (ret) {
 
979
                        verbosef(VL_DEBUG,
 
980
                                 "Error writing dirblock %"PRIu64"\n",
 
981
                                 db->db_blkno);
 
982
                        break;
 
983
                }
 
984
        }
 
985
 
 
986
        return ret;
 
987
}
 
988
 
 
989
static errcode_t init_new_dirblocks(ocfs2_filesys *fs,
 
990
                                    struct tunefs_trailer_context *tc)
 
991
{
 
992
        int i;
 
993
        errcode_t ret;
 
994
        uint64_t blkno;
 
995
        uint64_t orig_block = ocfs2_blocks_in_bytes(fs, tc->d_di->i_size);
 
996
        ocfs2_cached_inode *cinode;
 
997
        char *blockptr;
 
998
        struct ocfs2_dir_entry *first;
 
999
 
 
1000
        ret = ocfs2_read_cached_inode(fs, tc->d_blkno, &cinode);
 
1001
        if (ret)
 
1002
                goto out;
 
1003
        assert(!memcmp(tc->d_di, cinode->ci_inode, fs->fs_blocksize));
 
1004
 
 
1005
        for (i = 0; i < tc->d_blocks_needed; i++) {
 
1006
                ret = ocfs2_extent_map_get_blocks(cinode, orig_block + i,
 
1007
                                                  1, &blkno, NULL, NULL);
 
1008
                if (ret)
 
1009
                        goto out;
 
1010
                blockptr = tc->d_new_blocks + (i * fs->fs_blocksize);
 
1011
                memset(blockptr, 0, fs->fs_blocksize);
 
1012
                first = (struct ocfs2_dir_entry *)blockptr;
 
1013
                first->rec_len = ocfs2_dir_trailer_blk_off(fs);
 
1014
                ocfs2_init_dir_trailer(fs, tc->d_di, blkno, blockptr);
 
1015
        }
 
1016
 
 
1017
out:
 
1018
        return ret;
 
1019
}
 
1020
 
 
1021
static errcode_t write_new_dirblocks(ocfs2_filesys *fs,
 
1022
                                     struct tunefs_trailer_context *tc)
 
1023
{
 
1024
        int i;
 
1025
        errcode_t ret;
 
1026
        uint64_t blkno;
 
1027
        uint64_t orig_block = ocfs2_blocks_in_bytes(fs, tc->d_di->i_size);
 
1028
        ocfs2_cached_inode *cinode;
 
1029
        char *blockptr;
 
1030
 
 
1031
        ret = ocfs2_read_cached_inode(fs, tc->d_blkno, &cinode);
 
1032
        if (ret)
 
1033
                goto out;
 
1034
        assert(!memcmp(tc->d_di, cinode->ci_inode, fs->fs_blocksize));
 
1035
 
 
1036
        for (i = 0; i < tc->d_blocks_needed; i++) {
 
1037
                ret = ocfs2_extent_map_get_blocks(cinode, orig_block + i,
 
1038
                                                  1, &blkno, NULL, NULL);
 
1039
                if (ret)
 
1040
                        goto out;
 
1041
                blockptr = tc->d_new_blocks + (i * fs->fs_blocksize);
 
1042
                ret = ocfs2_write_dir_block(fs, tc->d_di, blkno, blockptr);
 
1043
                if (ret) {
 
1044
                        verbosef(VL_DEBUG,
 
1045
                                 "Error writing dirblock %"PRIu64"\n",
 
1046
                                 blkno);
 
1047
                        goto out;
 
1048
                }
 
1049
        }
 
1050
 
 
1051
out:
 
1052
        return ret;
 
1053
}
 
1054
 
 
1055
errcode_t tunefs_install_dir_trailer(ocfs2_filesys *fs,
 
1056
                                        struct ocfs2_dinode *di,
 
1057
                                        struct tunefs_trailer_context *tc)
 
1058
{
 
1059
        errcode_t ret = 0;
 
1060
        struct tunefs_trailer_context *our_tc = NULL;
 
1061
 
 
1062
        if (!tc) {
 
1063
                ret = tunefs_prepare_dir_trailer(fs, di, &our_tc);
 
1064
                if (ret)
 
1065
                        goto out;
 
1066
                tc = our_tc;
 
1067
        }
 
1068
 
 
1069
        if (tc->d_di != di) {
 
1070
                ret = OCFS2_ET_INVALID_ARGUMENT;
 
1071
                goto out;
 
1072
        }
 
1073
 
 
1074
        if (tc->d_blocks_needed) {
 
1075
                ret = ocfs2_malloc_blocks(fs->fs_io, tc->d_blocks_needed,
 
1076
                                          &tc->d_new_blocks);
 
1077
                if (ret)
 
1078
                        goto out;
 
1079
 
 
1080
                tc->d_cur_block = tc->d_new_blocks;
 
1081
 
 
1082
                ret = expand_dir_if_needed(fs, di, tc->d_blocks_needed);
 
1083
                if (ret)
 
1084
                        goto out;
 
1085
 
 
1086
                ret = init_new_dirblocks(fs, tc);
 
1087
                if (ret)
 
1088
                        goto out;
 
1089
                tc->d_next_dirent = (struct ocfs2_dir_entry *)tc->d_cur_block;
 
1090
                verbosef(VL_DEBUG, "t_next_dirent has rec_len of %u\n",
 
1091
                         tc->d_next_dirent->rec_len);
 
1092
        }
 
1093
 
 
1094
        ret = run_dirblocks(fs, tc);
 
1095
        if (ret)
 
1096
                goto out;
 
1097
 
 
1098
        /*
 
1099
         * We write in a specific order.  We write any new dirblocks first
 
1100
         * so that they are on disk.  Then we write the new i_size in the
 
1101
         * inode.  If we crash at this point, the directory has duplicate
 
1102
         * entries but no lost entries.  fsck can clean it up.  Finally, we
 
1103
         * write the modified dirblocks with trailers.
 
1104
         */
 
1105
        if (tc->d_blocks_needed) {
 
1106
                ret = write_new_dirblocks(fs, tc);
 
1107
                if (ret)
 
1108
                        goto out;
 
1109
 
 
1110
                di->i_size += ocfs2_blocks_to_bytes(fs, tc->d_blocks_needed);
 
1111
                ret = ocfs2_write_inode(fs, di->i_blkno, (char *)di);
 
1112
                if (ret)
 
1113
                        goto out;
 
1114
        }
 
1115
 
 
1116
        ret = write_dirblocks(fs, tc);
 
1117
 
 
1118
out:
 
1119
        if (our_tc)
 
1120
                tunefs_trailer_context_free(our_tc);
 
1121
        return ret;
 
1122
}
580
1123
 
581
1124
/*
582
1125
 * Starting, opening, closing, and exiting.
1306
1849
         * allocates it, child filesyses just use it.
1307
1850
         */
1308
1851
        if (state->ts_master != fs) {
1309
 
                fs->fs_io = state->ts_master->fs_io;
 
1852
                io_share_cache(state->ts_master->fs_io, fs->fs_io);
1310
1853
                return;
1311
1854
        }
1312
1855
 
1362
1905
        }
1363
1906
}
1364
1907
 
1365
 
static void tunefs_drop_cache(ocfs2_filesys *fs)
1366
 
{
1367
 
        struct tunefs_filesystem_state *state = tunefs_get_state(fs);
1368
 
 
1369
 
        /*
1370
 
         * The master filesys created our cache.  We don't want
1371
 
         * ocfs2_close() to kill it if we're closing a non-master,
1372
 
         * so kill the pointer for those.
1373
 
         */
1374
 
        if (state->ts_master == fs)
1375
 
                io_destroy_cache(fs->fs_io);
1376
 
        else
1377
 
                fs->fs_io = NULL;
1378
 
}
1379
 
 
1380
1908
static errcode_t tunefs_add_fs(ocfs2_filesys *fs, int flags)
1381
1909
{
1382
1910
        errcode_t err;
1533
2061
out:
1534
2062
        if (err && !tunefs_special_errorp(err)) {
1535
2063
                if (fs) {
1536
 
                        tunefs_drop_cache(fs);
1537
2064
                        tunefs_remove_fs(fs);
1538
2065
                        ocfs2_close(fs);
1539
2066
                        fs = NULL;
1563
2090
                if (!err)
1564
2091
                        err = tmp;
1565
2092
 
1566
 
                tunefs_drop_cache(fs);
1567
2093
                tunefs_remove_fs(fs);
1568
2094
                tmp = ocfs2_close(fs);
1569
2095
                if (!err)