hide kqueue_register from public view, and replace it w/ kqfd_register...
this eliminates a possible race in aio registering a kevent..
This commit is contained in:
parent
aeab19b21f
commit
4db71d27a1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162594
@ -88,6 +88,8 @@ TASKQUEUE_DEFINE_THREAD(kqueue);
|
||||
|
||||
static int kevent_copyout(void *arg, struct kevent *kevp, int count);
|
||||
static int kevent_copyin(void *arg, struct kevent *kevp, int count);
|
||||
static int kqueue_register(struct kqueue *kq, struct kevent *kev,
|
||||
struct thread *td, int waitok);
|
||||
static int kqueue_aquire(struct file *fp, struct kqueue **kqp);
|
||||
static void kqueue_release(struct kqueue *kq, int locked);
|
||||
static int kqueue_expand(struct kqueue *kq, struct filterops *fops,
|
||||
@ -783,11 +785,11 @@ kqueue_fo_release(int filt)
|
||||
}
|
||||
|
||||
/*
|
||||
* A ref to kq (obtained via kqueue_aquire) should be held. waitok will
|
||||
* A ref to kq (obtained via kqueue_aquire) must be held. waitok will
|
||||
* influence if memory allocation should wait. Make sure it is 0 if you
|
||||
* hold any mutexes.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int waitok)
|
||||
{
|
||||
struct filterops *fops;
|
||||
@ -1939,3 +1941,29 @@ knote_free(struct knote *kn)
|
||||
if (kn != NULL)
|
||||
uma_zfree(knote_zone, kn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the kev w/ the kq specified by fd.
|
||||
*/
|
||||
int
|
||||
kqfd_register(int fd, struct kevent *kev, struct thread *td, int waitok)
|
||||
{
|
||||
struct kqueue *kq;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
if ((error = fget(td, fd, &fp)) != 0)
|
||||
return (error);
|
||||
if ((error = kqueue_aquire(fp, &kq)) != 0)
|
||||
goto noaquire;
|
||||
|
||||
error = kqueue_register(kq, kev, td, waitok);
|
||||
|
||||
kqueue_release(kq, 0);
|
||||
|
||||
noaquire:
|
||||
if (fp != NULL)
|
||||
fdrop(fp, td);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1332,12 +1332,10 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
|
||||
struct aiocblist *aiocbe, *cb;
|
||||
struct kaioinfo *ki;
|
||||
struct kevent kev;
|
||||
struct kqueue *kq;
|
||||
struct file *kq_fp;
|
||||
struct sockbuf *sb;
|
||||
int opcode;
|
||||
int error;
|
||||
int fd;
|
||||
int fd, kqfd;
|
||||
int jid;
|
||||
|
||||
if (p->p_aioinfo == NULL)
|
||||
@ -1452,26 +1450,15 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
|
||||
goto aqueue_fail;
|
||||
}
|
||||
|
||||
if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_KEVENT)
|
||||
kev.ident = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue;
|
||||
else
|
||||
if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT)
|
||||
goto no_kqueue;
|
||||
error = fget(td, (u_int)kev.ident, &kq_fp);
|
||||
if (error)
|
||||
goto aqueue_fail;
|
||||
if (kq_fp->f_type != DTYPE_KQUEUE) {
|
||||
fdrop(kq_fp, td);
|
||||
error = EBADF;
|
||||
goto aqueue_fail;
|
||||
}
|
||||
kq = kq_fp->f_data;
|
||||
kqfd = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue;
|
||||
kev.ident = (uintptr_t)aiocbe->uuaiocb;
|
||||
kev.filter = EVFILT_AIO;
|
||||
kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1;
|
||||
kev.data = (intptr_t)aiocbe;
|
||||
kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sival_ptr;
|
||||
error = kqueue_register(kq, &kev, td, 1);
|
||||
fdrop(kq_fp, td);
|
||||
error = kqfd_register(kqfd, &kev, td, 1);
|
||||
aqueue_fail:
|
||||
if (error) {
|
||||
fdrop(fp, td);
|
||||
@ -1979,8 +1966,6 @@ do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev)
|
||||
struct kaioinfo *ki;
|
||||
struct aioliojob *lj;
|
||||
struct kevent kev;
|
||||
struct kqueue * kq;
|
||||
struct file *kq_fp;
|
||||
int nent;
|
||||
int error;
|
||||
int nerror;
|
||||
@ -2020,26 +2005,14 @@ do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev)
|
||||
|
||||
if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) {
|
||||
/* Assume only new style KEVENT */
|
||||
error = fget(td, lj->lioj_signal.sigev_notify_kqueue,
|
||||
&kq_fp);
|
||||
if (error) {
|
||||
uma_zfree(aiolio_zone, lj);
|
||||
return (error);
|
||||
}
|
||||
if (kq_fp->f_type != DTYPE_KQUEUE) {
|
||||
fdrop(kq_fp, td);
|
||||
uma_zfree(aiolio_zone, lj);
|
||||
return (EBADF);
|
||||
}
|
||||
kq = (struct kqueue *)kq_fp->f_data;
|
||||
kev.filter = EVFILT_LIO;
|
||||
kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1;
|
||||
kev.ident = (uintptr_t)uap->acb_list; /* something unique */
|
||||
kev.data = (intptr_t)lj;
|
||||
/* pass user defined sigval data */
|
||||
kev.udata = lj->lioj_signal.sigev_value.sival_ptr;
|
||||
error = kqueue_register(kq, &kev, td, 1);
|
||||
fdrop(kq_fp, td);
|
||||
error = kqfd_register(
|
||||
lj->lioj_signal.sigev_notify_kqueue, &kev, td, 1);
|
||||
if (error) {
|
||||
uma_zfree(aiolio_zone, lj);
|
||||
return (error);
|
||||
|
@ -218,8 +218,8 @@ extern void knlist_cleardel(struct knlist *knl, struct thread *td,
|
||||
#define knlist_delete(knl, td, islocked) \
|
||||
knlist_cleardel((knl), (td), (islocked), 1)
|
||||
extern void knote_fdclose(struct thread *p, int fd);
|
||||
extern int kqueue_register(struct kqueue *kq,
|
||||
struct kevent *kev, struct thread *p, int waitok);
|
||||
extern int kqfd_register(int fd, struct kevent *kev, struct thread *p,
|
||||
int waitok);
|
||||
extern int kqueue_add_filteropts(int filt, struct filterops *filtops);
|
||||
extern int kqueue_del_filteropts(int filt);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user