@@ -564,23 +564,21 @@ __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
564564}
565565
566566/*
567- * Loading a module requires dropping mutex that guards the
568- * transaction.
569- * We first need to abort any pending transactions as once
570- * mutex is unlocked a different client could start a new
571- * transaction. It must not see any 'future generation'
572- * changes * as these changes will never happen.
567+ * Loading a module requires dropping mutex that guards the transaction.
568+ * A different client might race to start a new transaction meanwhile. Zap the
569+ * list of pending transaction and then restore it once the mutex is grabbed
570+ * again. Users of this function return EAGAIN which implicitly triggers the
571+ * transaction abort path to clean up the list of pending transactions.
573572 */
574573#ifdef CONFIG_MODULES
575- static int __nf_tables_abort (struct net * net );
576-
577574static void nft_request_module (struct net * net , const char * fmt , ...)
578575{
579576 char module_name [MODULE_NAME_LEN ];
577+ LIST_HEAD (commit_list );
580578 va_list args ;
581579 int ret ;
582580
583- __nf_tables_abort ( net );
581+ list_splice_init ( & net -> nft . commit_list , & commit_list );
584582
585583 va_start (args , fmt );
586584 ret = vsnprintf (module_name , MODULE_NAME_LEN , fmt , args );
@@ -591,6 +589,9 @@ static void nft_request_module(struct net *net, const char *fmt, ...)
591589 mutex_unlock (& net -> nft .commit_mutex );
592590 request_module ("%s" , module_name );
593591 mutex_lock (& net -> nft .commit_mutex );
592+
593+ WARN_ON_ONCE (!list_empty (& net -> nft .commit_list ));
594+ list_splice (& commit_list , & net -> nft .commit_list );
594595}
595596#endif
596597
0 commit comments