17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
534709573Sraf * Common Development and Distribution License (the "License").
634709573Sraf * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
2134709573Sraf
227c478bd9Sstevel@tonic-gate /*
23dd1e66b6SVamsi Nagineni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * Kernel asynchronous I/O.
297c478bd9Sstevel@tonic-gate * This is only for raw devices now (as of Nov. 1993).
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/errno.h>
347c478bd9Sstevel@tonic-gate #include <sys/conf.h>
357c478bd9Sstevel@tonic-gate #include <sys/file.h>
367c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h>
377c478bd9Sstevel@tonic-gate #include <sys/unistd.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate #include <vm/as.h>
407c478bd9Sstevel@tonic-gate #include <vm/faultcode.h>
417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
427c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
437c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
447c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
457c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
467c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
477c478bd9Sstevel@tonic-gate #include <sys/aio_impl.h>
487c478bd9Sstevel@tonic-gate #include <sys/debug.h>
497c478bd9Sstevel@tonic-gate #include <sys/param.h>
507c478bd9Sstevel@tonic-gate #include <sys/systm.h>
517c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
527c478bd9Sstevel@tonic-gate #include <sys/fs/pxfs_ki.h>
537c478bd9Sstevel@tonic-gate #include <sys/contract/process_impl.h>
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate * external entry point.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate #ifdef _LP64
597c478bd9Sstevel@tonic-gate static int64_t kaioc(long, long, long, long, long, long);
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate static int kaio(ulong_t *, rval_t *);
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate #define AIO_64 0
657c478bd9Sstevel@tonic-gate #define AIO_32 1
667c478bd9Sstevel@tonic-gate #define AIO_LARGEFILE 2
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate * implementation specific functions (private)
707c478bd9Sstevel@tonic-gate */
717c478bd9Sstevel@tonic-gate #ifdef _LP64
7234709573Sraf static int alio(int, aiocb_t **, int, struct sigevent *);
737c478bd9Sstevel@tonic-gate #endif
747c478bd9Sstevel@tonic-gate static int aionotify(void);
757c478bd9Sstevel@tonic-gate static int aioinit(void);
767c478bd9Sstevel@tonic-gate static int aiostart(void);
777c478bd9Sstevel@tonic-gate static void alio_cleanup(aio_t *, aiocb_t **, int, int);
787c478bd9Sstevel@tonic-gate static int (*check_vp(struct vnode *, int))(vnode_t *, struct aio_req *,
797c478bd9Sstevel@tonic-gate cred_t *);
8034b3058fSpraks static void lio_set_error(aio_req_t *, int portused);
817c478bd9Sstevel@tonic-gate static aio_t *aio_aiop_alloc();
827c478bd9Sstevel@tonic-gate static int aio_req_alloc(aio_req_t **, aio_result_t *);
837c478bd9Sstevel@tonic-gate static int aio_lio_alloc(aio_lio_t **);
847c478bd9Sstevel@tonic-gate static aio_req_t *aio_req_done(void *);
857c478bd9Sstevel@tonic-gate static aio_req_t *aio_req_remove(aio_req_t *);
867c478bd9Sstevel@tonic-gate static int aio_req_find(aio_result_t *, aio_req_t **);
877c478bd9Sstevel@tonic-gate static int aio_hash_insert(struct aio_req_t *, aio_t *);
887c478bd9Sstevel@tonic-gate static int aio_req_setup(aio_req_t **, aio_t *, aiocb_t *,
89*d2749ac6SRoger A. Faulkner aio_result_t *, vnode_t *, int);
907c478bd9Sstevel@tonic-gate static int aio_cleanup_thread(aio_t *);
917c478bd9Sstevel@tonic-gate static aio_lio_t *aio_list_get(aio_result_t *);
927c478bd9Sstevel@tonic-gate static void lio_set_uerror(void *, int);
937c478bd9Sstevel@tonic-gate extern void aio_zerolen(aio_req_t *);
947c478bd9Sstevel@tonic-gate static int aiowait(struct timeval *, int, long *);
957c478bd9Sstevel@tonic-gate static int aiowaitn(void *, uint_t, uint_t *, timespec_t *);
967c478bd9Sstevel@tonic-gate static int aio_unlock_requests(caddr_t iocblist, int iocb_index,
977c478bd9Sstevel@tonic-gate aio_req_t *reqlist, aio_t *aiop, model_t model);
987c478bd9Sstevel@tonic-gate static int aio_reqlist_concat(aio_t *aiop, aio_req_t **reqlist, int max);
997c478bd9Sstevel@tonic-gate static int aiosuspend(void *, int, struct timespec *, int,
1007c478bd9Sstevel@tonic-gate long *, int);
1017c478bd9Sstevel@tonic-gate static int aliowait(int, void *, int, void *, int);
1027c478bd9Sstevel@tonic-gate static int aioerror(void *, int);
1037c478bd9Sstevel@tonic-gate static int aio_cancel(int, void *, long *, int);
1047c478bd9Sstevel@tonic-gate static int arw(int, int, char *, int, offset_t, aio_result_t *, int);
1057c478bd9Sstevel@tonic-gate static int aiorw(int, void *, int, int);
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate static int alioLF(int, void *, int, void *);
10834709573Sraf static int aio_req_setupLF(aio_req_t **, aio_t *, aiocb64_32_t *,
109*d2749ac6SRoger A. Faulkner aio_result_t *, vnode_t *, int);
1107c478bd9Sstevel@tonic-gate static int alio32(int, void *, int, void *);
1117c478bd9Sstevel@tonic-gate static int driver_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p);
1127c478bd9Sstevel@tonic-gate static int driver_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p);
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1157c478bd9Sstevel@tonic-gate static void aiocb_LFton(aiocb64_32_t *, aiocb_t *);
1167c478bd9Sstevel@tonic-gate void aiocb_32ton(aiocb32_t *, aiocb_t *);
1177c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate * implementation specific functions (external)
1217c478bd9Sstevel@tonic-gate */
1227c478bd9Sstevel@tonic-gate void aio_req_free(aio_t *, aio_req_t *);
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate * Event Port framework
1267c478bd9Sstevel@tonic-gate */
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate void aio_req_free_port(aio_t *, aio_req_t *);
1297c478bd9Sstevel@tonic-gate static int aio_port_callback(void *, int *, pid_t, int, void *);
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * This is the loadable module wrapper.
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
1357c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate #ifdef _LP64
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate static struct sysent kaio_sysent = {
1407c478bd9Sstevel@tonic-gate 6,
1417c478bd9Sstevel@tonic-gate SE_NOUNLOAD | SE_64RVAL | SE_ARGC,
1427c478bd9Sstevel@tonic-gate (int (*)())kaioc
1437c478bd9Sstevel@tonic-gate };
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1467c478bd9Sstevel@tonic-gate static struct sysent kaio_sysent32 = {
1477c478bd9Sstevel@tonic-gate 7,
1487c478bd9Sstevel@tonic-gate SE_NOUNLOAD | SE_64RVAL,
1497c478bd9Sstevel@tonic-gate kaio
1507c478bd9Sstevel@tonic-gate };
1517c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate #else /* _LP64 */
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate static struct sysent kaio_sysent = {
1567c478bd9Sstevel@tonic-gate 7,
1577c478bd9Sstevel@tonic-gate SE_NOUNLOAD | SE_32RVAL1,
1587c478bd9Sstevel@tonic-gate kaio
1597c478bd9Sstevel@tonic-gate };
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate #endif /* _LP64 */
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate * Module linkage information for the kernel.
1657c478bd9Sstevel@tonic-gate */
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate static struct modlsys modlsys = {
1687c478bd9Sstevel@tonic-gate &mod_syscallops,
1697c478bd9Sstevel@tonic-gate "kernel Async I/O",
1707c478bd9Sstevel@tonic-gate &kaio_sysent
1717c478bd9Sstevel@tonic-gate };
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1747c478bd9Sstevel@tonic-gate static struct modlsys modlsys32 = {
1757c478bd9Sstevel@tonic-gate &mod_syscallops32,
1767c478bd9Sstevel@tonic-gate "kernel Async I/O for 32 bit compatibility",
1777c478bd9Sstevel@tonic-gate &kaio_sysent32
1787c478bd9Sstevel@tonic-gate };
1797c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1837c478bd9Sstevel@tonic-gate MODREV_1,
1847c478bd9Sstevel@tonic-gate &modlsys,
1857c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1867c478bd9Sstevel@tonic-gate &modlsys32,
1877c478bd9Sstevel@tonic-gate #endif
1887c478bd9Sstevel@tonic-gate NULL
1897c478bd9Sstevel@tonic-gate };
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate int
_init(void)1927c478bd9Sstevel@tonic-gate _init(void)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate int retval;
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate if ((retval = mod_install(&modlinkage)) != 0)
1977c478bd9Sstevel@tonic-gate return (retval);
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate return (0);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate int
_fini(void)2037c478bd9Sstevel@tonic-gate _fini(void)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate int retval;
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate retval = mod_remove(&modlinkage);
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate return (retval);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2137c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate #ifdef _LP64
2197c478bd9Sstevel@tonic-gate static int64_t
kaioc(long a0,long a1,long a2,long a3,long a4,long a5)2207c478bd9Sstevel@tonic-gate kaioc(
2217c478bd9Sstevel@tonic-gate long a0,
2227c478bd9Sstevel@tonic-gate long a1,
2237c478bd9Sstevel@tonic-gate long a2,
2247c478bd9Sstevel@tonic-gate long a3,
2257c478bd9Sstevel@tonic-gate long a4,
2267c478bd9Sstevel@tonic-gate long a5)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate int error;
2297c478bd9Sstevel@tonic-gate long rval = 0;
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate switch ((int)a0 & ~AIO_POLL_BIT) {
2327c478bd9Sstevel@tonic-gate case AIOREAD:
2337c478bd9Sstevel@tonic-gate error = arw((int)a0, (int)a1, (char *)a2, (int)a3,
2347c478bd9Sstevel@tonic-gate (offset_t)a4, (aio_result_t *)a5, FREAD);
2357c478bd9Sstevel@tonic-gate break;
2367c478bd9Sstevel@tonic-gate case AIOWRITE:
2377c478bd9Sstevel@tonic-gate error = arw((int)a0, (int)a1, (char *)a2, (int)a3,
2387c478bd9Sstevel@tonic-gate (offset_t)a4, (aio_result_t *)a5, FWRITE);
2397c478bd9Sstevel@tonic-gate break;
2407c478bd9Sstevel@tonic-gate case AIOWAIT:
2417c478bd9Sstevel@tonic-gate error = aiowait((struct timeval *)a1, (int)a2, &rval);
2427c478bd9Sstevel@tonic-gate break;
2437c478bd9Sstevel@tonic-gate case AIOWAITN:
2447c478bd9Sstevel@tonic-gate error = aiowaitn((void *)a1, (uint_t)a2, (uint_t *)a3,
2457c478bd9Sstevel@tonic-gate (timespec_t *)a4);
2467c478bd9Sstevel@tonic-gate break;
2477c478bd9Sstevel@tonic-gate case AIONOTIFY:
2487c478bd9Sstevel@tonic-gate error = aionotify();
2497c478bd9Sstevel@tonic-gate break;
2507c478bd9Sstevel@tonic-gate case AIOINIT:
2517c478bd9Sstevel@tonic-gate error = aioinit();
2527c478bd9Sstevel@tonic-gate break;
2537c478bd9Sstevel@tonic-gate case AIOSTART:
2547c478bd9Sstevel@tonic-gate error = aiostart();
2557c478bd9Sstevel@tonic-gate break;
2567c478bd9Sstevel@tonic-gate case AIOLIO:
25734709573Sraf error = alio((int)a1, (aiocb_t **)a2, (int)a3,
2587c478bd9Sstevel@tonic-gate (struct sigevent *)a4);
2597c478bd9Sstevel@tonic-gate break;
2607c478bd9Sstevel@tonic-gate case AIOLIOWAIT:
2617c478bd9Sstevel@tonic-gate error = aliowait((int)a1, (void *)a2, (int)a3,
2627c478bd9Sstevel@tonic-gate (struct sigevent *)a4, AIO_64);
2637c478bd9Sstevel@tonic-gate break;
2647c478bd9Sstevel@tonic-gate case AIOSUSPEND:
2657c478bd9Sstevel@tonic-gate error = aiosuspend((void *)a1, (int)a2, (timespec_t *)a3,
2667c478bd9Sstevel@tonic-gate (int)a4, &rval, AIO_64);
2677c478bd9Sstevel@tonic-gate break;
2687c478bd9Sstevel@tonic-gate case AIOERROR:
2697c478bd9Sstevel@tonic-gate error = aioerror((void *)a1, AIO_64);
2707c478bd9Sstevel@tonic-gate break;
2717c478bd9Sstevel@tonic-gate case AIOAREAD:
2727c478bd9Sstevel@tonic-gate error = aiorw((int)a0, (void *)a1, FREAD, AIO_64);
2737c478bd9Sstevel@tonic-gate break;
2747c478bd9Sstevel@tonic-gate case AIOAWRITE:
2757c478bd9Sstevel@tonic-gate error = aiorw((int)a0, (void *)a1, FWRITE, AIO_64);
2767c478bd9Sstevel@tonic-gate break;
2777c478bd9Sstevel@tonic-gate case AIOCANCEL:
2787c478bd9Sstevel@tonic-gate error = aio_cancel((int)a1, (void *)a2, &rval, AIO_64);
2797c478bd9Sstevel@tonic-gate break;
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * The large file related stuff is valid only for
2837c478bd9Sstevel@tonic-gate * 32 bit kernel and not for 64 bit kernel
2847c478bd9Sstevel@tonic-gate * On 64 bit kernel we convert large file calls
2857c478bd9Sstevel@tonic-gate * to regular 64bit calls.
2867c478bd9Sstevel@tonic-gate */
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate default:
2897c478bd9Sstevel@tonic-gate error = EINVAL;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate if (error)
2927c478bd9Sstevel@tonic-gate return ((int64_t)set_errno(error));
2937c478bd9Sstevel@tonic-gate return (rval);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate #endif
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate static int
kaio(ulong_t * uap,rval_t * rvp)2987c478bd9Sstevel@tonic-gate kaio(
2997c478bd9Sstevel@tonic-gate ulong_t *uap,
3007c478bd9Sstevel@tonic-gate rval_t *rvp)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate long rval = 0;
3037c478bd9Sstevel@tonic-gate int error = 0;
3047c478bd9Sstevel@tonic-gate offset_t off;
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate rvp->r_vals = 0;
3087c478bd9Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN)
3097c478bd9Sstevel@tonic-gate off = ((u_offset_t)uap[5] << 32) | (u_offset_t)uap[4];
3107c478bd9Sstevel@tonic-gate #else
3117c478bd9Sstevel@tonic-gate off = ((u_offset_t)uap[4] << 32) | (u_offset_t)uap[5];
3127c478bd9Sstevel@tonic-gate #endif
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate switch (uap[0] & ~AIO_POLL_BIT) {
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate * It must be the 32 bit system call on 64 bit kernel
3177c478bd9Sstevel@tonic-gate */
3187c478bd9Sstevel@tonic-gate case AIOREAD:
3197c478bd9Sstevel@tonic-gate return (arw((int)uap[0], (int)uap[1], (char *)uap[2],
3207c478bd9Sstevel@tonic-gate (int)uap[3], off, (aio_result_t *)uap[6], FREAD));
3217c478bd9Sstevel@tonic-gate case AIOWRITE:
3227c478bd9Sstevel@tonic-gate return (arw((int)uap[0], (int)uap[1], (char *)uap[2],
3237c478bd9Sstevel@tonic-gate (int)uap[3], off, (aio_result_t *)uap[6], FWRITE));
3247c478bd9Sstevel@tonic-gate case AIOWAIT:
3257c478bd9Sstevel@tonic-gate error = aiowait((struct timeval *)uap[1], (int)uap[2],
3267c478bd9Sstevel@tonic-gate &rval);
3277c478bd9Sstevel@tonic-gate break;
3287c478bd9Sstevel@tonic-gate case AIOWAITN:
3297c478bd9Sstevel@tonic-gate error = aiowaitn((void *)uap[1], (uint_t)uap[2],
3307c478bd9Sstevel@tonic-gate (uint_t *)uap[3], (timespec_t *)uap[4]);
3317c478bd9Sstevel@tonic-gate break;
3327c478bd9Sstevel@tonic-gate case AIONOTIFY:
3337c478bd9Sstevel@tonic-gate return (aionotify());
3347c478bd9Sstevel@tonic-gate case AIOINIT:
3357c478bd9Sstevel@tonic-gate return (aioinit());
3367c478bd9Sstevel@tonic-gate case AIOSTART:
3377c478bd9Sstevel@tonic-gate return (aiostart());
3387c478bd9Sstevel@tonic-gate case AIOLIO:
3397c478bd9Sstevel@tonic-gate return (alio32((int)uap[1], (void *)uap[2], (int)uap[3],
3407c478bd9Sstevel@tonic-gate (void *)uap[4]));
3417c478bd9Sstevel@tonic-gate case AIOLIOWAIT:
3427c478bd9Sstevel@tonic-gate return (aliowait((int)uap[1], (void *)uap[2],
3437c478bd9Sstevel@tonic-gate (int)uap[3], (struct sigevent *)uap[4], AIO_32));
3447c478bd9Sstevel@tonic-gate case AIOSUSPEND:
3457c478bd9Sstevel@tonic-gate error = aiosuspend((void *)uap[1], (int)uap[2],
3467c478bd9Sstevel@tonic-gate (timespec_t *)uap[3], (int)uap[4],
3477c478bd9Sstevel@tonic-gate &rval, AIO_32);
3487c478bd9Sstevel@tonic-gate break;
3497c478bd9Sstevel@tonic-gate case AIOERROR:
3507c478bd9Sstevel@tonic-gate return (aioerror((void *)uap[1], AIO_32));
3517c478bd9Sstevel@tonic-gate case AIOAREAD:
3527c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1],
3537c478bd9Sstevel@tonic-gate FREAD, AIO_32));
3547c478bd9Sstevel@tonic-gate case AIOAWRITE:
3557c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1],
3567c478bd9Sstevel@tonic-gate FWRITE, AIO_32));
3577c478bd9Sstevel@tonic-gate case AIOCANCEL:
3587c478bd9Sstevel@tonic-gate error = (aio_cancel((int)uap[1], (void *)uap[2], &rval,
3597c478bd9Sstevel@tonic-gate AIO_32));
3607c478bd9Sstevel@tonic-gate break;
3617c478bd9Sstevel@tonic-gate case AIOLIO64:
3627c478bd9Sstevel@tonic-gate return (alioLF((int)uap[1], (void *)uap[2],
3637c478bd9Sstevel@tonic-gate (int)uap[3], (void *)uap[4]));
3647c478bd9Sstevel@tonic-gate case AIOLIOWAIT64:
3657c478bd9Sstevel@tonic-gate return (aliowait(uap[1], (void *)uap[2],
3667c478bd9Sstevel@tonic-gate (int)uap[3], (void *)uap[4], AIO_LARGEFILE));
3677c478bd9Sstevel@tonic-gate case AIOSUSPEND64:
3687c478bd9Sstevel@tonic-gate error = aiosuspend((void *)uap[1], (int)uap[2],
3697c478bd9Sstevel@tonic-gate (timespec_t *)uap[3], (int)uap[4], &rval,
3707c478bd9Sstevel@tonic-gate AIO_LARGEFILE);
3717c478bd9Sstevel@tonic-gate break;
3727c478bd9Sstevel@tonic-gate case AIOERROR64:
3737c478bd9Sstevel@tonic-gate return (aioerror((void *)uap[1], AIO_LARGEFILE));
3747c478bd9Sstevel@tonic-gate case AIOAREAD64:
3757c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1], FREAD,
3767c478bd9Sstevel@tonic-gate AIO_LARGEFILE));
3777c478bd9Sstevel@tonic-gate case AIOAWRITE64:
3787c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1], FWRITE,
3797c478bd9Sstevel@tonic-gate AIO_LARGEFILE));
3807c478bd9Sstevel@tonic-gate case AIOCANCEL64:
3817c478bd9Sstevel@tonic-gate error = (aio_cancel((int)uap[1], (void *)uap[2],
3827c478bd9Sstevel@tonic-gate &rval, AIO_LARGEFILE));
3837c478bd9Sstevel@tonic-gate break;
3847c478bd9Sstevel@tonic-gate default:
3857c478bd9Sstevel@tonic-gate return (EINVAL);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate rvp->r_val1 = rval;
3897c478bd9Sstevel@tonic-gate return (error);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate * wake up LWPs in this process that are sleeping in
3947c478bd9Sstevel@tonic-gate * aiowait().
3957c478bd9Sstevel@tonic-gate */
3967c478bd9Sstevel@tonic-gate static int
aionotify(void)3977c478bd9Sstevel@tonic-gate aionotify(void)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate aio_t *aiop;
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
4027c478bd9Sstevel@tonic-gate if (aiop == NULL)
4037c478bd9Sstevel@tonic-gate return (0);
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
4067c478bd9Sstevel@tonic-gate aiop->aio_notifycnt++;
4077c478bd9Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv);
4087c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate return (0);
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate static int
timeval2reltime(struct timeval * timout,timestruc_t * rqtime,timestruc_t ** rqtp,int * blocking)4147c478bd9Sstevel@tonic-gate timeval2reltime(struct timeval *timout, timestruc_t *rqtime,
4157c478bd9Sstevel@tonic-gate timestruc_t **rqtp, int *blocking)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
4187c478bd9Sstevel@tonic-gate struct timeval32 wait_time_32;
4197c478bd9Sstevel@tonic-gate #endif
4207c478bd9Sstevel@tonic-gate struct timeval wait_time;
4217c478bd9Sstevel@tonic-gate model_t model = get_udatamodel();
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate *rqtp = NULL;
4247c478bd9Sstevel@tonic-gate if (timout == NULL) { /* wait indefinitely */
4257c478bd9Sstevel@tonic-gate *blocking = 1;
4267c478bd9Sstevel@tonic-gate return (0);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate * Need to correctly compare with the -1 passed in for a user
4317c478bd9Sstevel@tonic-gate * address pointer, with both 32 bit and 64 bit apps.
4327c478bd9Sstevel@tonic-gate */
4337c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) {
4347c478bd9Sstevel@tonic-gate if ((intptr_t)timout == (intptr_t)-1) { /* don't wait */
4357c478bd9Sstevel@tonic-gate *blocking = 0;
4367c478bd9Sstevel@tonic-gate return (0);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate if (copyin(timout, &wait_time, sizeof (wait_time)))
4407c478bd9Sstevel@tonic-gate return (EFAULT);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
4437c478bd9Sstevel@tonic-gate else {
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * -1 from a 32bit app. It will not get sign extended.
4467c478bd9Sstevel@tonic-gate * don't wait if -1.
4477c478bd9Sstevel@tonic-gate */
4487c478bd9Sstevel@tonic-gate if ((intptr_t)timout == (intptr_t)((uint32_t)-1)) {
4497c478bd9Sstevel@tonic-gate *blocking = 0;
4507c478bd9Sstevel@tonic-gate return (0);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate if (copyin(timout, &wait_time_32, sizeof (wait_time_32)))
4547c478bd9Sstevel@tonic-gate return (EFAULT);
4557c478bd9Sstevel@tonic-gate TIMEVAL32_TO_TIMEVAL(&wait_time, &wait_time_32);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate if (wait_time.tv_sec == 0 && wait_time.tv_usec == 0) { /* don't wait */
4607c478bd9Sstevel@tonic-gate *blocking = 0;
4617c478bd9Sstevel@tonic-gate return (0);
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate if (wait_time.tv_sec < 0 ||
4657c478bd9Sstevel@tonic-gate wait_time.tv_usec < 0 || wait_time.tv_usec >= MICROSEC)
4667c478bd9Sstevel@tonic-gate return (EINVAL);
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate rqtime->tv_sec = wait_time.tv_sec;
4697c478bd9Sstevel@tonic-gate rqtime->tv_nsec = wait_time.tv_usec * 1000;
4707c478bd9Sstevel@tonic-gate *rqtp = rqtime;
4717c478bd9Sstevel@tonic-gate *blocking = 1;
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate return (0);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate static int
timespec2reltime(timespec_t * timout,timestruc_t * rqtime,timestruc_t ** rqtp,int * blocking)4777c478bd9Sstevel@tonic-gate timespec2reltime(timespec_t *timout, timestruc_t *rqtime,
4787c478bd9Sstevel@tonic-gate timestruc_t **rqtp, int *blocking)
4797c478bd9Sstevel@tonic-gate {
4807c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
4817c478bd9Sstevel@tonic-gate timespec32_t wait_time_32;
4827c478bd9Sstevel@tonic-gate #endif
4837c478bd9Sstevel@tonic-gate model_t model = get_udatamodel();
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate *rqtp = NULL;
4867c478bd9Sstevel@tonic-gate if (timout == NULL) {
4877c478bd9Sstevel@tonic-gate *blocking = 1;
4887c478bd9Sstevel@tonic-gate return (0);
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) {
4927c478bd9Sstevel@tonic-gate if (copyin(timout, rqtime, sizeof (*rqtime)))
4937c478bd9Sstevel@tonic-gate return (EFAULT);
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
4967c478bd9Sstevel@tonic-gate else {
4977c478bd9Sstevel@tonic-gate if (copyin(timout, &wait_time_32, sizeof (wait_time_32)))
4987c478bd9Sstevel@tonic-gate return (EFAULT);
4997c478bd9Sstevel@tonic-gate TIMESPEC32_TO_TIMESPEC(rqtime, &wait_time_32);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate if (rqtime->tv_sec == 0 && rqtime->tv_nsec == 0) {
5047c478bd9Sstevel@tonic-gate *blocking = 0;
5057c478bd9Sstevel@tonic-gate return (0);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate if (rqtime->tv_sec < 0 ||
5097c478bd9Sstevel@tonic-gate rqtime->tv_nsec < 0 || rqtime->tv_nsec >= NANOSEC)
5107c478bd9Sstevel@tonic-gate return (EINVAL);
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate *rqtp = rqtime;
5137c478bd9Sstevel@tonic-gate *blocking = 1;
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate return (0);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5197c478bd9Sstevel@tonic-gate static int
aiowait(struct timeval * timout,int dontblockflg,long * rval)5207c478bd9Sstevel@tonic-gate aiowait(
5217c478bd9Sstevel@tonic-gate struct timeval *timout,
5227c478bd9Sstevel@tonic-gate int dontblockflg,
5237c478bd9Sstevel@tonic-gate long *rval)
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate int error;
5267c478bd9Sstevel@tonic-gate aio_t *aiop;
5277c478bd9Sstevel@tonic-gate aio_req_t *reqp;
5287c478bd9Sstevel@tonic-gate clock_t status;
5297c478bd9Sstevel@tonic-gate int blocking;
5303348528fSdm120769 int timecheck;
5317c478bd9Sstevel@tonic-gate timestruc_t rqtime;
5327c478bd9Sstevel@tonic-gate timestruc_t *rqtp;
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
5357c478bd9Sstevel@tonic-gate if (aiop == NULL)
5367c478bd9Sstevel@tonic-gate return (EINVAL);
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate /*
5397c478bd9Sstevel@tonic-gate * Establish the absolute future time for the timeout.
5407c478bd9Sstevel@tonic-gate */
5417c478bd9Sstevel@tonic-gate error = timeval2reltime(timout, &rqtime, &rqtp, &blocking);
5427c478bd9Sstevel@tonic-gate if (error)
5437c478bd9Sstevel@tonic-gate return (error);
5447c478bd9Sstevel@tonic-gate if (rqtp) {
5457c478bd9Sstevel@tonic-gate timestruc_t now;
5463348528fSdm120769 timecheck = timechanged;
5477c478bd9Sstevel@tonic-gate gethrestime(&now);
5487c478bd9Sstevel@tonic-gate timespecadd(rqtp, &now);
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
5527c478bd9Sstevel@tonic-gate for (;;) {
5537c478bd9Sstevel@tonic-gate /* process requests on poll queue */
5547c478bd9Sstevel@tonic-gate if (aiop->aio_pollq) {
5557c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
5567c478bd9Sstevel@tonic-gate aio_cleanup(0);
5577c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate if ((reqp = aio_req_remove(NULL)) != NULL) {
5607c478bd9Sstevel@tonic-gate *rval = (long)reqp->aio_req_resultp;
5617c478bd9Sstevel@tonic-gate break;
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate /* user-level done queue might not be empty */
5647c478bd9Sstevel@tonic-gate if (aiop->aio_notifycnt > 0) {
5657c478bd9Sstevel@tonic-gate aiop->aio_notifycnt--;
5667c478bd9Sstevel@tonic-gate *rval = 1;
5677c478bd9Sstevel@tonic-gate break;
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate /* don't block if no outstanding aio */
5707c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0 && dontblockflg) {
5717c478bd9Sstevel@tonic-gate error = EINVAL;
5727c478bd9Sstevel@tonic-gate break;
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate if (blocking) {
5757c478bd9Sstevel@tonic-gate status = cv_waituntil_sig(&aiop->aio_waitcv,
5763348528fSdm120769 &aiop->aio_mutex, rqtp, timecheck);
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate if (status > 0) /* check done queue again */
5797c478bd9Sstevel@tonic-gate continue;
5807c478bd9Sstevel@tonic-gate if (status == 0) { /* interrupted by a signal */
5817c478bd9Sstevel@tonic-gate error = EINTR;
5827c478bd9Sstevel@tonic-gate *rval = -1;
5837c478bd9Sstevel@tonic-gate } else { /* timer expired */
5847c478bd9Sstevel@tonic-gate error = ETIME;
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate break;
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
5907c478bd9Sstevel@tonic-gate if (reqp) {
5917c478bd9Sstevel@tonic-gate aphysio_unlock(reqp);
5927c478bd9Sstevel@tonic-gate aio_copyout_result(reqp);
5937c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
5947c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
5957c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate return (error);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate /*
6017c478bd9Sstevel@tonic-gate * aiowaitn can be used to reap completed asynchronous requests submitted with
6027c478bd9Sstevel@tonic-gate * lio_listio, aio_read or aio_write.
6037c478bd9Sstevel@tonic-gate * This function only reaps asynchronous raw I/Os.
6047c478bd9Sstevel@tonic-gate */
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6077c478bd9Sstevel@tonic-gate static int
aiowaitn(void * uiocb,uint_t nent,uint_t * nwait,timespec_t * timout)6087c478bd9Sstevel@tonic-gate aiowaitn(void *uiocb, uint_t nent, uint_t *nwait, timespec_t *timout)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate int error = 0;
6117c478bd9Sstevel@tonic-gate aio_t *aiop;
6127c478bd9Sstevel@tonic-gate aio_req_t *reqlist = NULL;
6137c478bd9Sstevel@tonic-gate caddr_t iocblist = NULL; /* array of iocb ptr's */
6147c478bd9Sstevel@tonic-gate uint_t waitcnt, cnt = 0; /* iocb cnt */
6157c478bd9Sstevel@tonic-gate size_t iocbsz; /* users iocb size */
6167c478bd9Sstevel@tonic-gate size_t riocbsz; /* returned iocb size */
6177c478bd9Sstevel@tonic-gate int iocb_index = 0;
6187c478bd9Sstevel@tonic-gate model_t model = get_udatamodel();
6197c478bd9Sstevel@tonic-gate int blocking = 1;
6203348528fSdm120769 int timecheck;
6217c478bd9Sstevel@tonic-gate timestruc_t rqtime;
6227c478bd9Sstevel@tonic-gate timestruc_t *rqtp;
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
625dd1e66b6SVamsi Nagineni if (aiop == NULL || nent == 0 || nent > _AIO_LISTIO_MAX)
626dd1e66b6SVamsi Nagineni return (EINVAL);
6277c478bd9Sstevel@tonic-gate
628dd1e66b6SVamsi Nagineni if (aiop->aio_outstanding == 0)
6297c478bd9Sstevel@tonic-gate return (EAGAIN);
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate if (copyin(nwait, &waitcnt, sizeof (uint_t)))
6327c478bd9Sstevel@tonic-gate return (EFAULT);
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate /* set *nwait to zero, if we must return prematurely */
6357c478bd9Sstevel@tonic-gate if (copyout(&cnt, nwait, sizeof (uint_t)))
6367c478bd9Sstevel@tonic-gate return (EFAULT);
6377c478bd9Sstevel@tonic-gate
6387c478bd9Sstevel@tonic-gate if (waitcnt == 0) {
6397c478bd9Sstevel@tonic-gate blocking = 0;
6407c478bd9Sstevel@tonic-gate rqtp = NULL;
6417c478bd9Sstevel@tonic-gate waitcnt = nent;
6427c478bd9Sstevel@tonic-gate } else {
6437c478bd9Sstevel@tonic-gate error = timespec2reltime(timout, &rqtime, &rqtp, &blocking);
6447c478bd9Sstevel@tonic-gate if (error)
6457c478bd9Sstevel@tonic-gate return (error);
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
6497c478bd9Sstevel@tonic-gate iocbsz = (sizeof (aiocb_t *) * nent);
6507c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
6517c478bd9Sstevel@tonic-gate else
6527c478bd9Sstevel@tonic-gate iocbsz = (sizeof (caddr32_t) * nent);
6537c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate /*
6567c478bd9Sstevel@tonic-gate * Only one aio_waitn call is allowed at a time.
6577c478bd9Sstevel@tonic-gate * The active aio_waitn will collect all requests
6587c478bd9Sstevel@tonic-gate * out of the "done" list and if necessary it will wait
6597c478bd9Sstevel@tonic-gate * for some/all pending requests to fulfill the nwait
6607c478bd9Sstevel@tonic-gate * parameter.
6617c478bd9Sstevel@tonic-gate * A second or further aio_waitn calls will sleep here
6627c478bd9Sstevel@tonic-gate * until the active aio_waitn finishes and leaves the kernel
6637c478bd9Sstevel@tonic-gate * If the second call does not block (poll), then return
6647c478bd9Sstevel@tonic-gate * immediately with the error code : EAGAIN.
6657c478bd9Sstevel@tonic-gate * If the second call should block, then sleep here, but
6667c478bd9Sstevel@tonic-gate * do not touch the timeout. The timeout starts when this
6677c478bd9Sstevel@tonic-gate * aio_waitn-call becomes active.
6687c478bd9Sstevel@tonic-gate */
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate while (aiop->aio_flags & AIO_WAITN) {
6737c478bd9Sstevel@tonic-gate if (blocking == 0) {
6747c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
6757c478bd9Sstevel@tonic-gate return (EAGAIN);
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate /* block, no timeout */
6797c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_WAITN_PENDING;
6807c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&aiop->aio_waitncv, &aiop->aio_mutex)) {
6817c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
6827c478bd9Sstevel@tonic-gate return (EINTR);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate * Establish the absolute future time for the timeout.
6887c478bd9Sstevel@tonic-gate */
6897c478bd9Sstevel@tonic-gate if (rqtp) {
6907c478bd9Sstevel@tonic-gate timestruc_t now;
6913348528fSdm120769 timecheck = timechanged;
6927c478bd9Sstevel@tonic-gate gethrestime(&now);
6937c478bd9Sstevel@tonic-gate timespecadd(rqtp, &now);
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate if (iocbsz > aiop->aio_iocbsz && aiop->aio_iocb != NULL) {
6977c478bd9Sstevel@tonic-gate kmem_free(aiop->aio_iocb, aiop->aio_iocbsz);
6987c478bd9Sstevel@tonic-gate aiop->aio_iocb = NULL;
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate if (aiop->aio_iocb == NULL) {
7027c478bd9Sstevel@tonic-gate iocblist = kmem_zalloc(iocbsz, KM_NOSLEEP);
7037c478bd9Sstevel@tonic-gate if (iocblist == NULL) {
7047c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
7057c478bd9Sstevel@tonic-gate return (ENOMEM);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate aiop->aio_iocb = (aiocb_t **)iocblist;
7087c478bd9Sstevel@tonic-gate aiop->aio_iocbsz = iocbsz;
7097c478bd9Sstevel@tonic-gate } else {
7107c478bd9Sstevel@tonic-gate iocblist = (char *)aiop->aio_iocb;
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate aiop->aio_waitncnt = waitcnt;
7147c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_WAITN;
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate for (;;) {
7177c478bd9Sstevel@tonic-gate /* push requests on poll queue to done queue */
7187c478bd9Sstevel@tonic-gate if (aiop->aio_pollq) {
7197c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
7207c478bd9Sstevel@tonic-gate aio_cleanup(0);
7217c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate /* check for requests on done queue */
7257c478bd9Sstevel@tonic-gate if (aiop->aio_doneq) {
7267c478bd9Sstevel@tonic-gate cnt += aio_reqlist_concat(aiop, &reqlist, nent - cnt);
7277c478bd9Sstevel@tonic-gate aiop->aio_waitncnt = waitcnt - cnt;
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate
7307c478bd9Sstevel@tonic-gate /* user-level done queue might not be empty */
7317c478bd9Sstevel@tonic-gate if (aiop->aio_notifycnt > 0) {
7327c478bd9Sstevel@tonic-gate aiop->aio_notifycnt--;
7337c478bd9Sstevel@tonic-gate error = 0;
7347c478bd9Sstevel@tonic-gate break;
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate /*
7387c478bd9Sstevel@tonic-gate * if we are here second time as a result of timer
7397c478bd9Sstevel@tonic-gate * expiration, we reset error if there are enough
7407c478bd9Sstevel@tonic-gate * aiocb's to satisfy request.
7417c478bd9Sstevel@tonic-gate * We return also if all requests are already done
7427c478bd9Sstevel@tonic-gate * and we picked up the whole done queue.
7437c478bd9Sstevel@tonic-gate */
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate if ((cnt >= waitcnt) || (cnt > 0 && aiop->aio_pending == 0 &&
7467c478bd9Sstevel@tonic-gate aiop->aio_doneq == NULL)) {
7477c478bd9Sstevel@tonic-gate error = 0;
7487c478bd9Sstevel@tonic-gate break;
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate if ((cnt < waitcnt) && blocking) {
7527c478bd9Sstevel@tonic-gate int rval = cv_waituntil_sig(&aiop->aio_waitcv,
7533348528fSdm120769 &aiop->aio_mutex, rqtp, timecheck);
7547c478bd9Sstevel@tonic-gate if (rval > 0)
7557c478bd9Sstevel@tonic-gate continue;
7567c478bd9Sstevel@tonic-gate if (rval < 0) {
7577c478bd9Sstevel@tonic-gate error = ETIME;
7587c478bd9Sstevel@tonic-gate blocking = 0;
7597c478bd9Sstevel@tonic-gate continue;
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate error = EINTR;
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate break;
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate if (cnt > 0) {
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate iocb_index = aio_unlock_requests(iocblist, iocb_index, reqlist,
7717c478bd9Sstevel@tonic-gate aiop, model);
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
7747c478bd9Sstevel@tonic-gate riocbsz = (sizeof (aiocb_t *) * cnt);
7757c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
7767c478bd9Sstevel@tonic-gate else
7777c478bd9Sstevel@tonic-gate riocbsz = (sizeof (caddr32_t) * cnt);
7787c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate if (copyout(iocblist, uiocb, riocbsz) ||
7817c478bd9Sstevel@tonic-gate copyout(&cnt, nwait, sizeof (uint_t)))
7827c478bd9Sstevel@tonic-gate error = EFAULT;
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate /* check if there is another thread waiting for execution */
7867c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
7877c478bd9Sstevel@tonic-gate aiop->aio_flags &= ~AIO_WAITN;
7887c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_WAITN_PENDING) {
7897c478bd9Sstevel@tonic-gate aiop->aio_flags &= ~AIO_WAITN_PENDING;
7907c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_waitncv);
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate return (error);
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate /*
7987c478bd9Sstevel@tonic-gate * aio_unlock_requests
7997c478bd9Sstevel@tonic-gate * copyouts the result of the request as well as the return value.
8007c478bd9Sstevel@tonic-gate * It builds the list of completed asynchronous requests,
8017c478bd9Sstevel@tonic-gate * unlocks the allocated memory ranges and
8027c478bd9Sstevel@tonic-gate * put the aio request structure back into the free list.
8037c478bd9Sstevel@tonic-gate */
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate static int
aio_unlock_requests(caddr_t iocblist,int iocb_index,aio_req_t * reqlist,aio_t * aiop,model_t model)8067c478bd9Sstevel@tonic-gate aio_unlock_requests(
8077c478bd9Sstevel@tonic-gate caddr_t iocblist,
8087c478bd9Sstevel@tonic-gate int iocb_index,
8097c478bd9Sstevel@tonic-gate aio_req_t *reqlist,
8107c478bd9Sstevel@tonic-gate aio_t *aiop,
8117c478bd9Sstevel@tonic-gate model_t model)
8127c478bd9Sstevel@tonic-gate {
8137c478bd9Sstevel@tonic-gate aio_req_t *reqp, *nreqp;
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) {
8167c478bd9Sstevel@tonic-gate for (reqp = reqlist; reqp != NULL; reqp = nreqp) {
8177c478bd9Sstevel@tonic-gate (((caddr_t *)iocblist)[iocb_index++]) =
8187c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb;
8197c478bd9Sstevel@tonic-gate nreqp = reqp->aio_req_next;
8207c478bd9Sstevel@tonic-gate aphysio_unlock(reqp);
8217c478bd9Sstevel@tonic-gate aio_copyout_result(reqp);
8227c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
8237c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
8247c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
8287c478bd9Sstevel@tonic-gate else {
8297c478bd9Sstevel@tonic-gate for (reqp = reqlist; reqp != NULL; reqp = nreqp) {
8307c478bd9Sstevel@tonic-gate ((caddr32_t *)iocblist)[iocb_index++] =
8317c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32;
8327c478bd9Sstevel@tonic-gate nreqp = reqp->aio_req_next;
8337c478bd9Sstevel@tonic-gate aphysio_unlock(reqp);
8347c478bd9Sstevel@tonic-gate aio_copyout_result(reqp);
8357c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
8367c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
8377c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
8417c478bd9Sstevel@tonic-gate return (iocb_index);
8427c478bd9Sstevel@tonic-gate }
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate /*
8457c478bd9Sstevel@tonic-gate * aio_reqlist_concat
8467c478bd9Sstevel@tonic-gate * moves "max" elements from the done queue to the reqlist queue and removes
8477c478bd9Sstevel@tonic-gate * the AIO_DONEQ flag.
8487c478bd9Sstevel@tonic-gate * - reqlist queue is a simple linked list
8497c478bd9Sstevel@tonic-gate * - done queue is a double linked list
8507c478bd9Sstevel@tonic-gate */
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate static int
aio_reqlist_concat(aio_t * aiop,aio_req_t ** reqlist,int max)8537c478bd9Sstevel@tonic-gate aio_reqlist_concat(aio_t *aiop, aio_req_t **reqlist, int max)
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate aio_req_t *q2, *q2work, *list;
8567c478bd9Sstevel@tonic-gate int count = 0;
8577c478bd9Sstevel@tonic-gate
8587c478bd9Sstevel@tonic-gate list = *reqlist;
8597c478bd9Sstevel@tonic-gate q2 = aiop->aio_doneq;
8607c478bd9Sstevel@tonic-gate q2work = q2;
8617c478bd9Sstevel@tonic-gate while (max-- > 0) {
8627c478bd9Sstevel@tonic-gate q2work->aio_req_flags &= ~AIO_DONEQ;
8637c478bd9Sstevel@tonic-gate q2work = q2work->aio_req_next;
8647c478bd9Sstevel@tonic-gate count++;
8657c478bd9Sstevel@tonic-gate if (q2work == q2)
8667c478bd9Sstevel@tonic-gate break;
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate if (q2work == q2) {
8707c478bd9Sstevel@tonic-gate /* all elements revised */
8717c478bd9Sstevel@tonic-gate q2->aio_req_prev->aio_req_next = list;
8727c478bd9Sstevel@tonic-gate list = q2;
8737c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL;
8747c478bd9Sstevel@tonic-gate } else {
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate * max < elements in the doneq
8777c478bd9Sstevel@tonic-gate * detach only the required amount of elements
8787c478bd9Sstevel@tonic-gate * out of the doneq
8797c478bd9Sstevel@tonic-gate */
8807c478bd9Sstevel@tonic-gate q2work->aio_req_prev->aio_req_next = list;
8817c478bd9Sstevel@tonic-gate list = q2;
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate aiop->aio_doneq = q2work;
8847c478bd9Sstevel@tonic-gate q2work->aio_req_prev = q2->aio_req_prev;
8857c478bd9Sstevel@tonic-gate q2->aio_req_prev->aio_req_next = q2work;
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate *reqlist = list;
8887c478bd9Sstevel@tonic-gate return (count);
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8927c478bd9Sstevel@tonic-gate static int
aiosuspend(void * aiocb,int nent,struct timespec * timout,int flag,long * rval,int run_mode)8937c478bd9Sstevel@tonic-gate aiosuspend(
8947c478bd9Sstevel@tonic-gate void *aiocb,
8957c478bd9Sstevel@tonic-gate int nent,
8967c478bd9Sstevel@tonic-gate struct timespec *timout,
8977c478bd9Sstevel@tonic-gate int flag,
8987c478bd9Sstevel@tonic-gate long *rval,
8997c478bd9Sstevel@tonic-gate int run_mode)
9007c478bd9Sstevel@tonic-gate {
9017c478bd9Sstevel@tonic-gate int error;
9027c478bd9Sstevel@tonic-gate aio_t *aiop;
9037c478bd9Sstevel@tonic-gate aio_req_t *reqp, *found, *next;
9047c478bd9Sstevel@tonic-gate caddr_t cbplist = NULL;
9057c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp;
9067c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
9077c478bd9Sstevel@tonic-gate aiocb32_t *cbp32;
9087c478bd9Sstevel@tonic-gate caddr32_t *ucbp32;
9097c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
9107c478bd9Sstevel@tonic-gate aiocb64_32_t *cbp64;
9117c478bd9Sstevel@tonic-gate int rv;
9127c478bd9Sstevel@tonic-gate int i;
9137c478bd9Sstevel@tonic-gate size_t ssize;
9147c478bd9Sstevel@tonic-gate model_t model = get_udatamodel();
9157c478bd9Sstevel@tonic-gate int blocking;
9163348528fSdm120769 int timecheck;
9177c478bd9Sstevel@tonic-gate timestruc_t rqtime;
9187c478bd9Sstevel@tonic-gate timestruc_t *rqtp;
9197c478bd9Sstevel@tonic-gate
9207c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
921dd1e66b6SVamsi Nagineni if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX)
9227c478bd9Sstevel@tonic-gate return (EINVAL);
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gate /*
9257c478bd9Sstevel@tonic-gate * Establish the absolute future time for the timeout.
9267c478bd9Sstevel@tonic-gate */
9277c478bd9Sstevel@tonic-gate error = timespec2reltime(timout, &rqtime, &rqtp, &blocking);
9287c478bd9Sstevel@tonic-gate if (error)
9297c478bd9Sstevel@tonic-gate return (error);
9307c478bd9Sstevel@tonic-gate if (rqtp) {
9317c478bd9Sstevel@tonic-gate timestruc_t now;
9323348528fSdm120769 timecheck = timechanged;
9337c478bd9Sstevel@tonic-gate gethrestime(&now);
9347c478bd9Sstevel@tonic-gate timespecadd(rqtp, &now);
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate /*
9387c478bd9Sstevel@tonic-gate * If we are not blocking and there's no IO complete
9397c478bd9Sstevel@tonic-gate * skip aiocb copyin.
9407c478bd9Sstevel@tonic-gate */
9417c478bd9Sstevel@tonic-gate if (!blocking && (aiop->aio_pollq == NULL) &&
9427c478bd9Sstevel@tonic-gate (aiop->aio_doneq == NULL)) {
9437c478bd9Sstevel@tonic-gate return (EAGAIN);
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
9477c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent);
9487c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
9497c478bd9Sstevel@tonic-gate else
9507c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent);
9517c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_NOSLEEP);
9547c478bd9Sstevel@tonic-gate if (cbplist == NULL)
9557c478bd9Sstevel@tonic-gate return (ENOMEM);
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate if (copyin(aiocb, cbplist, ssize)) {
9587c478bd9Sstevel@tonic-gate error = EFAULT;
9597c478bd9Sstevel@tonic-gate goto done;
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate
9627c478bd9Sstevel@tonic-gate found = NULL;
9637c478bd9Sstevel@tonic-gate /*
9647c478bd9Sstevel@tonic-gate * we need to get the aio_cleanupq_mutex since we call
9657c478bd9Sstevel@tonic-gate * aio_req_done().
9667c478bd9Sstevel@tonic-gate */
9677c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex);
9687c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
9697c478bd9Sstevel@tonic-gate for (;;) {
9707c478bd9Sstevel@tonic-gate /* push requests on poll queue to done queue */
9717c478bd9Sstevel@tonic-gate if (aiop->aio_pollq) {
9727c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
9737c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex);
9747c478bd9Sstevel@tonic-gate aio_cleanup(0);
9757c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex);
9767c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
9777c478bd9Sstevel@tonic-gate }
9787c478bd9Sstevel@tonic-gate /* check for requests on done queue */
9797c478bd9Sstevel@tonic-gate if (aiop->aio_doneq) {
9807c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
9817c478bd9Sstevel@tonic-gate ucbp = (aiocb_t **)cbplist;
9827c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
9837c478bd9Sstevel@tonic-gate else
9847c478bd9Sstevel@tonic-gate ucbp32 = (caddr32_t *)cbplist;
9857c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
9867c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++) {
9877c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) {
9887c478bd9Sstevel@tonic-gate if ((cbp = *ucbp++) == NULL)
9897c478bd9Sstevel@tonic-gate continue;
9907c478bd9Sstevel@tonic-gate if (run_mode != AIO_LARGEFILE)
9917c478bd9Sstevel@tonic-gate reqp = aio_req_done(
9927c478bd9Sstevel@tonic-gate &cbp->aio_resultp);
9937c478bd9Sstevel@tonic-gate else {
9947c478bd9Sstevel@tonic-gate cbp64 = (aiocb64_32_t *)cbp;
9957c478bd9Sstevel@tonic-gate reqp = aio_req_done(
9967c478bd9Sstevel@tonic-gate &cbp64->aio_resultp);
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
10007c478bd9Sstevel@tonic-gate else {
10017c478bd9Sstevel@tonic-gate if (run_mode == AIO_32) {
10027c478bd9Sstevel@tonic-gate if ((cbp32 =
10037c478bd9Sstevel@tonic-gate (aiocb32_t *)(uintptr_t)
10047c478bd9Sstevel@tonic-gate *ucbp32++) == NULL)
10057c478bd9Sstevel@tonic-gate continue;
10067c478bd9Sstevel@tonic-gate reqp = aio_req_done(
10077c478bd9Sstevel@tonic-gate &cbp32->aio_resultp);
10087c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_LARGEFILE) {
10097c478bd9Sstevel@tonic-gate if ((cbp64 =
10107c478bd9Sstevel@tonic-gate (aiocb64_32_t *)(uintptr_t)
10117c478bd9Sstevel@tonic-gate *ucbp32++) == NULL)
10127c478bd9Sstevel@tonic-gate continue;
10137c478bd9Sstevel@tonic-gate reqp = aio_req_done(
10147c478bd9Sstevel@tonic-gate &cbp64->aio_resultp);
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate }
10187c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
10197c478bd9Sstevel@tonic-gate if (reqp) {
10207c478bd9Sstevel@tonic-gate reqp->aio_req_next = found;
10217c478bd9Sstevel@tonic-gate found = reqp;
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate if (aiop->aio_doneq == NULL)
10247c478bd9Sstevel@tonic-gate break;
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate if (found)
10277c478bd9Sstevel@tonic-gate break;
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate if (aiop->aio_notifycnt > 0) {
10307c478bd9Sstevel@tonic-gate /*
10317c478bd9Sstevel@tonic-gate * nothing on the kernel's queue. the user
10327c478bd9Sstevel@tonic-gate * has notified the kernel that it has items
10337c478bd9Sstevel@tonic-gate * on a user-level queue.
10347c478bd9Sstevel@tonic-gate */
10357c478bd9Sstevel@tonic-gate aiop->aio_notifycnt--;
10367c478bd9Sstevel@tonic-gate *rval = 1;
10377c478bd9Sstevel@tonic-gate error = 0;
10387c478bd9Sstevel@tonic-gate break;
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate /* don't block if nothing is outstanding */
10417c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0) {
10427c478bd9Sstevel@tonic-gate error = EAGAIN;
10437c478bd9Sstevel@tonic-gate break;
10447c478bd9Sstevel@tonic-gate }
10457c478bd9Sstevel@tonic-gate if (blocking) {
10467c478bd9Sstevel@tonic-gate /*
10477c478bd9Sstevel@tonic-gate * drop the aio_cleanupq_mutex as we are
10487c478bd9Sstevel@tonic-gate * going to block.
10497c478bd9Sstevel@tonic-gate */
10507c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex);
10517c478bd9Sstevel@tonic-gate rv = cv_waituntil_sig(&aiop->aio_waitcv,
10523348528fSdm120769 &aiop->aio_mutex, rqtp, timecheck);
10537c478bd9Sstevel@tonic-gate /*
10547c478bd9Sstevel@tonic-gate * we have to drop aio_mutex and
10557c478bd9Sstevel@tonic-gate * grab it in the right order.
10567c478bd9Sstevel@tonic-gate */
10577c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
10587c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex);
10597c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
10607c478bd9Sstevel@tonic-gate if (rv > 0) /* check done queue again */
10617c478bd9Sstevel@tonic-gate continue;
10627c478bd9Sstevel@tonic-gate if (rv == 0) /* interrupted by a signal */
10637c478bd9Sstevel@tonic-gate error = EINTR;
10647c478bd9Sstevel@tonic-gate else /* timer expired */
10657c478bd9Sstevel@tonic-gate error = ETIME;
10667c478bd9Sstevel@tonic-gate } else {
10677c478bd9Sstevel@tonic-gate error = EAGAIN;
10687c478bd9Sstevel@tonic-gate }
10697c478bd9Sstevel@tonic-gate break;
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
10727c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex);
10737c478bd9Sstevel@tonic-gate for (reqp = found; reqp != NULL; reqp = next) {
10747c478bd9Sstevel@tonic-gate next = reqp->aio_req_next;
10757c478bd9Sstevel@tonic-gate aphysio_unlock(reqp);
10767c478bd9Sstevel@tonic-gate aio_copyout_result(reqp);
10777c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
10787c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
10797c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate done:
10827c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
10837c478bd9Sstevel@tonic-gate return (error);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate * initialize aio by allocating an aio_t struct for this
10887c478bd9Sstevel@tonic-gate * process.
10897c478bd9Sstevel@tonic-gate */
10907c478bd9Sstevel@tonic-gate static int
aioinit(void)10917c478bd9Sstevel@tonic-gate aioinit(void)
10927c478bd9Sstevel@tonic-gate {
10937c478bd9Sstevel@tonic-gate proc_t *p = curproc;
10947c478bd9Sstevel@tonic-gate aio_t *aiop;
10957c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
10967c478bd9Sstevel@tonic-gate if ((aiop = p->p_aio) == NULL) {
10977c478bd9Sstevel@tonic-gate aiop = aio_aiop_alloc();
10987c478bd9Sstevel@tonic-gate p->p_aio = aiop;
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
11017c478bd9Sstevel@tonic-gate if (aiop == NULL)
11027c478bd9Sstevel@tonic-gate return (ENOMEM);
11037c478bd9Sstevel@tonic-gate return (0);
11047c478bd9Sstevel@tonic-gate }
11057c478bd9Sstevel@tonic-gate
11067c478bd9Sstevel@tonic-gate /*
11077c478bd9Sstevel@tonic-gate * start a special thread that will cleanup after aio requests
11087c478bd9Sstevel@tonic-gate * that are preventing a segment from being unmapped. as_unmap()
11097c478bd9Sstevel@tonic-gate * blocks until all phsyio to this segment is completed. this
11107c478bd9Sstevel@tonic-gate * doesn't happen until all the pages in this segment are not
11117c478bd9Sstevel@tonic-gate * SOFTLOCKed. Some pages will be SOFTLOCKed when there are aio
11127c478bd9Sstevel@tonic-gate * requests still outstanding. this special thread will make sure
11137c478bd9Sstevel@tonic-gate * that these SOFTLOCKed pages will eventually be SOFTUNLOCKed.
11147c478bd9Sstevel@tonic-gate *
11157c478bd9Sstevel@tonic-gate * this function will return an error if the process has only
11167c478bd9Sstevel@tonic-gate * one LWP. the assumption is that the caller is a separate LWP
11177c478bd9Sstevel@tonic-gate * that remains blocked in the kernel for the life of this process.
11187c478bd9Sstevel@tonic-gate */
11197c478bd9Sstevel@tonic-gate static int
aiostart(void)11207c478bd9Sstevel@tonic-gate aiostart(void)
11217c478bd9Sstevel@tonic-gate {
11227c478bd9Sstevel@tonic-gate proc_t *p = curproc;
11237c478bd9Sstevel@tonic-gate aio_t *aiop;
11247c478bd9Sstevel@tonic-gate int first, error = 0;
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate if (p->p_lwpcnt == 1)
11277c478bd9Sstevel@tonic-gate return (EDEADLK);
11287c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
11297c478bd9Sstevel@tonic-gate if ((aiop = p->p_aio) == NULL)
11307c478bd9Sstevel@tonic-gate error = EINVAL;
11317c478bd9Sstevel@tonic-gate else {
11327c478bd9Sstevel@tonic-gate first = aiop->aio_ok;
11337c478bd9Sstevel@tonic-gate if (aiop->aio_ok == 0)
11347c478bd9Sstevel@tonic-gate aiop->aio_ok = 1;
11357c478bd9Sstevel@tonic-gate }
11367c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
11377c478bd9Sstevel@tonic-gate if (error == 0 && first == 0) {
11387c478bd9Sstevel@tonic-gate return (aio_cleanup_thread(aiop));
11397c478bd9Sstevel@tonic-gate /* should return only to exit */
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate return (error);
11427c478bd9Sstevel@tonic-gate }
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate /*
11457c478bd9Sstevel@tonic-gate * Associate an aiocb with a port.
11467c478bd9Sstevel@tonic-gate * This function is used by aiorw() to associate a transaction with a port.
11477c478bd9Sstevel@tonic-gate * Allocate an event port structure (port_alloc_event()) and store the
11487c478bd9Sstevel@tonic-gate * delivered user pointer (portnfy_user) in the portkev_user field of the
11497c478bd9Sstevel@tonic-gate * port_kevent_t structure..
11507c478bd9Sstevel@tonic-gate * The aio_req_portkev pointer in the aio_req_t structure was added to identify
11517c478bd9Sstevel@tonic-gate * the port association.
11527c478bd9Sstevel@tonic-gate */
11537c478bd9Sstevel@tonic-gate
11547c478bd9Sstevel@tonic-gate static int
aio_req_assoc_port_rw(port_notify_t * pntfy,aiocb_t * cbp,aio_req_t * reqp,int event)115534709573Sraf aio_req_assoc_port_rw(port_notify_t *pntfy, aiocb_t *cbp,
115634709573Sraf aio_req_t *reqp, int event)
11577c478bd9Sstevel@tonic-gate {
11587c478bd9Sstevel@tonic-gate port_kevent_t *pkevp = NULL;
11597c478bd9Sstevel@tonic-gate int error;
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate error = port_alloc_event(pntfy->portnfy_port, PORT_ALLOC_DEFAULT,
11627c478bd9Sstevel@tonic-gate PORT_SOURCE_AIO, &pkevp);
11637c478bd9Sstevel@tonic-gate if (error) {
11647c478bd9Sstevel@tonic-gate if ((error == ENOMEM) || (error == EAGAIN))
11657c478bd9Sstevel@tonic-gate error = EAGAIN;
11667c478bd9Sstevel@tonic-gate else
11677c478bd9Sstevel@tonic-gate error = EINVAL;
11687c478bd9Sstevel@tonic-gate } else {
11697c478bd9Sstevel@tonic-gate port_init_event(pkevp, (uintptr_t)cbp, pntfy->portnfy_user,
11707c478bd9Sstevel@tonic-gate aio_port_callback, reqp);
117134709573Sraf pkevp->portkev_events = event;
11727c478bd9Sstevel@tonic-gate reqp->aio_req_portkev = pkevp;
11737c478bd9Sstevel@tonic-gate reqp->aio_req_port = pntfy->portnfy_port;
11747c478bd9Sstevel@tonic-gate }
11757c478bd9Sstevel@tonic-gate return (error);
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate #ifdef _LP64
11797c478bd9Sstevel@tonic-gate
11807c478bd9Sstevel@tonic-gate /*
11817c478bd9Sstevel@tonic-gate * Asynchronous list IO. A chain of aiocb's are copied in
11827c478bd9Sstevel@tonic-gate * one at a time. If the aiocb is invalid, it is skipped.
11837c478bd9Sstevel@tonic-gate * For each aiocb, the appropriate driver entry point is
11847c478bd9Sstevel@tonic-gate * called. Optimize for the common case where the list
11857c478bd9Sstevel@tonic-gate * of requests is to the same file descriptor.
11867c478bd9Sstevel@tonic-gate *
11877c478bd9Sstevel@tonic-gate * One possible optimization is to define a new driver entry
11887c478bd9Sstevel@tonic-gate * point that supports a list of IO requests. Whether this
11897c478bd9Sstevel@tonic-gate * improves performance depends somewhat on the driver's
11907c478bd9Sstevel@tonic-gate * locking strategy. Processing a list could adversely impact
11917c478bd9Sstevel@tonic-gate * the driver's interrupt latency.
11927c478bd9Sstevel@tonic-gate */
11937c478bd9Sstevel@tonic-gate static int
alio(int mode_arg,aiocb_t ** aiocb_arg,int nent,struct sigevent * sigev)11947c478bd9Sstevel@tonic-gate alio(
11957c478bd9Sstevel@tonic-gate int mode_arg,
11967c478bd9Sstevel@tonic-gate aiocb_t **aiocb_arg,
11977c478bd9Sstevel@tonic-gate int nent,
11987c478bd9Sstevel@tonic-gate struct sigevent *sigev)
11997c478bd9Sstevel@tonic-gate {
12007c478bd9Sstevel@tonic-gate file_t *fp;
12017c478bd9Sstevel@tonic-gate file_t *prev_fp = NULL;
12027c478bd9Sstevel@tonic-gate int prev_mode = -1;
12037c478bd9Sstevel@tonic-gate struct vnode *vp;
12047c478bd9Sstevel@tonic-gate aio_lio_t *head;
12057c478bd9Sstevel@tonic-gate aio_req_t *reqp;
12067c478bd9Sstevel@tonic-gate aio_t *aiop;
12077c478bd9Sstevel@tonic-gate caddr_t cbplist;
12087c478bd9Sstevel@tonic-gate aiocb_t cb;
12097c478bd9Sstevel@tonic-gate aiocb_t *aiocb = &cb;
121034709573Sraf aiocb_t *cbp;
121134709573Sraf aiocb_t **ucbp;
12127c478bd9Sstevel@tonic-gate struct sigevent sigevk;
12137c478bd9Sstevel@tonic-gate sigqueue_t *sqp;
12147c478bd9Sstevel@tonic-gate int (*aio_func)();
12157c478bd9Sstevel@tonic-gate int mode;
12167c478bd9Sstevel@tonic-gate int error = 0;
12177c478bd9Sstevel@tonic-gate int aio_errors = 0;
12187c478bd9Sstevel@tonic-gate int i;
12197c478bd9Sstevel@tonic-gate size_t ssize;
12207c478bd9Sstevel@tonic-gate int deadhead = 0;
12217c478bd9Sstevel@tonic-gate int aio_notsupported = 0;
122234709573Sraf int lio_head_port;
122334709573Sraf int aio_port;
122434709573Sraf int aio_thread;
12257c478bd9Sstevel@tonic-gate port_kevent_t *pkevtp = NULL;
122634b3058fSpraks int portused = 0;
12277c478bd9Sstevel@tonic-gate port_notify_t pnotify;
122834709573Sraf int event;
12297c478bd9Sstevel@tonic-gate
12307c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
12317c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX)
12327c478bd9Sstevel@tonic-gate return (EINVAL);
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent);
12357c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP);
12367c478bd9Sstevel@tonic-gate ucbp = (aiocb_t **)cbplist;
12377c478bd9Sstevel@tonic-gate
123834709573Sraf if (copyin(aiocb_arg, cbplist, ssize) ||
123934709573Sraf (sigev && copyin(sigev, &sigevk, sizeof (struct sigevent)))) {
12407c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
12417c478bd9Sstevel@tonic-gate return (EFAULT);
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate
124434709573Sraf /* Event Ports */
124534709573Sraf if (sigev &&
124634709573Sraf (sigevk.sigev_notify == SIGEV_THREAD ||
124734709573Sraf sigevk.sigev_notify == SIGEV_PORT)) {
124834709573Sraf if (sigevk.sigev_notify == SIGEV_THREAD) {
124934709573Sraf pnotify.portnfy_port = sigevk.sigev_signo;
125034709573Sraf pnotify.portnfy_user = sigevk.sigev_value.sival_ptr;
125134709573Sraf } else if (copyin(sigevk.sigev_value.sival_ptr,
125234709573Sraf &pnotify, sizeof (pnotify))) {
12537c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
12547c478bd9Sstevel@tonic-gate return (EFAULT);
12557c478bd9Sstevel@tonic-gate }
125634709573Sraf error = port_alloc_event(pnotify.portnfy_port,
125734709573Sraf PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO, &pkevtp);
125834709573Sraf if (error) {
125934709573Sraf if (error == ENOMEM || error == EAGAIN)
126034709573Sraf error = EAGAIN;
126134709573Sraf else
126234709573Sraf error = EINVAL;
126334709573Sraf kmem_free(cbplist, ssize);
126434709573Sraf return (error);
126534709573Sraf }
126634709573Sraf lio_head_port = pnotify.portnfy_port;
126734b3058fSpraks portused = 1;
12687c478bd9Sstevel@tonic-gate }
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate /*
12717c478bd9Sstevel@tonic-gate * a list head should be allocated if notification is
12727c478bd9Sstevel@tonic-gate * enabled for this list.
12737c478bd9Sstevel@tonic-gate */
12747c478bd9Sstevel@tonic-gate head = NULL;
12757c478bd9Sstevel@tonic-gate
127634709573Sraf if (mode_arg == LIO_WAIT || sigev) {
12777c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
12787c478bd9Sstevel@tonic-gate error = aio_lio_alloc(&head);
12797c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
12807c478bd9Sstevel@tonic-gate if (error)
12817c478bd9Sstevel@tonic-gate goto done;
12827c478bd9Sstevel@tonic-gate deadhead = 1;
12837c478bd9Sstevel@tonic-gate head->lio_nent = nent;
12847c478bd9Sstevel@tonic-gate head->lio_refcnt = nent;
128534709573Sraf head->lio_port = -1;
128634709573Sraf head->lio_portkev = NULL;
128734709573Sraf if (sigev && sigevk.sigev_notify == SIGEV_SIGNAL &&
128834709573Sraf sigevk.sigev_signo > 0 && sigevk.sigev_signo < NSIG) {
12897c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP);
12907c478bd9Sstevel@tonic-gate if (sqp == NULL) {
12917c478bd9Sstevel@tonic-gate error = EAGAIN;
12927c478bd9Sstevel@tonic-gate goto done;
12937c478bd9Sstevel@tonic-gate }
12947c478bd9Sstevel@tonic-gate sqp->sq_func = NULL;
12957c478bd9Sstevel@tonic-gate sqp->sq_next = NULL;
12967c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO;
12977c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid;
12987c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc);
12997c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid();
13007c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred);
13017c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigevk.sigev_signo;
13027c478bd9Sstevel@tonic-gate sqp->sq_info.si_value = sigevk.sigev_value;
13037c478bd9Sstevel@tonic-gate head->lio_sigqp = sqp;
13047c478bd9Sstevel@tonic-gate } else {
13057c478bd9Sstevel@tonic-gate head->lio_sigqp = NULL;
13067c478bd9Sstevel@tonic-gate }
130734709573Sraf if (pkevtp) {
130834709573Sraf /*
130934709573Sraf * Prepare data to send when list of aiocb's
131034709573Sraf * has completed.
131134709573Sraf */
131234709573Sraf port_init_event(pkevtp, (uintptr_t)sigev,
131334709573Sraf (void *)(uintptr_t)pnotify.portnfy_user,
131434709573Sraf NULL, head);
131534709573Sraf pkevtp->portkev_events = AIOLIO;
131634709573Sraf head->lio_portkev = pkevtp;
131734709573Sraf head->lio_port = pnotify.portnfy_port;
131834709573Sraf }
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++, ucbp++) {
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate cbp = *ucbp;
13247c478bd9Sstevel@tonic-gate /* skip entry if it can't be copied. */
132534709573Sraf if (cbp == NULL || copyin(cbp, aiocb, sizeof (*aiocb))) {
13267c478bd9Sstevel@tonic-gate if (head) {
13277c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
13287c478bd9Sstevel@tonic-gate head->lio_nent--;
13297c478bd9Sstevel@tonic-gate head->lio_refcnt--;
13307c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
13317c478bd9Sstevel@tonic-gate }
13327c478bd9Sstevel@tonic-gate continue;
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate /* skip if opcode for aiocb is LIO_NOP */
13367c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode;
13377c478bd9Sstevel@tonic-gate if (mode == LIO_NOP) {
13387c478bd9Sstevel@tonic-gate cbp = NULL;
13397c478bd9Sstevel@tonic-gate if (head) {
13407c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
13417c478bd9Sstevel@tonic-gate head->lio_nent--;
13427c478bd9Sstevel@tonic-gate head->lio_refcnt--;
13437c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
13447c478bd9Sstevel@tonic-gate }
13457c478bd9Sstevel@tonic-gate continue;
13467c478bd9Sstevel@tonic-gate }
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate /* increment file descriptor's ref count. */
13497c478bd9Sstevel@tonic-gate if ((fp = getf(aiocb->aio_fildes)) == NULL) {
13507c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF);
13517c478bd9Sstevel@tonic-gate if (head) {
13527c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
13537c478bd9Sstevel@tonic-gate head->lio_nent--;
13547c478bd9Sstevel@tonic-gate head->lio_refcnt--;
13557c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
13567c478bd9Sstevel@tonic-gate }
13577c478bd9Sstevel@tonic-gate aio_errors++;
13587c478bd9Sstevel@tonic-gate continue;
13597c478bd9Sstevel@tonic-gate }
13607c478bd9Sstevel@tonic-gate
13617c478bd9Sstevel@tonic-gate /*
13627c478bd9Sstevel@tonic-gate * check the permission of the partition
13637c478bd9Sstevel@tonic-gate */
13647c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) {
13657c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
13667c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF);
13677c478bd9Sstevel@tonic-gate if (head) {
13687c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
13697c478bd9Sstevel@tonic-gate head->lio_nent--;
13707c478bd9Sstevel@tonic-gate head->lio_refcnt--;
13717c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
13727c478bd9Sstevel@tonic-gate }
13737c478bd9Sstevel@tonic-gate aio_errors++;
13747c478bd9Sstevel@tonic-gate continue;
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate /*
137834709573Sraf * common case where requests are to the same fd
137934709573Sraf * for the same r/w operation.
13807c478bd9Sstevel@tonic-gate * for UFS, need to set EBADFD
13817c478bd9Sstevel@tonic-gate */
138234709573Sraf vp = fp->f_vnode;
138334709573Sraf if (fp != prev_fp || mode != prev_mode) {
13847c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode);
13857c478bd9Sstevel@tonic-gate if (aio_func == NULL) {
13867c478bd9Sstevel@tonic-gate prev_fp = NULL;
13877c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
13887c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADFD);
13897c478bd9Sstevel@tonic-gate aio_notsupported++;
13907c478bd9Sstevel@tonic-gate if (head) {
13917c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
13927c478bd9Sstevel@tonic-gate head->lio_nent--;
13937c478bd9Sstevel@tonic-gate head->lio_refcnt--;
13947c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
13957c478bd9Sstevel@tonic-gate }
13967c478bd9Sstevel@tonic-gate continue;
13977c478bd9Sstevel@tonic-gate } else {
13987c478bd9Sstevel@tonic-gate prev_fp = fp;
13997c478bd9Sstevel@tonic-gate prev_mode = mode;
14007c478bd9Sstevel@tonic-gate }
14017c478bd9Sstevel@tonic-gate }
14027c478bd9Sstevel@tonic-gate
140334709573Sraf error = aio_req_setup(&reqp, aiop, aiocb,
1404*d2749ac6SRoger A. Faulkner &cbp->aio_resultp, vp, 0);
140534709573Sraf if (error) {
14067c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
14077c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error);
14087c478bd9Sstevel@tonic-gate if (head) {
14097c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
14107c478bd9Sstevel@tonic-gate head->lio_nent--;
14117c478bd9Sstevel@tonic-gate head->lio_refcnt--;
14127c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
14137c478bd9Sstevel@tonic-gate }
14147c478bd9Sstevel@tonic-gate aio_errors++;
14157c478bd9Sstevel@tonic-gate continue;
14167c478bd9Sstevel@tonic-gate }
14177c478bd9Sstevel@tonic-gate
14187c478bd9Sstevel@tonic-gate reqp->aio_req_lio = head;
14197c478bd9Sstevel@tonic-gate deadhead = 0;
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate /*
14227c478bd9Sstevel@tonic-gate * Set the errno field now before sending the request to
14237c478bd9Sstevel@tonic-gate * the driver to avoid a race condition
14247c478bd9Sstevel@tonic-gate */
14257c478bd9Sstevel@tonic-gate (void) suword32(&cbp->aio_resultp.aio_errno,
14267c478bd9Sstevel@tonic-gate EINPROGRESS);
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = (caddr_t)cbp;
14297c478bd9Sstevel@tonic-gate
143034709573Sraf event = (mode == LIO_READ)? AIOAREAD : AIOAWRITE;
143134709573Sraf aio_port = (aiocb->aio_sigevent.sigev_notify == SIGEV_PORT);
143234709573Sraf aio_thread = (aiocb->aio_sigevent.sigev_notify == SIGEV_THREAD);
143334709573Sraf if (aio_port | aio_thread) {
143434709573Sraf port_kevent_t *lpkevp;
143534709573Sraf /*
143634709573Sraf * Prepare data to send with each aiocb completed.
143734709573Sraf */
143834709573Sraf if (aio_port) {
143934709573Sraf void *paddr =
144034709573Sraf aiocb->aio_sigevent.sigev_value.sival_ptr;
144134709573Sraf if (copyin(paddr, &pnotify, sizeof (pnotify)))
144234709573Sraf error = EFAULT;
144334709573Sraf } else { /* aio_thread */
144434709573Sraf pnotify.portnfy_port =
144534709573Sraf aiocb->aio_sigevent.sigev_signo;
144634709573Sraf pnotify.portnfy_user =
144734709573Sraf aiocb->aio_sigevent.sigev_value.sival_ptr;
144834709573Sraf }
144934709573Sraf if (error)
145034709573Sraf /* EMPTY */;
145134709573Sraf else if (pkevtp != NULL &&
145234709573Sraf pnotify.portnfy_port == lio_head_port)
145334709573Sraf error = port_dup_event(pkevtp, &lpkevp,
145434709573Sraf PORT_ALLOC_DEFAULT);
145534709573Sraf else
145634709573Sraf error = port_alloc_event(pnotify.portnfy_port,
145734709573Sraf PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO,
145834709573Sraf &lpkevp);
145934709573Sraf if (error == 0) {
146034709573Sraf port_init_event(lpkevp, (uintptr_t)cbp,
146134709573Sraf (void *)(uintptr_t)pnotify.portnfy_user,
146234709573Sraf aio_port_callback, reqp);
146334709573Sraf lpkevp->portkev_events = event;
146434709573Sraf reqp->aio_req_portkev = lpkevp;
14657c478bd9Sstevel@tonic-gate reqp->aio_req_port = pnotify.portnfy_port;
146634709573Sraf }
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate /*
14707c478bd9Sstevel@tonic-gate * send the request to driver.
14717c478bd9Sstevel@tonic-gate */
14727c478bd9Sstevel@tonic-gate if (error == 0) {
14737c478bd9Sstevel@tonic-gate if (aiocb->aio_nbytes == 0) {
14747c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes);
14757c478bd9Sstevel@tonic-gate aio_zerolen(reqp);
14767c478bd9Sstevel@tonic-gate continue;
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req,
14797c478bd9Sstevel@tonic-gate CRED());
14807c478bd9Sstevel@tonic-gate }
148134709573Sraf
14827c478bd9Sstevel@tonic-gate /*
14837c478bd9Sstevel@tonic-gate * the fd's ref count is not decremented until the IO has
14847c478bd9Sstevel@tonic-gate * completed unless there was an error.
14857c478bd9Sstevel@tonic-gate */
14867c478bd9Sstevel@tonic-gate if (error) {
14877c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
14887c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error);
14897c478bd9Sstevel@tonic-gate if (head) {
14907c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
14917c478bd9Sstevel@tonic-gate head->lio_nent--;
14927c478bd9Sstevel@tonic-gate head->lio_refcnt--;
14937c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
14947c478bd9Sstevel@tonic-gate }
14957c478bd9Sstevel@tonic-gate if (error == ENOTSUP)
14967c478bd9Sstevel@tonic-gate aio_notsupported++;
14977c478bd9Sstevel@tonic-gate else
14987c478bd9Sstevel@tonic-gate aio_errors++;
149934b3058fSpraks lio_set_error(reqp, portused);
15007c478bd9Sstevel@tonic-gate } else {
15017c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes);
15027c478bd9Sstevel@tonic-gate }
15037c478bd9Sstevel@tonic-gate }
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate if (aio_notsupported) {
15067c478bd9Sstevel@tonic-gate error = ENOTSUP;
15077c478bd9Sstevel@tonic-gate } else if (aio_errors) {
15087c478bd9Sstevel@tonic-gate /*
15097c478bd9Sstevel@tonic-gate * return EIO if any request failed
15107c478bd9Sstevel@tonic-gate */
15117c478bd9Sstevel@tonic-gate error = EIO;
15127c478bd9Sstevel@tonic-gate }
15137c478bd9Sstevel@tonic-gate
15147c478bd9Sstevel@tonic-gate if (mode_arg == LIO_WAIT) {
15157c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
15167c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) {
15177c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) {
15187c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
15197c478bd9Sstevel@tonic-gate error = EINTR;
15207c478bd9Sstevel@tonic-gate goto done;
15217c478bd9Sstevel@tonic-gate }
15227c478bd9Sstevel@tonic-gate }
15237c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
15247c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, AIO_64);
15257c478bd9Sstevel@tonic-gate }
15267c478bd9Sstevel@tonic-gate
15277c478bd9Sstevel@tonic-gate done:
15287c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
15297c478bd9Sstevel@tonic-gate if (deadhead) {
15307c478bd9Sstevel@tonic-gate if (head->lio_sigqp)
15317c478bd9Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t));
153234709573Sraf if (head->lio_portkev)
153334709573Sraf port_free_event(head->lio_portkev);
15347c478bd9Sstevel@tonic-gate kmem_free(head, sizeof (aio_lio_t));
15357c478bd9Sstevel@tonic-gate }
15367c478bd9Sstevel@tonic-gate return (error);
15377c478bd9Sstevel@tonic-gate }
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate #endif /* _LP64 */
15407c478bd9Sstevel@tonic-gate
15417c478bd9Sstevel@tonic-gate /*
15427c478bd9Sstevel@tonic-gate * Asynchronous list IO.
15437c478bd9Sstevel@tonic-gate * If list I/O is called with LIO_WAIT it can still return
15447c478bd9Sstevel@tonic-gate * before all the I/O's are completed if a signal is caught
15457c478bd9Sstevel@tonic-gate * or if the list include UFS I/O requests. If this happens,
15467c478bd9Sstevel@tonic-gate * libaio will call aliowait() to wait for the I/O's to
15477c478bd9Sstevel@tonic-gate * complete
15487c478bd9Sstevel@tonic-gate */
15497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15507c478bd9Sstevel@tonic-gate static int
aliowait(int mode,void * aiocb,int nent,void * sigev,int run_mode)15517c478bd9Sstevel@tonic-gate aliowait(
15527c478bd9Sstevel@tonic-gate int mode,
15537c478bd9Sstevel@tonic-gate void *aiocb,
15547c478bd9Sstevel@tonic-gate int nent,
15557c478bd9Sstevel@tonic-gate void *sigev,
15567c478bd9Sstevel@tonic-gate int run_mode)
15577c478bd9Sstevel@tonic-gate {
15587c478bd9Sstevel@tonic-gate aio_lio_t *head;
15597c478bd9Sstevel@tonic-gate aio_t *aiop;
15607c478bd9Sstevel@tonic-gate caddr_t cbplist;
15617c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp;
15627c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
15637c478bd9Sstevel@tonic-gate aiocb32_t *cbp32;
15647c478bd9Sstevel@tonic-gate caddr32_t *ucbp32;
15657c478bd9Sstevel@tonic-gate aiocb64_32_t *cbp64;
15667c478bd9Sstevel@tonic-gate #endif
15677c478bd9Sstevel@tonic-gate int error = 0;
15687c478bd9Sstevel@tonic-gate int i;
15697c478bd9Sstevel@tonic-gate size_t ssize = 0;
15707c478bd9Sstevel@tonic-gate model_t model = get_udatamodel();
15717c478bd9Sstevel@tonic-gate
15727c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
15737c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX)
15747c478bd9Sstevel@tonic-gate return (EINVAL);
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
15777c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent);
15787c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
15797c478bd9Sstevel@tonic-gate else
15807c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent);
15817c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
15827c478bd9Sstevel@tonic-gate
15837c478bd9Sstevel@tonic-gate if (ssize == 0)
15847c478bd9Sstevel@tonic-gate return (EINVAL);
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP);
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
15897c478bd9Sstevel@tonic-gate ucbp = (aiocb_t **)cbplist;
15907c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
15917c478bd9Sstevel@tonic-gate else
15927c478bd9Sstevel@tonic-gate ucbp32 = (caddr32_t *)cbplist;
15937c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate if (copyin(aiocb, cbplist, ssize)) {
15967c478bd9Sstevel@tonic-gate error = EFAULT;
15977c478bd9Sstevel@tonic-gate goto done;
15987c478bd9Sstevel@tonic-gate }
15997c478bd9Sstevel@tonic-gate
16007c478bd9Sstevel@tonic-gate /*
16017c478bd9Sstevel@tonic-gate * To find the list head, we go through the
16027c478bd9Sstevel@tonic-gate * list of aiocb structs, find the request
16037c478bd9Sstevel@tonic-gate * its for, then get the list head that reqp
16047c478bd9Sstevel@tonic-gate * points to
16057c478bd9Sstevel@tonic-gate */
16067c478bd9Sstevel@tonic-gate head = NULL;
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++) {
16097c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) {
16107c478bd9Sstevel@tonic-gate /*
16117c478bd9Sstevel@tonic-gate * Since we are only checking for a NULL pointer
16127c478bd9Sstevel@tonic-gate * Following should work on both native data sizes
16137c478bd9Sstevel@tonic-gate * as well as for largefile aiocb.
16147c478bd9Sstevel@tonic-gate */
16157c478bd9Sstevel@tonic-gate if ((cbp = *ucbp++) == NULL)
16167c478bd9Sstevel@tonic-gate continue;
16177c478bd9Sstevel@tonic-gate if (run_mode != AIO_LARGEFILE)
16187c478bd9Sstevel@tonic-gate if (head = aio_list_get(&cbp->aio_resultp))
16197c478bd9Sstevel@tonic-gate break;
16207c478bd9Sstevel@tonic-gate else {
16217c478bd9Sstevel@tonic-gate /*
16227c478bd9Sstevel@tonic-gate * This is a case when largefile call is
16237c478bd9Sstevel@tonic-gate * made on 32 bit kernel.
16247c478bd9Sstevel@tonic-gate * Treat each pointer as pointer to
16257c478bd9Sstevel@tonic-gate * aiocb64_32
16267c478bd9Sstevel@tonic-gate */
16277c478bd9Sstevel@tonic-gate if (head = aio_list_get((aio_result_t *)
16287c478bd9Sstevel@tonic-gate &(((aiocb64_32_t *)cbp)->aio_resultp)))
16297c478bd9Sstevel@tonic-gate break;
16307c478bd9Sstevel@tonic-gate }
16317c478bd9Sstevel@tonic-gate }
16327c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
16337c478bd9Sstevel@tonic-gate else {
16347c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) {
16357c478bd9Sstevel@tonic-gate if ((cbp64 = (aiocb64_32_t *)
16367c478bd9Sstevel@tonic-gate (uintptr_t)*ucbp32++) == NULL)
16377c478bd9Sstevel@tonic-gate continue;
16387c478bd9Sstevel@tonic-gate if (head = aio_list_get((aio_result_t *)
16397c478bd9Sstevel@tonic-gate &cbp64->aio_resultp))
16407c478bd9Sstevel@tonic-gate break;
16417c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_32) {
16427c478bd9Sstevel@tonic-gate if ((cbp32 = (aiocb32_t *)
16437c478bd9Sstevel@tonic-gate (uintptr_t)*ucbp32++) == NULL)
16447c478bd9Sstevel@tonic-gate continue;
16457c478bd9Sstevel@tonic-gate if (head = aio_list_get((aio_result_t *)
16467c478bd9Sstevel@tonic-gate &cbp32->aio_resultp))
16477c478bd9Sstevel@tonic-gate break;
16487c478bd9Sstevel@tonic-gate }
16497c478bd9Sstevel@tonic-gate }
16507c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
16517c478bd9Sstevel@tonic-gate }
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate if (head == NULL) {
16547c478bd9Sstevel@tonic-gate error = EINVAL;
16557c478bd9Sstevel@tonic-gate goto done;
16567c478bd9Sstevel@tonic-gate }
16577c478bd9Sstevel@tonic-gate
16587c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
16597c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) {
16607c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) {
16617c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
16627c478bd9Sstevel@tonic-gate error = EINTR;
16637c478bd9Sstevel@tonic-gate goto done;
16647c478bd9Sstevel@tonic-gate }
16657c478bd9Sstevel@tonic-gate }
16667c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
16677c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, run_mode);
16687c478bd9Sstevel@tonic-gate done:
16697c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
16707c478bd9Sstevel@tonic-gate return (error);
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate
16737c478bd9Sstevel@tonic-gate aio_lio_t *
aio_list_get(aio_result_t * resultp)16747c478bd9Sstevel@tonic-gate aio_list_get(aio_result_t *resultp)
16757c478bd9Sstevel@tonic-gate {
16767c478bd9Sstevel@tonic-gate aio_lio_t *head = NULL;
16777c478bd9Sstevel@tonic-gate aio_t *aiop;
16787c478bd9Sstevel@tonic-gate aio_req_t **bucket;
16797c478bd9Sstevel@tonic-gate aio_req_t *reqp;
16807c478bd9Sstevel@tonic-gate long index;
16817c478bd9Sstevel@tonic-gate
16827c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
16837c478bd9Sstevel@tonic-gate if (aiop == NULL)
16847c478bd9Sstevel@tonic-gate return (NULL);
16857c478bd9Sstevel@tonic-gate
16867c478bd9Sstevel@tonic-gate if (resultp) {
16877c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp);
16887c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index];
16897c478bd9Sstevel@tonic-gate for (reqp = *bucket; reqp != NULL;
16907c478bd9Sstevel@tonic-gate reqp = reqp->aio_hash_next) {
16917c478bd9Sstevel@tonic-gate if (reqp->aio_req_resultp == resultp) {
16927c478bd9Sstevel@tonic-gate head = reqp->aio_req_lio;
16937c478bd9Sstevel@tonic-gate return (head);
16947c478bd9Sstevel@tonic-gate }
16957c478bd9Sstevel@tonic-gate }
16967c478bd9Sstevel@tonic-gate }
16977c478bd9Sstevel@tonic-gate return (NULL);
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate static void
lio_set_uerror(void * resultp,int error)17027c478bd9Sstevel@tonic-gate lio_set_uerror(void *resultp, int error)
17037c478bd9Sstevel@tonic-gate {
17047c478bd9Sstevel@tonic-gate /*
17057c478bd9Sstevel@tonic-gate * the resultp field is a pointer to where the
17067c478bd9Sstevel@tonic-gate * error should be written out to the user's
17077c478bd9Sstevel@tonic-gate * aiocb.
17087c478bd9Sstevel@tonic-gate *
17097c478bd9Sstevel@tonic-gate */
17107c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) {
17117c478bd9Sstevel@tonic-gate (void) sulword(&((aio_result_t *)resultp)->aio_return,
17127c478bd9Sstevel@tonic-gate (ssize_t)-1);
17137c478bd9Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_errno, error);
17147c478bd9Sstevel@tonic-gate }
17157c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
17167c478bd9Sstevel@tonic-gate else {
17177c478bd9Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_return,
17187c478bd9Sstevel@tonic-gate (uint_t)-1);
17197c478bd9Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_errno, error);
17207c478bd9Sstevel@tonic-gate }
17217c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
17227c478bd9Sstevel@tonic-gate }
17237c478bd9Sstevel@tonic-gate
17247c478bd9Sstevel@tonic-gate /*
17257c478bd9Sstevel@tonic-gate * do cleanup completion for all requests in list. memory for
17267c478bd9Sstevel@tonic-gate * each request is also freed.
17277c478bd9Sstevel@tonic-gate */
17287c478bd9Sstevel@tonic-gate static void
alio_cleanup(aio_t * aiop,aiocb_t ** cbp,int nent,int run_mode)17297c478bd9Sstevel@tonic-gate alio_cleanup(aio_t *aiop, aiocb_t **cbp, int nent, int run_mode)
17307c478bd9Sstevel@tonic-gate {
17317c478bd9Sstevel@tonic-gate int i;
17327c478bd9Sstevel@tonic-gate aio_req_t *reqp;
17337c478bd9Sstevel@tonic-gate aio_result_t *resultp;
17347c478bd9Sstevel@tonic-gate aiocb64_32_t *aiocb_64;
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++) {
17377c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) {
17387c478bd9Sstevel@tonic-gate if (cbp[i] == NULL)
17397c478bd9Sstevel@tonic-gate continue;
17407c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) {
17417c478bd9Sstevel@tonic-gate aiocb_64 = (aiocb64_32_t *)cbp[i];
174234709573Sraf resultp = (aio_result_t *)
174334709573Sraf &aiocb_64->aio_resultp;
17447c478bd9Sstevel@tonic-gate } else
17457c478bd9Sstevel@tonic-gate resultp = &cbp[i]->aio_resultp;
17467c478bd9Sstevel@tonic-gate }
17477c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
17487c478bd9Sstevel@tonic-gate else {
17497c478bd9Sstevel@tonic-gate aiocb32_t *aiocb_32;
17507c478bd9Sstevel@tonic-gate caddr32_t *cbp32;
17517c478bd9Sstevel@tonic-gate
17527c478bd9Sstevel@tonic-gate cbp32 = (caddr32_t *)cbp;
17537c478bd9Sstevel@tonic-gate if (cbp32[i] == NULL)
17547c478bd9Sstevel@tonic-gate continue;
17557c478bd9Sstevel@tonic-gate if (run_mode == AIO_32) {
17567c478bd9Sstevel@tonic-gate aiocb_32 = (aiocb32_t *)(uintptr_t)cbp32[i];
17577c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&aiocb_32->
17587c478bd9Sstevel@tonic-gate aio_resultp;
17597c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_LARGEFILE) {
17607c478bd9Sstevel@tonic-gate aiocb_64 = (aiocb64_32_t *)(uintptr_t)cbp32[i];
17617c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&aiocb_64->
17627c478bd9Sstevel@tonic-gate aio_resultp;
17637c478bd9Sstevel@tonic-gate }
17647c478bd9Sstevel@tonic-gate }
17657c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
17667c478bd9Sstevel@tonic-gate /*
17677c478bd9Sstevel@tonic-gate * we need to get the aio_cleanupq_mutex since we call
17687c478bd9Sstevel@tonic-gate * aio_req_done().
17697c478bd9Sstevel@tonic-gate */
17707c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex);
17717c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
17727c478bd9Sstevel@tonic-gate reqp = aio_req_done(resultp);
17737c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
17747c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex);
17757c478bd9Sstevel@tonic-gate if (reqp != NULL) {
17767c478bd9Sstevel@tonic-gate aphysio_unlock(reqp);
17777c478bd9Sstevel@tonic-gate aio_copyout_result(reqp);
17787c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
17797c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
17807c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
17817c478bd9Sstevel@tonic-gate }
17827c478bd9Sstevel@tonic-gate }
17837c478bd9Sstevel@tonic-gate }
17847c478bd9Sstevel@tonic-gate
17857c478bd9Sstevel@tonic-gate /*
178634709573Sraf * Write out the results for an aio request that is done.
17877c478bd9Sstevel@tonic-gate */
17887c478bd9Sstevel@tonic-gate static int
aioerror(void * cb,int run_mode)17897c478bd9Sstevel@tonic-gate aioerror(void *cb, int run_mode)
17907c478bd9Sstevel@tonic-gate {
17917c478bd9Sstevel@tonic-gate aio_result_t *resultp;
17927c478bd9Sstevel@tonic-gate aio_t *aiop;
17937c478bd9Sstevel@tonic-gate aio_req_t *reqp;
17947c478bd9Sstevel@tonic-gate int retval;
17957c478bd9Sstevel@tonic-gate
17967c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
17977c478bd9Sstevel@tonic-gate if (aiop == NULL || cb == NULL)
17987c478bd9Sstevel@tonic-gate return (EINVAL);
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) {
18017c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE)
18027c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb)->
18037c478bd9Sstevel@tonic-gate aio_resultp;
18047c478bd9Sstevel@tonic-gate else
18057c478bd9Sstevel@tonic-gate resultp = &((aiocb_t *)cb)->aio_resultp;
18067c478bd9Sstevel@tonic-gate }
18077c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
18087c478bd9Sstevel@tonic-gate else {
18097c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE)
18107c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb)->
18117c478bd9Sstevel@tonic-gate aio_resultp;
18127c478bd9Sstevel@tonic-gate else if (run_mode == AIO_32)
18137c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb32_t *)cb)->
18147c478bd9Sstevel@tonic-gate aio_resultp;
18157c478bd9Sstevel@tonic-gate }
18167c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
18177c478bd9Sstevel@tonic-gate /*
18187c478bd9Sstevel@tonic-gate * we need to get the aio_cleanupq_mutex since we call
18197c478bd9Sstevel@tonic-gate * aio_req_find().
18207c478bd9Sstevel@tonic-gate */
18217c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex);
18227c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
18237c478bd9Sstevel@tonic-gate retval = aio_req_find(resultp, &reqp);
18247c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
18257c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex);
18267c478bd9Sstevel@tonic-gate if (retval == 0) {
18277c478bd9Sstevel@tonic-gate aphysio_unlock(reqp);
18287c478bd9Sstevel@tonic-gate aio_copyout_result(reqp);
18297c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
18307c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
18317c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
18327c478bd9Sstevel@tonic-gate return (0);
18337c478bd9Sstevel@tonic-gate } else if (retval == 1)
18347c478bd9Sstevel@tonic-gate return (EINPROGRESS);
18357c478bd9Sstevel@tonic-gate else if (retval == 2)
18367c478bd9Sstevel@tonic-gate return (EINVAL);
18377c478bd9Sstevel@tonic-gate return (0);
18387c478bd9Sstevel@tonic-gate }
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate /*
18417c478bd9Sstevel@tonic-gate * aio_cancel - if no requests outstanding,
18427c478bd9Sstevel@tonic-gate * return AIO_ALLDONE
18437c478bd9Sstevel@tonic-gate * else
18447c478bd9Sstevel@tonic-gate * return AIO_NOTCANCELED
18457c478bd9Sstevel@tonic-gate */
18467c478bd9Sstevel@tonic-gate static int
aio_cancel(int fildes,void * cb,long * rval,int run_mode)18477c478bd9Sstevel@tonic-gate aio_cancel(
18487c478bd9Sstevel@tonic-gate int fildes,
18497c478bd9Sstevel@tonic-gate void *cb,
18507c478bd9Sstevel@tonic-gate long *rval,
18517c478bd9Sstevel@tonic-gate int run_mode)
18527c478bd9Sstevel@tonic-gate {
18537c478bd9Sstevel@tonic-gate aio_t *aiop;
18547c478bd9Sstevel@tonic-gate void *resultp;
18557c478bd9Sstevel@tonic-gate int index;
18567c478bd9Sstevel@tonic-gate aio_req_t **bucket;
18577c478bd9Sstevel@tonic-gate aio_req_t *ent;
18587c478bd9Sstevel@tonic-gate
18597c478bd9Sstevel@tonic-gate
18607c478bd9Sstevel@tonic-gate /*
18617c478bd9Sstevel@tonic-gate * Verify valid file descriptor
18627c478bd9Sstevel@tonic-gate */
18637c478bd9Sstevel@tonic-gate if ((getf(fildes)) == NULL) {
18647c478bd9Sstevel@tonic-gate return (EBADF);
18657c478bd9Sstevel@tonic-gate }
18667c478bd9Sstevel@tonic-gate releasef(fildes);
18677c478bd9Sstevel@tonic-gate
18687c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
18697c478bd9Sstevel@tonic-gate if (aiop == NULL)
18707c478bd9Sstevel@tonic-gate return (EINVAL);
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0) {
18737c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE;
18747c478bd9Sstevel@tonic-gate return (0);
18757c478bd9Sstevel@tonic-gate }
18767c478bd9Sstevel@tonic-gate
18777c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
18787c478bd9Sstevel@tonic-gate if (cb != NULL) {
18797c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) {
18807c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE)
18817c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb)
18827c478bd9Sstevel@tonic-gate ->aio_resultp;
18837c478bd9Sstevel@tonic-gate else
18847c478bd9Sstevel@tonic-gate resultp = &((aiocb_t *)cb)->aio_resultp;
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
18877c478bd9Sstevel@tonic-gate else {
18887c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE)
18897c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb)
18907c478bd9Sstevel@tonic-gate ->aio_resultp;
18917c478bd9Sstevel@tonic-gate else if (run_mode == AIO_32)
18927c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb32_t *)cb)
18937c478bd9Sstevel@tonic-gate ->aio_resultp;
18947c478bd9Sstevel@tonic-gate }
18957c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
18967c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp);
18977c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index];
18987c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) {
18997c478bd9Sstevel@tonic-gate if (ent->aio_req_resultp == resultp) {
19007c478bd9Sstevel@tonic-gate if ((ent->aio_req_flags & AIO_PENDING) == 0) {
19017c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
19027c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE;
19037c478bd9Sstevel@tonic-gate return (0);
19047c478bd9Sstevel@tonic-gate }
19057c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
19067c478bd9Sstevel@tonic-gate *rval = AIO_NOTCANCELED;
19077c478bd9Sstevel@tonic-gate return (0);
19087c478bd9Sstevel@tonic-gate }
19097c478bd9Sstevel@tonic-gate }
19107c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
19117c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE;
19127c478bd9Sstevel@tonic-gate return (0);
19137c478bd9Sstevel@tonic-gate }
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gate for (index = 0; index < AIO_HASHSZ; index++) {
19167c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index];
19177c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) {
19187c478bd9Sstevel@tonic-gate if (ent->aio_req_fd == fildes) {
19197c478bd9Sstevel@tonic-gate if ((ent->aio_req_flags & AIO_PENDING) != 0) {
19207c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
19217c478bd9Sstevel@tonic-gate *rval = AIO_NOTCANCELED;
19227c478bd9Sstevel@tonic-gate return (0);
19237c478bd9Sstevel@tonic-gate }
19247c478bd9Sstevel@tonic-gate }
19257c478bd9Sstevel@tonic-gate }
19267c478bd9Sstevel@tonic-gate }
19277c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
19287c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE;
19297c478bd9Sstevel@tonic-gate return (0);
19307c478bd9Sstevel@tonic-gate }
19317c478bd9Sstevel@tonic-gate
19327c478bd9Sstevel@tonic-gate /*
19337c478bd9Sstevel@tonic-gate * solaris version of asynchronous read and write
19347c478bd9Sstevel@tonic-gate */
19357c478bd9Sstevel@tonic-gate static int
arw(int opcode,int fdes,char * bufp,int bufsize,offset_t offset,aio_result_t * resultp,int mode)19367c478bd9Sstevel@tonic-gate arw(
19377c478bd9Sstevel@tonic-gate int opcode,
19387c478bd9Sstevel@tonic-gate int fdes,
19397c478bd9Sstevel@tonic-gate char *bufp,
19407c478bd9Sstevel@tonic-gate int bufsize,
19417c478bd9Sstevel@tonic-gate offset_t offset,
19427c478bd9Sstevel@tonic-gate aio_result_t *resultp,
19437c478bd9Sstevel@tonic-gate int mode)
19447c478bd9Sstevel@tonic-gate {
19457c478bd9Sstevel@tonic-gate file_t *fp;
19467c478bd9Sstevel@tonic-gate int error;
19477c478bd9Sstevel@tonic-gate struct vnode *vp;
19487c478bd9Sstevel@tonic-gate aio_req_t *reqp;
19497c478bd9Sstevel@tonic-gate aio_t *aiop;
19507c478bd9Sstevel@tonic-gate int (*aio_func)();
19517c478bd9Sstevel@tonic-gate #ifdef _LP64
19527c478bd9Sstevel@tonic-gate aiocb_t aiocb;
19537c478bd9Sstevel@tonic-gate #else
19547c478bd9Sstevel@tonic-gate aiocb64_32_t aiocb64;
19557c478bd9Sstevel@tonic-gate #endif
19567c478bd9Sstevel@tonic-gate
19577c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
19587c478bd9Sstevel@tonic-gate if (aiop == NULL)
19597c478bd9Sstevel@tonic-gate return (EINVAL);
19607c478bd9Sstevel@tonic-gate
19617c478bd9Sstevel@tonic-gate if ((fp = getf(fdes)) == NULL) {
19627c478bd9Sstevel@tonic-gate return (EBADF);
19637c478bd9Sstevel@tonic-gate }
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate /*
19667c478bd9Sstevel@tonic-gate * check the permission of the partition
19677c478bd9Sstevel@tonic-gate */
19687c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) {
19697c478bd9Sstevel@tonic-gate releasef(fdes);
19707c478bd9Sstevel@tonic-gate return (EBADF);
19717c478bd9Sstevel@tonic-gate }
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate vp = fp->f_vnode;
19747c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode);
19757c478bd9Sstevel@tonic-gate if (aio_func == NULL) {
19767c478bd9Sstevel@tonic-gate releasef(fdes);
19777c478bd9Sstevel@tonic-gate return (EBADFD);
19787c478bd9Sstevel@tonic-gate }
19797c478bd9Sstevel@tonic-gate #ifdef _LP64
19807c478bd9Sstevel@tonic-gate aiocb.aio_fildes = fdes;
19817c478bd9Sstevel@tonic-gate aiocb.aio_buf = bufp;
19827c478bd9Sstevel@tonic-gate aiocb.aio_nbytes = bufsize;
19837c478bd9Sstevel@tonic-gate aiocb.aio_offset = offset;
19847c478bd9Sstevel@tonic-gate aiocb.aio_sigevent.sigev_notify = 0;
1985*d2749ac6SRoger A. Faulkner error = aio_req_setup(&reqp, aiop, &aiocb, resultp, vp, 1);
19867c478bd9Sstevel@tonic-gate #else
19877c478bd9Sstevel@tonic-gate aiocb64.aio_fildes = fdes;
19887c478bd9Sstevel@tonic-gate aiocb64.aio_buf = (caddr32_t)bufp;
19897c478bd9Sstevel@tonic-gate aiocb64.aio_nbytes = bufsize;
19907c478bd9Sstevel@tonic-gate aiocb64.aio_offset = offset;
19917c478bd9Sstevel@tonic-gate aiocb64.aio_sigevent.sigev_notify = 0;
1992*d2749ac6SRoger A. Faulkner error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, vp, 1);
19937c478bd9Sstevel@tonic-gate #endif
19947c478bd9Sstevel@tonic-gate if (error) {
19957c478bd9Sstevel@tonic-gate releasef(fdes);
19967c478bd9Sstevel@tonic-gate return (error);
19977c478bd9Sstevel@tonic-gate }
19987c478bd9Sstevel@tonic-gate
19997c478bd9Sstevel@tonic-gate /*
20007c478bd9Sstevel@tonic-gate * enable polling on this request if the opcode has
20017c478bd9Sstevel@tonic-gate * the AIO poll bit set
20027c478bd9Sstevel@tonic-gate */
20037c478bd9Sstevel@tonic-gate if (opcode & AIO_POLL_BIT)
20047c478bd9Sstevel@tonic-gate reqp->aio_req_flags |= AIO_POLL;
20057c478bd9Sstevel@tonic-gate
20067c478bd9Sstevel@tonic-gate if (bufsize == 0) {
20077c478bd9Sstevel@tonic-gate clear_active_fd(fdes);
20087c478bd9Sstevel@tonic-gate aio_zerolen(reqp);
20097c478bd9Sstevel@tonic-gate return (0);
20107c478bd9Sstevel@tonic-gate }
20117c478bd9Sstevel@tonic-gate /*
20127c478bd9Sstevel@tonic-gate * send the request to driver.
20137c478bd9Sstevel@tonic-gate */
20147c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, CRED());
20157c478bd9Sstevel@tonic-gate /*
20167c478bd9Sstevel@tonic-gate * the fd is stored in the aio_req_t by aio_req_setup(), and
20177c478bd9Sstevel@tonic-gate * is released by the aio_cleanup_thread() when the IO has
20187c478bd9Sstevel@tonic-gate * completed.
20197c478bd9Sstevel@tonic-gate */
20207c478bd9Sstevel@tonic-gate if (error) {
20217c478bd9Sstevel@tonic-gate releasef(fdes);
20227c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
20237c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
20247c478bd9Sstevel@tonic-gate aiop->aio_pending--;
20257c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK)
20267c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv);
20277c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
20287c478bd9Sstevel@tonic-gate return (error);
20297c478bd9Sstevel@tonic-gate }
20307c478bd9Sstevel@tonic-gate clear_active_fd(fdes);
20317c478bd9Sstevel@tonic-gate return (0);
20327c478bd9Sstevel@tonic-gate }
20337c478bd9Sstevel@tonic-gate
20347c478bd9Sstevel@tonic-gate /*
20357c478bd9Sstevel@tonic-gate * posix version of asynchronous read and write
20367c478bd9Sstevel@tonic-gate */
20377c478bd9Sstevel@tonic-gate static int
aiorw(int opcode,void * aiocb_arg,int mode,int run_mode)20387c478bd9Sstevel@tonic-gate aiorw(
20397c478bd9Sstevel@tonic-gate int opcode,
20407c478bd9Sstevel@tonic-gate void *aiocb_arg,
20417c478bd9Sstevel@tonic-gate int mode,
20427c478bd9Sstevel@tonic-gate int run_mode)
20437c478bd9Sstevel@tonic-gate {
20447c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
20457c478bd9Sstevel@tonic-gate aiocb32_t aiocb32;
20467c478bd9Sstevel@tonic-gate struct sigevent32 *sigev32;
20477c478bd9Sstevel@tonic-gate port_notify32_t pntfy32;
20487c478bd9Sstevel@tonic-gate #endif
20497c478bd9Sstevel@tonic-gate aiocb64_32_t aiocb64;
20507c478bd9Sstevel@tonic-gate aiocb_t aiocb;
20517c478bd9Sstevel@tonic-gate file_t *fp;
20527c478bd9Sstevel@tonic-gate int error, fd;
20537c478bd9Sstevel@tonic-gate size_t bufsize;
20547c478bd9Sstevel@tonic-gate struct vnode *vp;
20557c478bd9Sstevel@tonic-gate aio_req_t *reqp;
20567c478bd9Sstevel@tonic-gate aio_t *aiop;
20577c478bd9Sstevel@tonic-gate int (*aio_func)();
20587c478bd9Sstevel@tonic-gate aio_result_t *resultp;
20597c478bd9Sstevel@tonic-gate struct sigevent *sigev;
20607c478bd9Sstevel@tonic-gate model_t model;
20617c478bd9Sstevel@tonic-gate int aio_use_port = 0;
20627c478bd9Sstevel@tonic-gate port_notify_t pntfy;
20637c478bd9Sstevel@tonic-gate
20647c478bd9Sstevel@tonic-gate model = get_udatamodel();
20657c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
20667c478bd9Sstevel@tonic-gate if (aiop == NULL)
20677c478bd9Sstevel@tonic-gate return (EINVAL);
20687c478bd9Sstevel@tonic-gate
20697c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) {
20707c478bd9Sstevel@tonic-gate if (run_mode != AIO_LARGEFILE) {
20717c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb, sizeof (aiocb_t)))
20727c478bd9Sstevel@tonic-gate return (EFAULT);
20737c478bd9Sstevel@tonic-gate bufsize = aiocb.aio_nbytes;
20747c478bd9Sstevel@tonic-gate resultp = &(((aiocb_t *)aiocb_arg)->aio_resultp);
20757c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb.aio_fildes)) == NULL) {
20767c478bd9Sstevel@tonic-gate return (EBADF);
20777c478bd9Sstevel@tonic-gate }
20787c478bd9Sstevel@tonic-gate sigev = &aiocb.aio_sigevent;
20797c478bd9Sstevel@tonic-gate } else {
20807c478bd9Sstevel@tonic-gate /*
20817c478bd9Sstevel@tonic-gate * We come here only when we make largefile
20827c478bd9Sstevel@tonic-gate * call on 32 bit kernel using 32 bit library.
20837c478bd9Sstevel@tonic-gate */
20847c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb64, sizeof (aiocb64_32_t)))
20857c478bd9Sstevel@tonic-gate return (EFAULT);
20867c478bd9Sstevel@tonic-gate bufsize = aiocb64.aio_nbytes;
20877c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&(((aiocb64_32_t *)aiocb_arg)
20887c478bd9Sstevel@tonic-gate ->aio_resultp);
208934709573Sraf if ((fp = getf(fd = aiocb64.aio_fildes)) == NULL)
20907c478bd9Sstevel@tonic-gate return (EBADF);
20917c478bd9Sstevel@tonic-gate sigev = (struct sigevent *)&aiocb64.aio_sigevent;
20927c478bd9Sstevel@tonic-gate }
20937c478bd9Sstevel@tonic-gate
20947c478bd9Sstevel@tonic-gate if (sigev->sigev_notify == SIGEV_PORT) {
20957c478bd9Sstevel@tonic-gate if (copyin((void *)sigev->sigev_value.sival_ptr,
20967c478bd9Sstevel@tonic-gate &pntfy, sizeof (port_notify_t))) {
20977c478bd9Sstevel@tonic-gate releasef(fd);
20987c478bd9Sstevel@tonic-gate return (EFAULT);
20997c478bd9Sstevel@tonic-gate }
21007c478bd9Sstevel@tonic-gate aio_use_port = 1;
210134709573Sraf } else if (sigev->sigev_notify == SIGEV_THREAD) {
210234709573Sraf pntfy.portnfy_port = aiocb.aio_sigevent.sigev_signo;
210334709573Sraf pntfy.portnfy_user =
210434709573Sraf aiocb.aio_sigevent.sigev_value.sival_ptr;
210534709573Sraf aio_use_port = 1;
21067c478bd9Sstevel@tonic-gate }
21077c478bd9Sstevel@tonic-gate }
21087c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
21097c478bd9Sstevel@tonic-gate else {
21107c478bd9Sstevel@tonic-gate if (run_mode == AIO_32) {
21117c478bd9Sstevel@tonic-gate /* 32 bit system call is being made on 64 bit kernel */
21127c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb32, sizeof (aiocb32_t)))
21137c478bd9Sstevel@tonic-gate return (EFAULT);
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate bufsize = aiocb32.aio_nbytes;
21167c478bd9Sstevel@tonic-gate aiocb_32ton(&aiocb32, &aiocb);
21177c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&(((aiocb32_t *)aiocb_arg)->
21187c478bd9Sstevel@tonic-gate aio_resultp);
21197c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb32.aio_fildes)) == NULL) {
21207c478bd9Sstevel@tonic-gate return (EBADF);
21217c478bd9Sstevel@tonic-gate }
21227c478bd9Sstevel@tonic-gate sigev32 = &aiocb32.aio_sigevent;
21237c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_LARGEFILE) {
21247c478bd9Sstevel@tonic-gate /*
21257c478bd9Sstevel@tonic-gate * We come here only when we make largefile
21267c478bd9Sstevel@tonic-gate * call on 64 bit kernel using 32 bit library.
21277c478bd9Sstevel@tonic-gate */
21287c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb64, sizeof (aiocb64_32_t)))
21297c478bd9Sstevel@tonic-gate return (EFAULT);
21307c478bd9Sstevel@tonic-gate bufsize = aiocb64.aio_nbytes;
21317c478bd9Sstevel@tonic-gate aiocb_LFton(&aiocb64, &aiocb);
21327c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&(((aiocb64_32_t *)aiocb_arg)
21337c478bd9Sstevel@tonic-gate ->aio_resultp);
21347c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb64.aio_fildes)) == NULL)
21357c478bd9Sstevel@tonic-gate return (EBADF);
21367c478bd9Sstevel@tonic-gate sigev32 = &aiocb64.aio_sigevent;
21377c478bd9Sstevel@tonic-gate }
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate if (sigev32->sigev_notify == SIGEV_PORT) {
21407c478bd9Sstevel@tonic-gate if (copyin(
21417c478bd9Sstevel@tonic-gate (void *)(uintptr_t)sigev32->sigev_value.sival_ptr,
21427c478bd9Sstevel@tonic-gate &pntfy32, sizeof (port_notify32_t))) {
21437c478bd9Sstevel@tonic-gate releasef(fd);
21447c478bd9Sstevel@tonic-gate return (EFAULT);
21457c478bd9Sstevel@tonic-gate }
21467c478bd9Sstevel@tonic-gate pntfy.portnfy_port = pntfy32.portnfy_port;
214734709573Sraf pntfy.portnfy_user = (void *)(uintptr_t)
214834709573Sraf pntfy32.portnfy_user;
214934709573Sraf aio_use_port = 1;
215034709573Sraf } else if (sigev32->sigev_notify == SIGEV_THREAD) {
215134709573Sraf pntfy.portnfy_port = sigev32->sigev_signo;
215234709573Sraf pntfy.portnfy_user = (void *)(uintptr_t)
215334709573Sraf sigev32->sigev_value.sival_ptr;
21547c478bd9Sstevel@tonic-gate aio_use_port = 1;
21557c478bd9Sstevel@tonic-gate }
21567c478bd9Sstevel@tonic-gate }
21577c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate /*
21607c478bd9Sstevel@tonic-gate * check the permission of the partition
21617c478bd9Sstevel@tonic-gate */
21627c478bd9Sstevel@tonic-gate
21637c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) {
21647c478bd9Sstevel@tonic-gate releasef(fd);
21657c478bd9Sstevel@tonic-gate return (EBADF);
21667c478bd9Sstevel@tonic-gate }
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate vp = fp->f_vnode;
21697c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode);
21707c478bd9Sstevel@tonic-gate if (aio_func == NULL) {
21717c478bd9Sstevel@tonic-gate releasef(fd);
21727c478bd9Sstevel@tonic-gate return (EBADFD);
21737c478bd9Sstevel@tonic-gate }
217434709573Sraf if (run_mode == AIO_LARGEFILE)
2175*d2749ac6SRoger A. Faulkner error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, vp, 0);
21767c478bd9Sstevel@tonic-gate else
2177*d2749ac6SRoger A. Faulkner error = aio_req_setup(&reqp, aiop, &aiocb, resultp, vp, 0);
21787c478bd9Sstevel@tonic-gate
21797c478bd9Sstevel@tonic-gate if (error) {
21807c478bd9Sstevel@tonic-gate releasef(fd);
21817c478bd9Sstevel@tonic-gate return (error);
21827c478bd9Sstevel@tonic-gate }
21837c478bd9Sstevel@tonic-gate /*
21847c478bd9Sstevel@tonic-gate * enable polling on this request if the opcode has
21857c478bd9Sstevel@tonic-gate * the AIO poll bit set
21867c478bd9Sstevel@tonic-gate */
21877c478bd9Sstevel@tonic-gate if (opcode & AIO_POLL_BIT)
21887c478bd9Sstevel@tonic-gate reqp->aio_req_flags |= AIO_POLL;
21897c478bd9Sstevel@tonic-gate
21907c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE)
21917c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = aiocb_arg;
21927c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
21937c478bd9Sstevel@tonic-gate else
21947c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32 = (caddr32_t)(uintptr_t)aiocb_arg;
21957c478bd9Sstevel@tonic-gate #endif
21967c478bd9Sstevel@tonic-gate
219734709573Sraf if (aio_use_port) {
219834709573Sraf int event = (run_mode == AIO_LARGEFILE)?
219934709573Sraf ((mode == FREAD)? AIOAREAD64 : AIOAWRITE64) :
220034709573Sraf ((mode == FREAD)? AIOAREAD : AIOAWRITE);
220134709573Sraf error = aio_req_assoc_port_rw(&pntfy, aiocb_arg, reqp, event);
220234709573Sraf }
22037c478bd9Sstevel@tonic-gate
22047c478bd9Sstevel@tonic-gate /*
22057c478bd9Sstevel@tonic-gate * send the request to driver.
22067c478bd9Sstevel@tonic-gate */
22077c478bd9Sstevel@tonic-gate if (error == 0) {
22087c478bd9Sstevel@tonic-gate if (bufsize == 0) {
22097c478bd9Sstevel@tonic-gate clear_active_fd(fd);
22107c478bd9Sstevel@tonic-gate aio_zerolen(reqp);
22117c478bd9Sstevel@tonic-gate return (0);
22127c478bd9Sstevel@tonic-gate }
22137c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, CRED());
22147c478bd9Sstevel@tonic-gate }
22157c478bd9Sstevel@tonic-gate
22167c478bd9Sstevel@tonic-gate /*
22177c478bd9Sstevel@tonic-gate * the fd is stored in the aio_req_t by aio_req_setup(), and
22187c478bd9Sstevel@tonic-gate * is released by the aio_cleanup_thread() when the IO has
22197c478bd9Sstevel@tonic-gate * completed.
22207c478bd9Sstevel@tonic-gate */
22217c478bd9Sstevel@tonic-gate if (error) {
22227c478bd9Sstevel@tonic-gate releasef(fd);
22237c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
222434b3058fSpraks if (aio_use_port)
222534709573Sraf aio_deq(&aiop->aio_portpending, reqp);
22267c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
22277c478bd9Sstevel@tonic-gate aiop->aio_pending--;
22287c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK)
22297c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv);
22307c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
22317c478bd9Sstevel@tonic-gate return (error);
22327c478bd9Sstevel@tonic-gate }
22337c478bd9Sstevel@tonic-gate clear_active_fd(fd);
22347c478bd9Sstevel@tonic-gate return (0);
22357c478bd9Sstevel@tonic-gate }
22367c478bd9Sstevel@tonic-gate
22377c478bd9Sstevel@tonic-gate
22387c478bd9Sstevel@tonic-gate /*
22397c478bd9Sstevel@tonic-gate * set error for a list IO entry that failed.
22407c478bd9Sstevel@tonic-gate */
22417c478bd9Sstevel@tonic-gate static void
lio_set_error(aio_req_t * reqp,int portused)224234b3058fSpraks lio_set_error(aio_req_t *reqp, int portused)
22437c478bd9Sstevel@tonic-gate {
22447c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
22457c478bd9Sstevel@tonic-gate
22467c478bd9Sstevel@tonic-gate if (aiop == NULL)
22477c478bd9Sstevel@tonic-gate return;
22487c478bd9Sstevel@tonic-gate
22497c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
225034b3058fSpraks if (portused)
225134709573Sraf aio_deq(&aiop->aio_portpending, reqp);
22527c478bd9Sstevel@tonic-gate aiop->aio_pending--;
22537c478bd9Sstevel@tonic-gate /* request failed, AIO_PHYSIODONE set to aviod physio cleanup. */
22547c478bd9Sstevel@tonic-gate reqp->aio_req_flags |= AIO_PHYSIODONE;
22557c478bd9Sstevel@tonic-gate /*
22567c478bd9Sstevel@tonic-gate * Need to free the request now as its never
22577c478bd9Sstevel@tonic-gate * going to get on the done queue
22587c478bd9Sstevel@tonic-gate *
22597c478bd9Sstevel@tonic-gate * Note: aio_outstanding is decremented in
22607c478bd9Sstevel@tonic-gate * aio_req_free()
22617c478bd9Sstevel@tonic-gate */
22627c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp);
22637c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK)
22647c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv);
22657c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
22667c478bd9Sstevel@tonic-gate }
22677c478bd9Sstevel@tonic-gate
22687c478bd9Sstevel@tonic-gate /*
22697c478bd9Sstevel@tonic-gate * check if a specified request is done, and remove it from
22707c478bd9Sstevel@tonic-gate * the done queue. otherwise remove anybody from the done queue
22717c478bd9Sstevel@tonic-gate * if NULL is specified.
22727c478bd9Sstevel@tonic-gate */
22737c478bd9Sstevel@tonic-gate static aio_req_t *
aio_req_done(void * resultp)22747c478bd9Sstevel@tonic-gate aio_req_done(void *resultp)
22757c478bd9Sstevel@tonic-gate {
22767c478bd9Sstevel@tonic-gate aio_req_t **bucket;
22777c478bd9Sstevel@tonic-gate aio_req_t *ent;
22787c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
22797c478bd9Sstevel@tonic-gate long index;
22807c478bd9Sstevel@tonic-gate
22817c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_cleanupq_mutex));
22827c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex));
22837c478bd9Sstevel@tonic-gate
22847c478bd9Sstevel@tonic-gate if (resultp) {
22857c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp);
22867c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index];
22877c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) {
22887c478bd9Sstevel@tonic-gate if (ent->aio_req_resultp == (aio_result_t *)resultp) {
22897c478bd9Sstevel@tonic-gate if (ent->aio_req_flags & AIO_DONEQ) {
22907c478bd9Sstevel@tonic-gate return (aio_req_remove(ent));
22917c478bd9Sstevel@tonic-gate }
22927c478bd9Sstevel@tonic-gate return (NULL);
22937c478bd9Sstevel@tonic-gate }
22947c478bd9Sstevel@tonic-gate }
22957c478bd9Sstevel@tonic-gate /* no match, resultp is invalid */
22967c478bd9Sstevel@tonic-gate return (NULL);
22977c478bd9Sstevel@tonic-gate }
22987c478bd9Sstevel@tonic-gate return (aio_req_remove(NULL));
22997c478bd9Sstevel@tonic-gate }
23007c478bd9Sstevel@tonic-gate
23017c478bd9Sstevel@tonic-gate /*
23027c478bd9Sstevel@tonic-gate * determine if a user-level resultp pointer is associated with an
23037c478bd9Sstevel@tonic-gate * active IO request. Zero is returned when the request is done,
23047c478bd9Sstevel@tonic-gate * and the request is removed from the done queue. Only when the
23057c478bd9Sstevel@tonic-gate * return value is zero, is the "reqp" pointer valid. One is returned
23067c478bd9Sstevel@tonic-gate * when the request is inprogress. Two is returned when the request
23077c478bd9Sstevel@tonic-gate * is invalid.
23087c478bd9Sstevel@tonic-gate */
23097c478bd9Sstevel@tonic-gate static int
aio_req_find(aio_result_t * resultp,aio_req_t ** reqp)23107c478bd9Sstevel@tonic-gate aio_req_find(aio_result_t *resultp, aio_req_t **reqp)
23117c478bd9Sstevel@tonic-gate {
23127c478bd9Sstevel@tonic-gate aio_req_t **bucket;
23137c478bd9Sstevel@tonic-gate aio_req_t *ent;
23147c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
23157c478bd9Sstevel@tonic-gate long index;
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_cleanupq_mutex));
23187c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex));
23197c478bd9Sstevel@tonic-gate
23207c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp);
23217c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index];
23227c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) {
23237c478bd9Sstevel@tonic-gate if (ent->aio_req_resultp == resultp) {
23247c478bd9Sstevel@tonic-gate if (ent->aio_req_flags & AIO_DONEQ) {
23257c478bd9Sstevel@tonic-gate *reqp = aio_req_remove(ent);
23267c478bd9Sstevel@tonic-gate return (0);
23277c478bd9Sstevel@tonic-gate }
23287c478bd9Sstevel@tonic-gate return (1);
23297c478bd9Sstevel@tonic-gate }
23307c478bd9Sstevel@tonic-gate }
23317c478bd9Sstevel@tonic-gate /* no match, resultp is invalid */
23327c478bd9Sstevel@tonic-gate return (2);
23337c478bd9Sstevel@tonic-gate }
23347c478bd9Sstevel@tonic-gate
23357c478bd9Sstevel@tonic-gate /*
23367c478bd9Sstevel@tonic-gate * remove a request from the done queue.
23377c478bd9Sstevel@tonic-gate */
23387c478bd9Sstevel@tonic-gate static aio_req_t *
aio_req_remove(aio_req_t * reqp)23397c478bd9Sstevel@tonic-gate aio_req_remove(aio_req_t *reqp)
23407c478bd9Sstevel@tonic-gate {
23417c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
23427c478bd9Sstevel@tonic-gate
23437c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex));
23447c478bd9Sstevel@tonic-gate
234534709573Sraf if (reqp != NULL) {
23467c478bd9Sstevel@tonic-gate ASSERT(reqp->aio_req_flags & AIO_DONEQ);
23477c478bd9Sstevel@tonic-gate if (reqp->aio_req_next == reqp) {
23487c478bd9Sstevel@tonic-gate /* only one request on queue */
23497c478bd9Sstevel@tonic-gate if (reqp == aiop->aio_doneq) {
23507c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL;
23517c478bd9Sstevel@tonic-gate } else {
23527c478bd9Sstevel@tonic-gate ASSERT(reqp == aiop->aio_cleanupq);
23537c478bd9Sstevel@tonic-gate aiop->aio_cleanupq = NULL;
23547c478bd9Sstevel@tonic-gate }
23557c478bd9Sstevel@tonic-gate } else {
23567c478bd9Sstevel@tonic-gate reqp->aio_req_next->aio_req_prev = reqp->aio_req_prev;
23577c478bd9Sstevel@tonic-gate reqp->aio_req_prev->aio_req_next = reqp->aio_req_next;
23587c478bd9Sstevel@tonic-gate /*
23597c478bd9Sstevel@tonic-gate * The request can be either on the aio_doneq or the
23607c478bd9Sstevel@tonic-gate * aio_cleanupq
23617c478bd9Sstevel@tonic-gate */
23627c478bd9Sstevel@tonic-gate if (reqp == aiop->aio_doneq)
23637c478bd9Sstevel@tonic-gate aiop->aio_doneq = reqp->aio_req_next;
23647c478bd9Sstevel@tonic-gate
23657c478bd9Sstevel@tonic-gate if (reqp == aiop->aio_cleanupq)
23667c478bd9Sstevel@tonic-gate aiop->aio_cleanupq = reqp->aio_req_next;
23677c478bd9Sstevel@tonic-gate }
23687c478bd9Sstevel@tonic-gate reqp->aio_req_flags &= ~AIO_DONEQ;
236934709573Sraf reqp->aio_req_next = NULL;
237034709573Sraf reqp->aio_req_prev = NULL;
237134709573Sraf } else if ((reqp = aiop->aio_doneq) != NULL) {
237234709573Sraf ASSERT(reqp->aio_req_flags & AIO_DONEQ);
237334709573Sraf if (reqp == reqp->aio_req_next) {
23747c478bd9Sstevel@tonic-gate /* only one request on queue */
23757c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL;
23767c478bd9Sstevel@tonic-gate } else {
237734709573Sraf reqp->aio_req_prev->aio_req_next = reqp->aio_req_next;
237834709573Sraf reqp->aio_req_next->aio_req_prev = reqp->aio_req_prev;
237934709573Sraf aiop->aio_doneq = reqp->aio_req_next;
23807c478bd9Sstevel@tonic-gate }
238134709573Sraf reqp->aio_req_flags &= ~AIO_DONEQ;
238234709573Sraf reqp->aio_req_next = NULL;
238334709573Sraf reqp->aio_req_prev = NULL;
23847c478bd9Sstevel@tonic-gate }
238534709573Sraf if (aiop->aio_doneq == NULL && (aiop->aio_flags & AIO_WAITN))
238634709573Sraf cv_broadcast(&aiop->aio_waitcv);
238734709573Sraf return (reqp);
23887c478bd9Sstevel@tonic-gate }
23897c478bd9Sstevel@tonic-gate
23907c478bd9Sstevel@tonic-gate static int
aio_req_setup(aio_req_t ** reqpp,aio_t * aiop,aiocb_t * arg,aio_result_t * resultp,vnode_t * vp,int old_solaris_req)23917c478bd9Sstevel@tonic-gate aio_req_setup(
23927c478bd9Sstevel@tonic-gate aio_req_t **reqpp,
23937c478bd9Sstevel@tonic-gate aio_t *aiop,
23947c478bd9Sstevel@tonic-gate aiocb_t *arg,
23957c478bd9Sstevel@tonic-gate aio_result_t *resultp,
2396*d2749ac6SRoger A. Faulkner vnode_t *vp,
2397*d2749ac6SRoger A. Faulkner int old_solaris_req)
23987c478bd9Sstevel@tonic-gate {
239934709573Sraf sigqueue_t *sqp = NULL;
24007c478bd9Sstevel@tonic-gate aio_req_t *reqp;
24017c478bd9Sstevel@tonic-gate struct uio *uio;
24027c478bd9Sstevel@tonic-gate struct sigevent *sigev;
24037c478bd9Sstevel@tonic-gate int error;
24047c478bd9Sstevel@tonic-gate
24057c478bd9Sstevel@tonic-gate sigev = &arg->aio_sigevent;
240634709573Sraf if (sigev->sigev_notify == SIGEV_SIGNAL &&
240734709573Sraf sigev->sigev_signo > 0 && sigev->sigev_signo < NSIG) {
24087c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP);
24097c478bd9Sstevel@tonic-gate if (sqp == NULL)
24107c478bd9Sstevel@tonic-gate return (EAGAIN);
24117c478bd9Sstevel@tonic-gate sqp->sq_func = NULL;
24127c478bd9Sstevel@tonic-gate sqp->sq_next = NULL;
24137c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO;
24147c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid;
24157c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc);
24167c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid();
24177c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred);
24187c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigev->sigev_signo;
24197c478bd9Sstevel@tonic-gate sqp->sq_info.si_value = sigev->sigev_value;
242034709573Sraf }
24217c478bd9Sstevel@tonic-gate
24227c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
24237c478bd9Sstevel@tonic-gate
24247c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) {
24257c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
24267c478bd9Sstevel@tonic-gate if (sqp)
24277c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t));
24287c478bd9Sstevel@tonic-gate return (EIO);
24297c478bd9Sstevel@tonic-gate }
24307c478bd9Sstevel@tonic-gate /*
24317c478bd9Sstevel@tonic-gate * get an aio_reqp from the free list or allocate one
24327c478bd9Sstevel@tonic-gate * from dynamic memory.
24337c478bd9Sstevel@tonic-gate */
24347c478bd9Sstevel@tonic-gate if (error = aio_req_alloc(&reqp, resultp)) {
24357c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
24367c478bd9Sstevel@tonic-gate if (sqp)
24377c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t));
24387c478bd9Sstevel@tonic-gate return (error);
24397c478bd9Sstevel@tonic-gate }
24407c478bd9Sstevel@tonic-gate aiop->aio_pending++;
24417c478bd9Sstevel@tonic-gate aiop->aio_outstanding++;
24427c478bd9Sstevel@tonic-gate reqp->aio_req_flags = AIO_PENDING;
2443*d2749ac6SRoger A. Faulkner if (old_solaris_req) {
2444*d2749ac6SRoger A. Faulkner /* this is an old solaris aio request */
2445*d2749ac6SRoger A. Faulkner reqp->aio_req_flags |= AIO_SOLARIS;
2446*d2749ac6SRoger A. Faulkner aiop->aio_flags |= AIO_SOLARIS_REQ;
2447*d2749ac6SRoger A. Faulkner }
244834709573Sraf if (sigev->sigev_notify == SIGEV_THREAD ||
244934709573Sraf sigev->sigev_notify == SIGEV_PORT)
245034709573Sraf aio_enq(&aiop->aio_portpending, reqp, 0);
24517c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
24527c478bd9Sstevel@tonic-gate /*
24537c478bd9Sstevel@tonic-gate * initialize aio request.
24547c478bd9Sstevel@tonic-gate */
24557c478bd9Sstevel@tonic-gate reqp->aio_req_fd = arg->aio_fildes;
24567c478bd9Sstevel@tonic-gate reqp->aio_req_sigqp = sqp;
24577c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = NULL;
245834709573Sraf reqp->aio_req_lio = NULL;
24597c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_file = vp;
24607c478bd9Sstevel@tonic-gate uio = reqp->aio_req.aio_uio;
24617c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1;
24627c478bd9Sstevel@tonic-gate uio->uio_iov->iov_base = (caddr_t)arg->aio_buf;
24637c478bd9Sstevel@tonic-gate uio->uio_iov->iov_len = arg->aio_nbytes;
24647c478bd9Sstevel@tonic-gate uio->uio_loffset = arg->aio_offset;
24657c478bd9Sstevel@tonic-gate *reqpp = reqp;
24667c478bd9Sstevel@tonic-gate return (0);
24677c478bd9Sstevel@tonic-gate }
24687c478bd9Sstevel@tonic-gate
24697c478bd9Sstevel@tonic-gate /*
24707c478bd9Sstevel@tonic-gate * Allocate p_aio struct.
24717c478bd9Sstevel@tonic-gate */
24727c478bd9Sstevel@tonic-gate static aio_t *
aio_aiop_alloc(void)24737c478bd9Sstevel@tonic-gate aio_aiop_alloc(void)
24747c478bd9Sstevel@tonic-gate {
24757c478bd9Sstevel@tonic-gate aio_t *aiop;
24767c478bd9Sstevel@tonic-gate
24777c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&curproc->p_lock));
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate aiop = kmem_zalloc(sizeof (struct aio), KM_NOSLEEP);
24807c478bd9Sstevel@tonic-gate if (aiop) {
24817c478bd9Sstevel@tonic-gate mutex_init(&aiop->aio_mutex, NULL, MUTEX_DEFAULT, NULL);
24827c478bd9Sstevel@tonic-gate mutex_init(&aiop->aio_cleanupq_mutex, NULL, MUTEX_DEFAULT,
24837c478bd9Sstevel@tonic-gate NULL);
24847c478bd9Sstevel@tonic-gate mutex_init(&aiop->aio_portq_mutex, NULL, MUTEX_DEFAULT, NULL);
24857c478bd9Sstevel@tonic-gate }
24867c478bd9Sstevel@tonic-gate return (aiop);
24877c478bd9Sstevel@tonic-gate }
24887c478bd9Sstevel@tonic-gate
24897c478bd9Sstevel@tonic-gate /*
24907c478bd9Sstevel@tonic-gate * Allocate an aio_req struct.
24917c478bd9Sstevel@tonic-gate */
24927c478bd9Sstevel@tonic-gate static int
aio_req_alloc(aio_req_t ** nreqp,aio_result_t * resultp)24937c478bd9Sstevel@tonic-gate aio_req_alloc(aio_req_t **nreqp, aio_result_t *resultp)
24947c478bd9Sstevel@tonic-gate {
24957c478bd9Sstevel@tonic-gate aio_req_t *reqp;
24967c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
24977c478bd9Sstevel@tonic-gate
24987c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex));
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate if ((reqp = aiop->aio_free) != NULL) {
25017c478bd9Sstevel@tonic-gate aiop->aio_free = reqp->aio_req_next;
250234709573Sraf bzero(reqp, sizeof (*reqp));
25037c478bd9Sstevel@tonic-gate } else {
25047c478bd9Sstevel@tonic-gate /*
25057c478bd9Sstevel@tonic-gate * Check whether memory is getting tight.
25067c478bd9Sstevel@tonic-gate * This is a temporary mechanism to avoid memory
25077c478bd9Sstevel@tonic-gate * exhaustion by a single process until we come up
25087c478bd9Sstevel@tonic-gate * with a per process solution such as setrlimit().
25097c478bd9Sstevel@tonic-gate */
25107c478bd9Sstevel@tonic-gate if (freemem < desfree)
25117c478bd9Sstevel@tonic-gate return (EAGAIN);
25127c478bd9Sstevel@tonic-gate reqp = kmem_zalloc(sizeof (struct aio_req_t), KM_NOSLEEP);
25137c478bd9Sstevel@tonic-gate if (reqp == NULL)
25147c478bd9Sstevel@tonic-gate return (EAGAIN);
25157c478bd9Sstevel@tonic-gate }
251634709573Sraf reqp->aio_req.aio_uio = &reqp->aio_req_uio;
251734709573Sraf reqp->aio_req.aio_uio->uio_iov = &reqp->aio_req_iov;
251834709573Sraf reqp->aio_req.aio_private = reqp;
25197c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_offset = -1;
25207c478bd9Sstevel@tonic-gate reqp->aio_req_resultp = resultp;
25217c478bd9Sstevel@tonic-gate if (aio_hash_insert(reqp, aiop)) {
25227c478bd9Sstevel@tonic-gate reqp->aio_req_next = aiop->aio_free;
25237c478bd9Sstevel@tonic-gate aiop->aio_free = reqp;
252475e1bcdeSPrakash Sangappa return (EBUSY);
25257c478bd9Sstevel@tonic-gate }
25267c478bd9Sstevel@tonic-gate *nreqp = reqp;
25277c478bd9Sstevel@tonic-gate return (0);
25287c478bd9Sstevel@tonic-gate }
25297c478bd9Sstevel@tonic-gate
25307c478bd9Sstevel@tonic-gate /*
25317c478bd9Sstevel@tonic-gate * Allocate an aio_lio_t struct.
25327c478bd9Sstevel@tonic-gate */
25337c478bd9Sstevel@tonic-gate static int
aio_lio_alloc(aio_lio_t ** head)25347c478bd9Sstevel@tonic-gate aio_lio_alloc(aio_lio_t **head)
25357c478bd9Sstevel@tonic-gate {
25367c478bd9Sstevel@tonic-gate aio_lio_t *liop;
25377c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
25387c478bd9Sstevel@tonic-gate
25397c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex));
25407c478bd9Sstevel@tonic-gate
25417c478bd9Sstevel@tonic-gate if ((liop = aiop->aio_lio_free) != NULL) {
25427c478bd9Sstevel@tonic-gate aiop->aio_lio_free = liop->lio_next;
25437c478bd9Sstevel@tonic-gate } else {
25447c478bd9Sstevel@tonic-gate /*
25457c478bd9Sstevel@tonic-gate * Check whether memory is getting tight.
25467c478bd9Sstevel@tonic-gate * This is a temporary mechanism to avoid memory
25477c478bd9Sstevel@tonic-gate * exhaustion by a single process until we come up
25487c478bd9Sstevel@tonic-gate * with a per process solution such as setrlimit().
25497c478bd9Sstevel@tonic-gate */
25507c478bd9Sstevel@tonic-gate if (freemem < desfree)
25517c478bd9Sstevel@tonic-gate return (EAGAIN);
25527c478bd9Sstevel@tonic-gate
25537c478bd9Sstevel@tonic-gate liop = kmem_zalloc(sizeof (aio_lio_t), KM_NOSLEEP);
25547c478bd9Sstevel@tonic-gate if (liop == NULL)
25557c478bd9Sstevel@tonic-gate return (EAGAIN);
25567c478bd9Sstevel@tonic-gate }
25577c478bd9Sstevel@tonic-gate *head = liop;
25587c478bd9Sstevel@tonic-gate return (0);
25597c478bd9Sstevel@tonic-gate }
25607c478bd9Sstevel@tonic-gate
25617c478bd9Sstevel@tonic-gate /*
25627c478bd9Sstevel@tonic-gate * this is a special per-process thread that is only activated if
25637c478bd9Sstevel@tonic-gate * the process is unmapping a segment with outstanding aio. normally,
25647c478bd9Sstevel@tonic-gate * the process will have completed the aio before unmapping the
25657c478bd9Sstevel@tonic-gate * segment. If the process does unmap a segment with outstanding aio,
25667c478bd9Sstevel@tonic-gate * this special thread will guarentee that the locked pages due to
25677c478bd9Sstevel@tonic-gate * aphysio() are released, thereby permitting the segment to be
2568b0b27ce6Spraks * unmapped. In addition to this, the cleanup thread is woken up
2569b0b27ce6Spraks * during DR operations to release the locked pages.
25707c478bd9Sstevel@tonic-gate */
25717c478bd9Sstevel@tonic-gate
25727c478bd9Sstevel@tonic-gate static int
aio_cleanup_thread(aio_t * aiop)25737c478bd9Sstevel@tonic-gate aio_cleanup_thread(aio_t *aiop)
25747c478bd9Sstevel@tonic-gate {
25757c478bd9Sstevel@tonic-gate proc_t *p = curproc;
25767c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
25777c478bd9Sstevel@tonic-gate int poked = 0;
25787c478bd9Sstevel@tonic-gate kcondvar_t *cvp;
25797c478bd9Sstevel@tonic-gate int exit_flag = 0;
2580b0b27ce6Spraks int rqclnup = 0;
25817c478bd9Sstevel@tonic-gate
25827c478bd9Sstevel@tonic-gate sigfillset(&curthread->t_hold);
25837c478bd9Sstevel@tonic-gate sigdiffset(&curthread->t_hold, &cantmask);
25847c478bd9Sstevel@tonic-gate for (;;) {
25857c478bd9Sstevel@tonic-gate /*
25867c478bd9Sstevel@tonic-gate * if a segment is being unmapped, and the current
25877c478bd9Sstevel@tonic-gate * process's done queue is not empty, then every request
25887c478bd9Sstevel@tonic-gate * on the doneq with locked resources should be forced
25897c478bd9Sstevel@tonic-gate * to release their locks. By moving the doneq request
25907c478bd9Sstevel@tonic-gate * to the cleanupq, aio_cleanup() will process the cleanupq,
25917c478bd9Sstevel@tonic-gate * and place requests back onto the doneq. All requests
25927c478bd9Sstevel@tonic-gate * processed by aio_cleanup() will have their physical
25937c478bd9Sstevel@tonic-gate * resources unlocked.
25947c478bd9Sstevel@tonic-gate */
25957c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
25967c478bd9Sstevel@tonic-gate if ((aiop->aio_flags & AIO_CLEANUP) == 0) {
25977c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_CLEANUP;
25987c478bd9Sstevel@tonic-gate mutex_enter(&as->a_contents);
2599b0b27ce6Spraks if (aiop->aio_rqclnup) {
2600b0b27ce6Spraks aiop->aio_rqclnup = 0;
2601b0b27ce6Spraks rqclnup = 1;
2602b0b27ce6Spraks }
26037c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents);
260416660111SSurya Prakki if (aiop->aio_doneq) {
260516660111SSurya Prakki aio_req_t *doneqhead = aiop->aio_doneq;
26067c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL;
26077c478bd9Sstevel@tonic-gate aio_cleanupq_concat(aiop, doneqhead, AIO_DONEQ);
26087c478bd9Sstevel@tonic-gate }
26097c478bd9Sstevel@tonic-gate }
26107c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
26117c478bd9Sstevel@tonic-gate aio_cleanup(AIO_CLEANUP_THREAD);
26127c478bd9Sstevel@tonic-gate /*
26137c478bd9Sstevel@tonic-gate * thread should block on the cleanupcv while
26147c478bd9Sstevel@tonic-gate * AIO_CLEANUP is set.
26157c478bd9Sstevel@tonic-gate */
26167c478bd9Sstevel@tonic-gate cvp = &aiop->aio_cleanupcv;
26177c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
26187c478bd9Sstevel@tonic-gate
26197c478bd9Sstevel@tonic-gate if (aiop->aio_pollq != NULL || aiop->aio_cleanupq != NULL ||
26207c478bd9Sstevel@tonic-gate aiop->aio_notifyq != NULL ||
26217c478bd9Sstevel@tonic-gate aiop->aio_portcleanupq != NULL) {
26227c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
26237c478bd9Sstevel@tonic-gate continue;
26247c478bd9Sstevel@tonic-gate }
26257c478bd9Sstevel@tonic-gate mutex_enter(&as->a_contents);
26267c478bd9Sstevel@tonic-gate
26277c478bd9Sstevel@tonic-gate /*
26287c478bd9Sstevel@tonic-gate * AIO_CLEANUP determines when the cleanup thread
2629b0b27ce6Spraks * should be active. This flag is set when
2630b0b27ce6Spraks * the cleanup thread is awakened by as_unmap() or
2631b0b27ce6Spraks * due to DR operations.
26327c478bd9Sstevel@tonic-gate * The flag is cleared when the blocking as_unmap()
26337c478bd9Sstevel@tonic-gate * that originally awakened us is allowed to
26347c478bd9Sstevel@tonic-gate * complete. as_unmap() blocks when trying to
26357c478bd9Sstevel@tonic-gate * unmap a segment that has SOFTLOCKed pages. when
26367c478bd9Sstevel@tonic-gate * the segment's pages are all SOFTUNLOCKed,
2637b0b27ce6Spraks * as->a_flags & AS_UNMAPWAIT should be zero.
2638b0b27ce6Spraks *
2639b0b27ce6Spraks * In case of cleanup request by DR, the flag is cleared
2640b0b27ce6Spraks * once all the pending aio requests have been processed.
2641b0b27ce6Spraks *
2642b0b27ce6Spraks * The flag shouldn't be cleared right away if the
2643b0b27ce6Spraks * cleanup thread was interrupted because the process
2644b0b27ce6Spraks * is doing forkall(). This happens when cv_wait_sig()
2645b0b27ce6Spraks * returns zero, because it was awakened by a pokelwps().
2646b0b27ce6Spraks * If the process is not exiting, it must be doing forkall().
26477c478bd9Sstevel@tonic-gate */
26487c478bd9Sstevel@tonic-gate if ((poked == 0) &&
2649b0b27ce6Spraks ((!rqclnup && (AS_ISUNMAPWAIT(as) == 0)) ||
2650b0b27ce6Spraks (aiop->aio_pending == 0))) {
26517c478bd9Sstevel@tonic-gate aiop->aio_flags &= ~(AIO_CLEANUP | AIO_CLEANUP_PORT);
26527c478bd9Sstevel@tonic-gate cvp = &as->a_cv;
2653b0b27ce6Spraks rqclnup = 0;
26547c478bd9Sstevel@tonic-gate }
26557c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
26567c478bd9Sstevel@tonic-gate if (poked) {
26577c478bd9Sstevel@tonic-gate /*
26587c478bd9Sstevel@tonic-gate * If the process is exiting/killed, don't return
26597c478bd9Sstevel@tonic-gate * immediately without waiting for pending I/O's
26607c478bd9Sstevel@tonic-gate * and releasing the page locks.
26617c478bd9Sstevel@tonic-gate */
26627c478bd9Sstevel@tonic-gate if (p->p_flag & (SEXITLWPS|SKILLED)) {
26637c478bd9Sstevel@tonic-gate /*
26647c478bd9Sstevel@tonic-gate * If exit_flag is set, then it is
26657c478bd9Sstevel@tonic-gate * safe to exit because we have released
26667c478bd9Sstevel@tonic-gate * page locks of completed I/O's.
26677c478bd9Sstevel@tonic-gate */
26687c478bd9Sstevel@tonic-gate if (exit_flag)
26697c478bd9Sstevel@tonic-gate break;
26707c478bd9Sstevel@tonic-gate
26717c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents);
26727c478bd9Sstevel@tonic-gate
26737c478bd9Sstevel@tonic-gate /*
26747c478bd9Sstevel@tonic-gate * Wait for all the pending aio to complete.
26757c478bd9Sstevel@tonic-gate */
26767c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
26777c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_REQ_BLOCK;
26787c478bd9Sstevel@tonic-gate while (aiop->aio_pending != 0)
26797c478bd9Sstevel@tonic-gate cv_wait(&aiop->aio_cleanupcv,
26807c478bd9Sstevel@tonic-gate &aiop->aio_mutex);
26817c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
26827c478bd9Sstevel@tonic-gate exit_flag = 1;
26837c478bd9Sstevel@tonic-gate continue;
26847c478bd9Sstevel@tonic-gate } else if (p->p_flag &
26857c478bd9Sstevel@tonic-gate (SHOLDFORK|SHOLDFORK1|SHOLDWATCH)) {
26867c478bd9Sstevel@tonic-gate /*
26877c478bd9Sstevel@tonic-gate * hold LWP until it
26887c478bd9Sstevel@tonic-gate * is continued.
26897c478bd9Sstevel@tonic-gate */
26907c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents);
26917c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
26927c478bd9Sstevel@tonic-gate stop(PR_SUSPENDED, SUSPEND_NORMAL);
26937c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
26947c478bd9Sstevel@tonic-gate poked = 0;
26957c478bd9Sstevel@tonic-gate continue;
26967c478bd9Sstevel@tonic-gate }
26977c478bd9Sstevel@tonic-gate } else {
26987c478bd9Sstevel@tonic-gate /*
26997c478bd9Sstevel@tonic-gate * When started this thread will sleep on as->a_cv.
27007c478bd9Sstevel@tonic-gate * as_unmap will awake this thread if the
27017c478bd9Sstevel@tonic-gate * segment has SOFTLOCKed pages (poked = 0).
27027c478bd9Sstevel@tonic-gate * 1. pokelwps() awakes this thread =>
27037c478bd9Sstevel@tonic-gate * break the loop to check SEXITLWPS, SHOLDFORK, etc
27047c478bd9Sstevel@tonic-gate * 2. as_unmap awakes this thread =>
27057c478bd9Sstevel@tonic-gate * to break the loop it is necessary that
27067c478bd9Sstevel@tonic-gate * - AS_UNMAPWAIT is set (as_unmap is waiting for
27077c478bd9Sstevel@tonic-gate * memory to be unlocked)
27087c478bd9Sstevel@tonic-gate * - AIO_CLEANUP is not set
27097c478bd9Sstevel@tonic-gate * (if AIO_CLEANUP is set we have to wait for
27107c478bd9Sstevel@tonic-gate * pending requests. aio_done will send a signal
27117c478bd9Sstevel@tonic-gate * for every request which completes to continue
27127c478bd9Sstevel@tonic-gate * unmapping the corresponding address range)
2713b0b27ce6Spraks * 3. A cleanup request will wake this thread up, ex.
2714b0b27ce6Spraks * by the DR operations. The aio_rqclnup flag will
2715b0b27ce6Spraks * be set.
27167c478bd9Sstevel@tonic-gate */
27177c478bd9Sstevel@tonic-gate while (poked == 0) {
2718b0b27ce6Spraks /*
2719fa7f62f0Ssp92102 * The clean up requests that came in
2720fa7f62f0Ssp92102 * after we had just cleaned up, couldn't
2721fa7f62f0Ssp92102 * be causing the unmap thread to block - as
2722fa7f62f0Ssp92102 * unmap event happened first.
2723fa7f62f0Ssp92102 * Let aio_done() wake us up if it sees a need.
2724b0b27ce6Spraks */
2725fa7f62f0Ssp92102 if (aiop->aio_rqclnup &&
2726b0b27ce6Spraks (aiop->aio_flags & AIO_CLEANUP) == 0)
27277c478bd9Sstevel@tonic-gate break;
27287c478bd9Sstevel@tonic-gate poked = !cv_wait_sig(cvp, &as->a_contents);
27297c478bd9Sstevel@tonic-gate if (AS_ISUNMAPWAIT(as) == 0)
27307c478bd9Sstevel@tonic-gate cv_signal(cvp);
27317c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding != 0)
27327c478bd9Sstevel@tonic-gate break;
27337c478bd9Sstevel@tonic-gate }
27347c478bd9Sstevel@tonic-gate }
27357c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents);
27367c478bd9Sstevel@tonic-gate }
27377c478bd9Sstevel@tonic-gate exit:
27387c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents);
27397c478bd9Sstevel@tonic-gate ASSERT((curproc->p_flag & (SEXITLWPS|SKILLED)));
27407c478bd9Sstevel@tonic-gate aston(curthread); /* make thread do post_syscall */
27417c478bd9Sstevel@tonic-gate return (0);
27427c478bd9Sstevel@tonic-gate }
27437c478bd9Sstevel@tonic-gate
27447c478bd9Sstevel@tonic-gate /*
27457c478bd9Sstevel@tonic-gate * save a reference to a user's outstanding aio in a hash list.
27467c478bd9Sstevel@tonic-gate */
27477c478bd9Sstevel@tonic-gate static int
aio_hash_insert(aio_req_t * aio_reqp,aio_t * aiop)27487c478bd9Sstevel@tonic-gate aio_hash_insert(
27497c478bd9Sstevel@tonic-gate aio_req_t *aio_reqp,
27507c478bd9Sstevel@tonic-gate aio_t *aiop)
27517c478bd9Sstevel@tonic-gate {
27527c478bd9Sstevel@tonic-gate long index;
27537c478bd9Sstevel@tonic-gate aio_result_t *resultp = aio_reqp->aio_req_resultp;
27547c478bd9Sstevel@tonic-gate aio_req_t *current;
27557c478bd9Sstevel@tonic-gate aio_req_t **nextp;
27567c478bd9Sstevel@tonic-gate
27577c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp);
27587c478bd9Sstevel@tonic-gate nextp = &aiop->aio_hash[index];
27597c478bd9Sstevel@tonic-gate while ((current = *nextp) != NULL) {
27607c478bd9Sstevel@tonic-gate if (current->aio_req_resultp == resultp)
27617c478bd9Sstevel@tonic-gate return (DUPLICATE);
27627c478bd9Sstevel@tonic-gate nextp = ¤t->aio_hash_next;
27637c478bd9Sstevel@tonic-gate }
27647c478bd9Sstevel@tonic-gate *nextp = aio_reqp;
27657c478bd9Sstevel@tonic-gate aio_reqp->aio_hash_next = NULL;
27667c478bd9Sstevel@tonic-gate return (0);
27677c478bd9Sstevel@tonic-gate }
27687c478bd9Sstevel@tonic-gate
27697c478bd9Sstevel@tonic-gate static int
check_vp(struct vnode * vp,int mode)27707c478bd9Sstevel@tonic-gate (*check_vp(struct vnode *vp, int mode))(vnode_t *, struct aio_req *,
27717c478bd9Sstevel@tonic-gate cred_t *)
27727c478bd9Sstevel@tonic-gate {
27737c478bd9Sstevel@tonic-gate struct snode *sp;
27747c478bd9Sstevel@tonic-gate dev_t dev;
27757c478bd9Sstevel@tonic-gate struct cb_ops *cb;
27767c478bd9Sstevel@tonic-gate major_t major;
27777c478bd9Sstevel@tonic-gate int (*aio_func)();
27787c478bd9Sstevel@tonic-gate
27797c478bd9Sstevel@tonic-gate dev = vp->v_rdev;
27807c478bd9Sstevel@tonic-gate major = getmajor(dev);
27817c478bd9Sstevel@tonic-gate
27827c478bd9Sstevel@tonic-gate /*
27837c478bd9Sstevel@tonic-gate * return NULL for requests to files and STREAMs so
27847c478bd9Sstevel@tonic-gate * that libaio takes care of them.
27857c478bd9Sstevel@tonic-gate */
27867c478bd9Sstevel@tonic-gate if (vp->v_type == VCHR) {
27877c478bd9Sstevel@tonic-gate /* no stream device for kaio */
27887c478bd9Sstevel@tonic-gate if (STREAMSTAB(major)) {
27897c478bd9Sstevel@tonic-gate return (NULL);
27907c478bd9Sstevel@tonic-gate }
27917c478bd9Sstevel@tonic-gate } else {
27927c478bd9Sstevel@tonic-gate return (NULL);
27937c478bd9Sstevel@tonic-gate }
27947c478bd9Sstevel@tonic-gate
27957c478bd9Sstevel@tonic-gate /*
27967c478bd9Sstevel@tonic-gate * Check old drivers which do not have async I/O entry points.
27977c478bd9Sstevel@tonic-gate */
27987c478bd9Sstevel@tonic-gate if (devopsp[major]->devo_rev < 3)
27997c478bd9Sstevel@tonic-gate return (NULL);
28007c478bd9Sstevel@tonic-gate
28017c478bd9Sstevel@tonic-gate cb = devopsp[major]->devo_cb_ops;
28027c478bd9Sstevel@tonic-gate
28037c478bd9Sstevel@tonic-gate if (cb->cb_rev < 1)
28047c478bd9Sstevel@tonic-gate return (NULL);
28057c478bd9Sstevel@tonic-gate
28067c478bd9Sstevel@tonic-gate /*
28077c478bd9Sstevel@tonic-gate * Check whether this device is a block device.
28087c478bd9Sstevel@tonic-gate * Kaio is not supported for devices like tty.
28097c478bd9Sstevel@tonic-gate */
28107c478bd9Sstevel@tonic-gate if (cb->cb_strategy == nodev || cb->cb_strategy == NULL)
28117c478bd9Sstevel@tonic-gate return (NULL);
28127c478bd9Sstevel@tonic-gate
28137c478bd9Sstevel@tonic-gate /*
28147c478bd9Sstevel@tonic-gate * Clustering: If vnode is a PXFS vnode, then the device may be remote.
28157c478bd9Sstevel@tonic-gate * We cannot call the driver directly. Instead return the
28167c478bd9Sstevel@tonic-gate * PXFS functions.
28177c478bd9Sstevel@tonic-gate */
28187c478bd9Sstevel@tonic-gate
28197c478bd9Sstevel@tonic-gate if (IS_PXFSVP(vp)) {
28207c478bd9Sstevel@tonic-gate if (mode & FREAD)
28217c478bd9Sstevel@tonic-gate return (clpxfs_aio_read);
28227c478bd9Sstevel@tonic-gate else
28237c478bd9Sstevel@tonic-gate return (clpxfs_aio_write);
28247c478bd9Sstevel@tonic-gate }
28257c478bd9Sstevel@tonic-gate if (mode & FREAD)
28267c478bd9Sstevel@tonic-gate aio_func = (cb->cb_aread == nodev) ? NULL : driver_aio_read;
28277c478bd9Sstevel@tonic-gate else
28287c478bd9Sstevel@tonic-gate aio_func = (cb->cb_awrite == nodev) ? NULL : driver_aio_write;
28297c478bd9Sstevel@tonic-gate
28307c478bd9Sstevel@tonic-gate /*
28317c478bd9Sstevel@tonic-gate * Do we need this ?
28327c478bd9Sstevel@tonic-gate * nodev returns ENXIO anyway.
28337c478bd9Sstevel@tonic-gate */
28347c478bd9Sstevel@tonic-gate if (aio_func == nodev)
28357c478bd9Sstevel@tonic-gate return (NULL);
28367c478bd9Sstevel@tonic-gate
28377c478bd9Sstevel@tonic-gate sp = VTOS(vp);
28387c478bd9Sstevel@tonic-gate smark(sp, SACC);
28397c478bd9Sstevel@tonic-gate return (aio_func);
28407c478bd9Sstevel@tonic-gate }
28417c478bd9Sstevel@tonic-gate
28427c478bd9Sstevel@tonic-gate /*
28437c478bd9Sstevel@tonic-gate * Clustering: We want check_vp to return a function prototyped
28447c478bd9Sstevel@tonic-gate * correctly that will be common to both PXFS and regular case.
28457c478bd9Sstevel@tonic-gate * We define this intermediate function that will do the right
28467c478bd9Sstevel@tonic-gate * thing for driver cases.
28477c478bd9Sstevel@tonic-gate */
28487c478bd9Sstevel@tonic-gate
28497c478bd9Sstevel@tonic-gate static int
driver_aio_write(vnode_t * vp,struct aio_req * aio,cred_t * cred_p)28507c478bd9Sstevel@tonic-gate driver_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p)
28517c478bd9Sstevel@tonic-gate {
28527c478bd9Sstevel@tonic-gate dev_t dev;
28537c478bd9Sstevel@tonic-gate struct cb_ops *cb;
28547c478bd9Sstevel@tonic-gate
28557c478bd9Sstevel@tonic-gate ASSERT(vp->v_type == VCHR);
28567c478bd9Sstevel@tonic-gate ASSERT(!IS_PXFSVP(vp));
28577c478bd9Sstevel@tonic-gate dev = VTOS(vp)->s_dev;
28587c478bd9Sstevel@tonic-gate ASSERT(STREAMSTAB(getmajor(dev)) == NULL);
28597c478bd9Sstevel@tonic-gate
28607c478bd9Sstevel@tonic-gate cb = devopsp[getmajor(dev)]->devo_cb_ops;
28617c478bd9Sstevel@tonic-gate
28627c478bd9Sstevel@tonic-gate ASSERT(cb->cb_awrite != nodev);
28637c478bd9Sstevel@tonic-gate return ((*cb->cb_awrite)(dev, aio, cred_p));
28647c478bd9Sstevel@tonic-gate }
28657c478bd9Sstevel@tonic-gate
28667c478bd9Sstevel@tonic-gate /*
28677c478bd9Sstevel@tonic-gate * Clustering: We want check_vp to return a function prototyped
28687c478bd9Sstevel@tonic-gate * correctly that will be common to both PXFS and regular case.
28697c478bd9Sstevel@tonic-gate * We define this intermediate function that will do the right
28707c478bd9Sstevel@tonic-gate * thing for driver cases.
28717c478bd9Sstevel@tonic-gate */
28727c478bd9Sstevel@tonic-gate
28737c478bd9Sstevel@tonic-gate static int
driver_aio_read(vnode_t * vp,struct aio_req * aio,cred_t * cred_p)28747c478bd9Sstevel@tonic-gate driver_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p)
28757c478bd9Sstevel@tonic-gate {
28767c478bd9Sstevel@tonic-gate dev_t dev;
28777c478bd9Sstevel@tonic-gate struct cb_ops *cb;
28787c478bd9Sstevel@tonic-gate
28797c478bd9Sstevel@tonic-gate ASSERT(vp->v_type == VCHR);
28807c478bd9Sstevel@tonic-gate ASSERT(!IS_PXFSVP(vp));
28817c478bd9Sstevel@tonic-gate dev = VTOS(vp)->s_dev;
28827c478bd9Sstevel@tonic-gate ASSERT(!STREAMSTAB(getmajor(dev)));
28837c478bd9Sstevel@tonic-gate
28847c478bd9Sstevel@tonic-gate cb = devopsp[getmajor(dev)]->devo_cb_ops;
28857c478bd9Sstevel@tonic-gate
28867c478bd9Sstevel@tonic-gate ASSERT(cb->cb_aread != nodev);
28877c478bd9Sstevel@tonic-gate return ((*cb->cb_aread)(dev, aio, cred_p));
28887c478bd9Sstevel@tonic-gate }
28897c478bd9Sstevel@tonic-gate
28907c478bd9Sstevel@tonic-gate /*
28917c478bd9Sstevel@tonic-gate * This routine is called when a largefile call is made by a 32bit
28927c478bd9Sstevel@tonic-gate * process on a ILP32 or LP64 kernel. All 64bit processes are large
28937c478bd9Sstevel@tonic-gate * file by definition and will call alio() instead.
28947c478bd9Sstevel@tonic-gate */
28957c478bd9Sstevel@tonic-gate static int
alioLF(int mode_arg,void * aiocb_arg,int nent,void * sigev)28967c478bd9Sstevel@tonic-gate alioLF(
28977c478bd9Sstevel@tonic-gate int mode_arg,
28987c478bd9Sstevel@tonic-gate void *aiocb_arg,
28997c478bd9Sstevel@tonic-gate int nent,
29007c478bd9Sstevel@tonic-gate void *sigev)
29017c478bd9Sstevel@tonic-gate {
29027c478bd9Sstevel@tonic-gate file_t *fp;
29037c478bd9Sstevel@tonic-gate file_t *prev_fp = NULL;
29047c478bd9Sstevel@tonic-gate int prev_mode = -1;
29057c478bd9Sstevel@tonic-gate struct vnode *vp;
29067c478bd9Sstevel@tonic-gate aio_lio_t *head;
29077c478bd9Sstevel@tonic-gate aio_req_t *reqp;
29087c478bd9Sstevel@tonic-gate aio_t *aiop;
29097c478bd9Sstevel@tonic-gate caddr_t cbplist;
29107c478bd9Sstevel@tonic-gate aiocb64_32_t cb64;
29117c478bd9Sstevel@tonic-gate aiocb64_32_t *aiocb = &cb64;
291234709573Sraf aiocb64_32_t *cbp;
291334709573Sraf caddr32_t *ucbp;
29147c478bd9Sstevel@tonic-gate #ifdef _LP64
29157c478bd9Sstevel@tonic-gate aiocb_t aiocb_n;
29167c478bd9Sstevel@tonic-gate #endif
29177c478bd9Sstevel@tonic-gate struct sigevent32 sigevk;
29187c478bd9Sstevel@tonic-gate sigqueue_t *sqp;
29197c478bd9Sstevel@tonic-gate int (*aio_func)();
29207c478bd9Sstevel@tonic-gate int mode;
292134709573Sraf int error = 0;
292234709573Sraf int aio_errors = 0;
29237c478bd9Sstevel@tonic-gate int i;
29247c478bd9Sstevel@tonic-gate size_t ssize;
29257c478bd9Sstevel@tonic-gate int deadhead = 0;
29267c478bd9Sstevel@tonic-gate int aio_notsupported = 0;
292734709573Sraf int lio_head_port;
292834709573Sraf int aio_port;
292934709573Sraf int aio_thread;
29307c478bd9Sstevel@tonic-gate port_kevent_t *pkevtp = NULL;
293134b3058fSpraks int portused = 0;
29327c478bd9Sstevel@tonic-gate port_notify32_t pnotify;
293334709573Sraf int event;
29347c478bd9Sstevel@tonic-gate
29357c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
29367c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX)
29377c478bd9Sstevel@tonic-gate return (EINVAL);
29387c478bd9Sstevel@tonic-gate
29397c478bd9Sstevel@tonic-gate ASSERT(get_udatamodel() == DATAMODEL_ILP32);
29407c478bd9Sstevel@tonic-gate
29417c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent);
29427c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP);
29437c478bd9Sstevel@tonic-gate ucbp = (caddr32_t *)cbplist;
29447c478bd9Sstevel@tonic-gate
294534709573Sraf if (copyin(aiocb_arg, cbplist, ssize) ||
294634709573Sraf (sigev && copyin(sigev, &sigevk, sizeof (sigevk)))) {
29477c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
29487c478bd9Sstevel@tonic-gate return (EFAULT);
29497c478bd9Sstevel@tonic-gate }
29507c478bd9Sstevel@tonic-gate
295134709573Sraf /* Event Ports */
295234709573Sraf if (sigev &&
295334709573Sraf (sigevk.sigev_notify == SIGEV_THREAD ||
295434709573Sraf sigevk.sigev_notify == SIGEV_PORT)) {
295534709573Sraf if (sigevk.sigev_notify == SIGEV_THREAD) {
295634709573Sraf pnotify.portnfy_port = sigevk.sigev_signo;
295734709573Sraf pnotify.portnfy_user = sigevk.sigev_value.sival_ptr;
295834709573Sraf } else if (copyin(
295934709573Sraf (void *)(uintptr_t)sigevk.sigev_value.sival_ptr,
296034709573Sraf &pnotify, sizeof (pnotify))) {
29617c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
29627c478bd9Sstevel@tonic-gate return (EFAULT);
29637c478bd9Sstevel@tonic-gate }
296434709573Sraf error = port_alloc_event(pnotify.portnfy_port,
296534709573Sraf PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO, &pkevtp);
296634709573Sraf if (error) {
296734709573Sraf if (error == ENOMEM || error == EAGAIN)
296834709573Sraf error = EAGAIN;
296934709573Sraf else
297034709573Sraf error = EINVAL;
297134709573Sraf kmem_free(cbplist, ssize);
297234709573Sraf return (error);
297334709573Sraf }
297434709573Sraf lio_head_port = pnotify.portnfy_port;
297534b3058fSpraks portused = 1;
29767c478bd9Sstevel@tonic-gate }
29777c478bd9Sstevel@tonic-gate
29787c478bd9Sstevel@tonic-gate /*
29797c478bd9Sstevel@tonic-gate * a list head should be allocated if notification is
29807c478bd9Sstevel@tonic-gate * enabled for this list.
29817c478bd9Sstevel@tonic-gate */
29827c478bd9Sstevel@tonic-gate head = NULL;
29837c478bd9Sstevel@tonic-gate
298434709573Sraf if (mode_arg == LIO_WAIT || sigev) {
29857c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
29867c478bd9Sstevel@tonic-gate error = aio_lio_alloc(&head);
29877c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
29887c478bd9Sstevel@tonic-gate if (error)
29897c478bd9Sstevel@tonic-gate goto done;
29907c478bd9Sstevel@tonic-gate deadhead = 1;
29917c478bd9Sstevel@tonic-gate head->lio_nent = nent;
29927c478bd9Sstevel@tonic-gate head->lio_refcnt = nent;
299334709573Sraf head->lio_port = -1;
299434709573Sraf head->lio_portkev = NULL;
299534709573Sraf if (sigev && sigevk.sigev_notify == SIGEV_SIGNAL &&
299634709573Sraf sigevk.sigev_signo > 0 && sigevk.sigev_signo < NSIG) {
29977c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP);
29987c478bd9Sstevel@tonic-gate if (sqp == NULL) {
29997c478bd9Sstevel@tonic-gate error = EAGAIN;
30007c478bd9Sstevel@tonic-gate goto done;
30017c478bd9Sstevel@tonic-gate }
30027c478bd9Sstevel@tonic-gate sqp->sq_func = NULL;
30037c478bd9Sstevel@tonic-gate sqp->sq_next = NULL;
30047c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO;
30057c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid;
30067c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc);
30077c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid();
30087c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred);
30097c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigevk.sigev_signo;
30107c478bd9Sstevel@tonic-gate sqp->sq_info.si_value.sival_int =
30117c478bd9Sstevel@tonic-gate sigevk.sigev_value.sival_int;
30127c478bd9Sstevel@tonic-gate head->lio_sigqp = sqp;
30137c478bd9Sstevel@tonic-gate } else {
30147c478bd9Sstevel@tonic-gate head->lio_sigqp = NULL;
30157c478bd9Sstevel@tonic-gate }
301634709573Sraf if (pkevtp) {
301734709573Sraf /*
301834709573Sraf * Prepare data to send when list of aiocb's
301934709573Sraf * has completed.
302034709573Sraf */
302134709573Sraf port_init_event(pkevtp, (uintptr_t)sigev,
302234709573Sraf (void *)(uintptr_t)pnotify.portnfy_user,
302334709573Sraf NULL, head);
302434709573Sraf pkevtp->portkev_events = AIOLIO64;
302534709573Sraf head->lio_portkev = pkevtp;
302634709573Sraf head->lio_port = pnotify.portnfy_port;
302734709573Sraf }
30287c478bd9Sstevel@tonic-gate }
30297c478bd9Sstevel@tonic-gate
30307c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++, ucbp++) {
30317c478bd9Sstevel@tonic-gate
30327c478bd9Sstevel@tonic-gate cbp = (aiocb64_32_t *)(uintptr_t)*ucbp;
30337c478bd9Sstevel@tonic-gate /* skip entry if it can't be copied. */
303434709573Sraf if (cbp == NULL || copyin(cbp, aiocb, sizeof (*aiocb))) {
30357c478bd9Sstevel@tonic-gate if (head) {
30367c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
30377c478bd9Sstevel@tonic-gate head->lio_nent--;
30387c478bd9Sstevel@tonic-gate head->lio_refcnt--;
30397c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
30407c478bd9Sstevel@tonic-gate }
30417c478bd9Sstevel@tonic-gate continue;
30427c478bd9Sstevel@tonic-gate }
30437c478bd9Sstevel@tonic-gate
30447c478bd9Sstevel@tonic-gate /* skip if opcode for aiocb is LIO_NOP */
30457c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode;
30467c478bd9Sstevel@tonic-gate if (mode == LIO_NOP) {
30477c478bd9Sstevel@tonic-gate cbp = NULL;
30487c478bd9Sstevel@tonic-gate if (head) {
30497c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
30507c478bd9Sstevel@tonic-gate head->lio_nent--;
30517c478bd9Sstevel@tonic-gate head->lio_refcnt--;
30527c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
30537c478bd9Sstevel@tonic-gate }
30547c478bd9Sstevel@tonic-gate continue;
30557c478bd9Sstevel@tonic-gate }
30567c478bd9Sstevel@tonic-gate
30577c478bd9Sstevel@tonic-gate /* increment file descriptor's ref count. */
30587c478bd9Sstevel@tonic-gate if ((fp = getf(aiocb->aio_fildes)) == NULL) {
30597c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF);
30607c478bd9Sstevel@tonic-gate if (head) {
30617c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
30627c478bd9Sstevel@tonic-gate head->lio_nent--;
30637c478bd9Sstevel@tonic-gate head->lio_refcnt--;
30647c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
30657c478bd9Sstevel@tonic-gate }
30667c478bd9Sstevel@tonic-gate aio_errors++;
30677c478bd9Sstevel@tonic-gate continue;
30687c478bd9Sstevel@tonic-gate }
30697c478bd9Sstevel@tonic-gate
30707c478bd9Sstevel@tonic-gate /*
30717c478bd9Sstevel@tonic-gate * check the permission of the partition
30727c478bd9Sstevel@tonic-gate */
30737c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) {
30747c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
30757c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF);
30767c478bd9Sstevel@tonic-gate if (head) {
30777c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
30787c478bd9Sstevel@tonic-gate head->lio_nent--;
30797c478bd9Sstevel@tonic-gate head->lio_refcnt--;
30807c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
30817c478bd9Sstevel@tonic-gate }
30827c478bd9Sstevel@tonic-gate aio_errors++;
30837c478bd9Sstevel@tonic-gate continue;
30847c478bd9Sstevel@tonic-gate }
30857c478bd9Sstevel@tonic-gate
30867c478bd9Sstevel@tonic-gate /*
30877c478bd9Sstevel@tonic-gate * common case where requests are to the same fd
30887c478bd9Sstevel@tonic-gate * for the same r/w operation
30897c478bd9Sstevel@tonic-gate * for UFS, need to set EBADFD
30907c478bd9Sstevel@tonic-gate */
309134709573Sraf vp = fp->f_vnode;
309234709573Sraf if (fp != prev_fp || mode != prev_mode) {
30937c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode);
30947c478bd9Sstevel@tonic-gate if (aio_func == NULL) {
30957c478bd9Sstevel@tonic-gate prev_fp = NULL;
30967c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
30977c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADFD);
30987c478bd9Sstevel@tonic-gate aio_notsupported++;
30997c478bd9Sstevel@tonic-gate if (head) {
31007c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
31017c478bd9Sstevel@tonic-gate head->lio_nent--;
31027c478bd9Sstevel@tonic-gate head->lio_refcnt--;
31037c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
31047c478bd9Sstevel@tonic-gate }
31057c478bd9Sstevel@tonic-gate continue;
31067c478bd9Sstevel@tonic-gate } else {
31077c478bd9Sstevel@tonic-gate prev_fp = fp;
31087c478bd9Sstevel@tonic-gate prev_mode = mode;
31097c478bd9Sstevel@tonic-gate }
31107c478bd9Sstevel@tonic-gate }
311134709573Sraf
31127c478bd9Sstevel@tonic-gate #ifdef _LP64
31137c478bd9Sstevel@tonic-gate aiocb_LFton(aiocb, &aiocb_n);
31147c478bd9Sstevel@tonic-gate error = aio_req_setup(&reqp, aiop, &aiocb_n,
3115*d2749ac6SRoger A. Faulkner (aio_result_t *)&cbp->aio_resultp, vp, 0);
31167c478bd9Sstevel@tonic-gate #else
31177c478bd9Sstevel@tonic-gate error = aio_req_setupLF(&reqp, aiop, aiocb,
3118*d2749ac6SRoger A. Faulkner (aio_result_t *)&cbp->aio_resultp, vp, 0);
31197c478bd9Sstevel@tonic-gate #endif /* _LP64 */
31207c478bd9Sstevel@tonic-gate if (error) {
31217c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
312234709573Sraf lio_set_uerror(&cbp->aio_resultp, error);
31237c478bd9Sstevel@tonic-gate if (head) {
31247c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
31257c478bd9Sstevel@tonic-gate head->lio_nent--;
31267c478bd9Sstevel@tonic-gate head->lio_refcnt--;
31277c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
31287c478bd9Sstevel@tonic-gate }
31297c478bd9Sstevel@tonic-gate aio_errors++;
31307c478bd9Sstevel@tonic-gate continue;
31317c478bd9Sstevel@tonic-gate }
31327c478bd9Sstevel@tonic-gate
31337c478bd9Sstevel@tonic-gate reqp->aio_req_lio = head;
31347c478bd9Sstevel@tonic-gate deadhead = 0;
31357c478bd9Sstevel@tonic-gate
31367c478bd9Sstevel@tonic-gate /*
31377c478bd9Sstevel@tonic-gate * Set the errno field now before sending the request to
31387c478bd9Sstevel@tonic-gate * the driver to avoid a race condition
31397c478bd9Sstevel@tonic-gate */
31407c478bd9Sstevel@tonic-gate (void) suword32(&cbp->aio_resultp.aio_errno,
31417c478bd9Sstevel@tonic-gate EINPROGRESS);
31427c478bd9Sstevel@tonic-gate
31437c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32 = *ucbp;
31447c478bd9Sstevel@tonic-gate
314534709573Sraf event = (mode == LIO_READ)? AIOAREAD64 : AIOAWRITE64;
314634709573Sraf aio_port = (aiocb->aio_sigevent.sigev_notify == SIGEV_PORT);
314734709573Sraf aio_thread = (aiocb->aio_sigevent.sigev_notify == SIGEV_THREAD);
314834709573Sraf if (aio_port | aio_thread) {
314934709573Sraf port_kevent_t *lpkevp;
315034709573Sraf /*
315134709573Sraf * Prepare data to send with each aiocb completed.
315234709573Sraf */
315334709573Sraf if (aio_port) {
315434709573Sraf void *paddr = (void *)(uintptr_t)
315534709573Sraf aiocb->aio_sigevent.sigev_value.sival_ptr;
315634709573Sraf if (copyin(paddr, &pnotify, sizeof (pnotify)))
315734709573Sraf error = EFAULT;
315834709573Sraf } else { /* aio_thread */
315934709573Sraf pnotify.portnfy_port =
316034709573Sraf aiocb->aio_sigevent.sigev_signo;
316134709573Sraf pnotify.portnfy_user =
316234709573Sraf aiocb->aio_sigevent.sigev_value.sival_ptr;
316334709573Sraf }
316434709573Sraf if (error)
316534709573Sraf /* EMPTY */;
316634709573Sraf else if (pkevtp != NULL &&
316734709573Sraf pnotify.portnfy_port == lio_head_port)
316834709573Sraf error = port_dup_event(pkevtp, &lpkevp,
316934709573Sraf PORT_ALLOC_DEFAULT);
317034709573Sraf else
317134709573Sraf error = port_alloc_event(pnotify.portnfy_port,
317234709573Sraf PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO,
317334709573Sraf &lpkevp);
317434709573Sraf if (error == 0) {
317534709573Sraf port_init_event(lpkevp, (uintptr_t)*ucbp,
31767c478bd9Sstevel@tonic-gate (void *)(uintptr_t)pnotify.portnfy_user,
317734709573Sraf aio_port_callback, reqp);
317834709573Sraf lpkevp->portkev_events = event;
317934709573Sraf reqp->aio_req_portkev = lpkevp;
318034709573Sraf reqp->aio_req_port = pnotify.portnfy_port;
318134709573Sraf }
31827c478bd9Sstevel@tonic-gate }
31837c478bd9Sstevel@tonic-gate
31847c478bd9Sstevel@tonic-gate /*
31857c478bd9Sstevel@tonic-gate * send the request to driver.
31867c478bd9Sstevel@tonic-gate */
31877c478bd9Sstevel@tonic-gate if (error == 0) {
31887c478bd9Sstevel@tonic-gate if (aiocb->aio_nbytes == 0) {
31897c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes);
31907c478bd9Sstevel@tonic-gate aio_zerolen(reqp);
31917c478bd9Sstevel@tonic-gate continue;
31927c478bd9Sstevel@tonic-gate }
31937c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req,
31947c478bd9Sstevel@tonic-gate CRED());
31957c478bd9Sstevel@tonic-gate }
31967c478bd9Sstevel@tonic-gate
31977c478bd9Sstevel@tonic-gate /*
31987c478bd9Sstevel@tonic-gate * the fd's ref count is not decremented until the IO has
31997c478bd9Sstevel@tonic-gate * completed unless there was an error.
32007c478bd9Sstevel@tonic-gate */
32017c478bd9Sstevel@tonic-gate if (error) {
32027c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
32037c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error);
32047c478bd9Sstevel@tonic-gate if (head) {
32057c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
32067c478bd9Sstevel@tonic-gate head->lio_nent--;
32077c478bd9Sstevel@tonic-gate head->lio_refcnt--;
32087c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
32097c478bd9Sstevel@tonic-gate }
32107c478bd9Sstevel@tonic-gate if (error == ENOTSUP)
32117c478bd9Sstevel@tonic-gate aio_notsupported++;
32127c478bd9Sstevel@tonic-gate else
32137c478bd9Sstevel@tonic-gate aio_errors++;
321434b3058fSpraks lio_set_error(reqp, portused);
32157c478bd9Sstevel@tonic-gate } else {
32167c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes);
32177c478bd9Sstevel@tonic-gate }
32187c478bd9Sstevel@tonic-gate }
32197c478bd9Sstevel@tonic-gate
32207c478bd9Sstevel@tonic-gate if (aio_notsupported) {
32217c478bd9Sstevel@tonic-gate error = ENOTSUP;
32227c478bd9Sstevel@tonic-gate } else if (aio_errors) {
32237c478bd9Sstevel@tonic-gate /*
32247c478bd9Sstevel@tonic-gate * return EIO if any request failed
32257c478bd9Sstevel@tonic-gate */
32267c478bd9Sstevel@tonic-gate error = EIO;
32277c478bd9Sstevel@tonic-gate }
32287c478bd9Sstevel@tonic-gate
32297c478bd9Sstevel@tonic-gate if (mode_arg == LIO_WAIT) {
32307c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
32317c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) {
32327c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) {
32337c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
32347c478bd9Sstevel@tonic-gate error = EINTR;
32357c478bd9Sstevel@tonic-gate goto done;
32367c478bd9Sstevel@tonic-gate }
32377c478bd9Sstevel@tonic-gate }
32387c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
32397c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, AIO_LARGEFILE);
32407c478bd9Sstevel@tonic-gate }
32417c478bd9Sstevel@tonic-gate
32427c478bd9Sstevel@tonic-gate done:
32437c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
32447c478bd9Sstevel@tonic-gate if (deadhead) {
32457c478bd9Sstevel@tonic-gate if (head->lio_sigqp)
32467c478bd9Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t));
324734709573Sraf if (head->lio_portkev)
324834709573Sraf port_free_event(head->lio_portkev);
32497c478bd9Sstevel@tonic-gate kmem_free(head, sizeof (aio_lio_t));
32507c478bd9Sstevel@tonic-gate }
32517c478bd9Sstevel@tonic-gate return (error);
32527c478bd9Sstevel@tonic-gate }
32537c478bd9Sstevel@tonic-gate
32547c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
32557c478bd9Sstevel@tonic-gate static void
aiocb_LFton(aiocb64_32_t * src,aiocb_t * dest)32567c478bd9Sstevel@tonic-gate aiocb_LFton(aiocb64_32_t *src, aiocb_t *dest)
32577c478bd9Sstevel@tonic-gate {
32587c478bd9Sstevel@tonic-gate dest->aio_fildes = src->aio_fildes;
32597c478bd9Sstevel@tonic-gate dest->aio_buf = (void *)(uintptr_t)src->aio_buf;
32607c478bd9Sstevel@tonic-gate dest->aio_nbytes = (size_t)src->aio_nbytes;
32617c478bd9Sstevel@tonic-gate dest->aio_offset = (off_t)src->aio_offset;
32627c478bd9Sstevel@tonic-gate dest->aio_reqprio = src->aio_reqprio;
32637c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify = src->aio_sigevent.sigev_notify;
32647c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_signo = src->aio_sigevent.sigev_signo;
32657c478bd9Sstevel@tonic-gate
32667c478bd9Sstevel@tonic-gate /*
32677c478bd9Sstevel@tonic-gate * See comment in sigqueue32() on handling of 32-bit
32687c478bd9Sstevel@tonic-gate * sigvals in a 64-bit kernel.
32697c478bd9Sstevel@tonic-gate */
32707c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_value.sival_int =
32717c478bd9Sstevel@tonic-gate (int)src->aio_sigevent.sigev_value.sival_int;
32727c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_function = (void (*)(union sigval))
32737c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_function;
32747c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_attributes = (pthread_attr_t *)
32757c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_attributes;
32767c478bd9Sstevel@tonic-gate dest->aio_sigevent.__sigev_pad2 = src->aio_sigevent.__sigev_pad2;
32777c478bd9Sstevel@tonic-gate dest->aio_lio_opcode = src->aio_lio_opcode;
32787c478bd9Sstevel@tonic-gate dest->aio_state = src->aio_state;
32797c478bd9Sstevel@tonic-gate dest->aio__pad[0] = src->aio__pad[0];
32807c478bd9Sstevel@tonic-gate }
32817c478bd9Sstevel@tonic-gate #endif
32827c478bd9Sstevel@tonic-gate
32837c478bd9Sstevel@tonic-gate /*
32847c478bd9Sstevel@tonic-gate * This function is used only for largefile calls made by
328534709573Sraf * 32 bit applications.
32867c478bd9Sstevel@tonic-gate */
32877c478bd9Sstevel@tonic-gate static int
aio_req_setupLF(aio_req_t ** reqpp,aio_t * aiop,aiocb64_32_t * arg,aio_result_t * resultp,vnode_t * vp,int old_solaris_req)32887c478bd9Sstevel@tonic-gate aio_req_setupLF(
32897c478bd9Sstevel@tonic-gate aio_req_t **reqpp,
32907c478bd9Sstevel@tonic-gate aio_t *aiop,
32917c478bd9Sstevel@tonic-gate aiocb64_32_t *arg,
32927c478bd9Sstevel@tonic-gate aio_result_t *resultp,
3293*d2749ac6SRoger A. Faulkner vnode_t *vp,
3294*d2749ac6SRoger A. Faulkner int old_solaris_req)
32957c478bd9Sstevel@tonic-gate {
329634709573Sraf sigqueue_t *sqp = NULL;
32977c478bd9Sstevel@tonic-gate aio_req_t *reqp;
32987c478bd9Sstevel@tonic-gate struct uio *uio;
329934709573Sraf struct sigevent32 *sigev;
33007c478bd9Sstevel@tonic-gate int error;
33017c478bd9Sstevel@tonic-gate
330234709573Sraf sigev = &arg->aio_sigevent;
330334709573Sraf if (sigev->sigev_notify == SIGEV_SIGNAL &&
330434709573Sraf sigev->sigev_signo > 0 && sigev->sigev_signo < NSIG) {
33057c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP);
33067c478bd9Sstevel@tonic-gate if (sqp == NULL)
33077c478bd9Sstevel@tonic-gate return (EAGAIN);
33087c478bd9Sstevel@tonic-gate sqp->sq_func = NULL;
33097c478bd9Sstevel@tonic-gate sqp->sq_next = NULL;
33107c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO;
33117c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid;
33127c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc);
33137c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid();
33147c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred);
33157c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigev->sigev_signo;
331634709573Sraf sqp->sq_info.si_value.sival_int = sigev->sigev_value.sival_int;
331734709573Sraf }
33187c478bd9Sstevel@tonic-gate
33197c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
33207c478bd9Sstevel@tonic-gate
33217c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) {
33227c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
33237c478bd9Sstevel@tonic-gate if (sqp)
33247c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t));
33257c478bd9Sstevel@tonic-gate return (EIO);
33267c478bd9Sstevel@tonic-gate }
33277c478bd9Sstevel@tonic-gate /*
33287c478bd9Sstevel@tonic-gate * get an aio_reqp from the free list or allocate one
33297c478bd9Sstevel@tonic-gate * from dynamic memory.
33307c478bd9Sstevel@tonic-gate */
33317c478bd9Sstevel@tonic-gate if (error = aio_req_alloc(&reqp, resultp)) {
33327c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
33337c478bd9Sstevel@tonic-gate if (sqp)
33347c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t));
33357c478bd9Sstevel@tonic-gate return (error);
33367c478bd9Sstevel@tonic-gate }
33377c478bd9Sstevel@tonic-gate aiop->aio_pending++;
33387c478bd9Sstevel@tonic-gate aiop->aio_outstanding++;
33397c478bd9Sstevel@tonic-gate reqp->aio_req_flags = AIO_PENDING;
3340*d2749ac6SRoger A. Faulkner if (old_solaris_req) {
3341*d2749ac6SRoger A. Faulkner /* this is an old solaris aio request */
3342*d2749ac6SRoger A. Faulkner reqp->aio_req_flags |= AIO_SOLARIS;
3343*d2749ac6SRoger A. Faulkner aiop->aio_flags |= AIO_SOLARIS_REQ;
3344*d2749ac6SRoger A. Faulkner }
334534709573Sraf if (sigev->sigev_notify == SIGEV_THREAD ||
334634709573Sraf sigev->sigev_notify == SIGEV_PORT)
334734709573Sraf aio_enq(&aiop->aio_portpending, reqp, 0);
33487c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
33497c478bd9Sstevel@tonic-gate /*
33507c478bd9Sstevel@tonic-gate * initialize aio request.
33517c478bd9Sstevel@tonic-gate */
33527c478bd9Sstevel@tonic-gate reqp->aio_req_fd = arg->aio_fildes;
33537c478bd9Sstevel@tonic-gate reqp->aio_req_sigqp = sqp;
33547c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = NULL;
335534709573Sraf reqp->aio_req_lio = NULL;
33567c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_file = vp;
33577c478bd9Sstevel@tonic-gate uio = reqp->aio_req.aio_uio;
33587c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1;
33597c478bd9Sstevel@tonic-gate uio->uio_iov->iov_base = (caddr_t)(uintptr_t)arg->aio_buf;
33607c478bd9Sstevel@tonic-gate uio->uio_iov->iov_len = arg->aio_nbytes;
33617c478bd9Sstevel@tonic-gate uio->uio_loffset = arg->aio_offset;
33627c478bd9Sstevel@tonic-gate *reqpp = reqp;
33637c478bd9Sstevel@tonic-gate return (0);
33647c478bd9Sstevel@tonic-gate }
33657c478bd9Sstevel@tonic-gate
33667c478bd9Sstevel@tonic-gate /*
33677c478bd9Sstevel@tonic-gate * This routine is called when a non largefile call is made by a 32bit
33687c478bd9Sstevel@tonic-gate * process on a ILP32 or LP64 kernel.
33697c478bd9Sstevel@tonic-gate */
33707c478bd9Sstevel@tonic-gate static int
alio32(int mode_arg,void * aiocb_arg,int nent,void * sigev)33717c478bd9Sstevel@tonic-gate alio32(
33727c478bd9Sstevel@tonic-gate int mode_arg,
33737c478bd9Sstevel@tonic-gate void *aiocb_arg,
33747c478bd9Sstevel@tonic-gate int nent,
337534709573Sraf void *sigev)
33767c478bd9Sstevel@tonic-gate {
33777c478bd9Sstevel@tonic-gate file_t *fp;
33787c478bd9Sstevel@tonic-gate file_t *prev_fp = NULL;
33797c478bd9Sstevel@tonic-gate int prev_mode = -1;
33807c478bd9Sstevel@tonic-gate struct vnode *vp;
33817c478bd9Sstevel@tonic-gate aio_lio_t *head;
33827c478bd9Sstevel@tonic-gate aio_req_t *reqp;
33837c478bd9Sstevel@tonic-gate aio_t *aiop;
338434709573Sraf caddr_t cbplist;
33857c478bd9Sstevel@tonic-gate aiocb_t cb;
33867c478bd9Sstevel@tonic-gate aiocb_t *aiocb = &cb;
33877c478bd9Sstevel@tonic-gate #ifdef _LP64
33887c478bd9Sstevel@tonic-gate aiocb32_t *cbp;
33897c478bd9Sstevel@tonic-gate caddr32_t *ucbp;
33907c478bd9Sstevel@tonic-gate aiocb32_t cb32;
33917c478bd9Sstevel@tonic-gate aiocb32_t *aiocb32 = &cb32;
339234709573Sraf struct sigevent32 sigevk;
33937c478bd9Sstevel@tonic-gate #else
33947c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp;
339534709573Sraf struct sigevent sigevk;
33967c478bd9Sstevel@tonic-gate #endif
33977c478bd9Sstevel@tonic-gate sigqueue_t *sqp;
33987c478bd9Sstevel@tonic-gate int (*aio_func)();
33997c478bd9Sstevel@tonic-gate int mode;
340034709573Sraf int error = 0;
340134709573Sraf int aio_errors = 0;
34027c478bd9Sstevel@tonic-gate int i;
34037c478bd9Sstevel@tonic-gate size_t ssize;
34047c478bd9Sstevel@tonic-gate int deadhead = 0;
34057c478bd9Sstevel@tonic-gate int aio_notsupported = 0;
340634709573Sraf int lio_head_port;
340734709573Sraf int aio_port;
340834709573Sraf int aio_thread;
34097c478bd9Sstevel@tonic-gate port_kevent_t *pkevtp = NULL;
341034b3058fSpraks int portused = 0;
34117c478bd9Sstevel@tonic-gate #ifdef _LP64
34127c478bd9Sstevel@tonic-gate port_notify32_t pnotify;
34137c478bd9Sstevel@tonic-gate #else
34147c478bd9Sstevel@tonic-gate port_notify_t pnotify;
34157c478bd9Sstevel@tonic-gate #endif
341634709573Sraf int event;
341734709573Sraf
34187c478bd9Sstevel@tonic-gate aiop = curproc->p_aio;
34197c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX)
34207c478bd9Sstevel@tonic-gate return (EINVAL);
34217c478bd9Sstevel@tonic-gate
34227c478bd9Sstevel@tonic-gate #ifdef _LP64
34237c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent);
34247c478bd9Sstevel@tonic-gate #else
34257c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent);
34267c478bd9Sstevel@tonic-gate #endif
34277c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP);
34287c478bd9Sstevel@tonic-gate ucbp = (void *)cbplist;
34297c478bd9Sstevel@tonic-gate
343034709573Sraf if (copyin(aiocb_arg, cbplist, ssize) ||
343134709573Sraf (sigev && copyin(sigev, &sigevk, sizeof (struct sigevent32)))) {
34327c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
34337c478bd9Sstevel@tonic-gate return (EFAULT);
34347c478bd9Sstevel@tonic-gate }
34357c478bd9Sstevel@tonic-gate
343634709573Sraf /* Event Ports */
343734709573Sraf if (sigev &&
343834709573Sraf (sigevk.sigev_notify == SIGEV_THREAD ||
343934709573Sraf sigevk.sigev_notify == SIGEV_PORT)) {
344034709573Sraf if (sigevk.sigev_notify == SIGEV_THREAD) {
344134709573Sraf pnotify.portnfy_port = sigevk.sigev_signo;
344234709573Sraf pnotify.portnfy_user = sigevk.sigev_value.sival_ptr;
344334709573Sraf } else if (copyin(
344434709573Sraf (void *)(uintptr_t)sigevk.sigev_value.sival_ptr,
344534709573Sraf &pnotify, sizeof (pnotify))) {
34467c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
34477c478bd9Sstevel@tonic-gate return (EFAULT);
34487c478bd9Sstevel@tonic-gate }
344934709573Sraf error = port_alloc_event(pnotify.portnfy_port,
345034709573Sraf PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO, &pkevtp);
345134709573Sraf if (error) {
345234709573Sraf if (error == ENOMEM || error == EAGAIN)
345334709573Sraf error = EAGAIN;
345434709573Sraf else
345534709573Sraf error = EINVAL;
345634709573Sraf kmem_free(cbplist, ssize);
345734709573Sraf return (error);
345834709573Sraf }
345934709573Sraf lio_head_port = pnotify.portnfy_port;
346034b3058fSpraks portused = 1;
34617c478bd9Sstevel@tonic-gate }
34627c478bd9Sstevel@tonic-gate
34637c478bd9Sstevel@tonic-gate /*
34647c478bd9Sstevel@tonic-gate * a list head should be allocated if notification is
34657c478bd9Sstevel@tonic-gate * enabled for this list.
34667c478bd9Sstevel@tonic-gate */
34677c478bd9Sstevel@tonic-gate head = NULL;
34687c478bd9Sstevel@tonic-gate
346934709573Sraf if (mode_arg == LIO_WAIT || sigev) {
34707c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
34717c478bd9Sstevel@tonic-gate error = aio_lio_alloc(&head);
34727c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
34737c478bd9Sstevel@tonic-gate if (error)
34747c478bd9Sstevel@tonic-gate goto done;
34757c478bd9Sstevel@tonic-gate deadhead = 1;
34767c478bd9Sstevel@tonic-gate head->lio_nent = nent;
34777c478bd9Sstevel@tonic-gate head->lio_refcnt = nent;
347834709573Sraf head->lio_port = -1;
347934709573Sraf head->lio_portkev = NULL;
348034709573Sraf if (sigev && sigevk.sigev_notify == SIGEV_SIGNAL &&
348134709573Sraf sigevk.sigev_signo > 0 && sigevk.sigev_signo < NSIG) {
34827c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP);
34837c478bd9Sstevel@tonic-gate if (sqp == NULL) {
34847c478bd9Sstevel@tonic-gate error = EAGAIN;
34857c478bd9Sstevel@tonic-gate goto done;
34867c478bd9Sstevel@tonic-gate }
34877c478bd9Sstevel@tonic-gate sqp->sq_func = NULL;
34887c478bd9Sstevel@tonic-gate sqp->sq_next = NULL;
34897c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO;
34907c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid;
34917c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc);
34927c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid();
34937c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred);
349434709573Sraf sqp->sq_info.si_signo = sigevk.sigev_signo;
34957c478bd9Sstevel@tonic-gate sqp->sq_info.si_value.sival_int =
349634709573Sraf sigevk.sigev_value.sival_int;
34977c478bd9Sstevel@tonic-gate head->lio_sigqp = sqp;
34987c478bd9Sstevel@tonic-gate } else {
34997c478bd9Sstevel@tonic-gate head->lio_sigqp = NULL;
35007c478bd9Sstevel@tonic-gate }
350134709573Sraf if (pkevtp) {
350234709573Sraf /*
350334709573Sraf * Prepare data to send when list of aiocb's has
350434709573Sraf * completed.
350534709573Sraf */
350634709573Sraf port_init_event(pkevtp, (uintptr_t)sigev,
350734709573Sraf (void *)(uintptr_t)pnotify.portnfy_user,
350834709573Sraf NULL, head);
350934709573Sraf pkevtp->portkev_events = AIOLIO;
351034709573Sraf head->lio_portkev = pkevtp;
351134709573Sraf head->lio_port = pnotify.portnfy_port;
351234709573Sraf }
35137c478bd9Sstevel@tonic-gate }
35147c478bd9Sstevel@tonic-gate
35157c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++, ucbp++) {
35167c478bd9Sstevel@tonic-gate
35177c478bd9Sstevel@tonic-gate /* skip entry if it can't be copied. */
35187c478bd9Sstevel@tonic-gate #ifdef _LP64
35197c478bd9Sstevel@tonic-gate cbp = (aiocb32_t *)(uintptr_t)*ucbp;
352034709573Sraf if (cbp == NULL || copyin(cbp, aiocb32, sizeof (*aiocb32)))
35217c478bd9Sstevel@tonic-gate #else
35227c478bd9Sstevel@tonic-gate cbp = (aiocb_t *)*ucbp;
352334709573Sraf if (cbp == NULL || copyin(cbp, aiocb, sizeof (*aiocb)))
35247c478bd9Sstevel@tonic-gate #endif
352534709573Sraf {
35267c478bd9Sstevel@tonic-gate if (head) {
35277c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
35287c478bd9Sstevel@tonic-gate head->lio_nent--;
35297c478bd9Sstevel@tonic-gate head->lio_refcnt--;
35307c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
35317c478bd9Sstevel@tonic-gate }
35327c478bd9Sstevel@tonic-gate continue;
35337c478bd9Sstevel@tonic-gate }
35347c478bd9Sstevel@tonic-gate #ifdef _LP64
35357c478bd9Sstevel@tonic-gate /*
35367c478bd9Sstevel@tonic-gate * copy 32 bit structure into 64 bit structure
35377c478bd9Sstevel@tonic-gate */
35387c478bd9Sstevel@tonic-gate aiocb_32ton(aiocb32, aiocb);
35397c478bd9Sstevel@tonic-gate #endif /* _LP64 */
35407c478bd9Sstevel@tonic-gate
35417c478bd9Sstevel@tonic-gate /* skip if opcode for aiocb is LIO_NOP */
35427c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode;
35437c478bd9Sstevel@tonic-gate if (mode == LIO_NOP) {
35447c478bd9Sstevel@tonic-gate cbp = NULL;
35457c478bd9Sstevel@tonic-gate if (head) {
35467c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
35477c478bd9Sstevel@tonic-gate head->lio_nent--;
35487c478bd9Sstevel@tonic-gate head->lio_refcnt--;
35497c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
35507c478bd9Sstevel@tonic-gate }
35517c478bd9Sstevel@tonic-gate continue;
35527c478bd9Sstevel@tonic-gate }
35537c478bd9Sstevel@tonic-gate
35547c478bd9Sstevel@tonic-gate /* increment file descriptor's ref count. */
35557c478bd9Sstevel@tonic-gate if ((fp = getf(aiocb->aio_fildes)) == NULL) {
35567c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF);
35577c478bd9Sstevel@tonic-gate if (head) {
35587c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
35597c478bd9Sstevel@tonic-gate head->lio_nent--;
35607c478bd9Sstevel@tonic-gate head->lio_refcnt--;
35617c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
35627c478bd9Sstevel@tonic-gate }
35637c478bd9Sstevel@tonic-gate aio_errors++;
35647c478bd9Sstevel@tonic-gate continue;
35657c478bd9Sstevel@tonic-gate }
35667c478bd9Sstevel@tonic-gate
35677c478bd9Sstevel@tonic-gate /*
35687c478bd9Sstevel@tonic-gate * check the permission of the partition
35697c478bd9Sstevel@tonic-gate */
35707c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) {
35717c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
35727c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF);
35737c478bd9Sstevel@tonic-gate if (head) {
35747c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
35757c478bd9Sstevel@tonic-gate head->lio_nent--;
35767c478bd9Sstevel@tonic-gate head->lio_refcnt--;
35777c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
35787c478bd9Sstevel@tonic-gate }
35797c478bd9Sstevel@tonic-gate aio_errors++;
35807c478bd9Sstevel@tonic-gate continue;
35817c478bd9Sstevel@tonic-gate }
35827c478bd9Sstevel@tonic-gate
35837c478bd9Sstevel@tonic-gate /*
35847c478bd9Sstevel@tonic-gate * common case where requests are to the same fd
35857c478bd9Sstevel@tonic-gate * for the same r/w operation
35867c478bd9Sstevel@tonic-gate * for UFS, need to set EBADFD
35877c478bd9Sstevel@tonic-gate */
358834709573Sraf vp = fp->f_vnode;
358934709573Sraf if (fp != prev_fp || mode != prev_mode) {
35907c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode);
35917c478bd9Sstevel@tonic-gate if (aio_func == NULL) {
35927c478bd9Sstevel@tonic-gate prev_fp = NULL;
35937c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
359434709573Sraf lio_set_uerror(&cbp->aio_resultp, EBADFD);
35957c478bd9Sstevel@tonic-gate aio_notsupported++;
35967c478bd9Sstevel@tonic-gate if (head) {
35977c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
35987c478bd9Sstevel@tonic-gate head->lio_nent--;
35997c478bd9Sstevel@tonic-gate head->lio_refcnt--;
36007c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
36017c478bd9Sstevel@tonic-gate }
36027c478bd9Sstevel@tonic-gate continue;
36037c478bd9Sstevel@tonic-gate } else {
36047c478bd9Sstevel@tonic-gate prev_fp = fp;
36057c478bd9Sstevel@tonic-gate prev_mode = mode;
36067c478bd9Sstevel@tonic-gate }
36077c478bd9Sstevel@tonic-gate }
360834709573Sraf
360934709573Sraf error = aio_req_setup(&reqp, aiop, aiocb,
3610*d2749ac6SRoger A. Faulkner (aio_result_t *)&cbp->aio_resultp, vp, 0);
361134709573Sraf if (error) {
36127c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
36137c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error);
36147c478bd9Sstevel@tonic-gate if (head) {
36157c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
36167c478bd9Sstevel@tonic-gate head->lio_nent--;
36177c478bd9Sstevel@tonic-gate head->lio_refcnt--;
36187c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
36197c478bd9Sstevel@tonic-gate }
36207c478bd9Sstevel@tonic-gate aio_errors++;
36217c478bd9Sstevel@tonic-gate continue;
36227c478bd9Sstevel@tonic-gate }
36237c478bd9Sstevel@tonic-gate
36247c478bd9Sstevel@tonic-gate reqp->aio_req_lio = head;
36257c478bd9Sstevel@tonic-gate deadhead = 0;
36267c478bd9Sstevel@tonic-gate
36277c478bd9Sstevel@tonic-gate /*
36287c478bd9Sstevel@tonic-gate * Set the errno field now before sending the request to
36297c478bd9Sstevel@tonic-gate * the driver to avoid a race condition
36307c478bd9Sstevel@tonic-gate */
36317c478bd9Sstevel@tonic-gate (void) suword32(&cbp->aio_resultp.aio_errno,
36327c478bd9Sstevel@tonic-gate EINPROGRESS);
36337c478bd9Sstevel@tonic-gate
363434709573Sraf reqp->aio_req_iocb.iocb32 = (caddr32_t)(uintptr_t)cbp;
36357c478bd9Sstevel@tonic-gate
363634709573Sraf event = (mode == LIO_READ)? AIOAREAD : AIOAWRITE;
363734709573Sraf aio_port = (aiocb->aio_sigevent.sigev_notify == SIGEV_PORT);
363834709573Sraf aio_thread = (aiocb->aio_sigevent.sigev_notify == SIGEV_THREAD);
363934709573Sraf if (aio_port | aio_thread) {
364034709573Sraf port_kevent_t *lpkevp;
364134709573Sraf /*
364234709573Sraf * Prepare data to send with each aiocb completed.
364334709573Sraf */
36447c478bd9Sstevel@tonic-gate #ifdef _LP64
364534709573Sraf if (aio_port) {
364634709573Sraf void *paddr = (void *)(uintptr_t)
364734709573Sraf aiocb32->aio_sigevent.sigev_value.sival_ptr;
364834709573Sraf if (copyin(paddr, &pnotify, sizeof (pnotify)))
364934709573Sraf error = EFAULT;
365034709573Sraf } else { /* aio_thread */
365134709573Sraf pnotify.portnfy_port =
365234709573Sraf aiocb32->aio_sigevent.sigev_signo;
365334709573Sraf pnotify.portnfy_user =
365434709573Sraf aiocb32->aio_sigevent.sigev_value.sival_ptr;
365534709573Sraf }
36567c478bd9Sstevel@tonic-gate #else
365734709573Sraf if (aio_port) {
365834709573Sraf void *paddr =
365934709573Sraf aiocb->aio_sigevent.sigev_value.sival_ptr;
366034709573Sraf if (copyin(paddr, &pnotify, sizeof (pnotify)))
366134709573Sraf error = EFAULT;
366234709573Sraf } else { /* aio_thread */
366334709573Sraf pnotify.portnfy_port =
366434709573Sraf aiocb->aio_sigevent.sigev_signo;
366534709573Sraf pnotify.portnfy_user =
366634709573Sraf aiocb->aio_sigevent.sigev_value.sival_ptr;
366734709573Sraf }
36687c478bd9Sstevel@tonic-gate #endif
366934709573Sraf if (error)
367034709573Sraf /* EMPTY */;
367134709573Sraf else if (pkevtp != NULL &&
367234709573Sraf pnotify.portnfy_port == lio_head_port)
367334709573Sraf error = port_dup_event(pkevtp, &lpkevp,
367434709573Sraf PORT_ALLOC_DEFAULT);
367534709573Sraf else
367634709573Sraf error = port_alloc_event(pnotify.portnfy_port,
367734709573Sraf PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO,
367834709573Sraf &lpkevp);
367934709573Sraf if (error == 0) {
368034709573Sraf port_init_event(lpkevp, (uintptr_t)cbp,
368134709573Sraf (void *)(uintptr_t)pnotify.portnfy_user,
368234709573Sraf aio_port_callback, reqp);
368334709573Sraf lpkevp->portkev_events = event;
368434709573Sraf reqp->aio_req_portkev = lpkevp;
368534709573Sraf reqp->aio_req_port = pnotify.portnfy_port;
368634709573Sraf }
36877c478bd9Sstevel@tonic-gate }
36887c478bd9Sstevel@tonic-gate
36897c478bd9Sstevel@tonic-gate /*
36907c478bd9Sstevel@tonic-gate * send the request to driver.
36917c478bd9Sstevel@tonic-gate */
36927c478bd9Sstevel@tonic-gate if (error == 0) {
36937c478bd9Sstevel@tonic-gate if (aiocb->aio_nbytes == 0) {
36947c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes);
36957c478bd9Sstevel@tonic-gate aio_zerolen(reqp);
36967c478bd9Sstevel@tonic-gate continue;
36977c478bd9Sstevel@tonic-gate }
36987c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req,
36997c478bd9Sstevel@tonic-gate CRED());
37007c478bd9Sstevel@tonic-gate }
37017c478bd9Sstevel@tonic-gate
37027c478bd9Sstevel@tonic-gate /*
37037c478bd9Sstevel@tonic-gate * the fd's ref count is not decremented until the IO has
37047c478bd9Sstevel@tonic-gate * completed unless there was an error.
37057c478bd9Sstevel@tonic-gate */
37067c478bd9Sstevel@tonic-gate if (error) {
37077c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes);
37087c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error);
37097c478bd9Sstevel@tonic-gate if (head) {
37107c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
37117c478bd9Sstevel@tonic-gate head->lio_nent--;
37127c478bd9Sstevel@tonic-gate head->lio_refcnt--;
37137c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
37147c478bd9Sstevel@tonic-gate }
37157c478bd9Sstevel@tonic-gate if (error == ENOTSUP)
37167c478bd9Sstevel@tonic-gate aio_notsupported++;
37177c478bd9Sstevel@tonic-gate else
37187c478bd9Sstevel@tonic-gate aio_errors++;
371934b3058fSpraks lio_set_error(reqp, portused);
37207c478bd9Sstevel@tonic-gate } else {
37217c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes);
37227c478bd9Sstevel@tonic-gate }
37237c478bd9Sstevel@tonic-gate }
37247c478bd9Sstevel@tonic-gate
37257c478bd9Sstevel@tonic-gate if (aio_notsupported) {
37267c478bd9Sstevel@tonic-gate error = ENOTSUP;
37277c478bd9Sstevel@tonic-gate } else if (aio_errors) {
37287c478bd9Sstevel@tonic-gate /*
37297c478bd9Sstevel@tonic-gate * return EIO if any request failed
37307c478bd9Sstevel@tonic-gate */
37317c478bd9Sstevel@tonic-gate error = EIO;
37327c478bd9Sstevel@tonic-gate }
37337c478bd9Sstevel@tonic-gate
37347c478bd9Sstevel@tonic-gate if (mode_arg == LIO_WAIT) {
37357c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
37367c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) {
37377c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) {
37387c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
37397c478bd9Sstevel@tonic-gate error = EINTR;
37407c478bd9Sstevel@tonic-gate goto done;
37417c478bd9Sstevel@tonic-gate }
37427c478bd9Sstevel@tonic-gate }
37437c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
37447c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, AIO_32);
37457c478bd9Sstevel@tonic-gate }
37467c478bd9Sstevel@tonic-gate
37477c478bd9Sstevel@tonic-gate done:
37487c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize);
37497c478bd9Sstevel@tonic-gate if (deadhead) {
37507c478bd9Sstevel@tonic-gate if (head->lio_sigqp)
37517c478bd9Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t));
375234709573Sraf if (head->lio_portkev)
375334709573Sraf port_free_event(head->lio_portkev);
37547c478bd9Sstevel@tonic-gate kmem_free(head, sizeof (aio_lio_t));
37557c478bd9Sstevel@tonic-gate }
37567c478bd9Sstevel@tonic-gate return (error);
37577c478bd9Sstevel@tonic-gate }
37587c478bd9Sstevel@tonic-gate
37597c478bd9Sstevel@tonic-gate
37607c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
37617c478bd9Sstevel@tonic-gate void
aiocb_32ton(aiocb32_t * src,aiocb_t * dest)37627c478bd9Sstevel@tonic-gate aiocb_32ton(aiocb32_t *src, aiocb_t *dest)
37637c478bd9Sstevel@tonic-gate {
37647c478bd9Sstevel@tonic-gate dest->aio_fildes = src->aio_fildes;
37657c478bd9Sstevel@tonic-gate dest->aio_buf = (caddr_t)(uintptr_t)src->aio_buf;
37667c478bd9Sstevel@tonic-gate dest->aio_nbytes = (size_t)src->aio_nbytes;
37677c478bd9Sstevel@tonic-gate dest->aio_offset = (off_t)src->aio_offset;
37687c478bd9Sstevel@tonic-gate dest->aio_reqprio = src->aio_reqprio;
37697c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify = src->aio_sigevent.sigev_notify;
37707c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_signo = src->aio_sigevent.sigev_signo;
37717c478bd9Sstevel@tonic-gate
37727c478bd9Sstevel@tonic-gate /*
37737c478bd9Sstevel@tonic-gate * See comment in sigqueue32() on handling of 32-bit
37747c478bd9Sstevel@tonic-gate * sigvals in a 64-bit kernel.
37757c478bd9Sstevel@tonic-gate */
37767c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_value.sival_int =
37777c478bd9Sstevel@tonic-gate (int)src->aio_sigevent.sigev_value.sival_int;
37787c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_function = (void (*)(union sigval))
37797c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_function;
37807c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_attributes = (pthread_attr_t *)
37817c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_attributes;
37827c478bd9Sstevel@tonic-gate dest->aio_sigevent.__sigev_pad2 = src->aio_sigevent.__sigev_pad2;
37837c478bd9Sstevel@tonic-gate dest->aio_lio_opcode = src->aio_lio_opcode;
37847c478bd9Sstevel@tonic-gate dest->aio_state = src->aio_state;
37857c478bd9Sstevel@tonic-gate dest->aio__pad[0] = src->aio__pad[0];
37867c478bd9Sstevel@tonic-gate }
37877c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
37887c478bd9Sstevel@tonic-gate
37897c478bd9Sstevel@tonic-gate /*
37907c478bd9Sstevel@tonic-gate * aio_port_callback() is called just before the event is retrieved from the
37917c478bd9Sstevel@tonic-gate * port. The task of this callback function is to finish the work of the
37927c478bd9Sstevel@tonic-gate * transaction for the application, it means :
37937c478bd9Sstevel@tonic-gate * - copyout transaction data to the application
37947c478bd9Sstevel@tonic-gate * (this thread is running in the right process context)
37957c478bd9Sstevel@tonic-gate * - keep trace of the transaction (update of counters).
37967c478bd9Sstevel@tonic-gate * - free allocated buffers
37977c478bd9Sstevel@tonic-gate * The aiocb pointer is the object element of the port_kevent_t structure.
37987c478bd9Sstevel@tonic-gate *
37997c478bd9Sstevel@tonic-gate * flag :
38007c478bd9Sstevel@tonic-gate * PORT_CALLBACK_DEFAULT : do copyout and free resources
38017c478bd9Sstevel@tonic-gate * PORT_CALLBACK_CLOSE : don't do copyout, free resources
38027c478bd9Sstevel@tonic-gate */
38037c478bd9Sstevel@tonic-gate
38047c478bd9Sstevel@tonic-gate /*ARGSUSED*/
38057c478bd9Sstevel@tonic-gate int
aio_port_callback(void * arg,int * events,pid_t pid,int flag,void * evp)38067c478bd9Sstevel@tonic-gate aio_port_callback(void *arg, int *events, pid_t pid, int flag, void *evp)
38077c478bd9Sstevel@tonic-gate {
38087c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio;
38097c478bd9Sstevel@tonic-gate aio_req_t *reqp = arg;
38107c478bd9Sstevel@tonic-gate struct iovec *iov;
38117c478bd9Sstevel@tonic-gate struct buf *bp;
38127c478bd9Sstevel@tonic-gate void *resultp;
38137c478bd9Sstevel@tonic-gate
38147c478bd9Sstevel@tonic-gate if (pid != curproc->p_pid) {
38157c478bd9Sstevel@tonic-gate /* wrong proc !!, can not deliver data here ... */
38167c478bd9Sstevel@tonic-gate return (EACCES);
38177c478bd9Sstevel@tonic-gate }
38187c478bd9Sstevel@tonic-gate
38197c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_portq_mutex);
38207c478bd9Sstevel@tonic-gate reqp->aio_req_portkev = NULL;
38217c478bd9Sstevel@tonic-gate aio_req_remove_portq(aiop, reqp); /* remove request from portq */
38227c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex);
38237c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); /* unlock used pages */
38247c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex);
38257c478bd9Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_COPYOUTDONE) {
38267c478bd9Sstevel@tonic-gate aio_req_free_port(aiop, reqp); /* back to free list */
38277c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
38287c478bd9Sstevel@tonic-gate return (0);
38297c478bd9Sstevel@tonic-gate }
38307c478bd9Sstevel@tonic-gate
38317c478bd9Sstevel@tonic-gate iov = reqp->aio_req_uio.uio_iov;
38327c478bd9Sstevel@tonic-gate bp = &reqp->aio_req_buf;
38337c478bd9Sstevel@tonic-gate resultp = (void *)reqp->aio_req_resultp;
38347c478bd9Sstevel@tonic-gate aio_req_free_port(aiop, reqp); /* request struct back to free list */
38357c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex);
38367c478bd9Sstevel@tonic-gate if (flag == PORT_CALLBACK_DEFAULT)
38377c478bd9Sstevel@tonic-gate aio_copyout_result_port(iov, bp, resultp);
38387c478bd9Sstevel@tonic-gate return (0);
38397c478bd9Sstevel@tonic-gate }
3840