diff options
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r-- | fs/xfs/xfs_attr.c | 61 |
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 | ||
203 | int | 203 | STATIC int |
204 | xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, | 204 | xfs_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 | */ |
470 | int | 471 | STATIC int |
471 | xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) | 472 | xfs_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: | |||
822 | STATIC int | 822 | STATIC int |
823 | xfs_attr_shortform_addname(xfs_da_args_t *args) | 823 | xfs_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, |