]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[interface] Provide the ability to shut down multiple interfaces
authorMichael Brown <mcb30@ipxe.org>
Thu, 2 Feb 2017 15:49:21 +0000 (15:49 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 2 Feb 2017 15:49:21 +0000 (15:49 +0000)
Shutting down (and optionally restarting) multiple interfaces is
fraught with problems if there are loops in the interface connectivity
(e.g. the HTTP content-decoded and transfer-decoded interfaces, which
will generally loop back to each other).  Various workarounds
currently exist across the codebase, generally involving preceding
calls to intf_nullify() to avoid problems due to known loops.

Provide intfs_shutdown() and intfs_restart() to allow all of an
object's interfaces to be shut down (or restarted) in a single call,
without having to worry about potential external loops.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/interface.c
src/include/ipxe/interface.h

index f7802be071c0d94c2fb064b3cad16348956e6a04..402aa45415059b009e4fbc5e8bfd325cece691de 100644 (file)
@@ -290,6 +290,41 @@ void intf_shutdown ( struct interface *intf, int rc ) {
        intf_unplug ( &tmp );
 }
 
+/**
+ * Shut down multiple object interfaces
+ *
+ * @v intfs            Object interfaces
+ * @v rc               Reason for close
+ */
+void intfs_vshutdown ( va_list intfs, int rc ) {
+       struct interface *intf;
+       va_list tmp;
+
+       /* Nullify all interfaces to avoid potential loops */
+       va_copy ( tmp, intfs );
+       while ( ( intf = va_arg ( tmp, struct interface * ) ) )
+               intf_nullify ( intf );
+       va_end ( tmp );
+
+       /* Shut down all interfaces */
+       while ( ( intf = va_arg ( intfs, struct interface * ) ) )
+               intf_shutdown ( intf, rc );
+}
+
+/**
+ * Shut down multiple object interfaces
+ *
+ * @v rc               Reason for close
+ * @v ...              Object interfaces
+ */
+void intfs_shutdown ( int rc, ... ) {
+       va_list intfs;
+
+       va_start ( intfs, rc );
+       intfs_vshutdown ( intfs, rc );
+       va_end ( intfs );
+}
+
 /**
  * Shut down and restart an object interface
  *
@@ -316,6 +351,40 @@ void intf_restart ( struct interface *intf, int rc ) {
        intf_reinit ( intf );
 }
 
+/**
+ * Shut down and restart multiple object interfaces
+ *
+ * @v intfs            Object interfaces
+ * @v rc               Reason for close
+ */
+void intfs_vrestart ( va_list intfs, int rc ) {
+       struct interface *intf;
+       va_list tmp;
+
+       /* Shut down all interfaces */
+       va_copy ( tmp, intfs );
+       intfs_vshutdown ( tmp, rc );
+       va_end ( tmp );
+
+       /* Reinitialise all interfaces */
+       while ( ( intf = va_arg ( intfs, struct interface * ) ) )
+               intf_reinit ( intf );
+}
+
+/**
+ * Shut down and restart multiple object interfaces
+ *
+ * @v rc               Reason for close
+ * @v ...              Object interfaces
+ */
+void intfs_restart ( int rc, ... ) {
+       va_list intfs;
+
+       va_start ( intfs, rc );
+       intfs_vrestart ( intfs, rc );
+       va_end ( intfs );
+}
+
 /**
  * Poke an object interface
  *
index ebb1b691114a366f56805db21266236bc1db496c..b65002c805f8ec5d107b7423d97af9e801978974 100644 (file)
@@ -10,6 +10,7 @@
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <stddef.h>
+#include <stdarg.h>
 #include <ipxe/refcnt.h>
 
 /** An object interface operation */
@@ -148,7 +149,11 @@ extern void intf_close ( struct interface *intf, int rc );
        typeof ( void ( object_type, int rc ) )
 
 extern void intf_shutdown ( struct interface *intf, int rc );
+extern void intfs_vshutdown ( va_list intfs, int rc );
+extern void intfs_shutdown ( int rc, ... ) __attribute__ (( sentinel ));
 extern void intf_restart ( struct interface *intf, int rc );
+extern void intfs_vrestart ( va_list intfs, int rc );
+extern void intfs_restart ( int rc, ... ) __attribute__ (( sentinel ));
 
 extern void intf_poke ( struct interface *intf,
                        void ( type ) ( struct interface *intf ) );