io-wq.h 3.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
#ifndef INTERNAL_IO_WQ_H
#define INTERNAL_IO_WQ_H

struct io_wq;

enum {
	IO_WQ_WORK_CANCEL	= 1,
	IO_WQ_WORK_HAS_MM	= 2,
	IO_WQ_WORK_HASHED	= 4,
	IO_WQ_WORK_NEEDS_USER	= 8,
11
	IO_WQ_WORK_NEEDS_FILES	= 16,
12
	IO_WQ_WORK_UNBOUND	= 32,
13
	IO_WQ_WORK_INTERNAL	= 64,
14
	IO_WQ_WORK_CB		= 128,
15 16 17 18 19 20 21 22 23 24

	IO_WQ_HASH_SHIFT	= 24,	/* upper 8 bits are used for hash key */
};

enum io_wq_cancel {
	IO_WQ_CANCEL_OK,	/* cancelled before started */
	IO_WQ_CANCEL_RUNNING,	/* found, running, and attempted cancelled */
	IO_WQ_CANCEL_NOTFOUND,	/* work not found */
};

J
Jens Axboe 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
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)

66
struct io_wq_work {
67
	union {
J
Jens Axboe 已提交
68
		struct io_wq_work_node list;
69 70
		void *data;
	};
71
	void (*func)(struct io_wq_work **);
72
	struct files_struct *files;
J
Jens Axboe 已提交
73
	unsigned flags;
74 75 76 77
};

#define INIT_IO_WORK(work, _func)			\
	do {						\
J
Jens Axboe 已提交
78
		(work)->list.next = NULL;		\
79 80
		(work)->func = _func;			\
		(work)->flags = 0;			\
81
		(work)->files = NULL;			\
82 83
	} while (0)					\

84 85 86
typedef void (get_work_fn)(struct io_wq_work *);
typedef void (put_work_fn)(struct io_wq_work *);

87 88 89
struct io_wq_data {
	struct mm_struct *mm;
	struct user_struct *user;
90
	const struct cred *creds;
91 92 93 94 95 96

	get_work_fn *get_work;
	put_work_fn *put_work;
};

struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data);
97 98 99 100 101 102 103 104 105
void io_wq_destroy(struct io_wq *wq);

void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work);
void io_wq_enqueue_hashed(struct io_wq *wq, struct io_wq_work *work, void *val);
void io_wq_flush(struct io_wq *wq);

void io_wq_cancel_all(struct io_wq *wq);
enum io_wq_cancel io_wq_cancel_work(struct io_wq *wq, struct io_wq_work *cwork);

106 107 108 109 110
typedef bool (work_cancel_fn)(struct io_wq_work *, void *);

enum io_wq_cancel io_wq_cancel_cb(struct io_wq *wq, work_cancel_fn *cancel,
					void *data);

111 112 113 114 115 116 117 118 119 120 121 122
#if defined(CONFIG_IO_WQ)
extern void io_wq_worker_sleeping(struct task_struct *);
extern void io_wq_worker_running(struct task_struct *);
#else
static inline void io_wq_worker_sleeping(struct task_struct *tsk)
{
}
static inline void io_wq_worker_running(struct task_struct *tsk)
{
}
#endif

123 124 125 126
static inline bool io_wq_current_is_worker(void)
{
	return in_task() && (current->flags & PF_IO_WORKER);
}
127
#endif