diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-11-26 11:59:32 -0700 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-11-26 15:02:56 -0700 |
commit | 6206f0e180d4eddc0a178f57120ab1b913701f6e (patch) | |
tree | 2b8867ea99fc8cfdf723e84b624417a966cd44cf /fs/io-wq.h | |
parent | 3fc50ab559f5ae400aa33bd0836b3602da7fa51b (diff) | |
download | linux-6206f0e180d4eddc0a178f57120ab1b913701f6e.tar.gz linux-6206f0e180d4eddc0a178f57120ab1b913701f6e.tar.bz2 linux-6206f0e180d4eddc0a178f57120ab1b913701f6e.zip |
io-wq: shrink io_wq_work a bit
Currently we're using 40 bytes for the io_wq_work structure, and 16 of
those is the doubly link list node. We don't need doubly linked lists,
we always add to tail to keep things ordered, and any other use case
is list traversal with deletion. For the deletion case, we can easily
support any node deletion by keeping track of the previous entry.
This shrinks io_wq_work to 32 bytes, and subsequently io_kiock from
io_uring to 216 to 208 bytes.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/io-wq.h')
-rw-r--r-- | fs/io-wq.h | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/fs/io-wq.h b/fs/io-wq.h index 5cd8c7697e88..600e0158cba7 100644 --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -22,18 +22,60 @@ enum io_wq_cancel { 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; \ |