]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/xfs/xfs_dir2.c
Merge remote-tracking branch 'regulator/fix/core' into regulator-linus
[karo-tx-linux.git] / fs / xfs / xfs_dir2.c
index e365c98c0f1ea93c6bcdbd38d916234088cb9743..79670cda48ae4797f902af912d59d105215885bb 100644 (file)
@@ -85,38 +85,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_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
        mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
 
-       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 = mp->m_dir_inode_ops->node_hdr_size;
-       mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_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);
 }
 
 /*
@@ -192,6 +228,7 @@ xfs_dir_init(
        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);
@@ -226,6 +263,7 @@ xfs_dir_createname(
        if (!args)
                return ENOMEM;
 
+       args->geo = dp->i_mount->m_dir_geo;
        args->name = name->name;
        args->namelen = name->len;
        args->filetype = name->type;
@@ -244,7 +282,7 @@ xfs_dir_createname(
                goto out_free;
        }
 
-       rval = xfs_dir2_isblock(dp, &v);
+       rval = xfs_dir2_isblock(args, &v);
        if (rval)
                goto out_free;
        if (v) {
@@ -252,7 +290,7 @@ xfs_dir_createname(
                goto out_free;
        }
 
-       rval = xfs_dir2_isleaf(dp, &v);
+       rval = xfs_dir2_isleaf(args, &v);
        if (rval)
                goto out_free;
        if (v)
@@ -320,6 +358,7 @@ xfs_dir_lookup(
         * 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;
@@ -336,7 +375,7 @@ xfs_dir_lookup(
                goto out_check_rval;
        }
 
-       rval = xfs_dir2_isblock(dp, &v);
+       rval = xfs_dir2_isblock(args, &v);
        if (rval)
                goto out_free;
        if (v) {
@@ -344,7 +383,7 @@ xfs_dir_lookup(
                goto out_check_rval;
        }
 
-       rval = xfs_dir2_isleaf(dp, &v);
+       rval = xfs_dir2_isleaf(args, &v);
        if (rval)
                goto out_free;
        if (v)
@@ -391,6 +430,7 @@ xfs_dir_removename(
        if (!args)
                return ENOMEM;
 
+       args->geo = dp->i_mount->m_dir_geo;
        args->name = name->name;
        args->namelen = name->len;
        args->filetype = name->type;
@@ -408,7 +448,7 @@ xfs_dir_removename(
                goto out_free;
        }
 
-       rval = xfs_dir2_isblock(dp, &v);
+       rval = xfs_dir2_isblock(args, &v);
        if (rval)
                goto out_free;
        if (v) {
@@ -416,7 +456,7 @@ xfs_dir_removename(
                goto out_free;
        }
 
-       rval = xfs_dir2_isleaf(dp, &v);
+       rval = xfs_dir2_isleaf(args, &v);
        if (rval)
                goto out_free;
        if (v)
@@ -455,6 +495,7 @@ xfs_dir_replace(
        if (!args)
                return ENOMEM;
 
+       args->geo = dp->i_mount->m_dir_geo;
        args->name = name->name;
        args->namelen = name->len;
        args->filetype = name->type;
@@ -472,7 +513,7 @@ xfs_dir_replace(
                goto out_free;
        }
 
-       rval = xfs_dir2_isblock(dp, &v);
+       rval = xfs_dir2_isblock(args, &v);
        if (rval)
                goto out_free;
        if (v) {
@@ -480,7 +521,7 @@ xfs_dir_replace(
                goto out_free;
        }
 
-       rval = xfs_dir2_isleaf(dp, &v);
+       rval = xfs_dir2_isleaf(args, &v);
        if (rval)
                goto out_free;
        if (v)
@@ -516,6 +557,7 @@ xfs_dir_canenter(
        if (!args)
                return ENOMEM;
 
+       args->geo = dp->i_mount->m_dir_geo;
        args->name = name->name;
        args->namelen = name->len;
        args->filetype = name->type;
@@ -531,7 +573,7 @@ xfs_dir_canenter(
                goto out_free;
        }
 
-       rval = xfs_dir2_isblock(dp, &v);
+       rval = xfs_dir2_isblock(args, &v);
        if (rval)
                goto out_free;
        if (v) {
@@ -539,7 +581,7 @@ xfs_dir_canenter(
                goto out_free;
        }
 
-       rval = xfs_dir2_isleaf(dp, &v);
+       rval = xfs_dir2_isleaf(args, &v);
        if (rval)
                goto out_free;
        if (v)
@@ -579,13 +621,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.
@@ -607,18 +649,16 @@ xfs_dir2_grow_inode(
  */
 int
 xfs_dir2_isblock(
-       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(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;
 }
@@ -628,17 +668,15 @@ xfs_dir2_isblock(
  */
 int
 xfs_dir2_isleaf(
-       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(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;
 }
 
@@ -666,11 +704,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))) {
                /*
@@ -697,12 +735,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))) {
@@ -711,7 +749,7 @@ xfs_dir2_shrink_inode(
                 */
                return error;
        }
-       if (db == mp->m_dirdatablk)
+       if (db == args->geo->datablk)
                ASSERT(bno == 0);
        else
                ASSERT(bno > 0);