aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2005-11-01 18:34:53 -0500
committerNathan Scott <nathans@sgi.com>2005-11-01 18:34:53 -0500
commitd8cc890d4095f1eaa7f411a85051015b21262b12 (patch)
treee13bec06a94a8dc5552dab733e90ef4f4d41fb8b /fs/xfs/xfs_bmap.c
parentaa82daa06198b27963fe3d6ee8035855b29f6524 (diff)
[XFS] Ondisk format extension for extended attributes (attr2). Basically,
the data/attr forks now grow up/down from either end of the literal area, rather than dividing the literal area into two chunks and growing both upward. Means we can now make much more efficient use of the attribute space, incl. fitting DMF attributes inline in 256 byte inodes, and large jumps in dbench3 performance numbers. It is self enabling, but can be forced on/off via the attr2/noattr2 mount options. SGI-PV: 941645 SGI-Modid: xfs-linux:xfs-kern:23835a Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c84
1 files changed, 66 insertions, 18 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 26645d267f1b..3e013530d00d 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -62,6 +62,7 @@
62#include "xfs_error.h" 62#include "xfs_error.h"
63#include "xfs_da_btree.h" 63#include "xfs_da_btree.h"
64#include "xfs_dir_leaf.h" 64#include "xfs_dir_leaf.h"
65#include "xfs_attr_leaf.h"
65#include "xfs_bit.h" 66#include "xfs_bit.h"
66#include "xfs_rw.h" 67#include "xfs_rw.h"
67#include "xfs_quota.h" 68#include "xfs_quota.h"
@@ -3337,6 +3338,29 @@ xfs_bmap_insert_exlist(
3337} 3338}
3338 3339
3339/* 3340/*
3341 * Helper routine to reset inode di_forkoff field when switching
3342 * attribute fork from local to extent format - we reset it where
3343 * possible to make space available for inline data fork extents.
3344 */
3345STATIC void
3346xfs_bmap_forkoff_reset(
3347 xfs_mount_t *mp,
3348 xfs_inode_t *ip,
3349 int whichfork)
3350{
3351 if (whichfork == XFS_ATTR_FORK &&
3352 (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
3353 (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
3354 ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
3355 ip->i_d.di_forkoff = mp->m_attroffset >> 3;
3356 ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
3357 (uint)sizeof(xfs_bmbt_rec_t);
3358 ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) /
3359 (uint)sizeof(xfs_bmbt_rec_t);
3360 }
3361}
3362
3363/*
3340 * Convert a local file to an extents file. 3364 * Convert a local file to an extents file.
3341 * This code is out of bounds for data forks of regular files, 3365 * This code is out of bounds for data forks of regular files,
3342 * since the file data needs to get logged so things will stay consistent. 3366 * since the file data needs to get logged so things will stay consistent.
@@ -3403,6 +3427,7 @@ xfs_bmap_local_to_extents(
3403 memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data, 3427 memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
3404 ifp->if_bytes); 3428 ifp->if_bytes);
3405 xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); 3429 xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
3430 xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
3406 xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); 3431 xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
3407 xfs_iext_realloc(ip, 1, whichfork); 3432 xfs_iext_realloc(ip, 1, whichfork);
3408 ep = ifp->if_u1.if_extents; 3433 ep = ifp->if_u1.if_extents;
@@ -3413,8 +3438,10 @@ xfs_bmap_local_to_extents(
3413 XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip, 3438 XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
3414 XFS_TRANS_DQ_BCOUNT, 1L); 3439 XFS_TRANS_DQ_BCOUNT, 1L);
3415 flags |= XFS_ILOG_FEXT(whichfork); 3440 flags |= XFS_ILOG_FEXT(whichfork);
3416 } else 3441 } else {
3417 ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); 3442 ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
3443 xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
3444 }
3418 ifp->if_flags &= ~XFS_IFINLINE; 3445 ifp->if_flags &= ~XFS_IFINLINE;
3419 ifp->if_flags |= XFS_IFEXTENTS; 3446 ifp->if_flags |= XFS_IFEXTENTS;
3420 XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); 3447 XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
@@ -3796,22 +3823,24 @@ xfs_bunmap_trace(
3796int /* error code */ 3823int /* error code */
3797xfs_bmap_add_attrfork( 3824xfs_bmap_add_attrfork(
3798 xfs_inode_t *ip, /* incore inode pointer */ 3825 xfs_inode_t *ip, /* incore inode pointer */
3799 int rsvd) /* OK to allocated reserved blocks in trans */ 3826 int size, /* space new attribute needs */
3827 int rsvd) /* xact may use reserved blks */
3800{ 3828{
3801 int blks; /* space reservation */
3802 int committed; /* xaction was committed */
3803 int error; /* error return value */
3804 xfs_fsblock_t firstblock; /* 1st block/ag allocated */ 3829 xfs_fsblock_t firstblock; /* 1st block/ag allocated */
3805 xfs_bmap_free_t flist; /* freed extent list */ 3830 xfs_bmap_free_t flist; /* freed extent list */
3806 int logflags; /* logging flags */
3807 xfs_mount_t *mp; /* mount structure */ 3831 xfs_mount_t *mp; /* mount structure */
3808 unsigned long s; /* spinlock spl value */
3809 xfs_trans_t *tp; /* transaction pointer */ 3832 xfs_trans_t *tp; /* transaction pointer */
3833 unsigned long s; /* spinlock spl value */
3834 int blks; /* space reservation */
3835 int version = 1; /* superblock attr version */
3836 int committed; /* xaction was committed */
3837 int logflags; /* logging flags */
3838 int error; /* error return value */
3810 3839
3840 ASSERT(XFS_IFORK_Q(ip) == 0);
3811 ASSERT(ip->i_df.if_ext_max == 3841 ASSERT(ip->i_df.if_ext_max ==
3812 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t)); 3842 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
3813 if (XFS_IFORK_Q(ip)) 3843
3814 return 0;
3815 mp = ip->i_mount; 3844 mp = ip->i_mount;
3816 ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); 3845 ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
3817 tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK); 3846 tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
@@ -3853,7 +3882,11 @@ xfs_bmap_add_attrfork(
3853 case XFS_DINODE_FMT_LOCAL: 3882 case XFS_DINODE_FMT_LOCAL:
3854 case XFS_DINODE_FMT_EXTENTS: 3883 case XFS_DINODE_FMT_EXTENTS:
3855 case XFS_DINODE_FMT_BTREE: 3884 case XFS_DINODE_FMT_BTREE:
3856 ip->i_d.di_forkoff = mp->m_attroffset >> 3; 3885 ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
3886 if (!ip->i_d.di_forkoff)
3887 ip->i_d.di_forkoff = mp->m_attroffset >> 3;
3888 else if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR))
3889 version = 2;
3857 break; 3890 break;
3858 default: 3891 default:
3859 ASSERT(0); 3892 ASSERT(0);
@@ -3890,12 +3923,21 @@ xfs_bmap_add_attrfork(
3890 xfs_trans_log_inode(tp, ip, logflags); 3923 xfs_trans_log_inode(tp, ip, logflags);
3891 if (error) 3924 if (error)
3892 goto error2; 3925 goto error2;
3893 if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) { 3926 if (!XFS_SB_VERSION_HASATTR(&mp->m_sb) ||
3927 (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2)) {
3928 logflags = 0;
3894 s = XFS_SB_LOCK(mp); 3929 s = XFS_SB_LOCK(mp);
3895 if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) { 3930 if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) {
3896 XFS_SB_VERSION_ADDATTR(&mp->m_sb); 3931 XFS_SB_VERSION_ADDATTR(&mp->m_sb);
3932 logflags |= XFS_SB_VERSIONNUM;
3933 }
3934 if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2) {
3935 XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
3936 logflags |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
3937 }
3938 if (logflags) {
3897 XFS_SB_UNLOCK(mp, s); 3939 XFS_SB_UNLOCK(mp, s);
3898 xfs_mod_sb(tp, XFS_SB_VERSIONNUM); 3940 xfs_mod_sb(tp, logflags);
3899 } else 3941 } else
3900 XFS_SB_UNLOCK(mp, s); 3942 XFS_SB_UNLOCK(mp, s);
3901 } 3943 }
@@ -3988,13 +4030,19 @@ xfs_bmap_compute_maxlevels(
3988 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents 4030 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
3989 * (a signed 16-bit number, xfs_aextnum_t). 4031 * (a signed 16-bit number, xfs_aextnum_t).
3990 */ 4032 */
3991 maxleafents = (whichfork == XFS_DATA_FORK) ? MAXEXTNUM : MAXAEXTNUM; 4033 if (whichfork == XFS_DATA_FORK) {
4034 maxleafents = MAXEXTNUM;
4035 sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
4036 mp->m_attroffset : XFS_BMDR_SPACE_CALC(MINDBTPTRS);
4037 } else {
4038 maxleafents = MAXAEXTNUM;
4039 sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
4040 mp->m_sb.sb_inodesize - mp->m_attroffset :
4041 XFS_BMDR_SPACE_CALC(MINABTPTRS);
4042 }
4043 maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
3992 minleafrecs = mp->m_bmap_dmnr[0]; 4044 minleafrecs = mp->m_bmap_dmnr[0];
3993 minnoderecs = mp->m_bmap_dmnr[1]; 4045 minnoderecs = mp->m_bmap_dmnr[1];
3994 sz = (whichfork == XFS_DATA_FORK) ?
3995 mp->m_attroffset :
3996 mp->m_sb.sb_inodesize - mp->m_attroffset;
3997 maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
3998 maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; 4046 maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
3999 for (level = 1; maxblocks > 1; level++) { 4047 for (level = 1; maxblocks > 1; level++) {
4000 if (maxblocks <= maxrootrecs) 4048 if (maxblocks <= maxrootrecs)