@@ -350,16 +350,14 @@ xfs_attr_set_resv(
350350 */
351351STATIC int
352352xfs_attr_try_sf_addname (
353- struct xfs_inode * dp ,
354353 struct xfs_da_args * args )
355354{
356-
357355 int error ;
358356
359357 /*
360358 * Build initial attribute list (if required).
361359 */
362- if (dp -> i_af .if_format == XFS_DINODE_FMT_EXTENTS )
360+ if (args -> dp -> i_af .if_format == XFS_DINODE_FMT_EXTENTS )
363361 xfs_attr_shortform_create (args );
364362
365363 error = xfs_attr_shortform_addname (args );
@@ -371,9 +369,9 @@ xfs_attr_try_sf_addname(
371369 * NOTE: this is also the error path (EEXIST, etc).
372370 */
373371 if (!error )
374- xfs_trans_ichgtime (args -> trans , dp , XFS_ICHGTIME_CHG );
372+ xfs_trans_ichgtime (args -> trans , args -> dp , XFS_ICHGTIME_CHG );
375373
376- if (xfs_has_wsync (dp -> i_mount ))
374+ if (xfs_has_wsync (args -> dp -> i_mount ))
377375 xfs_trans_set_sync (args -> trans );
378376
379377 return error ;
@@ -384,10 +382,9 @@ xfs_attr_sf_addname(
384382 struct xfs_attr_intent * attr )
385383{
386384 struct xfs_da_args * args = attr -> xattri_da_args ;
387- struct xfs_inode * dp = args -> dp ;
388385 int error = 0 ;
389386
390- error = xfs_attr_try_sf_addname (dp , args );
387+ error = xfs_attr_try_sf_addname (args );
391388 if (error != - ENOSPC ) {
392389 ASSERT (!error || error == - EEXIST );
393390 attr -> xattri_dela_state = XFS_DAS_DONE ;
@@ -1031,6 +1028,95 @@ xfs_attr_add_fork(
10311028 return error ;
10321029}
10331030
1031+ /*
1032+ * Decide if it is theoretically possible to try to bypass the attr intent
1033+ * mechanism for better performance. Other constraints (e.g. available space
1034+ * in the existing structure) are not considered here.
1035+ */
1036+ static inline bool
1037+ xfs_attr_can_shortcut (
1038+ const struct xfs_inode * ip )
1039+ {
1040+ return xfs_inode_has_attr_fork (ip ) && xfs_attr_is_shortform (ip );
1041+ }
1042+
1043+ /* Try to set an attr in one transaction or fall back to attr intents. */
1044+ int
1045+ xfs_attr_setname (
1046+ struct xfs_da_args * args ,
1047+ int rmt_blks )
1048+ {
1049+ int error ;
1050+
1051+ if (!rmt_blks && xfs_attr_can_shortcut (args -> dp )) {
1052+ args -> op_flags |= XFS_DA_OP_ADDNAME ;
1053+
1054+ error = xfs_attr_try_sf_addname (args );
1055+ if (error != - ENOSPC )
1056+ return error ;
1057+ }
1058+
1059+ xfs_attr_defer_add (args , XFS_ATTR_DEFER_SET );
1060+ return 0 ;
1061+ }
1062+
1063+ /* Try to remove an attr in one transaction or fall back to attr intents. */
1064+ int
1065+ xfs_attr_removename (
1066+ struct xfs_da_args * args )
1067+ {
1068+ if (xfs_attr_can_shortcut (args -> dp ))
1069+ return xfs_attr_sf_removename (args );
1070+
1071+ xfs_attr_defer_add (args , XFS_ATTR_DEFER_REMOVE );
1072+ return 0 ;
1073+ }
1074+
1075+ /* Try to replace an attr in one transaction or fall back to attr intents. */
1076+ int
1077+ xfs_attr_replacename (
1078+ struct xfs_da_args * args ,
1079+ int rmt_blks )
1080+ {
1081+ int error ;
1082+
1083+ if (rmt_blks || !xfs_attr_can_shortcut (args -> dp )) {
1084+ xfs_attr_defer_add (args , XFS_ATTR_DEFER_REPLACE );
1085+ return 0 ;
1086+ }
1087+
1088+ error = xfs_attr_shortform_replace (args );
1089+ if (error != - ENOSPC )
1090+ return error ;
1091+
1092+ args -> op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE ;
1093+
1094+ error = xfs_attr_sf_removename (args );
1095+ if (error )
1096+ return error ;
1097+
1098+ if (args -> attr_filter & XFS_ATTR_PARENT ) {
1099+ /*
1100+ * Move the new name/value to the regular name/value slots and
1101+ * zero out the new name/value slots because we don't need to
1102+ * log them for a PPTR_SET operation.
1103+ */
1104+ xfs_attr_update_pptr_replace_args (args );
1105+ args -> new_name = NULL ;
1106+ args -> new_namelen = 0 ;
1107+ args -> new_value = NULL ;
1108+ args -> new_valuelen = 0 ;
1109+ }
1110+ args -> op_flags &= ~XFS_DA_OP_REPLACE ;
1111+
1112+ error = xfs_attr_try_sf_addname (args );
1113+ if (error != - ENOSPC )
1114+ return error ;
1115+
1116+ xfs_attr_defer_add (args , XFS_ATTR_DEFER_SET );
1117+ return 0 ;
1118+ }
1119+
10341120/*
10351121 * Make a change to the xattr structure.
10361122 *
@@ -1111,14 +1197,19 @@ xfs_attr_set(
11111197 case - EEXIST :
11121198 if (op == XFS_ATTRUPDATE_REMOVE ) {
11131199 /* if no value, we are performing a remove operation */
1114- xfs_attr_defer_add (args , XFS_ATTR_DEFER_REMOVE );
1200+ error = xfs_attr_removename (args );
1201+ if (error )
1202+ goto out_trans_cancel ;
11151203 break ;
11161204 }
11171205
11181206 /* Pure create fails if the attr already exists */
11191207 if (op == XFS_ATTRUPDATE_CREATE )
11201208 goto out_trans_cancel ;
1121- xfs_attr_defer_add (args , XFS_ATTR_DEFER_REPLACE );
1209+
1210+ error = xfs_attr_replacename (args , rmt_blks );
1211+ if (error )
1212+ goto out_trans_cancel ;
11221213 break ;
11231214 case - ENOATTR :
11241215 /* Can't remove what isn't there. */
@@ -1128,7 +1219,10 @@ xfs_attr_set(
11281219 /* Pure replace fails if no existing attr to replace. */
11291220 if (op == XFS_ATTRUPDATE_REPLACE )
11301221 goto out_trans_cancel ;
1131- xfs_attr_defer_add (args , XFS_ATTR_DEFER_SET );
1222+
1223+ error = xfs_attr_setname (args , rmt_blks );
1224+ if (error )
1225+ goto out_trans_cancel ;
11321226 break ;
11331227 default :
11341228 goto out_trans_cancel ;
0 commit comments