summaryrefslogtreecommitdiff
path: root/include/linux/aio.h
blob: 985e664fb05d2277c0d878366b723269e7f1ccad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#ifndef __LINUX__AIO_H
#define __LINUX__AIO_H

#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/aio_abi.h>
#include <linux/uio.h>
#include <linux/rcupdate.h>
#include <linux/atomic.h>
#include <linux/batch_complete.h>

struct kioctx;
struct kiocb;
struct batch_complete;

/*
 * CANCELLATION
 *
 * SEMANTICS:
 *
 * Userspace may indicate (via io_cancel()) that they wish an iocb to be
 * cancelled. io_cancel() does nothing more than indicate that the iocb should
 * be cancelled if possible; it does not indicate whether it succeeded (nor will
 * it block).
 *
 * If cancellation does succeed, userspace should be informed by passing
 * -ECANCELLED to aio_complete(); userspace retrieves the io_event in the usual
 * manner.
 *
 * DRIVERS:
 *
 * A driver that wishes to support cancellation may (but does not have to)
 * implement a ki_cancel callback. If it doesn't implement a callback, it can
 * check if the kiocb has been marked as cancelled (with kiocb_cancelled()).
 * This is what the block layer does - when dequeuing requests it checks to see
 * if it's for a bio that's been marked as cancelled, and if so doesn't send it
 * to the device.
 *
 * Some drivers are going to need to kick something to notice that kiocb has
 * been cancelled - those will want to implement a ki_cancel function. The
 * callback could, say, issue a wakeup so that the thread processing the kiocb
 * can notice the cancellation - or it might do something else entirely.
 * kiocb->private is owned by the driver, so that ki_cancel can find the
 * driver's state.
 *
 * A driver must guarantee that a kiocb completes in bounded time if it's been
 * cancelled - this means that ki_cancel may have to guarantee forward progress.
 *
 * ki_cancel() may not call aio_complete().
 *
 * SYNCHRONIZATION:
 *
 * The aio code ensures that after aio_complete() returns, no ki_cancel function
 * can be called or still be executing. Thus, the driver should free whatever
 * kiocb->private points to after calling aio_complete().
 *
 * Drivers must not set kiocb->ki_cancel directly; they should use
 * kiocb_set_cancel_fn(), which guards against races with kiocb_cancel(). It
 * might be the case that userspace cancelled the iocb before the driver called
 * kiocb_set_cancel_fn() - in that case, kiocb_set_cancel_fn() will immediately
 * call the cancel function you passed it, and leave ki_cancel set to
 * KIOCB_CANCELLED.
 */

/*
 * Special values for kiocb->ki_cancel - these indicate that a kiocb has either
 * been cancelled, or has a ki_cancel function currently running.
 */
#define KIOCB_CANCELLED		((void *) (-1LL))
#define KIOCB_CANCELLING	((void *) (-2LL))

typedef int (kiocb_cancel_fn)(struct kiocb *);

struct kiocb {
	struct kiocb		*ki_next;	/* batch completion */

	/*
	 * If the aio_resfd field of the userspace iocb is not zero,
	 * this is the underlying eventfd context to deliver events to.
	 */
	struct eventfd_ctx	*ki_eventfd;
	struct file		*ki_filp;
	struct kioctx		*ki_ctx;	/* NULL for sync ops */
	void			*private;

	/* Only zero up to here in aio_get_req() */
	kiocb_cancel_fn		*ki_cancel;
	unsigned		ki_id;

	union {
		void __user		*user;
		struct task_struct	*tsk;
	} ki_obj;

	__u64			ki_user_data;	/* user's data for completion */
	long			ki_res;
	long			ki_res2;

	loff_t			ki_pos;
	size_t			ki_nbytes;	/* copy of iocb->aio_nbytes */
};

static inline bool kiocb_cancelled(struct kiocb *kiocb)
{
	return kiocb->ki_cancel == KIOCB_CANCELLED;
}

static inline bool is_sync_kiocb(struct kiocb *kiocb)
{
	return kiocb->ki_ctx == NULL;
}

static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
{
	*kiocb = (struct kiocb) {
			.ki_ctx = NULL,
			.ki_filp = filp,
			.ki_obj.tsk = current,
		};
}

/* prototypes */
#ifdef CONFIG_AIO
extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
extern void batch_complete_aio(struct batch_complete *batch);
extern void aio_complete_batch(struct kiocb *iocb, long res, long res2,
			       struct batch_complete *batch);
struct mm_struct;
extern void exit_aio(struct mm_struct *mm);
extern long do_io_submit(aio_context_t ctx_id, long nr,
			 struct iocb __user *__user *iocbpp, bool compat);
void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
#else
static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
static inline void batch_complete_aio(struct batch_complete *batch) { }
static inline void aio_complete_batch(struct kiocb *iocb, long res, long res2,
				      struct batch_complete *batch)
{
	return;
}
struct mm_struct;
static inline void exit_aio(struct mm_struct *mm) { }
static inline long do_io_submit(aio_context_t ctx_id, long nr,
				struct iocb __user * __user *iocbpp,
				bool compat) { return 0; }
static inline void kiocb_set_cancel_fn(struct kiocb *req,
				       kiocb_cancel_fn *cancel) { }
#endif /* CONFIG_AIO */

static inline void aio_complete(struct kiocb *iocb, long res, long res2)
{
	aio_complete_batch(iocb, res, res2, NULL);
}

/* for sysctl: */
extern unsigned long aio_nr;
extern unsigned long aio_max_nr;

#endif /* __LINUX__AIO_H */