@@ -3332,8 +3332,27 @@ xfs_alloc_vextent_iterate_ags(
args->pag = NULL;
return error;
}
- if (args->agbp)
+ if (args->agbp) {
+ /*
+ * XXX: this looks like a pre-existing bug. alloc_size fails
+ * because of nominleft, and we return here with the AGF locked
+ * with args->agbno == NULLAGBLOCK If this happens with any AG
+ * higher than the start_agno, if the caller then tries to allocate
+ * again with more restricted parameters, we try locking from
+ * start_agno again and we deadlock because we've already got a
+ * higher AGF locked. Hence we need to drop the AGF lock if
+ * we failed to allocate here. g/476 triggers this reliably.
+ */
+ if (args->agbno == NULLAGBLOCK) {
+ /*
+ * XXX: This is not a reliable workaround if the AGF was
+ * modified!
+ */
+ xfs_trans_brelse(args->tp, args->agbp);
+ args->agbp = NULL;
+ }
return 0;
+ }
/*
* We didn't find an AG we can alloation from. If we were given