@@ -51,7 +51,6 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
5151STATIC int xfs_attr_leaf_get (xfs_da_args_t * args );
5252STATIC int xfs_attr_leaf_removename (xfs_da_args_t * args );
5353STATIC int xfs_attr_leaf_hasname (struct xfs_da_args * args , struct xfs_buf * * bp );
54- STATIC int xfs_attr_leaf_try_add (struct xfs_da_args * args );
5554
5655/*
5756 * Internal routines when attribute list is more than one block.
@@ -437,6 +436,33 @@ xfs_attr_hashval(
437436 return xfs_attr_hashname (name , namelen );
438437}
439438
439+ /* Save the current remote block info and clear the current pointers. */
440+ static void
441+ xfs_attr_save_rmt_blk (
442+ struct xfs_da_args * args )
443+ {
444+ args -> blkno2 = args -> blkno ;
445+ args -> index2 = args -> index ;
446+ args -> rmtblkno2 = args -> rmtblkno ;
447+ args -> rmtblkcnt2 = args -> rmtblkcnt ;
448+ args -> rmtvaluelen2 = args -> rmtvaluelen ;
449+ args -> rmtblkno = 0 ;
450+ args -> rmtblkcnt = 0 ;
451+ args -> rmtvaluelen = 0 ;
452+ }
453+
454+ /* Set stored info about a remote block */
455+ static void
456+ xfs_attr_restore_rmt_blk (
457+ struct xfs_da_args * args )
458+ {
459+ args -> blkno = args -> blkno2 ;
460+ args -> index = args -> index2 ;
461+ args -> rmtblkno = args -> rmtblkno2 ;
462+ args -> rmtblkcnt = args -> rmtblkcnt2 ;
463+ args -> rmtvaluelen = args -> rmtvaluelen2 ;
464+ }
465+
440466/*
441467 * PPTR_REPLACE operations require the caller to set the old and new names and
442468 * values explicitly. Update the canonical fields to the new name and value
@@ -482,48 +508,73 @@ xfs_attr_complete_op(
482508 return replace_state ;
483509}
484510
511+ /*
512+ * Try to add an attribute to an inode in leaf form.
513+ */
485514static int
486515xfs_attr_leaf_addname (
487516 struct xfs_attr_intent * attr )
488517{
489518 struct xfs_da_args * args = attr -> xattri_da_args ;
519+ struct xfs_buf * bp ;
490520 int error ;
491521
492522 ASSERT (xfs_attr_is_leaf (args -> dp ));
493523
524+ error = xfs_attr3_leaf_read (args -> trans , args -> dp , args -> owner , 0 , & bp );
525+ if (error )
526+ return error ;
527+
494528 /*
495- * Use the leaf buffer we may already hold locked as a result of
496- * a sf-to-leaf conversion.
529+ * Look up the xattr name to set the insertion point for the new xattr.
497530 */
498- error = xfs_attr_leaf_try_add (args );
499-
500- if (error == - ENOSPC ) {
501- error = xfs_attr3_leaf_to_node (args );
502- if (error )
503- return error ;
531+ error = xfs_attr3_leaf_lookup_int (bp , args );
532+ switch (error ) {
533+ case - ENOATTR :
534+ if (args -> op_flags & XFS_DA_OP_REPLACE )
535+ goto out_brelse ;
536+ break ;
537+ case - EEXIST :
538+ if (!(args -> op_flags & XFS_DA_OP_REPLACE ))
539+ goto out_brelse ;
504540
541+ trace_xfs_attr_leaf_replace (args );
505542 /*
506- * We're not in leaf format anymore, so roll the transaction and
507- * retry the add to the newly allocated node block.
543+ * Save the existing remote attr state so that the current
544+ * values reflect the state of the new attribute we are about to
545+ * add, not the attribute we just found and will remove later.
508546 */
509- attr -> xattri_dela_state = XFS_DAS_NODE_ADD ;
510- goto out ;
547+ xfs_attr_save_rmt_blk (args );
548+ break ;
549+ case 0 :
550+ break ;
551+ default :
552+ goto out_brelse ;
511553 }
512- if (error )
513- return error ;
514554
515555 /*
516556 * We need to commit and roll if we need to allocate remote xattr blocks
517557 * or perform more xattr manipulations. Otherwise there is nothing more
518558 * to do and we can return success.
519559 */
520- if (args -> rmtblkno )
560+ if (!xfs_attr3_leaf_add (bp , args )) {
561+ error = xfs_attr3_leaf_to_node (args );
562+ if (error )
563+ return error ;
564+
565+ attr -> xattri_dela_state = XFS_DAS_NODE_ADD ;
566+ } else if (args -> rmtblkno ) {
521567 attr -> xattri_dela_state = XFS_DAS_LEAF_SET_RMT ;
522- else
523- attr -> xattri_dela_state = xfs_attr_complete_op (attr ,
524- XFS_DAS_LEAF_REPLACE );
525- out :
568+ } else {
569+ attr -> xattri_dela_state =
570+ xfs_attr_complete_op (attr , XFS_DAS_LEAF_REPLACE );
571+ }
572+
526573 trace_xfs_attr_leaf_addname_return (attr -> xattri_dela_state , args -> dp );
574+ return 0 ;
575+
576+ out_brelse :
577+ xfs_trans_brelse (args -> trans , bp );
527578 return error ;
528579}
529580
@@ -546,7 +597,7 @@ xfs_attr_node_addname(
546597 return error ;
547598
548599 error = xfs_attr_node_try_addname (attr );
549- if (error == - ENOSPC ) {
600+ if (error == 1 ) {
550601 error = xfs_attr3_leaf_to_node (args );
551602 if (error )
552603 return error ;
@@ -1170,88 +1221,6 @@ xfs_attr_shortform_addname(
11701221 * External routines when attribute list is one block
11711222 *========================================================================*/
11721223
1173- /* Save the current remote block info and clear the current pointers. */
1174- static void
1175- xfs_attr_save_rmt_blk (
1176- struct xfs_da_args * args )
1177- {
1178- args -> blkno2 = args -> blkno ;
1179- args -> index2 = args -> index ;
1180- args -> rmtblkno2 = args -> rmtblkno ;
1181- args -> rmtblkcnt2 = args -> rmtblkcnt ;
1182- args -> rmtvaluelen2 = args -> rmtvaluelen ;
1183- args -> rmtblkno = 0 ;
1184- args -> rmtblkcnt = 0 ;
1185- args -> rmtvaluelen = 0 ;
1186- }
1187-
1188- /* Set stored info about a remote block */
1189- static void
1190- xfs_attr_restore_rmt_blk (
1191- struct xfs_da_args * args )
1192- {
1193- args -> blkno = args -> blkno2 ;
1194- args -> index = args -> index2 ;
1195- args -> rmtblkno = args -> rmtblkno2 ;
1196- args -> rmtblkcnt = args -> rmtblkcnt2 ;
1197- args -> rmtvaluelen = args -> rmtvaluelen2 ;
1198- }
1199-
1200- /*
1201- * Tries to add an attribute to an inode in leaf form
1202- *
1203- * This function is meant to execute as part of a delayed operation and leaves
1204- * the transaction handling to the caller. On success the attribute is added
1205- * and the inode and transaction are left dirty. If there is not enough space,
1206- * the attr data is converted to node format and -ENOSPC is returned. Caller is
1207- * responsible for handling the dirty inode and transaction or adding the attr
1208- * in node format.
1209- */
1210- STATIC int
1211- xfs_attr_leaf_try_add (
1212- struct xfs_da_args * args )
1213- {
1214- struct xfs_buf * bp ;
1215- int error ;
1216-
1217- error = xfs_attr3_leaf_read (args -> trans , args -> dp , args -> owner , 0 , & bp );
1218- if (error )
1219- return error ;
1220-
1221- /*
1222- * Look up the xattr name to set the insertion point for the new xattr.
1223- */
1224- error = xfs_attr3_leaf_lookup_int (bp , args );
1225- switch (error ) {
1226- case - ENOATTR :
1227- if (args -> op_flags & XFS_DA_OP_REPLACE )
1228- goto out_brelse ;
1229- break ;
1230- case - EEXIST :
1231- if (!(args -> op_flags & XFS_DA_OP_REPLACE ))
1232- goto out_brelse ;
1233-
1234- trace_xfs_attr_leaf_replace (args );
1235- /*
1236- * Save the existing remote attr state so that the current
1237- * values reflect the state of the new attribute we are about to
1238- * add, not the attribute we just found and will remove later.
1239- */
1240- xfs_attr_save_rmt_blk (args );
1241- break ;
1242- case 0 :
1243- break ;
1244- default :
1245- goto out_brelse ;
1246- }
1247-
1248- return xfs_attr3_leaf_add (bp , args );
1249-
1250- out_brelse :
1251- xfs_trans_brelse (args -> trans , bp );
1252- return error ;
1253- }
1254-
12551224/*
12561225 * Return EEXIST if attr is found, or ENOATTR if not
12571226 */
@@ -1417,31 +1386,34 @@ xfs_attr_node_addname_find_attr(
14171386/*
14181387 * Add a name to a Btree-format attribute list.
14191388 *
1420- * This will involve walking down the Btree, and may involve splitting
1421- * leaf nodes and even splitting intermediate nodes up to and including
1422- * the root node (a special case of an intermediate node).
1389+ * This will involve walking down the Btree, and may involve splitting leaf
1390+ * nodes and even splitting intermediate nodes up to and including the root
1391+ * node (a special case of an intermediate node).
1392+ *
1393+ * If the tree was still in single leaf format and needs to converted to
1394+ * real node format return 1 and let the caller handle that.
14231395 */
14241396static int
14251397xfs_attr_node_try_addname (
14261398 struct xfs_attr_intent * attr )
14271399{
14281400 struct xfs_da_state * state = attr -> xattri_da_state ;
14291401 struct xfs_da_state_blk * blk ;
1430- int error ;
1402+ int error = 0 ;
14311403
14321404 trace_xfs_attr_node_addname (state -> args );
14331405
14341406 blk = & state -> path .blk [state -> path .active - 1 ];
14351407 ASSERT (blk -> magic == XFS_ATTR_LEAF_MAGIC );
14361408
1437- error = xfs_attr3_leaf_add (blk -> bp , state -> args );
1438- if (error == - ENOSPC ) {
1409+ if (!xfs_attr3_leaf_add (blk -> bp , state -> args )) {
14391410 if (state -> path .active == 1 ) {
14401411 /*
14411412 * Its really a single leaf node, but it had
14421413 * out-of-line values so it looked like it *might*
14431414 * have been a b-tree. Let the caller deal with this.
14441415 */
1416+ error = 1 ;
14451417 goto out ;
14461418 }
14471419
0 commit comments