changeset 10719:203f5727fba9

6887205 program using Posix aio gets unexpected SIGPOLL (SIGIO) signals
author Roger A. Faulkner <Roger.Faulkner@Sun.COM>
date Mon, 05 Oct 2009 12:36:45 -0700
parents 77613d4558c6
children c45747dcac4f
files usr/src/uts/common/os/aio.c usr/src/uts/common/os/aio_subr.c usr/src/uts/common/sys/aio_impl.h
diffstat 3 files changed, 56 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/os/aio.c	Mon Oct 05 11:35:02 2009 -0700
+++ b/usr/src/uts/common/os/aio.c	Mon Oct 05 12:36:45 2009 -0700
@@ -86,7 +86,7 @@
 static int aio_req_find(aio_result_t *, aio_req_t **);
 static int aio_hash_insert(struct aio_req_t *, aio_t *);
 static int aio_req_setup(aio_req_t **, aio_t *, aiocb_t *,
-    aio_result_t *, vnode_t *);
+    aio_result_t *, vnode_t *, int);
 static int aio_cleanup_thread(aio_t *);
 static aio_lio_t *aio_list_get(aio_result_t *);
 static void lio_set_uerror(void *, int);
@@ -106,7 +106,7 @@
 
 static int alioLF(int, void *, int, void *);
 static int aio_req_setupLF(aio_req_t **, aio_t *, aiocb64_32_t *,
-    aio_result_t *, vnode_t *);
+    aio_result_t *, vnode_t *, int);
 static int alio32(int, void *, int, void *);
 static int driver_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p);
 static int driver_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p);
@@ -1401,7 +1401,7 @@
 		}
 
 		error = aio_req_setup(&reqp, aiop, aiocb,
-		    &cbp->aio_resultp, vp);
+		    &cbp->aio_resultp, vp, 0);
 		if (error) {
 			releasef(aiocb->aio_fildes);
 			lio_set_uerror(&cbp->aio_resultp, error);
@@ -1982,14 +1982,14 @@
 	aiocb.aio_nbytes = bufsize;
 	aiocb.aio_offset = offset;
 	aiocb.aio_sigevent.sigev_notify = 0;
-	error = aio_req_setup(&reqp, aiop, &aiocb, resultp, vp);
+	error = aio_req_setup(&reqp, aiop, &aiocb, resultp, vp, 1);
 #else
 	aiocb64.aio_fildes = fdes;
 	aiocb64.aio_buf = (caddr32_t)bufp;
 	aiocb64.aio_nbytes = bufsize;
 	aiocb64.aio_offset = offset;
 	aiocb64.aio_sigevent.sigev_notify = 0;
-	error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, vp);
+	error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, vp, 1);
 #endif
 	if (error) {
 		releasef(fdes);
@@ -2172,9 +2172,9 @@
 		return (EBADFD);
 	}
 	if (run_mode == AIO_LARGEFILE)
-		error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, vp);
+		error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, vp, 0);
 	else
-		error = aio_req_setup(&reqp, aiop, &aiocb, resultp, vp);
+		error = aio_req_setup(&reqp, aiop, &aiocb, resultp, vp, 0);
 
 	if (error) {
 		releasef(fd);
@@ -2393,7 +2393,8 @@
 	aio_t 		*aiop,
 	aiocb_t 	*arg,
 	aio_result_t 	*resultp,
-	vnode_t		*vp)
+	vnode_t		*vp,
+	int		old_solaris_req)
 {
 	sigqueue_t	*sqp = NULL;
 	aio_req_t 	*reqp;
@@ -2439,6 +2440,11 @@
 	aiop->aio_pending++;
 	aiop->aio_outstanding++;
 	reqp->aio_req_flags = AIO_PENDING;
+	if (old_solaris_req) {
+		/* this is an old solaris aio request */
+		reqp->aio_req_flags |= AIO_SOLARIS;
+		aiop->aio_flags |= AIO_SOLARIS_REQ;
+	}
 	if (sigev->sigev_notify == SIGEV_THREAD ||
 	    sigev->sigev_notify == SIGEV_PORT)
 		aio_enq(&aiop->aio_portpending, reqp, 0);
@@ -3106,10 +3112,10 @@
 #ifdef	_LP64
 		aiocb_LFton(aiocb, &aiocb_n);
 		error = aio_req_setup(&reqp, aiop, &aiocb_n,
-		    (aio_result_t *)&cbp->aio_resultp, vp);
+		    (aio_result_t *)&cbp->aio_resultp, vp, 0);
 #else
 		error = aio_req_setupLF(&reqp, aiop, aiocb,
-		    (aio_result_t *)&cbp->aio_resultp, vp);
+		    (aio_result_t *)&cbp->aio_resultp, vp, 0);
 #endif  /* _LP64 */
 		if (error) {
 			releasef(aiocb->aio_fildes);
@@ -3284,7 +3290,8 @@
 	aio_t		*aiop,
 	aiocb64_32_t	*arg,
 	aio_result_t	*resultp,
-	vnode_t		*vp)
+	vnode_t		*vp,
+	int		old_solaris_req)
 {
 	sigqueue_t	*sqp = NULL;
 	aio_req_t	*reqp;
@@ -3330,6 +3337,11 @@
 	aiop->aio_pending++;
 	aiop->aio_outstanding++;
 	reqp->aio_req_flags = AIO_PENDING;
+	if (old_solaris_req) {
+		/* this is an old solaris aio request */
+		reqp->aio_req_flags |= AIO_SOLARIS;
+		aiop->aio_flags |= AIO_SOLARIS_REQ;
+	}
 	if (sigev->sigev_notify == SIGEV_THREAD ||
 	    sigev->sigev_notify == SIGEV_PORT)
 		aio_enq(&aiop->aio_portpending, reqp, 0);
@@ -3595,7 +3607,7 @@
 		}
 
 		error = aio_req_setup(&reqp, aiop, aiocb,
-		    (aio_result_t *)&cbp->aio_resultp, vp);
+		    (aio_result_t *)&cbp->aio_resultp, vp, 0);
 		if (error) {
 			releasef(aiocb->aio_fildes);
 			lio_set_uerror(&cbp->aio_resultp, error);
--- a/usr/src/uts/common/os/aio_subr.c	Mon Oct 05 11:35:02 2009 -0700
+++ b/usr/src/uts/common/os/aio_subr.c	Mon Oct 05 12:36:45 2009 -0700
@@ -388,9 +388,11 @@
 
 	/*
 	 * No need to set this flag for pollq, portq, lio requests.
-	 * Send a SIGIO signal when the process has a handler enabled.
+	 * If this is an old Solaris aio request, and the process has
+	 * a SIGIO signal handler enabled, then send a SIGIO signal.
 	 */
 	if (!sigev && !use_port && head == NULL &&
+	    (reqp->aio_req_flags & AIO_SOLARIS) &&
 	    (func = PTOU(p)->u_signal[SIGIO - 1]) != SIG_DFL &&
 	    (func != SIG_IGN)) {
 		send_signal = 1;
@@ -774,6 +776,12 @@
 	 */
 
 	mutex_enter(&aiop->aio_mutex);
+	/*
+	 * If there has never been an old solaris aio request
+	 * issued by this process, then do not send a SIGIO signal.
+	 */
+	if (!(aiop->aio_flags & AIO_SOLARIS_REQ))
+		signalled = 1;
 	cv_broadcast(&aiop->aio_waitcv);
 	mutex_exit(&aiop->aio_mutex);
 
--- a/usr/src/uts/common/sys/aio_impl.h	Mon Oct 05 11:35:02 2009 -0700
+++ b/usr/src/uts/common/sys/aio_impl.h	Mon Oct 05 12:36:45 2009 -0700
@@ -135,34 +135,36 @@
 /*
  * aio_flags for an aio_t.
  */
-#define	AIO_CLEANUP		0x1		/* do aio cleanup processing */
-#define	AIO_WAITN		0x2		/* aiowaitn in progress */
-#define	AIO_WAITN_PENDING	0x4		/* aiowaitn requests pending */
-#define	AIO_REQ_BLOCK		0x8		/* block new requests */
-#define	AIO_CLEANUP_PORT	0x10
-#define	AIO_DONE_ACTIVE		0x20		/* aio_done call in progress */
+#define	AIO_CLEANUP		0x0001	/* do aio cleanup processing */
+#define	AIO_WAITN		0x0002	/* aiowaitn in progress */
+#define	AIO_WAITN_PENDING	0x0004	/* aiowaitn requests pending */
+#define	AIO_REQ_BLOCK		0x0008	/* block new requests */
+#define	AIO_CLEANUP_PORT	0x0010
+#define	AIO_DONE_ACTIVE		0x0020	/* aio_done call in progress */
+#define	AIO_SOLARIS_REQ		0x0040	/* an old solaris aio req was issued */
 
 /*
  * aio_req_flags for an aio_req_t
  */
-#define	AIO_POLL	0x1			/* AIO_INPROGRESS is set */
-#define	AIO_PENDING	0x2			/* aio is in progress */
-#define	AIO_PHYSIODONE	0x4			/* unlocked phys pages */
-#define	AIO_COPYOUTDONE	0x8			/* result copied to userland */
-#define	AIO_NOTIFYQ	0x10			/* aio req is on the notifyq */
-#define	AIO_CLEANUPQ	0x20			/* aio req is on the cleanupq */
-#define	AIO_POLLQ	0x40			/* aio req is on the pollq */
-#define	AIO_DONEQ	0x80			/* aio req is on the doneq */
-#define	AIO_ZEROLEN	0x100			/* aio req is zero length */
-#define	AIO_PAGELOCKDONE	0x200		/* aio called as_pagelock() */
-#define	AIO_CLOSE_PORT	0x400		/* port is being closed */
-#define	AIO_SIGNALLED	0x800		/* process signalled by this req */
+#define	AIO_POLL	0x0001		/* AIO_INPROGRESS is set */
+#define	AIO_PENDING	0x0002		/* aio is in progress */
+#define	AIO_PHYSIODONE	0x0004		/* unlocked phys pages */
+#define	AIO_COPYOUTDONE	0x0008		/* result copied to userland */
+#define	AIO_NOTIFYQ	0x0010		/* aio req is on the notifyq */
+#define	AIO_CLEANUPQ	0x0020		/* aio req is on the cleanupq */
+#define	AIO_POLLQ	0x0040		/* aio req is on the pollq */
+#define	AIO_DONEQ	0x0080		/* aio req is on the doneq */
+#define	AIO_ZEROLEN	0x0100		/* aio req is zero length */
+#define	AIO_PAGELOCKDONE 0x0200		/* aio called as_pagelock() */
+#define	AIO_CLOSE_PORT	0x0400		/* port is being closed */
+#define	AIO_SIGNALLED	0x0800		/* process signalled by this req */
+#define	AIO_SOLARIS	0x1000		/* this is an old solaris aio req */
 
 /* flag argument of aio_cleanup() */
 
-#define	AIO_CLEANUP_POLL	0		/* check kaio poll queue */
-#define	AIO_CLEANUP_EXIT	1		/* aio_cleanup_exit() */
-#define	AIO_CLEANUP_THREAD	2		/* aio_cleanup_thread() */
+#define	AIO_CLEANUP_POLL	0	/* check kaio poll queue */
+#define	AIO_CLEANUP_EXIT	1	/* aio_cleanup_exit() */
+#define	AIO_CLEANUP_THREAD	2	/* aio_cleanup_thread() */
 
 /* functions exported by common/os/aio_subr.c */