Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_socket.c
Show First 20 Lines • Show All 802 Lines • ▼ Show 20 Lines | soo_aio_queue(struct file *fp, struct kaiocb *job) | ||||
struct sockbuf *sb; | struct sockbuf *sb; | ||||
int error; | int error; | ||||
so = fp->f_data; | so = fp->f_data; | ||||
error = (*so->so_proto->pr_usrreqs->pru_aio_queue)(so, job); | error = (*so->so_proto->pr_usrreqs->pru_aio_queue)(so, job); | ||||
if (error == 0) | if (error == 0) | ||||
return (0); | return (0); | ||||
/* Lock through the socket, since this may be a listening socket. */ | |||||
switch (job->uaiocb.aio_lio_opcode & (LIO_WRITE | LIO_READ)) { | switch (job->uaiocb.aio_lio_opcode & (LIO_WRITE | LIO_READ)) { | ||||
case LIO_READ: | case LIO_READ: | ||||
sb = &so->so_rcv; | sb = &so->so_rcv; | ||||
SOCK_RECVBUF_LOCK(so); | |||||
break; | break; | ||||
case LIO_WRITE: | case LIO_WRITE: | ||||
sb = &so->so_snd; | sb = &so->so_snd; | ||||
SOCK_SENDBUF_LOCK(so); | |||||
break; | break; | ||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
SOCKBUF_LOCK(sb); | if (SOLISTENING(so)) { | ||||
if (sb == &so->so_rcv) | |||||
SOCK_RECVBUF_UNLOCK(so); | |||||
else | |||||
SOCK_SENDBUF_UNLOCK(so); | |||||
return (EINVAL); | |||||
} | |||||
if (!aio_set_cancel_function(job, soo_aio_cancel)) | if (!aio_set_cancel_function(job, soo_aio_cancel)) | ||||
panic("new job was cancelled"); | panic("new job was cancelled"); | ||||
TAILQ_INSERT_TAIL(&sb->sb_aiojobq, job, list); | TAILQ_INSERT_TAIL(&sb->sb_aiojobq, job, list); | ||||
if (!(sb->sb_flags & SB_AIO_RUNNING)) { | if (!(sb->sb_flags & SB_AIO_RUNNING)) { | ||||
if (soaio_ready(so, sb)) | if (soaio_ready(so, sb)) | ||||
sowakeup_aio(so, sb); | sowakeup_aio(so, sb); | ||||
else | else | ||||
sb->sb_flags |= SB_AIO; | sb->sb_flags |= SB_AIO; | ||||
} | } | ||||
SOCKBUF_UNLOCK(sb); | SOCKBUF_UNLOCK(sb); | ||||
return (0); | return (0); | ||||
} | } |