Index: stable/11/lib/librt/Symbol.map =================================================================== --- stable/11/lib/librt/Symbol.map (revision 322891) +++ stable/11/lib/librt/Symbol.map (revision 322892) @@ -1,74 +1,75 @@ /* * $FreeBSD$ */ FBSD_1.0 { aio_read; aio_write; aio_return; aio_waitcomplete; aio_fsync; mq_open; mq_close; mq_notify; mq_getattr; mq_setattr; mq_timedreceive; mq_timedsend; mq_unlink; mq_send; mq_receive; timer_create; timer_delete; timer_gettime; timer_settime; timer_getoverrun; }; FBSD_1.5 { + lio_listio; mq_getfd_np; timer_oshandle_np; }; FBSDprivate_1.0 { _aio_read; _aio_write; _aio_return; _aio_waitcomplete; _aio_fsync; __aio_read; __aio_write; __aio_return; __aio_waitcomplete; __aio_fsync; _mq_open; _mq_close; _mq_notify; _mq_getattr; _mq_setattr; _mq_timedreceive; _mq_timedsend; _mq_unlink; _mq_send; _mq_receive; __mq_open; __mq_close; __mq_notify; __mq_getattr; __mq_setattr; __mq_timedreceive; __mq_timedsend; __mq_unlink; __mq_send; __mq_receive; _timer_create; _timer_delete; _timer_gettime; _timer_settime; _timer_getoverrun; __timer_create; __timer_delete; __timer_gettime; __timer_settime; __timer_getoverrun; }; Index: stable/11/lib/librt/aio.c =================================================================== --- stable/11/lib/librt/aio.c (revision 322891) +++ stable/11/lib/librt/aio.c (revision 322892) @@ -1,204 +1,235 @@ /* * Copyright (c) 2005 David Xu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ * */ #include #include #include #include #include "namespace.h" #include #include #include #include "sigev_thread.h" #include "un-namespace.h" __weak_reference(__aio_read, _aio_read); __weak_reference(__aio_read, aio_read); __weak_reference(__aio_write, _aio_write); __weak_reference(__aio_write, aio_write); __weak_reference(__aio_return, _aio_return); __weak_reference(__aio_return, aio_return); __weak_reference(__aio_waitcomplete, _aio_waitcomplete); __weak_reference(__aio_waitcomplete, aio_waitcomplete); __weak_reference(__aio_fsync, _aio_fsync); __weak_reference(__aio_fsync, aio_fsync); +__weak_reference(__lio_listio, lio_listio); typedef void (*aio_func)(union sigval val, struct aiocb *iocb); extern int __sys_aio_read(struct aiocb *iocb); extern int __sys_aio_write(struct aiocb *iocb); extern ssize_t __sys_aio_waitcomplete(struct aiocb **iocbp, struct timespec *timeout); extern ssize_t __sys_aio_return(struct aiocb *iocb); extern int __sys_aio_error(struct aiocb *iocb); extern int __sys_aio_fsync(int op, struct aiocb *iocb); +extern int __sys_lio_listio(int mode, struct aiocb * const list[], int nent, + struct sigevent *sig); static void aio_dispatch(struct sigev_node *sn) { aio_func f = sn->sn_func; f(sn->sn_value, (struct aiocb *)sn->sn_id); } static int -aio_sigev_alloc(struct aiocb *iocb, struct sigev_node **sn, - struct sigevent *saved_ev) +aio_sigev_alloc(sigev_id_t id, struct sigevent *sigevent, + struct sigev_node **sn, struct sigevent *saved_ev) { if (__sigev_check_init()) { /* This might be that thread library is not enabled. */ errno = EINVAL; return (-1); } - *sn = __sigev_alloc(SI_ASYNCIO, &iocb->aio_sigevent, NULL, 1); + *sn = __sigev_alloc(SI_ASYNCIO, sigevent, NULL, 1); if (*sn == NULL) { errno = EAGAIN; return (-1); } - *saved_ev = iocb->aio_sigevent; - (*sn)->sn_id = (sigev_id_t)iocb; - __sigev_get_sigevent(*sn, &iocb->aio_sigevent, (*sn)->sn_id); + *saved_ev = *sigevent; + (*sn)->sn_id = id; + __sigev_get_sigevent(*sn, sigevent, (*sn)->sn_id); (*sn)->sn_dispatch = aio_dispatch; __sigev_list_lock(); __sigev_register(*sn); __sigev_list_unlock(); return (0); } static int aio_io(struct aiocb *iocb, int (*sysfunc)(struct aiocb *iocb)) { struct sigev_node *sn; struct sigevent saved_ev; int ret, err; if (iocb->aio_sigevent.sigev_notify != SIGEV_THREAD) { ret = sysfunc(iocb); return (ret); } - ret = aio_sigev_alloc(iocb, &sn, &saved_ev); + ret = aio_sigev_alloc((sigev_id_t)iocb, &iocb->aio_sigevent, &sn, + &saved_ev); if (ret) return (ret); ret = sysfunc(iocb); iocb->aio_sigevent = saved_ev; if (ret != 0) { err = errno; __sigev_list_lock(); __sigev_delete_node(sn); __sigev_list_unlock(); errno = err; } return (ret); } int __aio_read(struct aiocb *iocb) { return aio_io(iocb, &__sys_aio_read); } int __aio_write(struct aiocb *iocb) { return aio_io(iocb, &__sys_aio_write); } ssize_t __aio_waitcomplete(struct aiocb **iocbp, struct timespec *timeout) { ssize_t ret; int err; ret = __sys_aio_waitcomplete(iocbp, timeout); if (*iocbp) { if ((*iocbp)->aio_sigevent.sigev_notify == SIGEV_THREAD) { err = errno; __sigev_list_lock(); __sigev_delete(SI_ASYNCIO, (sigev_id_t)(*iocbp)); __sigev_list_unlock(); errno = err; } } return (ret); } ssize_t __aio_return(struct aiocb *iocb) { if (iocb->aio_sigevent.sigev_notify == SIGEV_THREAD) { if (__sys_aio_error(iocb) == EINPROGRESS) { /* * Fail with EINVAL to match the semantics of * __sys_aio_return() for an in-progress * request. */ errno = EINVAL; return (-1); } __sigev_list_lock(); __sigev_delete(SI_ASYNCIO, (sigev_id_t)iocb); __sigev_list_unlock(); } return __sys_aio_return(iocb); } int __aio_fsync(int op, struct aiocb *iocb) { struct sigev_node *sn; struct sigevent saved_ev; int ret, err; if (iocb->aio_sigevent.sigev_notify != SIGEV_THREAD) return __sys_aio_fsync(op, iocb); - ret = aio_sigev_alloc(iocb, &sn, &saved_ev); + ret = aio_sigev_alloc((sigev_id_t)iocb, &iocb->aio_sigevent, &sn, + &saved_ev); if (ret) return (ret); ret = __sys_aio_fsync(op, iocb); iocb->aio_sigevent = saved_ev; + if (ret != 0) { + err = errno; + __sigev_list_lock(); + __sigev_delete_node(sn); + __sigev_list_unlock(); + errno = err; + } + return (ret); +} + +int +__lio_listio(int mode, struct aiocb * const list[], int nent, + struct sigevent *sig) +{ + struct sigev_node *sn; + struct sigevent saved_ev; + int ret, err; + + if (sig == NULL || sig->sigev_notify != SIGEV_THREAD) + return (__sys_lio_listio(mode, list, nent, sig)); + + ret = aio_sigev_alloc((sigev_id_t)list, sig, &sn, &saved_ev); + if (ret) + return (ret); + ret = __sys_lio_listio(mode, list, nent, sig); + *sig = saved_ev; if (ret != 0) { err = errno; __sigev_list_lock(); __sigev_delete_node(sn); __sigev_list_unlock(); errno = err; } return (ret); } Index: stable/11/tests/sys/aio/lio_test.c =================================================================== --- stable/11/tests/sys/aio/lio_test.c (revision 322891) +++ stable/11/tests/sys/aio/lio_test.c (revision 322892) @@ -1,145 +1,145 @@ /*- * Copyright (c) 2017 Spectra Logic Corp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include "freebsd_test_suite/macros.h" static sem_t completions; static void handler(int sig __unused) { ATF_REQUIRE_EQ(0, sem_post(&completions)); } static void thr_handler(union sigval sv __unused) { ATF_REQUIRE_EQ(0, sem_post(&completions)); } /* With LIO_WAIT, an empty lio_listio should return immediately */ ATF_TC_WITHOUT_HEAD(lio_listio_empty_wait); ATF_TC_BODY(lio_listio_empty_wait, tc) { struct aiocb *list = NULL; ATF_REQUIRE_EQ(0, lio_listio(LIO_WAIT, &list, 0, NULL)); } /* * With LIO_NOWAIT, an empty lio_listio should send completion notification * immediately */ ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait_kevent); ATF_TC_BODY(lio_listio_empty_nowait_kevent, tc) { struct aiocb *list = NULL; struct sigevent sev; struct kevent kq_returned; int kq, result; void *udata = (void*)0xdeadbeefdeadbeef; atf_tc_expect_timeout("Bug 220398 - lio_listio(2) never sends" " asynchronous notification if nent==0"); kq = kqueue(); ATF_REQUIRE(kq > 0); sev.sigev_notify = SIGEV_KEVENT; sev.sigev_notify_kqueue = kq; sev.sigev_value.sival_ptr = udata; ATF_REQUIRE_EQ(0, lio_listio(LIO_NOWAIT, &list, 0, &sev)); result = kevent(kq, NULL, 0, &kq_returned, 1, NULL); ATF_REQUIRE_MSG(result == 1, "Never got completion notification"); ATF_REQUIRE_EQ((uintptr_t)list, kq_returned.ident); ATF_REQUIRE_EQ(EVFILT_LIO, kq_returned.filter); ATF_REQUIRE_EQ(udata, kq_returned.udata); } /* * With LIO_NOWAIT, an empty lio_listio should send completion notification * immediately */ ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait_signal); ATF_TC_BODY(lio_listio_empty_nowait_signal, tc) { struct aiocb *list = NULL; struct sigevent sev; atf_tc_expect_timeout("Bug 220398 - lio_listio(2) never sends" "asynchronous notification if nent==0"); ATF_REQUIRE_EQ(0, sem_init(&completions, false, 0)); sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGUSR1; ATF_REQUIRE(SIG_ERR != signal(SIGUSR1, handler)); ATF_REQUIRE_EQ(0, lio_listio(LIO_NOWAIT, &list, 0, &sev)); ATF_REQUIRE_EQ(0, sem_wait(&completions)); ATF_REQUIRE_EQ(0, sem_destroy(&completions)); } /* * With LIO_NOWAIT, an empty lio_listio should send completion notification * immediately */ ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait_thread); ATF_TC_BODY(lio_listio_empty_nowait_thread, tc) { struct aiocb *list = NULL; struct sigevent sev; - atf_tc_expect_fail("Bug 220459 - lio_listio(2) doesn't support" - " SIGEV_THREAD"); + atf_tc_expect_timeout("Bug 220398 - lio_listio(2) never sends" + "asynchronous notification if nent==0"); ATF_REQUIRE_EQ(0, sem_init(&completions, false, 0)); bzero(&sev, sizeof(sev)); sev.sigev_notify = SIGEV_THREAD; sev.sigev_notify_function = thr_handler; sev.sigev_notify_attributes = NULL; ATF_REQUIRE_MSG(0 == lio_listio(LIO_NOWAIT, &list, 0, &sev), "lio_listio: %s", strerror(errno)); ATF_REQUIRE_EQ(0, sem_wait(&completions)); ATF_REQUIRE_EQ(0, sem_destroy(&completions)); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, lio_listio_empty_nowait_kevent); ATF_TP_ADD_TC(tp, lio_listio_empty_nowait_signal); ATF_TP_ADD_TC(tp, lio_listio_empty_nowait_thread); ATF_TP_ADD_TC(tp, lio_listio_empty_wait); return (atf_no_error()); } Index: stable/11 =================================================================== --- stable/11 (revision 322891) +++ stable/11 (revision 322892) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r321332