#define pr_fmt(fmt) …
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/aio_abi.h>
#include <linux/export.h>
#include <linux/syscalls.h>
#include <linux/backing-dev.h>
#include <linux/refcount.h>
#include <linux/uio.h>
#include <linux/sched/signal.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/aio.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
#include <linux/security.h>
#include <linux/eventfd.h>
#include <linux/blkdev.h>
#include <linux/compat.h>
#include <linux/migrate.h>
#include <linux/ramfs.h>
#include <linux/percpu-refcount.h>
#include <linux/mount.h>
#include <linux/pseudo_fs.h>
#include <linux/uaccess.h>
#include <linux/nospec.h>
#include "internal.h"
#define KIOCB_KEY …
#define AIO_RING_MAGIC …
#define AIO_RING_COMPAT_FEATURES …
#define AIO_RING_INCOMPAT_FEATURES …
struct aio_ring { … };
#define AIO_PLUG_THRESHOLD …
#define AIO_RING_PAGES …
struct kioctx_table { … };
struct kioctx_cpu { … };
struct ctx_rq_wait { … };
struct kioctx { … };
struct fsync_iocb { … };
struct poll_iocb { … };
struct aio_kiocb { … };
static DEFINE_SPINLOCK(aio_nr_lock);
static unsigned long aio_nr;
static unsigned long aio_max_nr = …;
#ifdef CONFIG_SYSCTL
static struct ctl_table aio_sysctls[] = …;
static void __init aio_sysctl_init(void)
{ … }
#else
#define aio_sysctl_init …
#endif
static struct kmem_cache *kiocb_cachep;
static struct kmem_cache *kioctx_cachep;
static struct vfsmount *aio_mnt;
static const struct file_operations aio_ring_fops;
static const struct address_space_operations aio_ctx_aops;
static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
{ … }
static int aio_init_fs_context(struct fs_context *fc)
{ … }
static int __init aio_setup(void)
{ … }
__initcall(aio_setup);
static void put_aio_ring_file(struct kioctx *ctx)
{ … }
static void aio_free_ring(struct kioctx *ctx)
{ … }
static int aio_ring_mremap(struct vm_area_struct *vma)
{ … }
static const struct vm_operations_struct aio_ring_vm_ops = …;
static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
{ … }
static const struct file_operations aio_ring_fops = …;
#if IS_ENABLED(CONFIG_MIGRATION)
static int aio_migrate_folio(struct address_space *mapping, struct folio *dst,
struct folio *src, enum migrate_mode mode)
{ … }
#else
#define aio_migrate_folio …
#endif
static const struct address_space_operations aio_ctx_aops = …;
static int aio_setup_ring(struct kioctx *ctx, unsigned int nr_events)
{ … }
#define AIO_EVENTS_PER_PAGE …
#define AIO_EVENTS_FIRST_PAGE …
#define AIO_EVENTS_OFFSET …
void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
{ … }
EXPORT_SYMBOL(…);
static void free_ioctx(struct work_struct *work)
{ … }
static void free_ioctx_reqs(struct percpu_ref *ref)
{ … }
static void free_ioctx_users(struct percpu_ref *ref)
{ … }
static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
{ … }
static void aio_nr_sub(unsigned nr)
{ … }
static struct kioctx *ioctx_alloc(unsigned nr_events)
{ … }
static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
struct ctx_rq_wait *wait)
{ … }
void exit_aio(struct mm_struct *mm)
{ … }
static void put_reqs_available(struct kioctx *ctx, unsigned nr)
{ … }
static bool __get_reqs_available(struct kioctx *ctx)
{ … }
static void refill_reqs_available(struct kioctx *ctx, unsigned head,
unsigned tail)
{ … }
static void user_refill_reqs_available(struct kioctx *ctx)
{ … }
static bool get_reqs_available(struct kioctx *ctx)
{ … }
static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
{ … }
static struct kioctx *lookup_ioctx(unsigned long ctx_id)
{ … }
static inline void iocb_destroy(struct aio_kiocb *iocb)
{ … }
struct aio_waiter { … };
static void aio_complete(struct aio_kiocb *iocb)
{ … }
static inline void iocb_put(struct aio_kiocb *iocb)
{ … }
static long aio_read_events_ring(struct kioctx *ctx,
struct io_event __user *event, long nr)
{ … }
static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr,
struct io_event __user *event, long *i)
{ … }
static long read_events(struct kioctx *ctx, long min_nr, long nr,
struct io_event __user *event,
ktime_t until)
{ … }
SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
{ … }
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_events, u32 __user *, ctx32p)
{ … }
#endif
SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
{ … }
static void aio_remove_iocb(struct aio_kiocb *iocb)
{ … }
static void aio_complete_rw(struct kiocb *kiocb, long res)
{ … }
static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb, int rw_type)
{ … }
static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
struct iovec **iovec, bool vectored, bool compat,
struct iov_iter *iter)
{ … }
static inline void aio_rw_done(struct kiocb *req, ssize_t ret)
{ … }
static int aio_read(struct kiocb *req, const struct iocb *iocb,
bool vectored, bool compat)
{ … }
static int aio_write(struct kiocb *req, const struct iocb *iocb,
bool vectored, bool compat)
{ … }
static void aio_fsync_work(struct work_struct *work)
{ … }
static int aio_fsync(struct fsync_iocb *req, const struct iocb *iocb,
bool datasync)
{ … }
static void aio_poll_put_work(struct work_struct *work)
{ … }
static bool poll_iocb_lock_wq(struct poll_iocb *req)
{ … }
static void poll_iocb_unlock_wq(struct poll_iocb *req)
{ … }
static void aio_poll_complete_work(struct work_struct *work)
{ … }
static int aio_poll_cancel(struct kiocb *iocb)
{ … }
static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
void *key)
{ … }
struct aio_poll_table { … };
static void
aio_poll_queue_proc(struct file *file, struct wait_queue_head *head,
struct poll_table_struct *p)
{ … }
static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb)
{ … }
static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb,
struct iocb __user *user_iocb, struct aio_kiocb *req,
bool compat)
{ … }
static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
bool compat)
{ … }
SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
struct iocb __user * __user *, iocbpp)
{ … }
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
int, nr, compat_uptr_t __user *, iocbpp)
{ … }
#endif
SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
struct io_event __user *, result)
{ … }
static long do_io_getevents(aio_context_t ctx_id,
long min_nr,
long nr,
struct io_event __user *events,
struct timespec64 *ts)
{ … }
#ifdef CONFIG_64BIT
SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
struct __kernel_timespec __user *, timeout)
{ … }
#endif
struct __aio_sigset { … };
SYSCALL_DEFINE6(io_pgetevents,
aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
struct __kernel_timespec __user *, timeout,
const struct __aio_sigset __user *, usig)
{ … }
#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
SYSCALL_DEFINE6(io_pgetevents_time32,
aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
struct old_timespec32 __user *, timeout,
const struct __aio_sigset __user *, usig)
{
struct __aio_sigset ksig = { NULL, };
struct timespec64 ts;
bool interrupted;
int ret;
if (timeout && unlikely(get_old_timespec32(&ts, timeout)))
return -EFAULT;
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
ret = set_user_sigmask(ksig.sigmask, ksig.sigsetsize);
if (ret)
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
interrupted = signal_pending(current);
restore_saved_sigmask_unless(interrupted);
if (interrupted && !ret)
ret = -ERESTARTNOHAND;
return ret;
}
#endif
#if defined(CONFIG_COMPAT_32BIT_TIME)
SYSCALL_DEFINE5(io_getevents_time32, __u32, ctx_id,
__s32, min_nr,
__s32, nr,
struct io_event __user *, events,
struct old_timespec32 __user *, timeout)
{ … }
#endif
#ifdef CONFIG_COMPAT
struct __compat_aio_sigset { … };
#if defined(CONFIG_COMPAT_32BIT_TIME)
COMPAT_SYSCALL_DEFINE6(io_pgetevents,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
struct io_event __user *, events,
struct old_timespec32 __user *, timeout,
const struct __compat_aio_sigset __user *, usig)
{ … }
#endif
COMPAT_SYSCALL_DEFINE6(io_pgetevents_time64,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
struct io_event __user *, events,
struct __kernel_timespec __user *, timeout,
const struct __compat_aio_sigset __user *, usig)
{ … }
#endif