+static int find_always(const struct io_plan *plan)
+{
+ for (size_t i = 0; i < num_always; i++)
+ if (always[i] == plan)
+ return i;
+ return -1;
+}
+
+static void remove_from_always(const struct io_plan *plan)
+{
+ int pos;
+
+ if (plan->status != IO_ALWAYS)
+ return;
+
+ pos = find_always(plan);
+ assert(pos >= 0);
+
+ /* Move last one down if we made a hole */
+ if (pos != num_always-1)
+ always[pos] = always[num_always-1];
+ num_always--;
+}
+
+bool backend_new_always(struct io_plan *plan)
+{
+ assert(find_always(plan) == -1);
+
+ if (!max_always) {
+ assert(num_always == 0);
+ always = tal_arr(NULL, struct io_plan *, 8);
+ if (!always)
+ return false;
+ max_always = 8;
+ }
+
+ if (num_always + 1 > max_always) {
+ size_t num = max_always * 2;
+
+ if (!tal_resize(&always, num))
+ return false;
+ max_always = num;
+ }
+
+ always[num_always++] = plan;
+ return true;
+}
+
+static void setup_pfd(struct io_conn *conn, struct pollfd *pfd)
+{
+ assert(pfd == &pollfds[conn->fd.backend_info]);
+
+ pfd->events = 0;
+ if (conn->plan[IO_IN].status == IO_POLLING_NOTSTARTED
+ || conn->plan[IO_IN].status == IO_POLLING_STARTED)
+ pfd->events |= POLLIN;
+ if (conn->plan[IO_OUT].status == IO_POLLING_NOTSTARTED
+ || conn->plan[IO_OUT].status == IO_POLLING_STARTED)
+ pfd->events |= POLLOUT;
+
+ if (pfd->events) {
+ pfd->fd = conn->fd.fd;
+ } else {
+ pfd->fd = -conn->fd.fd - 1;
+ }
+}
+
+void backend_new_plan(struct io_conn *conn)