![Christoph Hellwig](/assets/img/avatar_default.png)
The AIO interface is fairly complex because it tries to allow filesystems to always work async and then wakeup a synchronous caller through aio_complete. It turns out that basically no one was doing this to avoid the complexity and context switches, and we've already fixed up the remaining users and can now get rid of this case. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
97 lines
2.6 KiB
C
97 lines
2.6 KiB
C
#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>
|
|
|
|
struct kioctx;
|
|
struct kiocb;
|
|
|
|
#define KIOCB_KEY 0
|
|
|
|
/*
|
|
* We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
|
|
* cancelled or completed (this makes a certain amount of sense because
|
|
* successful cancellation - io_cancel() - does deliver the completion to
|
|
* userspace).
|
|
*
|
|
* And since most things don't implement kiocb cancellation and we'd really like
|
|
* kiocb completion to be lockless when possible, we use ki_cancel to
|
|
* synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
|
|
* with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
|
|
*/
|
|
#define KIOCB_CANCELLED ((void *) (~0ULL))
|
|
|
|
typedef int (kiocb_cancel_fn)(struct kiocb *);
|
|
|
|
struct kiocb {
|
|
struct file *ki_filp;
|
|
struct kioctx *ki_ctx; /* NULL for sync ops */
|
|
kiocb_cancel_fn *ki_cancel;
|
|
void *private;
|
|
|
|
union {
|
|
void __user *user;
|
|
} ki_obj;
|
|
|
|
__u64 ki_user_data; /* user's data for completion */
|
|
loff_t ki_pos;
|
|
|
|
struct list_head ki_list; /* the aio core uses this
|
|
* for cancellation */
|
|
|
|
/*
|
|
* 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;
|
|
};
|
|
|
|
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,
|
|
};
|
|
}
|
|
|
|
/* prototypes */
|
|
#ifdef CONFIG_AIO
|
|
extern void aio_complete(struct kiocb *iocb, long res, long res2);
|
|
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 void aio_complete(struct kiocb *iocb, long res, long res2) { }
|
|
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 struct kiocb *list_kiocb(struct list_head *h)
|
|
{
|
|
return list_entry(h, struct kiocb, ki_list);
|
|
}
|
|
|
|
/* for sysctl: */
|
|
extern unsigned long aio_nr;
|
|
extern unsigned long aio_max_nr;
|
|
|
|
#endif /* __LINUX__AIO_H */
|