Author: asomers
Date: Fri Aug 25 14:42:11 2017
New Revision: 322892
URL: https://svnweb.freebsd.org/changeset/base/322892

Log:
  MFC r321332:
  
  Implement SIGEV_THREAD notifications for lio_listio(2)
  
  Our man pages have always indicated that this was supported, but in fact the
  feature was never implemented for lio_listio(2).
  
  Reviewed by:  jhb, kib (earlier version)
  Sponsored by: Spectra Logic Corp
  Differential Revision:        https://reviews.freebsd.org/D11680

Modified:
  stable/11/lib/librt/Symbol.map
  stable/11/lib/librt/aio.c
  stable/11/tests/sys/aio/lio_test.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/librt/Symbol.map
==============================================================================
--- stable/11/lib/librt/Symbol.map      Fri Aug 25 14:37:23 2017        
(r322891)
+++ stable/11/lib/librt/Symbol.map      Fri Aug 25 14:42:11 2017        
(r322892)
@@ -26,6 +26,7 @@ FBSD_1.0 {
 };
 
 FBSD_1.5 {
+       lio_listio;
        mq_getfd_np;
        timer_oshandle_np;
 };

Modified: stable/11/lib/librt/aio.c
==============================================================================
--- stable/11/lib/librt/aio.c   Fri Aug 25 14:37:23 2017        (r322891)
+++ stable/11/lib/librt/aio.c   Fri Aug 25 14:42:11 2017        (r322892)
@@ -49,6 +49,7 @@ __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);
 
@@ -58,6 +59,8 @@ extern ssize_t __sys_aio_waitcomplete(struct aiocb **i
 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)
@@ -68,8 +71,8 @@ aio_dispatch(struct sigev_node *sn)
 }
 
 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. */
@@ -77,15 +80,15 @@ aio_sigev_alloc(struct aiocb *iocb, struct sigev_node 
                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();
@@ -107,7 +110,8 @@ aio_io(struct aiocb *iocb, int (*sysfunc)(struct aiocb
                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);
@@ -188,11 +192,38 @@ __aio_fsync(int op, struct aiocb *iocb)
        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();

Modified: stable/11/tests/sys/aio/lio_test.c
==============================================================================
--- stable/11/tests/sys/aio/lio_test.c  Fri Aug 25 14:37:23 2017        
(r322891)
+++ stable/11/tests/sys/aio/lio_test.c  Fri Aug 25 14:42:11 2017        
(r322892)
@@ -119,8 +119,8 @@ 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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to