aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr.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_attr.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_attr.c')
-rw-r--r--fs/xfs/xfs_attr.c61
1 files changed, 31 insertions, 30 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index ce9f673f2b4c..c2939b8f8d24 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -200,7 +200,7 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp,
200 return(error); 200 return(error);
201} 201}
202 202
203int 203STATIC int
204xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, 204xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
205 char *value, int valuelen, int flags) 205 char *value, int valuelen, int flags)
206{ 206{
@@ -220,12 +220,18 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
220 return (error); 220 return (error);
221 221
222 /* 222 /*
223 * Determine space new attribute will use, and if it would be
224 * "local" or "remote" (note: local != inline).
225 */
226 size = xfs_attr_leaf_newentsize(namelen, valuelen,
227 mp->m_sb.sb_blocksize, &local);
228
229 /*
223 * If the inode doesn't have an attribute fork, add one. 230 * If the inode doesn't have an attribute fork, add one.
224 * (inode must not be locked when we call this routine) 231 * (inode must not be locked when we call this routine)
225 */ 232 */
226 if (XFS_IFORK_Q(dp) == 0) { 233 if (XFS_IFORK_Q(dp) == 0) {
227 error = xfs_bmap_add_attrfork(dp, rsvd); 234 if ((error = xfs_bmap_add_attrfork(dp, size, rsvd)))
228 if (error)
229 return(error); 235 return(error);
230 } 236 }
231 237
@@ -243,14 +249,9 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
243 args.firstblock = &firstblock; 249 args.firstblock = &firstblock;
244 args.flist = &flist; 250 args.flist = &flist;
245 args.whichfork = XFS_ATTR_FORK; 251 args.whichfork = XFS_ATTR_FORK;
252 args.addname = 1;
246 args.oknoent = 1; 253 args.oknoent = 1;
247 254
248 /* Determine space new attribute will use, and if it will be inline
249 * or out of line.
250 */
251 size = xfs_attr_leaf_newentsize(namelen, valuelen,
252 mp->m_sb.sb_blocksize, &local);
253
254 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); 255 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
255 if (local) { 256 if (local) {
256 if (size > (mp->m_sb.sb_blocksize >> 1)) { 257 if (size > (mp->m_sb.sb_blocksize >> 1)) {
@@ -322,7 +323,7 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
322 * Build initial attribute list (if required). 323 * Build initial attribute list (if required).
323 */ 324 */
324 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) 325 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
325 (void)xfs_attr_shortform_create(&args); 326 xfs_attr_shortform_create(&args);
326 327
327 /* 328 /*
328 * Try to add the attr to the attribute list in 329 * Try to add the attr to the attribute list in
@@ -467,7 +468,7 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags,
467 * Generic handler routine to remove a name from an attribute list. 468 * Generic handler routine to remove a name from an attribute list.
468 * Transitions attribute list from Btree to shortform as necessary. 469 * Transitions attribute list from Btree to shortform as necessary.
469 */ 470 */
470int 471STATIC int
471xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) 472xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags)
472{ 473{
473 xfs_da_args_t args; 474 xfs_da_args_t args;
@@ -523,7 +524,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags)
523 XFS_ATTRRM_LOG_COUNT))) { 524 XFS_ATTRRM_LOG_COUNT))) {
524 xfs_trans_cancel(args.trans, 0); 525 xfs_trans_cancel(args.trans, 0);
525 return(error); 526 return(error);
526
527 } 527 }
528 528
529 xfs_ilock(dp, XFS_ILOCK_EXCL); 529 xfs_ilock(dp, XFS_ILOCK_EXCL);
@@ -822,7 +822,7 @@ out:
822STATIC int 822STATIC int
823xfs_attr_shortform_addname(xfs_da_args_t *args) 823xfs_attr_shortform_addname(xfs_da_args_t *args)
824{ 824{
825 int newsize, retval; 825 int newsize, forkoff, retval;
826 826
827 retval = xfs_attr_shortform_lookup(args); 827 retval = xfs_attr_shortform_lookup(args);
828 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { 828 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
@@ -834,16 +834,18 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
834 ASSERT(retval == 0); 834 ASSERT(retval == 0);
835 } 835 }
836 836
837 if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
838 args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
839 return(XFS_ERROR(ENOSPC));
840
837 newsize = XFS_ATTR_SF_TOTSIZE(args->dp); 841 newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
838 newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); 842 newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
839 if ((newsize <= XFS_IFORK_ASIZE(args->dp)) && 843
840 (args->namelen < XFS_ATTR_SF_ENTSIZE_MAX) && 844 forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
841 (args->valuelen < XFS_ATTR_SF_ENTSIZE_MAX)) { 845 if (!forkoff)
842 retval = xfs_attr_shortform_add(args);
843 ASSERT(retval == 0);
844 } else {
845 return(XFS_ERROR(ENOSPC)); 846 return(XFS_ERROR(ENOSPC));
846 } 847
848 xfs_attr_shortform_add(args, forkoff);
847 return(0); 849 return(0);
848} 850}
849 851
@@ -863,7 +865,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
863{ 865{
864 xfs_inode_t *dp; 866 xfs_inode_t *dp;
865 xfs_dabuf_t *bp; 867 xfs_dabuf_t *bp;
866 int retval, error, committed; 868 int retval, error, committed, forkoff;
867 869
868 /* 870 /*
869 * Read the (only) block in the attribute list in. 871 * Read the (only) block in the attribute list in.
@@ -1006,9 +1008,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1006 /* 1008 /*
1007 * If the result is small enough, shrink it all into the inode. 1009 * If the result is small enough, shrink it all into the inode.
1008 */ 1010 */
1009 if (xfs_attr_shortform_allfit(bp, dp)) { 1011 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1010 XFS_BMAP_INIT(args->flist, args->firstblock); 1012 XFS_BMAP_INIT(args->flist, args->firstblock);
1011 error = xfs_attr_leaf_to_shortform(bp, args); 1013 error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1012 /* bp is gone due to xfs_da_shrink_inode */ 1014 /* bp is gone due to xfs_da_shrink_inode */
1013 if (!error) { 1015 if (!error) {
1014 error = xfs_bmap_finish(&args->trans, 1016 error = xfs_bmap_finish(&args->trans,
@@ -1060,8 +1062,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
1060{ 1062{
1061 xfs_inode_t *dp; 1063 xfs_inode_t *dp;
1062 xfs_dabuf_t *bp; 1064 xfs_dabuf_t *bp;
1063 int committed; 1065 int error, committed, forkoff;
1064 int error;
1065 1066
1066 /* 1067 /*
1067 * Remove the attribute. 1068 * Remove the attribute.
@@ -1086,9 +1087,9 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
1086 /* 1087 /*
1087 * If the result is small enough, shrink it all into the inode. 1088 * If the result is small enough, shrink it all into the inode.
1088 */ 1089 */
1089 if (xfs_attr_shortform_allfit(bp, dp)) { 1090 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1090 XFS_BMAP_INIT(args->flist, args->firstblock); 1091 XFS_BMAP_INIT(args->flist, args->firstblock);
1091 error = xfs_attr_leaf_to_shortform(bp, args); 1092 error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1092 /* bp is gone due to xfs_da_shrink_inode */ 1093 /* bp is gone due to xfs_da_shrink_inode */
1093 if (!error) { 1094 if (!error) {
1094 error = xfs_bmap_finish(&args->trans, args->flist, 1095 error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1459,7 +1460,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
1459 xfs_da_state_blk_t *blk; 1460 xfs_da_state_blk_t *blk;
1460 xfs_inode_t *dp; 1461 xfs_inode_t *dp;
1461 xfs_dabuf_t *bp; 1462 xfs_dabuf_t *bp;
1462 int retval, error, committed; 1463 int retval, error, committed, forkoff;
1463 1464
1464 /* 1465 /*
1465 * Tie a string around our finger to remind us where we are. 1466 * Tie a string around our finger to remind us where we are.
@@ -1580,9 +1581,9 @@ xfs_attr_node_removename(xfs_da_args_t *args)
1580 bp->data)->hdr.info.magic, ARCH_CONVERT) 1581 bp->data)->hdr.info.magic, ARCH_CONVERT)
1581 == XFS_ATTR_LEAF_MAGIC); 1582 == XFS_ATTR_LEAF_MAGIC);
1582 1583
1583 if (xfs_attr_shortform_allfit(bp, dp)) { 1584 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1584 XFS_BMAP_INIT(args->flist, args->firstblock); 1585 XFS_BMAP_INIT(args->flist, args->firstblock);
1585 error = xfs_attr_leaf_to_shortform(bp, args); 1586 error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1586 /* bp is gone due to xfs_da_shrink_inode */ 1587 /* bp is gone due to xfs_da_shrink_inode */
1587 if (!error) { 1588 if (!error) {
1588 error = xfs_bmap_finish(&args->trans, 1589 error = xfs_bmap_finish(&args->trans,