MEDIUM: connection: automatically disable polling on error

We absolutely want to disable FD polling after an error is detected,
otherwise the data layer has to do it and it's far from being obvious
at these layers.

The way we did it was a bit tricky in conn_update_*_polling and
conn_*_polling_changes. However it has almost no impact on performance
and code size both for the fast and slow path.

We'll now be able to remove some flag updates in the stream interface.
diff --git a/include/proto/connection.h b/include/proto/connection.h
index fa82051..2b655a7 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -55,7 +55,7 @@
  * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
  * in CO_FL_WAIT_*, and the sock layer expectations indicated by CO_FL_SOCK_*.
  * The connection flags are updated with the new flags at the end of the
- * operation.
+ * operation. Polling is totally disabled if an error was reported.
  */
 void conn_update_sock_polling(struct connection *c);
 
@@ -63,39 +63,53 @@
  * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
  * in CO_FL_WAIT_*, and the data layer expectations indicated by CO_FL_DATA_*.
  * The connection flags are updated with the new flags at the end of the
- * operation.
+ * operation. Polling is totally disabled if an error was reported.
  */
 void conn_update_data_polling(struct connection *c);
 
 /* inspects c->flags and returns non-zero if DATA ENA changes from the CURR ENA
- * or if the WAIT flags set new flags that were not in CURR POL.
+ * or if the WAIT flags set new flags that were not in CURR POL. Additionally,
+ * non-zero is also returned if an error was reported on the connection. This
+ * function is used quite often and is inlined. In order to proceed optimally
+ * with very little code and CPU cycles, the bits are arranged so that a change
+ * can be detected by a simple left shift, a xor, and a mask. This operation
+ * detects when POLL:DATA differs from WAIT:CURR. In order to detect the ERROR
+ * flag without additional work, we remove it from the copy of the original
+ * flags (unshifted) before doing the XOR. This operation is parallelized with
+ * the shift and does not induce additional cycles. This explains why we check
+ * the error bit shifted left in the mask. Last, the final operation is an AND
+ * which the compiler is able to replace with a TEST in boolean conditions. The
+ * result is that all these checks are done in 5-6 cycles only and less than 20
+ * bytes.
  */
 static inline unsigned int conn_data_polling_changes(const struct connection *c)
 {
-	/* bits are equally aligned between CURR and DATA, so it's a simple shift
-	 * operation to get the changes from bits P:D into bits W:C. We want to
-	 * detect any change on the ENA flag and to POL flags only when they were
-	 * not set. It's the fastest way to check for such a change.
-	 */
 	unsigned int f = c->flags << 2;
-	return (c->flags ^ f) &
-		(CO_FL_WAIT_WR|CO_FL_CURR_WR_ENA|CO_FL_WAIT_RD|CO_FL_CURR_RD_ENA) &
+	return ((c->flags & ~(CO_FL_ERROR << 2)) ^ f) &
+		((CO_FL_ERROR<<2)|CO_FL_WAIT_WR|CO_FL_CURR_WR_ENA|CO_FL_WAIT_RD|CO_FL_CURR_RD_ENA) &
 		~(f & (CO_FL_WAIT_WR|CO_FL_WAIT_RD));
 }
 
 /* inspects c->flags and returns non-zero if SOCK ENA changes from the CURR ENA
- * or if the WAIT flags set new flags that were not in CURR POL.
+ * or if the WAIT flags set new flags that were not in CURR POL. Additionally,
+ * non-zero is also returned if an error was reported on the connection. This
+ * function is used quite often and is inlined. In order to proceed optimally
+ * with very little code and CPU cycles, the bits are arranged so that a change
+ * can be detected by a simple left shift, a xor, and a mask. This operation
+ * detects when CURR:POLL differs from SOCK:WAIT. In order to detect the ERROR
+ * flag without additional work, we remove it from the copy of the original
+ * flags (unshifted) before doing the XOR. This operation is parallelized with
+ * the shift and does not induce additional cycles. This explains why we check
+ * the error bit shifted left in the mask. Last, the final operation is an AND
+ * which the compiler is able to replace with a TEST in boolean conditions. The
+ * result is that all these checks are done in 5-6 cycles only and less than 20
+ * bytes.
  */
 static inline unsigned int conn_sock_polling_changes(const struct connection *c)
 {
-	/* bits are equally aligned between CURR and SOCK, so it's a simple shift
-	 * operation to get the changes from bits C:P into bits S:W. We want to
-	 * detect any change on the ENA flag and to POL flags only when they were
-	 * not set. It's the fastest way to check for such a change.
-	 */
 	unsigned int f = c->flags << 2;
-	return (c->flags ^ f) &
-		(CO_FL_WAIT_WR|CO_FL_SOCK_WR_ENA|CO_FL_WAIT_RD|CO_FL_SOCK_RD_ENA) &
+	return ((c->flags & ~(CO_FL_ERROR << 2)) ^ f) &
+		((CO_FL_ERROR<<2)|CO_FL_WAIT_WR|CO_FL_SOCK_WR_ENA|CO_FL_WAIT_RD|CO_FL_SOCK_RD_ENA) &
 		~(f & (CO_FL_WAIT_WR|CO_FL_WAIT_RD));
 }
 
diff --git a/src/connection.c b/src/connection.c
index 40a24ee..6cb124f 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -139,12 +139,20 @@
  * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
  * in CO_FL_WAIT_*, and the data layer expectations indicated by CO_FL_DATA_*.
  * The connection flags are updated with the new flags at the end of the
- * operation.
+ * operation. Polling is totally disabled if an error was reported.
  */
 void conn_update_data_polling(struct connection *c)
 {
 	unsigned int f = c->flags;
 
+	if (unlikely(f & CO_FL_ERROR)) {
+		c->flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA |
+		              CO_FL_SOCK_RD_ENA | CO_FL_SOCK_WR_ENA |
+		              CO_FL_DATA_RD_ENA | CO_FL_DATA_WR_ENA);
+		fd_stop_both(c->t.sock.fd);
+		return;
+	}
+
 	/* update read status if needed */
 	if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_DATA_RD_ENA)) == CO_FL_CURR_RD_ENA)) {
 		f &= ~(CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL);
@@ -181,12 +189,20 @@
  * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
  * in CO_FL_WAIT_*, and the sock layer expectations indicated by CO_FL_SOCK_*.
  * The connection flags are updated with the new flags at the end of the
- * operation.
+ * operation. Polling is totally disabled if an error was reported.
  */
 void conn_update_sock_polling(struct connection *c)
 {
 	unsigned int f = c->flags;
 
+	if (unlikely(f & CO_FL_ERROR)) {
+		c->flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA |
+		              CO_FL_SOCK_RD_ENA | CO_FL_SOCK_WR_ENA |
+		              CO_FL_DATA_RD_ENA | CO_FL_DATA_WR_ENA);
+		fd_stop_both(c->t.sock.fd);
+		return;
+	}
+
 	/* update read status if needed */
 	if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_CURR_RD_ENA)) {
 		f &= ~(CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL);