@@ -256,10 +256,31 @@ xfs_attr_set_args(
256
256
}
257
257
}
258
258
259
- if (xfs_bmap_one_block (dp , XFS_ATTR_FORK ))
259
+ if (xfs_bmap_one_block (dp , XFS_ATTR_FORK )) {
260
260
error = xfs_attr_leaf_addname (args );
261
- else
262
- error = xfs_attr_node_addname (args );
261
+ if (error != - ENOSPC )
262
+ return error ;
263
+
264
+ /*
265
+ * Finish any deferred work items and roll the transaction once
266
+ * more. The goal here is to call node_addname with the inode
267
+ * and transaction in the same state (inode locked and joined,
268
+ * transaction clean) no matter how we got to this step.
269
+ */
270
+ error = xfs_defer_finish (& args -> trans );
271
+ if (error )
272
+ return error ;
273
+
274
+ /*
275
+ * Commit the current trans (including the inode) and
276
+ * start a new one.
277
+ */
278
+ error = xfs_trans_roll_inode (& args -> trans , dp );
279
+ if (error )
280
+ return error ;
281
+ }
282
+
283
+ error = xfs_attr_node_addname (args );
263
284
return error ;
264
285
}
265
286
@@ -507,20 +528,21 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
507
528
*========================================================================*/
508
529
509
530
/*
510
- * Add a name to the leaf attribute list structure
531
+ * Tries to add an attribute to an inode in leaf form
511
532
*
512
- * This leaf block cannot have a "remote" value, we only call this routine
513
- * if bmap_one_block() says there is only one block (ie: no remote blks).
533
+ * This function is meant to execute as part of a delayed operation and leaves
534
+ * the transaction handling to the caller. On success the attribute is added
535
+ * and the inode and transaction are left dirty. If there is not enough space,
536
+ * the attr data is converted to node format and -ENOSPC is returned. Caller is
537
+ * responsible for handling the dirty inode and transaction or adding the attr
538
+ * in node format.
514
539
*/
515
540
STATIC int
516
- xfs_attr_leaf_addname (
517
- struct xfs_da_args * args )
541
+ xfs_attr_leaf_try_add (
542
+ struct xfs_da_args * args ,
543
+ struct xfs_buf * bp )
518
544
{
519
- struct xfs_buf * bp ;
520
- int retval , error , forkoff ;
521
- struct xfs_inode * dp = args -> dp ;
522
-
523
- trace_xfs_attr_leaf_addname (args );
545
+ int retval , error ;
524
546
525
547
/*
526
548
* Look up the given attribute in the leaf block. Figure out if
@@ -562,31 +584,39 @@ xfs_attr_leaf_addname(
562
584
retval = xfs_attr3_leaf_add (bp , args );
563
585
if (retval == - ENOSPC ) {
564
586
/*
565
- * Promote the attribute list to the Btree format, then
566
- * Commit that transaction so that the node_addname() call
567
- * can manage its own transactions.
587
+ * Promote the attribute list to the Btree format. Unless an
588
+ * error occurs, retain the -ENOSPC retval
568
589
*/
569
590
error = xfs_attr3_leaf_to_node (args );
570
591
if (error )
571
592
return error ;
572
- error = xfs_defer_finish (& args -> trans );
573
- if (error )
574
- return error ;
593
+ }
594
+ return retval ;
595
+ out_brelse :
596
+ xfs_trans_brelse (args -> trans , bp );
597
+ return retval ;
598
+ }
575
599
576
- /*
577
- * Commit the current trans (including the inode) and start
578
- * a new one.
579
- */
580
- error = xfs_trans_roll_inode (& args -> trans , dp );
581
- if (error )
582
- return error ;
583
600
584
- /*
585
- * Fob the whole rest of the problem off on the Btree code.
586
- */
587
- error = xfs_attr_node_addname (args );
601
+ /*
602
+ * Add a name to the leaf attribute list structure
603
+ *
604
+ * This leaf block cannot have a "remote" value, we only call this routine
605
+ * if bmap_one_block() says there is only one block (ie: no remote blks).
606
+ */
607
+ STATIC int
608
+ xfs_attr_leaf_addname (
609
+ struct xfs_da_args * args )
610
+ {
611
+ int error , forkoff ;
612
+ struct xfs_buf * bp = NULL ;
613
+ struct xfs_inode * dp = args -> dp ;
614
+
615
+ trace_xfs_attr_leaf_addname (args );
616
+
617
+ error = xfs_attr_leaf_try_add (args , bp );
618
+ if (error )
588
619
return error ;
589
- }
590
620
591
621
/*
592
622
* Commit the transaction that added the attr name so that
@@ -681,9 +711,6 @@ xfs_attr_leaf_addname(
681
711
error = xfs_attr3_leaf_clearflag (args );
682
712
}
683
713
return error ;
684
- out_brelse :
685
- xfs_trans_brelse (args -> trans , bp );
686
- return retval ;
687
714
}
688
715
689
716
/*
0 commit comments