struct io_wqe {
        struct {
                spinlock_t lock;
-               struct list_head work_list;
+               struct io_wq_work_list work_list;
                unsigned long hash_map;
                unsigned flags;
        } ____cacheline_aligned_in_smp;
 static inline bool io_wqe_run_queue(struct io_wqe *wqe)
        __must_hold(wqe->lock)
 {
-       if (!list_empty(&wqe->work_list) && !(wqe->flags & IO_WQE_FLAG_STALLED))
+       if (!wq_list_empty(&wqe->work_list) &&
+           !(wqe->flags & IO_WQE_FLAG_STALLED))
                return true;
        return false;
 }
 static struct io_wq_work *io_get_next_work(struct io_wqe *wqe, unsigned *hash)
        __must_hold(wqe->lock)
 {
+       struct io_wq_work_node *node, *prev;
        struct io_wq_work *work;
 
-       list_for_each_entry(work, &wqe->work_list, list) {
+       wq_list_for_each(node, prev, &wqe->work_list) {
+               work = container_of(node, struct io_wq_work, list);
+
                /* not hashed, can run anytime */
                if (!(work->flags & IO_WQ_WORK_HASHED)) {
-                       list_del(&work->list);
+                       wq_node_del(&wqe->work_list, node, prev);
                        return work;
                }
 
                *hash = work->flags >> IO_WQ_HASH_SHIFT;
                if (!(wqe->hash_map & BIT_ULL(*hash))) {
                        wqe->hash_map |= BIT_ULL(*hash);
-                       list_del(&work->list);
+                       wq_node_del(&wqe->work_list, node, prev);
                        return work;
                }
        }
                work = io_get_next_work(wqe, &hash);
                if (work)
                        __io_worker_busy(wqe, worker, work);
-               else if (!list_empty(&wqe->work_list))
+               else if (!wq_list_empty(&wqe->work_list))
                        wqe->flags |= IO_WQE_FLAG_STALLED;
 
                spin_unlock_irq(&wqe->lock);
 
        if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
                spin_lock_irq(&wqe->lock);
-               if (!list_empty(&wqe->work_list))
+               if (!wq_list_empty(&wqe->work_list))
                        io_worker_handle_work(worker);
                else
                        spin_unlock_irq(&wqe->lock);
        }
 
        spin_lock_irqsave(&wqe->lock, flags);
-       list_add_tail(&work->list, &wqe->work_list);
+       wq_list_add_tail(&work->list, &wqe->work_list);
        wqe->flags &= ~IO_WQE_FLAG_STALLED;
        spin_unlock_irqrestore(&wqe->lock, flags);
 
                .cancel = cancel,
                .caller_data = cancel_data,
        };
+       struct io_wq_work_node *node, *prev;
        struct io_wq_work *work;
        unsigned long flags;
        bool found = false;
 
        spin_lock_irqsave(&wqe->lock, flags);
-       list_for_each_entry(work, &wqe->work_list, list) {
+       wq_list_for_each(node, prev, &wqe->work_list) {
+               work = container_of(node, struct io_wq_work, list);
+
                if (cancel(work, cancel_data)) {
-                       list_del(&work->list);
+                       wq_node_del(&wqe->work_list, node, prev);
                        found = true;
                        break;
                }
 static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe,
                                            struct io_wq_work *cwork)
 {
+       struct io_wq_work_node *node, *prev;
        struct io_wq_work *work;
        unsigned long flags;
        bool found = false;
         * no completion will be posted for it.
         */
        spin_lock_irqsave(&wqe->lock, flags);
-       list_for_each_entry(work, &wqe->work_list, list) {
+       wq_list_for_each(node, prev, &wqe->work_list) {
+               work = container_of(node, struct io_wq_work, list);
+
                if (work == cwork) {
-                       list_del(&work->list);
+                       wq_node_del(&wqe->work_list, node, prev);
                        found = true;
                        break;
                }
                wqe->node = node;
                wqe->wq = wq;
                spin_lock_init(&wqe->lock);
-               INIT_LIST_HEAD(&wqe->work_list);
+               INIT_WQ_LIST(&wqe->work_list);
                INIT_HLIST_NULLS_HEAD(&wqe->free_list, 0);
                INIT_HLIST_NULLS_HEAD(&wqe->busy_list, 1);
                INIT_LIST_HEAD(&wqe->all_list);
 
        IO_WQ_CANCEL_NOTFOUND,  /* work not found */
 };
 
+struct io_wq_work_node {
+       struct io_wq_work_node *next;
+};
+
+struct io_wq_work_list {
+       struct io_wq_work_node *first;
+       struct io_wq_work_node *last;
+};
+
+static inline void wq_list_add_tail(struct io_wq_work_node *node,
+                                   struct io_wq_work_list *list)
+{
+       if (!list->first) {
+               list->first = list->last = node;
+       } else {
+               list->last->next = node;
+               list->last = node;
+       }
+}
+
+static inline void wq_node_del(struct io_wq_work_list *list,
+                              struct io_wq_work_node *node,
+                              struct io_wq_work_node *prev)
+{
+       if (node == list->first)
+               list->first = node->next;
+       if (node == list->last)
+               list->last = prev;
+       if (prev)
+               prev->next = node->next;
+}
+
+#define wq_list_for_each(pos, prv, head)                       \
+       for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next)
+
+#define wq_list_empty(list)    ((list)->first == NULL)
+#define INIT_WQ_LIST(list)     do {                            \
+       (list)->first = NULL;                                   \
+       (list)->last = NULL;                                    \
+} while (0)
+
 struct io_wq_work {
        union {
-               struct list_head list;
+               struct io_wq_work_node list;
                void *data;
        };
        void (*func)(struct io_wq_work **);
-       unsigned flags;
        struct files_struct *files;
+       unsigned flags;
 };
 
 #define INIT_IO_WORK(work, _func)                      \
        do {                                            \
+               (work)->list.next = NULL;               \
                (work)->func = _func;                   \
                (work)->flags = 0;                      \
                (work)->files = NULL;                   \