Skip to content

Commit

Permalink
[XFS] Ondisk format extension for extended attributes (attr2). Basica…
Browse files Browse the repository at this point in the history
…lly,

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>
  • Loading branch information
Nathan Scott committed Nov 1, 2005
1 parent aa82daa commit d8cc890
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 114 deletions.
61 changes: 31 additions & 30 deletions fs/xfs/xfs_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp,
return(error);
}

int
STATIC int
xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
char *value, int valuelen, int flags)
{
Expand All @@ -219,13 +219,19 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
return (error);

/*
* 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);

/*
* If the inode doesn't have an attribute fork, add one.
* (inode must not be locked when we call this routine)
*/
if (XFS_IFORK_Q(dp) == 0) {
error = xfs_bmap_add_attrfork(dp, rsvd);
if (error)
if ((error = xfs_bmap_add_attrfork(dp, size, rsvd)))
return(error);
}

Expand All @@ -243,14 +249,9 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
args.firstblock = &firstblock;
args.flist = &flist;
args.whichfork = XFS_ATTR_FORK;
args.addname = 1;
args.oknoent = 1;

/* Determine space new attribute will use, and if it will be inline
* or out of line.
*/
size = xfs_attr_leaf_newentsize(namelen, valuelen,
mp->m_sb.sb_blocksize, &local);

nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
if (local) {
if (size > (mp->m_sb.sb_blocksize >> 1)) {
Expand Down Expand Up @@ -322,7 +323,7 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
* Build initial attribute list (if required).
*/
if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
(void)xfs_attr_shortform_create(&args);
xfs_attr_shortform_create(&args);

/*
* Try to add the attr to the attribute list in
Expand Down Expand Up @@ -467,7 +468,7 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags,
* Generic handler routine to remove a name from an attribute list.
* Transitions attribute list from Btree to shortform as necessary.
*/
int
STATIC int
xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags)
{
xfs_da_args_t args;
Expand Down Expand Up @@ -523,7 +524,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags)
XFS_ATTRRM_LOG_COUNT))) {
xfs_trans_cancel(args.trans, 0);
return(error);

}

xfs_ilock(dp, XFS_ILOCK_EXCL);
Expand Down Expand Up @@ -822,7 +822,7 @@ xfs_attr_inactive(xfs_inode_t *dp)
STATIC int
xfs_attr_shortform_addname(xfs_da_args_t *args)
{
int newsize, retval;
int newsize, forkoff, retval;

retval = xfs_attr_shortform_lookup(args);
if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
Expand All @@ -834,16 +834,18 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
ASSERT(retval == 0);
}

if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
return(XFS_ERROR(ENOSPC));

newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
if ((newsize <= XFS_IFORK_ASIZE(args->dp)) &&
(args->namelen < XFS_ATTR_SF_ENTSIZE_MAX) &&
(args->valuelen < XFS_ATTR_SF_ENTSIZE_MAX)) {
retval = xfs_attr_shortform_add(args);
ASSERT(retval == 0);
} else {

forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
if (!forkoff)
return(XFS_ERROR(ENOSPC));
}

xfs_attr_shortform_add(args, forkoff);
return(0);
}

Expand All @@ -863,7 +865,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
{
xfs_inode_t *dp;
xfs_dabuf_t *bp;
int retval, error, committed;
int retval, error, committed, forkoff;

/*
* Read the (only) block in the attribute list in.
Expand Down Expand Up @@ -1006,9 +1008,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
/*
* If the result is small enough, shrink it all into the inode.
*/
if (xfs_attr_shortform_allfit(bp, dp)) {
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
XFS_BMAP_INIT(args->flist, args->firstblock);
error = xfs_attr_leaf_to_shortform(bp, args);
error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
/* bp is gone due to xfs_da_shrink_inode */
if (!error) {
error = xfs_bmap_finish(&args->trans,
Expand Down Expand Up @@ -1060,8 +1062,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
{
xfs_inode_t *dp;
xfs_dabuf_t *bp;
int committed;
int error;
int error, committed, forkoff;

/*
* Remove the attribute.
Expand All @@ -1086,9 +1087,9 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
/*
* If the result is small enough, shrink it all into the inode.
*/
if (xfs_attr_shortform_allfit(bp, dp)) {
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
XFS_BMAP_INIT(args->flist, args->firstblock);
error = xfs_attr_leaf_to_shortform(bp, args);
error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
/* bp is gone due to xfs_da_shrink_inode */
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
Expand Down Expand Up @@ -1459,7 +1460,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
xfs_da_state_blk_t *blk;
xfs_inode_t *dp;
xfs_dabuf_t *bp;
int retval, error, committed;
int retval, error, committed, forkoff;

/*
* Tie a string around our finger to remind us where we are.
Expand Down Expand Up @@ -1580,9 +1581,9 @@ xfs_attr_node_removename(xfs_da_args_t *args)
bp->data)->hdr.info.magic, ARCH_CONVERT)
== XFS_ATTR_LEAF_MAGIC);

if (xfs_attr_shortform_allfit(bp, dp)) {
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
XFS_BMAP_INIT(args->flist, args->firstblock);
error = xfs_attr_leaf_to_shortform(bp, args);
error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
/* bp is gone due to xfs_da_shrink_inode */
if (!error) {
error = xfs_bmap_finish(&args->trans,
Expand Down
Loading

0 comments on commit d8cc890

Please sign in to comment.