]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: update to 3.16 kernel code
authorDave Chinner <dchinner@redhat.com>
Thu, 30 Jul 2015 22:32:52 +0000 (08:32 +1000)
committerDave Chinner <david@fromorbit.com>
Thu, 30 Jul 2015 22:32:52 +0000 (08:32 +1000)
Bulk update, including all the changes to the surrounding userspace
code due to API changes.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
74 files changed:
db/block.c
db/bmap.c
db/bmroot.c
db/check.c
db/dir2.c
db/dir2sf.c
db/faddr.c
db/frag.c
db/inode.c
db/metadump.c
include/libxfs.h
include/xfs_ag.h
include/xfs_attr_leaf.h
include/xfs_bit.h
include/xfs_bmap.h
include/xfs_bmap_btree.h
include/xfs_btree.h
include/xfs_da_btree.h
include/xfs_da_format.h
include/xfs_dir2.h
include/xfs_format.h
include/xfs_fs.h
include/xfs_ialloc.h
include/xfs_inode_fork.h
include/xfs_quota_defs.h
include/xfs_sb.h
include/xfs_shared.h
include/xfs_trace.h
include/xfs_trans_resv.h
include/xfs_trans_space.h
libxfs/Makefile
libxfs/init.c
libxfs/rdwr.c
libxfs/util.c
libxfs/xfs.h
libxfs/xfs_alloc.c
libxfs/xfs_alloc_btree.c
libxfs/xfs_attr.c
libxfs/xfs_attr_leaf.c
libxfs/xfs_attr_remote.c
libxfs/xfs_bmap.c
libxfs/xfs_bmap_btree.c
libxfs/xfs_btree.c
libxfs/xfs_da_btree.c
libxfs/xfs_da_format.c [new file with mode: 0644]
libxfs/xfs_dir2.c
libxfs/xfs_dir2_block.c
libxfs/xfs_dir2_data.c
libxfs/xfs_dir2_leaf.c
libxfs/xfs_dir2_node.c
libxfs/xfs_dir2_priv.h
libxfs/xfs_dir2_sf.c
libxfs/xfs_dquot_buf.c
libxfs/xfs_ialloc.c
libxfs/xfs_ialloc_btree.c
libxfs/xfs_inode_buf.c
libxfs/xfs_inode_fork.c
libxfs/xfs_log_rlimit.c
libxfs/xfs_rtbitmap.c
libxfs/xfs_sb.c
libxfs/xfs_symlink_remote.c
libxfs/xfs_trans_resv.c
logprint/log_misc.c
mkfs/maxtrres.c
mkfs/proto.c
mkfs/xfs_mkfs.c
repair/attr_repair.c
repair/dino_chunks.c
repair/dinode.c
repair/dir2.c
repair/phase6.c
repair/prefetch.c
repair/versions.c
repair/xfs_repair.c

index b279aac6e857bc0f63d143aa4fe76e11f50d5be5..c561654f8de91f80c0d3fc7b44d47691cb095cf1 100644 (file)
@@ -185,7 +185,7 @@ dblock_f(
                dbprintf(_("no type for file data\n"));
                return 0;
        }
-       nex = nb = type == TYP_DIR2 ? mp->m_dirblkfsbs : 1;
+       nex = nb = type == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1;
        bmp = malloc(nb * sizeof(*bmp));
        bmap(bno, nb, XFS_DATA_FORK, &nex, bmp);
        if (nex == 0) {
index fe620fd2b986b44662300cbe52de9b95b9d88b6b..fafa8931b4e28ac8e385677c9b06faefc0b6ef7e 100644 (file)
--- a/db/bmap.c
+++ b/db/bmap.c
@@ -90,7 +90,7 @@ bmap(
                push_cur();
                rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
                fsize = XFS_DFORK_SIZE(dip, mp, whichfork);
-               pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(mp, fsize, 0));
+               pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(fsize, 0));
                kp = XFS_BMDR_KEY_ADDR(rblock, 1);
                bno = select_child(curoffset, kp, pp, 
                                        be16_to_cpu(rblock->bb_numrecs));
@@ -276,10 +276,9 @@ convert_extent(
        xfs_dfilblks_t          *cp,
        int                     *fp)
 {
-       xfs_bmbt_irec_t         irec;
+       struct xfs_bmbt_irec    irec;
 
        libxfs_bmbt_disk_get_all(rp, &irec);
-
        *fp = irec.br_state == XFS_EXT_UNWRITTEN;
        *op = irec.br_startoff;
        *sp = irec.br_startblock;
index 12b129ebb86e3997e6c26cd5bdbb409dc324f477..e2194aa1a5c50152b094b074b3cccceb035cab9d 100644 (file)
@@ -140,7 +140,7 @@ bmroota_ptr_offset(
        ASSERT(XFS_DFORK_Q(dip) && (char *)block == XFS_DFORK_APTR(dip));
        ASSERT(be16_to_cpu(block->bb_level) > 0);
        pp = XFS_BMDR_PTR_ADDR(block, idx,
-               xfs_bmdr_maxrecs(mp, XFS_DFORK_ASIZE(dip, mp), 0));
+               xfs_bmdr_maxrecs(XFS_DFORK_ASIZE(dip, mp), 0));
        return bitize((int)((char *)pp - (char *)block));
 }
 
@@ -235,7 +235,7 @@ bmrootd_ptr_offset(
        block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff));
        ASSERT(be16_to_cpu(block->bb_level) > 0);
        pp = XFS_BMDR_PTR_ADDR(block, idx,
-               xfs_bmdr_maxrecs(mp, XFS_DFORK_DSIZE(dip, mp), 0));
+               xfs_bmdr_maxrecs(XFS_DFORK_DSIZE(dip, mp), 0));
        return bitize((int)((char *)pp - (char *)block));
 }
 
index c103a5cdef2a1c19a712876672f6c13b374ecaa5..0e6762371cd55e5c0b00018b90915ba79efbab07 100644 (file)
@@ -1975,7 +1975,7 @@ process_block_dir_v2(
        int             v;
        int             x;
 
-       nex = blkmap_getn(blkmap, 0, mp->m_dirblkfsbs, &bmp);
+       nex = blkmap_getn(blkmap, 0, mp->m_dir_geo->fsbcount, &bmp);
        v = id->ilist || verbose;
        if (nex == 0) {
                if (!sflag || v)
@@ -1989,7 +1989,7 @@ process_block_dir_v2(
        if (nex > 1)
                make_bbmap(&bbmap, nex, bmp);
        set_cur(&typtab[TYP_DIR2], XFS_FSB_TO_DADDR(mp, bmp->startblock),
-               mp->m_dirblkfsbs * blkbb, DB_RING_IGN, nex > 1 ? &bbmap : NULL);
+               mp->m_dir_geo->fsbcount * blkbb, DB_RING_IGN, nex > 1 ? &bbmap : NULL);
        for (x = 0; !v && x < nex; x++) {
                for (b = bmp[x].startblock;
                     !v && b < bmp[x].startblock + bmp[x].blockcount;
@@ -2007,7 +2007,7 @@ process_block_dir_v2(
                return 0;
        }
        dir_hash_init();
-       parent = process_data_dir_v2(dot, dotdot, id, v, mp->m_dirdatablk,
+       parent = process_data_dir_v2(dot, dotdot, id, v, mp->m_dir_geo->datablk,
                NULL);
        dir_hash_check(id, v);
        dir_hash_done();
@@ -2138,7 +2138,7 @@ process_btinode(
                return;
        }
        if (be16_to_cpu(dib->bb_numrecs) >
-                       xfs_bmdr_maxrecs(mp, XFS_DFORK_SIZE(dip, mp, whichfork),
+                       xfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork),
                        be16_to_cpu(dib->bb_level) == 0)) {
                if (!sflag || id->ilist)
                        dbprintf(_("numrecs for ino %lld %s fork bmap root too "
@@ -2156,7 +2156,7 @@ process_btinode(
                *nex += be16_to_cpu(dib->bb_numrecs);
                return;
        } else {
-               pp = XFS_BMDR_PTR_ADDR(dib, 1, xfs_bmdr_maxrecs(mp,
+               pp = XFS_BMDR_PTR_ADDR(dib, 1, xfs_bmdr_maxrecs(
                                XFS_DFORK_SIZE(dip, mp, whichfork), 0));
                for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++)
                        scan_lbtree(be64_to_cpu(pp[i]), 
@@ -2224,15 +2224,15 @@ process_data_dir_v2(
                error++;
                return NULLFSINO;
        }
-       db = xfs_dir2_da_to_db(mp, dabno);
-       bf = xfs_dir3_data_bestfree_p(data);
-       ptr = (char *)xfs_dir3_data_unused_p(data);
+       db = xfs_dir2_da_to_db(mp->m_dir_geo, dabno);
+       bf = M_DIROPS(mp)->data_bestfree_p(data);
+       ptr = (char *)M_DIROPS(mp)->data_unused_p(data);
        if (be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC) {
-               btp = xfs_dir2_block_tail_p(mp, block);
+               btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
                lep = xfs_dir2_block_leaf_p(btp);
                endptr = (char *)lep;
                if (endptr <= ptr || endptr > (char *)btp) {
-                       endptr = (char *)data + mp->m_dirblksize;
+                       endptr = (char *)data + mp->m_dir_geo->blksize;
                        lep = NULL;
                        if (!sflag || v)
                                dbprintf(_("bad block directory tail for dir ino "
@@ -2241,7 +2241,7 @@ process_data_dir_v2(
                        error++;
                }
        } else
-               endptr = (char *)data + mp->m_dirblksize;
+               endptr = (char *)data + mp->m_dir_geo->blksize;
        bf_err = lastfree_err = tag_err = 0;
        count = lastfree = freeseen = 0;
        if (be16_to_cpu(bf[0].length) == 0) {
@@ -2310,7 +2310,7 @@ process_data_dir_v2(
                                        (int)((char *)dep - (char *)data));
                        error++;
                }
-               tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+               tagp = M_DIROPS(mp)->data_entry_tag_p(dep);
                if ((char *)tagp >= endptr) {
                        if (!sflag || v)
                                dbprintf(_("dir %lld block %d bad entry at %d\n"),
@@ -2320,12 +2320,12 @@ process_data_dir_v2(
                        break;
                }
                tag_err += be16_to_cpu(*tagp) != (char *)dep - (char *)data;
-               addr = xfs_dir2_db_off_to_dataptr(mp, db,
+               addr = xfs_dir2_db_off_to_dataptr(mp->m_dir_geo, db,
                        (char *)dep - (char *)data);
                xname.name = dep->name;
                xname.len = dep->namelen;
                dir_hash_add(mp->m_dirnameops->hashname(&xname), addr);
-               ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
                count++;
                lastfree = 0;
                lino = be64_to_cpu(dep->inumber);
@@ -2374,7 +2374,7 @@ process_data_dir_v2(
                }
        }
        if (be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC) {
-               endptr = (char *)data + mp->m_dirblksize;
+               endptr = (char *)data + mp->m_dir_geo->blksize;
                for (i = stale = 0; lep && i < be32_to_cpu(btp->count); i++) {
                        if ((char *)&lep[i] >= endptr) {
                                if (!sflag || v)
@@ -2447,7 +2447,7 @@ process_data_dir_v2_freefind(
        xfs_dir2_data_aoff_t    off;
 
        off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)data);
-       bf = xfs_dir3_data_bestfree_p(data);
+       bf = M_DIROPS(mp)->data_bestfree_p(data);
        if (be16_to_cpu(dup->length) <
                        be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
                return NULL;
@@ -2516,11 +2516,11 @@ process_dir_v2(
        if (size <= XFS_DFORK_DSIZE(dip, mp) &&
                                dip->di_format == XFS_DINODE_FMT_LOCAL)
                *parent = process_sf_dir_v2(dip, dot, dotdot, id);
-       else if (last == mp->m_dirblkfsbs &&
+       else if (last == mp->m_dir_geo->fsbcount &&
                        (dip->di_format == XFS_DINODE_FMT_EXTENTS ||
                        dip->di_format == XFS_DINODE_FMT_BTREE))
                *parent = process_block_dir_v2(blkmap, dot, dotdot, id);
-       else if (last >= mp->m_dirleafblk + mp->m_dirblkfsbs &&
+       else if (last >= mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount &&
                        (dip->di_format == XFS_DINODE_FMT_EXTENTS ||
                        dip->di_format == XFS_DINODE_FMT_BTREE))
                *parent = process_leaf_node_dir_v2(blkmap, dot, dotdot, id, size);
@@ -2925,14 +2925,14 @@ process_leaf_node_dir_v2(
        v2 = verbose || id->ilist;
        v = parent = 0;
        dbno = NULLFILEOFF;
-       freetab = malloc(FREETAB_SIZE(dirsize / mp->m_dirblksize));
-       freetab->naents = (int)(dirsize / mp->m_dirblksize);
+       freetab = malloc(FREETAB_SIZE(dirsize / mp->m_dir_geo->blksize));
+       freetab->naents = (int)(dirsize / mp->m_dir_geo->blksize);
        freetab->nents = 0;
        for (i = 0; i < freetab->naents; i++)
                freetab->ents[i] = NULLDATAOFF;
        dir_hash_init();
        while ((dbno = blkmap_next_off(blkmap, dbno, &t)) != NULLFILEOFF) {
-               nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp);
+               nex = blkmap_getn(blkmap, dbno, mp->m_dir_geo->fsbcount, &bmp);
                ASSERT(nex > 0);
                for (v = v2, x = 0; !v && x < nex; x++) {
                        for (b = bmp[x].startblock;
@@ -2948,7 +2948,7 @@ process_leaf_node_dir_v2(
                if (nex > 1)
                        make_bbmap(&bbmap, nex, bmp);
                set_cur(&typtab[TYP_DIR2], XFS_FSB_TO_DADDR(mp, bmp->startblock),
-                       mp->m_dirblkfsbs * blkbb, DB_RING_IGN,
+                       mp->m_dir_geo->fsbcount * blkbb, DB_RING_IGN,
                        nex > 1 ? &bbmap : NULL);
                free(bmp);
                if (iocur_top->data == NULL) {
@@ -2958,10 +2958,10 @@ process_leaf_node_dir_v2(
                                        (__uint32_t)dbno, id->ino);
                        error++;
                        pop_cur();
-                       dbno += mp->m_dirblkfsbs - 1;
+                       dbno += mp->m_dir_geo->fsbcount - 1;
                        continue;
                }
-               if (dbno < mp->m_dirleafblk) {
+               if (dbno < mp->m_dir_geo->leafblk) {
                        lino = process_data_dir_v2(dot, dotdot, id, v,
                                (xfs_dablk_t)dbno, &freetab);
                        if (lino) {
@@ -2974,7 +2974,7 @@ process_leaf_node_dir_v2(
                                } else
                                        parent = lino;
                        }
-               } else if (dbno < mp->m_dirfreeblk) {
+               } else if (dbno < mp->m_dir_geo->freeblk) {
                        process_leaf_node_dir_v2_int(id, v, (xfs_dablk_t)dbno,
                                freetab);
                } else {
@@ -2982,7 +2982,7 @@ process_leaf_node_dir_v2(
                                freetab);
                }
                pop_cur();
-               dbno += mp->m_dirblkfsbs - 1;
+               dbno += mp->m_dir_geo->fsbcount - 1;
        }
        dir_hash_check(id, v);
        dir_hash_done();
@@ -2991,7 +2991,7 @@ process_leaf_node_dir_v2(
                        if (!sflag || v)
                                dbprintf(_("missing free index for data block %d "
                                         "in dir ino %lld\n"),
-                                       xfs_dir2_db_to_da(mp, i), id->ino);
+                                       xfs_dir2_db_to_da(mp->m_dir_geo, i), id->ino);
                        error++;
                }
        }
@@ -3021,9 +3021,9 @@ process_leaf_node_dir_v2_free(
                error++;
                return;
        }
-       maxent = xfs_dir3_free_max_bests(mp);
-       if (be32_to_cpu(free->hdr.firstdb) != xfs_dir2_da_to_db(mp, 
-                                       dabno - mp->m_dirfreeblk) * maxent) {
+       maxent = M_DIROPS(mp)->free_max_bests(mp->m_dir_geo);
+       if (be32_to_cpu(free->hdr.firstdb) != xfs_dir2_da_to_db(mp->m_dir_geo
+                                       dabno - mp->m_dir_geo->freeblk) * maxent) {
                if (!sflag || v)
                        dbprintf(_("bad free block firstdb %d for dir ino %lld "
                                 "block %d\n"),
@@ -3103,15 +3103,15 @@ process_leaf_node_dir_v2_int(
                                        id->ino, dabno);
                        error++;
                }
-               if (dabno != mp->m_dirleafblk) {
+               if (dabno != mp->m_dir_geo->leafblk) {
                        if (!sflag || v)
                                dbprintf(_("single leaf block for dir ino %lld "
                                         "block %d should be at block %d\n"),
                                        id->ino, dabno,
-                                       (xfs_dablk_t)mp->m_dirleafblk);
+                                       (xfs_dablk_t)mp->m_dir_geo->leafblk);
                        error++;
                }
-               ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+               ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
                lbp = xfs_dir2_leaf_bests_p(ltp);
                for (i = 0; i < be32_to_cpu(ltp->bestcount); i++) {
                        if (freetab->nents <= i || freetab->ents[i] != 
@@ -3124,7 +3124,7 @@ process_leaf_node_dir_v2_int(
                                                        NULLDATAOFF :
                                                        freetab->ents[i],
                                                id->ino,
-                                               xfs_dir2_db_to_da(mp, i),
+                                               xfs_dir2_db_to_da(mp->m_dir_geo, i),
                                                be16_to_cpu(lbp[i]));
                        }
                        if (freetab->nents > i)
@@ -3137,7 +3137,7 @@ process_leaf_node_dir_v2_int(
                break;
        case XFS_DA_NODE_MAGIC:
                node = iocur_top->data;
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
+               M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
                if (nodehdr.level < 1 || nodehdr.level > XFS_DA_NODE_MAXDEPTH) {
                        if (!sflag || v)
                                dbprintf(_("bad node block level %d for dir ino "
@@ -3156,7 +3156,7 @@ process_leaf_node_dir_v2_int(
                error++;
                return;
        }
-       lep = xfs_dir3_leaf_ents_p(leaf);
+       lep = M_DIROPS(mp)->leaf_ents_p(leaf);
        for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
                if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR)
                        stale++;
@@ -3434,9 +3434,9 @@ process_sf_dir_v2(
                dbprintf(_("dir %lld entry . %lld\n"), id->ino, id->ino);
        (*dot)++;
        sfe = xfs_dir2_sf_firstentry(sf);
-       offset = xfs_dir3_data_first_offset(mp);
+       offset = M_DIROPS(mp)->data_first_offset;
        for (i = sf->count - 1, i8 = 0; i >= 0; i--) {
-               if ((__psint_t)sfe + xfs_dir3_sf_entsize(mp, sf, sfe->namelen) -
+               if ((__psint_t)sfe + M_DIROPS(mp)->sf_entsize(sf, sfe->namelen) -
                    (__psint_t)sf > be64_to_cpu(dip->di_size)) {
                        if (!sflag)
                                dbprintf(_("dir %llu bad size in entry at %d\n"),
@@ -3445,7 +3445,7 @@ process_sf_dir_v2(
                        error++;
                        break;
                }
-               lino = xfs_dir3_sfe_get_ino(mp, sf, sfe);
+               lino = M_DIROPS(mp)->sf_get_ino(sf, sfe);
                if (lino > XFS_DIR2_MAX_SHORT_INUM)
                        i8++;
                cid = find_inode(lino, 1);
@@ -3475,8 +3475,8 @@ process_sf_dir_v2(
                }
                offset =
                        xfs_dir2_sf_get_offset(sfe) +
-                       xfs_dir3_sf_entsize(mp, sf, sfe->namelen);
-               sfe = xfs_dir3_sf_nextentry(mp, sf, sfe);
+                       M_DIROPS(mp)->sf_entsize(sf, sfe->namelen);
+               sfe = M_DIROPS(mp)->sf_nextentry(sf, sfe);
        }
        if (i < 0 && (__psint_t)sfe - (__psint_t)sf != 
                                        be64_to_cpu(dip->di_size)) {
@@ -3487,12 +3487,12 @@ process_sf_dir_v2(
                error++;
        }
        if (offset + (sf->count + 2) * sizeof(xfs_dir2_leaf_entry_t) +
-           sizeof(xfs_dir2_block_tail_t) > mp->m_dirblksize) {
+           sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) {
                if (!sflag)
                        dbprintf(_("dir %llu offsets too high\n"), id->ino);
                error++;
        }
-       lino = xfs_dir2_sf_get_parent_ino(sf);
+       lino = M_DIROPS(mp)->sf_get_parent_ino(sf);
        if (lino > XFS_DIR2_MAX_SHORT_INUM)
                i8++;
        cid = find_inode(lino, 1);
@@ -4222,7 +4222,7 @@ scanfunc_ino(
                        set_cur(&typtab[TYP_INODE],
                                XFS_AGB_TO_DADDR(mp, seqno,
                                                 XFS_AGINO_TO_AGBNO(mp, agino)),
-                               (int)XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)),
+                               (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks),
                                DB_RING_IGN, NULL);
                        if (iocur_top->data == NULL) {
                                if (!sflag)
index d2423da9c72a6dcae456d6a1ff3432793514a9d4..18a54b6a1aeb02cbcfac36a4dea91587a1afa07f 100644 (file)
--- a/db/dir2.c
+++ b/db/dir2.c
@@ -203,7 +203,7 @@ __dir2_block_tail_offset(
 
        ASSERT(startoff == 0);
        ASSERT(idx == 0);
-       btp = xfs_dir2_block_tail_p(mp, block);
+       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
        return bitize((int)((char *)btp - (char *)block));
 }
 
@@ -223,7 +223,7 @@ __dir2_data_entries_count(
                        ptr += be16_to_cpu(dup->length);
                else {
                        dep = (xfs_dir2_data_entry_t *)ptr;
-                       ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+                       ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
                }
        }
        return i;
@@ -247,7 +247,7 @@ __dir2_data_entry_offset(
                        ptr += be16_to_cpu(dup->length);
                else {
                        dep = (xfs_dir2_data_entry_t *)ptr;
-                       ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+                       ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
                }
        }
        return ptr;
@@ -290,7 +290,7 @@ dir2_block_leaf_count(
        if (be32_to_cpu(block->magic) != XFS_DIR2_BLOCK_MAGIC &&
            be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC)
                return 0;
-       btp = xfs_dir2_block_tail_p(mp, block);
+       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
        return be32_to_cpu(btp->count);
 }
 
@@ -307,7 +307,7 @@ dir2_block_leaf_offset(
        ASSERT(startoff == 0);
        ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC ||
               be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC);
-       btp = xfs_dir2_block_tail_p(mp, block);
+       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
        lep = xfs_dir2_block_leaf_p(btp) + idx;
        return bitize((int)((char *)lep - (char *)block));
 }
@@ -360,9 +360,10 @@ dir2_block_u_count(
            be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC)
                return 0;
 
-       btp = xfs_dir2_block_tail_p(mp, block);
-       return __dir2_data_entries_count((char *)xfs_dir3_data_unused_p(block),
-                                        (char *)xfs_dir2_block_leaf_p(btp));
+       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
+       return __dir2_data_entries_count(
+                       (char *)M_DIROPS(mp)->data_unused_p(block),
+                       (char *)xfs_dir2_block_leaf_p(btp));
 }
 
 static int
@@ -378,9 +379,10 @@ dir2_block_u_offset(
        ASSERT(startoff == 0);
        ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC ||
               be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC);
-       btp = xfs_dir2_block_tail_p(mp, block);
-       ptr = __dir2_data_entry_offset((char *)xfs_dir3_data_unused_p(block),
-                                      (char *)xfs_dir2_block_leaf_p(btp), idx);
+       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
+       ptr = __dir2_data_entry_offset(
+                       (char *)M_DIROPS(mp)->data_unused_p(block),
+                       (char *)xfs_dir2_block_leaf_p(btp), idx);
        return bitize((int)(ptr - (char *)block));
 }
 
@@ -398,7 +400,7 @@ dir2_data_union_freetag_count(
        ASSERT(bitoffs(startoff) == 0);
        dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
        end = (char *)&dup->freetag + sizeof(dup->freetag);
-       return end <= (char *)obj + mp->m_dirblksize &&
+       return end <= (char *)obj + mp->m_dir_geo->blksize &&
               be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG;
 }
 
@@ -415,7 +417,7 @@ dir2_data_union_inumber_count(
        dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
        dep = (xfs_dir2_data_entry_t *)dup;
        end = (char *)&dep->inumber + sizeof(dep->inumber);
-       return end <= (char *)obj + mp->m_dirblksize &&
+       return end <= (char *)obj + mp->m_dir_geo->blksize &&
               be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG;
 }
 
@@ -430,7 +432,7 @@ dir2_data_union_length_count(
        ASSERT(bitoffs(startoff) == 0);
        dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
        end = (char *)&dup->length + sizeof(dup->length);
-       return end <= (char *)obj + mp->m_dirblksize &&
+       return end <= (char *)obj + mp->m_dir_geo->blksize &&
               be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG;
 }
 
@@ -447,11 +449,11 @@ dir2_data_union_name_count(
        dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
        dep = (xfs_dir2_data_entry_t *)dup;
        end = (char *)&dep->namelen + sizeof(dep->namelen);
-       if (end >= (char *)obj + mp->m_dirblksize ||
+       if (end >= (char *)obj + mp->m_dir_geo->blksize ||
            be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG)
                return 0;
        end = (char *)&dep->name[0] + dep->namelen;
-       return end <= (char *)obj + mp->m_dirblksize ? dep->namelen : 0;
+       return end <= (char *)obj + mp->m_dir_geo->blksize ? dep->namelen : 0;
 }
 
 static int
@@ -467,7 +469,7 @@ dir2_data_union_namelen_count(
        dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
        dep = (xfs_dir2_data_entry_t *)dup;
        end = (char *)&dep->namelen + sizeof(dep->namelen);
-       return end <= (char *)obj + mp->m_dirblksize &&
+       return end <= (char *)obj + mp->m_dir_geo->blksize &&
               be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG;
 }
 
@@ -485,21 +487,21 @@ dir2_data_union_tag_count(
        dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
        dep = (xfs_dir2_data_entry_t *)dup;
        end = (char *)&dup->freetag + sizeof(dup->freetag);
-       if (end > (char *)obj + mp->m_dirblksize)
+       if (end > (char *)obj + mp->m_dir_geo->blksize)
                return 0;
        if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
                end = (char *)&dup->length + sizeof(dup->length);
-               if (end > (char *)obj + mp->m_dirblksize)
+               if (end > (char *)obj + mp->m_dir_geo->blksize)
                        return 0;
                tagp = xfs_dir2_data_unused_tag_p(dup);
        } else {
                end = (char *)&dep->namelen + sizeof(dep->namelen);
-               if (end > (char *)obj + mp->m_dirblksize)
+               if (end > (char *)obj + mp->m_dir_geo->blksize)
                        return 0;
-               tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+               tagp = M_DIROPS(mp)->data_entry_tag_p(dep);
        }
        end = (char *)tagp + sizeof(*tagp);
-       return end <= (char *)obj + mp->m_dirblksize;
+       return end <= (char *)obj + mp->m_dir_geo->blksize;
 }
 
 static int
@@ -518,7 +520,7 @@ dir2_data_union_tag_offset(
                return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup) -
                                    (char *)dup));
        dep = (xfs_dir2_data_entry_t *)dup;
-       return bitize((int)((char *)xfs_dir3_data_entry_tag_p(mp, dep) -
+       return bitize((int)((char *)M_DIROPS(mp)->data_entry_tag_p(dep) -
                            (char *)dep));
 }
 
@@ -556,8 +558,9 @@ dir2_data_u_count(
            be32_to_cpu(data->magic) != XFS_DIR3_DATA_MAGIC)
                return 0;
 
-       return __dir2_data_entries_count((char *)xfs_dir3_data_unused_p(data),
-                                        (char *)data + mp->m_dirblksize);
+       return __dir2_data_entries_count(
+                               (char *)M_DIROPS(mp)->data_unused_p(data),
+                               (char *)data + mp->m_dir_geo->blksize);
 }
 
 static int
@@ -572,8 +575,9 @@ dir2_data_u_offset(
        ASSERT(startoff == 0);
        ASSERT(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC ||
               be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC);
-       ptr = __dir2_data_entry_offset((char *)xfs_dir3_data_unused_p(data),
-                                      (char *)data + mp->m_dirblksize, idx);
+       ptr = __dir2_data_entry_offset(
+                               (char *)M_DIROPS(mp)->data_unused_p(data),
+                               (char *)data + mp->m_dir_geo->blksize, idx);
        return bitize((int)(ptr - (char *)data));
 }
 
@@ -593,7 +597,7 @@ dir2_data_union_size(
                return bitize(be16_to_cpu(dup->length));
        else {
                dep = (xfs_dir2_data_entry_t *)dup;
-               return bitize(xfs_dir3_data_entsize(mp, dep->namelen));
+               return bitize(M_DIROPS(mp)->data_entsize(dep->namelen));
        }
 }
 
@@ -682,7 +686,7 @@ dir2_leaf_bests_count(
        if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC &&
            be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR3_LEAF1_MAGIC)
                return 0;
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
        return be32_to_cpu(ltp->bestcount);
 }
 
@@ -699,7 +703,7 @@ dir2_leaf_bests_offset(
        ASSERT(startoff == 0);
        ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||
               be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR3_LEAF1_MAGIC);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
        lbp = xfs_dir2_leaf_bests_p(ltp) + idx;
        return bitize((int)((char *)lbp - (char *)leaf));
 }
@@ -791,7 +795,7 @@ dir2_leaf_tail_offset(
        ASSERT(idx == 0);
        ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||
               be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR3_LEAF1_MAGIC);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
        return bitize((int)((char *)ltp - (char *)leaf));
 }
 
@@ -852,7 +856,7 @@ dir2_size(
        int     startoff,
        int     idx)
 {
-       return bitize(mp->m_dirblksize);
+       return bitize(mp->m_dir_geo->blksize);
 }
 
 /*
index 528564780758b7159cc3657b35b6dffd42869fa3..bbe60801439d13df79390068c24e43529b2646a3 100644 (file)
@@ -184,8 +184,8 @@ dir2_sf_entry_size(
        sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff));
        e = xfs_dir2_sf_firstentry(sf);
        for (i = 0; i < idx; i++)
-               e = xfs_dir3_sf_nextentry(mp, sf, e);
-       return bitize((int)xfs_dir3_sf_entsize(mp, sf, e->namelen));
+               e = M_DIROPS(mp)->sf_nextentry(sf, e);
+       return bitize((int)M_DIROPS(mp)->sf_entsize(sf, e->namelen));
 }
 
 /*ARGSUSED*/
@@ -229,7 +229,7 @@ dir2_sf_list_offset(
        sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff));
        e = xfs_dir2_sf_firstentry(sf);
        for (i = 0; i < idx; i++)
-               e = xfs_dir3_sf_nextentry(mp, sf, e);
+               e = M_DIROPS(mp)->sf_nextentry(sf, e);
        return bitize((int)((char *)e - (char *)sf));
 }
 
@@ -249,7 +249,7 @@ dir2sf_size(
        sf = (struct xfs_dir2_sf_hdr *)((char *)obj + byteize(startoff));
        e = xfs_dir2_sf_firstentry(sf);
        for (i = 0; i < sf->count; i++)
-               e = xfs_dir3_sf_nextentry(mp, sf, e);
+               e = M_DIROPS(mp)->sf_nextentry(sf, e);
        return bitize((int)((char *)e - (char *)sf));
 }
 
index d092663a573a71aa804efcdf7190d1c5951d9e91..437324109c1addbb6391d8659431f3a813b8df91 100644 (file)
@@ -148,7 +148,7 @@ fa_cfileoffd(
                dbprintf(_("null block number, cannot set new addr\n"));
                return;
        }
-       nex = nb = next == TYP_DIR2 ? mp->m_dirblkfsbs : 1;
+       nex = nb = next == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1;
        bmp = malloc(nb * sizeof(*bmp));
        bmap(bno, nb, XFS_DATA_FORK, &nex, bmp);
        if (nex == 0) {
@@ -180,7 +180,7 @@ fa_cfsblock(
                dbprintf(_("null block number, cannot set new addr\n"));
                return;
        }
-       nb = next == TYP_DIR2 ? mp->m_dirblkfsbs : 1;
+       nb = next == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1;
        ASSERT(typtab[next].typnm == next);
        set_cur(&typtab[next], XFS_FSB_TO_DADDR(mp, bno), nb * blkbb,
                DB_RING_ADD, NULL);
@@ -232,7 +232,7 @@ fa_dfiloffd(
                dbprintf(_("null block number, cannot set new addr\n"));
                return;
        }
-       nex = nb = next == TYP_DIR2 ? mp->m_dirblkfsbs : 1;
+       nex = nb = next == TYP_DIR2 ? mp->m_dir_geo->fsbcount : 1;
        bmp = malloc(nb * sizeof(*bmp));
        bmap(bno, nb, XFS_DATA_FORK, &nex, bmp);
        if (nex == 0) {
@@ -285,9 +285,9 @@ fa_dirblock(
                dbprintf(_("null directory block number, cannot set new addr\n"));
                return;
        }
-       nex = mp->m_dirblkfsbs;
+       nex = mp->m_dir_geo->fsbcount;
        bmp = malloc(nex * sizeof(*bmp));
-       bmap(bno, mp->m_dirblkfsbs, XFS_DATA_FORK, &nex, bmp);
+       bmap(bno, mp->m_dir_geo->fsbcount, XFS_DATA_FORK, &nex, bmp);
        if (nex == 0) {
                dbprintf(_("directory block is unmapped\n"));
                free(bmp);
@@ -298,7 +298,7 @@ fa_dirblock(
        if (nex > 1)
                make_bbmap(&bbmap, nex, bmp);
        set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno),
-               XFS_FSB_TO_BB(mp, mp->m_dirblkfsbs), DB_RING_ADD,
+               XFS_FSB_TO_BB(mp, mp->m_dir_geo->fsbcount), DB_RING_ADD,
                nex > 1 ? &bbmap : NULL);
        free(bmp);
 }
index 2eb33d87bb33de3beb72e14f84b1507d85724b40..ed401e83481d0d5255e19521eb2e493e95ff3afe 100644 (file)
--- a/db/frag.c
+++ b/db/frag.c
@@ -256,7 +256,7 @@ process_btinode(
                return;
        }
        pp = XFS_BMDR_PTR_ADDR(dib, 1,
-               xfs_bmdr_maxrecs(mp, XFS_DFORK_SIZE(dip, mp, whichfork), 0));
+               xfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0));
        for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++)
                scan_lbtree(be64_to_cpu(pp[i]), be16_to_cpu(dib->bb_level), 
                        scanfunc_bmap, extmapp,
@@ -484,7 +484,7 @@ scanfunc_ino(
                        set_cur(&typtab[TYP_INODE],
                                XFS_AGB_TO_DADDR(mp, seqno,
                                                 XFS_AGINO_TO_AGBNO(mp, agino)),
-                               XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)),
+                               XFS_FSB_TO_BB(mp, mp->m_ialloc_blks),
                                DB_RING_IGN, NULL);
                        if (iocur_top->data == NULL) {
                                dbprintf(_("can't read inode block %u/%u\n"),
index dfefbf5f876a16c5b4247c7d5eed6728550c05fd..fbae0bdcb33a000950d2272297b1786b0db7aa98 100644 (file)
@@ -559,7 +559,6 @@ inode_u_sfdir2_count(
        ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff));
        return dip->di_format == XFS_DINODE_FMT_LOCAL &&
               (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFDIR &&
-              xfs_sb_version_hasdirv2(&mp->m_sb) &&
               !xfs_sb_version_hasftype(&mp->m_sb);
 }
 
index 1d74f76fda952c1101bd9f885c16d82788f10f1a..7a7cf2e47593babae8faa478477ef13d45c02fa7 100644 (file)
@@ -1123,7 +1123,7 @@ process_sf_dir(
                        namelen = ino_dir_size - ((char *)&sfep->name[0] -
                                         (char *)sfp);
                } else if ((char *)sfep - (char *)sfp +
-                               xfs_dir3_sf_entsize(mp, sfp, sfep->namelen) >
+                               M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen) >
                                ino_dir_size) {
                        if (show_warnings)
                                print_warning("entry length in dir inode %llu "
@@ -1136,11 +1136,11 @@ process_sf_dir(
 
                if (obfuscate)
                        generate_obfuscated_name(
-                                        xfs_dir3_sfe_get_ino(mp, sfp, sfep),
+                                        M_DIROPS(mp)->sf_get_ino(sfp, sfep),
                                         namelen, &sfep->name[0]);
 
                sfep = (xfs_dir2_sf_entry_t *)((char *)sfep +
-                               xfs_dir3_sf_entsize(mp, sfp, namelen));
+                               M_DIROPS(mp)->sf_entsize(sfp, namelen));
        }
 
        /* zero stale data in rest of space in data fork, if any */
@@ -1301,7 +1301,7 @@ process_dir_data_block(
                xfs_dir2_leaf_entry_t   *blp;
                xfs_dir2_block_tail_t   *btp;
 
-               btp = xfs_dir2_block_tail_p(mp, datahdr);
+               btp = xfs_dir2_block_tail_p(mp->m_dir_geo, datahdr);
                blp = xfs_dir2_block_leaf_p(btp);
                if ((char *)blp > (char *)btp)
                        blp = (xfs_dir2_leaf_entry_t *)btp;
@@ -1312,7 +1312,7 @@ process_dir_data_block(
                else
                        wantmagic = XFS_DIR2_BLOCK_MAGIC;
        } else { /* leaf/node format */
-               end_of_data = mp->m_dirblkfsbs << mp->m_sb.sb_blocklog;
+               end_of_data = mp->m_dir_geo->fsbcount << mp->m_sb.sb_blocklog;
                if (xfs_sb_version_hascrc(&mp->m_sb))
                        wantmagic = XFS_DIR3_DATA_MAGIC;
                else
@@ -1327,9 +1327,9 @@ process_dir_data_block(
                return;
        }
 
-       dir_offset = xfs_dir3_data_entry_offset(datahdr);
+       dir_offset = M_DIROPS(mp)->data_entry_offset;
        ptr = block + dir_offset;
-       endptr = block + mp->m_dirblksize;
+       endptr = block + mp->m_dir_geo->blksize;
 
        while (ptr < endptr && dir_offset < end_of_data) {
                xfs_dir2_data_entry_t   *dep;
@@ -1372,7 +1372,7 @@ process_dir_data_block(
                }
 
                dep = (xfs_dir2_data_entry_t *)ptr;
-               length = xfs_dir3_data_entsize(mp, dep->namelen);
+               length = M_DIROPS(mp)->data_entsize(dep->namelen);
 
                if (dir_offset + length > end_of_data ||
                    ptr + length > endptr) {
@@ -1382,7 +1382,7 @@ process_dir_data_block(
                                        (long long)cur_ino);
                        return;
                }
-               if (be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) !=
+               if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) !=
                                dir_offset)
                        return;
 
@@ -1395,7 +1395,7 @@ process_dir_data_block(
                if (zero_stale_data) {
                        /* 1 byte for ftype; don't bother with conditional */
                        int zlen =
-                               (char *)xfs_dir3_data_entry_tag_p(mp, dep) -
+                               (char *)M_DIROPS(mp)->data_entry_tag_p(dep) -
                                (char *)&dep->name[dep->namelen] - 1;
                        if (zlen > 0) {
                                memset(&dep->name[dep->namelen] + 1, 0, zlen);
@@ -1445,7 +1445,7 @@ add_remote_vals(
                attr_data.remote_vals[attr_data.remote_val_count] = blockidx;
                attr_data.remote_val_count++;
                blockidx++;
-               length -= XFS_LBSIZE(mp);
+               length -= mp->m_sb.sb_blocksize;
        }
 
        if (attr_data.remote_val_count >= MAX_REMOTE_VALS) {
@@ -1509,7 +1509,7 @@ process_attr_block(
                if (!first_name || xfs_attr3_leaf_name(leaf, i) < first_name)
                        first_name = xfs_attr3_leaf_name(leaf, i);
 
-               if (be16_to_cpu(entry->nameidx) > XFS_LBSIZE(mp)) {
+               if (be16_to_cpu(entry->nameidx) > mp->m_sb.sb_blocksize) {
                        if (show_warnings)
                                print_warning(
                                "invalid attr nameidx in inode %llu",
@@ -1617,8 +1617,8 @@ process_single_fsb_objects(
                                struct xfs_da3_icnode_hdr hdr;
                                int used;
 
-                               xfs_da3_node_hdr_from_disk(&hdr, node);
-                               used = xfs_da3_node_hdr_size(node);
+                               M_DIROPS(mp)->node_hdr_from_disk(&hdr, node);
+                               used = M_DIROPS(mp)->node_hdr_size;
 
                                used += hdr.count
                                        * sizeof(struct xfs_da_node_entry);
@@ -1635,11 +1635,11 @@ process_single_fsb_objects(
                dp = iocur_top->data;
                switch (btype) {
                case TYP_DIR2:
-                       if (o >= mp->m_dirleafblk)
+                       if (o >= mp->m_dir_geo->leafblk)
                                break;
 
                        process_dir_data_block(dp, o,
-                                                last == mp->m_dirblkfsbs);
+                                        last == mp->m_dir_geo->fsbcount);
                        iocur_top->need_crc = 1;
                        break;
                case TYP_SYMLINK:
@@ -1694,8 +1694,8 @@ process_multi_fsb_objects(
        while (c > 0) {
                unsigned int    bm_len;
 
-               if (mfsb_length + c >= mp->m_dirblkfsbs) {
-                       bm_len = mp->m_dirblkfsbs - mfsb_length;
+               if (mfsb_length + c >= mp->m_dir_geo->fsbcount) {
+                       bm_len = mp->m_dir_geo->fsbcount - mfsb_length;
                        mfsb_length = 0;
                } else {
                        mfsb_length += c;
@@ -1722,13 +1722,13 @@ process_multi_fsb_objects(
                        }
 
                        if ((!obfuscate && !zero_stale_data) ||
-                            o >= mp->m_dirleafblk) {
+                            o >= mp->m_dir_geo->leafblk) {
                                ret = write_buf(iocur_top);
                                goto out_pop;
                        }
 
                        process_dir_data_block(iocur_top->data, o,
-                                              last == mp->m_dirblkfsbs);
+                                              last == mp->m_dir_geo->fsbcount);
                        iocur_top->need_crc = 1;
                        ret = write_buf(iocur_top);
 out_pop:
@@ -1822,7 +1822,7 @@ process_bmbt_reclist(
                }
 
                /* multi-extent blocks require special handling */
-               if (btype != TYP_DIR2 || mp->m_dirblkfsbs == 1) {
+               if (btype != TYP_DIR2 || mp->m_dir_geo->fsbcount == 1) {
                        error = process_single_fsb_objects(o, s, c, btype, last);
                } else {
                        error = process_multi_fsb_objects(o, s, c, btype, last);
@@ -1924,7 +1924,7 @@ process_btinode(
                                            nrecs, itype);
        }
 
-       maxrecs = xfs_bmdr_maxrecs(mp, XFS_DFORK_SIZE(dip, mp, whichfork), 0);
+       maxrecs = xfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0);
        if (nrecs > maxrecs) {
                if (show_warnings)
                        print_warning("invalid numrecs (%u) in inode %lld %s "
@@ -2133,7 +2133,7 @@ copy_inode_chunk(
 
        push_cur();
        set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno),
-                       XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)),
+                       XFS_FSB_TO_BB(mp, mp->m_ialloc_blks),
                        DB_RING_IGN, NULL);
        if (iocur_top->data == NULL) {
                print_warning("cannot read inode block %u/%u", agno, agbno);
index 59475f42d9013f9574fbb18cec87514f3f96e5d2..5629f28d5ece329420c4da1202cf9615801f70e9 100644 (file)
@@ -47,6 +47,9 @@
 #include <xfs/xfs_inum.h>
 #include <xfs/xfs_sb.h>
 #include <xfs/xfs_ag.h>
+#include <xfs/xfs_da_format.h>
+#include <xfs/xfs_da_btree.h>
+#include <xfs/xfs_dir2.h>
 #include <xfs/xfs_bmap_btree.h>
 #include <xfs/xfs_alloc_btree.h>
 #include <xfs/xfs_ialloc_btree.h>
@@ -199,8 +202,6 @@ typedef struct xfs_mount {
        uint                    m_flags;        /* global mount flags */
        uint                    m_qflags;       /* quota status flags */
        uint                    m_attroffset;   /* inode attribute offset */
-       uint                    m_dir_node_ents; /* #entries in a dir danode */
-       uint                    m_attr_node_ents; /* #entries in attr danode */
        int                     m_ialloc_inos;  /* inodes in inode allocation */
        int                     m_ialloc_blks;  /* blocks in inode allocation */
        int                     m_litino;       /* size of inode union area */
@@ -210,14 +211,13 @@ typedef struct xfs_mount {
        int                     m_dalign;       /* stripe unit */
        int                     m_swidth;       /* stripe width */
        int                     m_sinoalign;    /* stripe unit inode alignmnt */
-       int                     m_attr_magicpct;/* 37% of the blocksize */
-       int                     m_dir_magicpct; /* 37% of the dir blocksize */
        const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */
-       int                     m_dirblksize;   /* directory block sz--bytes */
-       int                     m_dirblkfsbs;   /* directory block sz--fsbs */
-       xfs_dablk_t             m_dirdatablk;   /* blockno of dir data v2 */
-       xfs_dablk_t             m_dirleafblk;   /* blockno of dir non-data v2 */
-       xfs_dablk_t             m_dirfreeblk;   /* blockno of dirfreeindex v2 */
+
+       struct xfs_da_geometry  *m_dir_geo;     /* directory block geometry */
+       struct xfs_da_geometry  *m_attr_geo;    /* attribute block geometry */
+       const struct xfs_dir_ops *m_dir_inode_ops; /* vector of dir inode ops */
+       const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
+#define M_DIROPS(mp)   ((mp)->m_dir_inode_ops)
 
        /*
         * anonymous struct to allow xfs_dquot_buf.c to compile.
@@ -274,13 +274,6 @@ extern xfs_mount_t *libxfs_mount (xfs_mount_t *, xfs_sb_t *,
 extern void    libxfs_umount (xfs_mount_t *);
 extern void    libxfs_rtmount_destroy (xfs_mount_t *);
 
-/*
- * xfs/xfs_da_format.h needs struct xfs_mount to be defined
- */
-#include <xfs/xfs_da_format.h>
-#include <xfs/xfs_da_btree.h>
-#include <xfs/xfs_dir2.h>
-
 /*
  * Simple I/O interface
  */
@@ -608,6 +601,7 @@ typedef struct xfs_inode {
        unsigned int            i_delayed_blks; /* count of delay alloc blks */
        xfs_icdinode_t          i_d;            /* most of ondisk inode */
        xfs_fsize_t             i_size;         /* in-memory size */
+       const struct xfs_dir_ops *d_ops;        /* directory ops vector */
 } xfs_inode_t;
 
 #define LIBXFS_ATTR_ROOT       0x0002  /* use attrs in root namespace */
@@ -743,7 +737,7 @@ int libxfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_extnum_t nexts, xfs_fsblock_t *firstblock,
                struct xfs_bmap_free *flist, int *done);
 void   libxfs_bmap_cancel(struct xfs_bmap_free *flist);
-int    libxfs_bmap_last_offset(struct xfs_trans *tp, struct xfs_inode *ip,
+int    libxfs_bmap_last_offset(struct xfs_inode *ip,
                xfs_fileoff_t *unused, int whichfork);
 
 /* xfs_dir2.h */
@@ -761,22 +755,27 @@ int       libxfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
                                xfs_fsblock_t *first,
                                struct xfs_bmap_free *flist, xfs_extlen_t tot);
 
-int    libxfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
-int    libxfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
+int    libxfs_dir2_isblock(struct xfs_da_args *args, int *r);
+int    libxfs_dir2_isleaf(struct xfs_da_args *args, int *r);
 int    libxfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
                                struct xfs_buf *bp);
-void   libxfs_dir2_data_freescan(struct xfs_mount *mp,
+
+void   libxfs_dir2_data_freescan(struct xfs_da_geometry *geo,
+               const struct xfs_dir_ops *ops,
                struct xfs_dir2_data_hdr *hdr, int *loghead);
-void   libxfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp,
-               struct xfs_dir2_data_entry *dep);
-void   libxfs_dir2_data_log_header(struct xfs_trans *tp,
+void   libxfs_dir2_data_log_entry(struct xfs_da_args *args,
+               struct xfs_buf *bp, struct xfs_dir2_data_entry *dep);
+void   libxfs_dir2_data_log_header(struct xfs_da_args *args,
                struct xfs_buf *bp);
-void   libxfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp,
+void   libxfs_dir2_data_log_unused(struct xfs_da_args *args,
+               struct xfs_buf *bp, struct xfs_dir2_data_unused *dup);
+void   libxfs_dir2_data_make_free(struct xfs_da_args *args,
+               struct xfs_buf *bp, xfs_dir2_data_aoff_t offset,
+               xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
+void   libxfs_dir2_data_use_free(struct xfs_da_args *args,
+               struct xfs_buf *bp, struct xfs_dir2_data_unused *dup,
                xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len,
                int *needlogp, int *needscanp);
-void   libxfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
-               struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset,
-               xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
 
 /* xfs_da_btree.h */
 uint   libxfs_da_hashname(const __uint8_t *name_string, int name_length);
@@ -794,10 +793,9 @@ void       libxfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
 /* xfs_inode_fork.h */
 void   libxfs_idata_realloc(struct xfs_inode *, int, int);
 
-/* xfs_shared.h */
+/* xfs_symlink_remote.h */
 int    libxfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
-bool   libxfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino,
-                             uint32_t offset, uint32_t size,
+bool   libxfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset, uint32_t size,
                              struct xfs_buf *bp);
 
 /* xfs_bit.h */
@@ -819,7 +817,19 @@ int libxfs_attr_remove(struct xfs_inode *, const unsigned char *, int);
 xfs_bmbt_rec_host_t *xfs_bmap_search_extents(xfs_inode_t *, xfs_fileoff_t,
                                int, int *, xfs_extnum_t *, xfs_bmbt_irec_t *,
                                xfs_bmbt_irec_t *);
-void libxfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
+void libxfs_bmbt_get_all(struct xfs_bmbt_rec_host *r, struct xfs_bmbt_irec *s);
+
+static inline void
+libxfs_bmbt_disk_get_all(
+       struct xfs_bmbt_rec     *rp,
+       struct xfs_bmbt_irec    *irec)
+{
+       struct xfs_bmbt_rec_host hrec;
+
+       hrec.l0 = be64_to_cpu(rp->l0);
+       hrec.l1 = be64_to_cpu(rp->l1);
+       libxfs_bmbt_get_all(&hrec, irec);
+}
 
 void libxfs_dinode_from_disk(struct xfs_icdinode *,
                             struct xfs_dinode *);
index 253165867298739f564f67475f726f823ff04a73..6e247a99f5dbce65c0b97f0261209f52e75951b7 100644 (file)
@@ -160,7 +160,9 @@ typedef struct xfs_agi {
         * still being referenced.
         */
        __be32          agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
-
+       /*
+        * This marks the end of logging region 1 and start of logging region 2.
+        */
        uuid_t          agi_uuid;       /* uuid of filesystem */
        __be32          agi_crc;        /* crc of agi sector */
        __be32          agi_pad32;
index 3ec5ec0b86789004428591b824d982a16262a829..fcfa1814b9bcc3353411f03c3878470d31f382e8 100644 (file)
@@ -56,7 +56,7 @@ int   xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
 
 
 /*
- * Internal routines when attribute fork size == XFS_LBSIZE(mp).
+ * Internal routines when attribute fork size == mp->m_sb.sb_blocksize 
  */
 int    xfs_attr3_leaf_to_node(struct xfs_da_args *args);
 int    xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
@@ -96,8 +96,7 @@ int   xfs_attr3_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
 xfs_dahash_t   xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count);
 int    xfs_attr_leaf_order(struct xfs_buf *leaf1_bp,
                                   struct xfs_buf *leaf2_bp);
-int    xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize,
-                                       int *local);
+int    xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local);
 int    xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
                        xfs_dablk_t bno, xfs_daddr_t mappedbno,
                        struct xfs_buf **bpp);
index f1e3c907044db190f9dccd1f6dce7453f9932495..e1649c0d3e02f0f4da1ce1f8476008d53c7a8a3f 100644 (file)
@@ -66,8 +66,11 @@ static inline int xfs_lowbit64(__uint64_t v)
                n = ffs(w);
        } else {        /* upper bits */
                w = (__uint32_t)(v >> 32);
-               if (w && (n = ffs(w)))
-               n += 32;
+               if (w) {
+                       n = ffs(w);
+                       if (n)
+                               n += 32;
+               }
        }
        return n - 1;
 }
index 33b41f35122574e0b1cf7ad7a2a9ae23ecfadddb..b879ca56a64ccfab5b2a42502a5b50f68b85f1df 100644 (file)
@@ -77,7 +77,6 @@ typedef       struct xfs_bmap_free
  * from written to unwritten, otherwise convert from unwritten to written.
  */
 #define XFS_BMAPI_CONVERT      0x040
-#define XFS_BMAPI_STACK_SWITCH 0x080
 
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
@@ -86,8 +85,7 @@ typedef       struct xfs_bmap_free
        { XFS_BMAPI_PREALLOC,   "PREALLOC" }, \
        { XFS_BMAPI_IGSTATE,    "IGSTATE" }, \
        { XFS_BMAPI_CONTIG,     "CONTIG" }, \
-       { XFS_BMAPI_CONVERT,    "CONVERT" }, \
-       { XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" }
+       { XFS_BMAPI_CONVERT,    "CONVERT" }
 
 
 static inline int xfs_bmapi_aflag(int w)
@@ -127,6 +125,16 @@ static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
        { BMAP_RIGHT_FILLING,   "RF" }, \
        { BMAP_ATTRFORK,        "ATTR" }
 
+
+/*
+ * This macro is used to determine how many extents will be shifted
+ * in one write transaction. We could require two splits,
+ * an extent move on the first and an extent merge on the second,
+ * So it is proper that one extent is shifted inside write transaction
+ * at a time.
+ */
+#define XFS_BMAP_MAX_SHIFT_EXTENTS     1
+
 #ifdef DEBUG
 void   xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
                int whichfork, unsigned long caller_ip);
@@ -146,8 +154,8 @@ int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
 int    xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_fileoff_t *last_block, int whichfork);
-int    xfs_bmap_last_offset(struct xfs_trans *tp, struct xfs_inode *ip,
-               xfs_fileoff_t *unused, int whichfork);
+int    xfs_bmap_last_offset(struct xfs_inode *ip, xfs_fileoff_t *unused,
+               int whichfork);
 int    xfs_bmap_one_block(struct xfs_inode *ip, int whichfork);
 int    xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip,
                int whichfork);
@@ -169,5 +177,10 @@ int        xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
 int    xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
                xfs_extnum_t num);
 uint   xfs_default_attroffset(struct xfs_inode *ip);
+int    xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
+               int *done, xfs_fileoff_t start_fsb,
+               xfs_fileoff_t offset_shift_fsb, xfs_extnum_t *current_ext,
+               xfs_fsblock_t *firstblock, struct xfs_bmap_free *flist,
+               int num_exts);
 
 #endif /* __XFS_BMAP_H__ */
index 6e42e1e50b89394e2c0a0a003c339ac03d127445..819a8a4dee952d4648ee6333a7c61ea7dff6e78f 100644 (file)
@@ -130,7 +130,7 @@ extern void xfs_bmbt_to_bmdr(struct xfs_mount *, struct xfs_btree_block *, int,
                        xfs_bmdr_block_t *, int);
 
 extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level);
-extern int xfs_bmdr_maxrecs(struct xfs_mount *, int blocklen, int leaf);
+extern int xfs_bmdr_maxrecs(int blocklen, int leaf);
 extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf);
 
 extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip,
index 2590d404153f750ad6f8709fb035595c4f6c27ac..a04b69422f676c990dafa22da49288b1db279071 100644 (file)
@@ -26,6 +26,31 @@ struct xfs_trans;
 
 extern kmem_zone_t     *xfs_btree_cur_zone;
 
+/*
+ * Generic key, ptr and record wrapper structures.
+ *
+ * These are disk format structures, and are converted where necessary
+ * by the btree specific code that needs to interpret them.
+ */
+union xfs_btree_ptr {
+       __be32                  s;      /* short form ptr */
+       __be64                  l;      /* long form ptr */
+};
+
+union xfs_btree_key {
+       xfs_bmbt_key_t          bmbt;
+       xfs_bmdr_key_t          bmbr;   /* bmbt root block */
+       xfs_alloc_key_t         alloc;
+       xfs_inobt_key_t         inobt;
+};
+
+union xfs_btree_rec {
+       xfs_bmbt_rec_t          bmbt;
+       xfs_bmdr_rec_t          bmbr;   /* bmbt root block */
+       xfs_alloc_rec_t         alloc;
+       xfs_inobt_rec_t         inobt;
+};
+
 /*
  * This nonsense is to make -wlint happy.
  */
@@ -107,7 +132,7 @@ struct xfs_btree_ops {
        int     (*alloc_block)(struct xfs_btree_cur *cur,
                               union xfs_btree_ptr *start_bno,
                               union xfs_btree_ptr *new_bno,
-                              int length, int *stat);
+                              int *stat);
        int     (*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp);
 
        /* update last record information */
@@ -150,25 +175,6 @@ struct xfs_btree_ops {
                                union xfs_btree_rec *r1,
                                union xfs_btree_rec *r2);
 #endif
-
-       /* btree tracing */
-#ifdef XFS_BTREE_TRACE
-       void            (*trace_enter)(struct xfs_btree_cur *, const char *,
-                                      char *, int, int, __psunsigned_t,
-                                      __psunsigned_t, __psunsigned_t,
-                                      __psunsigned_t, __psunsigned_t,
-                                      __psunsigned_t, __psunsigned_t,
-                                      __psunsigned_t, __psunsigned_t,
-                                      __psunsigned_t, __psunsigned_t);
-       void            (*trace_cursor)(struct xfs_btree_cur *, __uint32_t *,
-                                       __uint64_t *, __uint64_t *);
-       void            (*trace_key)(struct xfs_btree_cur *,
-                                    union xfs_btree_key *, __uint64_t *,
-                                    __uint64_t *);
-       void            (*trace_record)(struct xfs_btree_cur *,
-                                       union xfs_btree_rec *, __uint64_t *,
-                                       __uint64_t *, __uint64_t *);
-#endif
 };
 
 /*
@@ -440,4 +446,23 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
        (XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
                XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks)
 
+/*
+ * Trace hooks.  Currently not implemented as they need to be ported
+ * over to the generic tracing functionality, which is some effort.
+ *
+ * i,j = integer (32 bit)
+ * b = btree block buffer (xfs_buf_t)
+ * p = btree ptr
+ * r = btree record
+ * k = btree key
+ */
+#define        XFS_BTREE_TRACE_ARGBI(c, b, i)
+#define        XFS_BTREE_TRACE_ARGBII(c, b, i, j)
+#define        XFS_BTREE_TRACE_ARGI(c, i)
+#define        XFS_BTREE_TRACE_ARGIPK(c, i, p, s)
+#define        XFS_BTREE_TRACE_ARGIPR(c, i, p, r)
+#define        XFS_BTREE_TRACE_ARGIK(c, i, k)
+#define XFS_BTREE_TRACE_ARGR(c, r)
+#define        XFS_BTREE_TRACE_CURSOR(c, t)
+
 #endif /* __XFS_BTREE_H__ */
index e492dcadd0322dc00c4c156b4556811bef200890..6e153e399a7759ea5d73270c7e63645221f7026b 100644 (file)
@@ -23,6 +23,24 @@ struct xfs_bmap_free;
 struct xfs_inode;
 struct xfs_trans;
 struct zone;
+struct xfs_dir_ops;
+
+/*
+ * Directory/attribute geometry information. There will be one of these for each
+ * data fork type, and it will be passed around via the xfs_da_args. Global
+ * structures will be attached to the xfs_mount.
+ */
+struct xfs_da_geometry {
+       int             blksize;        /* da block size in bytes */
+       int             fsbcount;       /* da block size in filesystem blocks */
+       uint8_t         fsblog;         /* log2 of _filesystem_ block size */
+       uint8_t         blklog;         /* log2 of da block size */
+       uint            node_ents;      /* # of entries in a danode */
+       int             magicpct;       /* 37% of block size in bytes */
+       xfs_dablk_t     datablk;        /* blockno of dir data v2 */
+       xfs_dablk_t     leafblk;        /* blockno of leaf data v2 */
+       xfs_dablk_t     freeblk;        /* blockno of free data v2 */
+};
 
 /*========================================================================
  * Btree searching and modification structure definitions.
@@ -41,6 +59,7 @@ enum xfs_dacmp {
  * Structure to ease passing around component names.
  */
 typedef struct xfs_da_args {
+       struct xfs_da_geometry *geo;    /* da block geometry */
        const __uint8_t *name;          /* string (maybe not NULL terminated) */
        int             namelen;        /* length of string (maybe no NULL) */
        __uint8_t       filetype;       /* filetype of inode for directories */
@@ -59,10 +78,12 @@ typedef struct xfs_da_args {
        int             index;          /* index of attr of interest in blk */
        xfs_dablk_t     rmtblkno;       /* remote attr value starting blkno */
        int             rmtblkcnt;      /* remote attr value block count */
+       int             rmtvaluelen;    /* remote attr value length in bytes */
        xfs_dablk_t     blkno2;         /* blkno of 2nd attr leaf of interest */
        int             index2;         /* index of 2nd attr in blk */
        xfs_dablk_t     rmtblkno2;      /* remote attr value starting blkno */
        int             rmtblkcnt2;     /* remote attr value block count */
+       int             rmtvaluelen2;   /* remote attr value length in bytes */
        int             op_flags;       /* operation flags */
        enum xfs_dacmp  cmpresult;      /* name compare result for lookups */
 } xfs_da_args_t;
@@ -107,8 +128,6 @@ typedef struct xfs_da_state_path {
 typedef struct xfs_da_state {
        xfs_da_args_t           *args;          /* filename arguments */
        struct xfs_mount        *mp;            /* filesystem mount point */
-       unsigned int            blocksize;      /* logical block size */
-       unsigned int            node_ents;      /* how many entries in danode */
        xfs_da_state_path_t     path;           /* search/split paths */
        xfs_da_state_path_t     altpath;        /* alternate path for join */
        unsigned char           inleaf;         /* insert into 1->lf, 0->splf */
@@ -182,9 +201,9 @@ int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp,
                               xfs_dablk_t bno, xfs_daddr_t mappedbno,
                               struct xfs_buf **bpp, int whichfork,
                               const struct xfs_buf_ops *ops);
-xfs_daddr_t    xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
-                               xfs_dablk_t bno, xfs_daddr_t mapped_bno,
-                               int whichfork, const struct xfs_buf_ops *ops);
+xfs_daddr_t    xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno,
+                               xfs_daddr_t mapped_bno, int whichfork,
+                               const struct xfs_buf_ops *ops);
 int    xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
                                          struct xfs_buf *dead_buf);
 
index 11f142078e12985622f66bfde1562be015531398..0a49b02863724204450fbce07f9df2806b34af76 100644 (file)
 #ifndef __XFS_DA_FORMAT_H__
 #define __XFS_DA_FORMAT_H__
 
-/*========================================================================
- * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
- *========================================================================*/
-
 /*
  * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
  *
@@ -122,43 +118,6 @@ struct xfs_da3_icnode_hdr {
        __uint16_t      level;
 };
 
-extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
-                                      struct xfs_da_intnode *from);
-extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
-                                    struct xfs_da3_icnode_hdr *from);
-
-static inline int
-__xfs_da3_node_hdr_size(bool v3)
-{
-       if (v3)
-               return sizeof(struct xfs_da3_node_hdr);
-       return sizeof(struct xfs_da_node_hdr);
-}
-static inline int
-xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
-{
-       bool    v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC);
-
-       return __xfs_da3_node_hdr_size(v3);
-}
-
-static inline struct xfs_da_node_entry *
-xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
-{
-       if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
-               struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
-               return dap3->__btree;
-       }
-       return dap->__btree;
-}
-
-extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
-                                     struct xfs_da_intnode *from);
-extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
-                                   struct xfs_da3_icnode_hdr *from);
-
-#define        XFS_LBSIZE(mp)  (mp)->m_sb.sb_blocksize
-
 /*
  * Directory version 2.
  *
@@ -329,79 +288,6 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
                ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count));
 }
 
-static inline int
-xfs_dir3_sf_entsize(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_hdr  *hdr,
-       int                     len)
-{
-       int count = sizeof(struct xfs_dir2_sf_entry);   /* namelen + offset */
-
-       count += len;                                   /* name */
-       count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
-                               sizeof(xfs_dir2_ino4_t); /* ino # */
-       if (xfs_sb_version_hasftype(&mp->m_sb))
-               count += sizeof(__uint8_t);             /* file type */
-       return count;
-}
-
-static inline struct xfs_dir2_sf_entry *
-xfs_dir3_sf_nextentry(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_hdr  *hdr,
-       struct xfs_dir2_sf_entry *sfep)
-{
-       return (struct xfs_dir2_sf_entry *)
-               ((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen));
-}
-
-/*
- * in dir3 shortform directories, the file type field is stored at a variable
- * offset after the inode number. Because it's only a single byte, endian
- * conversion is not necessary.
- */
-static inline __uint8_t *
-xfs_dir3_sfe_ftypep(
-       struct xfs_dir2_sf_hdr  *hdr,
-       struct xfs_dir2_sf_entry *sfep)
-{
-       return (__uint8_t *)&sfep->name[sfep->namelen];
-}
-
-static inline __uint8_t
-xfs_dir3_sfe_get_ftype(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_hdr  *hdr,
-       struct xfs_dir2_sf_entry *sfep)
-{
-       __uint8_t       *ftp;
-
-       if (!xfs_sb_version_hasftype(&mp->m_sb))
-               return XFS_DIR3_FT_UNKNOWN;
-
-       ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
-       if (*ftp >= XFS_DIR3_FT_MAX)
-               return XFS_DIR3_FT_UNKNOWN;
-       return *ftp;
-}
-
-static inline void
-xfs_dir3_sfe_put_ftype(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_hdr  *hdr,
-       struct xfs_dir2_sf_entry *sfep,
-       __uint8_t               ftype)
-{
-       __uint8_t       *ftp;
-
-       ASSERT(ftype < XFS_DIR3_FT_MAX);
-
-       if (!xfs_sb_version_hasftype(&mp->m_sb))
-               return;
-       ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
-       *ftp = ftype;
-}
-
 /*
  * Data block structures.
  *
@@ -438,8 +324,6 @@ xfs_dir3_sfe_put_ftype(
 #define        XFS_DIR2_SPACE_SIZE     (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
 #define        XFS_DIR2_DATA_SPACE     0
 #define        XFS_DIR2_DATA_OFFSET    (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
-#define        XFS_DIR2_DATA_FIRSTDB(mp)       \
-       xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
 
 /*
  * Describe a free area in the data block.
@@ -485,17 +369,6 @@ struct xfs_dir3_data_hdr {
 
 #define XFS_DIR3_DATA_CRC_OFF  offsetof(struct xfs_dir3_data_hdr, hdr.crc)
 
-static inline struct xfs_dir2_data_free *
-xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
-{
-       if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
-           hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
-               struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
-               return hdr3->best_free;
-       }
-       return hdr->bestfree;
-}
-
 /*
  * Active entry in a data block.
  *
@@ -528,71 +401,6 @@ typedef struct xfs_dir2_data_unused {
        __be16                  tag;            /* starting offset of us */
 } xfs_dir2_data_unused_t;
 
-/*
- * Size of a data entry.
- */
-static inline int
-__xfs_dir3_data_entsize(
-       bool    ftype,
-       int     n)
-{
-       int     size = offsetof(struct xfs_dir2_data_entry, name[0]);
-
-       size += n;
-       size += sizeof(xfs_dir2_data_off_t);
-       if (ftype)
-               size += sizeof(__uint8_t);
-       return roundup(size, XFS_DIR2_DATA_ALIGN);
-}
-static inline int
-xfs_dir3_data_entsize(
-       struct xfs_mount        *mp,
-       int                     n)
-{
-       bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
-       return __xfs_dir3_data_entsize(ftype, n);
-}
-
-static inline __uint8_t
-xfs_dir3_dirent_get_ftype(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_data_entry *dep)
-{
-       if (xfs_sb_version_hasftype(&mp->m_sb)) {
-               __uint8_t       type = dep->name[dep->namelen];
-
-               if (type < XFS_DIR3_FT_MAX)
-                       return type;
-
-       }
-       return XFS_DIR3_FT_UNKNOWN;
-}
-
-static inline void
-xfs_dir3_dirent_put_ftype(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_data_entry *dep,
-       __uint8_t               type)
-{
-       ASSERT(type < XFS_DIR3_FT_MAX);
-       ASSERT(dep->namelen != 0);
-
-       if (xfs_sb_version_hasftype(&mp->m_sb))
-               dep->name[dep->namelen] = type;
-}
-
-/*
- * Pointer to an entry's tag word.
- */
-static inline __be16 *
-xfs_dir3_data_entry_tag_p(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_data_entry *dep)
-{
-       return (__be16 *)((char *)dep +
-               xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
-}
-
 /*
  * Pointer to a freespace's tag word.
  */
@@ -603,93 +411,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
                        be16_to_cpu(dup->length) - sizeof(__be16));
 }
 
-static inline size_t
-xfs_dir3_data_hdr_size(bool dir3)
-{
-       if (dir3)
-               return sizeof(struct xfs_dir3_data_hdr);
-       return sizeof(struct xfs_dir2_data_hdr);
-}
-
-static inline size_t
-xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
-{
-       bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
-                   hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
-       return xfs_dir3_data_hdr_size(dir3);
-}
-
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
-{
-       return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
-}
-
-static inline struct xfs_dir2_data_unused *
-xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
-{
-       return (struct xfs_dir2_data_unused *)
-               ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
-}
-
-/*
- * Offsets of . and .. in data space (always block 0)
- *
- * XXX: there is scope for significant optimisation of the logic here. Right
- * now we are checking for "dir3 format" over and over again. Ideally we should
- * only do it once for each operation.
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dot_offset(struct xfs_mount *mp)
-{
-       return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
-}
-
-static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
-{
-       return xfs_dir3_data_dot_offset(mp) +
-               xfs_dir3_data_entsize(mp, 1);
-}
-
-static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_first_offset(struct xfs_mount *mp)
-{
-       return xfs_dir3_data_dotdot_offset(mp) +
-               xfs_dir3_data_entsize(mp, 2);
-}
-
-/*
- * location of . and .. in data space (always block 0)
- */
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dot_entry_p(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_data_hdr *hdr)
-{
-       return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_dot_offset(mp));
-}
-
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dotdot_entry_p(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_data_hdr *hdr)
-{
-       return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
-}
-
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_first_entry_p(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_data_hdr *hdr)
-{
-       return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_first_offset(mp));
-}
-
 /*
  * Leaf block structures.
  *
@@ -727,8 +448,6 @@ xfs_dir3_data_first_entry_p(
  */
 #define        XFS_DIR2_LEAF_SPACE     1
 #define        XFS_DIR2_LEAF_OFFSET    (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
-#define        XFS_DIR2_LEAF_FIRSTDB(mp)       \
-       xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
 
 /*
  * Leaf block header.
@@ -784,50 +503,6 @@ struct xfs_dir3_leaf {
 
 #define XFS_DIR3_LEAF_CRC_OFF  offsetof(struct xfs_dir3_leaf_hdr, info.crc)
 
-extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
-                                       struct xfs_dir2_leaf *from);
-
-static inline int
-xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
-{
-       if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
-           lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
-               return sizeof(struct xfs_dir3_leaf_hdr);
-       return sizeof(struct xfs_dir2_leaf_hdr);
-}
-
-static inline int
-xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
-{
-       return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
-               (uint)sizeof(struct xfs_dir2_leaf_entry);
-}
-
-/*
- * Get address of the bestcount field in the single-leaf block.
- */
-static inline struct xfs_dir2_leaf_entry *
-xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
-{
-       if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
-           lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
-               struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
-               return lp3->__ents;
-       }
-       return lp->__ents;
-}
-
-/*
- * Get address of the bestcount field in the single-leaf block.
- */
-static inline struct xfs_dir2_leaf_tail *
-xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
-{
-       return (struct xfs_dir2_leaf_tail *)
-               ((char *)lp + mp->m_dirblksize -
-                 sizeof(struct xfs_dir2_leaf_tail));
-}
-
 /*
  * Get address of the bests array in the single-leaf block.
  */
@@ -837,123 +512,6 @@ xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp)
        return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
 }
 
-/*
- * DB blocks here are logical directory block numbers, not filesystem blocks.
- */
-
-/*
- * Convert dataptr to byte in file space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
-       return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
-}
-
-/*
- * Convert byte in file space to dataptr.  It had better be aligned.
- */
-static inline xfs_dir2_dataptr_t
-xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-       return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
-}
-
-/*
- * Convert byte in space to (DB) block
- */
-static inline xfs_dir2_db_t
-xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-       return (xfs_dir2_db_t)
-               (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog));
-}
-
-/*
- * Convert dataptr to a block number
- */
-static inline xfs_dir2_db_t
-xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
-       return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
-}
-
-/*
- * Convert byte in space to offset in a block
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-       return (xfs_dir2_data_aoff_t)(by &
-               ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1));
-}
-
-/*
- * Convert dataptr to a byte offset in a block
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
-       return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
-}
-
-/*
- * Convert block and offset to byte in space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
-                       xfs_dir2_data_aoff_t o)
-{
-       return ((xfs_dir2_off_t)db <<
-               (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o;
-}
-
-/*
- * Convert block (DB) to block (dablk)
- */
-static inline xfs_dablk_t
-xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
-       return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog);
-}
-
-/*
- * Convert byte in space to (DA) block
- */
-static inline xfs_dablk_t
-xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-       return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
-}
-
-/*
- * Convert block and offset to dataptr
- */
-static inline xfs_dir2_dataptr_t
-xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
-                          xfs_dir2_data_aoff_t o)
-{
-       return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
-}
-
-/*
- * Convert block (dablk) to block (DB)
- */
-static inline xfs_dir2_db_t
-xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
-{
-       return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog);
-}
-
-/*
- * Convert block (dablk) to byte offset in space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
-{
-       return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
-}
-
 /*
  * Free space block defintions for the node format.
  */
@@ -963,8 +521,6 @@ xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
  */
 #define        XFS_DIR2_FREE_SPACE     2
 #define        XFS_DIR2_FREE_OFFSET    (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
-#define        XFS_DIR2_FREE_FIRSTDB(mp)       \
-       xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
 
 typedef        struct xfs_dir2_free_hdr {
        __be32                  magic;          /* XFS_DIR2_FREE_MAGIC */
@@ -1008,48 +564,6 @@ struct xfs_dir3_icfree_hdr {
 
 };
 
-void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
-                                struct xfs_dir2_free *from);
-
-static inline int
-xfs_dir3_free_hdr_size(struct xfs_mount *mp)
-{
-       if (xfs_sb_version_hascrc(&mp->m_sb))
-               return sizeof(struct xfs_dir3_free_hdr);
-       return sizeof(struct xfs_dir2_free_hdr);
-}
-
-static inline int
-xfs_dir3_free_max_bests(struct xfs_mount *mp)
-{
-       return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
-               sizeof(xfs_dir2_data_off_t);
-}
-
-static inline __be16 *
-xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
-{
-       return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
-}
-
-/*
- * Convert data space db to the corresponding free db.
- */
-static inline xfs_dir2_db_t
-xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
-       return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
-}
-
-/*
- * Convert data space db to the corresponding index in a free db.
- */
-static inline int
-xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
-       return db % xfs_dir3_free_max_bests(mp);
-}
-
 /*
  * Single block format.
  *
@@ -1081,16 +595,6 @@ typedef struct xfs_dir2_block_tail {
        __be32          stale;                  /* count of stale lf entries */
 } xfs_dir2_block_tail_t;
 
-/*
- * Pointer to the leaf header embedded in a data block (1-block format)
- */
-static inline struct xfs_dir2_block_tail *
-xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr)
-{
-       return ((struct xfs_dir2_block_tail *)
-               ((char *)hdr + mp->m_dirblksize)) - 1;
-}
-
 /*
  * Pointer to the leaf entries embedded in a data block (1-block format)
  */
@@ -1110,10 +614,6 @@ xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
  * of an attribute name may not be unique, we may have duplicate keys.  The
  * internal links in the Btree are logical block offsets into the file.
  *
- *========================================================================
- * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
- *========================================================================
- *
  * Struct leaf_entry's are packed from the top.  Name/values grow from the
  * bottom but are not packed.  The freemap contains run-length-encoded entries
  * for the free bytes after the leaf_entry's, but only the N largest such,
index 2d41c5f90d0310c7d4c5efbcf9afe54ec5211145..c9121b569e560e5423f9e69dddc061e87472b469 100644 (file)
@@ -31,11 +31,98 @@ struct xfs_dir2_data_unused;
 
 extern struct xfs_name xfs_name_dotdot;
 
+/*
+ * directory filetype conversion tables.
+ */
+#define S_SHIFT 12
+extern const unsigned char xfs_mode_to_ftype[];
+
+/*
+ * directory operations vector for encode/decode routines
+ */
+struct xfs_dir_ops {
+       int     (*sf_entsize)(struct xfs_dir2_sf_hdr *hdr, int len);
+       struct xfs_dir2_sf_entry *
+               (*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr,
+                               struct xfs_dir2_sf_entry *sfep);
+       __uint8_t (*sf_get_ftype)(struct xfs_dir2_sf_entry *sfep);
+       void    (*sf_put_ftype)(struct xfs_dir2_sf_entry *sfep,
+                               __uint8_t ftype);
+       xfs_ino_t (*sf_get_ino)(struct xfs_dir2_sf_hdr *hdr,
+                               struct xfs_dir2_sf_entry *sfep);
+       void    (*sf_put_ino)(struct xfs_dir2_sf_hdr *hdr,
+                             struct xfs_dir2_sf_entry *sfep,
+                             xfs_ino_t ino);
+       xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr);
+       void    (*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr,
+                                    xfs_ino_t ino);
+
+       int     (*data_entsize)(int len);
+       __uint8_t (*data_get_ftype)(struct xfs_dir2_data_entry *dep);
+       void    (*data_put_ftype)(struct xfs_dir2_data_entry *dep,
+                               __uint8_t ftype);
+       __be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep);
+       struct xfs_dir2_data_free *
+               (*data_bestfree_p)(struct xfs_dir2_data_hdr *hdr);
+
+       xfs_dir2_data_aoff_t data_dot_offset;
+       xfs_dir2_data_aoff_t data_dotdot_offset;
+       xfs_dir2_data_aoff_t data_first_offset;
+       size_t  data_entry_offset;
+
+       struct xfs_dir2_data_entry *
+               (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr);
+       struct xfs_dir2_data_entry *
+               (*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr);
+       struct xfs_dir2_data_entry *
+               (*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr);
+       struct xfs_dir2_data_entry *
+               (*data_entry_p)(struct xfs_dir2_data_hdr *hdr);
+       struct xfs_dir2_data_unused *
+               (*data_unused_p)(struct xfs_dir2_data_hdr *hdr);
+
+       int     leaf_hdr_size;
+       void    (*leaf_hdr_to_disk)(struct xfs_dir2_leaf *to,
+                                   struct xfs_dir3_icleaf_hdr *from);
+       void    (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to,
+                                     struct xfs_dir2_leaf *from);
+       int     (*leaf_max_ents)(struct xfs_da_geometry *geo);
+       struct xfs_dir2_leaf_entry *
+               (*leaf_ents_p)(struct xfs_dir2_leaf *lp);
+
+       int     node_hdr_size;
+       void    (*node_hdr_to_disk)(struct xfs_da_intnode *to,
+                                   struct xfs_da3_icnode_hdr *from);
+       void    (*node_hdr_from_disk)(struct xfs_da3_icnode_hdr *to,
+                                     struct xfs_da_intnode *from);
+       struct xfs_da_node_entry *
+               (*node_tree_p)(struct xfs_da_intnode *dap);
+
+       int     free_hdr_size;
+       void    (*free_hdr_to_disk)(struct xfs_dir2_free *to,
+                                   struct xfs_dir3_icfree_hdr *from);
+       void    (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to,
+                                     struct xfs_dir2_free *from);
+       int     (*free_max_bests)(struct xfs_da_geometry *geo);
+       __be16 * (*free_bests_p)(struct xfs_dir2_free *free);
+       xfs_dir2_db_t (*db_to_fdb)(struct xfs_da_geometry *geo,
+                                  xfs_dir2_db_t db);
+       int     (*db_to_fdindex)(struct xfs_da_geometry *geo,
+                                xfs_dir2_db_t db);
+};
+
+extern const struct xfs_dir_ops *
+       xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp);
+extern const struct xfs_dir_ops *
+       xfs_nondir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp);
+
 /*
  * Generic directory interface routines
  */
 extern void xfs_dir_startup(void);
-extern void xfs_dir_mount(struct xfs_mount *mp);
+extern int xfs_da_mount(struct xfs_mount *mp);
+extern void xfs_da_unmount(struct xfs_mount *mp);
+
 extern int xfs_dir_isempty(struct xfs_inode *dp);
 extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
                                struct xfs_inode *pdp);
@@ -57,9 +144,6 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
 extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
                                struct xfs_name *name, uint resblks);
 
-#define S_SHIFT 12
-extern const unsigned char xfs_mode_to_ftype[];
-
 /*
  * Direct call from the bmap code, bypassing the generic directory layer.
  */
@@ -68,37 +152,31 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
 /*
  * Interface routines used by userspace utilities
  */
-extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp);
-extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp,
-               xfs_ino_t ino);
-extern xfs_ino_t xfs_dir3_sfe_get_ino(struct xfs_mount *mp,
-               struct xfs_dir2_sf_hdr *sfp, struct xfs_dir2_sf_entry *sfep);
-extern void xfs_dir3_sfe_put_ino(struct xfs_mount *mp,
-               struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep,
-               xfs_ino_t ino);
-
-extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
-extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
+extern int xfs_dir2_isblock(struct xfs_da_args *args, int *r);
+extern int xfs_dir2_isleaf(struct xfs_da_args *args, int *r);
 extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
                                struct xfs_buf *bp);
 
-extern void xfs_dir2_data_freescan(struct xfs_mount *mp,
+extern void xfs_dir2_data_freescan(struct xfs_da_geometry *geo,
+               const struct xfs_dir_ops *ops,
                struct xfs_dir2_data_hdr *hdr, int *loghead);
-extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp,
-               struct xfs_dir2_data_entry *dep);
-extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
+extern void xfs_dir2_data_log_entry(struct xfs_da_args *args,
+               struct xfs_buf *bp, struct xfs_dir2_data_entry *dep);
+extern void xfs_dir2_data_log_header(struct xfs_da_args *args,
                struct xfs_buf *bp);
-extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp,
-               struct xfs_dir2_data_unused *dup);
-extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp,
+extern void xfs_dir2_data_log_unused(struct xfs_da_args *args,
+               struct xfs_buf *bp, struct xfs_dir2_data_unused *dup);
+extern void xfs_dir2_data_make_free(struct xfs_da_args *args,
+               struct xfs_buf *bp, xfs_dir2_data_aoff_t offset,
+               xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
+extern void xfs_dir2_data_use_free(struct xfs_da_args *args,
+               struct xfs_buf *bp, struct xfs_dir2_data_unused *dup,
                xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len,
                int *needlogp, int *needscanp);
-extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
-               struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset,
-               xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
 
 extern struct xfs_dir2_data_free *xfs_dir2_data_freefind(
-               struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_unused *dup);
+               struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
+               struct xfs_dir2_data_unused *dup);
 
 extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
 
@@ -108,4 +186,138 @@ extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;
 extern const struct xfs_buf_ops xfs_dir3_free_buf_ops;
 extern const struct xfs_buf_ops xfs_dir3_data_buf_ops;
 
+/*
+ * Directory offset/block conversion functions.
+ *
+ * DB blocks here are logical directory block numbers, not filesystem blocks.
+ */
+
+/*
+ * Convert dataptr to byte in file space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp)
+{
+       return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
+}
+
+/*
+ * Convert byte in file space to dataptr.  It had better be aligned.
+ */
+static inline xfs_dir2_dataptr_t
+xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by)
+{
+       return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
+}
+
+/*
+ * Convert byte in space to (DB) block
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_byte_to_db(struct xfs_da_geometry *geo, xfs_dir2_off_t by)
+{
+       return (xfs_dir2_db_t)(by >> geo->blklog);
+}
+
+/*
+ * Convert dataptr to a block number
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_dataptr_to_db(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp)
+{
+       return xfs_dir2_byte_to_db(geo, xfs_dir2_dataptr_to_byte(dp));
+}
+
+/*
+ * Convert byte in space to offset in a block
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_byte_to_off(struct xfs_da_geometry *geo, xfs_dir2_off_t by)
+{
+       return (xfs_dir2_data_aoff_t)(by & (geo->blksize - 1));
+}
+
+/*
+ * Convert dataptr to a byte offset in a block
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_dataptr_to_off(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp)
+{
+       return xfs_dir2_byte_to_off(geo, xfs_dir2_dataptr_to_byte(dp));
+}
+
+/*
+ * Convert block and offset to byte in space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_db_off_to_byte(struct xfs_da_geometry *geo, xfs_dir2_db_t db,
+                       xfs_dir2_data_aoff_t o)
+{
+       return ((xfs_dir2_off_t)db << geo->blklog) + o;
+}
+
+/*
+ * Convert block (DB) to block (dablk)
+ */
+static inline xfs_dablk_t
+xfs_dir2_db_to_da(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
+{
+       return (xfs_dablk_t)(db << (geo->blklog - geo->fsblog));
+}
+
+/*
+ * Convert byte in space to (DA) block
+ */
+static inline xfs_dablk_t
+xfs_dir2_byte_to_da(struct xfs_da_geometry *geo, xfs_dir2_off_t by)
+{
+       return xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, by));
+}
+
+/*
+ * Convert block and offset to dataptr
+ */
+static inline xfs_dir2_dataptr_t
+xfs_dir2_db_off_to_dataptr(struct xfs_da_geometry *geo, xfs_dir2_db_t db,
+                          xfs_dir2_data_aoff_t o)
+{
+       return xfs_dir2_byte_to_dataptr(xfs_dir2_db_off_to_byte(geo, db, o));
+}
+
+/*
+ * Convert block (dablk) to block (DB)
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_da_to_db(struct xfs_da_geometry *geo, xfs_dablk_t da)
+{
+       return (xfs_dir2_db_t)(da >> (geo->blklog - geo->fsblog));
+}
+
+/*
+ * Convert block (dablk) to byte offset in space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_da_to_byte(struct xfs_da_geometry *geo, xfs_dablk_t da)
+{
+       return xfs_dir2_db_off_to_byte(geo, xfs_dir2_da_to_db(geo, da), 0);
+}
+
+/*
+ * Directory tail pointer accessor functions. Based on block geometry.
+ */
+static inline struct xfs_dir2_block_tail *
+xfs_dir2_block_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_data_hdr *hdr)
+{
+       return ((struct xfs_dir2_block_tail *)
+               ((char *)hdr + geo->blksize)) - 1;
+}
+
+static inline struct xfs_dir2_leaf_tail *
+xfs_dir2_leaf_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_leaf *lp)
+{
+       return (struct xfs_dir2_leaf_tail *)
+               ((char *)lp + geo->blksize -
+                 sizeof(struct xfs_dir2_leaf_tail));
+}
+
 #endif /* __XFS_DIR2_H__ */
index 758052f6af6b43d5816b17f33c1f396516870cdf..34d85aca305801ea3b1e982bab49305099dac465 100644 (file)
@@ -425,30 +425,4 @@ struct xfs_btree_block {
 #define XFS_BTREE_LBLOCK_CRC_OFF \
        offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
 
-/*
- * Generic key, ptr and record wrapper structures.
- *
- * These are disk format structures, and are converted where necessary
- * by the btree specific code that needs to interpret them.
- */
-union xfs_btree_ptr {
-       __be32                  s;      /* short form ptr */
-       __be64                  l;      /* long form ptr */
-};
-
-union xfs_btree_key {
-       xfs_bmbt_key_t          bmbt;
-       xfs_bmdr_key_t          bmbr;   /* bmbt root block */
-       xfs_alloc_key_t         alloc;
-       xfs_inobt_key_t         inobt;
-};
-
-union xfs_btree_rec {
-       xfs_bmbt_rec_t          bmbt;
-       xfs_bmdr_rec_t          bmbr;   /* bmbt root block */
-       xfs_alloc_rec_t         alloc;
-       xfs_inobt_rec_t         inobt;
-};
-
-
 #endif /* __XFS_FORMAT_H__ */
index 59c40fc4551f9dd6b61414f4446f9ab8d5bddee7..d34703dbcb423b7fdbb52438b2525dd74417f1eb 100644 (file)
@@ -240,7 +240,6 @@ typedef struct xfs_fsop_resblks {
 #define XFS_FSOP_GEOM_FLAGS_FTYPE      0x10000 /* inode directory types */
 #define XFS_FSOP_GEOM_FLAGS_FINOBT     0x20000 /* free inode btree */
 
-
 /*
  * Minimum and maximum sizes need for growth checks.
  *
index c8ac0a4ba3e5224e4561f2c06898f681ed3f659b..95ad1c002d600916f983806cdb6a484712f0a84b 100644 (file)
@@ -25,17 +25,18 @@ struct xfs_mount;
 struct xfs_trans;
 struct xfs_btree_cur;
 
-/*
- * Allocation parameters for inode allocation.
- */
-#define        XFS_IALLOC_INODES(mp)   (mp)->m_ialloc_inos
-#define        XFS_IALLOC_BLOCKS(mp)   (mp)->m_ialloc_blks
-
-/*
- * Move inodes in clusters of this size.
- */
+/* Move inodes in clusters of this size */
 #define        XFS_INODE_BIG_CLUSTER_SIZE      8192
-#define        XFS_INODE_CLUSTER_SIZE(mp)      (mp)->m_inode_cluster_size
+
+/* Calculate and return the number of filesystem blocks per inode cluster */
+static inline int
+xfs_icluster_size_fsb(
+       struct xfs_mount        *mp)
+{
+       if (mp->m_sb.sb_blocksize >= mp->m_inode_cluster_size)
+               return 1;
+       return mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog;
+}
 
 /*
  * Make an inode pointer out of the buffer/offset.
index eb329a1ea8886a3d878489765bc5d13dbbf26068..7d3b1ed6dcbe934dcea8d7b92ccb3342f784bff6 100644 (file)
@@ -127,8 +127,7 @@ typedef struct xfs_ifork {
 
 int            xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *);
 void           xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
-                               struct xfs_inode_log_item *, int,
-                               struct xfs_buf *);
+                               struct xfs_inode_log_item *, int);
 void           xfs_idestroy_fork(struct xfs_inode *, int);
 void           xfs_idata_realloc(struct xfs_inode *, int, int);
 void           xfs_iroot_realloc(struct xfs_inode *, int, int);
index b3b2b1065c0f4db8a6c972880b2dc8601e189e03..137e20937077a0923d7095b02094172e4992ec55 100644 (file)
@@ -156,6 +156,6 @@ typedef __uint16_t  xfs_qwarncnt_t;
 
 extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq,
                       xfs_dqid_t id, uint type, uint flags, char *str);
-extern int xfs_calc_dquots_per_chunk(struct xfs_mount *mp, unsigned int nbblks);
+extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
 
 #endif /* __XFS_QUOTA_H__ */
index 950d1ea058b23653f3940f3a0fbdf259888d64df..c43c2d609a24bb38816b422d60b80ba06b18fcd4 100644 (file)
@@ -36,8 +36,6 @@ struct xfs_trans;
 #define        XFS_SB_VERSION_5        5               /* CRC enabled filesystem */
 #define        XFS_SB_VERSION_NUMBITS          0x000f
 #define        XFS_SB_VERSION_ALLFBITS         0xfff0
-#define        XFS_SB_VERSION_SASHFBITS        0xf000
-#define        XFS_SB_VERSION_REALFBITS        0x0ff0
 #define        XFS_SB_VERSION_ATTRBIT          0x0010
 #define        XFS_SB_VERSION_NLINKBIT         0x0020
 #define        XFS_SB_VERSION_QUOTABIT         0x0040
@@ -50,24 +48,15 @@ struct xfs_trans;
 #define        XFS_SB_VERSION_DIRV2BIT         0x2000
 #define        XFS_SB_VERSION_BORGBIT          0x4000  /* ASCII only case-insens. */
 #define        XFS_SB_VERSION_MOREBITSBIT      0x8000
-#define        XFS_SB_VERSION_OKSASHFBITS      \
-       (XFS_SB_VERSION_EXTFLGBIT | \
-        XFS_SB_VERSION_DIRV2BIT | \
-        XFS_SB_VERSION_BORGBIT)
-#define        XFS_SB_VERSION_OKREALFBITS      \
-       (XFS_SB_VERSION_ATTRBIT | \
-        XFS_SB_VERSION_NLINKBIT | \
-        XFS_SB_VERSION_QUOTABIT | \
-        XFS_SB_VERSION_ALIGNBIT | \
-        XFS_SB_VERSION_DALIGNBIT | \
-        XFS_SB_VERSION_SHAREDBIT | \
-        XFS_SB_VERSION_LOGV2BIT | \
-        XFS_SB_VERSION_SECTORBIT | \
-        XFS_SB_VERSION_MOREBITSBIT)
-#define        XFS_SB_VERSION_OKREALBITS       \
-       (XFS_SB_VERSION_NUMBITS | \
-        XFS_SB_VERSION_OKREALFBITS | \
-        XFS_SB_VERSION_OKSASHFBITS)
+
+/*
+ * Supported feature bit list is just all bits in the versionnum field because
+ * we've used them all up and understand them all. Except, of course, for the
+ * shared superblock bit, which nobody knows what it does and so is unsupported.
+ */
+#define        XFS_SB_VERSION_OKBITS           \
+       ((XFS_SB_VERSION_NUMBITS | XFS_SB_VERSION_ALLFBITS) & \
+               ~XFS_SB_VERSION_SHAREDBIT)
 
 /*
  * There are two words to hold XFS "feature" bits: the original
@@ -76,7 +65,6 @@ struct xfs_trans;
  *
  * These defines represent bits in sb_features2.
  */
-#define XFS_SB_VERSION2_REALFBITS      0x00ffffff      /* Mask: features */
 #define XFS_SB_VERSION2_RESERVED1BIT   0x00000001
 #define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002      /* Superblk counters */
 #define XFS_SB_VERSION2_RESERVED4BIT   0x00000004
@@ -86,16 +74,11 @@ struct xfs_trans;
 #define XFS_SB_VERSION2_CRCBIT         0x00000100      /* metadata CRCs */
 #define XFS_SB_VERSION2_FTYPE          0x00000200      /* inode type in dir */
 
-#define        XFS_SB_VERSION2_OKREALFBITS     \
+#define        XFS_SB_VERSION2_OKBITS          \
        (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
         XFS_SB_VERSION2_ATTR2BIT       | \
         XFS_SB_VERSION2_PROJID32BIT    | \
         XFS_SB_VERSION2_FTYPE)
-#define        XFS_SB_VERSION2_OKSASHFBITS     \
-       (0)
-#define XFS_SB_VERSION2_OKREALBITS     \
-       (XFS_SB_VERSION2_OKREALFBITS |  \
-        XFS_SB_VERSION2_OKSASHFBITS )
 
 /*
  * Superblock - in core version.  Must match the ondisk version below.
@@ -345,214 +328,140 @@ typedef enum {
 
 #define        XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS)
 
-static inline int xfs_sb_good_version(xfs_sb_t *sbp)
-{
-       /* We always support version 1-3 */
-       if (sbp->sb_versionnum >= XFS_SB_VERSION_1 &&
-           sbp->sb_versionnum <= XFS_SB_VERSION_3)
-               return 1;
-
-       /* We support version 4 if all feature bits are supported */
-       if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) {
-               if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) ||
-                   ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) &&
-                    (sbp->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
-                       return 0;
-
-               if (sbp->sb_shared_vn > XFS_SB_MAX_SHARED_VN)
-                       return 0;
-               return 1;
-       }
-       if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5)
-               return 1;
-
-       return 0;
-}
-
 /*
- * Detect a mismatched features2 field.  Older kernels read/wrote
- * this into the wrong slot, so to be safe we keep them in sync.
+ * The first XFS version we support is a v4 superblock with V2 directories.
  */
-static inline int xfs_sb_has_mismatched_features2(xfs_sb_t *sbp)
+static inline bool xfs_sb_good_v4_features(struct xfs_sb *sbp)
 {
-       return (sbp->sb_bad_features2 != sbp->sb_features2);
-}
+       if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT))
+               return false;
 
-static inline unsigned xfs_sb_version_tonew(unsigned v)
-{
-       if (v == XFS_SB_VERSION_1)
-               return XFS_SB_VERSION_4;
+       /* check for unknown features in the fs */
+       if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) ||
+           ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) &&
+            (sbp->sb_features2 & ~XFS_SB_VERSION2_OKBITS)))
+               return false;
 
-       if (v == XFS_SB_VERSION_2)
-               return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT;
-
-       return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT |
-               XFS_SB_VERSION_NLINKBIT;
+       return true;
 }
 
-static inline unsigned xfs_sb_version_toold(unsigned v)
+static inline bool xfs_sb_good_version(struct xfs_sb *sbp)
 {
-       if (v & (XFS_SB_VERSION_QUOTABIT | XFS_SB_VERSION_ALIGNBIT))
-               return 0;
-       if (v & XFS_SB_VERSION_NLINKBIT)
-               return XFS_SB_VERSION_3;
-       if (v & XFS_SB_VERSION_ATTRBIT)
-               return XFS_SB_VERSION_2;
-       return XFS_SB_VERSION_1;
-}
-
-static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp)
-{
-       return sbp->sb_versionnum == XFS_SB_VERSION_2 ||
-               sbp->sb_versionnum == XFS_SB_VERSION_3 ||
-               (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-                (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT));
+       if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5)
+               return true;
+       if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
+               return xfs_sb_good_v4_features(sbp);
+       return false;
 }
 
-static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)
+/*
+ * Detect a mismatched features2 field.  Older kernels read/wrote
+ * this into the wrong slot, so to be safe we keep them in sync.
+ */
+static inline bool xfs_sb_has_mismatched_features2(struct xfs_sb *sbp)
 {
-       if (sbp->sb_versionnum == XFS_SB_VERSION_1)
-               sbp->sb_versionnum = XFS_SB_VERSION_2;
-       else if (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4)
-               sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
-       else
-               sbp->sb_versionnum = XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT;
+       return sbp->sb_bad_features2 != sbp->sb_features2;
 }
 
-static inline int xfs_sb_version_hasnlink(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasattr(struct xfs_sb *sbp)
 {
-       return sbp->sb_versionnum == XFS_SB_VERSION_3 ||
-                (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-                 (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT));
+       return (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT);
 }
 
-static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)
+static inline void xfs_sb_version_addattr(struct xfs_sb *sbp)
 {
-       if (sbp->sb_versionnum <= XFS_SB_VERSION_2)
-               sbp->sb_versionnum = XFS_SB_VERSION_3;
-       else
-               sbp->sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
+       sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
 }
 
-static inline int xfs_sb_version_hasquota(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasquota(struct xfs_sb *sbp)
 {
-       return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT);
+       return (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT);
 }
 
-static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)
+static inline void xfs_sb_version_addquota(struct xfs_sb *sbp)
 {
-       if (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4)
-               sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT;
-       else
-               sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) |
-                                       XFS_SB_VERSION_QUOTABIT;
+       sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT;
 }
 
-static inline int xfs_sb_version_hasalign(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasalign(struct xfs_sb *sbp)
 {
-       return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
-              (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
+       return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
                (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT));
 }
 
-static inline int xfs_sb_version_hasdalign(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasdalign(struct xfs_sb *sbp)
 {
-       return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT);
+       return (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT);
 }
 
-static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_haslogv2(struct xfs_sb *sbp)
 {
-       return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT);
+       return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
+              (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT);
 }
 
-static inline int xfs_sb_version_hasdirv2(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasextflgbit(struct xfs_sb *sbp)
 {
-       return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
-              (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT));
+       return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
+              (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT);
 }
 
-static inline int xfs_sb_version_haslogv2(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hassector(struct xfs_sb *sbp)
 {
-       return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
-              (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT));
+       return (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
 }
 
-static inline int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasasciici(struct xfs_sb *sbp)
 {
-       return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
-              (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT));
+       return (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
 }
 
-static inline int xfs_sb_version_hassector(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasmorebits(struct xfs_sb *sbp)
 {
-       return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
-}
-
-static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp)
-{
-       return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
-}
-
-static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
-{
-       return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
-              (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-               (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT));
+       return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
+              (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT);
 }
 
 /*
  * sb_features2 bit version macros.
- *
- * For example, for a bit defined as XFS_SB_VERSION2_FUNBIT, has a macro:
- *
- * SB_VERSION_HASFUNBIT(xfs_sb_t *sbp)
- *     ((xfs_sb_version_hasmorebits(sbp) &&
- *      ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
  */
-
-static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_haslazysbcount(struct xfs_sb *sbp)
 {
        return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
               (xfs_sb_version_hasmorebits(sbp) &&
                (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT));
 }
 
-static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasattr2(struct xfs_sb *sbp)
 {
        return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
               (xfs_sb_version_hasmorebits(sbp) &&
                (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT));
 }
 
-static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
+static inline void xfs_sb_version_addattr2(struct xfs_sb *sbp)
 {
        sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
        sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
+       sbp->sb_bad_features2 |= XFS_SB_VERSION2_ATTR2BIT;
 }
 
-static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)
+static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp)
 {
        sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
+       sbp->sb_bad_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
        if (!sbp->sb_features2)
                sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
 }
 
-static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasprojid32bit(struct xfs_sb *sbp)
 {
        return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
               (xfs_sb_version_hasmorebits(sbp) &&
                (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT));
 }
 
-static inline void xfs_sb_version_addprojid32bit(xfs_sb_t *sbp)
+static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp)
 {
        sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
        sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
@@ -625,12 +534,12 @@ xfs_sb_has_incompat_log_feature(
 /*
  * V5 superblock specific feature checks
  */
-static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
+static inline int xfs_sb_version_hascrc(struct xfs_sb *sbp)
 {
        return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
 }
 
-static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp)
+static inline int xfs_sb_version_has_pquotino(struct xfs_sb *sbp)
 {
        return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
 }
index 63c94b1e91a7676bff726d59e22d1a1c47eaf98b..82404da2ca6747c010a4c666132ebede1c9c7f90 100644 (file)
@@ -104,7 +104,8 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops;
 #define        XFS_TRANS_SB_COUNT              41
 #define        XFS_TRANS_CHECKPOINT            42
 #define        XFS_TRANS_ICREATE               43
-#define        XFS_TRANS_TYPE_MAX              43
+#define        XFS_TRANS_CREATE_TMPFILE        44
+#define        XFS_TRANS_TYPE_MAX              44
 /* new transaction types need to be reflected in xfs_logprint(8) */
 
 #define XFS_TRANS_TYPES \
@@ -112,6 +113,7 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops;
        { XFS_TRANS_SETATTR_SIZE,       "SETATTR_SIZE" }, \
        { XFS_TRANS_INACTIVE,           "INACTIVE" }, \
        { XFS_TRANS_CREATE,             "CREATE" }, \
+       { XFS_TRANS_CREATE_TMPFILE,     "CREATE_TMPFILE" }, \
        { XFS_TRANS_CREATE_TRUNC,       "CREATE_TRUNC" }, \
        { XFS_TRANS_TRUNCATE_FILE,      "TRUNCATE_FILE" }, \
        { XFS_TRANS_REMOVE,             "REMOVE" }, \
@@ -208,7 +210,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *);
 
 /*
  * Here we centralize the specification of XFS meta-data buffer reference count
- * values.  This determine how hard the buffer cache tries to hold onto the
+ * values.  This determines how hard the buffer cache tries to hold onto the
  * buffer.
  */
 #define        XFS_AGF_REF             4
@@ -236,7 +238,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *);
 int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
 int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
                        uint32_t size, struct xfs_buf *bp);
-bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
+bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset,
                        uint32_t size, struct xfs_buf *bp);
 void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
                                 struct xfs_inode *ip, struct xfs_ifork *ifp);
index 1d2728eeba2de2f0fd8439ebb89371921a040552..ab046a914664b51452d058560004d23f985de43a 100644 (file)
 #define trace_xfs_log_recover_item_add_cont(a,b,c,d)   ((void) 0)
 #define trace_xfs_log_recover_item_add(a,b,c,d)        ((void) 0)
 
-#define trace_xfs_btree_corrupt(a,b)   ((void) 0)
-#define trace_xfs_da_btree_corrupt(a,b)        ((void) 0)
+#define trace_xfs_btree_corrupt(a,b)           ((void) 0)
+#define trace_xfs_da_btree_corrupt(a,b)                ((void) 0)
 
 #define trace_xfs_free_extent(a,b,c,d,e,f,g)   ((void) 0)
-#define trace_xfs_agf(a,b,c,d)         ((void) 0)
+#define trace_xfs_agf(a,b,c,d)                 ((void) 0)
+#define trace_xfs_read_agf(a,b)                        ((void) 0)
+#define trace_xfs_alloc_read_agf(a,b)          ((void) 0)
+#define trace_xfs_read_agi(a,b)                        ((void) 0)
+#define trace_xfs_ialloc_read_agi(a,b)         ((void) 0)
 
 #define trace_xfs_iext_insert(a,b,c,d,e)       ((void) 0)
-#define trace_xfs_iext_remove(a,b,c,d) ((void) 0)
+#define trace_xfs_iext_remove(a,b,c,d)         ((void) 0)
 
-#define trace_xfs_dir2_grow_inode(a,b) ((void) 0)
+#define trace_xfs_dir2_grow_inode(a,b)         ((void) 0)
 #define trace_xfs_dir2_shrink_inode(a,b)       ((void) 0)
 
 #define trace_xfs_dir2_leaf_to_node(a) ((void) 0)
index de7de9aaad8a7bef18a18ca54ecc2a909d0ef466..1097d14cd583f974559b33c170467220c8cae2c7 100644 (file)
@@ -38,11 +38,11 @@ struct xfs_trans_resv {
        struct xfs_trans_res    tr_remove;      /* unlink trans */
        struct xfs_trans_res    tr_symlink;     /* symlink trans */
        struct xfs_trans_res    tr_create;      /* create trans */
+       struct xfs_trans_res    tr_create_tmpfile; /* create O_TMPFILE trans */
        struct xfs_trans_res    tr_mkdir;       /* mkdir trans */
        struct xfs_trans_res    tr_ifree;       /* inode free trans */
        struct xfs_trans_res    tr_ichange;     /* inode update trans */
        struct xfs_trans_res    tr_growdata;    /* fs data section grow trans */
-       struct xfs_trans_res    tr_swrite;      /* sync write inode trans */
        struct xfs_trans_res    tr_addafork;    /* add inode attr fork trans */
        struct xfs_trans_res    tr_writeid;     /* write setuid/setgid file */
        struct xfs_trans_res    tr_attrinval;   /* attr fork buffer
@@ -100,6 +100,7 @@ struct xfs_trans_resv {
 #define        XFS_ITRUNCATE_LOG_COUNT         2
 #define XFS_INACTIVE_LOG_COUNT         2
 #define        XFS_CREATE_LOG_COUNT            2
+#define        XFS_CREATE_TMPFILE_LOG_COUNT    2
 #define        XFS_MKDIR_LOG_COUNT             3
 #define        XFS_SYMLINK_LOG_COUNT           3
 #define        XFS_REMOVE_LOG_COUNT            2
index a7d1721ea9b1558c305471d730ab6aae9f333e56..bf9c4579334d500fea6c917d2a149ba05dead7fb 100644 (file)
@@ -28,7 +28,8 @@
        (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
          XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
          XFS_EXTENTADD_SPACE_RES(mp,w))
-#define        XFS_DAENTER_1B(mp,w)    ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1)
+#define        XFS_DAENTER_1B(mp,w)    \
+       ((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1)
 #define        XFS_DAENTER_DBS(mp,w)   \
        (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0))
 #define        XFS_DAENTER_BLOCKS(mp,w)        \
@@ -47,7 +48,7 @@
 #define        XFS_DIRREMOVE_SPACE_RES(mp)     \
        XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
 #define        XFS_IALLOC_SPACE_RES(mp)        \
-       (XFS_IALLOC_BLOCKS(mp) + \
+       ((mp)->m_ialloc_blks + \
         (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \
          ((mp)->m_in_maxlevels - 1)))
 
@@ -55,7 +56,7 @@
  * Space reservation values for various transactions.
  */
 #define        XFS_ADDAFORK_SPACE_RES(mp)      \
-       ((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
+       ((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
 #define        XFS_ATTRRM_SPACE_RES(mp)        \
        XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
 /* This macro is not used - see inline code in xfs_attr_set */
index ae15a5dcfcfe4304de5f46e97bc752f79d66d3e1..b44599839408a791793279a4d84d5b34421eeafb 100644 (file)
@@ -23,6 +23,7 @@ CFILES = cache.c \
        xfs_bmap_btree.c \
        xfs_btree.c \
        xfs_da_btree.c \
+       xfs_da_format.c \
        xfs_dir2.c \
        xfs_dir2_block.c \
        xfs_dir2_data.c \
index 06458e5e49d7ba2c4caced8c81220d9ca8f8d5b3..98054484f138bc768919cc79afc16593d1b98487 100644 (file)
@@ -709,18 +709,37 @@ libxfs_mount(
                        return NULL;
        }
 
-       /* Initialize the appropriate directory manager */
-       if (!xfs_sb_version_hasdirv2(sbp)) {
+       /*
+        * We automatically convert v1 inodes to v2 inodes now, so if
+        * the NLINK bit is not set we can't operate on the filesystem.
+        */
+       if (!(sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {
+
+               fprintf(stderr, _(
+       "%s: V1 inodes unsupported. Please try an older xfsprogs.\n"),
+                                progname);
+               exit(1);
+       }
+
+       /* Check for supported directory formats */
+       if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) {
 
                fprintf(stderr, _(
        "%s: V1 directories unsupported. Please try an older xfsprogs.\n"),
                                 progname);
                exit(1);
        }
-       xfs_dir_mount(mp);
 
-       /* Initialize cached values for the attribute manager */
-       mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
+       /* check for unsupported other features */
+       if (!xfs_sb_good_version(sbp)) {
+               fprintf(stderr, _(
+       "%s: Unsupported features detected. Please try a newer xfsprogs.\n"),
+                                progname);
+               exit(1);
+       }
+
+       xfs_da_mount(mp);
+
        if (xfs_sb_version_hasattr2(&mp->m_sb))
                mp->m_flags |= LIBXFS_MOUNT_ATTR2;
 
index 8b2037a886ec7424def32ef6d8453c87eb5d4a12..8318922a411fed8c766fe7ebc44b4f4bbb6f6abe 100644 (file)
@@ -1125,6 +1125,14 @@ libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags,
                return error;
        }
 
+       /*
+        * set up the inode ops structure that the libxfs code relies on
+        */
+       if (S_ISDIR(ip->i_d.di_mode))
+               ip->d_ops = mp->m_dir_inode_ops;
+       else
+               ip->d_ops = mp->m_nondir_inode_ops;
+
        *ipp = ip;
        return 0;
 }
index 49eb76d4a658a6db9a6b4d1dde034a40440b43ef..653592fbadced3388deb1ea05d9e6a6846b426f3 100644 (file)
@@ -217,13 +217,12 @@ libxfs_ialloc(
        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD);
 
        /*
-        * If the superblock version is up to where we support new format
-        * inodes and this is currently an old format inode, then change
-        * the inode version number now.  This way we only do the conversion
-        * here rather than here and in the flush/logging code.
+        * We only support filesystems that understand v2 format inodes. So if
+        * this is currently an old format inode, then change the inode version
+        * number now.  This way we only do the conversion here rather than here
+        * and in the flush/logging code.
         */
-       if (xfs_sb_version_hasnlink(&tp->t_mountp->m_sb) &&
-           ip->i_d.di_version == 1) {
+       if (ip->i_d.di_version == 1) {
                ip->i_d.di_version = 2;
                /*
                 * old link count, projid_lo/hi field, pad field
@@ -311,6 +310,14 @@ libxfs_ialloc(
        ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
        ip->i_d.di_anextents = 0;
 
+       /*
+        * set up the inode ops structure that the libxfs code relies on
+        */
+       if (S_ISDIR(ip->i_d.di_mode))
+               ip->d_ops = ip->i_mount->m_dir_inode_ops;
+       else
+               ip->d_ops = ip->i_mount->m_nondir_inode_ops;
+
        /*
         * Log the new values stuffed into the inode.
         */
@@ -399,6 +406,7 @@ libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp)
        ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
                ip->i_d.di_nextents > ip->i_df.if_ext_max);
+       ASSERT(ip->i_d.di_version > 1);
 
        iip = ip->i_itemp;
        mp = ip->i_mount;
@@ -431,40 +439,9 @@ libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp)
         */
        xfs_dinode_to_disk(dip, &ip->i_d);
 
-       /*
-        * If this is really an old format inode and the superblock version
-        * has not been updated to support only new format inodes, then
-        * convert back to the old inode format.  If the superblock version
-        * has been updated, then make the conversion permanent.
-        */
-       ASSERT(ip->i_d.di_version == 1 ||
-               xfs_sb_version_hasnlink(&mp->m_sb));
-       if (ip->i_d.di_version == 1) {
-               if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
-                       /*
-                        * Convert it back.
-                        */
-                       ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
-                       dip->di_onlink = cpu_to_be16(ip->i_d.di_nlink);
-               } else {
-                       /*
-                        * The superblock version has already been bumped,
-                        * so just make the conversion to the new inode
-                        * format permanent.
-                        */
-                       ip->i_d.di_version = 2;
-                       dip->di_version =  2;
-                       ip->i_d.di_onlink = 0;
-                       dip->di_onlink = 0;
-                       memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
-                       memset(&(dip->di_pad[0]), 0, sizeof(dip->di_pad));
-                       ASSERT(xfs_get_projid(&ip->i_d) == 0);
-               }
-       }
-
-       xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp);
+       xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK);
        if (XFS_IFORK_Q(ip)) 
-               xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
+               xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK);
 
        /* update the lsn in the on disk inode if required */
        if (ip->i_d.di_version == 3)
index 8865a8a2cf9b226a5797336c6789fe47c82a8613..cc6e3c5ddb09c8cae897bffa3aa5fb2992bcb9cc 100644 (file)
 #define xfs_bunmapi                    libxfs_bunmapi
 
 /* xfs_bmap_btree.h */
-#define xfs_bmbt_disk_get_all          libxfs_bmbt_disk_get_all
+#define xfs_bmbt_get_all               libxfs_bmbt_get_all
 
 /* xfs_da_btree.h */
 #define xfs_da_brelse                  libxfs_da_brelse
@@ -376,6 +376,8 @@ roundup_64(__uint64_t x, __uint32_t y)
 #define XFS_MOUNT_WSYNC                        0       /* ignored in userspace */
 #define XFS_MOUNT_NOALIGN              0       /* ignored in userspace */
 #define XFS_MOUNT_IKEEP                        0       /* ignored in userspace */
+#define XFS_MOUNT_SWALLOC              0       /* ignored in userspace */
+#define XFS_MOUNT_RDONLY               0       /* ignored in userspace */
 
 #define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
        xfs_mod_incore_sb(mp, field, delta, rsvd)
@@ -423,9 +425,12 @@ roundup_64(__uint64_t x, __uint32_t y)
 #define xfs_ilock(ip,mode)                             ((void) 0)
 #define xfs_ilock_nowait(ip,mode)                      ((void) 0)
 #define xfs_ilock_demote(ip,mode)                      ((void) 0)
-#define xfs_iunlock(ip,mode)                           ((void) 0)
-#define xfs_ilock_map_shared(ip,mode)                  ((void) 0)
-#define xfs_iunlock_map_shared(ip,mode)                        ((void) 0)
+#define xfs_ilock_data_map_shared(ip)                  (0)
+#define xfs_ilock_attr_map_shared(ip)                  (0)
+#define xfs_iunlock(ip,mode)                           ({      \
+       typeof(mode) __mode = mode;                             \
+       __mode = __mode; /* no set-but-unused warning */        \
+})
 #define __xfs_flock(ip)                                        ((void) 0)
 
 /* space allocation */
@@ -478,9 +483,6 @@ int xfs_attr_rmtval_get(struct xfs_da_args *);
 void xfs_bmap_del_free(xfs_bmap_free_t *, xfs_bmap_free_item_t *,
                        xfs_bmap_free_item_t *);
 
-/* xfs_inode.c */
-void xfs_iflush_fork(xfs_inode_t *, xfs_dinode_t *, xfs_inode_log_item_t *,
-                       int, xfs_buf_t *);
 /*
  * For regular files we only update the on-disk filesize when actually
  * writing data back to disk.  Until then only the copy in the VFS inode
index 6c82be00a0d65e0d213c407534281ad8126f7860..135b6e0d2426248e7dca4f746cd35058589072b1 100644 (file)
@@ -17,6 +17,8 @@
  */
 #include <xfs.h>
 
+struct workqueue_struct *xfs_alloc_wq;
+
 #define XFS_ABSDIFF(a,b)       (((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
 
 #define        XFSA_FIXUP_BNO_OK       1
@@ -235,16 +237,14 @@ xfs_alloc_fix_len(
        k = rlen % args->prod;
        if (k == args->mod)
                return;
-       if (k > args->mod) {
-               if ((int)(rlen = rlen - k - args->mod) < (int)args->minlen)
-                       return;
-       } else {
-               if ((int)(rlen = rlen - args->prod - (args->mod - k)) <
-                   (int)args->minlen)
-                       return;
-       }
-       ASSERT(rlen >= args->minlen);
-       ASSERT(rlen <= args->maxlen);
+       if (k > args->mod)
+               rlen = rlen - (k - args->mod);
+       else
+               rlen = rlen - args->prod + (args->mod - k);
+       if ((int)rlen < (int)args->minlen)
+               return;
+       ASSERT(rlen >= args->minlen && rlen <= args->maxlen);
+       ASSERT(rlen % args->prod == args->mod);
        args->len = rlen;
 }
 
@@ -519,7 +519,6 @@ xfs_alloc_read_agfl(
                        XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops);
        if (error)
                return error;
-       ASSERT(!xfs_buf_geterror(bp));
        xfs_buf_set_ref(bp, XFS_AGFL_REF);
        *bpp = bp;
        return 0;
@@ -1817,10 +1816,8 @@ xfs_alloc_longest_free_extent(
 /*
  * Decide whether to use this allocation group for this allocation.
  * If so, fix up the btree freelist's size.
- *
- * Note: This is public so mkfs can call it
  */
-int                            /* error */
+int                    /* error */
 xfs_alloc_fix_freelist(
        xfs_alloc_arg_t *args,  /* allocation argument structure */
        int             flags)  /* XFS_ALLOC_FLAG_... */
@@ -2267,6 +2264,8 @@ xfs_read_agf(
 {
        int             error;
 
+       trace_xfs_read_agf(mp, agno);
+
        ASSERT(agno != NULLAGNUMBER);
        error = xfs_trans_read_buf(
                        mp, tp, mp->m_ddev_targp,
@@ -2297,8 +2296,9 @@ xfs_alloc_read_agf(
        struct xfs_perag        *pag;           /* per allocation group data */
        int                     error;
 
-       ASSERT(agno != NULLAGNUMBER);
+       trace_xfs_alloc_read_agf(mp, agno);
 
+       ASSERT(agno != NULLAGNUMBER);
        error = xfs_read_agf(mp, tp, agno,
                        (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
                        bpp);
@@ -2321,6 +2321,8 @@ xfs_alloc_read_agf(
                        be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
                spin_lock_init(&pag->pagb_lock);
                pag->pagb_count = 0;
+               /* XXX: pagb_tree doesn't exist in userspace */
+               //pag->pagb_tree = RB_ROOT;
                pag->pagf_init = 1;
        }
 #ifdef DEBUG
index 215be7e4bb82f32f06e87bec8dbe781b7c645227..1787df8de6fcebdc3d09974c1fa90e4ca1a5c32f 100644 (file)
@@ -53,7 +53,6 @@ xfs_allocbt_alloc_block(
        struct xfs_btree_cur    *cur,
        union xfs_btree_ptr     *start,
        union xfs_btree_ptr     *new,
-       int                     length,
        int                     *stat)
 {
        int                     error;
@@ -91,6 +90,7 @@ xfs_allocbt_free_block(
        struct xfs_buf          *bp)
 {
        struct xfs_buf          *agbp = cur->bc_private.a.agbp;
+       struct xfs_agf          *agf = XFS_BUF_TO_AGF(agbp);
        xfs_agblock_t           bno;
        int                     error;
 
@@ -407,72 +407,6 @@ xfs_allocbt_recs_inorder(
 }
 #endif /* DEBUG */
 
-#ifdef XFS_BTREE_TRACE
-ktrace_t       *xfs_allocbt_trace_buf;
-
-STATIC void
-xfs_allocbt_trace_enter(
-       struct xfs_btree_cur    *cur,
-       const char              *func,
-       char                    *s,
-       int                     type,
-       int                     line,
-       __psunsigned_t          a0,
-       __psunsigned_t          a1,
-       __psunsigned_t          a2,
-       __psunsigned_t          a3,
-       __psunsigned_t          a4,
-       __psunsigned_t          a5,
-       __psunsigned_t          a6,
-       __psunsigned_t          a7,
-       __psunsigned_t          a8,
-       __psunsigned_t          a9,
-       __psunsigned_t          a10)
-{
-       ktrace_enter(xfs_allocbt_trace_buf, (void *)(__psint_t)type,
-               (void *)func, (void *)s, NULL, (void *)cur,
-               (void *)a0, (void *)a1, (void *)a2, (void *)a3,
-               (void *)a4, (void *)a5, (void *)a6, (void *)a7,
-               (void *)a8, (void *)a9, (void *)a10);
-}
-
-STATIC void
-xfs_allocbt_trace_cursor(
-       struct xfs_btree_cur    *cur,
-       __uint32_t              *s0,
-       __uint64_t              *l0,
-       __uint64_t              *l1)
-{
-       *s0 = cur->bc_private.a.agno;
-       *l0 = cur->bc_rec.a.ar_startblock;
-       *l1 = cur->bc_rec.a.ar_blockcount;
-}
-
-STATIC void
-xfs_allocbt_trace_key(
-       struct xfs_btree_cur    *cur,
-       union xfs_btree_key     *key,
-       __uint64_t              *l0,
-       __uint64_t              *l1)
-{
-       *l0 = be32_to_cpu(key->alloc.ar_startblock);
-       *l1 = be32_to_cpu(key->alloc.ar_blockcount);
-}
-
-STATIC void
-xfs_allocbt_trace_record(
-       struct xfs_btree_cur    *cur,
-       union xfs_btree_rec     *rec,
-       __uint64_t              *l0,
-       __uint64_t              *l1,
-       __uint64_t              *l2)
-{
-       *l0 = be32_to_cpu(rec->alloc.ar_startblock);
-       *l1 = be32_to_cpu(rec->alloc.ar_blockcount);
-       *l2 = 0;
-}
-#endif /* XFS_BTREE_TRACE */
-
 static const struct xfs_btree_ops xfs_allocbt_ops = {
        .rec_len                = sizeof(xfs_alloc_rec_t),
        .key_len                = sizeof(xfs_alloc_key_t),
@@ -494,13 +428,6 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
        .keys_inorder           = xfs_allocbt_keys_inorder,
        .recs_inorder           = xfs_allocbt_recs_inorder,
 #endif
-
-#ifdef XFS_BTREE_TRACE
-       .trace_enter            = xfs_allocbt_trace_enter,
-       .trace_cursor           = xfs_allocbt_trace_cursor,
-       .trace_key              = xfs_allocbt_trace_key,
-       .trace_record           = xfs_allocbt_trace_record,
-#endif
 };
 
 /*
index 17519d32e21e1ee73eaf4465cc48246f13c0b53f..b4a900a4bf0b5530bb0b9e97604f56f7182f571a 100644 (file)
@@ -51,17 +51,27 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
 
 
 STATIC int
-xfs_attr_name_to_xname(
-       struct xfs_name *xname,
-       const unsigned char *aname)
+xfs_attr_args_init(
+       struct xfs_da_args      *args,
+       struct xfs_inode        *dp,
+       const unsigned char     *name,
+       int                     flags)
 {
-       if (!aname)
+
+       if (!name)
                return EINVAL;
-       xname->name = aname;
-       xname->len = strlen((char *)aname);
-       if (xname->len >= MAXNAMELEN)
+
+       memset(args, 0, sizeof(*args));
+       args->geo = dp->i_mount->m_attr_geo;
+       args->whichfork = XFS_ATTR_FORK;
+       args->dp = dp;
+       args->flags = flags;
+       args->name = name;
+       args->namelen = strlen((const char *)name);
+       if (args->namelen >= MAXNAMELEN)
                return EFAULT;          /* match IRIX behaviour */
 
+       args->hashval = xfs_da_hashname(args->name, args->namelen);
        return 0;
 }
 
@@ -80,78 +90,46 @@ xfs_inode_hasattr(
  * Overall external interface routines.
  *========================================================================*/
 
-STATIC int
-xfs_attr_get_int(
+int
+xfs_attr_get(
        struct xfs_inode        *ip,
-       struct xfs_name         *name,
+       const unsigned char     *name,
        unsigned char           *value,
        int                     *valuelenp,
        int                     flags)
 {
-       xfs_da_args_t   args;
-       int             error;
+       struct xfs_da_args      args;
+       uint                    lock_mode;
+       int                     error;
+
+       XFS_STATS_INC(xs_attr_get);
+
+       if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+               return EIO;
 
        if (!xfs_inode_hasattr(ip))
                return ENOATTR;
 
-       /*
-        * Fill in the arg structure for this request.
-        */
-       memset((char *)&args, 0, sizeof(args));
-       args.name = name->name;
-       args.namelen = name->len;
+       error = xfs_attr_args_init(&args, ip, name, flags);
+       if (error)
+               return error;
+
        args.value = value;
        args.valuelen = *valuelenp;
-       args.flags = flags;
-       args.hashval = xfs_da_hashname(args.name, args.namelen);
-       args.dp = ip;
-       args.whichfork = XFS_ATTR_FORK;
 
-       /*
-        * Decide on what work routines to call based on the inode size.
-        */
-       if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+       lock_mode = xfs_ilock_attr_map_shared(ip);
+       if (!xfs_inode_hasattr(ip))
+               error = ENOATTR;
+       else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
                error = xfs_attr_shortform_getvalue(&args);
-       } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
+       else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK))
                error = xfs_attr_leaf_get(&args);
-       } else {
+       else
                error = xfs_attr_node_get(&args);
-       }
+       xfs_iunlock(ip, lock_mode);
 
-       /*
-        * Return the number of bytes in the value to the caller.
-        */
        *valuelenp = args.valuelen;
-
-       if (error == EEXIST)
-               error = 0;
-       return(error);
-}
-
-int
-xfs_attr_get(
-       xfs_inode_t     *ip,
-       const unsigned char *name,
-       unsigned char   *value,
-       int             *valuelenp,
-       int             flags)
-{
-       int             error;
-       struct xfs_name xname;
-
-       XFS_STATS_INC(xs_attr_get);
-
-       if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-               return(EIO);
-
-       error = xfs_attr_name_to_xname(&xname, name);
-       if (error)
-               return error;
-
-       xfs_ilock(ip, XFS_ILOCK_SHARED);
-       error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags);
-       xfs_iunlock(ip, XFS_ILOCK_SHARED);
-       return(error);
+       return error == EEXIST ? 0 : error;
 }
 
 /*
@@ -159,12 +137,10 @@ xfs_attr_get(
  */
 STATIC int
 xfs_attr_calc_size(
-       struct xfs_inode        *ip,
-       int                     namelen,
-       int                     valuelen,
+       struct xfs_da_args      *args,
        int                     *local)
 {
-       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_mount        *mp = args->dp->i_mount;
        int                     size;
        int                     nblks;
 
@@ -172,12 +148,10 @@ xfs_attr_calc_size(
         * Determine space new attribute will use, and if it would be
         * "local" or "remote" (note: local != inline).
         */
-       size = xfs_attr_leaf_newentsize(namelen, valuelen,
-                                       mp->m_sb.sb_blocksize, local);
-
+       size = xfs_attr_leaf_newentsize(args, local);
        nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
        if (*local) {
-               if (size > (mp->m_sb.sb_blocksize >> 1)) {
+               if (size > (args->geo->blksize / 2)) {
                        /* Double split possible */
                        nblks *= 2;
                }
@@ -186,7 +160,7 @@ xfs_attr_calc_size(
                 * Out of line attribute, cannot double split, but
                 * make room for the attribute value itself.
                 */
-               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
+               uint    dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
                nblks += dblocks;
                nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
        }
@@ -194,26 +168,38 @@ xfs_attr_calc_size(
        return nblks;
 }
 
-STATIC int
-xfs_attr_set_int(
-       struct xfs_inode *dp,
-       struct xfs_name *name,
-       unsigned char   *value,
-       int             valuelen,
-       int             flags)
+int
+xfs_attr_set(
+       struct xfs_inode        *dp,
+       const unsigned char     *name,
+       unsigned char           *value,
+       int                     valuelen,
+       int                     flags)
 {
-       xfs_da_args_t           args;
-       xfs_fsblock_t           firstblock;
-       xfs_bmap_free_t         flist;
-       int                     error, err2, committed;
        struct xfs_mount        *mp = dp->i_mount;
+       struct xfs_da_args      args;
+       struct xfs_bmap_free    flist;
        struct xfs_trans_res    tres;
+       xfs_fsblock_t           firstblock;
        int                     rsvd = (flags & ATTR_ROOT) != 0;
-       int                     local;
+       int                     error, err2, committed, local;
+
+       XFS_STATS_INC(xs_attr_set);
+
+       if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+               return EIO;
+
+       error = xfs_attr_args_init(&args, dp, name, flags);
+       if (error)
+               return error;
+
+       args.value = value;
+       args.valuelen = valuelen;
+       args.firstblock = &firstblock;
+       args.flist = &flist;
+       args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
+       args.total = xfs_attr_calc_size(&args, &local);
 
-       /*
-        * Attach the dquots to the inode.
-        */
        error = xfs_qm_dqattach(dp, 0);
        if (error)
                return error;
@@ -224,31 +210,13 @@ xfs_attr_set_int(
         */
        if (XFS_IFORK_Q(dp) == 0) {
                int sf_size = sizeof(xfs_attr_sf_hdr_t) +
-                             XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen);
+                       XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen);
 
-               if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
-                       return(error);
+               error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
+               if (error)
+                       return error;
        }
 
-       /*
-        * Fill in the arg structure for this request.
-        */
-       memset((char *)&args, 0, sizeof(args));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.value = value;
-       args.valuelen = valuelen;
-       args.flags = flags;
-       args.hashval = xfs_da_hashname(args.name, args.namelen);
-       args.dp = dp;
-       args.firstblock = &firstblock;
-       args.flist = &flist;
-       args.whichfork = XFS_ATTR_FORK;
-       args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
-
-       /* Size is now blocks for attribute data */
-       args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
-
        /*
         * Start our first transaction of the day.
         *
@@ -276,7 +244,7 @@ xfs_attr_set_int(
        error = xfs_trans_reserve(args.trans, &tres, args.total, 0);
        if (error) {
                xfs_trans_cancel(args.trans, 0);
-               return(error);
+               return error;
        }
        xfs_ilock(dp, XFS_ILOCK_EXCL);
 
@@ -286,7 +254,7 @@ xfs_attr_set_int(
        if (error) {
                xfs_iunlock(dp, XFS_ILOCK_EXCL);
                xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
-               return (error);
+               return error;
        }
 
        xfs_trans_ijoin(args.trans, dp, 0);
@@ -295,9 +263,9 @@ xfs_attr_set_int(
         * If the attribute list is non-existent or a shortform list,
         * upgrade it to a single-leaf-block attribute list.
         */
-       if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
-           ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) &&
-            (dp->i_d.di_anextents == 0))) {
+       if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
+           (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+            dp->i_d.di_anextents == 0)) {
 
                /*
                 * Build initial attribute list (if required).
@@ -322,9 +290,8 @@ xfs_attr_set_int(
                         * the transaction goes to disk before returning
                         * to the user.
                         */
-                       if (mp->m_flags & XFS_MOUNT_WSYNC) {
+                       if (mp->m_flags & XFS_MOUNT_WSYNC)
                                xfs_trans_set_sync(args.trans);
-                       }
 
                        if (!error && (flags & ATTR_KERNOTIME) == 0) {
                                xfs_trans_ichgtime(args.trans, dp,
@@ -334,7 +301,7 @@ xfs_attr_set_int(
                                                 XFS_TRANS_RELEASE_LOG_RES);
                        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-                       return(error == 0 ? err2 : error);
+                       return error ? error : err2;
                }
 
                /*
@@ -372,22 +339,19 @@ xfs_attr_set_int(
 
        }
 
-       if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
+       if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
                error = xfs_attr_leaf_addname(&args);
-       } else {
+       else
                error = xfs_attr_node_addname(&args);
-       }
-       if (error) {
+       if (error)
                goto out;
-       }
 
        /*
         * If this is a synchronous mount, make sure that the
         * transaction goes to disk before returning to the user.
         */
-       if (mp->m_flags & XFS_MOUNT_WSYNC) {
+       if (mp->m_flags & XFS_MOUNT_WSYNC)
                xfs_trans_set_sync(args.trans);
-       }
 
        if ((flags & ATTR_KERNOTIME) == 0)
                xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
@@ -399,65 +363,47 @@ xfs_attr_set_int(
        error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-       return(error);
+       return error;
 
 out:
-       if (args.trans)
+       if (args.trans) {
                xfs_trans_cancel(args.trans,
                        XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
+       }
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
-       return(error);
+       return error;
 }
 
+/*
+ * Generic handler routine to remove a name from an attribute list.
+ * Transitions attribute list from Btree to shortform as necessary.
+ */
 int
-xfs_attr_set(
-       xfs_inode_t     *dp,
-       const unsigned char *name,
-       unsigned char   *value,
-       int             valuelen,
-       int             flags)
+xfs_attr_remove(
+       struct xfs_inode        *dp,
+       const unsigned char     *name,
+       int                     flags)
 {
-       int             error;
-       struct xfs_name xname;
+       struct xfs_mount        *mp = dp->i_mount;
+       struct xfs_da_args      args;
+       struct xfs_bmap_free    flist;
+       xfs_fsblock_t           firstblock;
+       int                     error;
 
-       XFS_STATS_INC(xs_attr_set);
+       XFS_STATS_INC(xs_attr_remove);
 
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
-               return (EIO);
+               return EIO;
+
+       if (!xfs_inode_hasattr(dp))
+               return ENOATTR;
 
-       error = xfs_attr_name_to_xname(&xname, name);
+       error = xfs_attr_args_init(&args, dp, name, flags);
        if (error)
                return error;
 
-       return xfs_attr_set_int(dp, &xname, value, valuelen, flags);
-}
-
-/*
- * Generic handler routine to remove a name from an attribute list.
- * Transitions attribute list from Btree to shortform as necessary.
- */
-STATIC int
-xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
-{
-       xfs_da_args_t   args;
-       xfs_fsblock_t   firstblock;
-       xfs_bmap_free_t flist;
-       int             error;
-       xfs_mount_t     *mp = dp->i_mount;
-
-       /*
-        * Fill in the arg structure for this request.
-        */
-       memset((char *)&args, 0, sizeof(args));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.flags = flags;
-       args.hashval = xfs_da_hashname(args.name, args.namelen);
-       args.dp = dp;
        args.firstblock = &firstblock;
        args.flist = &flist;
-       args.total = 0;
-       args.whichfork = XFS_ATTR_FORK;
 
        /*
         * we have no control over the attribute names that userspace passes us
@@ -466,9 +412,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
         */
        args.op_flags = XFS_DA_OP_OKNOENT;
 
-       /*
-        * Attach the dquots to the inode.
-        */
        error = xfs_qm_dqattach(dp, 0);
        if (error)
                return error;
@@ -497,7 +440,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
                                  XFS_ATTRRM_SPACE_RES(mp), 0);
        if (error) {
                xfs_trans_cancel(args.trans, 0);
-               return(error);
+               return error;
        }
 
        xfs_ilock(dp, XFS_ILOCK_EXCL);
@@ -507,35 +450,26 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
         */
        xfs_trans_ijoin(args.trans, dp, 0);
 
-       /*
-        * Decide on what work routines to call based on the inode size.
-        */
        if (!xfs_inode_hasattr(dp)) {
                error = XFS_ERROR(ENOATTR);
-               goto out;
-       }
-       if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+       } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
                ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
                error = xfs_attr_shortform_remove(&args);
-               if (error) {
-                       goto out;
-               }
        } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
                error = xfs_attr_leaf_removename(&args);
        } else {
                error = xfs_attr_node_removename(&args);
        }
-       if (error) {
+
+       if (error)
                goto out;
-       }
 
        /*
         * If this is a synchronous mount, make sure that the
         * transaction goes to disk before returning to the user.
         */
-       if (mp->m_flags & XFS_MOUNT_WSYNC) {
+       if (mp->m_flags & XFS_MOUNT_WSYNC)
                xfs_trans_set_sync(args.trans);
-       }
 
        if ((flags & ATTR_KERNOTIME) == 0)
                xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
@@ -547,45 +481,17 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
        error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-       return(error);
+       return error;
 
 out:
-       if (args.trans)
+       if (args.trans) {
                xfs_trans_cancel(args.trans,
                        XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
-       xfs_iunlock(dp, XFS_ILOCK_EXCL);
-       return(error);
-}
-
-int
-xfs_attr_remove(
-       xfs_inode_t     *dp,
-       const unsigned char *name,
-       int             flags)
-{
-       int             error;
-       struct xfs_name xname;
-
-       XFS_STATS_INC(xs_attr_remove);
-
-       if (XFS_FORCED_SHUTDOWN(dp->i_mount))
-               return (EIO);
-
-       error = xfs_attr_name_to_xname(&xname, name);
-       if (error)
-               return error;
-
-       xfs_ilock(dp, XFS_ILOCK_SHARED);
-       if (!xfs_inode_hasattr(dp)) {
-               xfs_iunlock(dp, XFS_ILOCK_SHARED);
-               return XFS_ERROR(ENOATTR);
        }
-       xfs_iunlock(dp, XFS_ILOCK_SHARED);
-
-       return xfs_attr_remove_int(dp, &xname, flags);
+       xfs_iunlock(dp, XFS_ILOCK_EXCL);
+       return error;
 }
 
-
 /*========================================================================
  * External routines when attribute list is inside the inode
  *========================================================================*/
@@ -671,11 +577,22 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
 
                trace_xfs_attr_leaf_replace(args);
 
+               /* save the attribute state for later removal*/
                args->op_flags |= XFS_DA_OP_RENAME;     /* an atomic rename */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
                args->rmtblkno2 = args->rmtblkno;
                args->rmtblkcnt2 = args->rmtblkcnt;
+               args->rmtvaluelen2 = args->rmtvaluelen;
+
+               /*
+                * clear the remote attr state now that it is saved so that the
+                * values reflect the state of the attribute we are about to
+                * add, not the attribute we just found and will remove later.
+                */
+               args->rmtblkno = 0;
+               args->rmtblkcnt = 0;
+               args->rmtvaluelen = 0;
        }
 
        /*
@@ -767,6 +684,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                args->blkno = args->blkno2;
                args->rmtblkno = args->rmtblkno2;
                args->rmtblkcnt = args->rmtblkcnt2;
+               args->rmtvaluelen = args->rmtvaluelen2;
                if (args->rmtblkno) {
                        error = xfs_attr_rmtval_remove(args);
                        if (error)
@@ -919,7 +837,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
 }
 
 /*========================================================================
- * External routines when attribute list size > XFS_LBSIZE(mp).
+ * External routines when attribute list size > geo->blksize
  *========================================================================*/
 
 /*
@@ -952,8 +870,6 @@ restart:
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = mp;
-       state->blocksize = state->mp->m_sb.sb_blocksize;
-       state->node_ents = state->mp->m_attr_node_ents;
 
        /*
         * Search to see if name already exists, and get back a pointer
@@ -972,13 +888,22 @@ restart:
 
                trace_xfs_attr_node_replace(args);
 
+               /* save the attribute state for later removal*/
                args->op_flags |= XFS_DA_OP_RENAME;     /* atomic rename op */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
                args->rmtblkno2 = args->rmtblkno;
                args->rmtblkcnt2 = args->rmtblkcnt;
+               args->rmtvaluelen2 = args->rmtvaluelen;
+
+               /*
+                * clear the remote attr state now that it is saved so that the
+                * values reflect the state of the attribute we are about to
+                * add, not the attribute we just found and will remove later.
+                */
                args->rmtblkno = 0;
                args->rmtblkcnt = 0;
+               args->rmtvaluelen = 0;
        }
 
        retval = xfs_attr3_leaf_add(blk->bp, state->args);
@@ -1106,6 +1031,7 @@ restart:
                args->blkno = args->blkno2;
                args->rmtblkno = args->rmtblkno2;
                args->rmtblkcnt = args->rmtblkcnt2;
+               args->rmtvaluelen = args->rmtvaluelen2;
                if (args->rmtblkno) {
                        error = xfs_attr_rmtval_remove(args);
                        if (error)
@@ -1121,8 +1047,6 @@ restart:
                state = xfs_da_state_alloc();
                state->args = args;
                state->mp = mp;
-               state->blocksize = state->mp->m_sb.sb_blocksize;
-               state->node_ents = state->mp->m_attr_node_ents;
                state->inleaf = 0;
                error = xfs_da3_node_lookup_int(state, &retval);
                if (error)
@@ -1213,8 +1137,6 @@ xfs_attr_node_removename(xfs_da_args_t *args)
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = dp->i_mount;
-       state->blocksize = state->mp->m_sb.sb_blocksize;
-       state->node_ents = state->mp->m_attr_node_ents;
 
        /*
         * Search to see if name exists, and get back a pointer to it.
@@ -1476,8 +1398,6 @@ xfs_attr_node_get(xfs_da_args_t *args)
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = args->dp->i_mount;
-       state->blocksize = state->mp->m_sb.sb_blocksize;
-       state->node_ents = state->mp->m_attr_node_ents;
 
        /*
         * Search to see if name exists, and get back a pointer to it.
index f7f02ae1e5b9e11ae72c7a691338a38a889d3264..c630ddd8068c5fa492226b9715288798d76cf249 100644 (file)
@@ -54,11 +54,12 @@ STATIC int xfs_attr3_leaf_figure_balance(xfs_da_state_t *state,
 /*
  * Utility routines.
  */
-STATIC void xfs_attr3_leaf_moveents(struct xfs_attr_leafblock *src_leaf,
+STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args,
+                       struct xfs_attr_leafblock *src_leaf,
                        struct xfs_attr3_icleaf_hdr *src_ichdr, int src_start,
                        struct xfs_attr_leafblock *dst_leaf,
                        struct xfs_attr3_icleaf_hdr *dst_ichdr, int dst_start,
-                       int move_count, struct xfs_mount *mp);
+                       int move_count);
 STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
 
 void
@@ -685,6 +686,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
 
        memset((char *)&nargs, 0, sizeof(nargs));
        nargs.dp = dp;
+       nargs.geo = args->geo;
        nargs.firstblock = args->firstblock;
        nargs.flist = args->flist;
        nargs.total = args->total;
@@ -779,18 +781,18 @@ xfs_attr3_leaf_to_shortform(
 
        trace_xfs_attr_leaf_to_sf(args);
 
-       tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
+       tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP);
        if (!tmpbuffer)
                return ENOMEM;
 
-       memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(dp->i_mount));
+       memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
 
        leaf = (xfs_attr_leafblock_t *)tmpbuffer;
        xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
        entry = xfs_attr3_leaf_entryp(leaf);
 
        /* XXX (dgc): buffer is about to be marked stale - why zero it? */
-       memset(bp->b_addr, 0, XFS_LBSIZE(dp->i_mount));
+       memset(bp->b_addr, 0, args->geo->blksize);
 
        /*
         * Clean out the prior contents of the attribute list.
@@ -812,6 +814,7 @@ xfs_attr3_leaf_to_shortform(
         * Copy the attributes
         */
        memset((char *)&nargs, 0, sizeof(nargs));
+       nargs.geo = args->geo;
        nargs.dp = dp;
        nargs.firstblock = args->firstblock;
        nargs.flist = args->flist;
@@ -878,12 +881,12 @@ xfs_attr3_leaf_to_node(
        /* copy leaf to new buffer, update identifiers */
        xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF);
        bp2->b_ops = bp1->b_ops;
-       memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp));
+       memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize);
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_da3_blkinfo *hdr3 = bp2->b_addr;
                hdr3->blkno = cpu_to_be64(bp2->b_bn);
        }
-       xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(mp) - 1);
+       xfs_trans_log_buf(args->trans, bp2, 0, args->geo->blksize - 1);
 
        /*
         * Set up the new root node.
@@ -892,8 +895,8 @@ xfs_attr3_leaf_to_node(
        if (error)
                goto out;
        node = bp1->b_addr;
-       xfs_da3_node_hdr_from_disk(&icnodehdr, node);
-       btree = xfs_da3_node_tree_p(node);
+       dp->d_ops->node_hdr_from_disk(&icnodehdr, node);
+       btree = dp->d_ops->node_tree_p(node);
 
        leaf = bp2->b_addr;
        xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf);
@@ -903,8 +906,8 @@ xfs_attr3_leaf_to_node(
        btree[0].hashval = entries[icleafhdr.count - 1].hashval;
        btree[0].before = cpu_to_be32(blkno);
        icnodehdr.count = 1;
-       xfs_da3_node_hdr_to_disk(node, &icnodehdr);
-       xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(mp) - 1);
+       dp->d_ops->node_hdr_to_disk(node, &icnodehdr);
+       xfs_trans_log_buf(args->trans, bp1, 0, args->geo->blksize - 1);
        error = 0;
 out:
        return error;
@@ -940,10 +943,10 @@ xfs_attr3_leaf_create(
        bp->b_ops = &xfs_attr3_leaf_buf_ops;
        xfs_trans_buf_set_type(args->trans, bp, XFS_BLFT_ATTR_LEAF_BUF);
        leaf = bp->b_addr;
-       memset(leaf, 0, XFS_LBSIZE(mp));
+       memset(leaf, 0, args->geo->blksize);
 
        memset(&ichdr, 0, sizeof(ichdr));
-       ichdr.firstused = XFS_LBSIZE(mp);
+       ichdr.firstused = args->geo->blksize;
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_da3_blkinfo *hdr3 = bp->b_addr;
@@ -962,7 +965,7 @@ xfs_attr3_leaf_create(
        ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base;
 
        xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr);
-       xfs_trans_log_buf(args->trans, bp, 0, XFS_LBSIZE(mp) - 1);
+       xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1);
 
        *bpp = bp;
        return 0;
@@ -1048,8 +1051,7 @@ xfs_attr3_leaf_add(
        leaf = bp->b_addr;
        xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
        ASSERT(args->index >= 0 && args->index <= ichdr.count);
-       entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
-                          args->trans->t_mountp->m_sb.sb_blocksize, NULL);
+       entsize = xfs_attr_leaf_newentsize(args, NULL);
 
        /*
         * Search through freemap for first-fit on new name length.
@@ -1148,17 +1150,14 @@ xfs_attr3_leaf_add_work(
         * Allocate space for the new string (at the end of the run).
         */
        mp = args->trans->t_mountp;
-       ASSERT(ichdr->freemap[mapindex].base < XFS_LBSIZE(mp));
+       ASSERT(ichdr->freemap[mapindex].base < args->geo->blksize);
        ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0);
        ASSERT(ichdr->freemap[mapindex].size >=
-               xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
-                                        mp->m_sb.sb_blocksize, NULL));
-       ASSERT(ichdr->freemap[mapindex].size < XFS_LBSIZE(mp));
+               xfs_attr_leaf_newentsize(args, NULL));
+       ASSERT(ichdr->freemap[mapindex].size < args->geo->blksize);
        ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0);
 
-       ichdr->freemap[mapindex].size -=
-                       xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
-                                                mp->m_sb.sb_blocksize, &tmp);
+       ichdr->freemap[mapindex].size -= xfs_attr_leaf_newentsize(args, &tmp);
 
        entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base +
                                     ichdr->freemap[mapindex].size);
@@ -1203,6 +1202,7 @@ xfs_attr3_leaf_add_work(
                name_rmt->valueblk = 0;
                args->rmtblkno = 1;
                args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
+               args->rmtvaluelen = args->valuelen;
        }
        xfs_trans_log_buf(args->trans, bp,
             XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index),
@@ -1242,14 +1242,13 @@ xfs_attr3_leaf_compact(
        struct xfs_attr_leafblock *leaf_dst;
        struct xfs_attr3_icleaf_hdr ichdr_src;
        struct xfs_trans        *trans = args->trans;
-       struct xfs_mount        *mp = trans->t_mountp;
        char                    *tmpbuffer;
 
        trace_xfs_attr_leaf_compact(args);
 
-       tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP);
-       memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp));
-       memset(bp->b_addr, 0, XFS_LBSIZE(mp));
+       tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP);
+       memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
+       memset(bp->b_addr, 0, args->geo->blksize);
        leaf_src = (xfs_attr_leafblock_t *)tmpbuffer;
        leaf_dst = bp->b_addr;
 
@@ -1262,7 +1261,7 @@ xfs_attr3_leaf_compact(
 
        /* Initialise the incore headers */
        ichdr_src = *ichdr_dst; /* struct copy */
-       ichdr_dst->firstused = XFS_LBSIZE(mp);
+       ichdr_dst->firstused = args->geo->blksize;
        ichdr_dst->usedbytes = 0;
        ichdr_dst->count = 0;
        ichdr_dst->holes = 0;
@@ -1277,13 +1276,13 @@ xfs_attr3_leaf_compact(
         * Copy all entry's in the same (sorted) order,
         * but allocate name/value pairs packed and in sequence.
         */
-       xfs_attr3_leaf_moveents(leaf_src, &ichdr_src, 0, leaf_dst, ichdr_dst, 0,
-                               ichdr_src.count, mp);
+       xfs_attr3_leaf_moveents(args, leaf_src, &ichdr_src, 0,
+                               leaf_dst, ichdr_dst, 0, ichdr_src.count);
        /*
         * this logs the entire buffer, but the caller must write the header
         * back to the buffer when it is finished modifying it.
         */
-       xfs_trans_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1);
+       xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1);
 
        kmem_free(tmpbuffer);
 }
@@ -1434,8 +1433,8 @@ xfs_attr3_leaf_rebalance(
                /*
                 * Move high entries from leaf1 to low end of leaf2.
                 */
-               xfs_attr3_leaf_moveents(leaf1, &ichdr1, ichdr1.count - count,
-                               leaf2, &ichdr2, 0, count, state->mp);
+               xfs_attr3_leaf_moveents(args, leaf1, &ichdr1,
+                               ichdr1.count - count, leaf2, &ichdr2, 0, count);
 
        } else if (count > ichdr1.count) {
                /*
@@ -1463,14 +1462,14 @@ xfs_attr3_leaf_rebalance(
                /*
                 * Move low entries from leaf2 to high end of leaf1.
                 */
-               xfs_attr3_leaf_moveents(leaf2, &ichdr2, 0, leaf1, &ichdr1,
-                                       ichdr1.count, count, state->mp);
+               xfs_attr3_leaf_moveents(args, leaf2, &ichdr2, 0, leaf1, &ichdr1,
+                                       ichdr1.count, count);
        }
 
        xfs_attr3_leaf_hdr_to_disk(leaf1, &ichdr1);
        xfs_attr3_leaf_hdr_to_disk(leaf2, &ichdr2);
-       xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
-       xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
+       xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1);
+       xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1);
 
        /*
         * Copy out last hashval in each block for B-tree code.
@@ -1565,11 +1564,9 @@ xfs_attr3_leaf_figure_balance(
        max = ichdr1->count + ichdr2->count;
        half = (max + 1) * sizeof(*entry);
        half += ichdr1->usedbytes + ichdr2->usedbytes +
-                       xfs_attr_leaf_newentsize(state->args->namelen,
-                                                state->args->valuelen,
-                                                state->blocksize, NULL);
+                       xfs_attr_leaf_newentsize(state->args, NULL);
        half /= 2;
-       lastdelta = state->blocksize;
+       lastdelta = state->args->geo->blksize;
        entry = xfs_attr3_leaf_entryp(leaf1);
        for (count = index = 0; count < max; entry++, index++, count++) {
 
@@ -1579,10 +1576,7 @@ xfs_attr3_leaf_figure_balance(
                 */
                if (count == blk1->index) {
                        tmp = totallen + sizeof(*entry) +
-                               xfs_attr_leaf_newentsize(
-                                               state->args->namelen,
-                                               state->args->valuelen,
-                                               state->blocksize, NULL);
+                               xfs_attr_leaf_newentsize(state->args, NULL);
                        if (XFS_ATTR_ABS(half - tmp) > lastdelta)
                                break;
                        lastdelta = XFS_ATTR_ABS(half - tmp);
@@ -1618,10 +1612,7 @@ xfs_attr3_leaf_figure_balance(
        totallen -= count * sizeof(*entry);
        if (foundit) {
                totallen -= sizeof(*entry) +
-                               xfs_attr_leaf_newentsize(
-                                               state->args->namelen,
-                                               state->args->valuelen,
-                                               state->blocksize, NULL);
+                               xfs_attr_leaf_newentsize(state->args, NULL);
        }
 
        *countarg = count;
@@ -1673,7 +1664,7 @@ xfs_attr3_leaf_toosmall(
        bytes = xfs_attr3_leaf_hdr_size(leaf) +
                ichdr.count * sizeof(xfs_attr_leaf_entry_t) +
                ichdr.usedbytes;
-       if (bytes > (state->blocksize >> 1)) {
+       if (bytes > (state->args->geo->blksize >> 1)) {
                *action = 0;    /* blk over 50%, don't try to join */
                return(0);
        }
@@ -1727,7 +1718,8 @@ xfs_attr3_leaf_toosmall(
 
                xfs_attr3_leaf_hdr_from_disk(&ichdr2, bp->b_addr);
 
-               bytes = state->blocksize - (state->blocksize >> 2) -
+               bytes = state->args->geo->blksize -
+                       (state->args->geo->blksize >> 2) -
                        ichdr.usedbytes - ichdr2.usedbytes -
                        ((ichdr.count + ichdr2.count) *
                                        sizeof(xfs_attr_leaf_entry_t)) -
@@ -1778,7 +1770,6 @@ xfs_attr3_leaf_remove(
        struct xfs_attr_leafblock *leaf;
        struct xfs_attr3_icleaf_hdr ichdr;
        struct xfs_attr_leaf_entry *entry;
-       struct xfs_mount        *mp = args->trans->t_mountp;
        int                     before;
        int                     after;
        int                     smallest;
@@ -1792,7 +1783,7 @@ xfs_attr3_leaf_remove(
        leaf = bp->b_addr;
        xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
 
-       ASSERT(ichdr.count > 0 && ichdr.count < XFS_LBSIZE(mp) / 8);
+       ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8);
        ASSERT(args->index >= 0 && args->index < ichdr.count);
        ASSERT(ichdr.firstused >= ichdr.count * sizeof(*entry) +
                                        xfs_attr3_leaf_hdr_size(leaf));
@@ -1800,7 +1791,7 @@ xfs_attr3_leaf_remove(
        entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
 
        ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused);
-       ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));
+       ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize);
 
        /*
         * Scan through free region table:
@@ -1815,8 +1806,8 @@ xfs_attr3_leaf_remove(
        smallest = XFS_ATTR_LEAF_MAPSIZE - 1;
        entsize = xfs_attr_leaf_entsize(leaf, args->index);
        for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
-               ASSERT(ichdr.freemap[i].base < XFS_LBSIZE(mp));
-               ASSERT(ichdr.freemap[i].size < XFS_LBSIZE(mp));
+               ASSERT(ichdr.freemap[i].base < args->geo->blksize);
+               ASSERT(ichdr.freemap[i].size < args->geo->blksize);
                if (ichdr.freemap[i].base == tablesize) {
                        ichdr.freemap[i].base -= sizeof(xfs_attr_leaf_entry_t);
                        ichdr.freemap[i].size += sizeof(xfs_attr_leaf_entry_t);
@@ -1893,11 +1884,11 @@ xfs_attr3_leaf_remove(
         * removing the name.
         */
        if (smallest) {
-               tmp = XFS_LBSIZE(mp);
+               tmp = args->geo->blksize;
                entry = xfs_attr3_leaf_entryp(leaf);
                for (i = ichdr.count - 1; i >= 0; entry++, i--) {
                        ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused);
-                       ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));
+                       ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize);
 
                        if (be16_to_cpu(entry->nameidx) < tmp)
                                tmp = be16_to_cpu(entry->nameidx);
@@ -1920,7 +1911,7 @@ xfs_attr3_leaf_remove(
        tmp = ichdr.usedbytes + xfs_attr3_leaf_hdr_size(leaf) +
              ichdr.count * sizeof(xfs_attr_leaf_entry_t);
 
-       return tmp < mp->m_attr_magicpct; /* leaf is < 37% full */
+       return tmp < args->geo->magicpct; /* leaf is < 37% full */
 }
 
 /*
@@ -1937,7 +1928,6 @@ xfs_attr3_leaf_unbalance(
        struct xfs_attr3_icleaf_hdr drophdr;
        struct xfs_attr3_icleaf_hdr savehdr;
        struct xfs_attr_leaf_entry *entry;
-       struct xfs_mount        *mp = state->mp;
 
        trace_xfs_attr_leaf_unbalance(state->args);
 
@@ -1964,13 +1954,15 @@ xfs_attr3_leaf_unbalance(
                 */
                if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
                                         drop_blk->bp, &drophdr)) {
-                       xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0,
+                       xfs_attr3_leaf_moveents(state->args,
+                                               drop_leaf, &drophdr, 0,
                                                save_leaf, &savehdr, 0,
-                                               drophdr.count, mp);
+                                               drophdr.count);
                } else {
-                       xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0,
+                       xfs_attr3_leaf_moveents(state->args,
+                                               drop_leaf, &drophdr, 0,
                                                save_leaf, &savehdr,
-                                               savehdr.count, drophdr.count, mp);
+                                               savehdr.count, drophdr.count);
                }
        } else {
                /*
@@ -1980,7 +1972,7 @@ xfs_attr3_leaf_unbalance(
                struct xfs_attr_leafblock *tmp_leaf;
                struct xfs_attr3_icleaf_hdr tmphdr;
 
-               tmp_leaf = kmem_zalloc(state->blocksize, KM_SLEEP);
+               tmp_leaf = kmem_zalloc(state->args->geo->blksize, KM_SLEEP);
 
                /*
                 * Copy the header into the temp leaf so that all the stuff
@@ -1993,35 +1985,39 @@ xfs_attr3_leaf_unbalance(
                tmphdr.magic = savehdr.magic;
                tmphdr.forw = savehdr.forw;
                tmphdr.back = savehdr.back;
-               tmphdr.firstused = state->blocksize;
+               tmphdr.firstused = state->args->geo->blksize;
 
                /* write the header to the temp buffer to initialise it */
                xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr);
 
                if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
                                         drop_blk->bp, &drophdr)) {
-                       xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0,
+                       xfs_attr3_leaf_moveents(state->args,
+                                               drop_leaf, &drophdr, 0,
                                                tmp_leaf, &tmphdr, 0,
-                                               drophdr.count, mp);
-                       xfs_attr3_leaf_moveents(save_leaf, &savehdr, 0,
+                                               drophdr.count);
+                       xfs_attr3_leaf_moveents(state->args,
+                                               save_leaf, &savehdr, 0,
                                                tmp_leaf, &tmphdr, tmphdr.count,
-                                               savehdr.count, mp);
+                                               savehdr.count);
                } else {
-                       xfs_attr3_leaf_moveents(save_leaf, &savehdr, 0,
+                       xfs_attr3_leaf_moveents(state->args,
+                                               save_leaf, &savehdr, 0,
                                                tmp_leaf, &tmphdr, 0,
-                                               savehdr.count, mp);
-                       xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0,
+                                               savehdr.count);
+                       xfs_attr3_leaf_moveents(state->args,
+                                               drop_leaf, &drophdr, 0,
                                                tmp_leaf, &tmphdr, tmphdr.count,
-                                               drophdr.count, mp);
+                                               drophdr.count);
                }
-               memcpy(save_leaf, tmp_leaf, state->blocksize);
+               memcpy(save_leaf, tmp_leaf, state->args->geo->blksize);
                savehdr = tmphdr; /* struct copy */
                kmem_free(tmp_leaf);
        }
 
        xfs_attr3_leaf_hdr_to_disk(save_leaf, &savehdr);
        xfs_trans_log_buf(state->args->trans, save_blk->bp, 0,
-                                          state->blocksize - 1);
+                                          state->args->geo->blksize - 1);
 
        /*
         * Copy out last hashval in each block for B-tree code.
@@ -2067,7 +2063,7 @@ xfs_attr3_leaf_lookup_int(
        leaf = bp->b_addr;
        xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
        entries = xfs_attr3_leaf_entryp(leaf);
-       ASSERT(ichdr.count < XFS_LBSIZE(args->dp->i_mount) / 8);
+       ASSERT(ichdr.count < args->geo->blksize / 8);
 
        /*
         * Binary search.  (note: small blocks will skip this loop)
@@ -2141,11 +2137,11 @@ xfs_attr3_leaf_lookup_int(
                        if (!xfs_attr_namesp_match(args->flags, entry->flags))
                                continue;
                        args->index = probe;
-                       args->valuelen = be32_to_cpu(name_rmt->valuelen);
+                       args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen);
                        args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
                        args->rmtblkcnt = xfs_attr3_rmt_blocks(
                                                        args->dp->i_mount,
-                                                       args->valuelen);
+                                                       args->rmtvaluelen);
                        return XFS_ERROR(EEXIST);
                }
        }
@@ -2171,7 +2167,7 @@ xfs_attr3_leaf_getvalue(
 
        leaf = bp->b_addr;
        xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
-       ASSERT(ichdr.count < XFS_LBSIZE(args->dp->i_mount) / 8);
+       ASSERT(ichdr.count < args->geo->blksize / 8);
        ASSERT(args->index < ichdr.count);
 
        entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
@@ -2194,19 +2190,19 @@ xfs_attr3_leaf_getvalue(
                name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
                ASSERT(name_rmt->namelen == args->namelen);
                ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0);
-               valuelen = be32_to_cpu(name_rmt->valuelen);
+               args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen);
                args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
                args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount,
-                                                      valuelen);
+                                                      args->rmtvaluelen);
                if (args->flags & ATTR_KERNOVAL) {
-                       args->valuelen = valuelen;
+                       args->valuelen = args->rmtvaluelen;
                        return 0;
                }
-               if (args->valuelen < valuelen) {
-                       args->valuelen = valuelen;
+               if (args->valuelen < args->rmtvaluelen) {
+                       args->valuelen = args->rmtvaluelen;
                        return XFS_ERROR(ERANGE);
                }
-               args->valuelen = valuelen;
+               args->valuelen = args->rmtvaluelen;
        }
        return 0;
 }
@@ -2222,14 +2218,14 @@ xfs_attr3_leaf_getvalue(
 /*ARGSUSED*/
 STATIC void
 xfs_attr3_leaf_moveents(
+       struct xfs_da_args              *args,
        struct xfs_attr_leafblock       *leaf_s,
        struct xfs_attr3_icleaf_hdr     *ichdr_s,
        int                             start_s,
        struct xfs_attr_leafblock       *leaf_d,
        struct xfs_attr3_icleaf_hdr     *ichdr_d,
        int                             start_d,
-       int                             count,
-       struct xfs_mount                *mp)
+       int                             count)
 {
        struct xfs_attr_leaf_entry      *entry_s;
        struct xfs_attr_leaf_entry      *entry_d;
@@ -2249,10 +2245,10 @@ xfs_attr3_leaf_moveents(
        ASSERT(ichdr_s->magic == XFS_ATTR_LEAF_MAGIC ||
               ichdr_s->magic == XFS_ATTR3_LEAF_MAGIC);
        ASSERT(ichdr_s->magic == ichdr_d->magic);
-       ASSERT(ichdr_s->count > 0 && ichdr_s->count < XFS_LBSIZE(mp) / 8);
+       ASSERT(ichdr_s->count > 0 && ichdr_s->count < args->geo->blksize / 8);
        ASSERT(ichdr_s->firstused >= (ichdr_s->count * sizeof(*entry_s))
                                        + xfs_attr3_leaf_hdr_size(leaf_s));
-       ASSERT(ichdr_d->count < XFS_LBSIZE(mp) / 8);
+       ASSERT(ichdr_d->count < args->geo->blksize / 8);
        ASSERT(ichdr_d->firstused >= (ichdr_d->count * sizeof(*entry_d))
                                        + xfs_attr3_leaf_hdr_size(leaf_d));
 
@@ -2304,11 +2300,11 @@ xfs_attr3_leaf_moveents(
                        entry_d->nameidx = cpu_to_be16(ichdr_d->firstused);
                        entry_d->flags = entry_s->flags;
                        ASSERT(be16_to_cpu(entry_d->nameidx) + tmp
-                                                       <= XFS_LBSIZE(mp));
+                                                       <= args->geo->blksize);
                        memmove(xfs_attr3_leaf_name(leaf_d, desti),
                                xfs_attr3_leaf_name(leaf_s, start_s + i), tmp);
                        ASSERT(be16_to_cpu(entry_s->nameidx) + tmp
-                                                       <= XFS_LBSIZE(mp));
+                                                       <= args->geo->blksize);
                        memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp);
                        ichdr_s->usedbytes -= tmp;
                        ichdr_d->usedbytes += tmp;
@@ -2329,7 +2325,7 @@ xfs_attr3_leaf_moveents(
                tmp = count * sizeof(xfs_attr_leaf_entry_t);
                entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s];
                ASSERT(((char *)entry_s + tmp) <=
-                      ((char *)leaf_s + XFS_LBSIZE(mp)));
+                      ((char *)leaf_s + args->geo->blksize));
                memset(entry_s, 0, tmp);
        } else {
                /*
@@ -2344,7 +2340,7 @@ xfs_attr3_leaf_moveents(
                tmp = count * sizeof(xfs_attr_leaf_entry_t);
                entry_s = &xfs_attr3_leaf_entryp(leaf_s)[ichdr_s->count];
                ASSERT(((char *)entry_s + tmp) <=
-                      ((char *)leaf_s + XFS_LBSIZE(mp)));
+                      ((char *)leaf_s + args->geo->blksize));
                memset(entry_s, 0, tmp);
        }
 
@@ -2412,22 +2408,21 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
  * a "local" or a "remote" attribute.
  */
 int
-xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local)
+xfs_attr_leaf_newentsize(
+       struct xfs_da_args      *args,
+       int                     *local)
 {
-       int size;
+       int                     size;
 
-       size = xfs_attr_leaf_entsize_local(namelen, valuelen);
-       if (size < xfs_attr_leaf_entsize_local_max(blocksize)) {
-               if (local) {
+       size = xfs_attr_leaf_entsize_local(args->namelen, args->valuelen);
+       if (size < xfs_attr_leaf_entsize_local_max(args->geo->blksize)) {
+               if (local)
                        *local = 1;
-               }
-       } else {
-               size = xfs_attr_leaf_entsize_remote(namelen);
-               if (local) {
-                       *local = 0;
-               }
+               return size;
        }
-       return size;
+       if (local)
+               *local = 0;
+       return xfs_attr_leaf_entsize_remote(args->namelen);
 }
 
 
@@ -2493,7 +2488,7 @@ xfs_attr3_leaf_clearflag(
                ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0);
                name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
                name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
-               name_rmt->valuelen = cpu_to_be32(args->valuelen);
+               name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen);
                xfs_trans_log_buf(args->trans, bp,
                         XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
        }
@@ -2651,7 +2646,7 @@ xfs_attr3_leaf_flipflags(
                ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0);
                name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index);
                name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
-               name_rmt->valuelen = cpu_to_be32(args->valuelen);
+               name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen);
                xfs_trans_log_buf(args->trans, bp1,
                         XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt)));
        }
index 08b983b8c66056fc9c1e221fdfbcb9a69d29129a..9e02685fdaa14b27977705e23439fb99ccdc2918 100644 (file)
@@ -43,7 +43,6 @@ xfs_attr3_rmt_blocks(
  */
 static bool
 xfs_attr3_rmt_hdr_ok(
-       struct xfs_mount        *mp,
        void                    *ptr,
        xfs_ino_t               ino,
        uint32_t                offset,
@@ -101,6 +100,7 @@ xfs_attr3_rmt_read_verify(
        char            *ptr;
        int             len;
        xfs_daddr_t     bno;
+       int             blksize = mp->m_attr_geo->blksize;
 
        /* no verification of non-crc buffers */
        if (!xfs_sb_version_hascrc(&mp->m_sb))
@@ -109,21 +109,20 @@ xfs_attr3_rmt_read_verify(
        ptr = bp->b_addr;
        bno = bp->b_bn;
        len = BBTOB(bp->b_length);
-       ASSERT(len >= XFS_LBSIZE(mp));
+       ASSERT(len >= blksize);
 
        while (len > 0) {
-               if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
-                                     XFS_ATTR3_RMT_CRC_OFF)) {
+               if (!xfs_verify_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF)) {
                        xfs_buf_ioerror(bp, EFSBADCRC);
                        break;
                }
-               if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
+               if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) {
                        xfs_buf_ioerror(bp, EFSCORRUPTED);
                        break;
                }
-               len -= XFS_LBSIZE(mp);
-               ptr += XFS_LBSIZE(mp);
-               bno += mp->m_bsize;
+               len -= blksize;
+               ptr += blksize;
+               bno += BTOBB(blksize);
        }
 
        if (bp->b_error)
@@ -141,6 +140,7 @@ xfs_attr3_rmt_write_verify(
        char            *ptr;
        int             len;
        xfs_daddr_t     bno;
+       int             blksize = mp->m_attr_geo->blksize;
 
        /* no verification of non-crc buffers */
        if (!xfs_sb_version_hascrc(&mp->m_sb))
@@ -149,10 +149,10 @@ xfs_attr3_rmt_write_verify(
        ptr = bp->b_addr;
        bno = bp->b_bn;
        len = BBTOB(bp->b_length);
-       ASSERT(len >= XFS_LBSIZE(mp));
+       ASSERT(len >= blksize);
 
        while (len > 0) {
-               if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
+               if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) {
                        xfs_buf_ioerror(bp, EFSCORRUPTED);
                        xfs_verifier_error(bp);
                        return;
@@ -163,11 +163,11 @@ xfs_attr3_rmt_write_verify(
                        rmt = (struct xfs_attr3_rmt_hdr *)ptr;
                        rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
                }
-               xfs_update_cksum(ptr, XFS_LBSIZE(mp), XFS_ATTR3_RMT_CRC_OFF);
+               xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF);
 
-               len -= XFS_LBSIZE(mp);
-               ptr += XFS_LBSIZE(mp);
-               bno += mp->m_bsize;
+               len -= blksize;
+               ptr += blksize;
+               bno += BTOBB(blksize);
        }
        ASSERT(len == 0);
 }
@@ -216,17 +216,18 @@ xfs_attr_rmtval_copyout(
        char            *src = bp->b_addr;
        xfs_daddr_t     bno = bp->b_bn;
        int             len = BBTOB(bp->b_length);
+       int             blksize = mp->m_attr_geo->blksize;
 
-       ASSERT(len >= XFS_LBSIZE(mp));
+       ASSERT(len >= blksize);
 
        while (len > 0 && *valuelen > 0) {
                int hdr_size = 0;
-               int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
+               int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize);
 
                byte_cnt = min(*valuelen, byte_cnt);
 
                if (xfs_sb_version_hascrc(&mp->m_sb)) {
-                       if (!xfs_attr3_rmt_hdr_ok(mp, src, ino, *offset,
+                       if (!xfs_attr3_rmt_hdr_ok(src, ino, *offset,
                                                  byte_cnt, bno)) {
                                xfs_alert(mp,
 "remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
@@ -239,9 +240,9 @@ xfs_attr_rmtval_copyout(
                memcpy(*dst, src + hdr_size, byte_cnt);
 
                /* roll buffer forwards */
-               len -= XFS_LBSIZE(mp);
-               src += XFS_LBSIZE(mp);
-               bno += mp->m_bsize;
+               len -= blksize;
+               src += blksize;
+               bno += BTOBB(blksize);
 
                /* roll attribute data forwards */
                *valuelen -= byte_cnt;
@@ -263,12 +264,13 @@ xfs_attr_rmtval_copyin(
        char            *dst = bp->b_addr;
        xfs_daddr_t     bno = bp->b_bn;
        int             len = BBTOB(bp->b_length);
+       int             blksize = mp->m_attr_geo->blksize;
 
-       ASSERT(len >= XFS_LBSIZE(mp));
+       ASSERT(len >= blksize);
 
        while (len > 0 && *valuelen > 0) {
                int hdr_size;
-               int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
+               int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize);
 
                byte_cnt = min(*valuelen, byte_cnt);
                hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset,
@@ -280,17 +282,17 @@ xfs_attr_rmtval_copyin(
                 * If this is the last block, zero the remainder of it.
                 * Check that we are actually the last block, too.
                 */
-               if (byte_cnt + hdr_size < XFS_LBSIZE(mp)) {
+               if (byte_cnt + hdr_size < blksize) {
                        ASSERT(*valuelen - byte_cnt == 0);
-                       ASSERT(len == XFS_LBSIZE(mp));
+                       ASSERT(len == blksize);
                        memset(dst + hdr_size + byte_cnt, 0,
-                                       XFS_LBSIZE(mp) - hdr_size - byte_cnt);
+                                       blksize - hdr_size - byte_cnt);
                }
 
                /* roll buffer forwards */
-               len -= XFS_LBSIZE(mp);
-               dst += XFS_LBSIZE(mp);
-               bno += mp->m_bsize;
+               len -= blksize;
+               dst += blksize;
+               bno += BTOBB(blksize);
 
                /* roll attribute data forwards */
                *valuelen -= byte_cnt;
@@ -312,7 +314,7 @@ xfs_attr_rmtval_get(
        struct xfs_buf          *bp;
        xfs_dablk_t             lblkno = args->rmtblkno;
        __uint8_t               *dst = args->value;
-       int                     valuelen = args->valuelen;
+       int                     valuelen;
        int                     nmap;
        int                     error;
        int                     blkcnt = args->rmtblkcnt;
@@ -322,7 +324,9 @@ xfs_attr_rmtval_get(
        trace_xfs_attr_rmtval_get(args);
 
        ASSERT(!(args->flags & ATTR_KERNOVAL));
+       ASSERT(args->rmtvaluelen == args->valuelen);
 
+       valuelen = args->rmtvaluelen;
        while (valuelen > 0) {
                nmap = ATTR_RMTVALUE_MAPSIZE;
                error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
@@ -390,7 +394,7 @@ xfs_attr_rmtval_set(
         * attributes have headers, we can't just do a straight byte to FSB
         * conversion and have to take the header space into account.
         */
-       blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
+       blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen);
        error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
                                                   XFS_ATTR_FORK);
        if (error)
@@ -455,7 +459,7 @@ xfs_attr_rmtval_set(
         */
        lblkno = args->rmtblkno;
        blkcnt = args->rmtblkcnt;
-       valuelen = args->valuelen;
+       valuelen = args->rmtvaluelen;
        while (valuelen > 0) {
                struct xfs_buf  *bp;
                xfs_daddr_t     dblkno;
index c45b91a2b6d28210242a662381763b413a845cff..c1fc5250a2b8143921307647a0d82522285fef33 100644 (file)
@@ -61,7 +61,7 @@ xfs_bmap_compute_maxlevels(
                maxleafents = MAXAEXTNUM;
                sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
        }
-       maxrootrecs = xfs_bmdr_maxrecs(mp, sz, 0);
+       maxrootrecs = xfs_bmdr_maxrecs(sz, 0);
        minleafrecs = mp->m_bmap_dmnr[0];
        minnoderecs = mp->m_bmap_dmnr[1];
        maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
@@ -200,7 +200,6 @@ xfs_default_attroffset(
  */
 STATIC void
 xfs_bmap_forkoff_reset(
-       xfs_mount_t     *mp,
        xfs_inode_t     *ip,
        int             whichfork)
 {
@@ -872,7 +871,7 @@ xfs_bmap_local_to_extents_empty(
        ASSERT(ifp->if_bytes == 0);
        ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
 
-       xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
+       xfs_bmap_forkoff_reset(ip, whichfork);
        ifp->if_flags &= ~XFS_IFINLINE;
        ifp->if_flags |= XFS_IFEXTENTS;
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
@@ -1066,10 +1065,11 @@ xfs_bmap_add_attrfork_local(
 
        if (S_ISDIR(ip->i_d.di_mode)) {
                memset(&dargs, 0, sizeof(dargs));
+               dargs.geo = ip->i_mount->m_dir_geo;
                dargs.dp = ip;
                dargs.firstblock = firstblock;
                dargs.flist = flist;
-               dargs.total = ip->i_mount->m_dirblkfsbs;
+               dargs.total = dargs.geo->fsbcount;
                dargs.whichfork = XFS_DATA_FORK;
                dargs.trans = tp;
                return xfs_dir2_sf_to_block(&dargs);
@@ -1104,6 +1104,7 @@ xfs_bmap_add_attrfork(
        int                     committed;      /* xaction was committed */
        int                     logflags;       /* logging flags */
        int                     error;          /* error return value */
+       int                     cancel_flags = 0;
 
        ASSERT(XFS_IFORK_Q(ip) == 0);
 
@@ -1114,19 +1115,20 @@ xfs_bmap_add_attrfork(
        if (rsvd)
                tp->t_flags |= XFS_TRANS_RESERVE;
        error = xfs_trans_reserve(tp, &M_RES(mp)->tr_addafork, blks, 0);
-       if (error)
-               goto error0;
+       if (error) {
+               xfs_trans_cancel(tp, 0);
+               return error;
+       }
+       cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
                        XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
                        XFS_QMOPT_RES_REGBLKS);
-       if (error) {
-               xfs_iunlock(ip, XFS_ILOCK_EXCL);
-               xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
-               return error;
-       }
+       if (error)
+               goto trans_cancel;
+       cancel_flags |= XFS_TRANS_ABORT;
        if (XFS_IFORK_Q(ip))
-               goto error1;
+               goto trans_cancel;
        if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
                /*
                 * For inodes coming from pre-6.2 filesystems.
@@ -1136,7 +1138,7 @@ xfs_bmap_add_attrfork(
        }
        ASSERT(ip->i_d.di_anextents == 0);
 
-       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, 0);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
        switch (ip->i_d.di_format) {
@@ -1158,7 +1160,7 @@ xfs_bmap_add_attrfork(
        default:
                ASSERT(0);
                error = XFS_ERROR(EINVAL);
-               goto error1;
+               goto trans_cancel;
        }
 
        ASSERT(ip->i_afp == NULL);
@@ -1186,7 +1188,7 @@ xfs_bmap_add_attrfork(
        if (logflags)
                xfs_trans_log_inode(tp, ip, logflags);
        if (error)
-               goto error2;
+               goto bmap_cancel;
        if (!xfs_sb_version_hasattr(&mp->m_sb) ||
           (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
                __int64_t sbfields = 0;
@@ -1209,14 +1211,16 @@ xfs_bmap_add_attrfork(
 
        error = xfs_bmap_finish(&tp, &flist, &committed);
        if (error)
-               goto error2;
-       return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-error2:
+               goto bmap_cancel;
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       return error;
+
+bmap_cancel:
        xfs_bmap_cancel(&flist);
-error1:
+trans_cancel:
+       xfs_trans_cancel(tp, cancel_flags);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
-error0:
-       xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
        return error;
 }
 
@@ -1598,7 +1602,7 @@ xfs_bmap_last_extent(
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
  * at, or past the EOF.
  */
 STATIC int
@@ -1613,9 +1617,14 @@ xfs_bmap_isaeof(
        bma->aeof = 0;
        error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
                                     &is_empty);
-       if (error || is_empty)
+       if (error)
                return error;
 
+       if (is_empty) {
+               bma->aeof = 1;
+               return 0;
+       }
+
        /*
         * Check if we are allocation or past the last extent, or at least into
         * the last delayed allocated extent.
@@ -1633,7 +1642,6 @@ xfs_bmap_isaeof(
  */
 int
 xfs_bmap_last_offset(
-       struct xfs_trans        *tp,
        struct xfs_inode        *ip,
        xfs_fileoff_t           *last_block,
        int                     whichfork)
@@ -3475,6 +3483,67 @@ xfs_bmap_adjacent(
 #undef ISVALID
 }
 
+static int
+xfs_bmap_longest_free_extent(
+       struct xfs_trans        *tp,
+       xfs_agnumber_t          ag,
+       xfs_extlen_t            *blen,
+       int                     *notinit)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_perag        *pag;
+       xfs_extlen_t            longest;
+       int                     error = 0;
+
+       pag = xfs_perag_get(mp, ag);
+       if (!pag->pagf_init) {
+               error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK);
+               if (error)
+                       goto out;
+
+               if (!pag->pagf_init) {
+                       *notinit = 1;
+                       goto out;
+               }
+       }
+
+       longest = xfs_alloc_longest_free_extent(mp, pag);
+       if (*blen < longest)
+               *blen = longest;
+
+out:
+       xfs_perag_put(pag);
+       return error;
+}
+
+static void
+xfs_bmap_select_minlen(
+       struct xfs_bmalloca     *ap,
+       struct xfs_alloc_arg    *args,
+       xfs_extlen_t            *blen,
+       int                     notinit)
+{
+       if (notinit || *blen < ap->minlen) {
+               /*
+                * Since we did a BUF_TRYLOCK above, it is possible that
+                * there is space for this request.
+                */
+               args->minlen = ap->minlen;
+       } else if (*blen < args->maxlen) {
+               /*
+                * If the best seen length is less than the request length,
+                * use the best as the minimum.
+                */
+               args->minlen = *blen;
+       } else {
+               /*
+                * Otherwise we've seen an extent as big as maxlen, use that
+                * as the minimum.
+                */
+               args->minlen = args->maxlen;
+       }
+}
+
 STATIC int
 xfs_bmap_btalloc_nullfb(
        struct xfs_bmalloca     *ap,
@@ -3482,111 +3551,74 @@ xfs_bmap_btalloc_nullfb(
        xfs_extlen_t            *blen)
 {
        struct xfs_mount        *mp = ap->ip->i_mount;
-       struct xfs_perag        *pag;
        xfs_agnumber_t          ag, startag;
        int                     notinit = 0;
        int                     error;
 
-       if (ap->userdata && xfs_inode_is_filestream(ap->ip))
-               args->type = XFS_ALLOCTYPE_NEAR_BNO;
-       else
-               args->type = XFS_ALLOCTYPE_START_BNO;
+       args->type = XFS_ALLOCTYPE_START_BNO;
        args->total = ap->total;
 
-       /*
-        * Search for an allocation group with a single extent large enough
-        * for the request.  If one isn't found, then adjust the minimum
-        * allocation size to the largest space found.
-        */
        startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
        if (startag == NULLAGNUMBER)
                startag = ag = 0;
 
-       pag = xfs_perag_get(mp, ag);
        while (*blen < args->maxlen) {
-               if (!pag->pagf_init) {
-                       error = xfs_alloc_pagf_init(mp, args->tp, ag,
-                                                   XFS_ALLOC_FLAG_TRYLOCK);
-                       if (error) {
-                               xfs_perag_put(pag);
-                               return error;
-                       }
-               }
-
-               /*
-                * See xfs_alloc_fix_freelist...
-                */
-               if (pag->pagf_init) {
-                       xfs_extlen_t    longest;
-                       longest = xfs_alloc_longest_free_extent(mp, pag);
-                       if (*blen < longest)
-                               *blen = longest;
-               } else
-                       notinit = 1;
-
-               if (xfs_inode_is_filestream(ap->ip)) {
-                       if (*blen >= args->maxlen)
-                               break;
-
-                       if (ap->userdata) {
-                               /*
-                                * If startag is an invalid AG, we've
-                                * come here once before and
-                                * xfs_filestream_new_ag picked the
-                                * best currently available.
-                                *
-                                * Don't continue looping, since we
-                                * could loop forever.
-                                */
-                               if (startag == NULLAGNUMBER)
-                                       break;
-
-                               error = xfs_filestream_new_ag(ap, &ag);
-                               xfs_perag_put(pag);
-                               if (error)
-                                       return error;
+               error = xfs_bmap_longest_free_extent(args->tp, ag, blen,
+                                                    &notinit);
+               if (error)
+                       return error;
 
-                               /* loop again to set 'blen'*/
-                               startag = NULLAGNUMBER;
-                               pag = xfs_perag_get(mp, ag);
-                               continue;
-                       }
-               }
                if (++ag == mp->m_sb.sb_agcount)
                        ag = 0;
                if (ag == startag)
                        break;
-               xfs_perag_put(pag);
-               pag = xfs_perag_get(mp, ag);
        }
-       xfs_perag_put(pag);
 
-       /*
-        * Since the above loop did a BUF_TRYLOCK, it is
-        * possible that there is space for this request.
-        */
-       if (notinit || *blen < ap->minlen)
-               args->minlen = ap->minlen;
-       /*
-        * If the best seen length is less than the request
-        * length, use the best as the minimum.
-        */
-       else if (*blen < args->maxlen)
-               args->minlen = *blen;
-       /*
-        * Otherwise we've seen an extent as big as maxlen,
-        * use that as the minimum.
-        */
-       else
-               args->minlen = args->maxlen;
+       xfs_bmap_select_minlen(ap, args, blen, notinit);
+       return 0;
+}
+
+STATIC int
+xfs_bmap_btalloc_filestreams(
+       struct xfs_bmalloca     *ap,
+       struct xfs_alloc_arg    *args,
+       xfs_extlen_t            *blen)
+{
+       struct xfs_mount        *mp = ap->ip->i_mount;
+       xfs_agnumber_t          ag;
+       int                     notinit = 0;
+       int                     error;
+
+       args->type = XFS_ALLOCTYPE_NEAR_BNO;
+       args->total = ap->total;
+
+       ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
+       if (ag == NULLAGNUMBER)
+               ag = 0;
+
+       error = xfs_bmap_longest_free_extent(args->tp, ag, blen, &notinit);
+       if (error)
+               return error;
+
+       if (*blen < args->maxlen) {
+               error = xfs_filestream_new_ag(ap, &ag);
+               if (error)
+                       return error;
+
+               error = xfs_bmap_longest_free_extent(args->tp, ag, blen,
+                                                    &notinit);
+               if (error)
+                       return error;
+
+       }
+
+       xfs_bmap_select_minlen(ap, args, blen, notinit);
 
        /*
-        * set the failure fallback case to look in the selected
-        * AG as the stream may have moved.
+        * Set the failure fallback case to look in the selected AG as stream
+        * may have moved.
         */
-       if (xfs_inode_is_filestream(ap->ip))
-               ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
-
+       ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
        return 0;
 }
 
@@ -3606,10 +3638,19 @@ xfs_bmap_btalloc(
        int             isaligned;
        int             tryagain;
        int             error;
+       int             stripe_align;
 
        ASSERT(ap->length);
 
        mp = ap->ip->i_mount;
+
+       /* stripe alignment for allocation is determined by mount parameters */
+       stripe_align = 0;
+       if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+               stripe_align = mp->m_swidth;
+       else if (mp->m_dalign)
+               stripe_align = mp->m_dalign;
+
        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
        if (unlikely(align)) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3618,6 +3659,8 @@ xfs_bmap_btalloc(
                ASSERT(!error);
                ASSERT(ap->length);
        }
+
+
        nullfb = *ap->firstblock == NULLFSBLOCK;
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
        if (nullfb) {
@@ -3655,7 +3698,15 @@ xfs_bmap_btalloc(
        args.firstblock = *ap->firstblock;
        blen = 0;
        if (nullfb) {
-               error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
+               /*
+                * Search for an allocation group with a single extent large
+                * enough for the request.  If one isn't found, then adjust
+                * the minimum allocation size to the largest space found.
+                */
+               if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+                       error = xfs_bmap_btalloc_filestreams(ap, &args, &blen);
+               else
+                       error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
                if (error)
                        return error;
        } else if (ap->flist->xbf_low) {
@@ -3693,7 +3744,7 @@ xfs_bmap_btalloc(
         */
        if (!ap->flist->xbf_low && ap->aeof) {
                if (!ap->offset) {
-                       args.alignment = mp->m_dalign;
+                       args.alignment = stripe_align;
                        atype = args.type;
                        isaligned = 1;
                        /*
@@ -3718,13 +3769,13 @@ xfs_bmap_btalloc(
                         * of minlen+alignment+slop doesn't go up
                         * between the calls.
                         */
-                       if (blen > mp->m_dalign && blen <= args.maxlen)
-                               nextminlen = blen - mp->m_dalign;
+                       if (blen > stripe_align && blen <= args.maxlen)
+                               nextminlen = blen - stripe_align;
                        else
                                nextminlen = args.minlen;
-                       if (nextminlen + mp->m_dalign > args.minlen + 1)
+                       if (nextminlen + stripe_align > args.minlen + 1)
                                args.minalignslop =
-                                       nextminlen + mp->m_dalign -
+                                       nextminlen + stripe_align -
                                        args.minlen - 1;
                        else
                                args.minalignslop = 0;
@@ -3746,7 +3797,7 @@ xfs_bmap_btalloc(
                 */
                args.type = atype;
                args.fsbno = ap->blkno;
-               args.alignment = mp->m_dalign;
+               args.alignment = stripe_align;
                args.minlen = nextminlen;
                args.minalignslop = 0;
                isaligned = 1;
@@ -3960,6 +4011,7 @@ xfs_bmapi_read(
        ASSERT(*nmap >= 1);
        ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE|
                           XFS_BMAPI_IGSTATE)));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED|XFS_ILOCK_EXCL));
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -4154,6 +4206,7 @@ xfs_bmapi_delay(
        ASSERT(*nmap >= 1);
        ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
        ASSERT(!(flags & ~XFS_BMAPI_ENTIRE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&
@@ -4212,8 +4265,8 @@ xfs_bmapi_delay(
 }
 
 
-int
-__xfs_bmapi_allocate(
+static int
+xfs_bmapi_allocate(
        struct xfs_bmalloca     *bma)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
@@ -4447,6 +4500,7 @@ xfs_bmapi_write(
        ASSERT(tp != NULL);
        ASSERT(len > 0);
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -4491,9 +4545,6 @@ xfs_bmapi_write(
        bma.flist = flist;
        bma.firstblock = firstblock;
 
-       if (flags & XFS_BMAPI_STACK_SWITCH)
-               bma.stack_switch = 1;
-
        while (bno < end && n < *nmap) {
                inhole = eof || bma.got.br_startoff > bno;
                wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
@@ -4998,6 +5049,7 @@ xfs_bunmapi(
        if (XFS_FORCED_SHUTDOWN(mp))
                return XFS_ERROR(EIO);
 
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(len > 0);
        ASSERT(nexts >= 0);
 
@@ -5321,3 +5373,201 @@ error0:
        }
        return error;
 }
+
+/*
+ * Shift extent records to the left to cover a hole.
+ *
+ * The maximum number of extents to be shifted in a single operation
+ * is @num_exts, and @current_ext keeps track of the current extent
+ * index we have shifted. @offset_shift_fsb is the length by which each
+ * extent is shifted. If there is no hole to shift the extents
+ * into, this will be considered invalid operation and we abort immediately.
+ */
+int
+xfs_bmap_shift_extents(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip,
+       int                     *done,
+       xfs_fileoff_t           start_fsb,
+       xfs_fileoff_t           offset_shift_fsb,
+       xfs_extnum_t            *current_ext,
+       xfs_fsblock_t           *firstblock,
+       struct xfs_bmap_free    *flist,
+       int                     num_exts)
+{
+       struct xfs_btree_cur            *cur;
+       struct xfs_bmbt_rec_host        *gotp;
+       struct xfs_bmbt_irec            got;
+       struct xfs_bmbt_irec            left;
+       struct xfs_mount                *mp = ip->i_mount;
+       struct xfs_ifork                *ifp;
+       xfs_extnum_t                    nexts = 0;
+       xfs_fileoff_t                   startoff;
+       int                             error = 0;
+       int                             i;
+       int                             whichfork = XFS_DATA_FORK;
+       int                             logflags;
+       xfs_filblks_t                   blockcount = 0;
+       int                             total_extents;
+
+       if (unlikely(XFS_TEST_ERROR(
+           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
+            mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+               XFS_ERROR_REPORT("xfs_bmap_shift_extents",
+                                XFS_ERRLEVEL_LOW, mp);
+               return XFS_ERROR(EFSCORRUPTED);
+       }
+
+       if (XFS_FORCED_SHUTDOWN(mp))
+               return XFS_ERROR(EIO);
+
+       ASSERT(current_ext != NULL);
+
+       ifp = XFS_IFORK_PTR(ip, whichfork);
+       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+               /* Read in all the extents */
+               error = xfs_iread_extents(tp, ip, whichfork);
+               if (error)
+                       return error;
+       }
+
+       /*
+        * If *current_ext is 0, we would need to lookup the extent
+        * from where we would start shifting and store it in gotp.
+        */
+       if (!*current_ext) {
+               gotp = xfs_iext_bno_to_ext(ifp, start_fsb, current_ext);
+               /*
+                * gotp can be null in 2 cases: 1) if there are no extents
+                * or 2) start_fsb lies in a hole beyond which there are
+                * no extents. Either way, we are done.
+                */
+               if (!gotp) {
+                       *done = 1;
+                       return 0;
+               }
+       }
+
+       /* We are going to change core inode */
+       logflags = XFS_ILOG_CORE;
+       if (ifp->if_flags & XFS_IFBROOT) {
+               cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
+               cur->bc_private.b.firstblock = *firstblock;
+               cur->bc_private.b.flist = flist;
+               cur->bc_private.b.flags = 0;
+       } else {
+               cur = NULL;
+               logflags |= XFS_ILOG_DEXT;
+       }
+
+       /*
+        * There may be delalloc extents in the data fork before the range we
+        * are collapsing out, so we cannot
+        * use the count of real extents here. Instead we have to calculate it
+        * from the incore fork.
+        */
+       total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+       while (nexts++ < num_exts && *current_ext < total_extents) {
+
+               gotp = xfs_iext_get_ext(ifp, *current_ext);
+               xfs_bmbt_get_all(gotp, &got);
+               startoff = got.br_startoff - offset_shift_fsb;
+
+               /*
+                * Before shifting extent into hole, make sure that the hole
+                * is large enough to accomodate the shift.
+                */
+               if (*current_ext) {
+                       xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
+                                               *current_ext - 1), &left);
+
+                       if (startoff < left.br_startoff + left.br_blockcount)
+                               error = XFS_ERROR(EINVAL);
+               } else if (offset_shift_fsb > got.br_startoff) {
+                       /*
+                        * When first extent is shifted, offset_shift_fsb
+                        * should be less than the stating offset of
+                        * the first extent.
+                        */
+                       error = XFS_ERROR(EINVAL);
+               }
+
+               if (error)
+                       goto del_cursor;
+
+               if (cur) {
+                       error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
+                                                  got.br_startblock,
+                                                  got.br_blockcount,
+                                                  &i);
+                       if (error)
+                               goto del_cursor;
+                       XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+               }
+
+               /* Check if we can merge 2 adjacent extents */
+               if (*current_ext &&
+                   left.br_startoff + left.br_blockcount == startoff &&
+                   left.br_startblock + left.br_blockcount ==
+                               got.br_startblock &&
+                   left.br_state == got.br_state &&
+                   left.br_blockcount + got.br_blockcount <= MAXEXTLEN) {
+                       blockcount = left.br_blockcount +
+                               got.br_blockcount;
+                       xfs_iext_remove(ip, *current_ext, 1, 0);
+                       if (cur) {
+                               error = xfs_btree_delete(cur, &i);
+                               if (error)
+                                       goto del_cursor;
+                               XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+                       }
+                       XFS_IFORK_NEXT_SET(ip, whichfork,
+                               XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+                       gotp = xfs_iext_get_ext(ifp, --*current_ext);
+                       xfs_bmbt_get_all(gotp, &got);
+
+                       /* Make cursor point to the extent we will update */
+                       if (cur) {
+                               error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
+                                                          got.br_startblock,
+                                                          got.br_blockcount,
+                                                          &i);
+                               if (error)
+                                       goto del_cursor;
+                               XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+                       }
+
+                       xfs_bmbt_set_blockcount(gotp, blockcount);
+                       got.br_blockcount = blockcount;
+               } else {
+                       /* We have to update the startoff */
+                       xfs_bmbt_set_startoff(gotp, startoff);
+                       got.br_startoff = startoff;
+               }
+
+               if (cur) {
+                       error = xfs_bmbt_update(cur, got.br_startoff,
+                                               got.br_startblock,
+                                               got.br_blockcount,
+                                               got.br_state);
+                       if (error)
+                               goto del_cursor;
+               }
+
+               (*current_ext)++;
+               total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+       }
+
+       /* Check if we are done */
+       if (*current_ext == total_extents)
+               *done = 1;
+
+del_cursor:
+       if (cur)
+               xfs_btree_del_cursor(cur,
+                       error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+
+       xfs_trans_log_inode(tp, ip, logflags);
+       return error;
+}
index a4bd69da2a1c9c1298d1591098dec3f6b2f88839..40a5ac3176f3d9c91d81a9a704824f1a6c4d4226 100644 (file)
@@ -63,7 +63,7 @@ xfs_bmdr_to_bmbt(
        rblock->bb_level = dblock->bb_level;
        ASSERT(be16_to_cpu(rblock->bb_level) > 0);
        rblock->bb_numrecs = dblock->bb_numrecs;
-       dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
+       dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
        fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
        tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
        fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
@@ -422,7 +422,7 @@ xfs_bmbt_to_bmdr(
        ASSERT(rblock->bb_level != 0);
        dblock->bb_level = rblock->bb_level;
        dblock->bb_numrecs = rblock->bb_numrecs;
-       dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
+       dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
        fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
        tkp = XFS_BMDR_KEY_ADDR(dblock, 1);
        fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
@@ -498,7 +498,6 @@ xfs_bmbt_alloc_block(
        struct xfs_btree_cur    *cur,
        union xfs_btree_ptr     *start,
        union xfs_btree_ptr     *new,
-       int                     length,
        int                     *stat)
 {
        xfs_alloc_arg_t         args;           /* block allocation args */
@@ -651,8 +650,7 @@ xfs_bmbt_get_dmaxrecs(
 {
        if (level != cur->bc_nlevels - 1)
                return cur->bc_mp->m_bmap_dmxr[level != 0];
-       return xfs_bmdr_maxrecs(cur->bc_mp, cur->bc_private.b.forksize,
-                               level == 0);
+       return xfs_bmdr_maxrecs(cur->bc_private.b.forksize, level == 0);
 }
 
 STATIC void
@@ -812,95 +810,6 @@ xfs_bmbt_recs_inorder(
 }
 #endif /* DEBUG */
 
-#ifdef XFS_BTREE_TRACE
-ktrace_t       *xfs_bmbt_trace_buf;
-
-STATIC void
-xfs_bmbt_trace_enter(
-       struct xfs_btree_cur    *cur,
-       const char              *func,
-       char                    *s,
-       int                     type,
-       int                     line,
-       __psunsigned_t          a0,
-       __psunsigned_t          a1,
-       __psunsigned_t          a2,
-       __psunsigned_t          a3,
-       __psunsigned_t          a4,
-       __psunsigned_t          a5,
-       __psunsigned_t          a6,
-       __psunsigned_t          a7,
-       __psunsigned_t          a8,
-       __psunsigned_t          a9,
-       __psunsigned_t          a10)
-{
-       struct xfs_inode        *ip = cur->bc_private.b.ip;
-       int                     whichfork = cur->bc_private.b.whichfork;
-
-       ktrace_enter(xfs_bmbt_trace_buf,
-               (void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
-               (void *)func, (void *)s, (void *)ip, (void *)cur,
-               (void *)a0, (void *)a1, (void *)a2, (void *)a3,
-               (void *)a4, (void *)a5, (void *)a6, (void *)a7,
-               (void *)a8, (void *)a9, (void *)a10);
-}
-
-STATIC void
-xfs_bmbt_trace_cursor(
-       struct xfs_btree_cur    *cur,
-       __uint32_t              *s0,
-       __uint64_t              *l0,
-       __uint64_t              *l1)
-{
-       struct xfs_bmbt_rec_host r;
-
-       xfs_bmbt_set_all(&r, &cur->bc_rec.b);
-
-       *s0 = (cur->bc_nlevels << 24) |
-             (cur->bc_private.b.flags << 16) |
-              cur->bc_private.b.allocated;
-       *l0 = r.l0;
-       *l1 = r.l1;
-}
-
-STATIC void
-xfs_bmbt_trace_key(
-       struct xfs_btree_cur    *cur,
-       union xfs_btree_key     *key,
-       __uint64_t              *l0,
-       __uint64_t              *l1)
-{
-       *l0 = be64_to_cpu(key->bmbt.br_startoff);
-       *l1 = 0;
-}
-
-STATIC void
-xfs_bmbt_trace_record(
-       struct xfs_btree_cur    *cur,
-       union xfs_btree_rec     *rec,
-       __uint64_t              *l0,
-       __uint64_t              *l1,
-       __uint64_t              *l2)
-{
-       struct xfs_bmbt_irec    irec;
-
-       xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
-       *l0 = irec.br_startoff;
-       *l1 = irec.br_startblock;
-       *l2 = irec.br_blockcount;
-}
-#endif /* XFS_BTREE_TRACE */
-
-/* Endian flipping versions of the bmbt extraction functions */
-void
-xfs_bmbt_disk_get_all(
-       xfs_bmbt_rec_t  *r,
-       xfs_bmbt_irec_t *s)
-{
-       __xfs_bmbt_get_all(get_unaligned_be64(&r->l0),
-                               get_unaligned_be64(&r->l1), s);
-}
-
 static const struct xfs_btree_ops xfs_bmbt_ops = {
        .rec_len                = sizeof(xfs_bmbt_rec_t),
        .key_len                = sizeof(xfs_bmbt_key_t),
@@ -922,13 +831,6 @@ static const struct xfs_btree_ops xfs_bmbt_ops = {
        .keys_inorder           = xfs_bmbt_keys_inorder,
        .recs_inorder           = xfs_bmbt_recs_inorder,
 #endif
-
-#ifdef XFS_BTREE_TRACE
-       .trace_enter            = xfs_bmbt_trace_enter,
-       .trace_cursor           = xfs_bmbt_trace_cursor,
-       .trace_key              = xfs_bmbt_trace_key,
-       .trace_record           = xfs_bmbt_trace_record,
-#endif
 };
 
 /*
@@ -989,7 +891,6 @@ xfs_bmbt_maxrecs(
  */
 int
 xfs_bmdr_maxrecs(
-       struct xfs_mount        *mp,
        int                     blocklen,
        int                     leaf)
 {
@@ -1001,7 +902,7 @@ xfs_bmdr_maxrecs(
 }
 
 /*
- * Change the owner of a btree format fork of the inode passed in. Change it to
+ * Change the owner of a btree format fork fo the inode passed in. Change it to
  * the owner of that is passed in so that we can change owners before or after
  * we switch forks between inodes. The operation that the caller is doing will
  * determine whether is needs to change owner before or after the switch.
index cc823f534c4b7980dc0d9cf71c72e3d49ed1a404..9d1dd1cb6699a9eee67776835b41354fc18f781a 100644 (file)
@@ -537,14 +537,11 @@ xfs_btree_get_bufl(
        xfs_fsblock_t   fsbno,          /* file system block number */
        uint            lock)           /* lock flags for get_buf */
 {
-       xfs_buf_t       *bp;            /* buffer pointer (return value) */
        xfs_daddr_t             d;              /* real disk block address */
 
        ASSERT(fsbno != NULLFSBLOCK);
        d = XFS_FSB_TO_DADDR(mp, fsbno);
-       bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
-       ASSERT(!xfs_buf_geterror(bp));
-       return bp;
+       return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
 }
 
 /*
@@ -559,15 +556,12 @@ xfs_btree_get_bufs(
        xfs_agblock_t   agbno,          /* allocation group block number */
        uint            lock)           /* lock flags for get_buf */
 {
-       xfs_buf_t       *bp;            /* buffer pointer (return value) */
        xfs_daddr_t             d;              /* real disk block address */
 
        ASSERT(agno != NULLAGNUMBER);
        ASSERT(agbno != NULLAGBLOCK);
        d = XFS_AGB_TO_DADDR(mp, agno, agbno);
-       bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
-       ASSERT(!xfs_buf_geterror(bp));
-       return bp;
+       return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
 }
 
 /*
@@ -707,7 +701,6 @@ xfs_btree_read_bufl(
                                   mp->m_bsize, lock, &bp, ops);
        if (error)
                return error;
-       ASSERT(!xfs_buf_geterror(bp));
        if (bp)
                xfs_buf_set_ref(bp, refval);
        *bpp = bp;
@@ -1145,7 +1138,6 @@ STATIC int
 xfs_btree_read_buf_block(
        struct xfs_btree_cur    *cur,
        union xfs_btree_ptr     *ptr,
-       int                     level,
        int                     flags,
        struct xfs_btree_block  **block,
        struct xfs_buf          **bpp)
@@ -1164,7 +1156,6 @@ xfs_btree_read_buf_block(
        if (error)
                return error;
 
-       ASSERT(!xfs_buf_geterror(*bpp));
        xfs_btree_set_refs(cur, *bpp);
        *block = XFS_BUF_TO_BLOCK(*bpp);
        return 0;
@@ -1503,8 +1494,8 @@ xfs_btree_increment(
                union xfs_btree_ptr     *ptrp;
 
                ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block);
-               error = xfs_btree_read_buf_block(cur, ptrp, --lev,
-                                                       0, &block, &bp);
+               --lev;
+               error = xfs_btree_read_buf_block(cur, ptrp, 0, &block, &bp);
                if (error)
                        goto error0;
 
@@ -1602,8 +1593,8 @@ xfs_btree_decrement(
                union xfs_btree_ptr     *ptrp;
 
                ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block);
-               error = xfs_btree_read_buf_block(cur, ptrp, --lev,
-                                                       0, &block, &bp);
+               --lev;
+               error = xfs_btree_read_buf_block(cur, ptrp, 0, &block, &bp);
                if (error)
                        goto error0;
                xfs_btree_setbuf(cur, lev, bp);
@@ -1653,7 +1644,7 @@ xfs_btree_lookup_get_block(
                return 0;
        }
 
-       error = xfs_btree_read_buf_block(cur, pp, level, 0, blkp, &bp);
+       error = xfs_btree_read_buf_block(cur, pp, 0, blkp, &bp);
        if (error)
                return error;
 
@@ -2004,7 +1995,7 @@ xfs_btree_lshift(
                goto out0;
 
        /* Set up the left neighbor as "left". */
-       error = xfs_btree_read_buf_block(cur, &lptr, level, 0, &left, &lbp);
+       error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp);
        if (error)
                goto error0;
 
@@ -2188,7 +2179,7 @@ xfs_btree_rshift(
                goto out0;
 
        /* Set up the right neighbor as "right". */
-       error = xfs_btree_read_buf_block(cur, &rptr, level, 0, &right, &rbp);
+       error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp);
        if (error)
                goto error0;
 
@@ -2316,7 +2307,7 @@ error1:
  * record (to be inserted into parent).
  */
 STATIC int                                     /* error */
-xfs_btree_split(
+__xfs_btree_split(
        struct xfs_btree_cur    *cur,
        int                     level,
        union xfs_btree_ptr     *ptrp,
@@ -2358,7 +2349,7 @@ xfs_btree_split(
        xfs_btree_buf_to_ptr(cur, lbp, &lptr);
 
        /* Allocate the new block. If we can't do it, we're toast. Give up. */
-       error = cur->bc_ops->alloc_block(cur, &lptr, &rptr, 1, stat);
+       error = cur->bc_ops->alloc_block(cur, &lptr, &rptr, stat);
        if (error)
                goto error0;
        if (*stat == 0)
@@ -2456,7 +2447,7 @@ xfs_btree_split(
         * point back to right instead of to left.
         */
        if (!xfs_btree_ptr_is_null(cur, &rrptr)) {
-               error = xfs_btree_read_buf_block(cur, &rrptr, level,
+               error = xfs_btree_read_buf_block(cur, &rrptr,
                                                        0, &rrblock, &rrbp);
                if (error)
                        goto error0;
@@ -2496,6 +2487,92 @@ error0:
        return error;
 }
 
+/* XXX: kernel only code here! */
+#ifdef KERNEL
+struct xfs_btree_split_args {
+       struct xfs_btree_cur    *cur;
+       int                     level;
+       union xfs_btree_ptr     *ptrp;
+       union xfs_btree_key     *key;
+       struct xfs_btree_cur    **curp;
+       int                     *stat;          /* success/failure */
+       int                     result;
+       bool                    kswapd; /* allocation in kswapd context */
+       struct completion       *done;
+       struct work_struct      work;
+};
+
+/*
+ * Stack switching interfaces for allocation
+ */
+static void
+xfs_btree_split_worker(
+       struct work_struct      *work)
+{
+       struct xfs_btree_split_args     *args = container_of(work,
+                                               struct xfs_btree_split_args, work);
+       unsigned long           pflags;
+       unsigned long           new_pflags = PF_FSTRANS;
+
+       /*
+        * we are in a transaction context here, but may also be doing work
+        * in kswapd context, and hence we may need to inherit that state
+        * temporarily to ensure that we don't block waiting for memory reclaim
+        * in any way.
+        */
+       if (args->kswapd)
+               new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+
+       current_set_flags_nested(&pflags, new_pflags);
+
+       args->result = __xfs_btree_split(args->cur, args->level, args->ptrp,
+                                        args->key, args->curp, args->stat);
+       complete(args->done);
+
+       current_restore_flags_nested(&pflags, new_pflags);
+}
+#endif
+
+/*
+ * BMBT split requests often come in with little stack to work on. Push
+ * them off to a worker thread so there is lots of stack to use. For the other
+ * btree types, just call directly to avoid the context switch overhead here.
+ */
+STATIC int                                     /* error */
+xfs_btree_split(
+       struct xfs_btree_cur    *cur,
+       int                     level,
+       union xfs_btree_ptr     *ptrp,
+       union xfs_btree_key     *key,
+       struct xfs_btree_cur    **curp,
+       int                     *stat)          /* success/failure */
+{
+#ifdef KERNEL
+       struct xfs_btree_split_args     args;
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       if (cur->bc_btnum != XFS_BTNUM_BMAP)
+#endif
+               return __xfs_btree_split(cur, level, ptrp, key, curp, stat);
+
+#ifdef KERNEL
+       args.cur = cur;
+       args.level = level;
+       args.ptrp = ptrp;
+       args.key = key;
+       args.curp = curp;
+       args.stat = stat;
+       args.done = &done;
+       args.kswapd = current_is_kswapd();
+       INIT_WORK_ONSTACK(&args.work, xfs_btree_split_worker);
+       queue_work(xfs_alloc_wq, &args.work);
+       wait_for_completion(&done);
+       destroy_work_on_stack(&args.work);
+       return args.result;
+#endif
+}
+
+
 /*
  * Copy the old inode root contents into a real block and make the
  * broot point to it.
@@ -2531,7 +2608,7 @@ xfs_btree_new_iroot(
        pp = xfs_btree_ptr_addr(cur, 1, block);
 
        /* Allocate the new block. If we can't do it, we're toast. Give up. */
-       error = cur->bc_ops->alloc_block(cur, pp, &nptr, 1, stat);
+       error = cur->bc_ops->alloc_block(cur, pp, &nptr, stat);
        if (error)
                goto error0;
        if (*stat == 0) {
@@ -2635,7 +2712,7 @@ xfs_btree_new_root(
        cur->bc_ops->init_ptr_from_cur(cur, &rptr);
 
        /* Allocate the new block. If we can't do it, we're toast. Give up. */
-       error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, 1, stat);
+       error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, stat);
        if (error)
                goto error0;
        if (*stat == 0)
@@ -2670,8 +2747,7 @@ xfs_btree_new_root(
                lbp = bp;
                xfs_btree_buf_to_ptr(cur, lbp, &lptr);
                left = block;
-               error = xfs_btree_read_buf_block(cur, &rptr,
-                                       cur->bc_nlevels - 1, 0, &right, &rbp);
+               error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp);
                if (error)
                        goto error0;
                bp = rbp;
@@ -2682,8 +2758,7 @@ xfs_btree_new_root(
                xfs_btree_buf_to_ptr(cur, rbp, &rptr);
                right = block;
                xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB);
-               error = xfs_btree_read_buf_block(cur, &lptr,
-                                       cur->bc_nlevels - 1, 0, &left, &lbp);
+               error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp);
                if (error)
                        goto error0;
                bp = lbp;
@@ -3635,8 +3710,7 @@ xfs_btree_delrec(
                rptr = cptr;
                right = block;
                rbp = bp;
-               error = xfs_btree_read_buf_block(cur, &lptr, level,
-                                                       0, &left, &lbp);
+               error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp);
                if (error)
                        goto error0;
 
@@ -3653,8 +3727,7 @@ xfs_btree_delrec(
                lptr = cptr;
                left = block;
                lbp = bp;
-               error = xfs_btree_read_buf_block(cur, &rptr, level,
-                                                       0, &right, &rbp);
+               error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp);
                if (error)
                        goto error0;
 
@@ -3726,8 +3799,7 @@ xfs_btree_delrec(
        /* If there is a right sibling, point it to the remaining block. */
        xfs_btree_get_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB);
        if (!xfs_btree_ptr_is_null(cur, &cptr)) {
-               error = xfs_btree_read_buf_block(cur, &cptr, level,
-                                                       0, &rrblock, &rrbp);
+               error = xfs_btree_read_buf_block(cur, &cptr, 0, &rrblock, &rrbp);
                if (error)
                        goto error0;
                xfs_btree_set_sibling(cur, rrblock, &lptr, XFS_BB_LEFTSIB);
index b731b5451f055c17ca8842cff9ba518444759de3..6237e9aa4b8bc0f997bfecbe046a4c76778bdd1e 100644 (file)
@@ -106,56 +106,6 @@ xfs_da_state_free(xfs_da_state_t *state)
        kmem_zone_free(xfs_da_state_zone, state);
 }
 
-void
-xfs_da3_node_hdr_from_disk(
-       struct xfs_da3_icnode_hdr       *to,
-       struct xfs_da_intnode           *from)
-{
-       ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) ||
-              from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC));
-
-       if (from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
-               struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from;
-
-               to->forw = be32_to_cpu(hdr3->info.hdr.forw);
-               to->back = be32_to_cpu(hdr3->info.hdr.back);
-               to->magic = be16_to_cpu(hdr3->info.hdr.magic);
-               to->count = be16_to_cpu(hdr3->__count);
-               to->level = be16_to_cpu(hdr3->__level);
-               return;
-       }
-       to->forw = be32_to_cpu(from->hdr.info.forw);
-       to->back = be32_to_cpu(from->hdr.info.back);
-       to->magic = be16_to_cpu(from->hdr.info.magic);
-       to->count = be16_to_cpu(from->hdr.__count);
-       to->level = be16_to_cpu(from->hdr.__level);
-}
-
-void
-xfs_da3_node_hdr_to_disk(
-       struct xfs_da_intnode           *to,
-       struct xfs_da3_icnode_hdr       *from)
-{
-       ASSERT(from->magic == XFS_DA_NODE_MAGIC ||
-              from->magic == XFS_DA3_NODE_MAGIC);
-
-       if (from->magic == XFS_DA3_NODE_MAGIC) {
-               struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to;
-
-               hdr3->info.hdr.forw = cpu_to_be32(from->forw);
-               hdr3->info.hdr.back = cpu_to_be32(from->back);
-               hdr3->info.hdr.magic = cpu_to_be16(from->magic);
-               hdr3->__count = cpu_to_be16(from->count);
-               hdr3->__level = cpu_to_be16(from->level);
-               return;
-       }
-       to->hdr.info.forw = cpu_to_be32(from->forw);
-       to->hdr.info.back = cpu_to_be32(from->back);
-       to->hdr.info.magic = cpu_to_be16(from->magic);
-       to->hdr.__count = cpu_to_be16(from->count);
-       to->hdr.__level = cpu_to_be16(from->level);
-}
-
 static bool
 xfs_da3_node_verify(
        struct xfs_buf          *bp)
@@ -163,8 +113,11 @@ xfs_da3_node_verify(
        struct xfs_mount        *mp = bp->b_target->bt_mount;
        struct xfs_da_intnode   *hdr = bp->b_addr;
        struct xfs_da3_icnode_hdr ichdr;
+       const struct xfs_dir_ops *ops;
+
+       ops = xfs_dir_get_ops(mp, NULL);
 
-       xfs_da3_node_hdr_from_disk(&ichdr, hdr);
+       ops->node_hdr_from_disk(&ichdr, hdr);
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
@@ -191,8 +144,8 @@ xfs_da3_node_verify(
         * we don't know if the node is for and attribute or directory tree,
         * so only fail if the count is outside both bounds
         */
-       if (ichdr.count > mp->m_dir_node_ents &&
-           ichdr.count > mp->m_attr_node_ents)
+       if (ichdr.count > mp->m_dir_geo->node_ents &&
+           ichdr.count > mp->m_attr_geo->node_ents)
                return false;
 
        /* XXX: hash order check? */
@@ -332,11 +285,12 @@ xfs_da3_node_create(
        struct xfs_da3_icnode_hdr ichdr = {0};
        struct xfs_buf          *bp;
        int                     error;
+       struct xfs_inode        *dp = args->dp;
 
        trace_xfs_da_node_create(args);
        ASSERT(level <= XFS_DA_NODE_MAXDEPTH);
 
-       error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
+       error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, whichfork);
        if (error)
                return(error);
        bp->b_ops = &xfs_da3_node_buf_ops;
@@ -355,9 +309,9 @@ xfs_da3_node_create(
        }
        ichdr.level = level;
 
-       xfs_da3_node_hdr_to_disk(node, &ichdr);
+       dp->d_ops->node_hdr_to_disk(node, &ichdr);
        xfs_trans_log_buf(tp, bp,
-               XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node)));
+               XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size));
 
        *bpp = bp;
        return(0);
@@ -567,8 +521,8 @@ xfs_da3_root_split(
            oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
                struct xfs_da3_icnode_hdr nodehdr;
 
-               xfs_da3_node_hdr_from_disk(&nodehdr, oldroot);
-               btree = xfs_da3_node_tree_p(oldroot);
+               dp->d_ops->node_hdr_from_disk(&nodehdr, oldroot);
+               btree = dp->d_ops->node_tree_p(oldroot);
                size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot);
                level = nodehdr.level;
 
@@ -582,8 +536,8 @@ xfs_da3_root_split(
                struct xfs_dir2_leaf_entry *ents;
 
                leaf = (xfs_dir2_leaf_t *)oldroot;
-               xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-               ents = xfs_dir3_leaf_ents_p(leaf);
+               dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+               ents = dp->d_ops->leaf_ents_p(leaf);
 
                ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
                       leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
@@ -621,28 +575,28 @@ xfs_da3_root_split(
         * Set up the new root node.
         */
        error = xfs_da3_node_create(args,
-               (args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0,
+               (args->whichfork == XFS_DATA_FORK) ? args->geo->leafblk : 0,
                level + 1, &bp, args->whichfork);
        if (error)
                return error;
 
        node = bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
-       btree = xfs_da3_node_tree_p(node);
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+       btree = dp->d_ops->node_tree_p(node);
        btree[0].hashval = cpu_to_be32(blk1->hashval);
        btree[0].before = cpu_to_be32(blk1->blkno);
        btree[1].hashval = cpu_to_be32(blk2->hashval);
        btree[1].before = cpu_to_be32(blk2->blkno);
        nodehdr.count = 2;
-       xfs_da3_node_hdr_to_disk(node, &nodehdr);
+       dp->d_ops->node_hdr_to_disk(node, &nodehdr);
 
 #ifdef DEBUG
        if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
            oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
-               ASSERT(blk1->blkno >= mp->m_dirleafblk &&
-                      blk1->blkno < mp->m_dirfreeblk);
-               ASSERT(blk2->blkno >= mp->m_dirleafblk &&
-                      blk2->blkno < mp->m_dirfreeblk);
+               ASSERT(blk1->blkno >= args->geo->leafblk &&
+                      blk1->blkno < args->geo->freeblk);
+               ASSERT(blk2->blkno >= args->geo->leafblk &&
+                      blk2->blkno < args->geo->freeblk);
        }
 #endif
 
@@ -671,11 +625,12 @@ xfs_da3_node_split(
        int                     newcount;
        int                     error;
        int                     useextra;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_node_split(state->args);
 
        node = oldblk->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
 
        /*
         * With V2 dirs the extra block is data or freespace.
@@ -685,7 +640,7 @@ xfs_da3_node_split(
        /*
         * Do we have to split the node?
         */
-       if (nodehdr.count + newcount > state->node_ents) {
+       if (nodehdr.count + newcount > state->args->geo->node_ents) {
                /*
                 * Allocate a new node, add to the doubly linked chain of
                 * nodes, then move some of our excess entries into it.
@@ -722,7 +677,7 @@ xfs_da3_node_split(
         * If we had double-split op below us, then add the extra block too.
         */
        node = oldblk->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
        if (oldblk->index <= nodehdr.count) {
                oldblk->index++;
                xfs_da3_node_add(state, oldblk, addblk);
@@ -771,15 +726,16 @@ xfs_da3_node_rebalance(
        int                     count;
        int                     tmp;
        int                     swap = 0;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_node_rebalance(state->args);
 
        node1 = blk1->bp->b_addr;
        node2 = blk2->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr1, node1);
-       xfs_da3_node_hdr_from_disk(&nodehdr2, node2);
-       btree1 = xfs_da3_node_tree_p(node1);
-       btree2 = xfs_da3_node_tree_p(node2);
+       dp->d_ops->node_hdr_from_disk(&nodehdr1, node1);
+       dp->d_ops->node_hdr_from_disk(&nodehdr2, node2);
+       btree1 = dp->d_ops->node_tree_p(node1);
+       btree2 = dp->d_ops->node_tree_p(node2);
 
        /*
         * Figure out how many entries need to move, and in which direction.
@@ -792,10 +748,10 @@ xfs_da3_node_rebalance(
                tmpnode = node1;
                node1 = node2;
                node2 = tmpnode;
-               xfs_da3_node_hdr_from_disk(&nodehdr1, node1);
-               xfs_da3_node_hdr_from_disk(&nodehdr2, node2);
-               btree1 = xfs_da3_node_tree_p(node1);
-               btree2 = xfs_da3_node_tree_p(node2);
+               dp->d_ops->node_hdr_from_disk(&nodehdr1, node1);
+               dp->d_ops->node_hdr_from_disk(&nodehdr2, node2);
+               btree1 = dp->d_ops->node_tree_p(node1);
+               btree2 = dp->d_ops->node_tree_p(node2);
                swap = 1;
        }
 
@@ -857,15 +813,14 @@ xfs_da3_node_rebalance(
        /*
         * Log header of node 1 and all current bits of node 2.
         */
-       xfs_da3_node_hdr_to_disk(node1, &nodehdr1);
+       dp->d_ops->node_hdr_to_disk(node1, &nodehdr1);
        xfs_trans_log_buf(tp, blk1->bp,
-               XFS_DA_LOGRANGE(node1, &node1->hdr,
-                               xfs_da3_node_hdr_size(node1)));
+               XFS_DA_LOGRANGE(node1, &node1->hdr, dp->d_ops->node_hdr_size));
 
-       xfs_da3_node_hdr_to_disk(node2, &nodehdr2);
+       dp->d_ops->node_hdr_to_disk(node2, &nodehdr2);
        xfs_trans_log_buf(tp, blk2->bp,
                XFS_DA_LOGRANGE(node2, &node2->hdr,
-                               xfs_da3_node_hdr_size(node2) +
+                               dp->d_ops->node_hdr_size +
                                (sizeof(btree2[0]) * nodehdr2.count)));
 
        /*
@@ -875,10 +830,10 @@ xfs_da3_node_rebalance(
        if (swap) {
                node1 = blk1->bp->b_addr;
                node2 = blk2->bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&nodehdr1, node1);
-               xfs_da3_node_hdr_from_disk(&nodehdr2, node2);
-               btree1 = xfs_da3_node_tree_p(node1);
-               btree2 = xfs_da3_node_tree_p(node2);
+               dp->d_ops->node_hdr_from_disk(&nodehdr1, node1);
+               dp->d_ops->node_hdr_from_disk(&nodehdr2, node2);
+               btree1 = dp->d_ops->node_tree_p(node1);
+               btree2 = dp->d_ops->node_tree_p(node2);
        }
        blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval);
        blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval);
@@ -905,18 +860,19 @@ xfs_da3_node_add(
        struct xfs_da3_icnode_hdr nodehdr;
        struct xfs_da_node_entry *btree;
        int                     tmp;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_node_add(state->args);
 
        node = oldblk->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
-       btree = xfs_da3_node_tree_p(node);
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+       btree = dp->d_ops->node_tree_p(node);
 
        ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count);
        ASSERT(newblk->blkno != 0);
        if (state->args->whichfork == XFS_DATA_FORK)
-               ASSERT(newblk->blkno >= state->mp->m_dirleafblk &&
-                      newblk->blkno < state->mp->m_dirfreeblk);
+               ASSERT(newblk->blkno >= state->args->geo->leafblk &&
+                      newblk->blkno < state->args->geo->freeblk);
 
        /*
         * We may need to make some room before we insert the new node.
@@ -933,9 +889,9 @@ xfs_da3_node_add(
                                tmp + sizeof(*btree)));
 
        nodehdr.count += 1;
-       xfs_da3_node_hdr_to_disk(node, &nodehdr);
+       dp->d_ops->node_hdr_to_disk(node, &nodehdr);
        xfs_trans_log_buf(state->args->trans, oldblk->bp,
-               XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node)));
+               XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size));
 
        /*
         * Copy the last hash value from the oldblk to propagate upwards.
@@ -1072,6 +1028,7 @@ xfs_da3_root_join(
        struct xfs_da3_icnode_hdr oldroothdr;
        struct xfs_da_node_entry *btree;
        int                     error;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_root_join(state->args);
 
@@ -1079,7 +1036,7 @@ xfs_da3_root_join(
 
        args = state->args;
        oldroot = root_blk->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&oldroothdr, oldroot);
+       dp->d_ops->node_hdr_from_disk(&oldroothdr, oldroot);
        ASSERT(oldroothdr.forw == 0);
        ASSERT(oldroothdr.back == 0);
 
@@ -1093,10 +1050,10 @@ xfs_da3_root_join(
         * Read in the (only) child block, then copy those bytes into
         * the root block's buffer and free the original child block.
         */
-       btree = xfs_da3_node_tree_p(oldroot);
+       btree = dp->d_ops->node_tree_p(oldroot);
        child = be32_to_cpu(btree[0].before);
        ASSERT(child != 0);
-       error = xfs_da3_node_read(args->trans, args->dp, child, -1, &bp,
+       error = xfs_da3_node_read(args->trans, dp, child, -1, &bp,
                                             args->whichfork);
        if (error)
                return error;
@@ -1109,14 +1066,15 @@ xfs_da3_root_join(
         * that could occur. For dir3 blocks we also need to update the block
         * number in the buffer header.
         */
-       memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize);
+       memcpy(root_blk->bp->b_addr, bp->b_addr, args->geo->blksize);
        root_blk->bp->b_ops = bp->b_ops;
        xfs_trans_buf_copy_type(root_blk->bp, bp);
        if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) {
                struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr;
                da3->blkno = cpu_to_be64(root_blk->bp->b_bn);
        }
-       xfs_trans_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
+       xfs_trans_log_buf(args->trans, root_blk->bp, 0,
+                         args->geo->blksize - 1);
        error = xfs_da_shrink_inode(args, child, bp);
        return(error);
 }
@@ -1146,6 +1104,7 @@ xfs_da3_node_toosmall(
        int                     error;
        int                     retval;
        int                     i;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_node_toosmall(state->args);
 
@@ -1157,8 +1116,8 @@ xfs_da3_node_toosmall(
        blk = &state->path.blk[ state->path.active-1 ];
        info = blk->bp->b_addr;
        node = (xfs_da_intnode_t *)info;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
-       if (nodehdr.count > (state->node_ents >> 1)) {
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+       if (nodehdr.count > (state->args->geo->node_ents >> 1)) {
                *action = 0;    /* blk over 50%, don't try to join */
                return(0);      /* blk over 50%, don't try to join */
        }
@@ -1195,8 +1154,8 @@ xfs_da3_node_toosmall(
         * We prefer coalescing with the lower numbered sibling so as
         * to shrink a directory over time.
         */
-       count  = state->node_ents;
-       count -= state->node_ents >> 2;
+       count  = state->args->geo->node_ents;
+       count -= state->args->geo->node_ents >> 2;
        count -= nodehdr.count;
 
        /* start with smaller blk num */
@@ -1209,13 +1168,13 @@ xfs_da3_node_toosmall(
                        blkno = nodehdr.back;
                if (blkno == 0)
                        continue;
-               error = xfs_da3_node_read(state->args->trans, state->args->dp,
+               error = xfs_da3_node_read(state->args->trans, dp,
                                        blkno, -1, &bp, state->args->whichfork);
                if (error)
                        return(error);
 
                node = bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&thdr, node);
+               dp->d_ops->node_hdr_from_disk(&thdr, node);
                xfs_trans_brelse(state->args->trans, bp);
 
                if (count - thdr.count >= 0)
@@ -1253,6 +1212,7 @@ xfs_da3_node_toosmall(
  */
 STATIC uint
 xfs_da3_node_lasthash(
+       struct xfs_inode        *dp,
        struct xfs_buf          *bp,
        int                     *count)
 {
@@ -1261,12 +1221,12 @@ xfs_da3_node_lasthash(
        struct xfs_da3_icnode_hdr nodehdr;
 
        node = bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
        if (count)
                *count = nodehdr.count;
        if (!nodehdr.count)
                return 0;
-       btree = xfs_da3_node_tree_p(node);
+       btree = dp->d_ops->node_tree_p(node);
        return be32_to_cpu(btree[nodehdr.count - 1].hashval);
 }
 
@@ -1285,6 +1245,7 @@ xfs_da3_fixhashpath(
        xfs_dahash_t            lasthash=0;
        int                     level;
        int                     count;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_fixhashpath(state->args);
 
@@ -1297,12 +1258,12 @@ xfs_da3_fixhashpath(
                        return;
                break;
        case XFS_DIR2_LEAFN_MAGIC:
-               lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count);
+               lasthash = xfs_dir2_leafn_lasthash(dp, blk->bp, &count);
                if (count == 0)
                        return;
                break;
        case XFS_DA_NODE_MAGIC:
-               lasthash = xfs_da3_node_lasthash(blk->bp, &count);
+               lasthash = xfs_da3_node_lasthash(dp, blk->bp, &count);
                if (count == 0)
                        return;
                break;
@@ -1311,8 +1272,8 @@ xfs_da3_fixhashpath(
                struct xfs_da3_icnode_hdr nodehdr;
 
                node = blk->bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
-               btree = xfs_da3_node_tree_p(node);
+               dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+               btree = dp->d_ops->node_tree_p(node);
                if (be32_to_cpu(btree[blk->index].hashval) == lasthash)
                        break;
                blk->hashval = lasthash;
@@ -1338,11 +1299,12 @@ xfs_da3_node_remove(
        struct xfs_da_node_entry *btree;
        int                     index;
        int                     tmp;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_node_remove(state->args);
 
        node = drop_blk->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
        ASSERT(drop_blk->index < nodehdr.count);
        ASSERT(drop_blk->index >= 0);
 
@@ -1350,7 +1312,7 @@ xfs_da3_node_remove(
         * Copy over the offending entry, or just zero it out.
         */
        index = drop_blk->index;
-       btree = xfs_da3_node_tree_p(node);
+       btree = dp->d_ops->node_tree_p(node);
        if (index < nodehdr.count - 1) {
                tmp  = nodehdr.count - index - 1;
                tmp *= (uint)sizeof(xfs_da_node_entry_t);
@@ -1363,9 +1325,9 @@ xfs_da3_node_remove(
        xfs_trans_log_buf(state->args->trans, drop_blk->bp,
            XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index])));
        nodehdr.count -= 1;
-       xfs_da3_node_hdr_to_disk(node, &nodehdr);
+       dp->d_ops->node_hdr_to_disk(node, &nodehdr);
        xfs_trans_log_buf(state->args->trans, drop_blk->bp,
-           XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node)));
+           XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size));
 
        /*
         * Copy the last hash value from the block to propagate upwards.
@@ -1392,15 +1354,16 @@ xfs_da3_node_unbalance(
        struct xfs_trans        *tp;
        int                     sindex;
        int                     tmp;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_node_unbalance(state->args);
 
        drop_node = drop_blk->bp->b_addr;
        save_node = save_blk->bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&drop_hdr, drop_node);
-       xfs_da3_node_hdr_from_disk(&save_hdr, save_node);
-       drop_btree = xfs_da3_node_tree_p(drop_node);
-       save_btree = xfs_da3_node_tree_p(save_node);
+       dp->d_ops->node_hdr_from_disk(&drop_hdr, drop_node);
+       dp->d_ops->node_hdr_from_disk(&save_hdr, save_node);
+       drop_btree = dp->d_ops->node_tree_p(drop_node);
+       save_btree = dp->d_ops->node_tree_p(save_node);
        tp = state->args->trans;
 
        /*
@@ -1434,10 +1397,10 @@ xfs_da3_node_unbalance(
        memcpy(&save_btree[sindex], &drop_btree[0], tmp);
        save_hdr.count += drop_hdr.count;
 
-       xfs_da3_node_hdr_to_disk(save_node, &save_hdr);
+       dp->d_ops->node_hdr_to_disk(save_node, &save_hdr);
        xfs_trans_log_buf(tp, save_blk->bp,
                XFS_DA_LOGRANGE(save_node, &save_node->hdr,
-                               xfs_da3_node_hdr_size(save_node)));
+                               dp->d_ops->node_hdr_size));
 
        /*
         * Save the last hashval in the remaining block for upward propagation.
@@ -1479,6 +1442,7 @@ xfs_da3_node_lookup_int(
        int                     max;
        int                     error;
        int                     retval;
+       struct xfs_inode        *dp = state->args->dp;
 
        args = state->args;
 
@@ -1486,7 +1450,7 @@ xfs_da3_node_lookup_int(
         * Descend thru the B-tree searching each level for the right
         * node to use, until the right hashval is found.
         */
-       blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0;
+       blkno = (args->whichfork == XFS_DATA_FORK)? args->geo->leafblk : 0;
        for (blk = &state->path.blk[0], state->path.active = 1;
                         state->path.active <= XFS_DA_NODE_MAXDEPTH;
                         blk++, state->path.active++) {
@@ -1514,7 +1478,8 @@ xfs_da3_node_lookup_int(
                if (blk->magic == XFS_DIR2_LEAFN_MAGIC ||
                    blk->magic == XFS_DIR3_LEAFN_MAGIC) {
                        blk->magic = XFS_DIR2_LEAFN_MAGIC;
-                       blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
+                       blk->hashval = xfs_dir2_leafn_lasthash(args->dp,
+                                                              blk->bp, NULL);
                        break;
                }
 
@@ -1525,8 +1490,8 @@ xfs_da3_node_lookup_int(
                 * Search an intermediate node for a match.
                 */
                node = blk->bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
-               btree = xfs_da3_node_tree_p(node);
+               dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+               btree = dp->d_ops->node_tree_p(node);
 
                max = nodehdr.count;
                blk->hashval = be32_to_cpu(btree[max - 1].hashval);
@@ -1621,6 +1586,7 @@ xfs_da3_node_lookup_int(
  */
 STATIC int
 xfs_da3_node_order(
+       struct xfs_inode *dp,
        struct xfs_buf  *node1_bp,
        struct xfs_buf  *node2_bp)
 {
@@ -1633,10 +1599,10 @@ xfs_da3_node_order(
 
        node1 = node1_bp->b_addr;
        node2 = node2_bp->b_addr;
-       xfs_da3_node_hdr_from_disk(&node1hdr, node1);
-       xfs_da3_node_hdr_from_disk(&node2hdr, node2);
-       btree1 = xfs_da3_node_tree_p(node1);
-       btree2 = xfs_da3_node_tree_p(node2);
+       dp->d_ops->node_hdr_from_disk(&node1hdr, node1);
+       dp->d_ops->node_hdr_from_disk(&node2hdr, node2);
+       btree1 = dp->d_ops->node_tree_p(node1);
+       btree2 = dp->d_ops->node_tree_p(node2);
 
        if (node1hdr.count > 0 && node2hdr.count > 0 &&
            ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) ||
@@ -1663,6 +1629,7 @@ xfs_da3_blk_link(
        struct xfs_buf          *bp;
        int                     before = 0;
        int                     error;
+       struct xfs_inode        *dp = state->args->dp;
 
        /*
         * Set up environment.
@@ -1680,10 +1647,10 @@ xfs_da3_blk_link(
                before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
                break;
        case XFS_DIR2_LEAFN_MAGIC:
-               before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp);
+               before = xfs_dir2_leafn_order(dp, old_blk->bp, new_blk->bp);
                break;
        case XFS_DA_NODE_MAGIC:
-               before = xfs_da3_node_order(old_blk->bp, new_blk->bp);
+               before = xfs_da3_node_order(dp, old_blk->bp, new_blk->bp);
                break;
        }
 
@@ -1698,7 +1665,7 @@ xfs_da3_blk_link(
                new_info->forw = cpu_to_be32(old_blk->blkno);
                new_info->back = old_info->back;
                if (old_info->back) {
-                       error = xfs_da3_node_read(args->trans, args->dp,
+                       error = xfs_da3_node_read(args->trans, dp,
                                                be32_to_cpu(old_info->back),
                                                -1, &bp, args->whichfork);
                        if (error)
@@ -1719,7 +1686,7 @@ xfs_da3_blk_link(
                new_info->forw = old_info->forw;
                new_info->back = cpu_to_be32(old_blk->blkno);
                if (old_info->forw) {
-                       error = xfs_da3_node_read(args->trans, args->dp,
+                       error = xfs_da3_node_read(args->trans, dp,
                                                be32_to_cpu(old_info->forw),
                                                -1, &bp, args->whichfork);
                        if (error)
@@ -1839,6 +1806,7 @@ xfs_da3_path_shift(
        xfs_dablk_t             blkno = 0;
        int                     level;
        int                     error;
+       struct xfs_inode        *dp = state->args->dp;
 
        trace_xfs_da_path_shift(state->args);
 
@@ -1854,8 +1822,8 @@ xfs_da3_path_shift(
        level = (path->active-1) - 1;   /* skip bottom layer in path */
        for (blk = &path->blk[level]; level >= 0; blk--, level--) {
                node = blk->bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
-               btree = xfs_da3_node_tree_p(node);
+               dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+               btree = dp->d_ops->node_tree_p(node);
 
                if (forward && (blk->index < nodehdr.count - 1)) {
                        blk->index++;
@@ -1889,7 +1857,7 @@ xfs_da3_path_shift(
                 * Read the next child block.
                 */
                blk->blkno = blkno;
-               error = xfs_da3_node_read(args->trans, args->dp, blkno, -1,
+               error = xfs_da3_node_read(args->trans, dp, blkno, -1,
                                        &blk->bp, args->whichfork);
                if (error)
                        return(error);
@@ -1911,8 +1879,8 @@ xfs_da3_path_shift(
                case XFS_DA3_NODE_MAGIC:
                        blk->magic = XFS_DA_NODE_MAGIC;
                        node = (xfs_da_intnode_t *)info;
-                       xfs_da3_node_hdr_from_disk(&nodehdr, node);
-                       btree = xfs_da3_node_tree_p(node);
+                       dp->d_ops->node_hdr_from_disk(&nodehdr, node);
+                       btree = dp->d_ops->node_tree_p(node);
                        blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval);
                        if (forward)
                                blk->index = 0;
@@ -1925,16 +1893,15 @@ xfs_da3_path_shift(
                        blk->magic = XFS_ATTR_LEAF_MAGIC;
                        ASSERT(level == path->active-1);
                        blk->index = 0;
-                       blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
-                                                             NULL);
+                       blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
                        break;
                case XFS_DIR2_LEAFN_MAGIC:
                case XFS_DIR3_LEAFN_MAGIC:
                        blk->magic = XFS_DIR2_LEAFN_MAGIC;
                        ASSERT(level == path->active-1);
                        blk->index = 0;
-                       blk->hashval = xfs_dir2_leafn_lasthash(blk->bp,
-                                                              NULL);
+                       blk->hashval = xfs_dir2_leafn_lasthash(args->dp,
+                                                              blk->bp, NULL);
                        break;
                default:
                        ASSERT(0);
@@ -2101,20 +2068,12 @@ xfs_da_grow_inode(
        xfs_dablk_t             *new_blkno)
 {
        xfs_fileoff_t           bno;
-       int                     count;
        int                     error;
 
        trace_xfs_da_grow_inode(args);
 
-       if (args->whichfork == XFS_DATA_FORK) {
-               bno = args->dp->i_mount->m_dirleafblk;
-               count = args->dp->i_mount->m_dirblkfsbs;
-       } else {
-               bno = 0;
-               count = 1;
-       }
-
-       error = xfs_da_grow_inode_int(args, &bno, count);
+       bno = args->geo->leafblk;
+       error = xfs_da_grow_inode_int(args, &bno, args->geo->fsbcount);
        if (!error)
                *new_blkno = (xfs_dablk_t)bno;
        return error;
@@ -2141,7 +2100,7 @@ xfs_da3_swap_lastblock(
        struct xfs_dir2_leaf    *dead_leaf2;
        struct xfs_da_node_entry *btree;
        struct xfs_da3_icnode_hdr par_hdr;
-       struct xfs_inode        *ip;
+       struct xfs_inode        *dp;
        struct xfs_trans        *tp;
        struct xfs_mount        *mp;
        struct xfs_buf          *dead_buf;
@@ -2165,12 +2124,12 @@ xfs_da3_swap_lastblock(
        dead_buf = *dead_bufp;
        dead_blkno = *dead_blknop;
        tp = args->trans;
-       ip = args->dp;
+       dp = args->dp;
        w = args->whichfork;
        ASSERT(w == XFS_DATA_FORK);
-       mp = ip->i_mount;
-       lastoff = mp->m_dirfreeblk;
-       error = xfs_bmap_last_before(tp, ip, &lastoff, w);
+       mp = dp->i_mount;
+       lastoff = args->geo->freeblk;
+       error = xfs_bmap_last_before(tp, dp, &lastoff, w);
        if (error)
                return error;
        if (unlikely(lastoff == 0)) {
@@ -2181,15 +2140,15 @@ xfs_da3_swap_lastblock(
        /*
         * Read the last block in the btree space.
         */
-       last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs;
-       error = xfs_da3_node_read(tp, ip, last_blkno, -1, &last_buf, w);
+       last_blkno = (xfs_dablk_t)lastoff - args->geo->fsbcount;
+       error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w);
        if (error)
                return error;
        /*
         * Copy the last block into the dead buffer and log it.
         */
-       memcpy(dead_buf->b_addr, last_buf->b_addr, mp->m_dirblksize);
-       xfs_trans_log_buf(tp, dead_buf, 0, mp->m_dirblksize - 1);
+       memcpy(dead_buf->b_addr, last_buf->b_addr, args->geo->blksize);
+       xfs_trans_log_buf(tp, dead_buf, 0, args->geo->blksize - 1);
        dead_info = dead_buf->b_addr;
        /*
         * Get values from the moved block.
@@ -2200,16 +2159,16 @@ xfs_da3_swap_lastblock(
                struct xfs_dir2_leaf_entry *ents;
 
                dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
-               xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2);
-               ents = xfs_dir3_leaf_ents_p(dead_leaf2);
+               dp->d_ops->leaf_hdr_from_disk(&leafhdr, dead_leaf2);
+               ents = dp->d_ops->leaf_ents_p(dead_leaf2);
                dead_level = 0;
                dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval);
        } else {
                struct xfs_da3_icnode_hdr deadhdr;
 
                dead_node = (xfs_da_intnode_t *)dead_info;
-               xfs_da3_node_hdr_from_disk(&deadhdr, dead_node);
-               btree = xfs_da3_node_tree_p(dead_node);
+               dp->d_ops->node_hdr_from_disk(&deadhdr, dead_node);
+               btree = dp->d_ops->node_tree_p(dead_node);
                dead_level = deadhdr.level;
                dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval);
        }
@@ -2218,7 +2177,7 @@ xfs_da3_swap_lastblock(
         * If the moved block has a left sibling, fix up the pointers.
         */
        if ((sib_blkno = be32_to_cpu(dead_info->back))) {
-               error = xfs_da3_node_read(tp, ip, sib_blkno, -1, &sib_buf, w);
+               error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w);
                if (error)
                        goto done;
                sib_info = sib_buf->b_addr;
@@ -2240,7 +2199,7 @@ xfs_da3_swap_lastblock(
         * If the moved block has a right sibling, fix up the pointers.
         */
        if ((sib_blkno = be32_to_cpu(dead_info->forw))) {
-               error = xfs_da3_node_read(tp, ip, sib_blkno, -1, &sib_buf, w);
+               error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w);
                if (error)
                        goto done;
                sib_info = sib_buf->b_addr;
@@ -2258,17 +2217,17 @@ xfs_da3_swap_lastblock(
                                        sizeof(sib_info->back)));
                sib_buf = NULL;
        }
-       par_blkno = mp->m_dirleafblk;
+       par_blkno = args->geo->leafblk;
        level = -1;
        /*
         * Walk down the tree looking for the parent of the moved block.
         */
        for (;;) {
-               error = xfs_da3_node_read(tp, ip, par_blkno, -1, &par_buf, w);
+               error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w);
                if (error)
                        goto done;
                par_node = par_buf->b_addr;
-               xfs_da3_node_hdr_from_disk(&par_hdr, par_node);
+               dp->d_ops->node_hdr_from_disk(&par_hdr, par_node);
                if (level >= 0 && level != par_hdr.level + 1) {
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
                                         XFS_ERRLEVEL_LOW, mp);
@@ -2276,7 +2235,7 @@ xfs_da3_swap_lastblock(
                        goto done;
                }
                level = par_hdr.level;
-               btree = xfs_da3_node_tree_p(par_node);
+               btree = dp->d_ops->node_tree_p(par_node);
                for (entno = 0;
                     entno < par_hdr.count &&
                     be32_to_cpu(btree[entno].hashval) < dead_hash;
@@ -2315,18 +2274,18 @@ xfs_da3_swap_lastblock(
                        error = XFS_ERROR(EFSCORRUPTED);
                        goto done;
                }
-               error = xfs_da3_node_read(tp, ip, par_blkno, -1, &par_buf, w);
+               error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w);
                if (error)
                        goto done;
                par_node = par_buf->b_addr;
-               xfs_da3_node_hdr_from_disk(&par_hdr, par_node);
+               dp->d_ops->node_hdr_from_disk(&par_hdr, par_node);
                if (par_hdr.level != level) {
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
                                         XFS_ERRLEVEL_LOW, mp);
                        error = XFS_ERROR(EFSCORRUPTED);
                        goto done;
                }
-               btree = xfs_da3_node_tree_p(par_node);
+               btree = dp->d_ops->node_tree_p(par_node);
                entno = 0;
        }
        /*
@@ -2368,10 +2327,7 @@ xfs_da_shrink_inode(
        w = args->whichfork;
        tp = args->trans;
        mp = dp->i_mount;
-       if (w == XFS_DATA_FORK)
-               count = mp->m_dirblkfsbs;
-       else
-               count = 1;
+       count = args->geo->fsbcount;
        for (;;) {
                /*
                 * Remove extents.  If we get ENOSPC for a dir we have to move
@@ -2473,7 +2429,6 @@ xfs_buf_map_from_irec(
  */
 static int
 xfs_dabuf_map(
-       struct xfs_trans        *trans,
        struct xfs_inode        *dp,
        xfs_dablk_t             bno,
        xfs_daddr_t             mappedbno,
@@ -2491,7 +2446,10 @@ xfs_dabuf_map(
        ASSERT(map && *map);
        ASSERT(*nmaps == 1);
 
-       nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1;
+       if (whichfork == XFS_DATA_FORK)
+               nfsb = mp->m_dir_geo->fsbcount;
+       else
+               nfsb = mp->m_attr_geo->fsbcount;
 
        /*
         * Caller doesn't have a mapping.  -2 means don't complain
@@ -2569,7 +2527,7 @@ xfs_da_get_buf(
        *bpp = NULL;
        mapp = &map;
        nmap = 1;
-       error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork,
+       error = xfs_dabuf_map(dp, bno, mappedbno, whichfork,
                                &mapp, &nmap);
        if (error) {
                /* mapping a hole is not an error, but we don't continue */
@@ -2582,8 +2540,7 @@ xfs_da_get_buf(
                                    mapp, nmap, 0);
        error = bp ? bp->b_error : XFS_ERROR(EIO);
        if (error) {
-               if (bp)
-                       xfs_trans_brelse(trans, bp);
+               xfs_trans_brelse(trans, bp);
                goto out_free;
        }
 
@@ -2618,7 +2575,7 @@ xfs_da_read_buf(
        *bpp = NULL;
        mapp = &map;
        nmap = 1;
-       error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork,
+       error = xfs_dabuf_map(dp, bno, mappedbno, whichfork,
                                &mapp, &nmap);
        if (error) {
                /* mapping a hole is not an error, but we don't continue */
@@ -2637,47 +2594,6 @@ xfs_da_read_buf(
                xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF);
        else
                xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF);
-
-       /*
-        * This verification code will be moved to a CRC verification callback
-        * function so just leave it here unchanged until then.
-        */
-       {
-               xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
-               xfs_dir2_free_t         *free = bp->b_addr;
-               xfs_da_blkinfo_t        *info = bp->b_addr;
-               uint                    magic, magic1;
-               struct xfs_mount        *mp = dp->i_mount;
-
-               magic = be16_to_cpu(info->magic);
-               magic1 = be32_to_cpu(hdr->magic);
-               if (unlikely(
-                   XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
-                                  (magic != XFS_DA3_NODE_MAGIC) &&
-                                  (magic != XFS_ATTR_LEAF_MAGIC) &&
-                                  (magic != XFS_ATTR3_LEAF_MAGIC) &&
-                                  (magic != XFS_DIR2_LEAF1_MAGIC) &&
-                                  (magic != XFS_DIR3_LEAF1_MAGIC) &&
-                                  (magic != XFS_DIR2_LEAFN_MAGIC) &&
-                                  (magic != XFS_DIR3_LEAFN_MAGIC) &&
-                                  (magic1 != XFS_DIR2_BLOCK_MAGIC) &&
-                                  (magic1 != XFS_DIR3_BLOCK_MAGIC) &&
-                                  (magic1 != XFS_DIR2_DATA_MAGIC) &&
-                                  (magic1 != XFS_DIR3_DATA_MAGIC) &&
-                                  (free->hdr.magic !=
-                                       cpu_to_be32(XFS_DIR2_FREE_MAGIC)) &&
-                                  (free->hdr.magic !=
-                                       cpu_to_be32(XFS_DIR3_FREE_MAGIC)),
-                               mp, XFS_ERRTAG_DA_READ_BUF,
-                               XFS_RANDOM_DA_READ_BUF))) {
-                       trace_xfs_da_btree_corrupt(bp, _RET_IP_);
-                       XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)",
-                                            XFS_ERRLEVEL_LOW, mp, info);
-                       error = XFS_ERROR(EFSCORRUPTED);
-                       xfs_trans_brelse(trans, bp);
-                       goto out_free;
-               }
-       }
        *bpp = bp;
 out_free:
        if (mapp != &map)
@@ -2691,7 +2607,6 @@ out_free:
  */
 xfs_daddr_t
 xfs_da_reada_buf(
-       struct xfs_trans        *trans,
        struct xfs_inode        *dp,
        xfs_dablk_t             bno,
        xfs_daddr_t             mappedbno,
@@ -2705,7 +2620,7 @@ xfs_da_reada_buf(
 
        mapp = &map;
        nmap = 1;
-       error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork,
+       error = xfs_dabuf_map(dp, bno, mappedbno, whichfork,
                                &mapp, &nmap);
        if (error) {
                /* mapping a hole is not an error, but we don't continue */
diff --git a/libxfs/xfs_da_format.c b/libxfs/xfs_da_format.c
new file mode 100644 (file)
index 0000000..c5e36d9
--- /dev/null
@@ -0,0 +1,898 @@
+/*
+ * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2013 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <xfs.h>
+
+/*
+ * Shortform directory ops
+ */
+static int
+xfs_dir2_sf_entsize(
+       struct xfs_dir2_sf_hdr  *hdr,
+       int                     len)
+{
+       int count = sizeof(struct xfs_dir2_sf_entry);   /* namelen + offset */
+
+       count += len;                                   /* name */
+       count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
+                               sizeof(xfs_dir2_ino4_t); /* ino # */
+       return count;
+}
+
+static int
+xfs_dir3_sf_entsize(
+       struct xfs_dir2_sf_hdr  *hdr,
+       int                     len)
+{
+       return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t);
+}
+
+static struct xfs_dir2_sf_entry *
+xfs_dir2_sf_nextentry(
+       struct xfs_dir2_sf_hdr  *hdr,
+       struct xfs_dir2_sf_entry *sfep)
+{
+       return (struct xfs_dir2_sf_entry *)
+               ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen));
+}
+
+static struct xfs_dir2_sf_entry *
+xfs_dir3_sf_nextentry(
+       struct xfs_dir2_sf_hdr  *hdr,
+       struct xfs_dir2_sf_entry *sfep)
+{
+       return (struct xfs_dir2_sf_entry *)
+               ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen));
+}
+
+
+/*
+ * For filetype enabled shortform directories, the file type field is stored at
+ * the end of the name.  Because it's only a single byte, endian conversion is
+ * not necessary. For non-filetype enable directories, the type is always
+ * unknown and we never store the value.
+ */
+static __uint8_t
+xfs_dir2_sfe_get_ftype(
+       struct xfs_dir2_sf_entry *sfep)
+{
+       return XFS_DIR3_FT_UNKNOWN;
+}
+
+static void
+xfs_dir2_sfe_put_ftype(
+       struct xfs_dir2_sf_entry *sfep,
+       __uint8_t               ftype)
+{
+       ASSERT(ftype < XFS_DIR3_FT_MAX);
+}
+
+static __uint8_t
+xfs_dir3_sfe_get_ftype(
+       struct xfs_dir2_sf_entry *sfep)
+{
+       __uint8_t       ftype;
+
+       ftype = sfep->name[sfep->namelen];
+       if (ftype >= XFS_DIR3_FT_MAX)
+               return XFS_DIR3_FT_UNKNOWN;
+       return ftype;
+}
+
+static void
+xfs_dir3_sfe_put_ftype(
+       struct xfs_dir2_sf_entry *sfep,
+       __uint8_t               ftype)
+{
+       ASSERT(ftype < XFS_DIR3_FT_MAX);
+
+       sfep->name[sfep->namelen] = ftype;
+}
+
+/*
+ * Inode numbers in short-form directories can come in two versions,
+ * either 4 bytes or 8 bytes wide.  These helpers deal with the
+ * two forms transparently by looking at the headers i8count field.
+ *
+ * For 64-bit inode number the most significant byte must be zero.
+ */
+static xfs_ino_t
+xfs_dir2_sf_get_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       xfs_dir2_inou_t         *from)
+{
+       if (hdr->i8count)
+               return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
+       else
+               return get_unaligned_be32(&from->i4.i);
+}
+
+static void
+xfs_dir2_sf_put_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       xfs_dir2_inou_t         *to,
+       xfs_ino_t               ino)
+{
+       ASSERT((ino & 0xff00000000000000ULL) == 0);
+
+       if (hdr->i8count)
+               put_unaligned_be64(ino, &to->i8.i);
+       else
+               put_unaligned_be32(ino, &to->i4.i);
+}
+
+static xfs_ino_t
+xfs_dir2_sf_get_parent_ino(
+       struct xfs_dir2_sf_hdr  *hdr)
+{
+       return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
+}
+
+static void
+xfs_dir2_sf_put_parent_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       xfs_ino_t               ino)
+{
+       xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
+}
+
+/*
+ * In short-form directory entries the inode numbers are stored at variable
+ * offset behind the entry name. If the entry stores a filetype value, then it
+ * sits between the name and the inode number. Hence the inode numbers may only
+ * be accessed through the helpers below.
+ */
+static xfs_ino_t
+xfs_dir2_sfe_get_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       struct xfs_dir2_sf_entry *sfep)
+{
+       return xfs_dir2_sf_get_ino(hdr,
+                               (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]);
+}
+
+static void
+xfs_dir2_sfe_put_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       struct xfs_dir2_sf_entry *sfep,
+       xfs_ino_t               ino)
+{
+       xfs_dir2_sf_put_ino(hdr,
+                           (xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino);
+}
+
+static xfs_ino_t
+xfs_dir3_sfe_get_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       struct xfs_dir2_sf_entry *sfep)
+{
+       return xfs_dir2_sf_get_ino(hdr,
+                       (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]);
+}
+
+static void
+xfs_dir3_sfe_put_ino(
+       struct xfs_dir2_sf_hdr  *hdr,
+       struct xfs_dir2_sf_entry *sfep,
+       xfs_ino_t               ino)
+{
+       xfs_dir2_sf_put_ino(hdr,
+                       (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino);
+}
+
+
+/*
+ * Directory data block operations
+ */
+
+/*
+ * For special situations, the dirent size ends up fixed because we always know
+ * what the size of the entry is. That's true for the "." and "..", and
+ * therefore we know that they are a fixed size and hence their offsets are
+ * constant, as is the first entry.
+ *
+ * Hence, this calculation is written as a macro to be able to be calculated at
+ * compile time and so certain offsets can be calculated directly in the
+ * structure initaliser via the macro. There are two macros - one for dirents
+ * with ftype and without so there are no unresolvable conditionals in the
+ * calculations. We also use round_up() as XFS_DIR2_DATA_ALIGN is always a power
+ * of 2 and the compiler doesn't reject it (unlike roundup()).
+ */
+#define XFS_DIR2_DATA_ENTSIZE(n)                                       \
+       round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \
+                sizeof(xfs_dir2_data_off_t)), XFS_DIR2_DATA_ALIGN)
+
+#define XFS_DIR3_DATA_ENTSIZE(n)                                       \
+       round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \
+                sizeof(xfs_dir2_data_off_t) + sizeof(__uint8_t)),      \
+               XFS_DIR2_DATA_ALIGN)
+
+static int
+xfs_dir2_data_entsize(
+       int                     n)
+{
+       return XFS_DIR2_DATA_ENTSIZE(n);
+}
+
+static int
+xfs_dir3_data_entsize(
+       int                     n)
+{
+       return XFS_DIR3_DATA_ENTSIZE(n);
+}
+
+static __uint8_t
+xfs_dir2_data_get_ftype(
+       struct xfs_dir2_data_entry *dep)
+{
+       return XFS_DIR3_FT_UNKNOWN;
+}
+
+static void
+xfs_dir2_data_put_ftype(
+       struct xfs_dir2_data_entry *dep,
+       __uint8_t               ftype)
+{
+       ASSERT(ftype < XFS_DIR3_FT_MAX);
+}
+
+static __uint8_t
+xfs_dir3_data_get_ftype(
+       struct xfs_dir2_data_entry *dep)
+{
+       __uint8_t       ftype = dep->name[dep->namelen];
+
+       ASSERT(ftype < XFS_DIR3_FT_MAX);
+       if (ftype >= XFS_DIR3_FT_MAX)
+               return XFS_DIR3_FT_UNKNOWN;
+       return ftype;
+}
+
+static void
+xfs_dir3_data_put_ftype(
+       struct xfs_dir2_data_entry *dep,
+       __uint8_t               type)
+{
+       ASSERT(type < XFS_DIR3_FT_MAX);
+       ASSERT(dep->namelen != 0);
+
+       dep->name[dep->namelen] = type;
+}
+
+/*
+ * Pointer to an entry's tag word.
+ */
+static __be16 *
+xfs_dir2_data_entry_tag_p(
+       struct xfs_dir2_data_entry *dep)
+{
+       return (__be16 *)((char *)dep +
+               xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
+}
+
+static __be16 *
+xfs_dir3_data_entry_tag_p(
+       struct xfs_dir2_data_entry *dep)
+{
+       return (__be16 *)((char *)dep +
+               xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16));
+}
+
+/*
+ * location of . and .. in data space (always block 0)
+ */
+static struct xfs_dir2_data_entry *
+xfs_dir2_data_dot_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir2_data_dotdot_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR2_DATA_ENTSIZE(1));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir2_data_first_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR2_DATA_ENTSIZE(1) +
+                               XFS_DIR2_DATA_ENTSIZE(2));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir2_ftype_data_dotdot_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir2_ftype_data_first_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1) +
+                               XFS_DIR3_DATA_ENTSIZE(2));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir3_data_dot_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir3_data_dotdot_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir3_data_first_entry_p(
+       struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1) +
+                               XFS_DIR3_DATA_ENTSIZE(2));
+}
+
+static struct xfs_dir2_data_free *
+xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return hdr->bestfree;
+}
+
+static struct xfs_dir2_data_free *
+xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
+}
+
+static struct xfs_dir2_data_unused *
+xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_unused *)
+               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
+}
+
+static struct xfs_dir2_data_entry *
+xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_entry *)
+               ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
+}
+
+static struct xfs_dir2_data_unused *
+xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_unused *)
+               ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
+}
+
+
+/*
+ * Directory Leaf block operations
+ */
+static int
+xfs_dir2_max_leaf_ents(struct xfs_da_geometry *geo)
+{
+       return (geo->blksize - sizeof(struct xfs_dir2_leaf_hdr)) /
+               (uint)sizeof(struct xfs_dir2_leaf_entry);
+}
+
+static struct xfs_dir2_leaf_entry *
+xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp)
+{
+       return lp->__ents;
+}
+
+static int
+xfs_dir3_max_leaf_ents(struct xfs_da_geometry *geo)
+{
+       return (geo->blksize - sizeof(struct xfs_dir3_leaf_hdr)) /
+               (uint)sizeof(struct xfs_dir2_leaf_entry);
+}
+
+static struct xfs_dir2_leaf_entry *
+xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
+{
+       return ((struct xfs_dir3_leaf *)lp)->__ents;
+}
+
+static void
+xfs_dir2_leaf_hdr_from_disk(
+       struct xfs_dir3_icleaf_hdr      *to,
+       struct xfs_dir2_leaf            *from)
+{
+       to->forw = be32_to_cpu(from->hdr.info.forw);
+       to->back = be32_to_cpu(from->hdr.info.back);
+       to->magic = be16_to_cpu(from->hdr.info.magic);
+       to->count = be16_to_cpu(from->hdr.count);
+       to->stale = be16_to_cpu(from->hdr.stale);
+
+       ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC ||
+              to->magic == XFS_DIR2_LEAFN_MAGIC);
+}
+
+static void
+xfs_dir2_leaf_hdr_to_disk(
+       struct xfs_dir2_leaf            *to,
+       struct xfs_dir3_icleaf_hdr      *from)
+{
+       ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC ||
+              from->magic == XFS_DIR2_LEAFN_MAGIC);
+
+       to->hdr.info.forw = cpu_to_be32(from->forw);
+       to->hdr.info.back = cpu_to_be32(from->back);
+       to->hdr.info.magic = cpu_to_be16(from->magic);
+       to->hdr.count = cpu_to_be16(from->count);
+       to->hdr.stale = cpu_to_be16(from->stale);
+}
+
+static void
+xfs_dir3_leaf_hdr_from_disk(
+       struct xfs_dir3_icleaf_hdr      *to,
+       struct xfs_dir2_leaf            *from)
+{
+       struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from;
+
+       to->forw = be32_to_cpu(hdr3->info.hdr.forw);
+       to->back = be32_to_cpu(hdr3->info.hdr.back);
+       to->magic = be16_to_cpu(hdr3->info.hdr.magic);
+       to->count = be16_to_cpu(hdr3->count);
+       to->stale = be16_to_cpu(hdr3->stale);
+
+       ASSERT(to->magic == XFS_DIR3_LEAF1_MAGIC ||
+              to->magic == XFS_DIR3_LEAFN_MAGIC);
+}
+
+static void
+xfs_dir3_leaf_hdr_to_disk(
+       struct xfs_dir2_leaf            *to,
+       struct xfs_dir3_icleaf_hdr      *from)
+{
+       struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to;
+
+       ASSERT(from->magic == XFS_DIR3_LEAF1_MAGIC ||
+              from->magic == XFS_DIR3_LEAFN_MAGIC);
+
+       hdr3->info.hdr.forw = cpu_to_be32(from->forw);
+       hdr3->info.hdr.back = cpu_to_be32(from->back);
+       hdr3->info.hdr.magic = cpu_to_be16(from->magic);
+       hdr3->count = cpu_to_be16(from->count);
+       hdr3->stale = cpu_to_be16(from->stale);
+}
+
+
+/*
+ * Directory/Attribute Node block operations
+ */
+static struct xfs_da_node_entry *
+xfs_da2_node_tree_p(struct xfs_da_intnode *dap)
+{
+       return dap->__btree;
+}
+
+static struct xfs_da_node_entry *
+xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
+{
+       return ((struct xfs_da3_intnode *)dap)->__btree;
+}
+
+static void
+xfs_da2_node_hdr_from_disk(
+       struct xfs_da3_icnode_hdr       *to,
+       struct xfs_da_intnode           *from)
+{
+       ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
+       to->forw = be32_to_cpu(from->hdr.info.forw);
+       to->back = be32_to_cpu(from->hdr.info.back);
+       to->magic = be16_to_cpu(from->hdr.info.magic);
+       to->count = be16_to_cpu(from->hdr.__count);
+       to->level = be16_to_cpu(from->hdr.__level);
+}
+
+static void
+xfs_da2_node_hdr_to_disk(
+       struct xfs_da_intnode           *to,
+       struct xfs_da3_icnode_hdr       *from)
+{
+       ASSERT(from->magic == XFS_DA_NODE_MAGIC);
+       to->hdr.info.forw = cpu_to_be32(from->forw);
+       to->hdr.info.back = cpu_to_be32(from->back);
+       to->hdr.info.magic = cpu_to_be16(from->magic);
+       to->hdr.__count = cpu_to_be16(from->count);
+       to->hdr.__level = cpu_to_be16(from->level);
+}
+
+static void
+xfs_da3_node_hdr_from_disk(
+       struct xfs_da3_icnode_hdr       *to,
+       struct xfs_da_intnode           *from)
+{
+       struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from;
+
+       ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC));
+       to->forw = be32_to_cpu(hdr3->info.hdr.forw);
+       to->back = be32_to_cpu(hdr3->info.hdr.back);
+       to->magic = be16_to_cpu(hdr3->info.hdr.magic);
+       to->count = be16_to_cpu(hdr3->__count);
+       to->level = be16_to_cpu(hdr3->__level);
+}
+
+static void
+xfs_da3_node_hdr_to_disk(
+       struct xfs_da_intnode           *to,
+       struct xfs_da3_icnode_hdr       *from)
+{
+       struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to;
+
+       ASSERT(from->magic == XFS_DA3_NODE_MAGIC);
+       hdr3->info.hdr.forw = cpu_to_be32(from->forw);
+       hdr3->info.hdr.back = cpu_to_be32(from->back);
+       hdr3->info.hdr.magic = cpu_to_be16(from->magic);
+       hdr3->__count = cpu_to_be16(from->count);
+       hdr3->__level = cpu_to_be16(from->level);
+}
+
+
+/*
+ * Directory free space block operations
+ */
+static int
+xfs_dir2_free_max_bests(struct xfs_da_geometry *geo)
+{
+       return (geo->blksize - sizeof(struct xfs_dir2_free_hdr)) /
+               sizeof(xfs_dir2_data_off_t);
+}
+
+static __be16 *
+xfs_dir2_free_bests_p(struct xfs_dir2_free *free)
+{
+       return (__be16 *)((char *)free + sizeof(struct xfs_dir2_free_hdr));
+}
+
+/*
+ * Convert data space db to the corresponding free db.
+ */
+static xfs_dir2_db_t
+xfs_dir2_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
+{
+       return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) +
+                       (db / xfs_dir2_free_max_bests(geo));
+}
+
+/*
+ * Convert data space db to the corresponding index in a free db.
+ */
+static int
+xfs_dir2_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
+{
+       return db % xfs_dir2_free_max_bests(geo);
+}
+
+static int
+xfs_dir3_free_max_bests(struct xfs_da_geometry *geo)
+{
+       return (geo->blksize - sizeof(struct xfs_dir3_free_hdr)) /
+               sizeof(xfs_dir2_data_off_t);
+}
+
+static __be16 *
+xfs_dir3_free_bests_p(struct xfs_dir2_free *free)
+{
+       return (__be16 *)((char *)free + sizeof(struct xfs_dir3_free_hdr));
+}
+
+/*
+ * Convert data space db to the corresponding free db.
+ */
+static xfs_dir2_db_t
+xfs_dir3_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
+{
+       return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) +
+                       (db / xfs_dir3_free_max_bests(geo));
+}
+
+/*
+ * Convert data space db to the corresponding index in a free db.
+ */
+static int
+xfs_dir3_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
+{
+       return db % xfs_dir3_free_max_bests(geo);
+}
+
+static void
+xfs_dir2_free_hdr_from_disk(
+       struct xfs_dir3_icfree_hdr      *to,
+       struct xfs_dir2_free            *from)
+{
+       to->magic = be32_to_cpu(from->hdr.magic);
+       to->firstdb = be32_to_cpu(from->hdr.firstdb);
+       to->nvalid = be32_to_cpu(from->hdr.nvalid);
+       to->nused = be32_to_cpu(from->hdr.nused);
+       ASSERT(to->magic == XFS_DIR2_FREE_MAGIC);
+}
+
+static void
+xfs_dir2_free_hdr_to_disk(
+       struct xfs_dir2_free            *to,
+       struct xfs_dir3_icfree_hdr      *from)
+{
+       ASSERT(from->magic == XFS_DIR2_FREE_MAGIC);
+
+       to->hdr.magic = cpu_to_be32(from->magic);
+       to->hdr.firstdb = cpu_to_be32(from->firstdb);
+       to->hdr.nvalid = cpu_to_be32(from->nvalid);
+       to->hdr.nused = cpu_to_be32(from->nused);
+}
+
+static void
+xfs_dir3_free_hdr_from_disk(
+       struct xfs_dir3_icfree_hdr      *to,
+       struct xfs_dir2_free            *from)
+{
+       struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from;
+
+       to->magic = be32_to_cpu(hdr3->hdr.magic);
+       to->firstdb = be32_to_cpu(hdr3->firstdb);
+       to->nvalid = be32_to_cpu(hdr3->nvalid);
+       to->nused = be32_to_cpu(hdr3->nused);
+
+       ASSERT(to->magic == XFS_DIR3_FREE_MAGIC);
+}
+
+static void
+xfs_dir3_free_hdr_to_disk(
+       struct xfs_dir2_free            *to,
+       struct xfs_dir3_icfree_hdr      *from)
+{
+       struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to;
+
+       ASSERT(from->magic == XFS_DIR3_FREE_MAGIC);
+
+       hdr3->hdr.magic = cpu_to_be32(from->magic);
+       hdr3->firstdb = cpu_to_be32(from->firstdb);
+       hdr3->nvalid = cpu_to_be32(from->nvalid);
+       hdr3->nused = cpu_to_be32(from->nused);
+}
+
+static const struct xfs_dir_ops xfs_dir2_ops = {
+       .sf_entsize = xfs_dir2_sf_entsize,
+       .sf_nextentry = xfs_dir2_sf_nextentry,
+       .sf_get_ftype = xfs_dir2_sfe_get_ftype,
+       .sf_put_ftype = xfs_dir2_sfe_put_ftype,
+       .sf_get_ino = xfs_dir2_sfe_get_ino,
+       .sf_put_ino = xfs_dir2_sfe_put_ino,
+       .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
+       .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
+
+       .data_entsize = xfs_dir2_data_entsize,
+       .data_get_ftype = xfs_dir2_data_get_ftype,
+       .data_put_ftype = xfs_dir2_data_put_ftype,
+       .data_entry_tag_p = xfs_dir2_data_entry_tag_p,
+       .data_bestfree_p = xfs_dir2_data_bestfree_p,
+
+       .data_dot_offset = sizeof(struct xfs_dir2_data_hdr),
+       .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR2_DATA_ENTSIZE(1),
+       .data_first_offset =  sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR2_DATA_ENTSIZE(1) +
+                               XFS_DIR2_DATA_ENTSIZE(2),
+       .data_entry_offset = sizeof(struct xfs_dir2_data_hdr),
+
+       .data_dot_entry_p = xfs_dir2_data_dot_entry_p,
+       .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
+       .data_first_entry_p = xfs_dir2_data_first_entry_p,
+       .data_entry_p = xfs_dir2_data_entry_p,
+       .data_unused_p = xfs_dir2_data_unused_p,
+
+       .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr),
+       .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk,
+       .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk,
+       .leaf_max_ents = xfs_dir2_max_leaf_ents,
+       .leaf_ents_p = xfs_dir2_leaf_ents_p,
+
+       .node_hdr_size = sizeof(struct xfs_da_node_hdr),
+       .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
+       .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
+       .node_tree_p = xfs_da2_node_tree_p,
+
+       .free_hdr_size = sizeof(struct xfs_dir2_free_hdr),
+       .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk,
+       .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk,
+       .free_max_bests = xfs_dir2_free_max_bests,
+       .free_bests_p = xfs_dir2_free_bests_p,
+       .db_to_fdb = xfs_dir2_db_to_fdb,
+       .db_to_fdindex = xfs_dir2_db_to_fdindex,
+};
+
+static const struct xfs_dir_ops xfs_dir2_ftype_ops = {
+       .sf_entsize = xfs_dir3_sf_entsize,
+       .sf_nextentry = xfs_dir3_sf_nextentry,
+       .sf_get_ftype = xfs_dir3_sfe_get_ftype,
+       .sf_put_ftype = xfs_dir3_sfe_put_ftype,
+       .sf_get_ino = xfs_dir3_sfe_get_ino,
+       .sf_put_ino = xfs_dir3_sfe_put_ino,
+       .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
+       .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
+
+       .data_entsize = xfs_dir3_data_entsize,
+       .data_get_ftype = xfs_dir3_data_get_ftype,
+       .data_put_ftype = xfs_dir3_data_put_ftype,
+       .data_entry_tag_p = xfs_dir3_data_entry_tag_p,
+       .data_bestfree_p = xfs_dir2_data_bestfree_p,
+
+       .data_dot_offset = sizeof(struct xfs_dir2_data_hdr),
+       .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1),
+       .data_first_offset =  sizeof(struct xfs_dir2_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1) +
+                               XFS_DIR3_DATA_ENTSIZE(2),
+       .data_entry_offset = sizeof(struct xfs_dir2_data_hdr),
+
+       .data_dot_entry_p = xfs_dir2_data_dot_entry_p,
+       .data_dotdot_entry_p = xfs_dir2_ftype_data_dotdot_entry_p,
+       .data_first_entry_p = xfs_dir2_ftype_data_first_entry_p,
+       .data_entry_p = xfs_dir2_data_entry_p,
+       .data_unused_p = xfs_dir2_data_unused_p,
+
+       .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr),
+       .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk,
+       .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk,
+       .leaf_max_ents = xfs_dir2_max_leaf_ents,
+       .leaf_ents_p = xfs_dir2_leaf_ents_p,
+
+       .node_hdr_size = sizeof(struct xfs_da_node_hdr),
+       .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
+       .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
+       .node_tree_p = xfs_da2_node_tree_p,
+
+       .free_hdr_size = sizeof(struct xfs_dir2_free_hdr),
+       .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk,
+       .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk,
+       .free_max_bests = xfs_dir2_free_max_bests,
+       .free_bests_p = xfs_dir2_free_bests_p,
+       .db_to_fdb = xfs_dir2_db_to_fdb,
+       .db_to_fdindex = xfs_dir2_db_to_fdindex,
+};
+
+static const struct xfs_dir_ops xfs_dir3_ops = {
+       .sf_entsize = xfs_dir3_sf_entsize,
+       .sf_nextentry = xfs_dir3_sf_nextentry,
+       .sf_get_ftype = xfs_dir3_sfe_get_ftype,
+       .sf_put_ftype = xfs_dir3_sfe_put_ftype,
+       .sf_get_ino = xfs_dir3_sfe_get_ino,
+       .sf_put_ino = xfs_dir3_sfe_put_ino,
+       .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
+       .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
+
+       .data_entsize = xfs_dir3_data_entsize,
+       .data_get_ftype = xfs_dir3_data_get_ftype,
+       .data_put_ftype = xfs_dir3_data_put_ftype,
+       .data_entry_tag_p = xfs_dir3_data_entry_tag_p,
+       .data_bestfree_p = xfs_dir3_data_bestfree_p,
+
+       .data_dot_offset = sizeof(struct xfs_dir3_data_hdr),
+       .data_dotdot_offset = sizeof(struct xfs_dir3_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1),
+       .data_first_offset =  sizeof(struct xfs_dir3_data_hdr) +
+                               XFS_DIR3_DATA_ENTSIZE(1) +
+                               XFS_DIR3_DATA_ENTSIZE(2),
+       .data_entry_offset = sizeof(struct xfs_dir3_data_hdr),
+
+       .data_dot_entry_p = xfs_dir3_data_dot_entry_p,
+       .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p,
+       .data_first_entry_p = xfs_dir3_data_first_entry_p,
+       .data_entry_p = xfs_dir3_data_entry_p,
+       .data_unused_p = xfs_dir3_data_unused_p,
+
+       .leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr),
+       .leaf_hdr_to_disk = xfs_dir3_leaf_hdr_to_disk,
+       .leaf_hdr_from_disk = xfs_dir3_leaf_hdr_from_disk,
+       .leaf_max_ents = xfs_dir3_max_leaf_ents,
+       .leaf_ents_p = xfs_dir3_leaf_ents_p,
+
+       .node_hdr_size = sizeof(struct xfs_da3_node_hdr),
+       .node_hdr_to_disk = xfs_da3_node_hdr_to_disk,
+       .node_hdr_from_disk = xfs_da3_node_hdr_from_disk,
+       .node_tree_p = xfs_da3_node_tree_p,
+
+       .free_hdr_size = sizeof(struct xfs_dir3_free_hdr),
+       .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk,
+       .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk,
+       .free_max_bests = xfs_dir3_free_max_bests,
+       .free_bests_p = xfs_dir3_free_bests_p,
+       .db_to_fdb = xfs_dir3_db_to_fdb,
+       .db_to_fdindex = xfs_dir3_db_to_fdindex,
+};
+
+static const struct xfs_dir_ops xfs_dir2_nondir_ops = {
+       .node_hdr_size = sizeof(struct xfs_da_node_hdr),
+       .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
+       .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
+       .node_tree_p = xfs_da2_node_tree_p,
+};
+
+static const struct xfs_dir_ops xfs_dir3_nondir_ops = {
+       .node_hdr_size = sizeof(struct xfs_da3_node_hdr),
+       .node_hdr_to_disk = xfs_da3_node_hdr_to_disk,
+       .node_hdr_from_disk = xfs_da3_node_hdr_from_disk,
+       .node_tree_p = xfs_da3_node_tree_p,
+};
+
+/*
+ * Return the ops structure according to the current config.  If we are passed
+ * an inode, then that overrides the default config we use which is based on
+ * feature bits.
+ */
+const struct xfs_dir_ops *
+xfs_dir_get_ops(
+       struct xfs_mount        *mp,
+       struct xfs_inode        *dp)
+{
+       if (dp)
+               return dp->d_ops;
+       if (mp->m_dir_inode_ops)
+               return mp->m_dir_inode_ops;
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               return &xfs_dir3_ops;
+       if (xfs_sb_version_hasftype(&mp->m_sb))
+               return &xfs_dir2_ftype_ops;
+       return &xfs_dir2_ops;
+}
+
+const struct xfs_dir_ops *
+xfs_nondir_get_ops(
+       struct xfs_mount        *mp,
+       struct xfs_inode        *dp)
+{
+       if (dp)
+               return dp->d_ops;
+       if (mp->m_nondir_inode_ops)
+               return mp->m_nondir_inode_ops;
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               return &xfs_dir3_nondir_ops;
+       return &xfs_dir2_nondir_ops;
+}
index 4c8c836f016e91d1e7b29ec1692d592908edb74b..c406225ac9b6ed2a645863264a3b4ba5054d1510 100644 (file)
@@ -27,7 +27,7 @@ struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
  * structure if appropriate for the given operation and filesystem config.
  */
 const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
-       [0]                     = XFS_DIR3_FT_UNKNOWN,
+       [0]                     = XFS_DIR3_FT_UNKNOWN,
        [S_IFREG >> S_SHIFT]    = XFS_DIR3_FT_REG_FILE,
        [S_IFDIR >> S_SHIFT]    = XFS_DIR3_FT_DIR,
        [S_IFCHR >> S_SHIFT]    = XFS_DIR3_FT_CHRDEV,
@@ -37,6 +37,7 @@ const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
        [S_IFLNK >> S_SHIFT]    = XFS_DIR3_FT_SYMLINK,
 };
 
+
 /*
  * ASCII case-insensitive (ie. A-Z) support for directories that was
  * used in IRIX.
@@ -83,33 +84,74 @@ static struct xfs_nameops xfs_ascii_ci_nameops = {
        .compname       = xfs_ascii_ci_compname,
 };
 
-void
-xfs_dir_mount(
-       xfs_mount_t     *mp)
+int
+xfs_da_mount(
+       struct xfs_mount        *mp)
 {
-       int     nodehdr_size;
+       struct xfs_da_geometry  *dageo;
+       int                     nodehdr_size;
 
 
-       ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
+       ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
        ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
               XFS_MAX_BLOCKSIZE);
-       mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
-       mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
-       mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
-       mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
-       mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
-
-       nodehdr_size = __xfs_da3_node_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
-       mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) /
+
+       mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
+       mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
+
+       nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
+       mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
+                                   KM_SLEEP | KM_MAYFAIL);
+       mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
+                                    KM_SLEEP | KM_MAYFAIL);
+       if (!mp->m_dir_geo || !mp->m_attr_geo) {
+               kmem_free(mp->m_dir_geo);
+               kmem_free(mp->m_attr_geo);
+               return ENOMEM;
+       }
+
+       /* set up directory geometry */
+       dageo = mp->m_dir_geo;
+       dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
+       dageo->fsblog = mp->m_sb.sb_blocklog;
+       dageo->blksize = 1 << dageo->blklog;
+       dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
+
+       /*
+        * Now we've set up the block conversion variables, we can calculate the
+        * segment block constants using the geometry structure.
+        */
+       dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
+       dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
+       dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
+       dageo->node_ents = (dageo->blksize - nodehdr_size) /
                                (uint)sizeof(xfs_da_node_entry_t);
-       mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) /
+       dageo->magicpct = (dageo->blksize * 37) / 100;
+
+       /* set up attribute geometry - single fsb only */
+       dageo = mp->m_attr_geo;
+       dageo->blklog = mp->m_sb.sb_blocklog;
+       dageo->fsblog = mp->m_sb.sb_blocklog;
+       dageo->blksize = 1 << dageo->blklog;
+       dageo->fsbcount = 1;
+       dageo->node_ents = (dageo->blksize - nodehdr_size) /
                                (uint)sizeof(xfs_da_node_entry_t);
+       dageo->magicpct = (dageo->blksize * 37) / 100;
 
-       mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
        if (xfs_sb_version_hasasciici(&mp->m_sb))
                mp->m_dirnameops = &xfs_ascii_ci_nameops;
        else
                mp->m_dirnameops = &xfs_default_nameops;
+
+       return 0;
+}
+
+void
+xfs_da_unmount(
+       struct xfs_mount        *mp)
+{
+       kmem_free(mp->m_dir_geo);
+       kmem_free(mp->m_attr_geo);
 }
 
 /*
@@ -173,16 +215,24 @@ xfs_dir_init(
        xfs_inode_t     *dp,
        xfs_inode_t     *pdp)
 {
-       xfs_da_args_t   args;
+       struct xfs_da_args *args;
        int             error;
 
-       memset((char *)&args, 0, sizeof(args));
-       args.dp = dp;
-       args.trans = tp;
        ASSERT(S_ISDIR(dp->i_d.di_mode));
-       if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
+       error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
+       if (error)
                return error;
-       return xfs_dir2_sf_create(&args, pdp->i_ino);
+
+       args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+       if (!args)
+               return ENOMEM;
+
+       args->geo = dp->i_mount->m_dir_geo;
+       args->dp = dp;
+       args->trans = tp;
+       error = xfs_dir2_sf_create(args, pdp->i_ino);
+       kmem_free(args);
+       return error;
 }
 
 /*
@@ -198,41 +248,57 @@ xfs_dir_createname(
        xfs_bmap_free_t         *flist,         /* bmap's freeblock list */
        xfs_extlen_t            total)          /* bmap's total block count */
 {
-       xfs_da_args_t           args;
+       struct xfs_da_args      *args;
        int                     rval;
        int                     v;              /* type-checking value */
 
        ASSERT(S_ISDIR(dp->i_d.di_mode));
-       if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
+       rval = xfs_dir_ino_validate(tp->t_mountp, inum);
+       if (rval)
                return rval;
        XFS_STATS_INC(xs_dir_create);
 
-       memset(&args, 0, sizeof(xfs_da_args_t));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.filetype = name->type;
-       args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-       args.inumber = inum;
-       args.dp = dp;
-       args.firstblock = first;
-       args.flist = flist;
-       args.total = total;
-       args.whichfork = XFS_DATA_FORK;
-       args.trans = tp;
-       args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
-
-       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-               rval = xfs_dir2_sf_addname(&args);
-       else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_block_addname(&args);
-       else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_leaf_addname(&args);
+       args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+       if (!args)
+               return ENOMEM;
+
+       args->geo = dp->i_mount->m_dir_geo;
+       args->name = name->name;
+       args->namelen = name->len;
+       args->filetype = name->type;
+       args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+       args->inumber = inum;
+       args->dp = dp;
+       args->firstblock = first;
+       args->flist = flist;
+       args->total = total;
+       args->whichfork = XFS_DATA_FORK;
+       args->trans = tp;
+       args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
+
+       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+               rval = xfs_dir2_sf_addname(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isblock(args, &v);
+       if (rval)
+               goto out_free;
+       if (v) {
+               rval = xfs_dir2_block_addname(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isleaf(args, &v);
+       if (rval)
+               goto out_free;
+       if (v)
+               rval = xfs_dir2_leaf_addname(args);
        else
-               rval = xfs_dir2_node_addname(&args);
+               rval = xfs_dir2_node_addname(args);
+
+out_free:
+       kmem_free(args);
        return rval;
 }
 
@@ -275,46 +341,67 @@ xfs_dir_lookup(
        xfs_ino_t       *inum,          /* out: inode number */
        struct xfs_name *ci_name)       /* out: actual name if CI match */
 {
-       xfs_da_args_t   args;
+       struct xfs_da_args *args;
        int             rval;
        int             v;              /* type-checking value */
 
        ASSERT(S_ISDIR(dp->i_d.di_mode));
        XFS_STATS_INC(xs_dir_lookup);
 
-       memset(&args, 0, sizeof(xfs_da_args_t));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.filetype = name->type;
-       args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-       args.dp = dp;
-       args.whichfork = XFS_DATA_FORK;
-       args.trans = tp;
-       args.op_flags = XFS_DA_OP_OKNOENT;
+       /*
+        * We need to use KM_NOFS here so that lockdep will not throw false
+        * positive deadlock warnings on a non-transactional lookup path. It is
+        * safe to recurse into inode recalim in that case, but lockdep can't
+        * easily be taught about it. Hence KM_NOFS avoids having to add more
+        * lockdep Doing this avoids having to add a bunch of lockdep class
+        * annotations into the reclaim path for the ilock.
+        */
+       args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+       args->geo = dp->i_mount->m_dir_geo;
+       args->name = name->name;
+       args->namelen = name->len;
+       args->filetype = name->type;
+       args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+       args->dp = dp;
+       args->whichfork = XFS_DATA_FORK;
+       args->trans = tp;
+       args->op_flags = XFS_DA_OP_OKNOENT;
        if (ci_name)
-               args.op_flags |= XFS_DA_OP_CILOOKUP;
+               args->op_flags |= XFS_DA_OP_CILOOKUP;
 
-       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-               rval = xfs_dir2_sf_lookup(&args);
-       else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_block_lookup(&args);
-       else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_leaf_lookup(&args);
+       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+               rval = xfs_dir2_sf_lookup(args);
+               goto out_check_rval;
+       }
+
+       rval = xfs_dir2_isblock(args, &v);
+       if (rval)
+               goto out_free;
+       if (v) {
+               rval = xfs_dir2_block_lookup(args);
+               goto out_check_rval;
+       }
+
+       rval = xfs_dir2_isleaf(args, &v);
+       if (rval)
+               goto out_free;
+       if (v)
+               rval = xfs_dir2_leaf_lookup(args);
        else
-               rval = xfs_dir2_node_lookup(&args);
+               rval = xfs_dir2_node_lookup(args);
+
+out_check_rval:
        if (rval == EEXIST)
                rval = 0;
        if (!rval) {
-               *inum = args.inumber;
+               *inum = args->inumber;
                if (ci_name) {
-                       ci_name->name = args.value;
-                       ci_name->len = args.valuelen;
+                       ci_name->name = args->value;
+                       ci_name->len = args->valuelen;
                }
        }
+out_free:
+       kmem_free(args);
        return rval;
 }
 
@@ -331,38 +418,52 @@ xfs_dir_removename(
        xfs_bmap_free_t *flist,         /* bmap's freeblock list */
        xfs_extlen_t    total)          /* bmap's total block count */
 {
-       xfs_da_args_t   args;
+       struct xfs_da_args *args;
        int             rval;
        int             v;              /* type-checking value */
 
        ASSERT(S_ISDIR(dp->i_d.di_mode));
        XFS_STATS_INC(xs_dir_remove);
 
-       memset(&args, 0, sizeof(xfs_da_args_t));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.filetype = name->type;
-       args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-       args.inumber = ino;
-       args.dp = dp;
-       args.firstblock = first;
-       args.flist = flist;
-       args.total = total;
-       args.whichfork = XFS_DATA_FORK;
-       args.trans = tp;
-
-       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-               rval = xfs_dir2_sf_removename(&args);
-       else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_block_removename(&args);
-       else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_leaf_removename(&args);
+       args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+       if (!args)
+               return ENOMEM;
+
+       args->geo = dp->i_mount->m_dir_geo;
+       args->name = name->name;
+       args->namelen = name->len;
+       args->filetype = name->type;
+       args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+       args->inumber = ino;
+       args->dp = dp;
+       args->firstblock = first;
+       args->flist = flist;
+       args->total = total;
+       args->whichfork = XFS_DATA_FORK;
+       args->trans = tp;
+
+       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+               rval = xfs_dir2_sf_removename(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isblock(args, &v);
+       if (rval)
+               goto out_free;
+       if (v) {
+               rval = xfs_dir2_block_removename(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isleaf(args, &v);
+       if (rval)
+               goto out_free;
+       if (v)
+               rval = xfs_dir2_leaf_removename(args);
        else
-               rval = xfs_dir2_node_removename(&args);
+               rval = xfs_dir2_node_removename(args);
+out_free:
+       kmem_free(args);
        return rval;
 }
 
@@ -379,40 +480,55 @@ xfs_dir_replace(
        xfs_bmap_free_t *flist,         /* bmap's freeblock list */
        xfs_extlen_t    total)          /* bmap's total block count */
 {
-       xfs_da_args_t   args;
+       struct xfs_da_args *args;
        int             rval;
        int             v;              /* type-checking value */
 
        ASSERT(S_ISDIR(dp->i_d.di_mode));
 
-       if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
+       rval = xfs_dir_ino_validate(tp->t_mountp, inum);
+       if (rval)
                return rval;
 
-       memset(&args, 0, sizeof(xfs_da_args_t));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.filetype = name->type;
-       args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-       args.inumber = inum;
-       args.dp = dp;
-       args.firstblock = first;
-       args.flist = flist;
-       args.total = total;
-       args.whichfork = XFS_DATA_FORK;
-       args.trans = tp;
-
-       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-               rval = xfs_dir2_sf_replace(&args);
-       else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_block_replace(&args);
-       else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_leaf_replace(&args);
+       args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+       if (!args)
+               return ENOMEM;
+
+       args->geo = dp->i_mount->m_dir_geo;
+       args->name = name->name;
+       args->namelen = name->len;
+       args->filetype = name->type;
+       args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+       args->inumber = inum;
+       args->dp = dp;
+       args->firstblock = first;
+       args->flist = flist;
+       args->total = total;
+       args->whichfork = XFS_DATA_FORK;
+       args->trans = tp;
+
+       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+               rval = xfs_dir2_sf_replace(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isblock(args, &v);
+       if (rval)
+               goto out_free;
+       if (v) {
+               rval = xfs_dir2_block_replace(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isleaf(args, &v);
+       if (rval)
+               goto out_free;
+       if (v)
+               rval = xfs_dir2_leaf_replace(args);
        else
-               rval = xfs_dir2_node_replace(&args);
+               rval = xfs_dir2_node_replace(args);
+out_free:
+       kmem_free(args);
        return rval;
 }
 
@@ -427,7 +543,7 @@ xfs_dir_canenter(
        struct xfs_name *name,          /* name of entry to add */
        uint            resblks)
 {
-       xfs_da_args_t   args;
+       struct xfs_da_args *args;
        int             rval;
        int             v;              /* type-checking value */
 
@@ -436,29 +552,43 @@ xfs_dir_canenter(
 
        ASSERT(S_ISDIR(dp->i_d.di_mode));
 
-       memset(&args, 0, sizeof(xfs_da_args_t));
-       args.name = name->name;
-       args.namelen = name->len;
-       args.filetype = name->type;
-       args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-       args.dp = dp;
-       args.whichfork = XFS_DATA_FORK;
-       args.trans = tp;
-       args.op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
+       args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+       if (!args)
+               return ENOMEM;
+
+       args->geo = dp->i_mount->m_dir_geo;
+       args->name = name->name;
+       args->namelen = name->len;
+       args->filetype = name->type;
+       args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+       args->dp = dp;
+       args->whichfork = XFS_DATA_FORK;
+       args->trans = tp;
+       args->op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
                                                        XFS_DA_OP_OKNOENT;
 
-       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-               rval = xfs_dir2_sf_addname(&args);
-       else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_block_addname(&args);
-       else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-               return rval;
-       else if (v)
-               rval = xfs_dir2_leaf_addname(&args);
+       if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+               rval = xfs_dir2_sf_addname(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isblock(args, &v);
+       if (rval)
+               goto out_free;
+       if (v) {
+               rval = xfs_dir2_block_addname(args);
+               goto out_free;
+       }
+
+       rval = xfs_dir2_isleaf(args, &v);
+       if (rval)
+               goto out_free;
+       if (v)
+               rval = xfs_dir2_leaf_addname(args);
        else
-               rval = xfs_dir2_node_addname(&args);
+               rval = xfs_dir2_node_addname(args);
+out_free:
+       kmem_free(args);
        return rval;
 }
 
@@ -490,13 +620,13 @@ xfs_dir2_grow_inode(
         * Set lowest possible block in the space requested.
         */
        bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
-       count = mp->m_dirblkfsbs;
+       count = args->geo->fsbcount;
 
        error = xfs_da_grow_inode_int(args, &bno, count);
        if (error)
                return error;
 
-       *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
+       *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
 
        /*
         * Update file's size if this is the data space and it grew.
@@ -518,19 +648,16 @@ xfs_dir2_grow_inode(
  */
 int
 xfs_dir2_isblock(
-       xfs_trans_t     *tp,
-       xfs_inode_t     *dp,
-       int             *vp)            /* out: 1 is block, 0 is not block */
+       struct xfs_da_args      *args,
+       int                     *vp)    /* out: 1 is block, 0 is not block */
 {
-       xfs_fileoff_t   last;           /* last file offset */
-       xfs_mount_t     *mp;
-       int             rval;
+       xfs_fileoff_t           last;   /* last file offset */
+       int                     rval;
 
-       mp = dp->i_mount;
-       if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
+       if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
                return rval;
-       rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
-       ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
+       rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
+       ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize);
        *vp = rval;
        return 0;
 }
@@ -540,18 +667,15 @@ xfs_dir2_isblock(
  */
 int
 xfs_dir2_isleaf(
-       xfs_trans_t     *tp,
-       xfs_inode_t     *dp,
-       int             *vp)            /* out: 1 is leaf, 0 is not leaf */
+       struct xfs_da_args      *args,
+       int                     *vp)    /* out: 1 is block, 0 is not block */
 {
-       xfs_fileoff_t   last;           /* last file offset */
-       xfs_mount_t     *mp;
-       int             rval;
+       xfs_fileoff_t           last;   /* last file offset */
+       int                     rval;
 
-       mp = dp->i_mount;
-       if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
+       if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
                return rval;
-       *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
+       *vp = last == args->geo->leafblk + args->geo->fsbcount;
        return 0;
 }
 
@@ -579,11 +703,11 @@ xfs_dir2_shrink_inode(
        dp = args->dp;
        mp = dp->i_mount;
        tp = args->trans;
-       da = xfs_dir2_db_to_da(mp, db);
+       da = xfs_dir2_db_to_da(args->geo, db);
        /*
         * Unmap the fsblock(s).
         */
-       if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
+       if ((error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount,
                        XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
                        &done))) {
                /*
@@ -610,12 +734,12 @@ xfs_dir2_shrink_inode(
        /*
         * If it's not a data block, we're done.
         */
-       if (db >= XFS_DIR2_LEAF_FIRSTDB(mp))
+       if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
                return 0;
        /*
         * If the block isn't the last one in the directory, we're done.
         */
-       if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0))
+       if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
                return 0;
        bno = da;
        if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
@@ -624,7 +748,7 @@ xfs_dir2_shrink_inode(
                 */
                return error;
        }
-       if (db == mp->m_dirdatablk)
+       if (db == args->geo->datablk)
                ASSERT(bno == 0);
        else
                ASSERT(bno > 0);
index cede01f545cbeec7cfc22df26afb636f2d9deba4..8be52cf14db5faab44cfb9e9376eaa7a3038bdb8 100644 (file)
@@ -117,7 +117,7 @@ xfs_dir3_block_read(
        struct xfs_mount        *mp = dp->i_mount;
        int                     err;
 
-       err = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
+       err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp,
                                XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
        if (!err && tp)
                xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF);
@@ -150,6 +150,7 @@ xfs_dir3_block_init(
 
 static void
 xfs_dir2_block_need_space(
+       struct xfs_inode                *dp,
        struct xfs_dir2_data_hdr        *hdr,
        struct xfs_dir2_block_tail      *btp,
        struct xfs_dir2_leaf_entry      *blp,
@@ -165,7 +166,7 @@ xfs_dir2_block_need_space(
        struct xfs_dir2_data_unused     *enddup = NULL;
 
        *compact = 0;
-       bf = xfs_dir3_data_bestfree_p(hdr);
+       bf = dp->d_ops->data_bestfree_p(hdr);
 
        /*
         * If there are stale entries we'll use one for the leaf.
@@ -261,7 +262,7 @@ out:
  */
 static void
 xfs_dir2_block_compact(
-       struct xfs_trans                *tp,
+       struct xfs_da_args              *args,
        struct xfs_buf                  *bp,
        struct xfs_dir2_data_hdr        *hdr,
        struct xfs_dir2_block_tail      *btp,
@@ -294,18 +295,17 @@ xfs_dir2_block_compact(
        *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
        *lfloghigh -= be32_to_cpu(btp->stale) - 1;
        be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
-       xfs_dir2_data_make_free(tp, bp,
+       xfs_dir2_data_make_free(args, bp,
                (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
                (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
                needlog, &needscan);
-       blp += be32_to_cpu(btp->stale) - 1;
        btp->stale = cpu_to_be32(1);
        /*
         * If we now need to rebuild the bestfree map, do so.
         * This needs to happen before the next call to use_free.
         */
        if (needscan)
-               xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog);
+               xfs_dir2_data_freescan(args->geo, args->dp->d_ops, hdr, needlog);
 }
 
 /*
@@ -351,20 +351,20 @@ xfs_dir2_block_addname(
        if (error)
                return error;
 
-       len = xfs_dir3_data_entsize(mp, args->namelen);
+       len = dp->d_ops->data_entsize(args->namelen);
 
        /*
         * Set up pointers to parts of the block.
         */
        hdr = bp->b_addr;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
 
        /*
         * Find out if we can reuse stale entries or whether we need extra
         * space for entry and new leaf.
         */
-       xfs_dir2_block_need_space(hdr, btp, blp, &tagp, &dup,
+       xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup,
                                  &enddup, &compact, len);
 
        /*
@@ -400,7 +400,7 @@ xfs_dir2_block_addname(
         * If need to compact the leaf entries, do it now.
         */
        if (compact) {
-               xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
+               xfs_dir2_block_compact(args, bp, hdr, btp, blp, &needlog,
                                      &lfloghigh, &lfloglow);
                /* recalculate blp post-compaction */
                blp = xfs_dir2_block_leaf_p(btp);
@@ -435,7 +435,7 @@ xfs_dir2_block_addname(
                /*
                 * Mark the space needed for the new leaf entry, now in use.
                 */
-               xfs_dir2_data_use_free(tp, bp, enddup,
+               xfs_dir2_data_use_free(args, bp, enddup,
                        (xfs_dir2_data_aoff_t)
                        ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) -
                         sizeof(*blp)),
@@ -450,7 +450,8 @@ xfs_dir2_block_addname(
                 * This needs to happen before the next call to use_free.
                 */
                if (needscan) {
-                       xfs_dir2_data_freescan(mp, hdr, &needlog);
+                       xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr,
+                                              &needlog);
                        needscan = 0;
                }
                /*
@@ -516,13 +517,13 @@ xfs_dir2_block_addname(
         * Fill in the leaf entry.
         */
        blp[mid].hashval = cpu_to_be32(args->hashval);
-       blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+       blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                (char *)dep - (char *)hdr));
        xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
        /*
         * Mark space for the data entry used.
         */
-       xfs_dir2_data_use_free(tp, bp, dup,
+       xfs_dir2_data_use_free(args, bp, dup,
                (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
                (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
        /*
@@ -531,18 +532,18 @@ xfs_dir2_block_addname(
        dep->inumber = cpu_to_be64(args->inumber);
        dep->namelen = args->namelen;
        memcpy(dep->name, args->name, args->namelen);
-       xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
        /*
         * Clean up the bestfree array and log the header, tail, and entry.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, bp);
+               xfs_dir2_data_log_header(args, bp);
        xfs_dir2_block_log_tail(tp, bp);
-       xfs_dir2_data_log_entry(tp, bp, dep);
+       xfs_dir2_data_log_entry(args, bp, dep);
        xfs_dir3_data_check(dp, bp);
        return 0;
 }
@@ -561,7 +562,7 @@ xfs_dir2_block_log_leaf(
        xfs_dir2_leaf_entry_t   *blp;
        xfs_dir2_block_tail_t   *btp;
 
-       btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
+       btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
                (uint)((char *)&blp[last + 1] - (char *)hdr - 1));
@@ -578,7 +579,7 @@ xfs_dir2_block_log_tail(
        xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
        xfs_dir2_block_tail_t   *btp;
 
-       btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
+       btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
        xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
                (uint)((char *)(btp + 1) - (char *)hdr - 1));
 }
@@ -613,18 +614,19 @@ xfs_dir2_block_lookup(
        mp = dp->i_mount;
        hdr = bp->b_addr;
        xfs_dir3_data_check(dp, bp);
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Get the offset from the leaf entry, to point to the data.
         */
        dep = (xfs_dir2_data_entry_t *)((char *)hdr +
-               xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(blp[ent].address)));
        /*
         * Fill in inode number, CI name if appropriate, release the block.
         */
        args->inumber = be64_to_cpu(dep->inumber);
-       args->filetype = xfs_dir3_dirent_get_ftype(mp, dep);
+       args->filetype = dp->d_ops->data_get_ftype(dep);
        error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
        xfs_trans_brelse(args->trans, bp);
        return XFS_ERROR(error);
@@ -665,7 +667,7 @@ xfs_dir2_block_lookup_int(
 
        hdr = bp->b_addr;
        xfs_dir3_data_check(dp, bp);
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Loop doing a binary search for our hash value.
@@ -703,7 +705,7 @@ xfs_dir2_block_lookup_int(
                 * Get pointer to the entry from the leaf.
                 */
                dep = (xfs_dir2_data_entry_t *)
-                       ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr));
+                       ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, addr));
                /*
                 * Compare name and if it's an exact match, return the index
                 * and buffer. If it's the first case-insensitive match, store
@@ -770,20 +772,21 @@ xfs_dir2_block_removename(
        tp = args->trans;
        mp = dp->i_mount;
        hdr = bp->b_addr;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Point to the data entry using the leaf entry.
         */
-       dep = (xfs_dir2_data_entry_t *)
-             ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+       dep = (xfs_dir2_data_entry_t *)((char *)hdr +
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(blp[ent].address)));
        /*
         * Mark the data entry's space free.
         */
        needlog = needscan = 0;
-       xfs_dir2_data_make_free(tp, bp,
+       xfs_dir2_data_make_free(args, bp,
                (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
-               xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
+               dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
        /*
         * Fix up the block tail.
         */
@@ -798,9 +801,9 @@ xfs_dir2_block_removename(
         * Fix up bestfree, log the header if necessary.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, bp);
+               xfs_dir2_data_log_header(args, bp);
        xfs_dir3_data_check(dp, bp);
        /*
         * See if the size as a shortform is good enough.
@@ -845,20 +848,21 @@ xfs_dir2_block_replace(
        dp = args->dp;
        mp = dp->i_mount;
        hdr = bp->b_addr;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Point to the data entry we need to change.
         */
-       dep = (xfs_dir2_data_entry_t *)
-             ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+       dep = (xfs_dir2_data_entry_t *)((char *)hdr +
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(blp[ent].address)));
        ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
        /*
         * Change the inode number to the new value.
         */
        dep->inumber = cpu_to_be64(args->inumber);
-       xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
-       xfs_dir2_data_log_entry(args->trans, bp, dep);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
+       xfs_dir2_data_log_entry(args, bp, dep);
        xfs_dir3_data_check(dp, bp);
        return 0;
 }
@@ -916,9 +920,9 @@ xfs_dir2_leaf_to_block(
        tp = args->trans;
        mp = dp->i_mount;
        leaf = lbp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 
        ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
               leafhdr.magic == XFS_DIR3_LEAF1_MAGIC);
@@ -928,13 +932,13 @@ xfs_dir2_leaf_to_block(
         * been left behind during no-space-reservation operations.
         * These will show up in the leaf bests table.
         */
-       while (dp->i_d.di_size > mp->m_dirblksize) {
+       while (dp->i_d.di_size > args->geo->blksize) {
                int hdrsz;
 
-               hdrsz = xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
+               hdrsz = dp->d_ops->data_entry_offset;
                bestsp = xfs_dir2_leaf_bests_p(ltp);
                if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
-                                           mp->m_dirblksize - hdrsz) {
+                                           args->geo->blksize - hdrsz) {
                        if ((error =
                            xfs_dir2_leaf_trim_data(args, lbp,
                                    (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
@@ -946,7 +950,7 @@ xfs_dir2_leaf_to_block(
         * Read the data block if we don't already have it, give up if it fails.
         */
        if (!dbp) {
-               error = xfs_dir3_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp);
+               error = xfs_dir3_data_read(tp, dp, args->geo->datablk, -1, &dbp);
                if (error)
                        return error;
        }
@@ -962,7 +966,7 @@ xfs_dir2_leaf_to_block(
        /*
         * Look at the last data entry.
         */
-       tagp = (__be16 *)((char *)hdr + mp->m_dirblksize) - 1;
+       tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1;
        dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
        /*
         * If it's not free or is too short we can't do it.
@@ -981,12 +985,12 @@ xfs_dir2_leaf_to_block(
        /*
         * Use up the space at the end of the block (blp/btp).
         */
-       xfs_dir2_data_use_free(tp, dbp, dup, mp->m_dirblksize - size, size,
+       xfs_dir2_data_use_free(args, dbp, dup, args->geo->blksize - size, size,
                &needlog, &needscan);
        /*
         * Initialize the block tail.
         */
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale);
        btp->stale = 0;
        xfs_dir2_block_log_tail(tp, dbp);
@@ -1005,13 +1009,13 @@ xfs_dir2_leaf_to_block(
         * Scan the bestfree if we need it and log the data block header.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
+               xfs_dir2_data_log_header(args, dbp);
        /*
         * Pitch the old leaf block.
         */
-       error = xfs_da_shrink_inode(args, mp->m_dirleafblk, lbp);
+       error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp);
        if (error)
                return error;
 
@@ -1118,15 +1122,15 @@ xfs_dir2_sf_to_block(
         * The whole thing is initialized to free by the init routine.
         * Say we're using the leaf and tail area.
         */
-       dup = xfs_dir3_data_unused_p(hdr);
+       dup = dp->d_ops->data_unused_p(hdr);
        needlog = needscan = 0;
-       xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog,
-               &needscan);
+       xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,
+                              i, &needlog, &needscan);
        ASSERT(needscan == 0);
        /*
         * Fill in the tail.
         */
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        btp->count = cpu_to_be32(sfp->count + 2);       /* ., .. */
        btp->stale = 0;
        blp = xfs_dir2_block_leaf_p(btp);
@@ -1134,38 +1138,38 @@ xfs_dir2_sf_to_block(
        /*
         * Remove the freespace, we'll manage it.
         */
-       xfs_dir2_data_use_free(tp, bp, dup,
+       xfs_dir2_data_use_free(args, bp, dup,
                (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
                be16_to_cpu(dup->length), &needlog, &needscan);
        /*
         * Create entry for .
         */
-       dep = xfs_dir3_data_dot_entry_p(mp, hdr);
+       dep = dp->d_ops->data_dot_entry_p(hdr);
        dep->inumber = cpu_to_be64(dp->i_ino);
        dep->namelen = 1;
        dep->name[0] = '.';
-       xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-       xfs_dir2_data_log_entry(tp, bp, dep);
+       xfs_dir2_data_log_entry(args, bp, dep);
        blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
-       blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+       blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                (char *)dep - (char *)hdr));
        /*
         * Create entry for ..
         */
-       dep = xfs_dir3_data_dotdot_entry_p(mp, hdr);
-       dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
+       dep = dp->d_ops->data_dotdot_entry_p(hdr);
+       dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp));
        dep->namelen = 2;
        dep->name[0] = dep->name[1] = '.';
-       xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-       xfs_dir2_data_log_entry(tp, bp, dep);
+       xfs_dir2_data_log_entry(args, bp, dep);
        blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
-       blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+       blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                (char *)dep - (char *)hdr));
-       offset = xfs_dir3_data_first_offset(mp);
+       offset = dp->d_ops->data_first_offset;
        /*
         * Loop over existing entries, stuff them in.
         */
@@ -1195,8 +1199,10 @@ xfs_dir2_sf_to_block(
                        dup->length = cpu_to_be16(newoffset - offset);
                        *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
                                ((char *)dup - (char *)hdr));
-                       xfs_dir2_data_log_unused(tp, bp, dup);
-                       xfs_dir2_data_freeinsert(hdr, dup, &dummy);
+                       xfs_dir2_data_log_unused(args, bp, dup);
+                       xfs_dir2_data_freeinsert(hdr,
+                                                dp->d_ops->data_bestfree_p(hdr),
+                                                dup, &dummy);
                        offset += be16_to_cpu(dup->length);
                        continue;
                }
@@ -1204,25 +1210,24 @@ xfs_dir2_sf_to_block(
                 * Copy a real entry.
                 */
                dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
-               dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep));
+               dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep));
                dep->namelen = sfep->namelen;
-               xfs_dir3_dirent_put_ftype(mp, dep,
-                                       xfs_dir3_sfe_get_ftype(mp, sfp, sfep));
+               dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep));
                memcpy(dep->name, sfep->name, dep->namelen);
-               tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+               tagp = dp->d_ops->data_entry_tag_p(dep);
                *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-               xfs_dir2_data_log_entry(tp, bp, dep);
+               xfs_dir2_data_log_entry(args, bp, dep);
                name.name = sfep->name;
                name.len = sfep->namelen;
                blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
                                                        hashname(&name));
-               blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+               blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                                 (char *)dep - (char *)hdr));
                offset = (int)((char *)(tagp + 1) - (char *)hdr);
                if (++i == sfp->count)
                        sfep = NULL;
                else
-                       sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
+                       sfep = dp->d_ops->sf_nextentry(sfp, sfep);
        }
        /* Done with the temporary buffer */
        kmem_free(sfp);
index dc9df4d96398eab1ce8d3fcb74dc517869f50c3a..40ff57c2ece4f42f3f3c46bee99bbb4c430cc1de 100644 (file)
@@ -47,32 +47,52 @@ __xfs_dir3_data_check(
        char                    *p;             /* current data position */
        int                     stale;          /* count of stale leaves */
        struct xfs_name         name;
+       const struct xfs_dir_ops *ops;
+       struct xfs_da_geometry  *geo;
 
        mp = bp->b_target->bt_mount;
+       geo = mp->m_dir_geo;
+
+       /*
+        * We can be passed a null dp here from a verifier, so we need to go the
+        * hard way to get them.
+        */
+       ops = xfs_dir_get_ops(mp, dp);
+
        hdr = bp->b_addr;
-       bf = xfs_dir3_data_bestfree_p(hdr);
-       p = (char *)xfs_dir3_data_entry_p(hdr);
+       p = (char *)ops->data_entry_p(hdr);
 
        switch (hdr->magic) {
        case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
        case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
-               btp = xfs_dir2_block_tail_p(mp, hdr);
+               btp = xfs_dir2_block_tail_p(geo, hdr);
                lep = xfs_dir2_block_leaf_p(btp);
                endp = (char *)lep;
+
+               /*
+                * The number of leaf entries is limited by the size of the
+                * block and the amount of space used by the data entries.
+                * We don't know how much space is used by the data entries yet,
+                * so just ensure that the count falls somewhere inside the
+                * block right now.
+                */
+               XFS_WANT_CORRUPTED_RETURN(be32_to_cpu(btp->count) <
+                       ((char *)btp - p) / sizeof(struct xfs_dir2_leaf_entry));
                break;
        case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
        case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
-               endp = (char *)hdr + mp->m_dirblksize;
+               endp = (char *)hdr + geo->blksize;
                break;
        default:
                XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp);
                return EFSCORRUPTED;
        }
 
-       count = lastfree = freeseen = 0;
        /*
         * Account for zero bestfree entries.
         */
+       bf = ops->data_bestfree_p(hdr);
+       count = lastfree = freeseen = 0;
        if (!bf[0].length) {
                XFS_WANT_CORRUPTED_RETURN(!bf[0].offset);
                freeseen |= 1 << 0;
@@ -105,7 +125,7 @@ __xfs_dir3_data_check(
                        XFS_WANT_CORRUPTED_RETURN(
                                be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
                                               (char *)dup - (char *)hdr);
-                       dfp = xfs_dir2_data_freefind(hdr, dup);
+                       dfp = xfs_dir2_data_freefind(hdr, bf, dup);
                        if (dfp) {
                                i = (int)(dfp - bf);
                                XFS_WANT_CORRUPTED_RETURN(
@@ -131,17 +151,17 @@ __xfs_dir3_data_check(
                XFS_WANT_CORRUPTED_RETURN(
                        !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
                XFS_WANT_CORRUPTED_RETURN(
-                       be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) ==
+                       be16_to_cpu(*ops->data_entry_tag_p(dep)) ==
                                               (char *)dep - (char *)hdr);
                XFS_WANT_CORRUPTED_RETURN(
-                       xfs_dir3_dirent_get_ftype(mp, dep) < XFS_DIR3_FT_MAX);
+                               ops->data_get_ftype(dep) < XFS_DIR3_FT_MAX);
                count++;
                lastfree = 0;
                if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
                    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
-                       addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
-                               (xfs_dir2_data_aoff_t)
-                               ((char *)dep - (char *)hdr));
+                       addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
+                                               (xfs_dir2_data_aoff_t)
+                                               ((char *)dep - (char *)hdr));
                        name.name = dep->name;
                        name.len = dep->namelen;
                        hash = mp->m_dirnameops->hashname(&name);
@@ -152,7 +172,7 @@ __xfs_dir3_data_check(
                        }
                        XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
                }
-               p += xfs_dir3_data_entsize(mp, dep->namelen);
+               p += ops->data_entsize(dep->namelen);
        }
        /*
         * Need to have seen all the entries and all the bestfree slots.
@@ -296,12 +316,11 @@ xfs_dir3_data_read(
 
 int
 xfs_dir3_data_readahead(
-       struct xfs_trans        *tp,
        struct xfs_inode        *dp,
        xfs_dablk_t             bno,
        xfs_daddr_t             mapped_bno)
 {
-       return xfs_da_reada_buf(tp, dp, bno, mapped_bno,
+       return xfs_da_reada_buf(dp, bno, mapped_bno,
                                XFS_DATA_FORK, &xfs_dir3_data_reada_buf_ops);
 }
 
@@ -311,19 +330,18 @@ xfs_dir3_data_readahead(
  */
 xfs_dir2_data_free_t *
 xfs_dir2_data_freefind(
-       xfs_dir2_data_hdr_t     *hdr,           /* data block */
-       xfs_dir2_data_unused_t  *dup)           /* data unused entry */
+       struct xfs_dir2_data_hdr *hdr,          /* data block header */
+       struct xfs_dir2_data_free *bf,          /* bestfree table pointer */
+       struct xfs_dir2_data_unused *dup)       /* unused space */
 {
        xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
        xfs_dir2_data_aoff_t    off;            /* offset value needed */
-       struct xfs_dir2_data_free *bf;
 #ifdef DEBUG
        int                     matched;        /* matched the value */
        int                     seenzero;       /* saw a 0 bestfree entry */
 #endif
 
        off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
-       bf = xfs_dir3_data_bestfree_p(hdr);
 
 #ifdef DEBUG
        /*
@@ -383,11 +401,11 @@ xfs_dir2_data_freefind(
  */
 xfs_dir2_data_free_t *                         /* entry inserted */
 xfs_dir2_data_freeinsert(
-       xfs_dir2_data_hdr_t     *hdr,           /* data block pointer */
-       xfs_dir2_data_unused_t  *dup,           /* unused space */
+       struct xfs_dir2_data_hdr *hdr,          /* data block pointer */
+       struct xfs_dir2_data_free *dfp,         /* bestfree table pointer */
+       struct xfs_dir2_data_unused *dup,       /* unused space */
        int                     *loghead)       /* log the data header (out) */
 {
-       xfs_dir2_data_free_t    *dfp;           /* bestfree table pointer */
        xfs_dir2_data_free_t    new;            /* new bestfree entry */
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
@@ -395,7 +413,6 @@ xfs_dir2_data_freeinsert(
               hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
 
-       dfp = xfs_dir3_data_bestfree_p(hdr);
        new.length = dup->length;
        new.offset = cpu_to_be16((char *)dup - (char *)hdr);
 
@@ -428,11 +445,11 @@ xfs_dir2_data_freeinsert(
  */
 STATIC void
 xfs_dir2_data_freeremove(
-       xfs_dir2_data_hdr_t     *hdr,           /* data block header */
-       xfs_dir2_data_free_t    *dfp,           /* bestfree entry pointer */
+       struct xfs_dir2_data_hdr *hdr,          /* data block header */
+       struct xfs_dir2_data_free *bf,          /* bestfree table pointer */
+       struct xfs_dir2_data_free *dfp,         /* bestfree entry pointer */
        int                     *loghead)       /* out: log data header */
 {
-       struct xfs_dir2_data_free *bf;
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
@@ -442,7 +459,6 @@ xfs_dir2_data_freeremove(
        /*
         * It's the first entry, slide the next 2 up.
         */
-       bf = xfs_dir3_data_bestfree_p(hdr);
        if (dfp == &bf[0]) {
                bf[0] = bf[1];
                bf[1] = bf[2];
@@ -467,12 +483,17 @@ xfs_dir2_data_freeremove(
 
 /*
  * Given a data block, reconstruct its bestfree map.
+ *
+ * This is shared with userspace and called from contexts without a struct
+ * xfs_inode. Hence we pass the fundamental objects to the function rather than
+ * a higher level construct like inodes or xfs_da_args.
  */
 void
 xfs_dir2_data_freescan(
-       xfs_mount_t             *mp,            /* filesystem mount point */
-       xfs_dir2_data_hdr_t     *hdr,           /* data block header */
-       int                     *loghead)       /* out: log data header */
+       struct xfs_da_geometry  *geo,
+       const struct xfs_dir_ops *ops,
+       struct xfs_dir2_data_hdr *hdr,
+       int                     *loghead)
 {
        xfs_dir2_block_tail_t   *btp;           /* block tail */
        xfs_dir2_data_entry_t   *dep;           /* active data entry */
@@ -489,19 +510,19 @@ xfs_dir2_data_freescan(
        /*
         * Start by clearing the table.
         */
-       bf = xfs_dir3_data_bestfree_p(hdr);
+       bf = ops->data_bestfree_p(hdr);
        memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);
        *loghead = 1;
        /*
         * Set up pointers.
         */
-       p = (char *)xfs_dir3_data_entry_p(hdr);
+       p = (char *)ops->data_entry_p(hdr);
        if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
-               btp = xfs_dir2_block_tail_p(mp, hdr);
+               btp = xfs_dir2_block_tail_p(geo, hdr);
                endp = (char *)xfs_dir2_block_leaf_p(btp);
        } else
-               endp = (char *)hdr + mp->m_dirblksize;
+               endp = (char *)hdr + geo->blksize;
        /*
         * Loop over the block's entries.
         */
@@ -513,7 +534,7 @@ xfs_dir2_data_freescan(
                if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
                        ASSERT((char *)dup - (char *)hdr ==
                               be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
-                       xfs_dir2_data_freeinsert(hdr, dup, loghead);
+                       xfs_dir2_data_freeinsert(hdr, bf, dup, loghead);
                        p += be16_to_cpu(dup->length);
                }
                /*
@@ -522,8 +543,8 @@ xfs_dir2_data_freescan(
                else {
                        dep = (xfs_dir2_data_entry_t *)p;
                        ASSERT((char *)dep - (char *)hdr ==
-                              be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)));
-                       p += xfs_dir3_data_entsize(mp, dep->namelen);
+                              be16_to_cpu(*ops->data_entry_tag_p(dep)));
+                       p += ops->data_entsize(dep->namelen);
                }
        }
 }
@@ -555,8 +576,8 @@ xfs_dir3_data_init(
        /*
         * Get the buffer set up for the block.
         */
-       error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
-               XFS_DATA_FORK);
+       error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno),
+                              -1, &bp, XFS_DATA_FORK);
        if (error)
                return error;
        bp->b_ops = &xfs_dir3_data_buf_ops;
@@ -578,8 +599,8 @@ xfs_dir3_data_init(
        } else
                hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
 
-       bf = xfs_dir3_data_bestfree_p(hdr);
-       bf[0].offset = cpu_to_be16(xfs_dir3_data_entry_offset(hdr));
+       bf = dp->d_ops->data_bestfree_p(hdr);
+       bf[0].offset = cpu_to_be16(dp->d_ops->data_entry_offset);
        for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
                bf[i].length = 0;
                bf[i].offset = 0;
@@ -588,18 +609,18 @@ xfs_dir3_data_init(
        /*
         * Set up an unused entry for the block's body.
         */
-       dup = xfs_dir3_data_unused_p(hdr);
+       dup = dp->d_ops->data_unused_p(hdr);
        dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 
-       t = mp->m_dirblksize - (uint)xfs_dir3_data_entry_offset(hdr);
+       t = args->geo->blksize - (uint)dp->d_ops->data_entry_offset;
        bf[0].length = cpu_to_be16(t);
        dup->length = cpu_to_be16(t);
        *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
        /*
         * Log it and return it.
         */
-       xfs_dir2_data_log_header(tp, bp);
-       xfs_dir2_data_log_unused(tp, bp, dup);
+       xfs_dir2_data_log_header(args, bp);
+       xfs_dir2_data_log_unused(args, bp, dup);
        *bpp = bp;
        return 0;
 }
@@ -609,20 +630,19 @@ xfs_dir3_data_init(
  */
 void
 xfs_dir2_data_log_entry(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp,
        xfs_dir2_data_entry_t   *dep)           /* data entry pointer */
 {
        struct xfs_dir2_data_hdr *hdr = bp->b_addr;
-       struct xfs_mount        *mp = tp->t_mountp;
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
 
-       xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
-               (uint)((char *)(xfs_dir3_data_entry_tag_p(mp, dep) + 1) -
+       xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr),
+               (uint)((char *)(args->dp->d_ops->data_entry_tag_p(dep) + 1) -
                       (char *)hdr - 1));
 }
 
@@ -631,17 +651,20 @@ xfs_dir2_data_log_entry(
  */
 void
 xfs_dir2_data_log_header(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp)
 {
-       xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
+#ifdef DEBUG
+       struct xfs_dir2_data_hdr *hdr = bp->b_addr;
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
+#endif
 
-       xfs_trans_log_buf(tp, bp, 0, xfs_dir3_data_entry_offset(hdr) - 1);
+       xfs_trans_log_buf(args->trans, bp, 0,
+                         args->dp->d_ops->data_entry_offset - 1);
 }
 
 /*
@@ -649,7 +672,7 @@ xfs_dir2_data_log_header(
  */
 void
 xfs_dir2_data_log_unused(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp,
        xfs_dir2_data_unused_t  *dup)           /* data unused pointer */
 {
@@ -663,13 +686,13 @@ xfs_dir2_data_log_unused(
        /*
         * Log the first part of the unused entry.
         */
-       xfs_trans_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr),
+       xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr),
                (uint)((char *)&dup->length + sizeof(dup->length) -
                       1 - (char *)hdr));
        /*
         * Log the end (tag) of the unused entry.
         */
-       xfs_trans_log_buf(tp, bp,
+       xfs_trans_log_buf(args->trans, bp,
                (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
                (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
                       sizeof(xfs_dir2_data_off_t) - 1));
@@ -681,7 +704,7 @@ xfs_dir2_data_log_unused(
  */
 void
 xfs_dir2_data_make_free(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp,
        xfs_dir2_data_aoff_t    offset,         /* starting byte offset */
        xfs_dir2_data_aoff_t    len,            /* length in bytes */
@@ -691,14 +714,12 @@ xfs_dir2_data_make_free(
        xfs_dir2_data_hdr_t     *hdr;           /* data block pointer */
        xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
        char                    *endptr;        /* end of data area */
-       xfs_mount_t             *mp;            /* filesystem mount point */
        int                     needscan;       /* need to regen bestfree */
        xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
        xfs_dir2_data_unused_t  *postdup;       /* unused entry after us */
        xfs_dir2_data_unused_t  *prevdup;       /* unused entry before us */
        struct xfs_dir2_data_free *bf;
 
-       mp = tp->t_mountp;
        hdr = bp->b_addr;
 
        /*
@@ -706,20 +727,20 @@ xfs_dir2_data_make_free(
         */
        if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC))
-               endptr = (char *)hdr + mp->m_dirblksize;
+               endptr = (char *)hdr + args->geo->blksize;
        else {
                xfs_dir2_block_tail_t   *btp;   /* block tail */
 
                ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
                        hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
-               btp = xfs_dir2_block_tail_p(mp, hdr);
+               btp = xfs_dir2_block_tail_p(args->geo, hdr);
                endptr = (char *)xfs_dir2_block_leaf_p(btp);
        }
        /*
         * If this isn't the start of the block, then back up to
         * the previous entry and see if it's free.
         */
-       if (offset > xfs_dir3_data_entry_offset(hdr)) {
+       if (offset > args->dp->d_ops->data_entry_offset) {
                __be16                  *tagp;  /* tag just before us */
 
                tagp = (__be16 *)((char *)hdr + offset) - 1;
@@ -745,15 +766,15 @@ xfs_dir2_data_make_free(
         * Previous and following entries are both free,
         * merge everything into a single free entry.
         */
-       bf = xfs_dir3_data_bestfree_p(hdr);
+       bf = args->dp->d_ops->data_bestfree_p(hdr);
        if (prevdup && postdup) {
                xfs_dir2_data_free_t    *dfp2;  /* another bestfree pointer */
 
                /*
                 * See if prevdup and/or postdup are in bestfree table.
                 */
-               dfp = xfs_dir2_data_freefind(hdr, prevdup);
-               dfp2 = xfs_dir2_data_freefind(hdr, postdup);
+               dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
+               dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup);
                /*
                 * We need a rescan unless there are exactly 2 free entries
                 * namely our two.  Then we know what's happening, otherwise
@@ -767,7 +788,7 @@ xfs_dir2_data_make_free(
                be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
                *xfs_dir2_data_unused_tag_p(prevdup) =
                        cpu_to_be16((char *)prevdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, prevdup);
+               xfs_dir2_data_log_unused(args, bp, prevdup);
                if (!needscan) {
                        /*
                         * Has to be the case that entries 0 and 1 are
@@ -781,12 +802,13 @@ xfs_dir2_data_make_free(
                                ASSERT(dfp2 == dfp);
                                dfp2 = &bf[1];
                        }
-                       xfs_dir2_data_freeremove(hdr, dfp2, needlogp);
-                       xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+                       xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp);
+                       xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
                        /*
                         * Now insert the new entry.
                         */
-                       dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
+                       dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup,
+                                                      needlogp);
                        ASSERT(dfp == &bf[0]);
                        ASSERT(dfp->length == prevdup->length);
                        ASSERT(!dfp[1].length);
@@ -797,19 +819,19 @@ xfs_dir2_data_make_free(
         * The entry before us is free, merge with it.
         */
        else if (prevdup) {
-               dfp = xfs_dir2_data_freefind(hdr, prevdup);
+               dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
                be16_add_cpu(&prevdup->length, len);
                *xfs_dir2_data_unused_tag_p(prevdup) =
                        cpu_to_be16((char *)prevdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, prevdup);
+               xfs_dir2_data_log_unused(args, bp, prevdup);
                /*
                 * If the previous entry was in the table, the new entry
                 * is longer, so it will be in the table too.  Remove
                 * the old one and add the new one.
                 */
                if (dfp) {
-                       xfs_dir2_data_freeremove(hdr, dfp, needlogp);
-                       xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
+                       xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
+                       xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp);
                }
                /*
                 * Otherwise we need a scan if the new entry is big enough.
@@ -823,21 +845,21 @@ xfs_dir2_data_make_free(
         * The following entry is free, merge with it.
         */
        else if (postdup) {
-               dfp = xfs_dir2_data_freefind(hdr, postdup);
+               dfp = xfs_dir2_data_freefind(hdr, bf, postdup);
                newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
                newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
                newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
                *xfs_dir2_data_unused_tag_p(newdup) =
                        cpu_to_be16((char *)newdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, newdup);
+               xfs_dir2_data_log_unused(args, bp, newdup);
                /*
                 * If the following entry was in the table, the new entry
                 * is longer, so it will be in the table too.  Remove
                 * the old one and add the new one.
                 */
                if (dfp) {
-                       xfs_dir2_data_freeremove(hdr, dfp, needlogp);
-                       xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
+                       xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
+                       xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
                }
                /*
                 * Otherwise we need a scan if the new entry is big enough.
@@ -856,8 +878,8 @@ xfs_dir2_data_make_free(
                newdup->length = cpu_to_be16(len);
                *xfs_dir2_data_unused_tag_p(newdup) =
                        cpu_to_be16((char *)newdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, newdup);
-               xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
+               xfs_dir2_data_log_unused(args, bp, newdup);
+               xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
        }
        *needscanp = needscan;
 }
@@ -867,7 +889,7 @@ xfs_dir2_data_make_free(
  */
 void
 xfs_dir2_data_use_free(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp,
        xfs_dir2_data_unused_t  *dup,           /* unused entry */
        xfs_dir2_data_aoff_t    offset,         /* starting offset to use */
@@ -897,9 +919,9 @@ xfs_dir2_data_use_free(
        /*
         * Look up the entry in the bestfree table.
         */
-       dfp = xfs_dir2_data_freefind(hdr, dup);
        oldlen = be16_to_cpu(dup->length);
-       bf = xfs_dir3_data_bestfree_p(hdr);
+       bf = args->dp->d_ops->data_bestfree_p(hdr);
+       dfp = xfs_dir2_data_freefind(hdr, bf, dup);
        ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));
        /*
         * Check for alignment with front and back of the entry.
@@ -916,7 +938,8 @@ xfs_dir2_data_use_free(
                if (dfp) {
                        needscan = (bf[2].offset != 0);
                        if (!needscan)
-                               xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+                               xfs_dir2_data_freeremove(hdr, bf, dfp,
+                                                        needlogp);
                }
        }
        /*
@@ -929,13 +952,14 @@ xfs_dir2_data_use_free(
                newdup->length = cpu_to_be16(oldlen - len);
                *xfs_dir2_data_unused_tag_p(newdup) =
                        cpu_to_be16((char *)newdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, newdup);
+               xfs_dir2_data_log_unused(args, bp, newdup);
                /*
                 * If it was in the table, remove it and add the new one.
                 */
                if (dfp) {
-                       xfs_dir2_data_freeremove(hdr, dfp, needlogp);
-                       dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
+                       xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
+                       dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
+                                                      needlogp);
                        ASSERT(dfp != NULL);
                        ASSERT(dfp->length == newdup->length);
                        ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
@@ -956,13 +980,14 @@ xfs_dir2_data_use_free(
                newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
                *xfs_dir2_data_unused_tag_p(newdup) =
                        cpu_to_be16((char *)newdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, newdup);
+               xfs_dir2_data_log_unused(args, bp, newdup);
                /*
                 * If it was in the table, remove it and add the new one.
                 */
                if (dfp) {
-                       xfs_dir2_data_freeremove(hdr, dfp, needlogp);
-                       dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
+                       xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
+                       dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
+                                                      needlogp);
                        ASSERT(dfp != NULL);
                        ASSERT(dfp->length == newdup->length);
                        ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
@@ -983,13 +1008,13 @@ xfs_dir2_data_use_free(
                newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
                *xfs_dir2_data_unused_tag_p(newdup) =
                        cpu_to_be16((char *)newdup - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, newdup);
+               xfs_dir2_data_log_unused(args, bp, newdup);
                newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
                newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
                newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
                *xfs_dir2_data_unused_tag_p(newdup2) =
                        cpu_to_be16((char *)newdup2 - (char *)hdr);
-               xfs_dir2_data_log_unused(tp, bp, newdup2);
+               xfs_dir2_data_log_unused(args, bp, newdup2);
                /*
                 * If the old entry was in the table, we need to scan
                 * if the 3rd entry was valid, since these entries
@@ -1001,9 +1026,11 @@ xfs_dir2_data_use_free(
                if (dfp) {
                        needscan = (bf[2].length != 0);
                        if (!needscan) {
-                               xfs_dir2_data_freeremove(hdr, dfp, needlogp);
-                               xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
-                               xfs_dir2_data_freeinsert(hdr, newdup2,
+                               xfs_dir2_data_freeremove(hdr, bf, dfp,
+                                                        needlogp);
+                               xfs_dir2_data_freeinsert(hdr, bf, newdup,
+                                                        needlogp);
+                               xfs_dir2_data_freeinsert(hdr, bf, newdup2,
                                                         needlogp);
                        }
                }
index 8e0cbc971b69394605856e5eedb821f20bf74844..9e8ed9c31470795f2b68aa628636328afcb484c0 100644 (file)
  */
 static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp,
                                    int *indexp, struct xfs_buf **dbpp);
-static void xfs_dir3_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp,
-                                   int first, int last);
-static void xfs_dir3_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp);
+static void xfs_dir3_leaf_log_bests(struct xfs_da_args *args,
+                                   struct xfs_buf *bp, int first, int last);
+static void xfs_dir3_leaf_log_tail(struct xfs_da_args *args,
+                                  struct xfs_buf *bp);
 
 /*
  * Check the internal consistency of a leaf1 block.
  * Pop an assert if something is wrong.
  */
 #ifdef DEBUG
-#define        xfs_dir3_leaf_check(mp, bp) \
+#define        xfs_dir3_leaf_check(dp, bp) \
 do { \
-       if (!xfs_dir3_leaf1_check((mp), (bp))) \
+       if (!xfs_dir3_leaf1_check((dp), (bp))) \
                ASSERT(0); \
 } while (0);
 
 STATIC bool
 xfs_dir3_leaf1_check(
-       struct xfs_mount        *mp,
+       struct xfs_inode        *dp,
        struct xfs_buf          *bp)
 {
        struct xfs_dir2_leaf    *leaf = bp->b_addr;
        struct xfs_dir3_icleaf_hdr leafhdr;
 
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
 
        if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) {
                struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
@@ -56,71 +57,16 @@ xfs_dir3_leaf1_check(
        } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC)
                return false;
 
-       return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
+       return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf);
 }
 #else
-#define        xfs_dir3_leaf_check(mp, bp)
+#define        xfs_dir3_leaf_check(dp, bp)
 #endif
 
-void
-xfs_dir3_leaf_hdr_from_disk(
-       struct xfs_dir3_icleaf_hdr      *to,
-       struct xfs_dir2_leaf            *from)
-{
-       if (from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) ||
-           from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) {
-               to->forw = be32_to_cpu(from->hdr.info.forw);
-               to->back = be32_to_cpu(from->hdr.info.back);
-               to->magic = be16_to_cpu(from->hdr.info.magic);
-               to->count = be16_to_cpu(from->hdr.count);
-               to->stale = be16_to_cpu(from->hdr.stale);
-       } else {
-               struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from;
-
-               to->forw = be32_to_cpu(hdr3->info.hdr.forw);
-               to->back = be32_to_cpu(hdr3->info.hdr.back);
-               to->magic = be16_to_cpu(hdr3->info.hdr.magic);
-               to->count = be16_to_cpu(hdr3->count);
-               to->stale = be16_to_cpu(hdr3->stale);
-       }
-
-       ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC ||
-              to->magic == XFS_DIR3_LEAF1_MAGIC ||
-              to->magic == XFS_DIR2_LEAFN_MAGIC ||
-              to->magic == XFS_DIR3_LEAFN_MAGIC);
-}
-
-void
-xfs_dir3_leaf_hdr_to_disk(
-       struct xfs_dir2_leaf            *to,
-       struct xfs_dir3_icleaf_hdr      *from)
-{
-       ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC ||
-              from->magic == XFS_DIR3_LEAF1_MAGIC ||
-              from->magic == XFS_DIR2_LEAFN_MAGIC ||
-              from->magic == XFS_DIR3_LEAFN_MAGIC);
-
-       if (from->magic == XFS_DIR2_LEAF1_MAGIC ||
-           from->magic == XFS_DIR2_LEAFN_MAGIC) {
-               to->hdr.info.forw = cpu_to_be32(from->forw);
-               to->hdr.info.back = cpu_to_be32(from->back);
-               to->hdr.info.magic = cpu_to_be16(from->magic);
-               to->hdr.count = cpu_to_be16(from->count);
-               to->hdr.stale = cpu_to_be16(from->stale);
-       } else {
-               struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to;
-
-               hdr3->info.hdr.forw = cpu_to_be32(from->forw);
-               hdr3->info.hdr.back = cpu_to_be32(from->back);
-               hdr3->info.hdr.magic = cpu_to_be16(from->magic);
-               hdr3->count = cpu_to_be16(from->count);
-               hdr3->stale = cpu_to_be16(from->stale);
-       }
-}
-
 bool
 xfs_dir3_leaf_check_int(
        struct xfs_mount        *mp,
+       struct xfs_inode        *dp,
        struct xfs_dir3_icleaf_hdr *hdr,
        struct xfs_dir2_leaf    *leaf)
 {
@@ -128,16 +74,30 @@ xfs_dir3_leaf_check_int(
        xfs_dir2_leaf_tail_t    *ltp;
        int                     stale;
        int                     i;
+       const struct xfs_dir_ops *ops;
+       struct xfs_dir3_icleaf_hdr leafhdr;
+       struct xfs_da_geometry  *geo = mp->m_dir_geo;
 
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       /*
+        * we can be passed a null dp here from a verifier, so we need to go the
+        * hard way to get them.
+        */
+       ops = xfs_dir_get_ops(mp, dp);
+
+       if (!hdr) {
+               ops->leaf_hdr_from_disk(&leafhdr, leaf);
+               hdr = &leafhdr;
+       }
+
+       ents = ops->leaf_ents_p(leaf);
+       ltp = xfs_dir2_leaf_tail_p(geo, leaf);
 
        /*
         * XXX (dgc): This value is not restrictive enough.
         * Should factor in the size of the bests table as well.
         * We can deduce a value for that from di_size.
         */
-       if (hdr->count > xfs_dir3_max_leaf_ents(mp, leaf))
+       if (hdr->count > ops->leaf_max_ents(geo))
                return false;
 
        /* Leaves and bests don't overlap in leaf format. */
@@ -173,7 +133,6 @@ xfs_dir3_leaf_verify(
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
        struct xfs_dir2_leaf    *leaf = bp->b_addr;
-       struct xfs_dir3_icleaf_hdr leafhdr;
 
        ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC);
 
@@ -195,8 +154,7 @@ xfs_dir3_leaf_verify(
                        return false;
        }
 
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
+       return xfs_dir3_leaf_check_int(mp, NULL, NULL, leaf);
 }
 
 static void
@@ -350,7 +308,7 @@ xfs_dir3_leaf_init(
        if (type == XFS_DIR2_LEAF1_MAGIC) {
                struct xfs_dir2_leaf_tail *ltp;
 
-               ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+               ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
                ltp->bestcount = 0;
                bp->b_ops = &xfs_dir3_leaf1_buf_ops;
                xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAF1_BUF);
@@ -374,18 +332,18 @@ xfs_dir3_leaf_get_buf(
        int                     error;
 
        ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC);
-       ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) &&
-              bno < XFS_DIR2_FREE_FIRSTDB(mp));
+       ASSERT(bno >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET) &&
+              bno < xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET));
 
-       error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,
-                              XFS_DATA_FORK);
+       error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, bno),
+                              -1, &bp, XFS_DATA_FORK);
        if (error)
                return error;
 
        xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic);
-       xfs_dir3_leaf_log_header(tp, bp);
+       xfs_dir3_leaf_log_header(args, bp);
        if (magic == XFS_DIR2_LEAF1_MAGIC)
-               xfs_dir3_leaf_log_tail(tp, bp);
+               xfs_dir3_leaf_log_tail(args, bp);
        *bpp = bp;
        return 0;
 }
@@ -430,8 +388,8 @@ xfs_dir2_block_to_leaf(
        if ((error = xfs_da_grow_inode(args, &blkno))) {
                return error;
        }
-       ldb = xfs_dir2_da_to_db(mp, blkno);
-       ASSERT(ldb == XFS_DIR2_LEAF_FIRSTDB(mp));
+       ldb = xfs_dir2_da_to_db(args->geo, blkno);
+       ASSERT(ldb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET));
        /*
         * Initialize the leaf block, get a buffer for it.
         */
@@ -442,35 +400,35 @@ xfs_dir2_block_to_leaf(
        leaf = lbp->b_addr;
        hdr = dbp->b_addr;
        xfs_dir3_data_check(dp, dbp);
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
-       bf = xfs_dir3_data_bestfree_p(hdr);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       bf = dp->d_ops->data_bestfree_p(hdr);
+       ents = dp->d_ops->leaf_ents_p(leaf);
 
        /*
         * Set the counts in the leaf header.
         */
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
        leafhdr.count = be32_to_cpu(btp->count);
        leafhdr.stale = be32_to_cpu(btp->stale);
-       xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr);
-       xfs_dir3_leaf_log_header(tp, lbp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
+       xfs_dir3_leaf_log_header(args, lbp);
 
        /*
         * Could compact these but I think we always do the conversion
         * after squeezing out stale entries.
         */
        memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t));
-       xfs_dir3_leaf_log_ents(tp, lbp, 0, leafhdr.count - 1);
+       xfs_dir3_leaf_log_ents(args, lbp, 0, leafhdr.count - 1);
        needscan = 0;
        needlog = 1;
        /*
         * Make the space formerly occupied by the leaf entries and block
         * tail be free.
         */
-       xfs_dir2_data_make_free(tp, dbp,
+       xfs_dir2_data_make_free(args, dbp,
                (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
-               (xfs_dir2_data_aoff_t)((char *)hdr + mp->m_dirblksize -
+               (xfs_dir2_data_aoff_t)((char *)hdr + args->geo->blksize -
                                       (char *)blp),
                &needlog, &needscan);
        /*
@@ -484,11 +442,11 @@ xfs_dir2_block_to_leaf(
                hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
 
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        /*
         * Set up leaf tail and bests table.
         */
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
        ltp->bestcount = cpu_to_be32(1);
        bestsp = xfs_dir2_leaf_bests_p(ltp);
        bestsp[0] =  bf[0].length;
@@ -496,10 +454,10 @@ xfs_dir2_block_to_leaf(
         * Log the data header and leaf bests table.
         */
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
-       xfs_dir3_leaf_check(mp, lbp);
+               xfs_dir2_data_log_header(args, dbp);
+       xfs_dir3_leaf_check(dp, lbp);
        xfs_dir3_data_check(dp, dbp);
-       xfs_dir3_leaf_log_bests(tp, lbp, 0, 0);
+       xfs_dir3_leaf_log_bests(args, lbp, 0, 0);
        return 0;
 }
 
@@ -668,7 +626,7 @@ xfs_dir2_leaf_addname(
        tp = args->trans;
        mp = dp->i_mount;
 
-       error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);
+       error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, -1, &lbp);
        if (error)
                return error;
 
@@ -680,11 +638,11 @@ xfs_dir2_leaf_addname(
         */
        index = xfs_dir2_leaf_search_hash(args, lbp);
        leaf = lbp->b_addr;
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
        bestsp = xfs_dir2_leaf_bests_p(ltp);
-       length = xfs_dir3_data_entsize(mp, args->namelen);
+       length = dp->d_ops->data_entsize(args->namelen);
 
        /*
         * See if there are any entries with the same hash value
@@ -697,7 +655,7 @@ xfs_dir2_leaf_addname(
             index++, lep++) {
                if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
                        continue;
-               i = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
+               i = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
                ASSERT(i < be32_to_cpu(ltp->bestcount));
                ASSERT(bestsp[i] != cpu_to_be16(NULLDATAOFF));
                if (be16_to_cpu(bestsp[i]) >= length) {
@@ -837,16 +795,17 @@ xfs_dir2_leaf_addname(
                        memmove(&bestsp[0], &bestsp[1],
                                be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0]));
                        be32_add_cpu(&ltp->bestcount, 1);
-                       xfs_dir3_leaf_log_tail(tp, lbp);
-                       xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
+                       xfs_dir3_leaf_log_tail(args, lbp);
+                       xfs_dir3_leaf_log_bests(args, lbp, 0,
+                                               be32_to_cpu(ltp->bestcount) - 1);
                }
                /*
                 * If we're filling in a previously empty block just log it.
                 */
                else
-                       xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block);
+                       xfs_dir3_leaf_log_bests(args, lbp, use_block, use_block);
                hdr = dbp->b_addr;
-               bf = xfs_dir3_data_bestfree_p(hdr);
+               bf = dp->d_ops->data_bestfree_p(hdr);
                bestsp[use_block] = bf[0].length;
                grown = 1;
        } else {
@@ -855,14 +814,14 @@ xfs_dir2_leaf_addname(
                 * Just read that one in.
                 */
                error = xfs_dir3_data_read(tp, dp,
-                                          xfs_dir2_db_to_da(mp, use_block),
-                                          -1, &dbp);
+                                  xfs_dir2_db_to_da(args->geo, use_block),
+                                  -1, &dbp);
                if (error) {
                        xfs_trans_brelse(tp, lbp);
                        return error;
                }
                hdr = dbp->b_addr;
-               bf = xfs_dir3_data_bestfree_p(hdr);
+               bf = dp->d_ops->data_bestfree_p(hdr);
                grown = 0;
        }
        /*
@@ -875,7 +834,7 @@ xfs_dir2_leaf_addname(
        /*
         * Mark the initial part of our freespace in use for the new entry.
         */
-       xfs_dir2_data_use_free(tp, dbp, dup,
+       xfs_dir2_data_use_free(args, dbp, dup,
                (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
                &needlog, &needscan);
        /*
@@ -885,20 +844,20 @@ xfs_dir2_leaf_addname(
        dep->inumber = cpu_to_be64(args->inumber);
        dep->namelen = args->namelen;
        memcpy(dep->name, args->name, dep->namelen);
-       xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
        /*
         * Need to scan fix up the bestfree table.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        /*
         * Need to log the data block's header.
         */
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
-       xfs_dir2_data_log_entry(tp, dbp, dep);
+               xfs_dir2_data_log_header(args, dbp);
+       xfs_dir2_data_log_entry(args, dbp, dep);
        /*
         * If the bests table needs to be changed, do it.
         * Log the change unless we've already done that.
@@ -906,7 +865,7 @@ xfs_dir2_leaf_addname(
        if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) {
                bestsp[use_block] = bf[0].length;
                if (!grown)
-                       xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block);
+                       xfs_dir3_leaf_log_bests(args, lbp, use_block, use_block);
        }
 
        lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale,
@@ -916,15 +875,16 @@ xfs_dir2_leaf_addname(
         * Fill in the new leaf entry.
         */
        lep->hashval = cpu_to_be32(args->hashval);
-       lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, use_block,
+       lep->address = cpu_to_be32(
+                               xfs_dir2_db_off_to_dataptr(args->geo, use_block,
                                be16_to_cpu(*tagp)));
        /*
         * Log the leaf fields and give up the buffers.
         */
-       xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr);
-       xfs_dir3_leaf_log_header(tp, lbp);
-       xfs_dir3_leaf_log_ents(tp, lbp, lfloglow, lfloghigh);
-       xfs_dir3_leaf_check(mp, lbp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
+       xfs_dir3_leaf_log_header(args, lbp);
+       xfs_dir3_leaf_log_ents(args, lbp, lfloglow, lfloghigh);
+       xfs_dir3_leaf_check(dp, lbp);
        xfs_dir3_data_check(dp, dbp);
        return 0;
 }
@@ -944,6 +904,7 @@ xfs_dir3_leaf_compact(
        int             loglow;         /* first leaf entry to log */
        int             to;             /* target leaf index */
        struct xfs_dir2_leaf_entry *ents;
+       struct xfs_inode *dp = args->dp;
 
        leaf = bp->b_addr;
        if (!leafhdr->stale)
@@ -952,7 +913,7 @@ xfs_dir3_leaf_compact(
        /*
         * Compress out the stale entries in place.
         */
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
        for (from = to = 0, loglow = -1; from < leafhdr->count; from++) {
                if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
                        continue;
@@ -973,10 +934,10 @@ xfs_dir3_leaf_compact(
        leafhdr->count -= leafhdr->stale;
        leafhdr->stale = 0;
 
-       xfs_dir3_leaf_hdr_to_disk(leaf, leafhdr);
-       xfs_dir3_leaf_log_header(args->trans, bp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, leafhdr);
+       xfs_dir3_leaf_log_header(args, bp);
        if (loglow != -1)
-               xfs_dir3_leaf_log_ents(args->trans, bp, loglow, to - 1);
+               xfs_dir3_leaf_log_ents(args, bp, loglow, to - 1);
 }
 
 /*
@@ -1078,7 +1039,7 @@ xfs_dir3_leaf_compact_x1(
  */
 static void
 xfs_dir3_leaf_log_bests(
-       xfs_trans_t             *tp,            /* transaction pointer */
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp,            /* leaf buffer */
        int                     first,          /* first entry to log */
        int                     last)           /* last entry to log */
@@ -1091,10 +1052,11 @@ xfs_dir3_leaf_log_bests(
        ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) ||
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC));
 
-       ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
        firstb = xfs_dir2_leaf_bests_p(ltp) + first;
        lastb = xfs_dir2_leaf_bests_p(ltp) + last;
-       xfs_trans_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),
+       xfs_trans_log_buf(args->trans, bp,
+               (uint)((char *)firstb - (char *)leaf),
                (uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));
 }
 
@@ -1103,10 +1065,10 @@ xfs_dir3_leaf_log_bests(
  */
 void
 xfs_dir3_leaf_log_ents(
-       xfs_trans_t             *tp,            /* transaction pointer */
-       struct xfs_buf          *bp,            /* leaf buffer */
-       int                     first,          /* first entry to log */
-       int                     last)           /* last entry to log */
+       struct xfs_da_args      *args,
+       struct xfs_buf          *bp,
+       int                     first,
+       int                     last)
 {
        xfs_dir2_leaf_entry_t   *firstlep;      /* pointer to first entry */
        xfs_dir2_leaf_entry_t   *lastlep;       /* pointer to last entry */
@@ -1118,10 +1080,11 @@ xfs_dir3_leaf_log_ents(
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC));
 
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       ents = args->dp->d_ops->leaf_ents_p(leaf);
        firstlep = &ents[first];
        lastlep = &ents[last];
-       xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf),
+       xfs_trans_log_buf(args->trans, bp,
+               (uint)((char *)firstlep - (char *)leaf),
                (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1));
 }
 
@@ -1130,7 +1093,7 @@ xfs_dir3_leaf_log_ents(
  */
 void
 xfs_dir3_leaf_log_header(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp)
 {
        struct xfs_dir2_leaf    *leaf = bp->b_addr;
@@ -1140,8 +1103,9 @@ xfs_dir3_leaf_log_header(
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC));
 
-       xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf),
-                         xfs_dir3_leaf_hdr_size(leaf) - 1);
+       xfs_trans_log_buf(args->trans, bp,
+                         (uint)((char *)&leaf->hdr - (char *)leaf),
+                         args->dp->d_ops->leaf_hdr_size - 1);
 }
 
 /*
@@ -1149,21 +1113,20 @@ xfs_dir3_leaf_log_header(
  */
 STATIC void
 xfs_dir3_leaf_log_tail(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp)
 {
        struct xfs_dir2_leaf    *leaf = bp->b_addr;
        xfs_dir2_leaf_tail_t    *ltp;           /* leaf tail structure */
-       struct xfs_mount        *mp = tp->t_mountp;
 
        ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) ||
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
               leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC));
 
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
-       xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),
-               (uint)(mp->m_dirblksize - 1));
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
+       xfs_trans_log_buf(args->trans, bp, (uint)((char *)ltp - (char *)leaf),
+               (uint)(args->geo->blksize - 1));
 }
 
 /*
@@ -1196,9 +1159,9 @@ xfs_dir2_leaf_lookup(
        }
        tp = args->trans;
        dp = args->dp;
-       xfs_dir3_leaf_check(dp->i_mount, lbp);
+       xfs_dir3_leaf_check(dp, lbp);
        leaf = lbp->b_addr;
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
        /*
         * Get to the leaf entry and contained data entry address.
         */
@@ -1209,12 +1172,12 @@ xfs_dir2_leaf_lookup(
         */
        dep = (xfs_dir2_data_entry_t *)
              ((char *)dbp->b_addr +
-              xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
+              xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)));
        /*
         * Return the found inode number & CI name if appropriate
         */
        args->inumber = be64_to_cpu(dep->inumber);
-       args->filetype = xfs_dir3_dirent_get_ftype(dp->i_mount, dep);
+       args->filetype = dp->d_ops->data_get_ftype(dep);
        error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
        xfs_trans_brelse(tp, dbp);
        xfs_trans_brelse(tp, lbp);
@@ -1255,15 +1218,15 @@ xfs_dir2_leaf_lookup_int(
        tp = args->trans;
        mp = dp->i_mount;
 
-       error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);
+       error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, -1, &lbp);
        if (error)
                return error;
 
        *lbpp = lbp;
        leaf = lbp->b_addr;
-       xfs_dir3_leaf_check(mp, lbp);
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       xfs_dir3_leaf_check(dp, lbp);
+       ents = dp->d_ops->leaf_ents_p(leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
 
        /*
         * Look for the first leaf entry with our hash value.
@@ -1284,7 +1247,8 @@ xfs_dir2_leaf_lookup_int(
                /*
                 * Get the new data block number.
                 */
-               newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
+               newdb = xfs_dir2_dataptr_to_db(args->geo,
+                                              be32_to_cpu(lep->address));
                /*
                 * If it's not the same as the old data block number,
                 * need to pitch the old one and read the new one.
@@ -1293,8 +1257,8 @@ xfs_dir2_leaf_lookup_int(
                        if (dbp)
                                xfs_trans_brelse(tp, dbp);
                        error = xfs_dir3_data_read(tp, dp,
-                                                  xfs_dir2_db_to_da(mp, newdb),
-                                                  -1, &dbp);
+                                          xfs_dir2_db_to_da(args->geo, newdb),
+                                          -1, &dbp);
                        if (error) {
                                xfs_trans_brelse(tp, lbp);
                                return error;
@@ -1305,7 +1269,8 @@ xfs_dir2_leaf_lookup_int(
                 * Point to the data entry.
                 */
                dep = (xfs_dir2_data_entry_t *)((char *)dbp->b_addr +
-                       xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(lep->address)));
                /*
                 * Compare name and if it's an exact match, return the index
                 * and buffer. If it's the first case-insensitive match, store
@@ -1334,8 +1299,8 @@ xfs_dir2_leaf_lookup_int(
                if (cidb != curdb) {
                        xfs_trans_brelse(tp, dbp);
                        error = xfs_dir3_data_read(tp, dp,
-                                                  xfs_dir2_db_to_da(mp, cidb),
-                                                  -1, &dbp);
+                                          xfs_dir2_db_to_da(args->geo, cidb),
+                                          -1, &dbp);
                        if (error) {
                                xfs_trans_brelse(tp, lbp);
                                return error;
@@ -1397,60 +1362,60 @@ xfs_dir2_leaf_removename(
        leaf = lbp->b_addr;
        hdr = dbp->b_addr;
        xfs_dir3_data_check(dp, dbp);
-       bf = xfs_dir3_data_bestfree_p(hdr);
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       bf = dp->d_ops->data_bestfree_p(hdr);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
        /*
         * Point to the leaf entry, use that to point to the data entry.
         */
        lep = &ents[index];
-       db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
-       dep = (xfs_dir2_data_entry_t *)
-             ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
+       db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
+       dep = (xfs_dir2_data_entry_t *)((char *)hdr +
+               xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)));
        needscan = needlog = 0;
        oldbest = be16_to_cpu(bf[0].length);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
        bestsp = xfs_dir2_leaf_bests_p(ltp);
        ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
        /*
         * Mark the former data entry unused.
         */
-       xfs_dir2_data_make_free(tp, dbp,
+       xfs_dir2_data_make_free(args, dbp,
                (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
-               xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
+               dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
        /*
         * We just mark the leaf entry stale by putting a null in it.
         */
        leafhdr.stale++;
-       xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr);
-       xfs_dir3_leaf_log_header(tp, lbp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
+       xfs_dir3_leaf_log_header(args, lbp);
 
        lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
-       xfs_dir3_leaf_log_ents(tp, lbp, index, index);
+       xfs_dir3_leaf_log_ents(args, lbp, index, index);
 
        /*
         * Scan the freespace in the data block again if necessary,
         * log the data block header if necessary.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
+               xfs_dir2_data_log_header(args, dbp);
        /*
         * If the longest freespace in the data block has changed,
         * put the new value in the bests table and log that.
         */
        if (be16_to_cpu(bf[0].length) != oldbest) {
                bestsp[db] = bf[0].length;
-               xfs_dir3_leaf_log_bests(tp, lbp, db, db);
+               xfs_dir3_leaf_log_bests(args, lbp, db, db);
        }
        xfs_dir3_data_check(dp, dbp);
        /*
         * If the data block is now empty then get rid of the data block.
         */
        if (be16_to_cpu(bf[0].length) ==
-                       mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)) {
-               ASSERT(db != mp->m_dirdatablk);
+                       args->geo->blksize - dp->d_ops->data_entry_offset) {
+               ASSERT(db != args->geo->datablk);
                if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {
                        /*
                         * Nope, can't get rid of it because it caused
@@ -1460,7 +1425,7 @@ xfs_dir2_leaf_removename(
                         */
                        if (error == ENOSPC && args->total == 0)
                                error = 0;
-                       xfs_dir3_leaf_check(mp, lbp);
+                       xfs_dir3_leaf_check(dp, lbp);
                        return error;
                }
                dbp = NULL;
@@ -1483,18 +1448,19 @@ xfs_dir2_leaf_removename(
                        memmove(&bestsp[db - i], bestsp,
                                (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp));
                        be32_add_cpu(&ltp->bestcount, -(db - i));
-                       xfs_dir3_leaf_log_tail(tp, lbp);
-                       xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
+                       xfs_dir3_leaf_log_tail(args, lbp);
+                       xfs_dir3_leaf_log_bests(args, lbp, 0,
+                                               be32_to_cpu(ltp->bestcount) - 1);
                } else
                        bestsp[db] = cpu_to_be16(NULLDATAOFF);
        }
        /*
         * If the data block was not the first one, drop it.
         */
-       else if (db != mp->m_dirdatablk)
+       else if (db != args->geo->datablk)
                dbp = NULL;
 
-       xfs_dir3_leaf_check(mp, lbp);
+       xfs_dir3_leaf_check(dp, lbp);
        /*
         * See if we can convert to block form.
         */
@@ -1529,7 +1495,7 @@ xfs_dir2_leaf_replace(
        }
        dp = args->dp;
        leaf = lbp->b_addr;
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
        /*
         * Point to the leaf entry, get data address from it.
         */
@@ -1539,16 +1505,16 @@ xfs_dir2_leaf_replace(
         */
        dep = (xfs_dir2_data_entry_t *)
              ((char *)dbp->b_addr +
-              xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
+              xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)));
        ASSERT(args->inumber != be64_to_cpu(dep->inumber));
        /*
         * Put the new inode number in, log it.
         */
        dep->inumber = cpu_to_be64(args->inumber);
-       xfs_dir3_dirent_put_ftype(dp->i_mount, dep, args->filetype);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
        tp = args->trans;
-       xfs_dir2_data_log_entry(tp, dbp, dep);
-       xfs_dir3_leaf_check(dp->i_mount, lbp);
+       xfs_dir2_data_log_entry(args, dbp, dep);
+       xfs_dir3_leaf_check(dp, lbp);
        xfs_trans_brelse(tp, lbp);
        return 0;
 }
@@ -1574,8 +1540,8 @@ xfs_dir2_leaf_search_hash(
        struct xfs_dir3_icleaf_hdr leafhdr;
 
        leaf = lbp->b_addr;
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = args->dp->d_ops->leaf_ents_p(leaf);
+       args->dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
 
        /*
         * Note, the table cannot be empty, so we have to go through the loop.
@@ -1633,22 +1599,23 @@ xfs_dir2_leaf_trim_data(
        /*
         * Read the offending data block.  We need its buffer.
         */
-       error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp);
+       error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, db),
+                                  -1, &dbp);
        if (error)
                return error;
 
        leaf = lbp->b_addr;
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 
 #ifdef DEBUG
 {
        struct xfs_dir2_data_hdr *hdr = dbp->b_addr;
-       struct xfs_dir2_data_free *bf = xfs_dir3_data_bestfree_p(hdr);
+       struct xfs_dir2_data_free *bf = dp->d_ops->data_bestfree_p(hdr);
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
        ASSERT(be16_to_cpu(bf[0].length) ==
-              mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr));
+              args->geo->blksize - dp->d_ops->data_entry_offset);
        ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
 }
 #endif
@@ -1667,8 +1634,8 @@ xfs_dir2_leaf_trim_data(
        bestsp = xfs_dir2_leaf_bests_p(ltp);
        be32_add_cpu(&ltp->bestcount, -1);
        memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));
-       xfs_dir3_leaf_log_tail(tp, lbp);
-       xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
+       xfs_dir3_leaf_log_tail(args, lbp);
+       xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
        return 0;
 }
 
@@ -1732,22 +1699,22 @@ xfs_dir2_node_to_leaf(
        /*
         * Get the last offset in the file.
         */
-       if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK))) {
+       if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK))) {
                return error;
        }
-       fo -= mp->m_dirblkfsbs;
+       fo -= args->geo->fsbcount;
        /*
         * If there are freespace blocks other than the first one,
         * take this opportunity to remove trailing empty freespace blocks
         * that may have been left behind during no-space-reservation
         * operations.
         */
-       while (fo > mp->m_dirfreeblk) {
+       while (fo > args->geo->freeblk) {
                if ((error = xfs_dir2_node_trim_free(args, fo, &rval))) {
                        return error;
                }
                if (rval)
-                       fo -= mp->m_dirblkfsbs;
+                       fo -= args->geo->fsbcount;
                else
                        return 0;
        }
@@ -1760,11 +1727,11 @@ xfs_dir2_node_to_leaf(
        /*
         * If it's not the single leaf block, give up.
         */
-       if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + mp->m_dirblksize)
+       if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + args->geo->blksize)
                return 0;
        lbp = state->path.blk[0].bp;
        leaf = lbp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
 
        ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
               leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
@@ -1772,11 +1739,11 @@ xfs_dir2_node_to_leaf(
        /*
         * Read the freespace block.
         */
-       error = xfs_dir2_free_read(tp, dp,  mp->m_dirfreeblk, &fbp);
+       error = xfs_dir2_free_read(tp, dp,  args->geo->freeblk, &fbp);
        if (error)
                return error;
        free = fbp->b_addr;
-       xfs_dir3_free_hdr_from_disk(&freehdr, free);
+       dp->d_ops->free_hdr_from_disk(&freehdr, free);
 
        ASSERT(!freehdr.firstdb);
 
@@ -1784,7 +1751,7 @@ xfs_dir2_node_to_leaf(
         * Now see if the leafn and free data will fit in a leaf1.
         * If not, release the buffer and give up.
         */
-       if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > mp->m_dirblksize) {
+       if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > args->geo->blksize) {
                xfs_trans_brelse(tp, fbp);
                return 0;
        }
@@ -1804,25 +1771,27 @@ xfs_dir2_node_to_leaf(
        /*
         * Set up the leaf tail from the freespace block.
         */
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
        ltp->bestcount = cpu_to_be32(freehdr.nvalid);
 
        /*
         * Set up the leaf bests table.
         */
-       memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free),
+       memcpy(xfs_dir2_leaf_bests_p(ltp), dp->d_ops->free_bests_p(free),
                freehdr.nvalid * sizeof(xfs_dir2_data_off_t));
 
-       xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr);
-       xfs_dir3_leaf_log_header(tp, lbp);
-       xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
-       xfs_dir3_leaf_log_tail(tp, lbp);
-       xfs_dir3_leaf_check(mp, lbp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
+       xfs_dir3_leaf_log_header(args, lbp);
+       xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
+       xfs_dir3_leaf_log_tail(args, lbp);
+       xfs_dir3_leaf_check(dp, lbp);
 
        /*
         * Get rid of the freespace block.
         */
-       error = xfs_dir2_shrink_inode(args, XFS_DIR2_FREE_FIRSTDB(mp), fbp);
+       error = xfs_dir2_shrink_inode(args,
+                       xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET),
+                       fbp);
        if (error) {
                /*
                 * This can't fail here because it can only happen when
index 3737e4ebb5a6226233e9299c6270f768cc0cf6c7..dc502c478523001e60452718ca650708bef6011b 100644 (file)
@@ -37,21 +37,21 @@ static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
  * Check internal consistency of a leafn block.
  */
 #ifdef DEBUG
-#define        xfs_dir3_leaf_check(mp, bp) \
+#define        xfs_dir3_leaf_check(dp, bp) \
 do { \
-       if (!xfs_dir3_leafn_check((mp), (bp))) \
+       if (!xfs_dir3_leafn_check((dp), (bp))) \
                ASSERT(0); \
 } while (0);
 
 static bool
 xfs_dir3_leafn_check(
-       struct xfs_mount        *mp,
+       struct xfs_inode        *dp,
        struct xfs_buf          *bp)
 {
        struct xfs_dir2_leaf    *leaf = bp->b_addr;
        struct xfs_dir3_icleaf_hdr leafhdr;
 
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
 
        if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) {
                struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
@@ -60,10 +60,10 @@ xfs_dir3_leafn_check(
        } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC)
                return false;
 
-       return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
+       return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf);
 }
 #else
-#define        xfs_dir3_leaf_check(mp, bp)
+#define        xfs_dir3_leaf_check(dp, bp)
 #endif
 
 static bool
@@ -176,66 +176,20 @@ xfs_dir2_free_try_read(
        return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp);
 }
 
-
-void
-xfs_dir3_free_hdr_from_disk(
-       struct xfs_dir3_icfree_hdr      *to,
-       struct xfs_dir2_free            *from)
-{
-       if (from->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)) {
-               to->magic = be32_to_cpu(from->hdr.magic);
-               to->firstdb = be32_to_cpu(from->hdr.firstdb);
-               to->nvalid = be32_to_cpu(from->hdr.nvalid);
-               to->nused = be32_to_cpu(from->hdr.nused);
-       } else {
-               struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from;
-
-               to->magic = be32_to_cpu(hdr3->hdr.magic);
-               to->firstdb = be32_to_cpu(hdr3->firstdb);
-               to->nvalid = be32_to_cpu(hdr3->nvalid);
-               to->nused = be32_to_cpu(hdr3->nused);
-       }
-
-       ASSERT(to->magic == XFS_DIR2_FREE_MAGIC ||
-              to->magic == XFS_DIR3_FREE_MAGIC);
-}
-
-static void
-xfs_dir3_free_hdr_to_disk(
-       struct xfs_dir2_free            *to,
-       struct xfs_dir3_icfree_hdr      *from)
-{
-       ASSERT(from->magic == XFS_DIR2_FREE_MAGIC ||
-              from->magic == XFS_DIR3_FREE_MAGIC);
-
-       if (from->magic == XFS_DIR2_FREE_MAGIC) {
-               to->hdr.magic = cpu_to_be32(from->magic);
-               to->hdr.firstdb = cpu_to_be32(from->firstdb);
-               to->hdr.nvalid = cpu_to_be32(from->nvalid);
-               to->hdr.nused = cpu_to_be32(from->nused);
-       } else {
-               struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to;
-
-               hdr3->hdr.magic = cpu_to_be32(from->magic);
-               hdr3->firstdb = cpu_to_be32(from->firstdb);
-               hdr3->nvalid = cpu_to_be32(from->nvalid);
-               hdr3->nused = cpu_to_be32(from->nused);
-       }
-}
-
 static int
 xfs_dir3_free_get_buf(
-       struct xfs_trans        *tp,
-       struct xfs_inode        *dp,
+       xfs_da_args_t           *args,
        xfs_dir2_db_t           fbno,
        struct xfs_buf          **bpp)
 {
+       struct xfs_trans        *tp = args->trans;
+       struct xfs_inode        *dp = args->dp;
        struct xfs_mount        *mp = dp->i_mount;
        struct xfs_buf          *bp;
        int                     error;
        struct xfs_dir3_icfree_hdr hdr;
 
-       error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fbno),
+       error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno),
                                   -1, &bp, XFS_DATA_FORK);
        if (error)
                return error;
@@ -260,7 +214,7 @@ xfs_dir3_free_get_buf(
                uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid);
        } else
                hdr.magic = XFS_DIR2_FREE_MAGIC;
-       xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr);
+       dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr);
        *bpp = bp;
        return 0;
 }
@@ -270,7 +224,7 @@ xfs_dir3_free_get_buf(
  */
 STATIC void
 xfs_dir2_free_log_bests(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp,
        int                     first,          /* first entry to log */
        int                     last)           /* last entry to log */
@@ -279,10 +233,10 @@ xfs_dir2_free_log_bests(
        __be16                  *bests;
 
        free = bp->b_addr;
-       bests = xfs_dir3_free_bests_p(tp->t_mountp, free);
+       bests = args->dp->d_ops->free_bests_p(free);
        ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
               free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
-       xfs_trans_log_buf(tp, bp,
+       xfs_trans_log_buf(args->trans, bp,
                (uint)((char *)&bests[first] - (char *)free),
                (uint)((char *)&bests[last] - (char *)free +
                       sizeof(bests[0]) - 1));
@@ -293,7 +247,7 @@ xfs_dir2_free_log_bests(
  */
 static void
 xfs_dir2_free_log_header(
-       struct xfs_trans        *tp,
+       struct xfs_da_args      *args,
        struct xfs_buf          *bp)
 {
 #ifdef DEBUG
@@ -303,7 +257,8 @@ xfs_dir2_free_log_header(
        ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
               free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
 #endif
-       xfs_trans_log_buf(tp, bp, 0, xfs_dir3_free_hdr_size(tp->t_mountp) - 1);
+       xfs_trans_log_buf(args->trans, bp, 0,
+                         args->dp->d_ops->free_hdr_size - 1);
 }
 
 /*
@@ -343,27 +298,27 @@ xfs_dir2_leaf_to_node(
        if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) {
                return error;
        }
-       ASSERT(fdb == XFS_DIR2_FREE_FIRSTDB(mp));
+       ASSERT(fdb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET));
        /*
         * Get the buffer for the new freespace block.
         */
-       error = xfs_dir3_free_get_buf(tp, dp, fdb, &fbp);
+       error = xfs_dir3_free_get_buf(args, fdb, &fbp);
        if (error)
                return error;
 
        free = fbp->b_addr;
-       xfs_dir3_free_hdr_from_disk(&freehdr, free);
+       dp->d_ops->free_hdr_from_disk(&freehdr, free);
        leaf = lbp->b_addr;
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
        ASSERT(be32_to_cpu(ltp->bestcount) <=
-                               (uint)dp->i_d.di_size / mp->m_dirblksize);
+                               (uint)dp->i_d.di_size / args->geo->blksize);
 
        /*
         * Copy freespace entries from the leaf block to the new block.
         * Count active entries.
         */
        from = xfs_dir2_leaf_bests_p(ltp);
-       to = xfs_dir3_free_bests_p(mp, free);
+       to = dp->d_ops->free_bests_p(free);
        for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
                if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
                        n++;
@@ -376,9 +331,9 @@ xfs_dir2_leaf_to_node(
        freehdr.nused = n;
        freehdr.nvalid = be32_to_cpu(ltp->bestcount);
 
-       xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr);
-       xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1);
-       xfs_dir2_free_log_header(tp, fbp);
+       dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
+       xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1);
+       xfs_dir2_free_log_header(args, fbp);
 
        /*
         * Converting the leaf to a leafnode is just a matter of changing the
@@ -392,8 +347,8 @@ xfs_dir2_leaf_to_node(
                leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
        lbp->b_ops = &xfs_dir3_leafn_buf_ops;
        xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF);
-       xfs_dir3_leaf_log_header(tp, lbp);
-       xfs_dir3_leaf_check(mp, lbp);
+       xfs_dir3_leaf_log_header(args, lbp);
+       xfs_dir3_leaf_check(dp, lbp);
        return 0;
 }
 
@@ -426,8 +381,8 @@ xfs_dir2_leafn_add(
        mp = dp->i_mount;
        tp = args->trans;
        leaf = bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
 
        /*
         * Quick check just to make sure we are not going to index
@@ -443,7 +398,7 @@ xfs_dir2_leafn_add(
         * a compact.
         */
 
-       if (leafhdr.count == xfs_dir3_max_leaf_ents(mp, leaf)) {
+       if (leafhdr.count == dp->d_ops->leaf_max_ents(args->geo)) {
                if (!leafhdr.stale)
                        return XFS_ERROR(ENOSPC);
                compact = leafhdr.stale > 1;
@@ -478,33 +433,34 @@ xfs_dir2_leafn_add(
                                       highstale, &lfloglow, &lfloghigh);
 
        lep->hashval = cpu_to_be32(args->hashval);
-       lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
+       lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo,
                                args->blkno, args->index));
 
-       xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr);
-       xfs_dir3_leaf_log_header(tp, bp);
-       xfs_dir3_leaf_log_ents(tp, bp, lfloglow, lfloghigh);
-       xfs_dir3_leaf_check(mp, bp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
+       xfs_dir3_leaf_log_header(args, bp);
+       xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh);
+       xfs_dir3_leaf_check(dp, bp);
        return 0;
 }
 
 #ifdef DEBUG
 static void
 xfs_dir2_free_hdr_check(
-       struct xfs_mount *mp,
+       struct xfs_inode *dp,
        struct xfs_buf  *bp,
        xfs_dir2_db_t   db)
 {
        struct xfs_dir3_icfree_hdr hdr;
 
-       xfs_dir3_free_hdr_from_disk(&hdr, bp->b_addr);
+       dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr);
 
-       ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(mp)) == 0);
+       ASSERT((hdr.firstdb %
+               dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0);
        ASSERT(hdr.firstdb <= db);
        ASSERT(db < hdr.firstdb + hdr.nvalid);
 }
 #else
-#define xfs_dir2_free_hdr_check(mp, dp, db)
+#define xfs_dir2_free_hdr_check(dp, bp, db)
 #endif /* DEBUG */
 
 /*
@@ -513,6 +469,7 @@ xfs_dir2_free_hdr_check(
  */
 xfs_dahash_t                                   /* hash value */
 xfs_dir2_leafn_lasthash(
+       struct xfs_inode *dp,
        struct xfs_buf  *bp,                    /* leaf buffer */
        int             *count)                 /* count of entries in leaf */
 {
@@ -520,7 +477,7 @@ xfs_dir2_leafn_lasthash(
        struct xfs_dir2_leaf_entry *ents;
        struct xfs_dir3_icleaf_hdr leafhdr;
 
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
 
        ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
               leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
@@ -530,7 +487,7 @@ xfs_dir2_leafn_lasthash(
        if (!leafhdr.count)
                return 0;
 
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
        return be32_to_cpu(ents[leafhdr.count - 1].hashval);
 }
 
@@ -567,10 +524,10 @@ xfs_dir2_leafn_lookup_for_addname(
        tp = args->trans;
        mp = dp->i_mount;
        leaf = bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
 
-       xfs_dir3_leaf_check(mp, bp);
+       xfs_dir3_leaf_check(dp, bp);
        ASSERT(leafhdr.count > 0);
 
        /*
@@ -588,7 +545,7 @@ xfs_dir2_leafn_lookup_for_addname(
                ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
                       free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
        }
-       length = xfs_dir3_data_entsize(mp, args->namelen);
+       length = dp->d_ops->data_entsize(args->namelen);
        /*
         * Loop over leaf entries with the right hash value.
         */
@@ -603,7 +560,8 @@ xfs_dir2_leafn_lookup_for_addname(
                /*
                 * Pull the data block number from the entry.
                 */
-               newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
+               newdb = xfs_dir2_dataptr_to_db(args->geo,
+                                              be32_to_cpu(lep->address));
                /*
                 * For addname, we're looking for a place to put the new entry.
                 * We want to use a data block with an entry of equal
@@ -620,7 +578,7 @@ xfs_dir2_leafn_lookup_for_addname(
                         * Convert the data block to the free block
                         * holding its freespace information.
                         */
-                       newfdb = xfs_dir2_db_to_fdb(mp, newdb);
+                       newfdb = dp->d_ops->db_to_fdb(args->geo, newdb);
                        /*
                         * If it's not the one we have in hand, read it in.
                         */
@@ -632,22 +590,23 @@ xfs_dir2_leafn_lookup_for_addname(
                                        xfs_trans_brelse(tp, curbp);
 
                                error = xfs_dir2_free_read(tp, dp,
-                                               xfs_dir2_db_to_da(mp, newfdb),
+                                               xfs_dir2_db_to_da(args->geo,
+                                                                 newfdb),
                                                &curbp);
                                if (error)
                                        return error;
                                free = curbp->b_addr;
 
-                               xfs_dir2_free_hdr_check(mp, curbp, curdb);
+                               xfs_dir2_free_hdr_check(dp, curbp, curdb);
                        }
                        /*
                         * Get the index for our entry.
                         */
-                       fi = xfs_dir2_db_to_fdindex(mp, curdb);
+                       fi = dp->d_ops->db_to_fdindex(args->geo, curdb);
                        /*
                         * If it has room, return it.
                         */
-                       bests = xfs_dir3_free_bests_p(mp, free);
+                       bests = dp->d_ops->free_bests_p(free);
                        if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) {
                                XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
                                                        XFS_ERRLEVEL_LOW, mp);
@@ -717,10 +676,10 @@ xfs_dir2_leafn_lookup_for_entry(
        tp = args->trans;
        mp = dp->i_mount;
        leaf = bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
 
-       xfs_dir3_leaf_check(mp, bp);
+       xfs_dir3_leaf_check(dp, bp);
        ASSERT(leafhdr.count > 0);
 
        /*
@@ -748,7 +707,8 @@ xfs_dir2_leafn_lookup_for_entry(
                /*
                 * Pull the data block number from the entry.
                 */
-               newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
+               newdb = xfs_dir2_dataptr_to_db(args->geo,
+                                              be32_to_cpu(lep->address));
                /*
                 * Not adding a new entry, so we really want to find
                 * the name given to us.
@@ -773,7 +733,8 @@ xfs_dir2_leafn_lookup_for_entry(
                                curbp = state->extrablk.bp;
                        } else {
                                error = xfs_dir3_data_read(tp, dp,
-                                               xfs_dir2_db_to_da(mp, newdb),
+                                               xfs_dir2_db_to_da(args->geo,
+                                                                 newdb),
                                                -1, &curbp);
                                if (error)
                                        return error;
@@ -785,7 +746,8 @@ xfs_dir2_leafn_lookup_for_entry(
                 * Point to the data entry.
                 */
                dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr +
-                       xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(lep->address)));
                /*
                 * Compare the entry and if it's an exact match, return
                 * EEXIST immediately. If it's the first case-insensitive
@@ -799,7 +761,7 @@ xfs_dir2_leafn_lookup_for_entry(
                                xfs_trans_brelse(tp, state->extrablk.bp);
                        args->cmpresult = cmp;
                        args->inumber = be64_to_cpu(dep->inumber);
-                       args->filetype = xfs_dir3_dirent_get_ftype(mp, dep);
+                       args->filetype = dp->d_ops->data_get_ftype(dep);
                        *indexp = index;
                        state->extravalid = 1;
                        state->extrablk.bp = curbp;
@@ -871,7 +833,6 @@ xfs_dir3_leafn_moveents(
        int                             start_d,/* destination leaf index */
        int                             count)  /* count of leaves to copy */
 {
-       struct xfs_trans                *tp = args->trans;
        int                             stale;  /* count stale leaves copied */
 
        trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count);
@@ -890,7 +851,7 @@ xfs_dir3_leafn_moveents(
        if (start_d < dhdr->count) {
                memmove(&dents[start_d + count], &dents[start_d],
                        (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t));
-               xfs_dir3_leaf_log_ents(tp, bp_d, start_d + count,
+               xfs_dir3_leaf_log_ents(args, bp_d, start_d + count,
                                       count + dhdr->count - 1);
        }
        /*
@@ -912,7 +873,7 @@ xfs_dir3_leafn_moveents(
         */
        memcpy(&dents[start_d], &sents[start_s],
                count * sizeof(xfs_dir2_leaf_entry_t));
-       xfs_dir3_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1);
+       xfs_dir3_leaf_log_ents(args, bp_d, start_d, start_d + count - 1);
 
        /*
         * If there are source entries after the ones we copied,
@@ -921,7 +882,7 @@ xfs_dir3_leafn_moveents(
        if (start_s + count < shdr->count) {
                memmove(&sents[start_s], &sents[start_s + count],
                        count * sizeof(xfs_dir2_leaf_entry_t));
-               xfs_dir3_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1);
+               xfs_dir3_leaf_log_ents(args, bp_s, start_s, start_s + count - 1);
        }
 
        /*
@@ -939,6 +900,7 @@ xfs_dir3_leafn_moveents(
  */
 int                                            /* sort order */
 xfs_dir2_leafn_order(
+       struct xfs_inode        *dp,
        struct xfs_buf          *leaf1_bp,              /* leaf1 buffer */
        struct xfs_buf          *leaf2_bp)              /* leaf2 buffer */
 {
@@ -949,10 +911,10 @@ xfs_dir2_leafn_order(
        struct xfs_dir3_icleaf_hdr hdr1;
        struct xfs_dir3_icleaf_hdr hdr2;
 
-       xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1);
-       xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2);
-       ents1 = xfs_dir3_leaf_ents_p(leaf1);
-       ents2 = xfs_dir3_leaf_ents_p(leaf2);
+       dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1);
+       dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2);
+       ents1 = dp->d_ops->leaf_ents_p(leaf1);
+       ents2 = dp->d_ops->leaf_ents_p(leaf2);
 
        if (hdr1.count > 0 && hdr2.count > 0 &&
            (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) ||
@@ -990,12 +952,13 @@ xfs_dir2_leafn_rebalance(
        struct xfs_dir2_leaf_entry *ents2;
        struct xfs_dir3_icleaf_hdr hdr1;
        struct xfs_dir3_icleaf_hdr hdr2;
+       struct xfs_inode        *dp = state->args->dp;
 
        args = state->args;
        /*
         * If the block order is wrong, swap the arguments.
         */
-       if ((swap = xfs_dir2_leafn_order(blk1->bp, blk2->bp))) {
+       if ((swap = xfs_dir2_leafn_order(dp, blk1->bp, blk2->bp))) {
                xfs_da_state_blk_t      *tmp;   /* temp for block swap */
 
                tmp = blk1;
@@ -1004,10 +967,10 @@ xfs_dir2_leafn_rebalance(
        }
        leaf1 = blk1->bp->b_addr;
        leaf2 = blk2->bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1);
-       xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2);
-       ents1 = xfs_dir3_leaf_ents_p(leaf1);
-       ents2 = xfs_dir3_leaf_ents_p(leaf2);
+       dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1);
+       dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2);
+       ents1 = dp->d_ops->leaf_ents_p(leaf1);
+       ents2 = dp->d_ops->leaf_ents_p(leaf2);
 
        oldsum = hdr1.count + hdr2.count;
 #if defined(DEBUG) || defined(XFS_WARN)
@@ -1053,13 +1016,13 @@ xfs_dir2_leafn_rebalance(
        ASSERT(hdr1.stale + hdr2.stale == oldstale);
 
        /* log the changes made when moving the entries */
-       xfs_dir3_leaf_hdr_to_disk(leaf1, &hdr1);
-       xfs_dir3_leaf_hdr_to_disk(leaf2, &hdr2);
-       xfs_dir3_leaf_log_header(args->trans, blk1->bp);
-       xfs_dir3_leaf_log_header(args->trans, blk2->bp);
+       dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1);
+       dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2);
+       xfs_dir3_leaf_log_header(args, blk1->bp);
+       xfs_dir3_leaf_log_header(args, blk2->bp);
 
-       xfs_dir3_leaf_check(args->dp->i_mount, blk1->bp);
-       xfs_dir3_leaf_check(args->dp->i_mount, blk2->bp);
+       xfs_dir3_leaf_check(dp, blk1->bp);
+       xfs_dir3_leaf_check(dp, blk2->bp);
 
        /*
         * Mark whether we're inserting into the old or new leaf.
@@ -1080,10 +1043,10 @@ xfs_dir2_leafn_rebalance(
         * Finally sanity check just to make sure we are not returning a
         * negative index
         */
-       if(blk2->index < 0) {
+       if (blk2->index < 0) {
                state->inleaf = 1;
                blk2->index = 0;
-               xfs_alert(args->dp->i_mount,
+               xfs_alert(dp->i_mount,
        "%s: picked the wrong leaf? reverting original leaf: blk1->index %d",
                        __func__, blk1->index);
        }
@@ -1099,21 +1062,20 @@ xfs_dir3_data_block_free(
        struct xfs_buf          *fbp,
        int                     longest)
 {
-       struct xfs_trans        *tp = args->trans;
        int                     logfree = 0;
        __be16                  *bests;
        struct xfs_dir3_icfree_hdr freehdr;
+       struct xfs_inode        *dp = args->dp;
 
-       xfs_dir3_free_hdr_from_disk(&freehdr, free);
-
-       bests = xfs_dir3_free_bests_p(tp->t_mountp, free);
+       dp->d_ops->free_hdr_from_disk(&freehdr, free);
+       bests = dp->d_ops->free_bests_p(free);
        if (hdr) {
                /*
                 * Data block is not empty, just set the free entry to the new
                 * value.
                 */
                bests[findex] = cpu_to_be16(longest);
-               xfs_dir2_free_log_bests(tp, fbp, findex, findex);
+               xfs_dir2_free_log_bests(args, fbp, findex, findex);
                return 0;
        }
 
@@ -1140,8 +1102,8 @@ xfs_dir3_data_block_free(
                logfree = 1;
        }
 
-       xfs_dir3_free_hdr_to_disk(free, &freehdr);
-       xfs_dir2_free_log_header(tp, fbp);
+       dp->d_ops->free_hdr_to_disk(free, &freehdr);
+       xfs_dir2_free_log_header(args, fbp);
 
        /*
         * If there are no useful entries left in the block, get rid of the
@@ -1165,7 +1127,7 @@ xfs_dir3_data_block_free(
 
        /* Log the free entry that changed, unless we got rid of it.  */
        if (logfree)
-               xfs_dir2_free_log_bests(tp, fbp, findex, findex);
+               xfs_dir2_free_log_bests(args, fbp, findex, findex);
        return 0;
 }
 
@@ -1205,8 +1167,8 @@ xfs_dir2_leafn_remove(
        tp = args->trans;
        mp = dp->i_mount;
        leaf = bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
 
        /*
         * Point to the entry we're removing.
@@ -1216,9 +1178,9 @@ xfs_dir2_leafn_remove(
        /*
         * Extract the data block and offset from the entry.
         */
-       db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
+       db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
        ASSERT(dblk->blkno == db);
-       off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address));
+       off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address));
        ASSERT(dblk->index == off);
 
        /*
@@ -1226,11 +1188,11 @@ xfs_dir2_leafn_remove(
         * Log the leaf block changes.
         */
        leafhdr.stale++;
-       xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr);
-       xfs_dir3_leaf_log_header(tp, bp);
+       dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
+       xfs_dir3_leaf_log_header(args, bp);
 
        lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
-       xfs_dir3_leaf_log_ents(tp, bp, index, index);
+       xfs_dir3_leaf_log_ents(args, bp, index, index);
 
        /*
         * Make the data entry free.  Keep track of the longest freespace
@@ -1239,19 +1201,19 @@ xfs_dir2_leafn_remove(
        dbp = dblk->bp;
        hdr = dbp->b_addr;
        dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
-       bf = xfs_dir3_data_bestfree_p(hdr);
+       bf = dp->d_ops->data_bestfree_p(hdr);
        longest = be16_to_cpu(bf[0].length);
        needlog = needscan = 0;
-       xfs_dir2_data_make_free(tp, dbp, off,
-               xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
+       xfs_dir2_data_make_free(args, dbp, off,
+               dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
        /*
         * Rescan the data block freespaces for bestfree.
         * Log the data block header if needed.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
+               xfs_dir2_data_log_header(args, dbp);
        xfs_dir3_data_check(dp, dbp);
        /*
         * If the longest data block freespace changes, need to update
@@ -1268,8 +1230,9 @@ xfs_dir2_leafn_remove(
                 * Convert the data block number to a free block,
                 * read in the free block.
                 */
-               fdb = xfs_dir2_db_to_fdb(mp, db);
-               error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb),
+               fdb = dp->d_ops->db_to_fdb(args->geo, db);
+               error = xfs_dir2_free_read(tp, dp,
+                                          xfs_dir2_db_to_da(args->geo, fdb),
                                           &fbp);
                if (error)
                        return error;
@@ -1277,22 +1240,23 @@ xfs_dir2_leafn_remove(
 #ifdef DEBUG
        {
                struct xfs_dir3_icfree_hdr freehdr;
-               xfs_dir3_free_hdr_from_disk(&freehdr, free);
-               ASSERT(freehdr.firstdb == xfs_dir3_free_max_bests(mp) *
-                                         (fdb - XFS_DIR2_FREE_FIRSTDB(mp)));
+               dp->d_ops->free_hdr_from_disk(&freehdr, free);
+               ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) *
+                       (fdb - xfs_dir2_byte_to_db(args->geo,
+                                                  XFS_DIR2_FREE_OFFSET)));
        }
 #endif
                /*
                 * Calculate which entry we need to fix.
                 */
-               findex = xfs_dir2_db_to_fdindex(mp, db);
+               findex = dp->d_ops->db_to_fdindex(args->geo, db);
                longest = be16_to_cpu(bf[0].length);
                /*
                 * If the data block is now empty we can get rid of it
                 * (usually).
                 */
-               if (longest == mp->m_dirblksize -
-                              xfs_dir3_data_entry_offset(hdr)) {
+               if (longest == args->geo->blksize -
+                              dp->d_ops->data_entry_offset) {
                        /*
                         * Try to punch out the data block.
                         */
@@ -1319,14 +1283,14 @@ xfs_dir2_leafn_remove(
                        return error;
        }
 
-       xfs_dir3_leaf_check(mp, bp);
+       xfs_dir3_leaf_check(dp, bp);
        /*
         * Return indication of whether this leaf block is empty enough
         * to justify trying to join it with a neighbor.
         */
-       *rval = (xfs_dir3_leaf_hdr_size(leaf) +
+       *rval = (dp->d_ops->leaf_hdr_size +
                 (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) <
-               mp->m_dir_magicpct;
+               args->geo->magicpct;
        return 0;
 }
 
@@ -1343,13 +1307,14 @@ xfs_dir2_leafn_split(
        xfs_dablk_t             blkno;          /* new leaf block number */
        int                     error;          /* error return value */
        xfs_mount_t             *mp;            /* filesystem mount point */
+       struct xfs_inode        *dp;
 
        /*
         * Allocate space for a new leaf node.
         */
        args = state->args;
-       mp = args->dp->i_mount;
-       ASSERT(args != NULL);
+       dp = args->dp;
+       mp = dp->i_mount;
        ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC);
        error = xfs_da_grow_inode(args, &blkno);
        if (error) {
@@ -1358,7 +1323,7 @@ xfs_dir2_leafn_split(
        /*
         * Initialize the new leaf block.
         */
-       error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(mp, blkno),
+       error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(args->geo, blkno),
                                      &newblk->bp, XFS_DIR2_LEAFN_MAGIC);
        if (error)
                return error;
@@ -1384,10 +1349,10 @@ xfs_dir2_leafn_split(
        /*
         * Update last hashval in each block since we added the name.
         */
-       oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL);
-       newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL);
-       xfs_dir3_leaf_check(mp, oldblk->bp);
-       xfs_dir3_leaf_check(mp, newblk->bp);
+       oldblk->hashval = xfs_dir2_leafn_lasthash(dp, oldblk->bp, NULL);
+       newblk->hashval = xfs_dir2_leafn_lasthash(dp, newblk->bp, NULL);
+       xfs_dir3_leaf_check(dp, oldblk->bp);
+       xfs_dir3_leaf_check(dp, newblk->bp);
        return error;
 }
 
@@ -1417,6 +1382,7 @@ xfs_dir2_leafn_toosmall(
        int                     rval;           /* result from path_shift */
        struct xfs_dir3_icleaf_hdr leafhdr;
        struct xfs_dir2_leaf_entry *ents;
+       struct xfs_inode        *dp = state->args->dp;
 
        /*
         * Check for the degenerate case of the block being over 50% full.
@@ -1425,13 +1391,13 @@ xfs_dir2_leafn_toosmall(
         */
        blk = &state->path.blk[state->path.active - 1];
        leaf = blk->bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       xfs_dir3_leaf_check(state->args->dp->i_mount, blk->bp);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
+       xfs_dir3_leaf_check(dp, blk->bp);
 
        count = leafhdr.count - leafhdr.stale;
-       bytes = xfs_dir3_leaf_hdr_size(leaf) + count * sizeof(ents[0]);
-       if (bytes > (state->blocksize >> 1)) {
+       bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]);
+       if (bytes > (state->args->geo->blksize >> 1)) {
                /*
                 * Blk over 50%, don't try to join.
                 */
@@ -1475,7 +1441,7 @@ xfs_dir2_leafn_toosmall(
                /*
                 * Read the sibling leaf block.
                 */
-               error = xfs_dir3_leafn_read(state->args->trans, state->args->dp,
+               error = xfs_dir3_leafn_read(state->args->trans, dp,
                                            blkno, -1, &bp);
                if (error)
                        return error;
@@ -1484,11 +1450,12 @@ xfs_dir2_leafn_toosmall(
                 * Count bytes in the two blocks combined.
                 */
                count = leafhdr.count - leafhdr.stale;
-               bytes = state->blocksize - (state->blocksize >> 2);
+               bytes = state->args->geo->blksize -
+                       (state->args->geo->blksize >> 2);
 
                leaf = bp->b_addr;
-               xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf);
-               ents = xfs_dir3_leaf_ents_p(leaf);
+               dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf);
+               ents = dp->d_ops->leaf_ents_p(leaf);
                count += hdr2.count - hdr2.stale;
                bytes -= count * sizeof(ents[0]);
 
@@ -1542,6 +1509,7 @@ xfs_dir2_leafn_unbalance(
        struct xfs_dir3_icleaf_hdr drophdr;
        struct xfs_dir2_leaf_entry *sents;
        struct xfs_dir2_leaf_entry *dents;
+       struct xfs_inode        *dp = state->args->dp;
 
        args = state->args;
        ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
@@ -1549,10 +1517,10 @@ xfs_dir2_leafn_unbalance(
        drop_leaf = drop_blk->bp->b_addr;
        save_leaf = save_blk->bp->b_addr;
 
-       xfs_dir3_leaf_hdr_from_disk(&savehdr, save_leaf);
-       xfs_dir3_leaf_hdr_from_disk(&drophdr, drop_leaf);
-       sents = xfs_dir3_leaf_ents_p(save_leaf);
-       dents = xfs_dir3_leaf_ents_p(drop_leaf);
+       dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf);
+       dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf);
+       sents = dp->d_ops->leaf_ents_p(save_leaf);
+       dents = dp->d_ops->leaf_ents_p(drop_leaf);
 
        /*
         * If there are any stale leaf entries, take this opportunity
@@ -1567,7 +1535,7 @@ xfs_dir2_leafn_unbalance(
         * Move the entries from drop to the appropriate end of save.
         */
        drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval);
-       if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp))
+       if (xfs_dir2_leafn_order(dp, save_blk->bp, drop_blk->bp))
                xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0,
                                        save_blk->bp, &savehdr, sents, 0,
                                        drophdr.count);
@@ -1578,13 +1546,13 @@ xfs_dir2_leafn_unbalance(
        save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval);
 
        /* log the changes made when moving the entries */
-       xfs_dir3_leaf_hdr_to_disk(save_leaf, &savehdr);
-       xfs_dir3_leaf_hdr_to_disk(drop_leaf, &drophdr);
-       xfs_dir3_leaf_log_header(args->trans, save_blk->bp);
-       xfs_dir3_leaf_log_header(args->trans, drop_blk->bp);
+       dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr);
+       dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr);
+       xfs_dir3_leaf_log_header(args, save_blk->bp);
+       xfs_dir3_leaf_log_header(args, drop_blk->bp);
 
-       xfs_dir3_leaf_check(args->dp->i_mount, save_blk->bp);
-       xfs_dir3_leaf_check(args->dp->i_mount, drop_blk->bp);
+       xfs_dir3_leaf_check(dp, save_blk->bp);
+       xfs_dir3_leaf_check(dp, drop_blk->bp);
 }
 
 /*
@@ -1607,8 +1575,6 @@ xfs_dir2_node_addname(
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = args->dp->i_mount;
-       state->blocksize = state->mp->m_dirblksize;
-       state->node_ents = state->mp->m_dir_node_ents;
        /*
         * Look up the name.  We're not supposed to find it, but
         * this gives us the insertion point.
@@ -1695,7 +1661,7 @@ xfs_dir2_node_addname_int(
        dp = args->dp;
        mp = dp->i_mount;
        tp = args->trans;
-       length = xfs_dir3_data_entsize(mp, args->namelen);
+       length = dp->d_ops->data_entsize(args->namelen);
        /*
         * If we came in with a freespace block that means that lookup
         * found an entry with our hash value.  This is the freespace
@@ -1709,8 +1675,8 @@ xfs_dir2_node_addname_int(
                ifbno = fblk->blkno;
                free = fbp->b_addr;
                findex = fblk->index;
-               bests = xfs_dir3_free_bests_p(mp, free);
-               xfs_dir3_free_hdr_from_disk(&freehdr, free);
+               bests = dp->d_ops->free_bests_p(free);
+               dp->d_ops->free_hdr_from_disk(&freehdr, free);
 
                /*
                 * This means the free entry showed that the data block had
@@ -1747,9 +1713,9 @@ xfs_dir2_node_addname_int(
        if (dbno == -1) {
                xfs_fileoff_t   fo;             /* freespace block number */
 
-               if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK)))
+               if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK)))
                        return error;
-               lastfbno = xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo);
+               lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo);
                fbno = ifbno;
        }
        /*
@@ -1767,7 +1733,8 @@ xfs_dir2_node_addname_int(
                         * us a freespace block to start with.
                         */
                        if (++fbno == 0)
-                               fbno = XFS_DIR2_FREE_FIRSTDB(mp);
+                               fbno = xfs_dir2_byte_to_db(args->geo,
+                                                       XFS_DIR2_FREE_OFFSET);
                        /*
                         * If it's ifbno we already looked at it.
                         */
@@ -1785,8 +1752,8 @@ xfs_dir2_node_addname_int(
                         * to avoid it.
                         */
                        error = xfs_dir2_free_try_read(tp, dp,
-                                               xfs_dir2_db_to_da(mp, fbno),
-                                               &fbp);
+                                       xfs_dir2_db_to_da(args->geo, fbno),
+                                       &fbp);
                        if (error)
                                return error;
                        if (!fbp)
@@ -1802,8 +1769,8 @@ xfs_dir2_node_addname_int(
                 * and the freehdr are actually initialised if they are placed
                 * there, so we have to do it here to avoid warnings. Blech.
                 */
-               bests = xfs_dir3_free_bests_p(mp, free);
-               xfs_dir3_free_hdr_from_disk(&freehdr, free);
+               bests = dp->d_ops->free_bests_p(free);
+               dp->d_ops->free_hdr_from_disk(&freehdr, free);
                if (be16_to_cpu(bests[findex]) != NULLDATAOFF &&
                    be16_to_cpu(bests[findex]) >= length)
                        dbno = freehdr.firstdb + findex;
@@ -1854,10 +1821,10 @@ xfs_dir2_node_addname_int(
                 * Get the freespace block corresponding to the data block
                 * that was just allocated.
                 */
-               fbno = xfs_dir2_db_to_fdb(mp, dbno);
+               fbno = dp->d_ops->db_to_fdb(args->geo, dbno);
                error = xfs_dir2_free_try_read(tp, dp,
-                                              xfs_dir2_db_to_da(mp, fbno),
-                                              &fbp);
+                                      xfs_dir2_db_to_da(args->geo, fbno),
+                                      &fbp);
                if (error)
                        return error;
 
@@ -1871,12 +1838,13 @@ xfs_dir2_node_addname_int(
                        if (error)
                                return error;
 
-                       if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
+                       if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) {
                                xfs_alert(mp,
                        "%s: dir ino %llu needed freesp block %lld for\n"
                        "  data block %lld, got %lld ifbno %llu lastfbno %d",
                                        __func__, (unsigned long long)dp->i_ino,
-                                       (long long)xfs_dir2_db_to_fdb(mp, dbno),
+                                       (long long)dp->d_ops->db_to_fdb(
+                                                               args->geo, dbno),
                                        (long long)dbno, (long long)fbno,
                                        (unsigned long long)ifbno, lastfbno);
                                if (fblk) {
@@ -1897,34 +1865,36 @@ xfs_dir2_node_addname_int(
                        /*
                         * Get a buffer for the new block.
                         */
-                       error = xfs_dir3_free_get_buf(tp, dp, fbno, &fbp);
+                       error = xfs_dir3_free_get_buf(args, fbno, &fbp);
                        if (error)
                                return error;
                        free = fbp->b_addr;
-                       bests = xfs_dir3_free_bests_p(mp, free);
-                       xfs_dir3_free_hdr_from_disk(&freehdr, free);
+                       bests = dp->d_ops->free_bests_p(free);
+                       dp->d_ops->free_hdr_from_disk(&freehdr, free);
 
                        /*
                         * Remember the first slot as our empty slot.
                         */
-                       freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
-                                       xfs_dir3_free_max_bests(mp);
+                       freehdr.firstdb =
+                               (fbno - xfs_dir2_byte_to_db(args->geo,
+                                                       XFS_DIR2_FREE_OFFSET)) *
+                                       dp->d_ops->free_max_bests(args->geo);
                } else {
                        free = fbp->b_addr;
-                       bests = xfs_dir3_free_bests_p(mp, free);
-                       xfs_dir3_free_hdr_from_disk(&freehdr, free);
+                       bests = dp->d_ops->free_bests_p(free);
+                       dp->d_ops->free_hdr_from_disk(&freehdr, free);
                }
 
                /*
                 * Set the freespace block index from the data block number.
                 */
-               findex = xfs_dir2_db_to_fdindex(mp, dbno);
+               findex = dp->d_ops->db_to_fdindex(args->geo, dbno);
                /*
                 * If it's after the end of the current entries in the
                 * freespace block, extend that table.
                 */
                if (findex >= freehdr.nvalid) {
-                       ASSERT(findex < xfs_dir3_free_max_bests(mp));
+                       ASSERT(findex < dp->d_ops->free_max_bests(args->geo));
                        freehdr.nvalid = findex + 1;
                        /*
                         * Tag new entry so nused will go up.
@@ -1937,8 +1907,8 @@ xfs_dir2_node_addname_int(
                 */
                if (bests[findex] == cpu_to_be16(NULLDATAOFF)) {
                        freehdr.nused++;
-                       xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr);
-                       xfs_dir2_free_log_header(tp, fbp);
+                       dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
+                       xfs_dir2_free_log_header(args, fbp);
                }
                /*
                 * Update the real value in the table.
@@ -1946,7 +1916,7 @@ xfs_dir2_node_addname_int(
                 * change again.
                 */
                hdr = dbp->b_addr;
-               bf = xfs_dir3_data_bestfree_p(hdr);
+               bf = dp->d_ops->data_bestfree_p(hdr);
                bests[findex] = bf[0].length;
                logfree = 1;
        }
@@ -1963,12 +1933,13 @@ xfs_dir2_node_addname_int(
                /*
                 * Read the data block in.
                 */
-               error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno),
+               error = xfs_dir3_data_read(tp, dp,
+                                          xfs_dir2_db_to_da(args->geo, dbno),
                                           -1, &dbp);
                if (error)
                        return error;
                hdr = dbp->b_addr;
-               bf = xfs_dir3_data_bestfree_p(hdr);
+               bf = dp->d_ops->data_bestfree_p(hdr);
                logfree = 0;
        }
        ASSERT(be16_to_cpu(bf[0].length) >= length);
@@ -1981,7 +1952,7 @@ xfs_dir2_node_addname_int(
        /*
         * Mark the first part of the unused space, inuse for us.
         */
-       xfs_dir2_data_use_free(tp, dbp, dup,
+       xfs_dir2_data_use_free(args, dbp, dup,
                (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
                &needlog, &needscan);
        /*
@@ -1991,24 +1962,24 @@ xfs_dir2_node_addname_int(
        dep->inumber = cpu_to_be64(args->inumber);
        dep->namelen = args->namelen;
        memcpy(dep->name, args->name, dep->namelen);
-       xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-       xfs_dir2_data_log_entry(tp, dbp, dep);
+       xfs_dir2_data_log_entry(args, dbp, dep);
        /*
         * Rescan the block for bestfree if needed.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
        /*
         * Log the data block header if needed.
         */
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
+               xfs_dir2_data_log_header(args, dbp);
        /*
         * If the freespace entry is now wrong, update it.
         */
-       bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */
+       bests = dp->d_ops->free_bests_p(free); /* gcc is so stupid */
        if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) {
                bests[findex] = bf[0].length;
                logfree = 1;
@@ -2017,7 +1988,7 @@ xfs_dir2_node_addname_int(
         * Log the freespace entry if needed.
         */
        if (logfree)
-               xfs_dir2_free_log_bests(tp, fbp, findex, findex);
+               xfs_dir2_free_log_bests(args, fbp, findex, findex);
        /*
         * Return the data block and offset in args, then drop the data block.
         */
@@ -2048,8 +2019,6 @@ xfs_dir2_node_lookup(
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = args->dp->i_mount;
-       state->blocksize = state->mp->m_dirblksize;
-       state->node_ents = state->mp->m_dir_node_ents;
        /*
         * Fill in the path to the entry in the cursor.
         */
@@ -2103,8 +2072,6 @@ xfs_dir2_node_removename(
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = args->dp->i_mount;
-       state->blocksize = state->mp->m_dirblksize;
-       state->node_ents = state->mp->m_dir_node_ents;
 
        /* Look up the entry we're deleting, set up the cursor. */
        error = xfs_da3_node_lookup_int(state, &rval);
@@ -2173,8 +2140,6 @@ xfs_dir2_node_replace(
        state = xfs_da_state_alloc();
        state->args = args;
        state->mp = args->dp->i_mount;
-       state->blocksize = state->mp->m_dirblksize;
-       state->node_ents = state->mp->m_dir_node_ents;
        inum = args->inumber;
        /*
         * Lookup the entry to change in the btree.
@@ -2195,7 +2160,7 @@ xfs_dir2_node_replace(
                blk = &state->path.blk[state->path.active - 1];
                ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
                leaf = blk->bp->b_addr;
-               ents = xfs_dir3_leaf_ents_p(leaf);
+               ents = args->dp->d_ops->leaf_ents_p(leaf);
                lep = &ents[blk->index];
                ASSERT(state->extravalid);
                /*
@@ -2206,14 +2171,15 @@ xfs_dir2_node_replace(
                       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
                dep = (xfs_dir2_data_entry_t *)
                      ((char *)hdr +
-                      xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
+                      xfs_dir2_dataptr_to_off(args->geo,
+                                              be32_to_cpu(lep->address)));
                ASSERT(inum != be64_to_cpu(dep->inumber));
                /*
                 * Fill in the new inode number and log the entry.
                 */
                dep->inumber = cpu_to_be64(inum);
-               xfs_dir3_dirent_put_ftype(state->mp, dep, args->filetype);
-               xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep);
+               args->dp->d_ops->data_put_ftype(dep, args->filetype);
+               xfs_dir2_data_log_entry(args, state->extrablk.bp, dep);
                rval = 0;
        }
        /*
@@ -2268,7 +2234,7 @@ xfs_dir2_node_trim_free(
        if (!bp)
                return 0;
        free = bp->b_addr;
-       xfs_dir3_free_hdr_from_disk(&freehdr, free);
+       dp->d_ops->free_hdr_from_disk(&freehdr, free);
 
        /*
         * If there are used entries, there's nothing to do.
@@ -2281,9 +2247,9 @@ xfs_dir2_node_trim_free(
        /*
         * Blow the block away.
         */
-       if ((error =
-           xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo),
-                   bp))) {
+       error = xfs_dir2_shrink_inode(args,
+                       xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo), bp);
+       if (error) {
                /*
                 * Can't fail with ENOSPC since that only happens with no
                 * space reservation, when breaking up an extent into two
index 926715f3c86e97ba28a9be693de9fba1b3696ece..4a8df72cab001d294acf86c34e3bb9c265492624 100644 (file)
@@ -20,6 +20,7 @@
 
 struct dir_context;
 
+
 /* xfs_dir2.c */
 extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
                                xfs_dir2_db_t *dbp);
@@ -53,12 +54,13 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
 extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
 extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
                xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp);
-extern int xfs_dir3_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp,
-               xfs_dablk_t bno, xfs_daddr_t mapped_bno);
+extern int xfs_dir3_data_readahead(struct xfs_inode *dp, xfs_dablk_t bno,
+               xfs_daddr_t mapped_bno);
 
 extern struct xfs_dir2_data_free *
 xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr,
-               struct xfs_dir2_data_unused *dup, int *loghead);
+               struct xfs_dir2_data_free *bf, struct xfs_dir2_data_unused *dup,
+               int *loghead);
 extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
                struct xfs_buf **bpp);
 
@@ -75,9 +77,9 @@ extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr,
                int *lowstalep, int *highstalep, int *lowlogp, int *highlogp);
 extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno,
                struct xfs_buf **bpp, __uint16_t magic);
-extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp,
-               int first, int last);
-extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp,
+extern void xfs_dir3_leaf_log_ents(struct xfs_da_args *args,
+               struct xfs_buf *bp, int first, int last);
+extern void xfs_dir3_leaf_log_header(struct xfs_da_args *args,
                struct xfs_buf *bp);
 extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
 extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
@@ -92,21 +94,18 @@ xfs_dir3_leaf_find_entry(struct xfs_dir3_icleaf_hdr *leafhdr,
                int lowstale, int highstale, int *lfloglow, int *lfloghigh);
 extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
 
-extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
-               struct xfs_dir2_leaf *from);
-extern void xfs_dir3_leaf_hdr_to_disk(struct xfs_dir2_leaf *to,
-               struct xfs_dir3_icleaf_hdr *from);
-extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp,
+extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, struct xfs_inode *dp,
                struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf);
 
 /* xfs_dir2_node.c */
 extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
                struct xfs_buf *lbp);
-extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_buf *bp, int *count);
+extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_inode *dp,
+               struct xfs_buf *bp, int *count);
 extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp,
                struct xfs_da_args *args, int *indexp,
                struct xfs_da_state *state);
-extern int xfs_dir2_leafn_order(struct xfs_buf *leaf1_bp,
+extern int xfs_dir2_leafn_order(struct xfs_inode *dp, struct xfs_buf *leaf1_bp,
                struct xfs_buf *leaf2_bp);
 extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
        struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk);
index 75803338561376a4a758bc789d9e62931c2254c6..b5c5bca25c28e058048ba3c1771b839140e70f52 100644 (file)
@@ -39,89 +39,6 @@ static void xfs_dir2_sf_toino4(xfs_da_args_t *args);
 static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
 #endif /* XFS_BIG_INUMS */
 
-/*
- * Inode numbers in short-form directories can come in two versions,
- * either 4 bytes or 8 bytes wide.  These helpers deal with the
- * two forms transparently by looking at the headers i8count field.
- *
- * For 64-bit inode number the most significant byte must be zero.
- */
-static xfs_ino_t
-xfs_dir2_sf_get_ino(
-       struct xfs_dir2_sf_hdr  *hdr,
-       xfs_dir2_inou_t         *from)
-{
-       if (hdr->i8count)
-               return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
-       else
-               return get_unaligned_be32(&from->i4.i);
-}
-
-static void
-xfs_dir2_sf_put_ino(
-       struct xfs_dir2_sf_hdr  *hdr,
-       xfs_dir2_inou_t         *to,
-       xfs_ino_t               ino)
-{
-       ASSERT((ino & 0xff00000000000000ULL) == 0);
-
-       if (hdr->i8count)
-               put_unaligned_be64(ino, &to->i8.i);
-       else
-               put_unaligned_be32(ino, &to->i4.i);
-}
-
-xfs_ino_t
-xfs_dir2_sf_get_parent_ino(
-       struct xfs_dir2_sf_hdr  *hdr)
-{
-       return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
-}
-
-void
-xfs_dir2_sf_put_parent_ino(
-       struct xfs_dir2_sf_hdr  *hdr,
-       xfs_ino_t               ino)
-{
-       xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
-}
-
-/*
- * In short-form directory entries the inode numbers are stored at variable
- * offset behind the entry name. If the entry stores a filetype value, then it
- * sits between the name and the inode number. Hence the inode numbers may only
- * be accessed through the helpers below.
- */
-static xfs_dir2_inou_t *
-xfs_dir3_sfe_inop(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_entry *sfep)
-{
-       __uint8_t       *ptr = &sfep->name[sfep->namelen];
-       if (xfs_sb_version_hasftype(&mp->m_sb))
-               ptr++;
-       return (xfs_dir2_inou_t *)ptr;
-}
-
-xfs_ino_t
-xfs_dir3_sfe_get_ino(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_hdr  *hdr,
-       struct xfs_dir2_sf_entry *sfep)
-{
-       return xfs_dir2_sf_get_ino(hdr, xfs_dir3_sfe_inop(mp, sfep));
-}
-
-void
-xfs_dir3_sfe_put_ino(
-       struct xfs_mount        *mp,
-       struct xfs_dir2_sf_hdr  *hdr,
-       struct xfs_dir2_sf_entry *sfep,
-       xfs_ino_t               ino)
-{
-       xfs_dir2_sf_put_ino(hdr, xfs_dir3_sfe_inop(mp, sfep), ino);
-}
-
 /*
  * Given a block directory (dp/block), calculate its size as a shortform (sf)
  * directory and a header for the sf directory, if it will fit it the
@@ -148,8 +65,10 @@ xfs_dir2_block_sfsize(
        xfs_ino_t               parent = 0;     /* parent inode number */
        int                     size=0;         /* total computed size */
        int                     has_ftype;
+       struct xfs_da_geometry  *geo;
 
        mp = dp->i_mount;
+       geo = mp->m_dir_geo;
 
        /*
         * if there is a filetype field, add the extra byte to the namelen
@@ -158,7 +77,7 @@ xfs_dir2_block_sfsize(
        has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0;
 
        count = i8count = namelen = 0;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
 
        /*
@@ -170,8 +89,8 @@ xfs_dir2_block_sfsize(
                /*
                 * Calculate the pointer to the entry at hand.
                 */
-               dep = (xfs_dir2_data_entry_t *)
-                     ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr));
+               dep = (xfs_dir2_data_entry_t *)((char *)hdr +
+                               xfs_dir2_dataptr_to_off(geo, addr));
                /*
                 * Detect . and .., so we can special-case them.
                 * . is not included in sf directories.
@@ -209,7 +128,7 @@ xfs_dir2_block_sfsize(
         */
        sfhp->count = count;
        sfhp->i8count = i8count;
-       xfs_dir2_sf_put_parent_ino(sfhp, parent);
+       dp->d_ops->sf_put_parent_ino(sfhp, parent);
        return size;
 }
 
@@ -236,6 +155,7 @@ xfs_dir2_block_to_sf(
        char                    *ptr;           /* current data pointer */
        xfs_dir2_sf_entry_t     *sfep;          /* shortform entry */
        xfs_dir2_sf_hdr_t       *sfp;           /* shortform directory header */
+       xfs_dir2_sf_hdr_t       *dst;           /* temporary data buffer */
 
        trace_xfs_dir2_block_to_sf(args);
 
@@ -243,40 +163,25 @@ xfs_dir2_block_to_sf(
        mp = dp->i_mount;
 
        /*
-        * Make a copy of the block data, so we can shrink the inode
-        * and add local data.
+        * allocate a temporary destination buffer the size of the inode
+        * to format the data into. Once we have formatted the data, we
+        * can free the block and copy the formatted data into the inode literal
+        * area.
         */
-       hdr = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
-       memcpy(hdr, bp->b_addr, mp->m_dirblksize);
-       logflags = XFS_ILOG_CORE;
-       if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) {
-               ASSERT(error != ENOSPC);
-               goto out;
-       }
+       dst = kmem_alloc(mp->m_sb.sb_inodesize, KM_SLEEP);
+       hdr = bp->b_addr;
 
-       /*
-        * The buffer is now unconditionally gone, whether
-        * xfs_dir2_shrink_inode worked or not.
-        *
-        * Convert the inode to local format.
-        */
-       dp->i_df.if_flags &= ~XFS_IFEXTENTS;
-       dp->i_df.if_flags |= XFS_IFINLINE;
-       dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
-       ASSERT(dp->i_df.if_bytes == 0);
-       xfs_idata_realloc(dp, size, XFS_DATA_FORK);
-       logflags |= XFS_ILOG_DDATA;
        /*
         * Copy the header into the newly allocate local space.
         */
-       sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+       sfp = (xfs_dir2_sf_hdr_t *)dst;
        memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
-       dp->i_d.di_size = size;
+
        /*
         * Set up to loop over the block's entries.
         */
-       btp = xfs_dir2_block_tail_p(mp, hdr);
-       ptr = (char *)xfs_dir3_data_entry_p(hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
+       ptr = (char *)dp->d_ops->data_entry_p(hdr);
        endptr = (char *)xfs_dir2_block_leaf_p(btp);
        sfep = xfs_dir2_sf_firstentry(sfp);
        /*
@@ -304,7 +209,7 @@ xfs_dir2_block_to_sf(
                else if (dep->namelen == 2 &&
                         dep->name[0] == '.' && dep->name[1] == '.')
                        ASSERT(be64_to_cpu(dep->inumber) ==
-                              xfs_dir2_sf_get_parent_ino(sfp));
+                              dp->d_ops->sf_get_parent_ino(sfp));
                /*
                 * Normal entry, copy it into shortform.
                 */
@@ -314,20 +219,44 @@ xfs_dir2_block_to_sf(
                                (xfs_dir2_data_aoff_t)
                                ((char *)dep - (char *)hdr));
                        memcpy(sfep->name, dep->name, dep->namelen);
-                       xfs_dir3_sfe_put_ino(mp, sfp, sfep,
-                                            be64_to_cpu(dep->inumber));
-                       xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
-                                       xfs_dir3_dirent_get_ftype(mp, dep));
+                       dp->d_ops->sf_put_ino(sfp, sfep,
+                                             be64_to_cpu(dep->inumber));
+                       dp->d_ops->sf_put_ftype(sfep,
+                                       dp->d_ops->data_get_ftype(dep));
 
-                       sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
+                       sfep = dp->d_ops->sf_nextentry(sfp, sfep);
                }
-               ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+               ptr += dp->d_ops->data_entsize(dep->namelen);
        }
        ASSERT((char *)sfep - (char *)sfp == size);
+
+       /* now we are done with the block, we can shrink the inode */
+       logflags = XFS_ILOG_CORE;
+       error = xfs_dir2_shrink_inode(args, args->geo->datablk, bp);
+       if (error) {
+               ASSERT(error != ENOSPC);
+               goto out;
+       }
+
+       /*
+        * The buffer is now unconditionally gone, whether
+        * xfs_dir2_shrink_inode worked or not.
+        *
+        * Convert the inode to local format and copy the data in.
+        */
+       dp->i_df.if_flags &= ~XFS_IFEXTENTS;
+       dp->i_df.if_flags |= XFS_IFINLINE;
+       dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+       ASSERT(dp->i_df.if_bytes == 0);
+       xfs_idata_realloc(dp, size, XFS_DATA_FORK);
+
+       logflags |= XFS_ILOG_DDATA;
+       memcpy(dp->i_df.if_u1.if_data, dst, size);
+       dp->i_d.di_size = size;
        xfs_dir2_sf_check(args);
 out:
        xfs_trans_log_inode(args->trans, dp, logflags);
-       kmem_free(hdr);
+       kmem_free(dst);
        return error;
 }
 
@@ -341,14 +270,12 @@ int                                               /* error */
 xfs_dir2_sf_addname(
        xfs_da_args_t           *args)          /* operation arguments */
 {
-       int                     add_entsize;    /* size of the new entry */
        xfs_inode_t             *dp;            /* incore directory inode */
        int                     error;          /* error return value */
        int                     incr_isize;     /* total change in size */
        int                     new_isize;      /* di_size after adding name */
        int                     objchange;      /* changing to 8-byte inodes */
        xfs_dir2_data_aoff_t    offset = 0;     /* offset for new entry */
-       int                     old_isize;      /* di_size before adding name */
        int                     pick;           /* which algorithm to use */
        xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
        xfs_dir2_sf_entry_t     *sfep = NULL;   /* shortform entry */
@@ -372,8 +299,7 @@ xfs_dir2_sf_addname(
        /*
         * Compute entry (and change in) size.
         */
-       add_entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen);
-       incr_isize = add_entsize;
+       incr_isize = dp->d_ops->sf_entsize(sfp, args->namelen);
        objchange = 0;
 #if XFS_BIG_INUMS
        /*
@@ -381,11 +307,8 @@ xfs_dir2_sf_addname(
         */
        if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) {
                /*
-                * Yes, adjust the entry size and the total size.
+                * Yes, adjust the inode size.  old count + (parent + new)
                 */
-               add_entsize +=
-                       (uint)sizeof(xfs_dir2_ino8_t) -
-                       (uint)sizeof(xfs_dir2_ino4_t);
                incr_isize +=
                        (sfp->count + 2) *
                        ((uint)sizeof(xfs_dir2_ino8_t) -
@@ -393,8 +316,7 @@ xfs_dir2_sf_addname(
                objchange = 1;
        }
 #endif
-       old_isize = (int)dp->i_d.di_size;
-       new_isize = old_isize + incr_isize;
+       new_isize = (int)dp->i_d.di_size + incr_isize;
        /*
         * Won't fit as shortform any more (due to size),
         * or the pick routine says it won't (due to offset values).
@@ -466,8 +388,7 @@ xfs_dir2_sf_addname_easy(
        /*
         * Grow the in-inode space.
         */
-       xfs_idata_realloc(dp,
-                         xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen),
+       xfs_idata_realloc(dp, dp->d_ops->sf_entsize(sfp, args->namelen),
                          XFS_DATA_FORK);
        /*
         * Need to set up again due to realloc of the inode data.
@@ -480,8 +401,8 @@ xfs_dir2_sf_addname_easy(
        sfep->namelen = args->namelen;
        xfs_dir2_sf_put_offset(sfep, offset);
        memcpy(sfep->name, args->name, sfep->namelen);
-       xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, args->inumber);
-       xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep, args->filetype);
+       dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
+       dp->d_ops->sf_put_ftype(sfep, args->filetype);
 
        /*
         * Update the header and inode.
@@ -540,13 +461,13 @@ xfs_dir2_sf_addname_hard(
         * to insert the new entry.
         * If it's going to end up at the end then oldsfep will point there.
         */
-       for (offset = xfs_dir3_data_first_offset(mp),
+       for (offset = dp->d_ops->data_first_offset,
              oldsfep = xfs_dir2_sf_firstentry(oldsfp),
-             add_datasize = xfs_dir3_data_entsize(mp, args->namelen),
+             add_datasize = dp->d_ops->data_entsize(args->namelen),
              eof = (char *)oldsfep == &buf[old_isize];
             !eof;
-            offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen),
-             oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep),
+            offset = new_offset + dp->d_ops->data_entsize(oldsfep->namelen),
+             oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep),
              eof = (char *)oldsfep == &buf[old_isize]) {
                new_offset = xfs_dir2_sf_get_offset(oldsfep);
                if (offset + add_datasize <= new_offset)
@@ -575,8 +496,8 @@ xfs_dir2_sf_addname_hard(
        sfep->namelen = args->namelen;
        xfs_dir2_sf_put_offset(sfep, offset);
        memcpy(sfep->name, args->name, sfep->namelen);
-       xfs_dir3_sfe_put_ino(mp, sfp, sfep, args->inumber);
-       xfs_dir3_sfe_put_ftype(mp, sfp, sfep, args->filetype);
+       dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
+       dp->d_ops->sf_put_ftype(sfep, args->filetype);
        sfp->count++;
 #if XFS_BIG_INUMS
        if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -586,7 +507,7 @@ xfs_dir2_sf_addname_hard(
         * If there's more left to copy, do that.
         */
        if (!eof) {
-               sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
+               sfep = dp->d_ops->sf_nextentry(sfp, sfep);
                memcpy(sfep, oldsfep, old_isize - nbytes);
        }
        kmem_free(buf);
@@ -622,8 +543,8 @@ xfs_dir2_sf_addname_pick(
        mp = dp->i_mount;
 
        sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
-       size = xfs_dir3_data_entsize(mp, args->namelen);
-       offset = xfs_dir3_data_first_offset(mp);
+       size = dp->d_ops->data_entsize(args->namelen);
+       offset = dp->d_ops->data_first_offset;
        sfep = xfs_dir2_sf_firstentry(sfp);
        holefit = 0;
        /*
@@ -635,8 +556,8 @@ xfs_dir2_sf_addname_pick(
                if (!holefit)
                        holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
                offset = xfs_dir2_sf_get_offset(sfep) +
-                        xfs_dir3_data_entsize(mp, sfep->namelen);
-               sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
+                        dp->d_ops->data_entsize(sfep->namelen);
+               sfep = dp->d_ops->sf_nextentry(sfp, sfep);
        }
        /*
         * Calculate data bytes used excluding the new entry, if this
@@ -650,7 +571,7 @@ xfs_dir2_sf_addname_pick(
         * we'll go back, convert to block, then try the insert and convert
         * to leaf.
         */
-       if (used + (holefit ? 0 : size) > mp->m_dirblksize)
+       if (used + (holefit ? 0 : size) > args->geo->blksize)
                return 0;
        /*
         * If changing the inode number size, do it the hard way.
@@ -665,7 +586,7 @@ xfs_dir2_sf_addname_pick(
        /*
         * If it won't fit at the end then do it the hard way (use the hole).
         */
-       if (used + size > mp->m_dirblksize)
+       if (used + size > args->geo->blksize)
                return 2;
        /*
         * Do it the easy way.
@@ -696,28 +617,27 @@ xfs_dir2_sf_check(
        mp = dp->i_mount;
 
        sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
-       offset = xfs_dir3_data_first_offset(mp);
-       ino = xfs_dir2_sf_get_parent_ino(sfp);
+       offset = dp->d_ops->data_first_offset;
+       ino = dp->d_ops->sf_get_parent_ino(sfp);
        i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
 
        for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
             i < sfp->count;
-            i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep)) {
+            i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
                ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
-               ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
+               ino = dp->d_ops->sf_get_ino(sfp, sfep);
                i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
                offset =
                        xfs_dir2_sf_get_offset(sfep) +
-                       xfs_dir3_data_entsize(mp, sfep->namelen);
-               ASSERT(xfs_dir3_sfe_get_ftype(mp, sfp, sfep) <
-                                                       XFS_DIR3_FT_MAX);
+                       dp->d_ops->data_entsize(sfep->namelen);
+               ASSERT(dp->d_ops->sf_get_ftype(sfep) < XFS_DIR3_FT_MAX);
        }
        ASSERT(i8count == sfp->i8count);
        ASSERT(XFS_BIG_INUMS || i8count == 0);
        ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size);
        ASSERT(offset +
               (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
-              (uint)sizeof(xfs_dir2_block_tail_t) <= mp->m_dirblksize);
+              (uint)sizeof(xfs_dir2_block_tail_t) <= args->geo->blksize);
 }
 #endif /* DEBUG */
 
@@ -766,7 +686,7 @@ xfs_dir2_sf_create(
        /*
         * Now can put in the inode number, since i8count is set.
         */
-       xfs_dir2_sf_put_parent_ino(sfp, pino);
+       dp->d_ops->sf_put_parent_ino(sfp, pino);
        sfp->count = 0;
        dp->i_d.di_size = size;
        xfs_dir2_sf_check(args);
@@ -821,7 +741,7 @@ xfs_dir2_sf_lookup(
         */
        if (args->namelen == 2 &&
            args->name[0] == '.' && args->name[1] == '.') {
-               args->inumber = xfs_dir2_sf_get_parent_ino(sfp);
+               args->inumber = dp->d_ops->sf_get_parent_ino(sfp);
                args->cmpresult = XFS_CMP_EXACT;
                args->filetype = XFS_DIR3_FT_DIR;
                return XFS_ERROR(EEXIST);
@@ -831,7 +751,7 @@ xfs_dir2_sf_lookup(
         */
        ci_sfep = NULL;
        for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
-            i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
+            i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
                /*
                 * Compare name and if it's an exact match, return the inode
                 * number. If it's the first case-insensitive match, store the
@@ -841,10 +761,8 @@ xfs_dir2_sf_lookup(
                                                                sfep->namelen);
                if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
                        args->cmpresult = cmp;
-                       args->inumber = xfs_dir3_sfe_get_ino(dp->i_mount,
-                                                            sfp, sfep);
-                       args->filetype = xfs_dir3_sfe_get_ftype(dp->i_mount,
-                                                               sfp, sfep);
+                       args->inumber = dp->d_ops->sf_get_ino(sfp, sfep);
+                       args->filetype = dp->d_ops->sf_get_ftype(sfep);
                        if (cmp == XFS_CMP_EXACT)
                                return XFS_ERROR(EEXIST);
                        ci_sfep = sfep;
@@ -900,10 +818,10 @@ xfs_dir2_sf_removename(
         * Find the one we're deleting.
         */
        for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
-            i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
+            i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
                if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
                                                                XFS_CMP_EXACT) {
-                       ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) ==
+                       ASSERT(dp->d_ops->sf_get_ino(sfp, sfep) ==
                               args->inumber);
                        break;
                }
@@ -917,7 +835,7 @@ xfs_dir2_sf_removename(
         * Calculate sizes.
         */
        byteoff = (int)((char *)sfep - (char *)sfp);
-       entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen);
+       entsize = dp->d_ops->sf_entsize(sfp, args->namelen);
        newsize = oldsize - entsize;
        /*
         * Copy the part if any after the removed entry, sliding it down.
@@ -1024,28 +942,25 @@ xfs_dir2_sf_replace(
        if (args->namelen == 2 &&
            args->name[0] == '.' && args->name[1] == '.') {
 #if XFS_BIG_INUMS || defined(DEBUG)
-               ino = xfs_dir2_sf_get_parent_ino(sfp);
+               ino = dp->d_ops->sf_get_parent_ino(sfp);
                ASSERT(args->inumber != ino);
 #endif
-               xfs_dir2_sf_put_parent_ino(sfp, args->inumber);
+               dp->d_ops->sf_put_parent_ino(sfp, args->inumber);
        }
        /*
         * Normal entry, look for the name.
         */
        else {
                for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
-                    i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
+                    i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
                        if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
                                                                XFS_CMP_EXACT) {
 #if XFS_BIG_INUMS || defined(DEBUG)
-                               ino = xfs_dir3_sfe_get_ino(dp->i_mount,
-                                                          sfp, sfep);
+                               ino = dp->d_ops->sf_get_ino(sfp, sfep);
                                ASSERT(args->inumber != ino);
 #endif
-                               xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep,
-                                                    args->inumber);
-                               xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep,
-                                                      args->filetype);
+                               dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
+                               dp->d_ops->sf_put_ftype(sfep, args->filetype);
                                break;
                        }
                }
@@ -1148,22 +1063,21 @@ xfs_dir2_sf_toino4(
         */
        sfp->count = oldsfp->count;
        sfp->i8count = 0;
-       xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp));
+       dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp));
        /*
         * Copy the entries field by field.
         */
        for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
                    oldsfep = xfs_dir2_sf_firstentry(oldsfp);
             i < sfp->count;
-            i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep),
-                 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) {
+            i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep),
+                 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) {
                sfep->namelen = oldsfep->namelen;
                sfep->offset = oldsfep->offset;
                memcpy(sfep->name, oldsfep->name, sfep->namelen);
-               xfs_dir3_sfe_put_ino(mp, sfp, sfep,
-                       xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep));
-               xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
-                       xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep));
+               dp->d_ops->sf_put_ino(sfp, sfep,
+                                     dp->d_ops->sf_get_ino(oldsfp, oldsfep));
+               dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep));
        }
        /*
         * Clean up the inode.
@@ -1174,9 +1088,9 @@ xfs_dir2_sf_toino4(
 }
 
 /*
- * Convert from 4-byte inode numbers to 8-byte inode numbers.
- * The new 8-byte inode number is not there yet, we leave with the
- * count 1 but no corresponding entry.
+ * Convert existing entries from 4-byte inode numbers to 8-byte inode numbers.
+ * The new entry w/ an 8-byte inode number is not there yet; we leave with
+ * i8count set to 1, but no corresponding 8-byte entry.
  */
 static void
 xfs_dir2_sf_toino8(
@@ -1209,7 +1123,7 @@ xfs_dir2_sf_toino8(
        ASSERT(oldsfp->i8count == 0);
        memcpy(buf, oldsfp, oldsize);
        /*
-        * Compute the new inode size.
+        * Compute the new inode size (nb: entry count + 1 for parent)
         */
        newsize =
                oldsize +
@@ -1227,22 +1141,21 @@ xfs_dir2_sf_toino8(
         */
        sfp->count = oldsfp->count;
        sfp->i8count = 1;
-       xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp));
+       dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp));
        /*
         * Copy the entries field by field.
         */
        for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
                    oldsfep = xfs_dir2_sf_firstentry(oldsfp);
             i < sfp->count;
-            i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep),
-                 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) {
+            i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep),
+                 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) {
                sfep->namelen = oldsfep->namelen;
                sfep->offset = oldsfep->offset;
                memcpy(sfep->name, oldsfep->name, sfep->namelen);
-               xfs_dir3_sfe_put_ino(mp, sfp, sfep,
-                       xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep));
-               xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
-                       xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep));
+               dp->d_ops->sf_put_ino(sfp, sfep,
+                                     dp->d_ops->sf_get_ino(oldsfp, oldsfep));
+               dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep));
        }
        /*
         * Clean up the inode.
index e089ec8d9658f85db49e62d731174de6d7adb2cd..fae05a59825c214df2fe45f52dd224b955e6bb02 100644 (file)
  */
 #include "xfs.h"
 
+/*
+ * XXX: kernel implementation causes ndquots calc to go real
+ * bad. Just leaving the existing userspace calc here right now.
+ */
 int
 xfs_calc_dquots_per_chunk(
-       struct xfs_mount        *mp,
        unsigned int            nbblks) /* basic block units */
 {
+
        ASSERT(nbblks > 0);
        return BBTOB(nbblks) / sizeof(xfs_dqblk_t);
+
+#if 0  /* kernel code that goes wrong in userspace! */
+       unsigned int    ndquots;
+
+       ASSERT(nbblks > 0);
+       ndquots = BBTOB(nbblks);
+       do_div(ndquots, sizeof(xfs_dqblk_t));
+
+       return ndquots;
+#endif
 }
 
 /*
@@ -174,8 +188,8 @@ xfs_dquot_buf_verify_crc(
        if (mp->m_quotainfo)
                ndquots = mp->m_quotainfo->qi_dqperchunk;
        else
-               ndquots = xfs_calc_dquots_per_chunk(mp,
-                                       XFS_BB_TO_FSB(mp, bp->b_length));
+               ndquots = xfs_calc_dquots_per_chunk(bp->b_length);
+//                                     XFS_BB_TO_FSB(mp, bp->b_length));
 
        for (i = 0; i < ndquots; i++, d++) {
                if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
@@ -205,7 +219,7 @@ xfs_dquot_buf_verify(
        if (mp->m_quotainfo)
                ndquots = mp->m_quotainfo->qi_dqperchunk;
        else
-               ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length);
+               ndquots = xfs_calc_dquots_per_chunk(bp->b_length);
 
        /*
         * On the first read of the buffer, verify that each dquot is valid.
@@ -251,7 +265,7 @@ xfs_dquot_buf_read_verify(
  * the buffer after the update is done. This ensures that the dquot in the
  * buffer always has an up-to-date CRC value.
  */
-void
+static void
 xfs_dquot_buf_write_verify(
        struct xfs_buf  *bp)
 {
index b20a9ec6d0cf22112b33037b08b2eb7b6956c377..5c080c92e4302026ea6684efe2a31f42b8d754a0 100644 (file)
@@ -28,7 +28,7 @@ xfs_ialloc_cluster_alignment(
 {
        if (xfs_sb_version_hasalign(&args->mp->m_sb) &&
            args->mp->m_sb.sb_inoalignmt >=
-            XFS_B_TO_FSBT(args->mp, XFS_INODE_CLUSTER_SIZE(args->mp)))
+            XFS_B_TO_FSBT(args->mp, args->mp->m_inode_cluster_size))
                return args->mp->m_sb.sb_inoalignmt;
        return 1;
 }
@@ -206,27 +206,20 @@ xfs_ialloc_inode_init(
 {
        struct xfs_buf          *fbuf;
        struct xfs_dinode       *free;
-       int                     blks_per_cluster, nbufs, ninodes;
+       int                     nbufs, blks_per_cluster, inodes_per_cluster;
        int                     version;
        int                     i, j;
        xfs_daddr_t             d;
        xfs_ino_t               ino = 0;
 
        /*
-        * Loop over the new block(s), filling in the inodes.
-        * For small block sizes, manipulate the inodes in buffers
-        * which are multiples of the blocks size.
+        * Loop over the new block(s), filling in the inodes.  For small block
+        * sizes, manipulate the inodes in buffers  which are multiples of the
+        * blocks size.
         */
-       if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
-               blks_per_cluster = 1;
-               nbufs = length;
-               ninodes = mp->m_sb.sb_inopblock;
-       } else {
-               blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) /
-                                  mp->m_sb.sb_blocksize;
-               nbufs = length / blks_per_cluster;
-               ninodes = blks_per_cluster * mp->m_sb.sb_inopblock;
-       }
+       blks_per_cluster = xfs_icluster_size_fsb(mp);
+       inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
+       nbufs = length / blks_per_cluster;
 
        /*
         * Figure out what version number to use in the inodes we create.  If
@@ -261,12 +254,10 @@ xfs_ialloc_inode_init(
                 * they track in the AIL as if they were physically logged.
                 */
                if (tp)
-                       xfs_icreate_log(tp, agno, agbno, XFS_IALLOC_INODES(mp),
+                       xfs_icreate_log(tp, agno, agbno, mp->m_ialloc_inos,
                                        mp->m_sb.sb_inodesize, length, gen);
-       } else if (xfs_sb_version_hasnlink(&mp->m_sb))
+       } else
                version = 2;
-       else
-               version = 1;
 
        for (j = 0; j < nbufs; j++) {
                /*
@@ -282,7 +273,7 @@ xfs_ialloc_inode_init(
                /* Initialize the inode buffers and log them appropriately. */
                fbuf->b_ops = &xfs_inode_buf_ops;
                xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length));
-               for (i = 0; i < ninodes; i++) {
+               for (i = 0; i < inodes_per_cluster; i++) {
                        int     ioffset = i << mp->m_sb.sb_inodelog;
                        uint    isize = xfs_dinode_size(version);
 
@@ -362,11 +353,11 @@ xfs_ialloc_ag_alloc(
         * Locking will ensure that we don't have two callers in here
         * at one time.
         */
-       newlen = XFS_IALLOC_INODES(args.mp);
+       newlen = args.mp->m_ialloc_inos;
        if (args.mp->m_maxicount &&
            args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
                return XFS_ERROR(ENOSPC);
-       args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
+       args.minlen = args.maxlen = args.mp->m_ialloc_blks;
        /*
         * First try to allocate inodes contiguous with the last-allocated
         * chunk of inodes.  If the filesystem is striped, this will fill
@@ -376,7 +367,7 @@ xfs_ialloc_ag_alloc(
        newino = be32_to_cpu(agi->agi_newino);
        agno = be32_to_cpu(agi->agi_seqno);
        args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
-                       XFS_IALLOC_BLOCKS(args.mp);
+                    args.mp->m_ialloc_blks;
        if (likely(newino != NULLAGINO &&
                  (args.agbno < be32_to_cpu(agi->agi_length)))) {
                args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
@@ -403,6 +394,18 @@ xfs_ialloc_ag_alloc(
                args.minleft = args.mp->m_in_maxlevels - 1;
                if ((error = xfs_alloc_vextent(&args)))
                        return error;
+
+               /*
+                * This request might have dirtied the transaction if the AG can
+                * satisfy the request, but the exact block was not available.
+                * If the allocation did fail, subsequent requests will relax
+                * the exact agbno requirement and increase the alignment
+                * instead. It is critical that the total size of the request
+                * (len + alignment + slop) does not increase from this point
+                * on, so reset minalignslop to ensure it is not included in
+                * subsequent requests.
+                */
+               args.minalignslop = 0;
        } else
                args.fsbno = NULLFSBLOCK;
 
@@ -608,7 +611,7 @@ xfs_ialloc_ag_select(
                 * Is there enough free space for the file plus a block of
                 * inodes? (if we need to allocate some)?
                 */
-               ineed = XFS_IALLOC_BLOCKS(mp);
+               ineed = mp->m_ialloc_blks;
                longest = pag->pagf_longest;
                if (!longest)
                        longest = pag->pagf_flcount > 0;
@@ -693,13 +696,10 @@ xfs_ialloc_get_rec(
 }
 
 /*
- * Allocate an inode.
- *
- * The caller selected an AG for us, and made sure that free inodes are
- * available.
+ * Allocate an inode using the inobt-only algorithm.
  */
 STATIC int
-xfs_dialloc_ag_slow(
+xfs_dialloc_ag_inobt(
        struct xfs_trans        *tp,
        struct xfs_buf          *agbp,
        xfs_ino_t               parent,
@@ -957,6 +957,177 @@ error0:
        return error;
 }
 
+/*
+ * Use the free inode btree to allocate an inode based on distance from the
+ * parent. Note that the provided cursor may be deleted and replaced.
+ */
+STATIC int
+xfs_dialloc_ag_finobt_near(
+       xfs_agino_t                     pagino,
+       struct xfs_btree_cur            **ocur,
+       struct xfs_inobt_rec_incore     *rec)
+{
+       struct xfs_btree_cur            *lcur = *ocur;  /* left search cursor */
+       struct xfs_btree_cur            *rcur;  /* right search cursor */
+       struct xfs_inobt_rec_incore     rrec;
+       int                             error;
+       int                             i, j;
+
+       error = xfs_inobt_lookup(lcur, pagino, XFS_LOOKUP_LE, &i);
+       if (error)
+               return error;
+
+       if (i == 1) {
+               error = xfs_inobt_get_rec(lcur, rec, &i);
+               if (error)
+                       return error;
+               XFS_WANT_CORRUPTED_RETURN(i == 1);
+
+               /*
+                * See if we've landed in the parent inode record. The finobt
+                * only tracks chunks with at least one free inode, so record
+                * existence is enough.
+                */
+               if (pagino >= rec->ir_startino &&
+                   pagino < (rec->ir_startino + XFS_INODES_PER_CHUNK))
+                       return 0;
+       }
+
+       error = xfs_btree_dup_cursor(lcur, &rcur);
+       if (error)
+               return error;
+
+       error = xfs_inobt_lookup(rcur, pagino, XFS_LOOKUP_GE, &j);
+       if (error)
+               goto error_rcur;
+       if (j == 1) {
+               error = xfs_inobt_get_rec(rcur, &rrec, &j);
+               if (error)
+                       goto error_rcur;
+               XFS_WANT_CORRUPTED_GOTO(j == 1, error_rcur);
+       }
+
+       XFS_WANT_CORRUPTED_GOTO(i == 1 || j == 1, error_rcur);
+       if (i == 1 && j == 1) {
+               /*
+                * Both the left and right records are valid. Choose the closer
+                * inode chunk to the target.
+                */
+               if ((pagino - rec->ir_startino + XFS_INODES_PER_CHUNK - 1) >
+                   (rrec.ir_startino - pagino)) {
+                       *rec = rrec;
+                       xfs_btree_del_cursor(lcur, XFS_BTREE_NOERROR);
+                       *ocur = rcur;
+               } else {
+                       xfs_btree_del_cursor(rcur, XFS_BTREE_NOERROR);
+               }
+       } else if (j == 1) {
+               /* only the right record is valid */
+               *rec = rrec;
+               xfs_btree_del_cursor(lcur, XFS_BTREE_NOERROR);
+               *ocur = rcur;
+       } else if (i == 1) {
+               /* only the left record is valid */
+               xfs_btree_del_cursor(rcur, XFS_BTREE_NOERROR);
+       }
+
+       return 0;
+
+error_rcur:
+       xfs_btree_del_cursor(rcur, XFS_BTREE_ERROR);
+       return error;
+}
+
+/*
+ * Use the free inode btree to find a free inode based on a newino hint. If
+ * the hint is NULL, find the first free inode in the AG.
+ */
+STATIC int
+xfs_dialloc_ag_finobt_newino(
+       struct xfs_agi                  *agi,
+       struct xfs_btree_cur            *cur,
+       struct xfs_inobt_rec_incore     *rec)
+{
+       int error;
+       int i;
+
+       if (agi->agi_newino != cpu_to_be32(NULLAGINO)) {
+               error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino),
+                                        XFS_LOOKUP_EQ, &i);
+               if (error)
+                       return error;
+               if (i == 1) {
+                       error = xfs_inobt_get_rec(cur, rec, &i);
+                       if (error)
+                               return error;
+                       XFS_WANT_CORRUPTED_RETURN(i == 1);
+
+                       return 0;
+               }
+       }
+
+       /*
+        * Find the first inode available in the AG.
+        */
+       error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
+       if (error)
+               return error;
+       XFS_WANT_CORRUPTED_RETURN(i == 1);
+
+       error = xfs_inobt_get_rec(cur, rec, &i);
+       if (error)
+               return error;
+       XFS_WANT_CORRUPTED_RETURN(i == 1);
+
+       return 0;
+}
+
+/*
+ * Update the inobt based on a modification made to the finobt. Also ensure that
+ * the records from both trees are equivalent post-modification.
+ */
+STATIC int
+xfs_dialloc_ag_update_inobt(
+       struct xfs_btree_cur            *cur,   /* inobt cursor */
+       struct xfs_inobt_rec_incore     *frec,  /* finobt record */
+       int                             offset) /* inode offset */
+{
+       struct xfs_inobt_rec_incore     rec;
+       int                             error;
+       int                             i;
+
+       error = xfs_inobt_lookup(cur, frec->ir_startino, XFS_LOOKUP_EQ, &i);
+       if (error)
+               return error;
+       XFS_WANT_CORRUPTED_RETURN(i == 1);
+
+       error = xfs_inobt_get_rec(cur, &rec, &i);
+       if (error)
+               return error;
+       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       ASSERT((XFS_AGINO_TO_OFFSET(cur->bc_mp, rec.ir_startino) %
+                                  XFS_INODES_PER_CHUNK) == 0);
+
+       rec.ir_free &= ~XFS_INOBT_MASK(offset);
+       rec.ir_freecount--;
+
+       XFS_WANT_CORRUPTED_RETURN((rec.ir_free == frec->ir_free) &&
+                                 (rec.ir_freecount == frec->ir_freecount));
+
+       error = xfs_inobt_update(cur, &rec);
+       if (error)
+               return error;
+
+       return 0;
+}
+
+/*
+ * Allocate an inode using the free inode btree, if available. Otherwise, fall
+ * back to the inobt search algorithm.
+ *
+ * The caller selected an AG for us, and made sure that free inodes are
+ * available.
+ */
 STATIC int
 xfs_dialloc_ag(
        struct xfs_trans        *tp,
@@ -970,17 +1141,16 @@ xfs_dialloc_ag(
        xfs_agnumber_t                  pagno = XFS_INO_TO_AGNO(mp, parent);
        xfs_agino_t                     pagino = XFS_INO_TO_AGINO(mp, parent);
        struct xfs_perag                *pag;
-       struct xfs_btree_cur            *cur;
-       struct xfs_btree_cur            *tcur;
+       struct xfs_btree_cur            *cur;   /* finobt cursor */
+       struct xfs_btree_cur            *icur;  /* inobt cursor */
        struct xfs_inobt_rec_incore     rec;
-       struct xfs_inobt_rec_incore     trec;
        xfs_ino_t                       ino;
        int                             error;
        int                             offset;
-       int                             i, j;
+       int                             i;
 
        if (!xfs_sb_version_hasfinobt(&mp->m_sb))
-               return xfs_dialloc_ag_slow(tp, agbp, parent, inop);
+               return xfs_dialloc_ag_inobt(tp, agbp, parent, inop);
 
        pag = xfs_perag_get(mp, agno);
 
@@ -997,95 +1167,18 @@ xfs_dialloc_ag(
        if (error)
                goto error_cur;
 
-       if (agno == pagno) {
-               /*
-                * We're in the same AG as the parent inode so allocate the
-                * closest inode to the parent.
-                */
-               error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i);
-               if (error)
-                       goto error_cur;
-               if (i == 1) {
-                       error = xfs_inobt_get_rec(cur, &rec, &i);
-                       if (error)
-                               goto error_cur;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-
-                       /*
-                        * See if we've landed in the parent inode record. The
-                        * finobt only tracks chunks with at least one free
-                        * inode, so record existence is enough.
-                        */
-                       if (pagino >= rec.ir_startino &&
-                           pagino < (rec.ir_startino + XFS_INODES_PER_CHUNK))
-                               goto alloc_inode;
-               }
-
-               error = xfs_btree_dup_cursor(cur, &tcur);
-               if (error) 
-                       goto error_cur;
-
-               error = xfs_inobt_lookup(tcur, pagino, XFS_LOOKUP_GE, &j);
-               if (error)
-                       goto error_tcur;
-               if (j == 1) {
-                       error = xfs_inobt_get_rec(tcur, &trec, &j);
-                       if (error)
-                               goto error_tcur;
-                       XFS_WANT_CORRUPTED_GOTO(j == 1, error_tcur);
-               }
-
-               if (i == 1 && j == 1) {
-                       if ((pagino - rec.ir_startino + XFS_INODES_PER_CHUNK - 1) >
-                           (trec.ir_startino - pagino)) {
-                               rec = trec;
-                               xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-                               cur = tcur;
-                       } else {
-                               xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
-                       }
-               } else if (j == 1) {
-                       rec = trec;
-                       xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-                       cur = tcur;
-               } else {
-                       xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
-               }
-       } else {
-               /*
-                * Different AG from the parent inode. Check the record for the
-                * most recently allocated inode.
-                */
-               if (agi->agi_newino != cpu_to_be32(NULLAGINO)) {
-                       error = xfs_inobt_lookup(cur,
-                                                be32_to_cpu(agi->agi_newino),
-                                                XFS_LOOKUP_EQ, &i);
-                       if (error)
-                               goto error_cur;
-                       if (i == 1) {
-                               error = xfs_inobt_get_rec(cur, &rec, &i);
-                               if (error)
-                                       goto error_cur;
-                               XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-                               goto alloc_inode;
-                       }
-               }
-
-               /*
-                * Allocate the first inode available in the AG.
-                */
-               error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
-               if (error)
-                       goto error_cur;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-
-               error = xfs_inobt_get_rec(cur, &rec, &i);
-               if (error)
-                       goto error_cur;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-       }
+       /*
+        * The search algorithm depends on whether we're in the same AG as the
+        * parent. If so, find the closest available inode to the parent. If
+        * not, consider the agi hint or find the first free inode in the AG.
+        */
+       if (agno == pagno)
+               error = xfs_dialloc_ag_finobt_near(pagino, &cur, &rec);
+       else
+               error = xfs_dialloc_ag_finobt_newino(agi, cur, &rec);
+       if (error)
+               goto error_cur;
 
-alloc_inode:
        offset = xfs_lowbit64(rec.ir_free);
        ASSERT(offset >= 0);
        ASSERT(offset < XFS_INODES_PER_CHUNK);
@@ -1098,7 +1191,7 @@ alloc_inode:
         */
        rec.ir_free &= ~XFS_INOBT_MASK(offset);
        rec.ir_freecount--;
-       if (rec.ir_freecount) 
+       if (rec.ir_freecount)
                error = xfs_inobt_update(cur, &rec);
        else
                error = xfs_btree_delete(cur, &i);
@@ -1106,39 +1199,24 @@ alloc_inode:
                goto error_cur;
 
        /*
-        * Lookup and modify the equivalent record in the inobt.
+        * The finobt has now been updated appropriately. We haven't updated the
+        * agi and superblock yet, so we can create an inobt cursor and validate
+        * the original freecount. If all is well, make the equivalent update to
+        * the inobt using the finobt record and offset information.
         */
-       tcur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO);
-
-       error = xfs_check_agi_freecount(tcur, agi);
-       if (error)
-               goto error_tcur;
+       icur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO);
 
-       error = xfs_inobt_lookup(tcur, rec.ir_startino, XFS_LOOKUP_EQ, &i);
+       error = xfs_check_agi_freecount(icur, agi);
        if (error)
-               goto error_tcur;
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error_tcur);
+               goto error_icur;
 
-       error = xfs_inobt_get_rec(tcur, &trec, &i);
+       error = xfs_dialloc_ag_update_inobt(icur, &rec, offset);
        if (error)
-               goto error_tcur;
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error_tcur);
-       ASSERT((XFS_AGINO_TO_OFFSET(mp, trec.ir_startino) %
-                                  XFS_INODES_PER_CHUNK) == 0);
-
-       trec.ir_free &= ~XFS_INOBT_MASK(offset);
-       trec.ir_freecount--;
-
-       XFS_WANT_CORRUPTED_GOTO((rec.ir_free == trec.ir_free) &&
-                               (rec.ir_freecount == trec.ir_freecount),
-                               error_tcur);
-
-       error = xfs_inobt_update(tcur, &trec);
-       if (error)
-               goto error_tcur;
+               goto error_icur;
 
        /*
-        * Update the perag and superblock.
+        * Both trees have now been updated. We must update the perag and
+        * superblock before we can check the freecount for each btree.
         */
        be32_add_cpu(&agi->agi_freecount, -1);
        xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
@@ -1146,21 +1224,21 @@ alloc_inode:
 
        xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1);
 
-       error = xfs_check_agi_freecount(tcur, agi);
+       error = xfs_check_agi_freecount(icur, agi);
        if (error)
-               goto error_tcur;
+               goto error_icur;
        error = xfs_check_agi_freecount(cur, agi);
        if (error)
-               goto error_tcur;
+               goto error_icur;
 
-       xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
+       xfs_btree_del_cursor(icur, XFS_BTREE_NOERROR);
        xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
        xfs_perag_put(pag);
        *inop = ino;
        return 0;
 
-error_tcur:
-       xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
+error_icur:
+       xfs_btree_del_cursor(icur, XFS_BTREE_ERROR);
 error_cur:
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
        xfs_perag_put(pag);
@@ -1232,7 +1310,7 @@ xfs_dialloc(
         * inode.
         */
        if (mp->m_maxicount &&
-           mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) {
+           mp->m_sb.sb_icount + mp->m_ialloc_inos > mp->m_maxicount) {
                noroom = 1;
                okalloc = 0;
        }
@@ -1391,7 +1469,7 @@ xfs_difree_inobt(
         * When an inode cluster is free, it becomes eligible for removal
         */
        if (!(mp->m_flags & XFS_MOUNT_IKEEP) &&
-           (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
+           (rec.ir_freecount == mp->m_ialloc_inos)) {
 
                *deleted = 1;
                *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
@@ -1401,7 +1479,7 @@ xfs_difree_inobt(
                 * AGI and Superblock inode counts, and mark the disk space
                 * to be freed when the transaction is committed.
                 */
-               ilen = XFS_IALLOC_INODES(mp);
+               ilen = mp->m_ialloc_inos;
                be32_add_cpu(&agi->agi_count, -ilen);
                be32_add_cpu(&agi->agi_freecount, -(ilen - 1));
                xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
@@ -1417,9 +1495,9 @@ xfs_difree_inobt(
                        goto error0;
                }
 
-               xfs_bmap_add_free(XFS_AGB_TO_FSB(mp,
-                               agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),
-                               XFS_IALLOC_BLOCKS(mp), flist, mp);
+               xfs_bmap_add_free(XFS_AGB_TO_FSB(mp, agno,
+                                 XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)),
+                                 mp->m_ialloc_blks, flist, mp);
        } else {
                *deleted = 0;
 
@@ -1496,7 +1574,11 @@ xfs_difree_finobt(
        }
 
        /*
-        * Read and update the existing record.
+        * Read and update the existing record. We could just copy the ibtrec
+        * across here, but that would defeat the purpose of having redundant
+        * metadata. By making the modifications independently, we can catch
+        * corruptions that we wouldn't see if we just copied from one record
+        * to another.
         */
        error = xfs_inobt_get_rec(cur, &rec, &i);
        if (error)
@@ -1514,28 +1596,17 @@ xfs_difree_finobt(
         * The content of inobt records should always match between the inobt
         * and finobt. The lifecycle of records in the finobt is different from
         * the inobt in that the finobt only tracks records with at least one
-        * free inode. This is to optimize lookup for inode allocation purposes.
-        * The following checks determine whether to update the existing record or
-        * remove it entirely.
+        * free inode. Hence, if all of the inodes are free and we aren't
+        * keeping inode chunks permanently on disk, remove the record.
+        * Otherwise, update the record with the new information.
         */
-
-       if (rec.ir_freecount == XFS_IALLOC_INODES(mp) &&
+       if (rec.ir_freecount == mp->m_ialloc_inos &&
            !(mp->m_flags & XFS_MOUNT_IKEEP)) {
-               /*
-                * If all inodes are free and we're in !ikeep mode, the entire
-                * inode chunk has been deallocated. Remove the record from the
-                * finobt.
-                */
                error = xfs_btree_delete(cur, &i);
                if (error)
                        goto error;
                ASSERT(i == 1);
        } else {
-               /*
-                * The existing finobt record was modified and has a combination
-                * of allocated and free inodes or is completely free and ikeep
-                * is enabled. Update the record.
-                */
                error = xfs_inobt_update(cur, &rec);
                if (error)
                        goto error;
@@ -1684,7 +1755,7 @@ xfs_imap_lookup(
 
        /* check that the returned record contains the required inode */
        if (rec.ir_startino > agino ||
-           rec.ir_startino + XFS_IALLOC_INODES(mp) <= agino)
+           rec.ir_startino + mp->m_ialloc_inos <= agino)
                return EINVAL;
 
        /* for untrusted inodes check it is allocated first */
@@ -1757,7 +1828,7 @@ xfs_imap(
                return XFS_ERROR(EINVAL);
        }
 
-       blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
+       blks_per_cluster = xfs_icluster_size_fsb(mp);
 
        /*
         * For bulkstat and handle lookups, we have an untrusted inode number
@@ -1778,7 +1849,7 @@ xfs_imap(
         * If the inode cluster size is the same as the blocksize or
         * smaller we get to the buffer by simple arithmetics.
         */
-       if (XFS_INODE_CLUSTER_SIZE(mp) <= mp->m_sb.sb_blocksize) {
+       if (blks_per_cluster == 1) {
                offset = XFS_INO_TO_OFFSET(mp, ino);
                ASSERT(offset < mp->m_sb.sb_inopblock);
 
@@ -1856,7 +1927,16 @@ xfs_ialloc_compute_maxlevels(
 }
 
 /*
- * Log specified fields for the ag hdr (inode section)
+ * Log specified fields for the ag hdr (inode section). The growth of the agi
+ * structure over time requires that we interpret the buffer as two logical
+ * regions delineated by the end of the unlinked list. This is due to the size
+ * of the hash table and its location in the middle of the agi.
+ *
+ * For example, a request to log a field before agi_unlinked and a field after
+ * agi_unlinked could cause us to log the entire hash table and use an excessive
+ * amount of log space. To avoid this behavior, log the region up through
+ * agi_unlinked in one call and the region after agi_unlinked through the end of
+ * the structure in another.
  */
 void
 xfs_ialloc_log_agi(
@@ -1889,23 +1969,13 @@ xfs_ialloc_log_agi(
        agi = XFS_BUF_TO_AGI(bp);
        ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 #endif
-       /*
-        * The growth of the agi buffer over time now requires that we interpret
-        * the buffer as two logical regions delineated at the end of the unlinked
-        * list. This is due to the size of the hash table and its location in the
-        * middle of the agi.
-        *
-        * For example, a request to log a field before agi_unlinked and a field
-        * after agi_unlinked could cause us to log the entire hash table and use
-        * an excessive amount of log space. To avoid this behavior, log the
-        * region up through agi_unlinked in one call and the region after
-        * agi_unlinked through the end of the structure in another.
-        */
+
        xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF);
 
        /*
         * Compute byte offsets for the first and last fields in the first
-        * region and log agi buffer. This only logs up through agi_unlinked.
+        * region and log the agi buffer. This only logs up through
+        * agi_unlinked.
         */
        if (fields & XFS_AGI_ALL_BITS_R1) {
                xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS_R1,
@@ -1914,8 +1984,8 @@ xfs_ialloc_log_agi(
        }
 
        /*
-        * Mask off the bits in the first region and calculate the first and last
-        * field offsets for any bits in the second region.
+        * Mask off the bits in the first region and calculate the first and
+        * last field offsets for any bits in the second region.
         */
        fields &= ~XFS_AGI_ALL_BITS_R1;
        if (fields) {
@@ -2026,15 +2096,15 @@ xfs_read_agi(
 {
        int                     error;
 
-       ASSERT(agno != NULLAGNUMBER);
+       trace_xfs_read_agi(mp, agno);
 
+       ASSERT(agno != NULLAGNUMBER);
        error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
                        XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
                        XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops);
        if (error)
                return error;
 
-       ASSERT(!xfs_buf_geterror(*bpp));
        xfs_buf_set_ref(*bpp, XFS_AGI_REF);
        return 0;
 }
@@ -2050,6 +2120,8 @@ xfs_ialloc_read_agi(
        struct xfs_perag        *pag;   /* per allocation group data */
        int                     error;
 
+       trace_xfs_ialloc_read_agi(mp, agno);
+
        error = xfs_read_agi(mp, tp, agno, bpp);
        if (error)
                return error;
index c3373891d08066b9ad16b3d069a5754a010aacaf..37f5623c139e73b4009c1a34a40e5d5e0648e6fc 100644 (file)
@@ -68,7 +68,6 @@ xfs_inobt_alloc_block(
        struct xfs_btree_cur    *cur,
        union xfs_btree_ptr     *start,
        union xfs_btree_ptr     *new,
-       int                     length,
        int                     *stat)
 {
        xfs_alloc_arg_t         args;           /* block allocation args */
@@ -305,72 +304,6 @@ xfs_inobt_recs_inorder(
 }
 #endif /* DEBUG */
 
-#ifdef XFS_BTREE_TRACE
-ktrace_t       *xfs_inobt_trace_buf;
-
-STATIC void
-xfs_inobt_trace_enter(
-       struct xfs_btree_cur    *cur,
-       const char              *func,
-       char                    *s,
-       int                     type,
-       int                     line,
-       __psunsigned_t          a0,
-       __psunsigned_t          a1,
-       __psunsigned_t          a2,
-       __psunsigned_t          a3,
-       __psunsigned_t          a4,
-       __psunsigned_t          a5,
-       __psunsigned_t          a6,
-       __psunsigned_t          a7,
-       __psunsigned_t          a8,
-       __psunsigned_t          a9,
-       __psunsigned_t          a10)
-{
-       ktrace_enter(xfs_inobt_trace_buf, (void *)(__psint_t)type,
-               (void *)func, (void *)s, NULL, (void *)cur,
-               (void *)a0, (void *)a1, (void *)a2, (void *)a3,
-               (void *)a4, (void *)a5, (void *)a6, (void *)a7,
-               (void *)a8, (void *)a9, (void *)a10);
-}
-
-STATIC void
-xfs_inobt_trace_cursor(
-       struct xfs_btree_cur    *cur,
-       __uint32_t              *s0,
-       __uint64_t              *l0,
-       __uint64_t              *l1)
-{
-       *s0 = cur->bc_private.a.agno;
-       *l0 = cur->bc_rec.i.ir_startino;
-       *l1 = cur->bc_rec.i.ir_free;
-}
-
-STATIC void
-xfs_inobt_trace_key(
-       struct xfs_btree_cur    *cur,
-       union xfs_btree_key     *key,
-       __uint64_t              *l0,
-       __uint64_t              *l1)
-{
-       *l0 = be32_to_cpu(key->inobt.ir_startino);
-       *l1 = 0;
-}
-
-STATIC void
-xfs_inobt_trace_record(
-       struct xfs_btree_cur    *cur,
-       union xfs_btree_rec     *rec,
-       __uint64_t              *l0,
-       __uint64_t              *l1,
-       __uint64_t              *l2)
-{
-       *l0 = be32_to_cpu(rec->inobt.ir_startino);
-       *l1 = be32_to_cpu(rec->inobt.ir_freecount);
-       *l2 = be64_to_cpu(rec->inobt.ir_free);
-}
-#endif /* XFS_BTREE_TRACE */
-
 static const struct xfs_btree_ops xfs_inobt_ops = {
        .rec_len                = sizeof(xfs_inobt_rec_t),
        .key_len                = sizeof(xfs_inobt_key_t),
@@ -391,13 +324,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = {
        .keys_inorder           = xfs_inobt_keys_inorder,
        .recs_inorder           = xfs_inobt_recs_inorder,
 #endif
-
-#ifdef XFS_BTREE_TRACE
-       .trace_enter            = xfs_inobt_trace_enter,
-       .trace_cursor           = xfs_inobt_trace_cursor,
-       .trace_key              = xfs_inobt_trace_key,
-       .trace_record           = xfs_inobt_trace_record,
-#endif
 };
 
 static const struct xfs_btree_ops xfs_finobt_ops = {
index de16ed91666fa5b502372df35481866b816f5788..592ed3ee621709055d4aee37c96e91057ea1cabf 100644 (file)
@@ -55,7 +55,7 @@ xfs_inobp_check(
  * If the readahead buffer is invalid, we don't want to mark it with an error,
  * but we do want to clear the DONE status of the buffer so that a followup read
  * will re-read it from disk. This will ensure that we don't get an unnecessary
- * warnings during log recovery and we don't get unnecessary panics on debug
+ * warnings during log recovery and we don't get unnecssary panics on debug
  * kernels.
  */
 static void
@@ -318,6 +318,15 @@ xfs_dinode_calc_crc(
 
 /*
  * Read the disk inode attributes into the in-core inode structure.
+ *
+ * For version 5 superblocks, if we are initialising a new inode and we are not
+ * utilising the XFS_MOUNT_IKEEP inode cluster mode, we can simple build the new
+ * inode core with a random generation number. If we are keeping inodes around,
+ * we need to read the inode cluster to get the existing generation number off
+ * disk. Further, if we are using version 4 superblocks (i.e. v1/v2 inode
+ * format) then log recovery is dependent on the di_flushiter field being
+ * initialised from the current on-disk value and hence we must also read the
+ * inode off disk.
  */
 int
 xfs_iread(
@@ -337,6 +346,23 @@ xfs_iread(
        if (error)
                return error;
 
+       /* shortcut IO on inode allocation if possible */
+       if ((iget_flags & XFS_IGET_CREATE) &&
+           xfs_sb_version_hascrc(&mp->m_sb) &&
+           !(mp->m_flags & XFS_MOUNT_IKEEP)) {
+               /* initialise the on-disk inode core */
+               memset(&ip->i_d, 0, sizeof(ip->i_d));
+               ip->i_d.di_magic = XFS_DINODE_MAGIC;
+               ip->i_d.di_gen = prandom_u32();
+               if (xfs_sb_version_hascrc(&mp->m_sb)) {
+                       ip->i_d.di_version = 3;
+                       ip->i_d.di_ino = ip->i_ino;
+                       uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid);
+               } else
+                       ip->i_d.di_version = 2;
+               return 0;
+       }
+
        /*
         * Get pointers to the on-disk inode and the buffer containing it.
         */
@@ -397,17 +423,16 @@ xfs_iread(
        }
 
        /*
-        * The inode format changed when we moved the link count and
-        * made it 32 bits long.  If this is an old format inode,
-        * convert it in memory to look like a new one.  If it gets
-        * flushed to disk we will convert back before flushing or
-        * logging it.  We zero out the new projid field and the old link
-        * count field.  We'll handle clearing the pad field (the remains
-        * of the old uuid field) when we actually convert the inode to
-        * the new format. We don't change the version number so that we
-        * can distinguish this from a real new format inode.
+        * Automatically convert version 1 inode formats in memory to version 2
+        * inode format. If the inode is modified, it will get logged and
+        * rewritten as a version 2 inode. We can do this because we set the
+        * superblock feature bit for v2 inodes unconditionally during mount
+        * and it means the reast of the code can assume the inode version is 2
+        * or higher.
         */
        if (ip->i_d.di_version == 1) {
+               ip->i_d.di_version = 2;
+               memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
                ip->i_d.di_nlink = ip->i_d.di_onlink;
                ip->i_d.di_onlink = 0;
                xfs_set_projid(&ip->i_d, 0);
index dfa86aece13872fe4c5ea2c1d5966aa65e19d896..bc6826a136d746d43735f32cf40924147cfc4978 100644 (file)
@@ -412,6 +412,8 @@ xfs_iread_extents(
        xfs_ifork_t     *ifp;
        xfs_extnum_t    nextents;
 
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
        if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
                XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW,
                                 ip->i_mount);
@@ -702,15 +704,16 @@ xfs_idestroy_fork(
 }
 
 /*
- * xfs_iextents_copy()
+ * Convert in-core extents to on-disk form
  *
- * This is called to copy the REAL extents (as opposed to the delayed
- * allocation extents) from the inode into the given buffer.  It
- * returns the number of bytes copied into the buffer.
+ * For either the data or attr fork in extent format, we need to endian convert
+ * the in-core extent as we place them into the on-disk inode.
  *
- * If there are no delayed allocation extents, then we can just
- * memcpy() the extents into the buffer.  Otherwise, we need to
- * examine each extent in turn and skip those which are delayed.
+ * In the case of the data fork, the in-core and on-disk fork sizes can be
+ * different due to delayed allocation extents. We only copy on-disk extents
+ * here, so callers must always use the physical fork size to determine the
+ * size of the buffer passed to this routine.  We will return the size actually
+ * used.
  */
 int
 xfs_iextents_copy(
@@ -776,8 +779,7 @@ xfs_iflush_fork(
        xfs_inode_t             *ip,
        xfs_dinode_t            *dip,
        xfs_inode_log_item_t    *iip,
-       int                     whichfork,
-       xfs_buf_t               *bp)
+       int                     whichfork)
 {
        char                    *cp;
        xfs_ifork_t             *ifp;
@@ -1002,15 +1004,14 @@ xfs_iext_add(
                 * the next index needed in the indirection array.
                 */
                else {
-                       int     count = ext_diff;
+                       uint    count = ext_diff;
 
                        while (count) {
                                erp = xfs_iext_irec_new(ifp, erp_idx);
-                               erp->er_extcount = count;
-                               count -= MIN(count, (int)XFS_LINEAR_EXTS);
-                               if (count) {
+                               erp->er_extcount = min(count, XFS_LINEAR_EXTS);
+                               count -= erp->er_extcount;
+                               if (count)
                                        erp_idx++;
-                               }
                        }
                }
        }
index f52beed4968d6f4b5f8a08fdff80a5d77dafbbcf..8818c634dbf3211211c13de32a76b4b84deb09a9 100644 (file)
@@ -28,7 +28,7 @@ xfs_log_calc_max_attrsetm_res(
        int                     size;
        int                     nblks;
 
-       size = xfs_attr_leaf_entsize_local_max(mp->m_sb.sb_blocksize) -
+       size = xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize) -
               MAXNAMELEN - 1;
        nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
        nblks += XFS_B_TO_FSB(mp, size);
index cd2b51a7a0b24d63d46d7a76f8503b9541e5ec05..11bd98fcc1f024dc786eea1ec4d5bd633c498183 100644 (file)
@@ -51,7 +51,6 @@ xfs_rtbuf_get(
                                   mp->m_bsize, 0, &bp, NULL);
        if (error)
                return error;
-       ASSERT(!xfs_buf_geterror(bp));
        *bpp = bp;
        return 0;
 }
@@ -488,7 +487,7 @@ xfs_rtmodify_range(
        xfs_rtword_t    *first;         /* first used word in the buffer */
        int             i;              /* current bit number rel. to start */
        int             lastbit;        /* last useful bit in word */
-       xfs_rtword_t    mask;           /* mask orelevant bits for value */
+       xfs_rtword_t    mask;           /* mask o frelevant bits for value */
        int             word;           /* word number in the buffer */
 
        /*
index ea893674e40e868e18e07a3ecb2a18474f675f56..27fa7dd9581b7977a2d1223720ddcfc19d6aafbe 100644 (file)
@@ -184,24 +184,29 @@ xfs_mount_validate_sb(
                                        XFS_SB_FEAT_COMPAT_UNKNOWN)) {
                        xfs_warn(mp,
 "Superblock has unknown compatible features (0x%x) enabled.\n"
-"Using a more recent xfsprogs is recommended.",
+"Using a more recent kernel is recommended.",
                                (sbp->sb_features_compat &
                                                XFS_SB_FEAT_COMPAT_UNKNOWN));
                }
 
                if (xfs_sb_has_ro_compat_feature(sbp,
                                        XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
-                       xfs_warn(mp,
-"Superblock has unknown read-only compatible features (0x%x) enabled.\n"
-"Using a more recent xfsprogs is recommended.",
+                       xfs_alert(mp,
+"Superblock has unknown read-only compatible features (0x%x) enabled.",
                                (sbp->sb_features_ro_compat &
                                                XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
+                       if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+                               xfs_warn(mp,
+"Attempted to mount read-only compatible filesystem read-write.\n"
+"Filesystem can only be safely mounted read only.");
+                               return XFS_ERROR(EINVAL);
+                       }
                }
                if (xfs_sb_has_incompat_feature(sbp,
                                        XFS_SB_FEAT_INCOMPAT_UNKNOWN)) {
                        xfs_warn(mp,
 "Superblock has unknown incompatible features (0x%x) enabled.\n"
-"Filesystem can not be safely operated on by this xfsprogs installation",
+"Filesystem can not be safely mounted by this kernel.",
                                (sbp->sb_features_incompat &
                                                XFS_SB_FEAT_INCOMPAT_UNKNOWN));
                        return XFS_ERROR(EINVAL);
@@ -265,7 +270,8 @@ xfs_mount_validate_sb(
            (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)    ||
            sbp->sb_dblocks == 0                                        ||
            sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)                      ||
-           sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
+           sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp)                      ||
+           sbp->sb_shared_vn != 0)) {
                xfs_notice(mp, "SB sanity check failed");
                return XFS_ERROR(EFSCORRUPTED);
        }
@@ -292,14 +298,6 @@ xfs_mount_validate_sb(
                return XFS_ERROR(EFBIG);
        }
 
-       /*
-        * Version 1 directory format has never worked on Linux.
-        */
-       if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
-               xfs_warn(mp, "file system using version 1 directory format");
-               return XFS_ERROR(ENOSYS);
-       }
-
        return 0;
 }
 
@@ -408,8 +406,6 @@ xfs_sb_from_disk(
        to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat);
        to->sb_features_log_incompat =
                                be32_to_cpu(from->sb_features_log_incompat);
-       /* crc is only used on disk, not in memory; just init to 0 here. */
-       to->sb_crc = 0;
        to->sb_pad = 0;
        to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
        to->sb_lsn = be64_to_cpu(from->sb_lsn);
@@ -451,10 +447,16 @@ xfs_sb_quota_to_disk(
        }
 
        /*
-        * GQUOTINO and PQUOTINO cannot be used together in versions
-        * of superblock that do not have pquotino. from->sb_flags
-        * tells us which quota is active and should be copied to
-        * disk.
+        * GQUOTINO and PQUOTINO cannot be used together in versions of
+        * superblock that do not have pquotino. from->sb_flags tells us which
+        * quota is active and should be copied to disk. If neither are active,
+        * make sure we write NULLFSINO to the sb_gquotino field as a quota
+        * inode value of "0" is invalid when the XFS_SB_VERSION_QUOTA feature
+        * bit is set.
+        *
+        * Note that we don't need to handle the sb_uquotino or sb_pquotino here
+        * as they do not require any translation. Hence the main sb field loop
+        * will write them appropriately from the in-core superblock.
         */
        if ((*fields & XFS_SB_GQUOTINO) &&
                                (from->sb_qflags & XFS_GQUOTA_ACCT))
@@ -462,6 +464,17 @@ xfs_sb_quota_to_disk(
        else if ((*fields & XFS_SB_PQUOTINO) &&
                                (from->sb_qflags & XFS_PQUOTA_ACCT))
                to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
+       else {
+               /*
+                * We can't rely on just the fields being logged to tell us
+                * that it is safe to write NULLFSINO - we should only do that
+                * if quotas are not actually enabled. Hence only write
+                * NULLFSINO if both in-core quota inodes are NULL.
+                */
+               if (from->sb_gquotino == NULLFSINO &&
+                   from->sb_pquotino == NULLFSINO)
+                       to->sb_gquotino = cpu_to_be64(NULLFSINO);
+       }
 
        *fields &= ~(XFS_SB_PQUOTINO | XFS_SB_GQUOTINO);
 }
@@ -487,9 +500,6 @@ xfs_sb_to_disk(
        if (!fields)
                return;
 
-       /* We should never write the crc here, it's updated in the IO path */
-       fields &= ~XFS_SB_CRC;
-
        xfs_sb_quota_to_disk(to, from, &fields);
        while (fields) {
                f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
index ebf60acfc0a9340c17a35aeba6d0e0f739b0c726..9503b979d9b6c1b78943d7ae5da6df904fe2070f 100644 (file)
@@ -63,7 +63,6 @@ xfs_symlink_hdr_set(
  */
 bool
 xfs_symlink_hdr_ok(
-       struct xfs_mount        *mp,
        xfs_ino_t               ino,
        uint32_t                offset,
        uint32_t                size,
index 870d4fcef6bf64be75bbdfb3cce21fba9d87808a..b8576a160122b5c4686f1264106131f73fc9d490 100644 (file)
@@ -64,39 +64,54 @@ xfs_calc_buf_res(
  * on disk. Hence we need an inode reservation function that calculates all this
  * correctly. So, we log:
  *
- * - log op headers for object
+ * - 4 log op headers for object
+ *     - for the ilf, the inode core and 2 forks
  * - inode log format object
- * - the entire inode contents (core + 2 forks)
- * - two bmap btree block headers
+ * - the inode core
+ * - two inode forks containing bmap btree root blocks.
+ *     - the btree data contained by both forks will fit into the inode size,
+ *       hence when combined with the inode core above, we have a total of the
+ *       actual inode size.
+ *     - the BMBT headers need to be accounted separately, as they are
+ *       additional to the records and pointers that fit inside the inode
+ *       forks.
  */
 STATIC uint
 xfs_calc_inode_res(
        struct xfs_mount        *mp,
        uint                    ninodes)
 {
-       return ninodes * (sizeof(struct xlog_op_header) +
-                         sizeof(struct xfs_inode_log_format) +
-                         mp->m_sb.sb_inodesize +
-                         2 * XFS_BMBT_BLOCK_LEN(mp));
+       return ninodes *
+               (4 * sizeof(struct xlog_op_header) +
+                sizeof(struct xfs_inode_log_format) +
+                mp->m_sb.sb_inodesize +
+                2 * XFS_BMBT_BLOCK_LEN(mp));
 }
 
 /*
  * The free inode btree is a conditional feature and the log reservation
  * requirements differ slightly from that of the traditional inode allocation
- * btree. The finobt tracks records for inode chunks with at least one free inode.
- * Therefore, a record can be removed from the tree for an inode allocation or
- * free and the associated merge reservation is unconditional. This also covers
- * the possibility of a split on record insertion.
+ * btree. The finobt tracks records for inode chunks with at least one free
+ * inode. A record can be removed from the tree for an inode allocation
+ * or free and thus the finobt reservation is unconditional across:
+ *
+ *     - inode allocation
+ *     - inode free
+ *     - inode chunk allocation
+ *
+ * The 'modify' param indicates to include the record modification scenario. The
+ * 'alloc' param indicates to include the reservation for free space btree
+ * modifications on behalf of finobt modifications. This is required only for
+ * transactions that do not already account for free space btree modifications.
  *
  * the free inode btree: max depth * block size
+ * the allocation btrees: 2 trees * (max depth - 1) * block size
  * the free inode btree entry: block size
- *
- * TODO: is the modify res really necessary? covered by the merge/split res?
- * This seems to be the pattern of ifree, but not create_resv_alloc. Why?
  */
 STATIC uint
 xfs_calc_finobt_res(
        struct xfs_mount        *mp,
+       int                     alloc,
        int                     modify)
 {
        uint res;
@@ -105,6 +120,9 @@ xfs_calc_finobt_res(
                return 0;
 
        res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1));
+       if (alloc)
+               res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 
+                                       XFS_FSB_TO_B(mp, 1));
        if (modify)
                res += (uint)XFS_FSB_TO_B(mp, 1);
 
@@ -188,7 +206,7 @@ xfs_calc_itruncate_reservation(
                    xfs_calc_buf_res(5, 0) +
                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
                                     XFS_FSB_TO_B(mp, 1)) +
-                   xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
+                   xfs_calc_buf_res(2 + mp->m_ialloc_blks +
                                     mp->m_in_maxlevels, 0)));
 }
 
@@ -217,6 +235,19 @@ xfs_calc_rename_reservation(
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
+/*
+ * For removing an inode from unlinked list at first, we can modify:
+ *    the agi hash list and counters: sector size
+ *    the on disk inode before ours in the agi hash list: inode cluster size
+ */
+STATIC uint
+xfs_calc_iunlink_remove_reservation(
+       struct xfs_mount        *mp)
+{
+       return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
+              max_t(uint, XFS_FSB_TO_B(mp, 1), mp->m_inode_cluster_size);
+}
+
 /*
  * For creating a link to an inode:
  *    the parent directory inode: inode size
@@ -234,6 +265,7 @@ xfs_calc_link_reservation(
        struct xfs_mount        *mp)
 {
        return XFS_DQUOT_LOGRES(mp) +
+               xfs_calc_iunlink_remove_reservation(mp) +
                MAX((xfs_calc_inode_res(mp, 2) +
                     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
                                      XFS_FSB_TO_B(mp, 1))),
@@ -242,6 +274,18 @@ xfs_calc_link_reservation(
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
+/*
+ * For adding an inode to unlinked list we can modify:
+ *    the agi hash list: sector size
+ *    the unlinked inode: inode size
+ */
+STATIC uint
+xfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
+{
+       return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
+               xfs_calc_inode_res(mp, 1);
+}
+
 /*
  * For removing a directory entry we can modify:
  *    the parent directory inode: inode size
@@ -259,10 +303,11 @@ xfs_calc_remove_reservation(
        struct xfs_mount        *mp)
 {
        return XFS_DQUOT_LOGRES(mp) +
-               MAX((xfs_calc_inode_res(mp, 2) +
+               xfs_calc_iunlink_add_reservation(mp) +
+               MAX((xfs_calc_inode_res(mp, 1) +
                     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
                                      XFS_FSB_TO_B(mp, 1))),
-                   (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
+                   (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
                     xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
                                      XFS_FSB_TO_B(mp, 1))));
 }
@@ -281,7 +326,7 @@ xfs_calc_remove_reservation(
  *    the superblock for the nlink flag: sector size
  *    the directory btree: (max depth + v2) * dir block size
  *    the directory inode's bmap btree: (max depth + v2) * block size
- *    the finobt
+ *    the finobt (record modification and allocation btrees)
  */
 STATIC uint
 xfs_calc_create_resv_modify(
@@ -291,17 +336,16 @@ xfs_calc_create_resv_modify(
                xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
                (uint)XFS_FSB_TO_B(mp, 1) +
                xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_finobt_res(mp, 1);
+               xfs_calc_finobt_res(mp, 1, 1);
 }
 
 /*
  * For create we can allocate some inodes giving:
  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
  *    the superblock for the nlink flag: sector size
- *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
+ *    the inode blocks allocated: mp->m_ialloc_blks * blocksize
  *    the inode btree: max depth * blocksize
  *    the allocation btrees: 2 trees * (max depth - 1) * block size
- *    the finobt
  */
 STATIC uint
 xfs_calc_create_resv_alloc(
@@ -309,11 +353,10 @@ xfs_calc_create_resv_alloc(
 {
        return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
                mp->m_sb.sb_sectsize +
-               xfs_calc_buf_res(XFS_IALLOC_BLOCKS(mp), XFS_FSB_TO_B(mp, 1)) +
+               xfs_calc_buf_res(mp->m_ialloc_blks, XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
-                                XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_finobt_res(mp, 0);
+                                XFS_FSB_TO_B(mp, 1));
 }
 
 STATIC uint
@@ -331,7 +374,7 @@ __xfs_calc_create_reservation(
  *    the superblock for the nlink flag: sector size
  *    the inode btree: max depth * blocksize
  *    the allocation btrees: 2 trees * (max depth - 1) * block size
- *    the finobt
+ *    the finobt (record insertion)
  */
 STATIC uint
 xfs_calc_icreate_resv_alloc(
@@ -342,7 +385,7 @@ xfs_calc_icreate_resv_alloc(
                xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
                                 XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_finobt_res(mp, 0);
+               xfs_calc_finobt_res(mp, 0, 0);
 }
 
 STATIC uint
@@ -363,6 +406,20 @@ xfs_calc_create_reservation(
 
 }
 
+STATIC uint
+xfs_calc_create_tmpfile_reservation(
+       struct xfs_mount        *mp)
+{
+       uint    res = XFS_DQUOT_LOGRES(mp);
+
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               res += xfs_calc_icreate_resv_alloc(mp);
+       else
+               res += xfs_calc_create_resv_alloc(mp);
+
+       return res + xfs_calc_iunlink_add_reservation(mp);
+}
+
 /*
  * Making a new directory is the same as creating a new file.
  */
@@ -396,7 +453,7 @@ xfs_calc_symlink_reservation(
  *    the on disk inode before ours in the agi hash list: inode cluster size
  *    the inode btree: max depth * blocksize
  *    the allocation btrees: 2 trees * (max depth - 1) * block size
- *    the finobt
+ *    the finobt (record insertion, removal or modification)
  */
 STATIC uint
 xfs_calc_ifree_reservation(
@@ -404,16 +461,15 @@ xfs_calc_ifree_reservation(
 {
        return XFS_DQUOT_LOGRES(mp) +
                xfs_calc_inode_res(mp, 1) +
-               xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
+               xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
                xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) +
-               MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
-                   XFS_INODE_CLUSTER_SIZE(mp)) +
+               xfs_calc_iunlink_remove_reservation(mp) +
                xfs_calc_buf_res(1, 0) +
-               xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
+               xfs_calc_buf_res(2 + mp->m_ialloc_blks +
                                 mp->m_in_maxlevels, 0) +
                xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
                                 XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_finobt_res(mp, 1);
+               xfs_calc_finobt_res(mp, 0, 1);
 }
 
 /*
@@ -536,7 +592,7 @@ xfs_calc_addafork_reservation(
        return XFS_DQUOT_LOGRES(mp) +
                xfs_calc_inode_res(mp, 1) +
                xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
-               xfs_calc_buf_res(1, mp->m_dirblksize) +
+               xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
                xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
                                 XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
@@ -667,15 +723,14 @@ xfs_calc_qm_setqlim_reservation(
 
 /*
  * Allocating quota on disk if needed.
- *     the write transaction log space: M_RES(mp)->tr_write.tr_logres
+ *     the write transaction log space for quota file extent allocation
  *     the unit of quota allocation: one system block size
  */
 STATIC uint
 xfs_calc_qm_dqalloc_reservation(
        struct xfs_mount        *mp)
 {
-       ASSERT(M_RES(mp)->tr_write.tr_logres);
-       return M_RES(mp)->tr_write.tr_logres +
+       return xfs_calc_write_reservation(mp) +
                xfs_calc_buf_res(1,
                        XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
 }
@@ -752,6 +807,11 @@ xfs_trans_resv_calc(
        resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
        resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
+       resp->tr_create_tmpfile.tr_logres =
+                       xfs_calc_create_tmpfile_reservation(mp);
+       resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
+       resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+
        resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
        resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
        resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
@@ -807,7 +867,6 @@ xfs_trans_resv_calc(
        /* The following transaction are logged in logical format */
        resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
        resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
-       resp->tr_swrite.tr_logres = xfs_calc_swrite_reservation(mp);
        resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
        resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
        resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
index c9286c67b913b20851e0f49a657cd7014e92253d..c61bd0e07297cd9d0b0ae129179e45059f0dd6e2 100644 (file)
@@ -623,12 +623,12 @@ xlog_print_dir2_sf(
        count = sfp->count;
        sfep = xfs_dir2_sf_firstentry(sfp);
        for (i = 0; i < count; i++) {
-               ino = xfs_dir3_sfe_get_ino(log->l_mp, sfp, sfep);
+               ino = M_DIROPS(log->l_mp)->sf_get_ino(sfp, sfep);
                memmove(namebuf, (sfep->name), sfep->namelen);
                namebuf[sfep->namelen] = '\0';
                printf(_("%s ino 0x%llx namelen %d\n"),
                       namebuf, (unsigned long long)ino, sfep->namelen);
-               sfep = xfs_dir3_sf_nextentry(log->l_mp, sfp, sfep);
+               sfep = M_DIROPS(log->l_mp)->sf_nextentry(sfp, sfep);
        }
 }
 
index feeab9cab4b8c2971dd2d539cb2c1f3793b573e4..66a6c14d443934ed0d651dd0e1a33122db736c5b 100644 (file)
@@ -66,7 +66,8 @@ max_trans_res(
        sbp->sb_versionnum =
                        (crcs_enabled ? XFS_SB_VERSION_5 : XFS_SB_VERSION_4) |
                        (dirversion == 2 ? XFS_SB_VERSION_DIRV2BIT : 0) |
-                       (logversion > 1 ? XFS_SB_VERSION_LOGV2BIT : 0);
+                       (logversion > 1 ? XFS_SB_VERSION_LOGV2BIT : 0) |
+                       XFS_DFL_SB_VERSION_BITS;
 
        libxfs_mount(&mount, sbp, 0,0,0,0);
        maxfsb = xfs_log_calc_minimum_size(&mount);
index 744dcc6c66677b1000ea4f6a25e80fbbcae42d15..b6768769382f728e269375923745685d84212c5e 100644 (file)
@@ -39,7 +39,7 @@ static long filesize(int fd);
  * (basically no fragmentation).
  */
 #define        MKFS_BLOCKRES_INODE     \
-       ((uint)(XFS_IALLOC_BLOCKS(mp) + ((mp)->m_in_maxlevels - 1)))
+       ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1)))
 #define        MKFS_BLOCKRES(rb)       \
        ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
        (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
index e2a052d40a781040021fdded6ad61c09d997c5d1..845c980884557362127509a7a6fbe579d45683db 100644 (file)
@@ -202,7 +202,7 @@ char        *mopts[] = {
  * (basically no fragmentation).
  */
 #define        MKFS_BLOCKRES_INODE     \
-       ((uint)(XFS_IALLOC_BLOCKS(mp) + (XFS_IN_MAXLEVELS(mp) - 1)))
+       ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1)))
 #define        MKFS_BLOCKRES(rb)       \
        ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
        (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
index 5ce7bb63f750d67ba8bec5ae65bb72d3a2fa1c7a..7eb3bccc7622976d79e98b9cd01e512a2c589312 100644 (file)
@@ -184,8 +184,8 @@ traverse_int_dablock(xfs_mount_t    *mp,
                }
 
                node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp);
-               btree = xfs_da3_node_tree_p(node);
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
+               btree = M_DIROPS(mp)->node_tree_p(node);
+               M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
 
                if (nodehdr.magic != XFS_DA_NODE_MAGIC &&
                    nodehdr.magic != XFS_DA3_NODE_MAGIC)  {
@@ -196,12 +196,12 @@ traverse_int_dablock(xfs_mount_t  *mp,
                        goto error_out;
                }
 
-               if (nodehdr.count > mp->m_dir_node_ents)  {
+               if (nodehdr.count > mp->m_attr_geo->node_ents)  {
                        do_warn(_("bad record count in inode %" PRIu64 ", "
                                  "count = %d, max = %d\n"),
                                da_cursor->ino,
                                nodehdr.count,
-                               mp->m_dir_node_ents);
+                               mp->m_attr_geo->node_ents);
                        libxfs_putbuf(bp);
                        goto error_out;
                }
@@ -336,8 +336,8 @@ verify_final_da_path(xfs_mount_t    *mp,
         */
        entry = cursor->level[this_level].index;
        node = (xfs_da_intnode_t *)XFS_BUF_PTR(cursor->level[this_level].bp);
-       btree = xfs_da3_node_tree_p(node);
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       btree = M_DIROPS(mp)->node_tree_p(node);
+       M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
 
        /*
         * check internal block consistency on this level -- ensure
@@ -508,8 +508,8 @@ verify_da_path(xfs_mount_t  *mp,
         */
        entry = cursor->level[this_level].index;
        node = (xfs_da_intnode_t *)XFS_BUF_PTR(cursor->level[this_level].bp);
-       btree = xfs_da3_node_tree_p(node);
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       btree = M_DIROPS(mp)->node_tree_p(node);
+       M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
 
        /*
         * if this block is out of entries, validate this
@@ -562,8 +562,9 @@ verify_da_path(xfs_mount_t  *mp,
                }
 
                newnode = (xfs_da_intnode_t *)XFS_BUF_PTR(bp);
-               btree = xfs_da3_node_tree_p(node);
-               xfs_da3_node_hdr_from_disk(&nodehdr, newnode);
+               btree = M_DIROPS(mp)->node_tree_p(node);
+               M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, newnode);
+
                /*
                 * verify magic number and back pointer, sanity-check
                 * entry count, verify level
@@ -583,7 +584,7 @@ verify_da_path(xfs_mount_t  *mp,
                                dabno, fsbno, cursor->ino);
                        bad++;
                }
-               if (nodehdr.count > mp->m_dir_node_ents) {
+               if (nodehdr.count > mp->m_attr_geo->node_ents) {
                        do_warn(
        _("entry count %d too large in block %u (%" PRIu64 ") for directory inode %" PRIu64 "\n"),
                                nodehdr.count,
@@ -1186,7 +1187,7 @@ process_leaf_attr_block(
 
        /* does the count look sorta valid? */
        if (leafhdr.count * sizeof(xfs_attr_leaf_entry_t) + stop >
-                                                       XFS_LBSIZE(mp)) {
+                                               mp->m_sb.sb_blocksize) {
                do_warn(
        _("bad attribute count %d in attr block %u, inode %" PRIu64 "\n"),
                        leafhdr.count, da_bno, ino);
@@ -1201,7 +1202,7 @@ process_leaf_attr_block(
                        i < leafhdr.count; i++, entry++) {
 
                /* check if index is within some boundary. */
-               if (be16_to_cpu(entry->nameidx) > XFS_LBSIZE(mp)) {
+               if (be16_to_cpu(entry->nameidx) > mp->m_sb.sb_blocksize) {
                        do_warn(
        _("bad attribute nameidx %d in attr block %u, inode %" PRIu64 "\n"),
                                be16_to_cpu(entry->nameidx), da_bno, ino);
index afb26e09fdd4af12ab5c17db33247651a9ffc172..9a5e9a65d91d8cf361cfb60c4cccc329740a023a 100644 (file)
@@ -117,7 +117,7 @@ verify_inode_chunk(xfs_mount_t              *mp,
        agbno = XFS_INO_TO_AGBNO(mp, ino);
        *start_ino = NULLFSINO;
 
-       ASSERT(XFS_IALLOC_BLOCKS(mp) > 0);
+       ASSERT(mp->m_ialloc_blks > 0);
 
        if (agno == mp->m_sb.sb_agcount - 1)
                max_agbno = mp->m_sb.sb_dblocks -
@@ -135,7 +135,7 @@ verify_inode_chunk(xfs_mount_t              *mp,
         * check for the easy case, inodes per block >= XFS_INODES_PER_CHUNK
         * (multiple chunks per block)
         */
-       if (XFS_IALLOC_BLOCKS(mp) == 1)  {
+       if (mp->m_ialloc_blks == 1)  {
                if (agbno > max_agbno)
                        return 0;
                if (check_aginode_block(mp, agno, agino) == 0)
@@ -208,7 +208,7 @@ verify_inode_chunk(xfs_mount_t              *mp,
                 */
                start_agbno = rounddown(XFS_INO_TO_AGBNO(mp, ino),
                                        fs_ino_alignment);
-               end_agbno = start_agbno + XFS_IALLOC_BLOCKS(mp);
+               end_agbno = start_agbno + mp->m_ialloc_blks;
 
                /*
                 * if this fs has aligned inodes but the end of the
@@ -266,14 +266,14 @@ verify_inode_chunk(xfs_mount_t            *mp,
         * a discovered inode chunk completely within that range
         * would include the inode passed into us.
         */
-       if (XFS_IALLOC_BLOCKS(mp) > 1)  {
-               if (agino > XFS_IALLOC_INODES(mp))
-                       start_agbno = agbno - XFS_IALLOC_BLOCKS(mp) + 1;
+       if (mp->m_ialloc_blks > 1)  {
+               if (agino > mp->m_ialloc_inos)
+                       start_agbno = agbno - mp->m_ialloc_blks + 1;
                else
                        start_agbno = 1;
        }
 
-       end_agbno = agbno + XFS_IALLOC_BLOCKS(mp);
+       end_agbno = agbno + mp->m_ialloc_blks;
 
        if (end_agbno > max_agbno)
                end_agbno = max_agbno;
@@ -328,7 +328,7 @@ verify_inode_chunk(xfs_mount_t              *mp,
 
                        start_agbno = XFS_AGINO_TO_AGBNO(mp,
                                                irec_p->ino_startnum) +
-                                               XFS_IALLOC_BLOCKS(mp);
+                                               mp->m_ialloc_blks;
 
                        /*
                         * we know that the inode we're trying to verify isn't
@@ -336,7 +336,7 @@ verify_inode_chunk(xfs_mount_t              *mp,
                         * of the gap -- is it within the search range?
                         */
                        if (irec_next_p != NULL &&
-                                       agino + XFS_IALLOC_INODES(mp) >=
+                                       agino + mp->m_ialloc_inos >=
                                                irec_next_p->ino_startnum)
                                end_agbno = XFS_AGINO_TO_AGBNO(mp,
                                                irec_next_p->ino_startnum);
@@ -351,7 +351,7 @@ verify_inode_chunk(xfs_mount_t              *mp,
         * the inode in question and that the space between them
         * is too small for a legal inode chunk
         */
-       if (end_agbno - start_agbno < XFS_IALLOC_BLOCKS(mp))
+       if (end_agbno - start_agbno < mp->m_ialloc_blks)
                return(0);
 
        /*
@@ -395,8 +395,8 @@ verify_inode_chunk(xfs_mount_t              *mp,
 
        num_blks = chunk_stop_agbno - chunk_start_agbno;
 
-       if (num_blks < XFS_IALLOC_BLOCKS(mp) || ino_cnt == 0)
-               return(0);
+       if (num_blks < mp->m_ialloc_blks || ino_cnt == 0)
+               return 0;
 
        /*
         * XXX - later - if the entire range is selected and they're all
@@ -411,8 +411,8 @@ verify_inode_chunk(xfs_mount_t              *mp,
         * the chunk
         */
 
-       if (num_blks % XFS_IALLOC_BLOCKS(mp) != 0)  {
-               num_blks = rounddown(num_blks, XFS_IALLOC_BLOCKS(mp));
+       if (num_blks % mp->m_ialloc_blks != 0)  {
+               num_blks = rounddown(num_blks, mp->m_ialloc_blks);
                chunk_stop_agbno = chunk_start_agbno + num_blks;
        }
 
@@ -596,9 +596,9 @@ process_inode_chunk(
        ASSERT(XFS_AGINO_TO_OFFSET(mp, first_irec->ino_startnum) == 0);
 
        *bogus = 0;
-       ASSERT(XFS_IALLOC_BLOCKS(mp) > 0);
+       ASSERT(mp->m_ialloc_blks > 0);
 
-       blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
+       blks_per_cluster = mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog;
        if (blks_per_cluster == 0)
                blks_per_cluster = 1;
        cluster_count = XFS_INODES_PER_CHUNK / inodes_per_cluster;
@@ -688,7 +688,7 @@ process_inode_chunk(
                        icnt++;
                        cluster_offset++;
 
-                       if (icnt == XFS_IALLOC_INODES(mp) &&
+                       if (icnt == mp->m_ialloc_inos &&
                                        irec_offset == XFS_INODES_PER_CHUNK)  {
                                /*
                                 * done! - finished up irec and block
@@ -900,7 +900,7 @@ process_inode_chunk(
                icnt++;
                cluster_offset++;
 
-               if (icnt == XFS_IALLOC_INODES(mp) &&
+               if (icnt == mp->m_ialloc_inos &&
                                irec_offset == XFS_INODES_PER_CHUNK)  {
                        /*
                         * done! - finished up irec and block simultaneously
@@ -1002,7 +1002,7 @@ process_aginodes(
                 * the next block before we call the processing routines.
                 */
                num_inos = XFS_INODES_PER_CHUNK;
-               while (num_inos < XFS_IALLOC_INODES(mp) && ino_rec != NULL)  {
+               while (num_inos < mp->m_ialloc_inos && ino_rec != NULL)  {
                        /*
                         * inodes chunks will always be aligned and sized
                         * correctly
@@ -1011,7 +1011,7 @@ process_aginodes(
                                num_inos += XFS_INODES_PER_CHUNK;
                }
 
-               ASSERT(num_inos == XFS_IALLOC_INODES(mp));
+               ASSERT(num_inos == mp->m_ialloc_inos);
 
                if (pf_args) {
                        sem_post(&pf_args->ra_count);
@@ -1043,7 +1043,7 @@ process_aginodes(
                         */
                        num_inos = 0;
                        ino_rec = first_ino_rec;
-                       while (num_inos < XFS_IALLOC_INODES(mp) &&
+                       while (num_inos < mp->m_ialloc_inos &&
                                        ino_rec != NULL)  {
                                prev_ino_rec = ino_rec;
 
@@ -1227,7 +1227,7 @@ process_uncertain_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno)
                         * processing may add more records to the
                         * uncertain inode lists.
                         */
-                       if (process_inode_chunk(mp, agno, XFS_IALLOC_INODES(mp),
+                       if (process_inode_chunk(mp, agno, mp->m_ialloc_inos,
                                                nrec, 1, 0, 0, &bogus))  {
                                /* XXX - i/o error, we've got a problem */
                                abort();
index c9d467b9ae312f44891ae8c30fbac06b63072c29..d6c41d09d09e12481c98c6f279c4260a9ab7be37 100644 (file)
@@ -588,7 +588,7 @@ process_bmbt_reclist_int(
                ftype = ftype_regular;
 
        for (i = 0; i < *numrecs; i++) {
-               libxfs_bmbt_disk_get_all(rp + i, &irec);
+               libxfs_bmbt_disk_get_all((rp +i), &irec);
                if (i == 0)
                        *last_key = *first_key = irec.br_startoff;
                else
@@ -950,7 +950,7 @@ _("bad numrecs 0 in inode %" PRIu64 " bmap btree root block\n"),
        init_bm_cursor(&cursor, level + 1);
 
        pp = XFS_BMDR_PTR_ADDR(dib, 1,
-               xfs_bmdr_maxrecs(mp, XFS_DFORK_SIZE(dip, mp, whichfork), 0));
+               xfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0));
        pkey = XFS_BMDR_KEY_ADDR(dib, 1);
        last_key = NULLDFILOFF;
 
@@ -1192,8 +1192,7 @@ _("bad number of extents (%d) in symlink %" PRIu64 " data fork\n"),
        expected_offset = 0;
 
        for (i = 0; i < numrecs; i++)  {
-               libxfs_bmbt_disk_get_all(rp + i, &irec);
-
+               libxfs_bmbt_disk_get_all((rp +i), &irec);
                if (irec.br_startoff != expected_offset)  {
                        do_warn(
 _("bad extent #%d offset (%" PRIu64 ") in symlink %" PRIu64 " data fork\n"),
@@ -1298,8 +1297,8 @@ _("Bad symlink buffer CRC, block %" PRIu64 ", inode %" PRIu64 ".\n"
 
                src = bp->b_addr;
                if (xfs_sb_version_hascrc(&mp->m_sb)) {
-                       if (!libxfs_symlink_hdr_ok(mp, lino, offset,
-                                               byte_cnt, bp)) {
+                       if (!libxfs_symlink_hdr_ok(lino, offset,
+                                                  byte_cnt, bp)) {
                                do_warn(
 _("bad symlink header ino %" PRIu64 ", file block %d, disk block %" PRIu64 "\n"),
                                        lino, i, fsbno);
index 644c21402e13907da711edea1206f8f91eacf3ed..005156480ea13459cf38be6f3a797b4400b8c101 100644 (file)
@@ -151,7 +151,7 @@ traverse_int_dir2block(xfs_mount_t  *mp,
         * left-most leaf block setting up the btree cursor along
         * the way.
         */
-       bno = mp->m_dirleafblk;
+       bno = mp->m_dir_geo->leafblk;
        i = -1;
        node = NULL;
        da_cursor->active = 0;
@@ -160,8 +160,8 @@ traverse_int_dir2block(xfs_mount_t  *mp,
                /*
                 * read in each block along the way and set up cursor
                 */
-               nex = blkmap_getn(da_cursor->blkmap, bno, mp->m_dirblkfsbs,
-                               &bmp, &lbmp);
+               nex = blkmap_getn(da_cursor->blkmap, bno,
+                               mp->m_dir_geo->fsbcount, &bmp, &lbmp);
 
                if (nex == 0)
                        goto error_out;
@@ -177,7 +177,7 @@ _("can't read block %u for directory inode %" PRIu64 "\n"),
                }
 
                node = bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
+               M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
 
                if (nodehdr.magic == XFS_DIR2_LEAFN_MAGIC ||
                    nodehdr.magic == XFS_DIR3_LEAFN_MAGIC)  {
@@ -205,14 +205,14 @@ _("corrupt tree block %u for directory inode %" PRIu64 "\n"),
                                bno, da_cursor->ino);
                        goto error_out;
                }
-               btree = xfs_da3_node_tree_p(node);
-               if (nodehdr.count > mp->m_dir_node_ents)  {
+               btree = M_DIROPS(mp)->node_tree_p(node);
+               if (nodehdr.count > mp->m_dir_geo->node_ents)  {
                        libxfs_putbuf(bp);
                        do_warn(
 _("bad record count in inode %" PRIu64 ", count = %d, max = %d\n"),
                                da_cursor->ino,
                                nodehdr.count,
-                               mp->m_dir_node_ents);
+                               mp->m_dir_geo->node_ents);
                        goto error_out;
                }
                /*
@@ -340,8 +340,9 @@ verify_final_dir2_path(xfs_mount_t  *mp,
         */
        entry = cursor->level[this_level].index;
        node = (xfs_da_intnode_t *)(cursor->level[this_level].bp->b_addr);
-       btree = xfs_da3_node_tree_p(node);
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       btree = M_DIROPS(mp)->node_tree_p(node);
+       M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
+
        /*
         * check internal block consistency on this level -- ensure
         * that all entries are used, encountered and expected hashvals
@@ -495,8 +496,8 @@ verify_dir2_path(xfs_mount_t        *mp,
         */
        entry = cursor->level[this_level].index;
        node = cursor->level[this_level].bp->b_addr;
-       btree = xfs_da3_node_tree_p(node);
-       xfs_da3_node_hdr_from_disk(&nodehdr, node);
+       btree = M_DIROPS(mp)->node_tree_p(node);
+       M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, node);
 
        /*
         * if this block is out of entries, validate this
@@ -530,7 +531,7 @@ verify_dir2_path(xfs_mount_t        *mp,
                 */
                dabno = nodehdr.forw;
                ASSERT(dabno != 0);
-               nex = blkmap_getn(cursor->blkmap, dabno, mp->m_dirblkfsbs,
+               nex = blkmap_getn(cursor->blkmap, dabno, mp->m_dir_geo->fsbcount,
                        &bmp, &lbmp);
                if (nex == 0) {
                        do_warn(
@@ -551,8 +552,8 @@ _("can't read block %u for directory inode %" PRIu64 "\n"),
                }
 
                newnode = bp->b_addr;
-               btree = xfs_da3_node_tree_p(newnode);
-               xfs_da3_node_hdr_from_disk(&nodehdr, newnode);
+               btree = M_DIROPS(mp)->node_tree_p(newnode);
+               M_DIROPS(mp)->node_hdr_from_disk(&nodehdr, newnode);
                /*
                 * verify magic number and back pointer, sanity-check
                 * entry count, verify level
@@ -572,7 +573,7 @@ _("bad back pointer in block %u for directory inode %" PRIu64 "\n"),
                                dabno, cursor->ino);
                        bad++;
                }
-               if (nodehdr.count > mp->m_dir_node_ents)  {
+               if (nodehdr.count > mp->m_dir_geo->node_ents)  {
                        do_warn(
 _("entry count %d too large in block %u for directory inode %" PRIu64 "\n"),
                                nodehdr.count,
@@ -677,8 +678,8 @@ process_sf_dir2_fixi8(
        memmove(oldsfp, newsfp, oldsize);
        newsfp->count = oldsfp->count;
        newsfp->i8count = 0;
-       ino = xfs_dir2_sf_get_parent_ino(sfp);
-       xfs_dir2_sf_put_parent_ino(newsfp, ino);
+       ino = M_DIROPS(mp)->sf_get_parent_ino(sfp);
+       M_DIROPS(mp)->sf_put_parent_ino(newsfp, ino);
        oldsfep = xfs_dir2_sf_firstentry(oldsfp);
        newsfep = xfs_dir2_sf_firstentry(newsfp);
        while ((int)((char *)oldsfep - (char *)oldsfp) < oldsize) {
@@ -686,10 +687,10 @@ process_sf_dir2_fixi8(
                xfs_dir2_sf_put_offset(newsfep,
                        xfs_dir2_sf_get_offset(oldsfep));
                memmove(newsfep->name, oldsfep->name, newsfep->namelen);
-               ino = xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep);
-               xfs_dir3_sfe_put_ino(mp, newsfp, newsfep, ino);
-               oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep);
-               newsfep = xfs_dir3_sf_nextentry(mp, newsfp, newsfep);
+               ino = M_DIROPS(mp)->sf_get_ino(oldsfp, oldsfep);
+               M_DIROPS(mp)->sf_put_ino(newsfp, newsfep, ino);
+               oldsfep = M_DIROPS(mp)->sf_nextentry(oldsfp, oldsfep);
+               newsfep = M_DIROPS(mp)->sf_nextentry(newsfp, newsfep);
        }
        *next_sfep = newsfep;
        free(oldsfp);
@@ -710,12 +711,12 @@ process_sf_dir2_fixoff(
 
        sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
        sfep = xfs_dir2_sf_firstentry(sfp);
-       offset = xfs_dir3_data_first_offset(mp);
+       offset = M_DIROPS(mp)->data_first_offset;
 
        for (i = 0; i < sfp->count; i++) {
                xfs_dir2_sf_put_offset(sfep, offset);
-               offset += xfs_dir3_data_entsize(mp, sfep->namelen);
-               sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
+               offset += M_DIROPS(mp)->data_entsize(sfep->namelen);
+               sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep);
        }
 }
 
@@ -764,7 +765,7 @@ process_sf_dir2(
        max_size = XFS_DFORK_DSIZE(dip, mp);
        num_entries = sfp->count;
        ino_dir_size = be64_to_cpu(dip->di_size);
-       offset = xfs_dir3_data_first_offset(mp);
+       offset = M_DIROPS(mp)->data_first_offset;
        bad_offset = *repair = 0;
 
        ASSERT(ino_dir_size <= max_size);
@@ -772,12 +773,12 @@ process_sf_dir2(
        /*
         * Initialize i8 based on size of parent inode number.
         */
-       i8 = (xfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM);
+       i8 = (M_DIROPS(mp)->sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM);
 
        /*
         * check for bad entry count
         */
-       if (num_entries * xfs_dir3_sf_entsize(mp, sfp, 1) +
+       if (num_entries * M_DIROPS(mp)->sf_entsize(sfp, 1) +
                    xfs_dir2_sf_hdr_size(0) > max_size || num_entries == 0)
                num_entries = 0xFF;
 
@@ -793,7 +794,7 @@ process_sf_dir2(
                sfep = next_sfep;
                junkit = 0;
                bad_sfnamelen = 0;
-               lino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
+               lino = M_DIROPS(mp)->sf_get_ino(sfp, sfep);
                /*
                 * if entry points to self, junk it since only '.' or '..'
                 * should do that and shortform dirs don't contain either
@@ -874,7 +875,7 @@ _("entry \"%*.*s\" in shortform directory %" PRIu64 " references %s inode %" PRI
                        junkreason = _("is zero length");
                        bad_sfnamelen = 1;
                } else if ((__psint_t) sfep - (__psint_t) sfp +
-                               xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)
+                               M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen)
                                                        > ino_dir_size)  {
                        junkreason = _("extends past end of dir");
                        bad_sfnamelen = 1;
@@ -920,7 +921,7 @@ _("entry contains offset out of order in shortform dir %" PRIu64 "\n"),
                        bad_offset = 1;
                }
                offset = xfs_dir2_sf_get_offset(sfep) +
-                                       xfs_dir3_data_entsize(mp, namelen);
+                                       M_DIROPS(mp)->data_entsize(namelen);
 
                /*
                 * junk the entry by copying up the rest of the
@@ -937,7 +938,7 @@ _("entry contains offset out of order in shortform dir %" PRIu64 "\n"),
                        name[namelen] = '\0';
 
                        if (!no_modify)  {
-                               tmp_elen = xfs_dir3_sf_entsize(mp, sfp,
+                               tmp_elen = M_DIROPS(mp)->sf_entsize(sfp,
                                                                sfep->namelen);
                                be64_add_cpu(&dip->di_size, -tmp_elen);
                                ino_dir_size -= tmp_elen;
@@ -991,8 +992,8 @@ _("would have junked entry \"%s\" in directory inode %" PRIu64 "\n"),
                next_sfep = (tmp_sfep == NULL)
                        ? (xfs_dir2_sf_entry_t *) ((__psint_t) sfep
                                                        + ((!bad_sfnamelen)
-                               ? xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)
-                               : xfs_dir3_sf_entsize(mp, sfp, namelen)))
+                               ? M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen)
+                               : M_DIROPS(mp)->sf_entsize(sfp, namelen)))
                        : tmp_sfep;
        }
 
@@ -1050,7 +1051,7 @@ _("corrected directory %" PRIu64 " size, was %" PRId64 ", now %" PRIdPTR "\n"),
                }
        }
        if (offset + (sfp->count + 2) * sizeof(xfs_dir2_leaf_entry_t) +
-                       sizeof(xfs_dir2_block_tail_t) > mp->m_dirblksize) {
+                       sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) {
                do_warn(_("directory %" PRIu64 " offsets too high\n"), ino);
                bad_offset = 1;
        }
@@ -1072,7 +1073,7 @@ _("corrected entry offsets in directory %" PRIu64 "\n"),
        /*
         * check parent (..) entry
         */
-       *parent = xfs_dir2_sf_get_parent_ino(sfp);
+       *parent = M_DIROPS(mp)->sf_get_parent_ino(sfp);
 
        /*
         * if parent entry is bogus, null it out.  we'll fix it later .
@@ -1086,7 +1087,7 @@ _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
                if (!no_modify)  {
                        do_warn(_("clearing inode number\n"));
 
-                       xfs_dir2_sf_put_parent_ino(sfp, zero);
+                       M_DIROPS(mp)->sf_put_parent_ino(sfp, zero);
                        *dino_dirty = 1;
                        *repair = 1;
                } else  {
@@ -1101,7 +1102,7 @@ _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
 _("corrected root directory %" PRIu64 " .. entry, was %" PRIu64 ", now %" PRIu64 "\n"),
                                ino, *parent, ino);
                        *parent = ino;
-                       xfs_dir2_sf_put_parent_ino(sfp, ino);
+                       M_DIROPS(mp)->sf_put_parent_ino(sfp, ino);
                        *dino_dirty = 1;
                        *repair = 1;
                } else  {
@@ -1121,7 +1122,7 @@ _("bad .. entry in directory inode %" PRIu64 ", points to self, "),
                if (!no_modify)  {
                        do_warn(_("clearing inode number\n"));
 
-                       xfs_dir2_sf_put_parent_ino(sfp, zero);
+                       M_DIROPS(mp)->sf_put_parent_ino(sfp, zero);
                        *dino_dirty = 1;
                        *repair = 1;
                } else  {
@@ -1170,8 +1171,8 @@ process_dir2_data(
        xfs_ino_t               ent_ino;
 
        d = bp->b_addr;
-       bf = xfs_dir3_data_bestfree_p(d);
-       ptr = (char *)xfs_dir3_data_entry_p(d);
+       bf = M_DIROPS(mp)->data_bestfree_p(d);
+       ptr = (char *)M_DIROPS(mp)->data_entry_p(d);
        badbest = lastfree = freeseen = 0;
        if (be16_to_cpu(bf[0].length) == 0) {
                badbest |= be16_to_cpu(bf[0].offset) != 0;
@@ -1203,7 +1204,7 @@ process_dir2_data(
                                                        (char *)dup - (char *)d)
                                break;
                        badbest |= lastfree != 0;
-                       dfp = xfs_dir2_data_freefind(d, dup);
+                       dfp = xfs_dir2_data_freefind(d, bf, dup);
                        if (dfp) {
                                i = dfp - bf;
                                badbest |= (freeseen & (1 << i)) != 0;
@@ -1216,12 +1217,12 @@ process_dir2_data(
                        continue;
                }
                dep = (xfs_dir2_data_entry_t *)ptr;
-               if (ptr + xfs_dir3_data_entsize(mp, dep->namelen) > endptr)
+               if (ptr + M_DIROPS(mp)->data_entsize(dep->namelen) > endptr)
                        break;
-               if (be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) !=
+               if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) !=
                                                (char *)dep - (char *)d)
                        break;
-               ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
                lastfree = 0;
        }
        /*
@@ -1237,7 +1238,7 @@ process_dir2_data(
                        do_warn(_("\twould junk block\n"));
                return 1;
        }
-       ptr = (char *)xfs_dir3_data_entry_p(d);
+       ptr = (char *)M_DIROPS(mp)->data_entry_p(d);
        /*
         * Process the entries now.
         */
@@ -1491,7 +1492,7 @@ _("entry \"%*.*s\" in directory inode %" PRIu64 " points to self: "),
                /*
                 * Advance to the next entry.
                 */
-               ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
        }
        /*
         * Check the bestfree table.
@@ -1502,7 +1503,8 @@ _("bad bestfree table in block %u in directory inode %" PRIu64 ": "),
                        da_bno, ino);
                if (!no_modify) {
                        do_warn(_("repairing table\n"));
-                       libxfs_dir2_data_freescan(mp, d, &i);
+                       libxfs_dir2_data_freescan(mp->m_dir_geo, M_DIROPS(mp),
+                                                 d, &i);
                        *dirty = 1;
                } else {
                        do_warn(_("would repair table\n"));
@@ -1541,11 +1543,12 @@ process_block_dir2(
 
        *repair = *dot = *dotdot = 0;
        *parent = NULLFSINO;
-       nex = blkmap_getn(blkmap, mp->m_dirdatablk, mp->m_dirblkfsbs, &bmp, &lbmp);
+       nex = blkmap_getn(blkmap, mp->m_dir_geo->datablk,
+                               mp->m_dir_geo->fsbcount, &bmp, &lbmp);
        if (nex == 0) {
                do_warn(
 _("block %u for directory inode %" PRIu64 " is missing\n"),
-                       mp->m_dirdatablk, ino);
+                       mp->m_dir_geo->datablk, ino);
                return 1;
        }
        bp = da_read_buf(mp, nex, bmp, &xfs_dir3_block_buf_ops);
@@ -1554,7 +1557,7 @@ _("block %u for directory inode %" PRIu64 " is missing\n"),
        if (bp == NULL) {
                do_warn(
 _("can't read block %u for directory inode %" PRIu64 "\n"),
-                       mp->m_dirdatablk, ino);
+                       mp->m_dir_geo->datablk, ino);
                return 1;
        }
        /*
@@ -1565,12 +1568,12 @@ _("can't read block %u for directory inode %" PRIu64 "\n"),
              be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC))
                do_warn(
 _("bad directory block magic # %#x in block %u for directory inode %" PRIu64 "\n"),
-                       be32_to_cpu(block->magic), mp->m_dirdatablk, ino);
+                       be32_to_cpu(block->magic), mp->m_dir_geo->datablk, ino);
        /*
         * process the data area
         * this also checks & fixes the bestfree
         */
-       btp = xfs_dir2_block_tail_p(mp, block);
+       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Don't let this go past the end of the block.
@@ -1578,7 +1581,7 @@ _("bad directory block magic # %#x in block %u for directory inode %" PRIu64 "\n
        if ((char *)blp > (char *)btp)
                blp = (xfs_dir2_leaf_entry_t *)btp;
        rval = process_dir2_data(mp, ino, dip, ino_discovery, dirname, parent,
-               bp, dot, dotdot, mp->m_dirdatablk, (char *)blp, &dirty);
+               bp, dot, dotdot, mp->m_dir_geo->datablk, (char *)blp, &dirty);
        /* If block looks ok but CRC didn't match, make sure to recompute it. */
        if (!rval && bp->b_error == EFSBADCRC)
                dirty = 1;
@@ -1610,11 +1613,11 @@ process_leaf_block_dir2(
        struct xfs_dir2_leaf_entry *ents;
        struct xfs_dir3_icleaf_hdr leafhdr;
 
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
+       M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = M_DIROPS(mp)->leaf_ents_p(leaf);
 
        for (i = stale = 0; i < leafhdr.count; i++) {
-               if ((char *)&ents[i] >= (char *)leaf + mp->m_dirblksize) {
+               if ((char *)&ents[i] >= (char *)leaf + mp->m_dir_geo->blksize) {
                        do_warn(
 _("bad entry count in block %u of directory inode %" PRIu64 "\n"),
                                da_bno, ino);
@@ -1670,8 +1673,8 @@ process_leaf_level_dir2(
        buf_dirty = 0;
 
        do {
-               nex = blkmap_getn(da_cursor->blkmap, da_bno, mp->m_dirblkfsbs,
-                       &bmp, &lbmp);
+               nex = blkmap_getn(da_cursor->blkmap, da_bno,
+                               mp->m_dir_geo->fsbcount, &bmp, &lbmp);
                /*
                 * Directory code uses 0 as the NULL block pointer since 0
                 * is the root block and no directory block pointer can point
@@ -1696,7 +1699,7 @@ _("can't read file block %u for directory inode %" PRIu64 "\n"),
                        goto error_out;
                }
                leaf = bp->b_addr;
-               xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
+               M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf);
                /*
                 * Check magic number for leaf directory btree block.
                 */
@@ -1863,11 +1866,11 @@ process_leaf_node_dir2(
        *repair = *dot = *dotdot = good = 0;
        *parent = NULLFSINO;
        ndbno = NULLDFILOFF;
-       while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dirleafblk) {
-               nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp, &lbmp);
+       while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dir_geo->leafblk) {
+               nex = blkmap_getn(blkmap, dbno, mp->m_dir_geo->fsbcount, &bmp, &lbmp);
                /* Advance through map to last dfs block in this dir block */
                ndbno = dbno;
-               while (ndbno < dbno + mp->m_dirblkfsbs - 1) {
+               while (ndbno < dbno + mp->m_dir_geo->fsbcount - 1) {
                        ndbno = blkmap_next_off(blkmap, ndbno, &t);
                }
                if (nex == 0) {
@@ -1893,7 +1896,7 @@ _("bad directory block magic # %#x in block %" PRIu64 " for directory inode %" P
                                be32_to_cpu(data->magic), dbno, ino);
                i = process_dir2_data(mp, ino, dip, ino_discovery, dirname,
                        parent, bp, dot, dotdot, (xfs_dablk_t)dbno,
-                       (char *)data + mp->m_dirblksize, &dirty);
+                       (char *)data + mp->m_dir_geo->blksize, &dirty);
                if (i == 0) {
                        good++;
                        /* Maybe just CRC is wrong. Make sure we correct it. */
@@ -1957,18 +1960,18 @@ process_dir2(
                dot = dotdot = 1;
                res = process_sf_dir2(mp, ino, dip, ino_discovery, dino_dirty,
                        dirname, parent, &repair);
-       } else if (last == mp->m_dirblkfsbs &&
+       } else if (last == mp->m_dir_geo->fsbcount &&
                        (dip->di_format == XFS_DINODE_FMT_EXTENTS ||
                        dip->di_format == XFS_DINODE_FMT_BTREE)) {
                res = process_block_dir2(mp, ino, dip, ino_discovery,
                        dino_dirty, dirname, parent, blkmap, &dot, &dotdot,
                        &repair);
-       } else if (last >= mp->m_dirleafblk + mp->m_dirblkfsbs &&
+       } else if (last >= mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount &&
                        (dip->di_format == XFS_DINODE_FMT_EXTENTS ||
                        dip->di_format == XFS_DINODE_FMT_BTREE)) {
                res = process_leaf_node_dir2(mp, ino, dip, ino_discovery,
                        dirname, parent, blkmap, &dot, &dotdot, &repair,
-                       last > mp->m_dirleafblk + mp->m_dirblkfsbs);
+                       last > mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount);
        } else {
                do_warn(_("bad size/format for directory %" PRIu64 "\n"), ino);
                return 1;
index 25e49edaf97f1859e0ad92f9bd5f09429331fe98..945330f243046957279d03e6667cdd9e4dac2d17 100644 (file)
@@ -910,9 +910,12 @@ mk_root_dir(xfs_mount_t *mp)
        ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
        ip->i_df.if_u1.if_extents = NULL;
 
+
+
        /*
         * initialize the directory
         */
+       ip->d_ops = mp->m_dir_inode_ops;
        libxfs_dir_init(tp, ip, ip);
 
        libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
@@ -1328,8 +1331,7 @@ longform_dir2_rebuild(
                res_failed(error);
        libxfs_trans_ijoin(tp, ip, 0);
 
-       if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock,
-                                               XFS_DATA_FORK)))
+       if ((error = libxfs_bmap_last_offset(ip, &lastblock, XFS_DATA_FORK)))
                do_error(_("xfs_bmap_last_offset failed -- error - %d\n"),
                        error);
 
@@ -1438,11 +1440,11 @@ dir2_kill_block(
        args.firstblock = &firstblock;
        args.flist = &flist;
        args.whichfork = XFS_DATA_FORK;
-       if (da_bno >= mp->m_dirleafblk && da_bno < mp->m_dirfreeblk)
+       if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk)
                error = libxfs_da_shrink_inode(&args, da_bno, bp);
        else
                error = libxfs_dir2_shrink_inode(&args,
-                               xfs_dir2_da_to_db(mp, da_bno), bp);
+                               xfs_dir2_da_to_db(mp->m_dir_geo, da_bno), bp);
        if (error)
                do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"),
                        ip->i_ino, da_bno);
@@ -1498,16 +1500,20 @@ longform_dir2_entry_check_data(
        char                    *ptr;
        xfs_trans_t             *tp;
        int                     wantmagic;
+       struct xfs_da_args      da = {
+               .dp = ip,
+       };
+
 
        bp = *bpp;
        d = bp->b_addr;
-       ptr = (char *)xfs_dir3_data_entry_p(d);
+       ptr = (char *)M_DIROPS(mp)->data_entry_p(d);
        nbad = 0;
        needscan = needlog = 0;
        junkit = 0;
        freetab = *freetabp;
        if (isblock) {
-               btp = xfs_dir2_block_tail_p(mp, (struct xfs_dir2_data_hdr *)d);
+               btp = xfs_dir2_block_tail_p(mp->m_dir_geo, d);
                blp = xfs_dir2_block_leaf_p(btp);
                endptr = (char *)blp;
                if (endptr > (char *)btp)
@@ -1517,13 +1523,13 @@ longform_dir2_entry_check_data(
                else
                        wantmagic = XFS_DIR2_BLOCK_MAGIC;
        } else {
-               endptr = (char *)d + mp->m_dirblksize;
+               endptr = (char *)d + mp->m_dir_geo->blksize;
                if (xfs_sb_version_hascrc(&mp->m_sb))
                        wantmagic = XFS_DIR3_DATA_MAGIC;
                else
                        wantmagic = XFS_DIR2_DATA_MAGIC;
        }
-       db = xfs_dir2_da_to_db(mp, da_bno);
+       db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
 
        /* check for data block beyond expected end */
        if (freetab->naents <= db) {
@@ -1561,7 +1567,7 @@ longform_dir2_entry_check_data(
                                break;
 
                        /* check for block with no data entries */
-                       if ((ptr == (char *)xfs_dir3_data_entry_p(d)) &&
+                       if ((ptr == (char *)M_DIROPS(mp)->data_entry_p(d)) &&
                            (ptr + be16_to_cpu(dup->length) >= endptr)) {
                                junkit = 1;
                                *num_illegal += 1;
@@ -1576,12 +1582,12 @@ longform_dir2_entry_check_data(
 
                /* validate data entry size */
                dep = (xfs_dir2_data_entry_t *)ptr;
-               if (ptr + xfs_dir3_data_entsize(mp, dep->namelen) > endptr)
+               if (ptr + M_DIROPS(mp)->data_entsize(dep->namelen) > endptr)
                        break;
-               if (be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) !=
+               if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) !=
                                                (char *)dep - (char *)d)
                        break;
-               ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
        }
 
        /* did we find an empty or corrupt block? */
@@ -1615,6 +1621,7 @@ longform_dir2_entry_check_data(
        error = libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, 0, 0);
        if (error)
                res_failed(error);
+       da.trans = tp;
        libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_bjoin(tp, bp);
        libxfs_trans_bhold(tp, bp);
@@ -1631,7 +1638,7 @@ longform_dir2_entry_check_data(
                        do_warn(_("would fix magic # to %#x\n"), wantmagic);
        }
        lastfree = 0;
-       ptr = (char *)xfs_dir3_data_entry_p(d);
+       ptr = (char *)M_DIROPS(mp)->data_entry_p(d);
        /*
         * look at each entry.  reference inode pointed to by each
         * entry in the incore inode tree.
@@ -1652,12 +1659,13 @@ longform_dir2_entry_check_data(
        _("directory inode %" PRIu64 " block %u has consecutive free entries: "),
                                        ip->i_ino, da_bno);
                                if (!no_modify) {
+
                                        do_warn(_("joining together\n"));
                                        len = be16_to_cpu(dup->length);
-                                       libxfs_dir2_data_use_free(tp, bp, dup,
+                                       libxfs_dir2_data_use_free(&da, bp, dup,
                                                ptr - (char *)d, len, &needlog,
                                                &needscan);
-                                       libxfs_dir2_data_make_free(tp, bp,
+                                       libxfs_dir2_data_make_free(&da, bp,
                                                ptr - (char *)d, len, &needlog,
                                                &needscan);
                                } else
@@ -1667,9 +1675,10 @@ longform_dir2_entry_check_data(
                        lastfree = 1;
                        continue;
                }
-               addr = xfs_dir2_db_off_to_dataptr(mp, db, ptr - (char *)d);
+               addr = xfs_dir2_db_off_to_dataptr(mp->m_dir_geo, db,
+                                                 ptr - (char *)d);
                dep = (xfs_dir2_data_entry_t *)ptr;
-               ptr += xfs_dir3_data_entsize(mp, dep->namelen);
+               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
                inum = be64_to_cpu(dep->inumber);
                lastfree = 0;
                /*
@@ -1680,7 +1689,7 @@ longform_dir2_entry_check_data(
                if (dep->name[0] == '/')  {
                        nbad++;
                        if (!no_modify)
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                               libxfs_dir2_data_log_entry(&da, bp, dep);
                        continue;
                }
 
@@ -1696,7 +1705,7 @@ longform_dir2_entry_check_data(
        _("entry \"%s\" in directory inode %" PRIu64 " points to non-existent inode %" PRIu64 ""),
                                        fname, ip->i_ino, inum)) {
                                dep->name[0] = '/';
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                               libxfs_dir2_data_log_entry(&da, bp, dep);
                        }
                        continue;
                }
@@ -1713,7 +1722,7 @@ longform_dir2_entry_check_data(
        _("entry \"%s\" in directory inode %" PRIu64 " points to free inode %" PRIu64),
                                        fname, ip->i_ino, inum)) {
                                dep->name[0] = '/';
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                               libxfs_dir2_data_log_entry(&da, bp, dep);
                        }
                        continue;
                }
@@ -1731,7 +1740,7 @@ longform_dir2_entry_check_data(
        _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
                                                ORPHANAGE, inum, ip->i_ino)) {
                                        dep->name[0] = '/';
-                                       libxfs_dir2_data_log_entry(tp, bp, dep);
+                                       libxfs_dir2_data_log_entry(&da, bp, dep);
                                }
                                continue;
                        }
@@ -1747,13 +1756,13 @@ longform_dir2_entry_check_data(
                 * check for duplicate names in directory.
                 */
                if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen,
-                               dep->name, xfs_dir3_dirent_get_ftype(mp, dep))) {
+                               dep->name, M_DIROPS(mp)->data_get_ftype(dep))) {
                        nbad++;
                        if (entry_junked(
        _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
                                        fname, inum, ip->i_ino)) {
                                dep->name[0] = '/';
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                               libxfs_dir2_data_log_entry(&da, bp, dep);
                        }
                        if (inum == orphanage_ino)
                                orphanage_ino = 0;
@@ -1784,7 +1793,7 @@ longform_dir2_entry_check_data(
        _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is not in the the first block"), fname,
                                                inum, ip->i_ino)) {
                                        dep->name[0] = '/';
-                                       libxfs_dir2_data_log_entry(tp, bp, dep);
+                                       libxfs_dir2_data_log_entry(&da, bp, dep);
                                }
                        }
                        continue;
@@ -1803,14 +1812,14 @@ longform_dir2_entry_check_data(
                        ASSERT(dep->name[0] == '.' && dep->namelen == 1);
                        add_inode_ref(current_irec, current_ino_offset);
                        if (da_bno != 0 ||
-                           dep != xfs_dir3_data_entry_p(d)) {
+                           dep != M_DIROPS(mp)->data_entry_p(d)) {
                                /* "." should be the first entry */
                                nbad++;
                                if (entry_junked(
        _("entry \"%s\" in dir %" PRIu64 " is not the first entry"),
                                                fname, inum, ip->i_ino)) {
                                        dep->name[0] = '/';
-                                       libxfs_dir2_data_log_entry(tp, bp, dep);
+                                       libxfs_dir2_data_log_entry(&da, bp, dep);
                                }
                        }
                        *need_dot = 0;
@@ -1827,7 +1836,7 @@ longform_dir2_entry_check_data(
                        __uint8_t dir_ftype;
                        __uint8_t ino_ftype;
 
-                       dir_ftype = xfs_dir3_dirent_get_ftype(mp, dep);
+                       dir_ftype = M_DIROPS(mp)->data_get_ftype(dep);
                        ino_ftype = get_inode_ftype(irec, ino_offset);
 
                        if (dir_ftype != ino_ftype) {
@@ -1841,9 +1850,9 @@ longform_dir2_entry_check_data(
        _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
                                                dir_ftype, ino_ftype,
                                                ip->i_ino, inum);
-                                       xfs_dir3_dirent_put_ftype(mp, dep,
+                                       M_DIROPS(mp)->data_put_ftype(dep,
                                                                ino_ftype);
-                                       libxfs_dir2_data_log_entry(tp, bp, dep);
+                                       libxfs_dir2_data_log_entry(&da, bp, dep);
                                        dir_hash_update_ftype(hashtab, addr,
                                                              ino_ftype);
                                }
@@ -1899,7 +1908,7 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 "
                        nbad++;
                        if (!no_modify)  {
                                dep->name[0] = '/';
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                               libxfs_dir2_data_log_entry(&da, bp, dep);
                                if (verbose)
                                        do_warn(
                                        _("\twill clear entry \"%s\"\n"),
@@ -1912,14 +1921,14 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 "
        }
        *num_illegal += nbad;
        if (needscan)
-               libxfs_dir2_data_freescan(mp, d, &needlog);
+               libxfs_dir2_data_freescan(mp->m_dir_geo, M_DIROPS(mp), d, &i);
        if (needlog)
-               libxfs_dir2_data_log_header(tp, bp);
+               libxfs_dir2_data_log_header(&da, bp);
        libxfs_bmap_finish(&tp, &flist, &committed);
        libxfs_trans_commit(tp, 0);
 
        /* record the largest free space in the freetab for later checking */
-       bf = xfs_dir3_data_bestfree_p(d);
+       bf = M_DIROPS(mp)->data_bestfree_p(d);
        freetab->ents[db].v = be16_to_cpu(bf[0].length);
        freetab->ents[db].s = 0;
 }
@@ -2007,7 +2016,7 @@ longform_dir2_check_leaf(
        int                     error;
        int                     fixit = 0;
 
-       da_bno = mp->m_dirleafblk;
+       da_bno = mp->m_dir_geo->leafblk;
        error = dir_read_buf(ip, da_bno, -1, &bp, &xfs_dir3_leaf1_buf_ops,
                             &fixit);
        if (error == EFSBADCRC || error == EFSCORRUPTED || fixit) {
@@ -2023,16 +2032,16 @@ longform_dir2_check_leaf(
        }
 
        leaf = bp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = M_DIROPS(mp)->leaf_ents_p(leaf);
+       ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
        bestsp = xfs_dir2_leaf_bests_p(ltp);
        if (!(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
              leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) ||
                                leafhdr.forw || leafhdr.back ||
                                leafhdr.count < leafhdr.stale ||
                                leafhdr.count >
-                                       xfs_dir3_max_leaf_ents(mp, leaf) ||
+                                       M_DIROPS(mp)->leaf_max_ents(mp->m_dir_geo) ||
                                (char *)&ents[leafhdr.count] > (char *)bestsp) {
                do_warn(
        _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
@@ -2097,10 +2106,10 @@ longform_dir2_check_node(
        int                     error;
        int                     fixit = 0;
 
-       for (da_bno = mp->m_dirleafblk, next_da_bno = 0;
-                       next_da_bno != NULLFILEOFF && da_bno < mp->m_dirfreeblk;
+       for (da_bno = mp->m_dir_geo->leafblk, next_da_bno = 0;
+                       next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->freeblk;
                        da_bno = (xfs_dablk_t)next_da_bno) {
-               next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
+               next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
                if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
                        break;
 
@@ -2120,8 +2129,8 @@ longform_dir2_check_node(
                        return 1;
                }
                leaf = bp->b_addr;
-               xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-               ents = xfs_dir3_leaf_ents_p(leaf);
+               M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf);
+               ents = M_DIROPS(mp)->leaf_ents_p(leaf);
                if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
                      leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
                      leafhdr.magic == XFS_DA_NODE_MAGIC ||
@@ -2155,7 +2164,7 @@ longform_dir2_check_node(
                 * the right ops on the buffer for when we write it back out.
                 */
                bp->b_ops = &xfs_dir3_leafn_buf_ops;
-               if (leafhdr.count > xfs_dir3_max_leaf_ents(mp, leaf) ||
+               if (leafhdr.count > M_DIROPS(mp)->leaf_max_ents(mp->m_dir_geo) ||
                    leafhdr.count < leafhdr.stale) {
                        do_warn(
        _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
@@ -2172,10 +2181,10 @@ longform_dir2_check_node(
        if (dir_hash_check(hashtab, ip, seeval))
                return 1;
 
-       for (da_bno = mp->m_dirfreeblk, next_da_bno = 0;
+       for (da_bno = mp->m_dir_geo->freeblk, next_da_bno = 0;
             next_da_bno != NULLFILEOFF;
             da_bno = (xfs_dablk_t)next_da_bno) {
-               next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
+               next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
                if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
                        break;
 
@@ -2188,15 +2197,15 @@ longform_dir2_check_node(
                        return 1;
                }
                free = bp->b_addr;
-               xfs_dir3_free_hdr_from_disk(&freehdr, free);
-               bests = xfs_dir3_free_bests_p(mp, free);
-               fdb = xfs_dir2_da_to_db(mp, da_bno);
+               M_DIROPS(mp)->free_hdr_from_disk(&freehdr, free);
+               bests = M_DIROPS(mp)->free_bests_p(free);
+               fdb = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
                if (!(freehdr.magic == XFS_DIR2_FREE_MAGIC ||
                      freehdr.magic == XFS_DIR3_FREE_MAGIC) ||
-                               freehdr.firstdb !=
-                                       (fdb - XFS_DIR2_FREE_FIRSTDB(mp)) *
-                                               xfs_dir3_free_max_bests(mp) ||
-                               freehdr.nvalid < freehdr.nused) {
+                   freehdr.firstdb !=
+                       (fdb - xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
+                       M_DIROPS(mp)->free_max_bests(mp->m_dir_geo) ||
+                   freehdr.nvalid < freehdr.nused) {
                        do_warn(
        _("free block %u for directory inode %" PRIu64 " bad header\n"),
                                da_bno, ip->i_ino);
@@ -2271,16 +2280,17 @@ longform_dir2_entry_check(xfs_mount_t   *mp,
        int                     seeval;
        int                     fixit = 0;
        xfs_dir2_db_t           db;
+       struct xfs_da_args      args;
 
        *need_dot = 1;
-       freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
+       freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dir_geo->blksize));
        if (!freetab) {
                do_error(_("malloc failed in %s (%" PRId64 " bytes)\n"),
                        __func__,
-                       FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
+                       FREETAB_SIZE(ip->i_d.di_size / mp->m_dir_geo->blksize));
                exit(1);
        }
-       freetab->naents = ip->i_d.di_size / mp->m_dirblksize;
+       freetab->naents = ip->i_d.di_size / mp->m_dir_geo->blksize;
        freetab->nents = 0;
        for (i = 0; i < freetab->naents; i++) {
                freetab->ents[i].v = NULLDATAOFF;
@@ -2293,18 +2303,20 @@ longform_dir2_entry_check(xfs_mount_t   *mp,
                        __func__, num_bps * sizeof(struct xfs_buf*));
 
        /* is this a block, leaf, or node directory? */
-       libxfs_dir2_isblock(NULL, ip, &isblock);
-       libxfs_dir2_isleaf(NULL, ip, &isleaf);
+       args.dp = ip;
+       args.geo = mp->m_dir_geo;
+       libxfs_dir2_isblock(&args, &isblock);
+       libxfs_dir2_isleaf(&args, &isleaf);
 
        /* check directory "data" blocks (ie. name/inode pairs) */
        for (da_bno = 0, next_da_bno = 0;
-            next_da_bno != NULLFILEOFF && da_bno < mp->m_dirleafblk;
+            next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->leafblk;
             da_bno = (xfs_dablk_t)next_da_bno) {
                const struct xfs_buf_ops *ops;
                int                      error;
                struct xfs_dir2_data_hdr *d;
 
-               next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
+               next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
                if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) {
                        /*
                         * if this is the first block, there isn't anything we
@@ -2317,7 +2329,7 @@ longform_dir2_entry_check(xfs_mount_t     *mp,
                        break;
                }
 
-               db = xfs_dir2_da_to_db(mp, da_bno);
+               db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
                if (db >= num_bps) {
                        /* more data blocks than expected */
                        num_bps = db + 1;
@@ -2379,7 +2391,7 @@ longform_dir2_entry_check(xfs_mount_t     *mp,
                        xfs_dir2_leaf_entry_t   *blp;
 
                        block = bplist[0]->b_addr;
-                       btp = xfs_dir2_block_tail_p(mp, block);
+                       btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
                        blp = xfs_dir2_block_leaf_p(btp);
                        seeval = dir_hash_see_all(hashtab, blp,
                                                be32_to_cpu(btp->count),
@@ -2435,8 +2447,8 @@ shortform_dir2_junk(
        if (lino == orphanage_ino)
                orphanage_ino = 0;
 
-       next_elen = xfs_dir3_sf_entsize(mp, sfp, sfep->namelen);
-       next_sfep = (xfs_dir2_sf_entry_t *)((__psint_t)sfep + next_elen);
+       next_elen = M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen);
+       next_sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep);
 
        /*
         * if we are just checking, simply return the pointer to the next entry
@@ -2519,7 +2531,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                        do_warn(
        _("setting .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
                                ino, parent);
-                       xfs_dir2_sf_put_parent_ino(sfp, parent);
+                       M_DIROPS(mp)->sf_put_parent_ino(sfp, parent);
                        *ino_dirty = 1;
                }
                return;
@@ -2536,7 +2548,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
        /*
         * Initialise i8 counter -- the parent inode number counts as well.
         */
-       i8 = xfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM;
+       i8 = M_DIROPS(mp)->sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM;
 
        /*
         * now run through entries, stop at first bad entry, don't need
@@ -2550,7 +2562,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                        sfep = next_sfep, i++)  {
                bad_sfnamelen = 0;
 
-               lino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
+               lino = M_DIROPS(mp)->sf_get_ino(sfp, sfep);
 
                namelen = sfep->namelen;
 
@@ -2579,7 +2591,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                                break;
                        }
                } else if (no_modify && (__psint_t) sfep - (__psint_t) sfp +
-                               + xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)
+                               + M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen)
                                > ip->i_d.di_size)  {
                        bad_sfnamelen = 1;
 
@@ -2608,8 +2620,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                 */
 
                if (no_modify && verify_inum(mp, lino))  {
-                       next_sfep = (xfs_dir2_sf_entry_t *)((__psint_t)sfep +
-                               xfs_dir3_sf_entsize(mp, sfp, sfep->namelen));
+                       next_sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep);
                        continue;
                }
 
@@ -2671,7 +2682,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
                                (sfep - xfs_dir2_sf_firstentry(sfp)),
                                lino, sfep->namelen, sfep->name,
-                               xfs_dir3_sfe_get_ftype(mp, sfp, sfep))) {
+                               M_DIROPS(mp)->sf_get_ftype(sfep))) {
                        do_warn(
 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
                                fname, lino, ino);
@@ -2736,7 +2747,7 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
                        __uint8_t dir_ftype;
                        __uint8_t ino_ftype;
 
-                       dir_ftype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep);
+                       dir_ftype = M_DIROPS(mp)->sf_get_ftype(sfep);
                        ino_ftype = get_inode_ftype(irec, ino_offset);
 
                        if (dir_ftype != ino_ftype) {
@@ -2750,7 +2761,7 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
        _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
                                                dir_ftype, ino_ftype,
                                                ino, lino);
-                                       xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
+                                       M_DIROPS(mp)->sf_put_ftype(sfep,
                                                                ino_ftype);
                                        dir_hash_update_ftype(hashtab,
                        (xfs_dir2_dataptr_t)(sfep - xfs_dir2_sf_firstentry(sfp)),
@@ -2771,8 +2782,8 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
                ASSERT(no_modify || bad_sfnamelen == 0);
                next_sfep = (struct xfs_dir2_sf_entry *)((__psint_t)sfep +
                              (bad_sfnamelen
-                               ? xfs_dir3_sf_entsize(mp, sfp, namelen)
-                               : xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)));
+                               ? M_DIROPS(mp)->sf_entsize(sfp, namelen)
+                               : M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen)));
        }
 
        if (sfp->i8count != i8) {
index 47bc939168e8c3d21c4353e7d876653bbf4990dc..b61a859231837aef36c36ce75a961066e0b02cd6 100644 (file)
@@ -189,7 +189,7 @@ pf_read_bmbt_reclist(
                        goto out_free;
 
                if (!args->dirs_only && ((irec.br_startoff +
-                               irec.br_blockcount) >= mp->m_dirfreeblk))
+                               irec.br_blockcount) >= mp->m_dir_geo->freeblk))
                        break;  /* only Phase 6 reads the free blocks */
 
                op = irec.br_startoff;
@@ -200,8 +200,8 @@ pf_read_bmbt_reclist(
 
                        pftrace("queuing dir extent in AG %d", args->agno);
 
-                       if (len + irec.br_blockcount >= mp->m_dirblkfsbs)
-                               bm_len = mp->m_dirblkfsbs - len;
+                       if (len + irec.br_blockcount >= mp->m_dir_geo->fsbcount)
+                               bm_len = mp->m_dir_geo->fsbcount - len;
                        else
                                bm_len = irec.br_blockcount;
                        len += bm_len;
@@ -211,7 +211,7 @@ pf_read_bmbt_reclist(
                        map[nmaps].bm_len = XFS_FSB_TO_BB(mp, bm_len);
                        nmaps++;
 
-                       if (len == mp->m_dirblkfsbs) {
+                       if (len == mp->m_dir_geo->fsbcount) {
                                pf_queue_io(args, map, nmaps, B_DIR_META);
                                len = 0;
                                nmaps = 0;
@@ -357,7 +357,7 @@ pf_read_btinode(
                return;
 
        dsize = XFS_DFORK_DSIZE(dino, mp);
-       pp = XFS_BMDR_PTR_ADDR(dib, 1, xfs_bmdr_maxrecs(mp, dsize, 0));
+       pp = XFS_BMDR_PTR_ADDR(dib, 1, xfs_bmdr_maxrecs(dsize, 0));
 
        for (i = 0; i < numrecs; i++) {
                dbno = be64_to_cpu(pp[i]);
@@ -680,7 +680,7 @@ pf_queuing_worker(
        int                     i;
        int                     err;
 
-       blks_per_cluster =  XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
+       blks_per_cluster = mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog;
        if (blks_per_cluster == 0)
                blks_per_cluster = 1;
 
@@ -709,7 +709,7 @@ pf_queuing_worker(
                cur_irec = irec;
 
                num_inos = XFS_INODES_PER_CHUNK;
-               while (num_inos < XFS_IALLOC_INODES(mp) && irec != NULL) {
+               while (num_inos < mp->m_ialloc_inos && irec != NULL) {
                        irec = next_ino_rec(irec);
                        num_inos += XFS_INODES_PER_CHUNK;
                }
@@ -747,7 +747,7 @@ pf_queuing_worker(
                                                                 : B_INODE);
                        bno += blks_per_cluster;
                        num_inos += inodes_per_cluster;
-               } while (num_inos < XFS_IALLOC_INODES(mp));
+               } while (num_inos < mp->m_ialloc_inos);
        }
 
        pthread_mutex_lock(&args->lock);
@@ -842,9 +842,10 @@ start_inode_prefetch(
         */
 
        max_queue = libxfs_bcache->c_maxcount / thread_count / 8;
-       if (XFS_INODE_CLUSTER_SIZE(mp) > mp->m_sb.sb_blocksize)
-               max_queue = max_queue * (XFS_INODE_CLUSTER_SIZE(mp) >>
-                               mp->m_sb.sb_blocklog) / XFS_IALLOC_BLOCKS(mp);
+       if (mp->m_inode_cluster_size > mp->m_sb.sb_blocksize)
+               max_queue = max_queue *
+                       (mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog) /
+                       mp->m_ialloc_blks;
 
        sem_init(&args->ra_count, 0, max_queue);
 
index e8c4984a4b7d662e115c3a60ac83c8f27e4048ec..e176779beb47e142601125e7996ba8927f280f5b 100644 (file)
@@ -121,6 +121,11 @@ parse_sb_version(xfs_sb_t *sb)
                return 1;
        }
 
+       if (sb->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) {
+               do_warn(_("Shared Version bit set. Not supported. Ever.\n"));
+               return 1;
+       }
+
        /*
         * ok, check to make sure that the sb isn't newer
         * than we are
index d721cd0f6d0ccc2f133e49b8fe8760e81d77a73e..5024e8092d2d190a6f08f9f933df79c1fd22371b 100644 (file)
@@ -444,9 +444,9 @@ calc_mkfs(xfs_mount_t *mp)
                first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno, 0);
        }
 
-       ASSERT(XFS_IALLOC_BLOCKS(mp) > 0);
+       ASSERT(mp->m_ialloc_blks > 0);
 
-       if (XFS_IALLOC_BLOCKS(mp) > 1)
+       if (mp->m_ialloc_blks > 1)
                last_prealloc_ino = first_prealloc_ino + XFS_INODES_PER_CHUNK;
        else
                last_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno + 1, 0);
@@ -621,7 +621,7 @@ main(int argc, char **argv)
        chunks_pblock = mp->m_sb.sb_inopblock / XFS_INODES_PER_CHUNK;
        max_symlink_blocks = libxfs_symlink_blocks(mp, MAXPATHLEN);
        inodes_per_cluster = MAX(mp->m_sb.sb_inopblock,
-                       XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
+                       mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog);
 
        /*
         * Automatic striding for high agcount filesystems.