Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/vfs_aio.c
Show First 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | |||||
static int aio_queue_file(struct file *fp, struct kaiocb *job); | static int aio_queue_file(struct file *fp, struct kaiocb *job); | ||||
static void aio_physwakeup(struct bio *bp); | static void aio_physwakeup(struct bio *bp); | ||||
static void aio_proc_rundown(void *arg, struct proc *p); | static void aio_proc_rundown(void *arg, struct proc *p); | ||||
static void aio_proc_rundown_exec(void *arg, struct proc *p, | static void aio_proc_rundown_exec(void *arg, struct proc *p, | ||||
struct image_params *imgp); | struct image_params *imgp); | ||||
static int aio_qphysio(struct proc *p, struct kaiocb *job); | static int aio_qphysio(struct proc *p, struct kaiocb *job); | ||||
static void aio_daemon(void *param); | static void aio_daemon(void *param); | ||||
static void aio_bio_done_notify(struct proc *userp, struct kaiocb *job); | static void aio_bio_done_notify(struct proc *userp, struct kaiocb *job); | ||||
static bool aio_clear_cancel_function_locked(struct kaiocb *job); | |||||
static int aio_kick(struct proc *userp); | static int aio_kick(struct proc *userp); | ||||
static void aio_kick_nowait(struct proc *userp); | static void aio_kick_nowait(struct proc *userp); | ||||
static void aio_kick_helper(void *context, int pending); | static void aio_kick_helper(void *context, int pending); | ||||
static int filt_aioattach(struct knote *kn); | static int filt_aioattach(struct knote *kn); | ||||
static void filt_aiodetach(struct knote *kn); | static void filt_aiodetach(struct knote *kn); | ||||
static int filt_aio(struct knote *kn, long hint); | static int filt_aio(struct knote *kn, long hint); | ||||
static int filt_lioattach(struct knote *kn); | static int filt_lioattach(struct knote *kn); | ||||
static void filt_liodetach(struct knote *kn); | static void filt_liodetach(struct knote *kn); | ||||
▲ Show 20 Lines • Show All 592 Lines • ▼ Show 20 Lines | if (job->jobflags & KAIOCB_CHECKSYNC) { | ||||
schedule_fsync = false; | schedule_fsync = false; | ||||
TAILQ_FOREACH_SAFE(sjob, &ki->kaio_syncqueue, list, sjobn) { | TAILQ_FOREACH_SAFE(sjob, &ki->kaio_syncqueue, list, sjobn) { | ||||
if (job->fd_file != sjob->fd_file || | if (job->fd_file != sjob->fd_file || | ||||
job->seqno >= sjob->seqno) | job->seqno >= sjob->seqno) | ||||
continue; | continue; | ||||
if (--sjob->pending > 0) | if (--sjob->pending > 0) | ||||
continue; | continue; | ||||
TAILQ_REMOVE(&ki->kaio_syncqueue, sjob, list); | TAILQ_REMOVE(&ki->kaio_syncqueue, sjob, list); | ||||
if (!aio_clear_cancel_function(sjob)) | if (!aio_clear_cancel_function_locked(sjob)) | ||||
continue; | continue; | ||||
TAILQ_INSERT_TAIL(&ki->kaio_syncready, sjob, list); | TAILQ_INSERT_TAIL(&ki->kaio_syncready, sjob, list); | ||||
schedule_fsync = true; | schedule_fsync = true; | ||||
} | } | ||||
if (schedule_fsync) | if (schedule_fsync) | ||||
taskqueue_enqueue(taskqueue_aiod_kick, | taskqueue_enqueue(taskqueue_aiod_kick, | ||||
&ki->kaio_sync_task); | &ki->kaio_sync_task); | ||||
} | } | ||||
Show All 31 Lines | aio_cancel_cleared(struct kaiocb *job) | ||||
* aio_clear_cancel_function() was called and set this flag | * aio_clear_cancel_function() was called and set this flag | ||||
* ensuring this check sees an up-to-date value. However, | * ensuring this check sees an up-to-date value. However, | ||||
* there is no way to assert that. | * there is no way to assert that. | ||||
*/ | */ | ||||
ki = job->userproc->p_aioinfo; | ki = job->userproc->p_aioinfo; | ||||
return ((job->jobflags & KAIOCB_CLEARED) != 0); | return ((job->jobflags & KAIOCB_CLEARED) != 0); | ||||
} | } | ||||
bool | static bool | ||||
aio_clear_cancel_function(struct kaiocb *job) | aio_clear_cancel_function_locked(struct kaiocb *job) | ||||
{ | { | ||||
struct kaioinfo *ki; | |||||
ki = job->userproc->p_aioinfo; | AIO_LOCK_ASSERT(job->userproc->p_aioinfo, MA_OWNED); | ||||
AIO_LOCK(ki); | |||||
MPASS(job->cancel_fn != NULL); | MPASS(job->cancel_fn != NULL); | ||||
if (job->jobflags & KAIOCB_CANCELLING) { | if (job->jobflags & KAIOCB_CANCELLING) { | ||||
job->jobflags |= KAIOCB_CLEARED; | job->jobflags |= KAIOCB_CLEARED; | ||||
AIO_UNLOCK(ki); | |||||
return (false); | return (false); | ||||
} | } | ||||
job->cancel_fn = NULL; | job->cancel_fn = NULL; | ||||
AIO_UNLOCK(ki); | |||||
return (true); | return (true); | ||||
} | } | ||||
bool | bool | ||||
aio_set_cancel_function(struct kaiocb *job, aio_cancel_fn_t *func) | aio_clear_cancel_function(struct kaiocb *job) | ||||
{ | { | ||||
struct kaioinfo *ki; | struct kaioinfo *ki; | ||||
bool ret; | |||||
ki = job->userproc->p_aioinfo; | ki = job->userproc->p_aioinfo; | ||||
AIO_LOCK(ki); | AIO_LOCK(ki); | ||||
if (job->jobflags & KAIOCB_CANCELLED) { | ret = aio_clear_cancel_function_locked(job); | ||||
AIO_UNLOCK(ki); | AIO_UNLOCK(ki); | ||||
return (false); | return (ret); | ||||
} | } | ||||
static bool | |||||
aio_set_cancel_function_locked(struct kaiocb *job, aio_cancel_fn_t *func) | |||||
{ | |||||
AIO_LOCK_ASSERT(job->userproc->p_aioinfo, MA_OWNED); | |||||
if (job->jobflags & KAIOCB_CANCELLED) | |||||
return (false); | |||||
job->cancel_fn = func; | job->cancel_fn = func; | ||||
AIO_UNLOCK(ki); | |||||
return (true); | return (true); | ||||
} | } | ||||
bool | |||||
aio_set_cancel_function(struct kaiocb *job, aio_cancel_fn_t *func) | |||||
{ | |||||
struct kaioinfo *ki; | |||||
bool ret; | |||||
ki = job->userproc->p_aioinfo; | |||||
AIO_LOCK(ki); | |||||
ret = aio_set_cancel_function_locked(job, func); | |||||
AIO_UNLOCK(ki); | |||||
return (ret); | |||||
} | |||||
void | void | ||||
aio_complete(struct kaiocb *job, long status, int error) | aio_complete(struct kaiocb *job, long status, int error) | ||||
{ | { | ||||
struct kaioinfo *ki; | struct kaioinfo *ki; | ||||
struct proc *userp; | struct proc *userp; | ||||
job->uaiocb._aiocb_private.error = error; | job->uaiocb._aiocb_private.error = error; | ||||
job->uaiocb._aiocb_private.status = status; | job->uaiocb._aiocb_private.status = status; | ||||
▲ Show 20 Lines • Show All 638 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
aio_cancel_sync(struct kaiocb *job) | aio_cancel_sync(struct kaiocb *job) | ||||
{ | { | ||||
struct kaioinfo *ki; | struct kaioinfo *ki; | ||||
ki = job->userproc->p_aioinfo; | ki = job->userproc->p_aioinfo; | ||||
mtx_lock(&aio_job_mtx); | AIO_LOCK(ki); | ||||
if (!aio_cancel_cleared(job)) | if (!aio_cancel_cleared(job)) | ||||
TAILQ_REMOVE(&ki->kaio_syncqueue, job, list); | TAILQ_REMOVE(&ki->kaio_syncqueue, job, list); | ||||
mtx_unlock(&aio_job_mtx); | AIO_UNLOCK(ki); | ||||
aio_cancel(job); | aio_cancel(job); | ||||
} | } | ||||
int | int | ||||
aio_queue_file(struct file *fp, struct kaiocb *job) | aio_queue_file(struct file *fp, struct kaiocb *job) | ||||
{ | { | ||||
struct aioliojob *lj; | struct aioliojob *lj; | ||||
struct kaioinfo *ki; | struct kaioinfo *ki; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { | ||||
if (job2->fd_file == job->fd_file && | if (job2->fd_file == job->fd_file && | ||||
job2->uaiocb.aio_lio_opcode != LIO_SYNC && | job2->uaiocb.aio_lio_opcode != LIO_SYNC && | ||||
job2->seqno < job->seqno) { | job2->seqno < job->seqno) { | ||||
job2->jobflags |= KAIOCB_CHECKSYNC; | job2->jobflags |= KAIOCB_CHECKSYNC; | ||||
job->pending++; | job->pending++; | ||||
} | } | ||||
} | } | ||||
if (job->pending != 0) { | if (job->pending != 0) { | ||||
if (!aio_set_cancel_function(job, aio_cancel_sync)) { | if (!aio_set_cancel_function_locked(job, | ||||
aio_cancel_sync)) { | |||||
AIO_UNLOCK(ki); | AIO_UNLOCK(ki); | ||||
aio_cancel(job); | aio_cancel(job); | ||||
return (0); | return (0); | ||||
} | } | ||||
TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list); | TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list); | ||||
AIO_UNLOCK(ki); | AIO_UNLOCK(ki); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,249 Lines • Show Last 20 Lines |