1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Kernel asynchronous I/O. 31*7c478bd9Sstevel@tonic-gate * This is only for raw devices now (as of Nov. 1993). 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/unistd.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 41*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 42*7c478bd9Sstevel@tonic-gate #include <vm/faultcode.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/aio_impl.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/fs/pxfs_ki.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/contract/process_impl.h> 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * external entry point. 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate #ifdef _LP64 61*7c478bd9Sstevel@tonic-gate static int64_t kaioc(long, long, long, long, long, long); 62*7c478bd9Sstevel@tonic-gate #endif 63*7c478bd9Sstevel@tonic-gate static int kaio(ulong_t *, rval_t *); 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define AIO_64 0 67*7c478bd9Sstevel@tonic-gate #define AIO_32 1 68*7c478bd9Sstevel@tonic-gate #define AIO_LARGEFILE 2 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * implementation specific functions (private) 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate #ifdef _LP64 74*7c478bd9Sstevel@tonic-gate static int alio(int, int, aiocb_t **, int, struct sigevent *); 75*7c478bd9Sstevel@tonic-gate #endif 76*7c478bd9Sstevel@tonic-gate static int aionotify(void); 77*7c478bd9Sstevel@tonic-gate static int aioinit(void); 78*7c478bd9Sstevel@tonic-gate static int aiostart(void); 79*7c478bd9Sstevel@tonic-gate static void alio_cleanup(aio_t *, aiocb_t **, int, int); 80*7c478bd9Sstevel@tonic-gate static int (*check_vp(struct vnode *, int))(vnode_t *, struct aio_req *, 81*7c478bd9Sstevel@tonic-gate cred_t *); 82*7c478bd9Sstevel@tonic-gate static void lio_set_error(aio_req_t *); 83*7c478bd9Sstevel@tonic-gate static aio_t *aio_aiop_alloc(); 84*7c478bd9Sstevel@tonic-gate static int aio_req_alloc(aio_req_t **, aio_result_t *); 85*7c478bd9Sstevel@tonic-gate static int aio_lio_alloc(aio_lio_t **); 86*7c478bd9Sstevel@tonic-gate static aio_req_t *aio_req_done(void *); 87*7c478bd9Sstevel@tonic-gate static aio_req_t *aio_req_remove(aio_req_t *); 88*7c478bd9Sstevel@tonic-gate static int aio_req_find(aio_result_t *, aio_req_t **); 89*7c478bd9Sstevel@tonic-gate static int aio_hash_insert(struct aio_req_t *, aio_t *); 90*7c478bd9Sstevel@tonic-gate static int aio_req_setup(aio_req_t **, aio_t *, aiocb_t *, 91*7c478bd9Sstevel@tonic-gate aio_result_t *, int, vnode_t *); 92*7c478bd9Sstevel@tonic-gate static int aio_cleanup_thread(aio_t *); 93*7c478bd9Sstevel@tonic-gate static aio_lio_t *aio_list_get(aio_result_t *); 94*7c478bd9Sstevel@tonic-gate static void lio_set_uerror(void *, int); 95*7c478bd9Sstevel@tonic-gate extern void aio_zerolen(aio_req_t *); 96*7c478bd9Sstevel@tonic-gate static int aiowait(struct timeval *, int, long *); 97*7c478bd9Sstevel@tonic-gate static int aiowaitn(void *, uint_t, uint_t *, timespec_t *); 98*7c478bd9Sstevel@tonic-gate static int aio_unlock_requests(caddr_t iocblist, int iocb_index, 99*7c478bd9Sstevel@tonic-gate aio_req_t *reqlist, aio_t *aiop, model_t model); 100*7c478bd9Sstevel@tonic-gate static int aio_reqlist_concat(aio_t *aiop, aio_req_t **reqlist, int max); 101*7c478bd9Sstevel@tonic-gate static int aiosuspend(void *, int, struct timespec *, int, 102*7c478bd9Sstevel@tonic-gate long *, int); 103*7c478bd9Sstevel@tonic-gate static int aliowait(int, void *, int, void *, int); 104*7c478bd9Sstevel@tonic-gate static int aioerror(void *, int); 105*7c478bd9Sstevel@tonic-gate static int aio_cancel(int, void *, long *, int); 106*7c478bd9Sstevel@tonic-gate static int arw(int, int, char *, int, offset_t, aio_result_t *, int); 107*7c478bd9Sstevel@tonic-gate static int aiorw(int, void *, int, int); 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate static int alioLF(int, void *, int, void *); 110*7c478bd9Sstevel@tonic-gate static int aio_req_setupLF(aio_req_t **, aio_t *, 111*7c478bd9Sstevel@tonic-gate aiocb64_32_t *, aio_result_t *, int, vnode_t *); 112*7c478bd9Sstevel@tonic-gate static int alio32(int, void *, int, void *); 113*7c478bd9Sstevel@tonic-gate static int driver_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p); 114*7c478bd9Sstevel@tonic-gate static int driver_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 117*7c478bd9Sstevel@tonic-gate static void aiocb_LFton(aiocb64_32_t *, aiocb_t *); 118*7c478bd9Sstevel@tonic-gate void aiocb_32ton(aiocb32_t *, aiocb_t *); 119*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * implementation specific functions (external) 123*7c478bd9Sstevel@tonic-gate */ 124*7c478bd9Sstevel@tonic-gate void aio_req_free(aio_t *, aio_req_t *); 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * Event Port framework 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate void aio_req_free_port(aio_t *, aio_req_t *); 131*7c478bd9Sstevel@tonic-gate static int aio_port_callback(void *, int *, pid_t, int, void *); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * This is the loadable module wrapper. 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 137*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate #ifdef _LP64 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static struct sysent kaio_sysent = { 142*7c478bd9Sstevel@tonic-gate 6, 143*7c478bd9Sstevel@tonic-gate SE_NOUNLOAD | SE_64RVAL | SE_ARGC, 144*7c478bd9Sstevel@tonic-gate (int (*)())kaioc 145*7c478bd9Sstevel@tonic-gate }; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 148*7c478bd9Sstevel@tonic-gate static struct sysent kaio_sysent32 = { 149*7c478bd9Sstevel@tonic-gate 7, 150*7c478bd9Sstevel@tonic-gate SE_NOUNLOAD | SE_64RVAL, 151*7c478bd9Sstevel@tonic-gate kaio 152*7c478bd9Sstevel@tonic-gate }; 153*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate #else /* _LP64 */ 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate static struct sysent kaio_sysent = { 158*7c478bd9Sstevel@tonic-gate 7, 159*7c478bd9Sstevel@tonic-gate SE_NOUNLOAD | SE_32RVAL1, 160*7c478bd9Sstevel@tonic-gate kaio 161*7c478bd9Sstevel@tonic-gate }; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate static struct modlsys modlsys = { 170*7c478bd9Sstevel@tonic-gate &mod_syscallops, 171*7c478bd9Sstevel@tonic-gate "kernel Async I/O", 172*7c478bd9Sstevel@tonic-gate &kaio_sysent 173*7c478bd9Sstevel@tonic-gate }; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 176*7c478bd9Sstevel@tonic-gate static struct modlsys modlsys32 = { 177*7c478bd9Sstevel@tonic-gate &mod_syscallops32, 178*7c478bd9Sstevel@tonic-gate "kernel Async I/O for 32 bit compatibility", 179*7c478bd9Sstevel@tonic-gate &kaio_sysent32 180*7c478bd9Sstevel@tonic-gate }; 181*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 185*7c478bd9Sstevel@tonic-gate MODREV_1, 186*7c478bd9Sstevel@tonic-gate &modlsys, 187*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 188*7c478bd9Sstevel@tonic-gate &modlsys32, 189*7c478bd9Sstevel@tonic-gate #endif 190*7c478bd9Sstevel@tonic-gate NULL 191*7c478bd9Sstevel@tonic-gate }; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate int 194*7c478bd9Sstevel@tonic-gate _init(void) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate int retval; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate if ((retval = mod_install(&modlinkage)) != 0) 199*7c478bd9Sstevel@tonic-gate return (retval); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate return (0); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate int 205*7c478bd9Sstevel@tonic-gate _fini(void) 206*7c478bd9Sstevel@tonic-gate { 207*7c478bd9Sstevel@tonic-gate int retval; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate retval = mod_remove(&modlinkage); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate return (retval); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate int 215*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 216*7c478bd9Sstevel@tonic-gate { 217*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate #ifdef _LP64 221*7c478bd9Sstevel@tonic-gate static int64_t 222*7c478bd9Sstevel@tonic-gate kaioc( 223*7c478bd9Sstevel@tonic-gate long a0, 224*7c478bd9Sstevel@tonic-gate long a1, 225*7c478bd9Sstevel@tonic-gate long a2, 226*7c478bd9Sstevel@tonic-gate long a3, 227*7c478bd9Sstevel@tonic-gate long a4, 228*7c478bd9Sstevel@tonic-gate long a5) 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate int error; 231*7c478bd9Sstevel@tonic-gate long rval = 0; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate switch ((int)a0 & ~AIO_POLL_BIT) { 234*7c478bd9Sstevel@tonic-gate case AIOREAD: 235*7c478bd9Sstevel@tonic-gate error = arw((int)a0, (int)a1, (char *)a2, (int)a3, 236*7c478bd9Sstevel@tonic-gate (offset_t)a4, (aio_result_t *)a5, FREAD); 237*7c478bd9Sstevel@tonic-gate break; 238*7c478bd9Sstevel@tonic-gate case AIOWRITE: 239*7c478bd9Sstevel@tonic-gate error = arw((int)a0, (int)a1, (char *)a2, (int)a3, 240*7c478bd9Sstevel@tonic-gate (offset_t)a4, (aio_result_t *)a5, FWRITE); 241*7c478bd9Sstevel@tonic-gate break; 242*7c478bd9Sstevel@tonic-gate case AIOWAIT: 243*7c478bd9Sstevel@tonic-gate error = aiowait((struct timeval *)a1, (int)a2, &rval); 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate case AIOWAITN: 246*7c478bd9Sstevel@tonic-gate error = aiowaitn((void *)a1, (uint_t)a2, (uint_t *)a3, 247*7c478bd9Sstevel@tonic-gate (timespec_t *)a4); 248*7c478bd9Sstevel@tonic-gate break; 249*7c478bd9Sstevel@tonic-gate case AIONOTIFY: 250*7c478bd9Sstevel@tonic-gate error = aionotify(); 251*7c478bd9Sstevel@tonic-gate break; 252*7c478bd9Sstevel@tonic-gate case AIOINIT: 253*7c478bd9Sstevel@tonic-gate error = aioinit(); 254*7c478bd9Sstevel@tonic-gate break; 255*7c478bd9Sstevel@tonic-gate case AIOSTART: 256*7c478bd9Sstevel@tonic-gate error = aiostart(); 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate case AIOLIO: 259*7c478bd9Sstevel@tonic-gate error = alio((int)a0, (int)a1, (aiocb_t **)a2, (int)a3, 260*7c478bd9Sstevel@tonic-gate (struct sigevent *)a4); 261*7c478bd9Sstevel@tonic-gate break; 262*7c478bd9Sstevel@tonic-gate case AIOLIOWAIT: 263*7c478bd9Sstevel@tonic-gate error = aliowait((int)a1, (void *)a2, (int)a3, 264*7c478bd9Sstevel@tonic-gate (struct sigevent *)a4, AIO_64); 265*7c478bd9Sstevel@tonic-gate break; 266*7c478bd9Sstevel@tonic-gate case AIOSUSPEND: 267*7c478bd9Sstevel@tonic-gate error = aiosuspend((void *)a1, (int)a2, (timespec_t *)a3, 268*7c478bd9Sstevel@tonic-gate (int)a4, &rval, AIO_64); 269*7c478bd9Sstevel@tonic-gate break; 270*7c478bd9Sstevel@tonic-gate case AIOERROR: 271*7c478bd9Sstevel@tonic-gate error = aioerror((void *)a1, AIO_64); 272*7c478bd9Sstevel@tonic-gate break; 273*7c478bd9Sstevel@tonic-gate case AIOAREAD: 274*7c478bd9Sstevel@tonic-gate error = aiorw((int)a0, (void *)a1, FREAD, AIO_64); 275*7c478bd9Sstevel@tonic-gate break; 276*7c478bd9Sstevel@tonic-gate case AIOAWRITE: 277*7c478bd9Sstevel@tonic-gate error = aiorw((int)a0, (void *)a1, FWRITE, AIO_64); 278*7c478bd9Sstevel@tonic-gate break; 279*7c478bd9Sstevel@tonic-gate case AIOCANCEL: 280*7c478bd9Sstevel@tonic-gate error = aio_cancel((int)a1, (void *)a2, &rval, AIO_64); 281*7c478bd9Sstevel@tonic-gate break; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate * The large file related stuff is valid only for 285*7c478bd9Sstevel@tonic-gate * 32 bit kernel and not for 64 bit kernel 286*7c478bd9Sstevel@tonic-gate * On 64 bit kernel we convert large file calls 287*7c478bd9Sstevel@tonic-gate * to regular 64bit calls. 288*7c478bd9Sstevel@tonic-gate */ 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate default: 291*7c478bd9Sstevel@tonic-gate error = EINVAL; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate if (error) 294*7c478bd9Sstevel@tonic-gate return ((int64_t)set_errno(error)); 295*7c478bd9Sstevel@tonic-gate return (rval); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate #endif 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate static int 300*7c478bd9Sstevel@tonic-gate kaio( 301*7c478bd9Sstevel@tonic-gate ulong_t *uap, 302*7c478bd9Sstevel@tonic-gate rval_t *rvp) 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate long rval = 0; 305*7c478bd9Sstevel@tonic-gate int error = 0; 306*7c478bd9Sstevel@tonic-gate offset_t off; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate rvp->r_vals = 0; 310*7c478bd9Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN) 311*7c478bd9Sstevel@tonic-gate off = ((u_offset_t)uap[5] << 32) | (u_offset_t)uap[4]; 312*7c478bd9Sstevel@tonic-gate #else 313*7c478bd9Sstevel@tonic-gate off = ((u_offset_t)uap[4] << 32) | (u_offset_t)uap[5]; 314*7c478bd9Sstevel@tonic-gate #endif 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate switch (uap[0] & ~AIO_POLL_BIT) { 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * It must be the 32 bit system call on 64 bit kernel 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate case AIOREAD: 321*7c478bd9Sstevel@tonic-gate return (arw((int)uap[0], (int)uap[1], (char *)uap[2], 322*7c478bd9Sstevel@tonic-gate (int)uap[3], off, (aio_result_t *)uap[6], FREAD)); 323*7c478bd9Sstevel@tonic-gate case AIOWRITE: 324*7c478bd9Sstevel@tonic-gate return (arw((int)uap[0], (int)uap[1], (char *)uap[2], 325*7c478bd9Sstevel@tonic-gate (int)uap[3], off, (aio_result_t *)uap[6], FWRITE)); 326*7c478bd9Sstevel@tonic-gate case AIOWAIT: 327*7c478bd9Sstevel@tonic-gate error = aiowait((struct timeval *)uap[1], (int)uap[2], 328*7c478bd9Sstevel@tonic-gate &rval); 329*7c478bd9Sstevel@tonic-gate break; 330*7c478bd9Sstevel@tonic-gate case AIOWAITN: 331*7c478bd9Sstevel@tonic-gate error = aiowaitn((void *)uap[1], (uint_t)uap[2], 332*7c478bd9Sstevel@tonic-gate (uint_t *)uap[3], (timespec_t *)uap[4]); 333*7c478bd9Sstevel@tonic-gate break; 334*7c478bd9Sstevel@tonic-gate case AIONOTIFY: 335*7c478bd9Sstevel@tonic-gate return (aionotify()); 336*7c478bd9Sstevel@tonic-gate case AIOINIT: 337*7c478bd9Sstevel@tonic-gate return (aioinit()); 338*7c478bd9Sstevel@tonic-gate case AIOSTART: 339*7c478bd9Sstevel@tonic-gate return (aiostart()); 340*7c478bd9Sstevel@tonic-gate case AIOLIO: 341*7c478bd9Sstevel@tonic-gate return (alio32((int)uap[1], (void *)uap[2], (int)uap[3], 342*7c478bd9Sstevel@tonic-gate (void *)uap[4])); 343*7c478bd9Sstevel@tonic-gate case AIOLIOWAIT: 344*7c478bd9Sstevel@tonic-gate return (aliowait((int)uap[1], (void *)uap[2], 345*7c478bd9Sstevel@tonic-gate (int)uap[3], (struct sigevent *)uap[4], AIO_32)); 346*7c478bd9Sstevel@tonic-gate case AIOSUSPEND: 347*7c478bd9Sstevel@tonic-gate error = aiosuspend((void *)uap[1], (int)uap[2], 348*7c478bd9Sstevel@tonic-gate (timespec_t *)uap[3], (int)uap[4], 349*7c478bd9Sstevel@tonic-gate &rval, AIO_32); 350*7c478bd9Sstevel@tonic-gate break; 351*7c478bd9Sstevel@tonic-gate case AIOERROR: 352*7c478bd9Sstevel@tonic-gate return (aioerror((void *)uap[1], AIO_32)); 353*7c478bd9Sstevel@tonic-gate case AIOAREAD: 354*7c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1], 355*7c478bd9Sstevel@tonic-gate FREAD, AIO_32)); 356*7c478bd9Sstevel@tonic-gate case AIOAWRITE: 357*7c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1], 358*7c478bd9Sstevel@tonic-gate FWRITE, AIO_32)); 359*7c478bd9Sstevel@tonic-gate case AIOCANCEL: 360*7c478bd9Sstevel@tonic-gate error = (aio_cancel((int)uap[1], (void *)uap[2], &rval, 361*7c478bd9Sstevel@tonic-gate AIO_32)); 362*7c478bd9Sstevel@tonic-gate break; 363*7c478bd9Sstevel@tonic-gate case AIOLIO64: 364*7c478bd9Sstevel@tonic-gate return (alioLF((int)uap[1], (void *)uap[2], 365*7c478bd9Sstevel@tonic-gate (int)uap[3], (void *)uap[4])); 366*7c478bd9Sstevel@tonic-gate case AIOLIOWAIT64: 367*7c478bd9Sstevel@tonic-gate return (aliowait(uap[1], (void *)uap[2], 368*7c478bd9Sstevel@tonic-gate (int)uap[3], (void *)uap[4], AIO_LARGEFILE)); 369*7c478bd9Sstevel@tonic-gate case AIOSUSPEND64: 370*7c478bd9Sstevel@tonic-gate error = aiosuspend((void *)uap[1], (int)uap[2], 371*7c478bd9Sstevel@tonic-gate (timespec_t *)uap[3], (int)uap[4], &rval, 372*7c478bd9Sstevel@tonic-gate AIO_LARGEFILE); 373*7c478bd9Sstevel@tonic-gate break; 374*7c478bd9Sstevel@tonic-gate case AIOERROR64: 375*7c478bd9Sstevel@tonic-gate return (aioerror((void *)uap[1], AIO_LARGEFILE)); 376*7c478bd9Sstevel@tonic-gate case AIOAREAD64: 377*7c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1], FREAD, 378*7c478bd9Sstevel@tonic-gate AIO_LARGEFILE)); 379*7c478bd9Sstevel@tonic-gate case AIOAWRITE64: 380*7c478bd9Sstevel@tonic-gate return (aiorw((int)uap[0], (void *)uap[1], FWRITE, 381*7c478bd9Sstevel@tonic-gate AIO_LARGEFILE)); 382*7c478bd9Sstevel@tonic-gate case AIOCANCEL64: 383*7c478bd9Sstevel@tonic-gate error = (aio_cancel((int)uap[1], (void *)uap[2], 384*7c478bd9Sstevel@tonic-gate &rval, AIO_LARGEFILE)); 385*7c478bd9Sstevel@tonic-gate break; 386*7c478bd9Sstevel@tonic-gate default: 387*7c478bd9Sstevel@tonic-gate return (EINVAL); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate rvp->r_val1 = rval; 391*7c478bd9Sstevel@tonic-gate return (error); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * wake up LWPs in this process that are sleeping in 396*7c478bd9Sstevel@tonic-gate * aiowait(). 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate static int 399*7c478bd9Sstevel@tonic-gate aionotify(void) 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate aio_t *aiop; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 404*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 405*7c478bd9Sstevel@tonic-gate return (0); 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 408*7c478bd9Sstevel@tonic-gate aiop->aio_notifycnt++; 409*7c478bd9Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv); 410*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate return (0); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate static int 416*7c478bd9Sstevel@tonic-gate timeval2reltime(struct timeval *timout, timestruc_t *rqtime, 417*7c478bd9Sstevel@tonic-gate timestruc_t **rqtp, int *blocking) 418*7c478bd9Sstevel@tonic-gate { 419*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 420*7c478bd9Sstevel@tonic-gate struct timeval32 wait_time_32; 421*7c478bd9Sstevel@tonic-gate #endif 422*7c478bd9Sstevel@tonic-gate struct timeval wait_time; 423*7c478bd9Sstevel@tonic-gate model_t model = get_udatamodel(); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate *rqtp = NULL; 426*7c478bd9Sstevel@tonic-gate if (timout == NULL) { /* wait indefinitely */ 427*7c478bd9Sstevel@tonic-gate *blocking = 1; 428*7c478bd9Sstevel@tonic-gate return (0); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate /* 432*7c478bd9Sstevel@tonic-gate * Need to correctly compare with the -1 passed in for a user 433*7c478bd9Sstevel@tonic-gate * address pointer, with both 32 bit and 64 bit apps. 434*7c478bd9Sstevel@tonic-gate */ 435*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) { 436*7c478bd9Sstevel@tonic-gate if ((intptr_t)timout == (intptr_t)-1) { /* don't wait */ 437*7c478bd9Sstevel@tonic-gate *blocking = 0; 438*7c478bd9Sstevel@tonic-gate return (0); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate if (copyin(timout, &wait_time, sizeof (wait_time))) 442*7c478bd9Sstevel@tonic-gate return (EFAULT); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 445*7c478bd9Sstevel@tonic-gate else { 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * -1 from a 32bit app. It will not get sign extended. 448*7c478bd9Sstevel@tonic-gate * don't wait if -1. 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate if ((intptr_t)timout == (intptr_t)((uint32_t)-1)) { 451*7c478bd9Sstevel@tonic-gate *blocking = 0; 452*7c478bd9Sstevel@tonic-gate return (0); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (copyin(timout, &wait_time_32, sizeof (wait_time_32))) 456*7c478bd9Sstevel@tonic-gate return (EFAULT); 457*7c478bd9Sstevel@tonic-gate TIMEVAL32_TO_TIMEVAL(&wait_time, &wait_time_32); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate if (wait_time.tv_sec == 0 && wait_time.tv_usec == 0) { /* don't wait */ 462*7c478bd9Sstevel@tonic-gate *blocking = 0; 463*7c478bd9Sstevel@tonic-gate return (0); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate if (wait_time.tv_sec < 0 || 467*7c478bd9Sstevel@tonic-gate wait_time.tv_usec < 0 || wait_time.tv_usec >= MICROSEC) 468*7c478bd9Sstevel@tonic-gate return (EINVAL); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate rqtime->tv_sec = wait_time.tv_sec; 471*7c478bd9Sstevel@tonic-gate rqtime->tv_nsec = wait_time.tv_usec * 1000; 472*7c478bd9Sstevel@tonic-gate *rqtp = rqtime; 473*7c478bd9Sstevel@tonic-gate *blocking = 1; 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate return (0); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate static int 479*7c478bd9Sstevel@tonic-gate timespec2reltime(timespec_t *timout, timestruc_t *rqtime, 480*7c478bd9Sstevel@tonic-gate timestruc_t **rqtp, int *blocking) 481*7c478bd9Sstevel@tonic-gate { 482*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 483*7c478bd9Sstevel@tonic-gate timespec32_t wait_time_32; 484*7c478bd9Sstevel@tonic-gate #endif 485*7c478bd9Sstevel@tonic-gate model_t model = get_udatamodel(); 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate *rqtp = NULL; 488*7c478bd9Sstevel@tonic-gate if (timout == NULL) { 489*7c478bd9Sstevel@tonic-gate *blocking = 1; 490*7c478bd9Sstevel@tonic-gate return (0); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) { 494*7c478bd9Sstevel@tonic-gate if (copyin(timout, rqtime, sizeof (*rqtime))) 495*7c478bd9Sstevel@tonic-gate return (EFAULT); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 498*7c478bd9Sstevel@tonic-gate else { 499*7c478bd9Sstevel@tonic-gate if (copyin(timout, &wait_time_32, sizeof (wait_time_32))) 500*7c478bd9Sstevel@tonic-gate return (EFAULT); 501*7c478bd9Sstevel@tonic-gate TIMESPEC32_TO_TIMESPEC(rqtime, &wait_time_32); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (rqtime->tv_sec == 0 && rqtime->tv_nsec == 0) { 506*7c478bd9Sstevel@tonic-gate *blocking = 0; 507*7c478bd9Sstevel@tonic-gate return (0); 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if (rqtime->tv_sec < 0 || 511*7c478bd9Sstevel@tonic-gate rqtime->tv_nsec < 0 || rqtime->tv_nsec >= NANOSEC) 512*7c478bd9Sstevel@tonic-gate return (EINVAL); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate *rqtp = rqtime; 515*7c478bd9Sstevel@tonic-gate *blocking = 1; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate return (0); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 521*7c478bd9Sstevel@tonic-gate static int 522*7c478bd9Sstevel@tonic-gate aiowait( 523*7c478bd9Sstevel@tonic-gate struct timeval *timout, 524*7c478bd9Sstevel@tonic-gate int dontblockflg, 525*7c478bd9Sstevel@tonic-gate long *rval) 526*7c478bd9Sstevel@tonic-gate { 527*7c478bd9Sstevel@tonic-gate int error; 528*7c478bd9Sstevel@tonic-gate aio_t *aiop; 529*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 530*7c478bd9Sstevel@tonic-gate clock_t status; 531*7c478bd9Sstevel@tonic-gate int blocking; 532*7c478bd9Sstevel@tonic-gate int timecheck; 533*7c478bd9Sstevel@tonic-gate timestruc_t rqtime; 534*7c478bd9Sstevel@tonic-gate timestruc_t *rqtp; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 537*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 538*7c478bd9Sstevel@tonic-gate return (EINVAL); 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * Establish the absolute future time for the timeout. 542*7c478bd9Sstevel@tonic-gate */ 543*7c478bd9Sstevel@tonic-gate error = timeval2reltime(timout, &rqtime, &rqtp, &blocking); 544*7c478bd9Sstevel@tonic-gate if (error) 545*7c478bd9Sstevel@tonic-gate return (error); 546*7c478bd9Sstevel@tonic-gate if (rqtp) { 547*7c478bd9Sstevel@tonic-gate timestruc_t now; 548*7c478bd9Sstevel@tonic-gate timecheck = timechanged; 549*7c478bd9Sstevel@tonic-gate gethrestime(&now); 550*7c478bd9Sstevel@tonic-gate timespecadd(rqtp, &now); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 554*7c478bd9Sstevel@tonic-gate for (;;) { 555*7c478bd9Sstevel@tonic-gate /* process requests on poll queue */ 556*7c478bd9Sstevel@tonic-gate if (aiop->aio_pollq) { 557*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 558*7c478bd9Sstevel@tonic-gate aio_cleanup(0); 559*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate if ((reqp = aio_req_remove(NULL)) != NULL) { 562*7c478bd9Sstevel@tonic-gate *rval = (long)reqp->aio_req_resultp; 563*7c478bd9Sstevel@tonic-gate break; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate /* user-level done queue might not be empty */ 566*7c478bd9Sstevel@tonic-gate if (aiop->aio_notifycnt > 0) { 567*7c478bd9Sstevel@tonic-gate aiop->aio_notifycnt--; 568*7c478bd9Sstevel@tonic-gate *rval = 1; 569*7c478bd9Sstevel@tonic-gate break; 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate /* don't block if no outstanding aio */ 572*7c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0 && dontblockflg) { 573*7c478bd9Sstevel@tonic-gate error = EINVAL; 574*7c478bd9Sstevel@tonic-gate break; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate if (blocking) { 577*7c478bd9Sstevel@tonic-gate status = cv_waituntil_sig(&aiop->aio_waitcv, 578*7c478bd9Sstevel@tonic-gate &aiop->aio_mutex, rqtp, timecheck); 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate if (status > 0) /* check done queue again */ 581*7c478bd9Sstevel@tonic-gate continue; 582*7c478bd9Sstevel@tonic-gate if (status == 0) { /* interrupted by a signal */ 583*7c478bd9Sstevel@tonic-gate error = EINTR; 584*7c478bd9Sstevel@tonic-gate *rval = -1; 585*7c478bd9Sstevel@tonic-gate } else { /* timer expired */ 586*7c478bd9Sstevel@tonic-gate error = ETIME; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate break; 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 592*7c478bd9Sstevel@tonic-gate if (reqp) { 593*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); 594*7c478bd9Sstevel@tonic-gate aio_copyout_result(reqp); 595*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 596*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 597*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate return (error); 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * aiowaitn can be used to reap completed asynchronous requests submitted with 604*7c478bd9Sstevel@tonic-gate * lio_listio, aio_read or aio_write. 605*7c478bd9Sstevel@tonic-gate * This function only reaps asynchronous raw I/Os. 606*7c478bd9Sstevel@tonic-gate */ 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 609*7c478bd9Sstevel@tonic-gate static int 610*7c478bd9Sstevel@tonic-gate aiowaitn(void *uiocb, uint_t nent, uint_t *nwait, timespec_t *timout) 611*7c478bd9Sstevel@tonic-gate { 612*7c478bd9Sstevel@tonic-gate int error = 0; 613*7c478bd9Sstevel@tonic-gate aio_t *aiop; 614*7c478bd9Sstevel@tonic-gate aio_req_t *reqlist = NULL; 615*7c478bd9Sstevel@tonic-gate caddr_t iocblist = NULL; /* array of iocb ptr's */ 616*7c478bd9Sstevel@tonic-gate uint_t waitcnt, cnt = 0; /* iocb cnt */ 617*7c478bd9Sstevel@tonic-gate size_t iocbsz; /* users iocb size */ 618*7c478bd9Sstevel@tonic-gate size_t riocbsz; /* returned iocb size */ 619*7c478bd9Sstevel@tonic-gate int iocb_index = 0; 620*7c478bd9Sstevel@tonic-gate model_t model = get_udatamodel(); 621*7c478bd9Sstevel@tonic-gate int blocking = 1; 622*7c478bd9Sstevel@tonic-gate int timecheck; 623*7c478bd9Sstevel@tonic-gate timestruc_t rqtime; 624*7c478bd9Sstevel@tonic-gate timestruc_t *rqtp; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 627*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 628*7c478bd9Sstevel@tonic-gate return (EINVAL); 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0) 631*7c478bd9Sstevel@tonic-gate return (EAGAIN); 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate if (copyin(nwait, &waitcnt, sizeof (uint_t))) 634*7c478bd9Sstevel@tonic-gate return (EFAULT); 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate /* set *nwait to zero, if we must return prematurely */ 637*7c478bd9Sstevel@tonic-gate if (copyout(&cnt, nwait, sizeof (uint_t))) 638*7c478bd9Sstevel@tonic-gate return (EFAULT); 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate if (waitcnt == 0) { 641*7c478bd9Sstevel@tonic-gate blocking = 0; 642*7c478bd9Sstevel@tonic-gate rqtp = NULL; 643*7c478bd9Sstevel@tonic-gate waitcnt = nent; 644*7c478bd9Sstevel@tonic-gate } else { 645*7c478bd9Sstevel@tonic-gate error = timespec2reltime(timout, &rqtime, &rqtp, &blocking); 646*7c478bd9Sstevel@tonic-gate if (error) 647*7c478bd9Sstevel@tonic-gate return (error); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 651*7c478bd9Sstevel@tonic-gate iocbsz = (sizeof (aiocb_t *) * nent); 652*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 653*7c478bd9Sstevel@tonic-gate else 654*7c478bd9Sstevel@tonic-gate iocbsz = (sizeof (caddr32_t) * nent); 655*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate /* 658*7c478bd9Sstevel@tonic-gate * Only one aio_waitn call is allowed at a time. 659*7c478bd9Sstevel@tonic-gate * The active aio_waitn will collect all requests 660*7c478bd9Sstevel@tonic-gate * out of the "done" list and if necessary it will wait 661*7c478bd9Sstevel@tonic-gate * for some/all pending requests to fulfill the nwait 662*7c478bd9Sstevel@tonic-gate * parameter. 663*7c478bd9Sstevel@tonic-gate * A second or further aio_waitn calls will sleep here 664*7c478bd9Sstevel@tonic-gate * until the active aio_waitn finishes and leaves the kernel 665*7c478bd9Sstevel@tonic-gate * If the second call does not block (poll), then return 666*7c478bd9Sstevel@tonic-gate * immediately with the error code : EAGAIN. 667*7c478bd9Sstevel@tonic-gate * If the second call should block, then sleep here, but 668*7c478bd9Sstevel@tonic-gate * do not touch the timeout. The timeout starts when this 669*7c478bd9Sstevel@tonic-gate * aio_waitn-call becomes active. 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate while (aiop->aio_flags & AIO_WAITN) { 675*7c478bd9Sstevel@tonic-gate if (blocking == 0) { 676*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 677*7c478bd9Sstevel@tonic-gate return (EAGAIN); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate /* block, no timeout */ 681*7c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_WAITN_PENDING; 682*7c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&aiop->aio_waitncv, &aiop->aio_mutex)) { 683*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 684*7c478bd9Sstevel@tonic-gate return (EINTR); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate /* 689*7c478bd9Sstevel@tonic-gate * Establish the absolute future time for the timeout. 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate if (rqtp) { 692*7c478bd9Sstevel@tonic-gate timestruc_t now; 693*7c478bd9Sstevel@tonic-gate timecheck = timechanged; 694*7c478bd9Sstevel@tonic-gate gethrestime(&now); 695*7c478bd9Sstevel@tonic-gate timespecadd(rqtp, &now); 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate if (iocbsz > aiop->aio_iocbsz && aiop->aio_iocb != NULL) { 699*7c478bd9Sstevel@tonic-gate kmem_free(aiop->aio_iocb, aiop->aio_iocbsz); 700*7c478bd9Sstevel@tonic-gate aiop->aio_iocb = NULL; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate if (aiop->aio_iocb == NULL) { 704*7c478bd9Sstevel@tonic-gate iocblist = kmem_zalloc(iocbsz, KM_NOSLEEP); 705*7c478bd9Sstevel@tonic-gate if (iocblist == NULL) { 706*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 707*7c478bd9Sstevel@tonic-gate return (ENOMEM); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate aiop->aio_iocb = (aiocb_t **)iocblist; 710*7c478bd9Sstevel@tonic-gate aiop->aio_iocbsz = iocbsz; 711*7c478bd9Sstevel@tonic-gate } else { 712*7c478bd9Sstevel@tonic-gate iocblist = (char *)aiop->aio_iocb; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate aiop->aio_waitncnt = waitcnt; 716*7c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_WAITN; 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate for (;;) { 719*7c478bd9Sstevel@tonic-gate /* push requests on poll queue to done queue */ 720*7c478bd9Sstevel@tonic-gate if (aiop->aio_pollq) { 721*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 722*7c478bd9Sstevel@tonic-gate aio_cleanup(0); 723*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate /* check for requests on done queue */ 727*7c478bd9Sstevel@tonic-gate if (aiop->aio_doneq) { 728*7c478bd9Sstevel@tonic-gate cnt += aio_reqlist_concat(aiop, &reqlist, nent - cnt); 729*7c478bd9Sstevel@tonic-gate aiop->aio_waitncnt = waitcnt - cnt; 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate /* user-level done queue might not be empty */ 733*7c478bd9Sstevel@tonic-gate if (aiop->aio_notifycnt > 0) { 734*7c478bd9Sstevel@tonic-gate aiop->aio_notifycnt--; 735*7c478bd9Sstevel@tonic-gate error = 0; 736*7c478bd9Sstevel@tonic-gate break; 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate /* 740*7c478bd9Sstevel@tonic-gate * if we are here second time as a result of timer 741*7c478bd9Sstevel@tonic-gate * expiration, we reset error if there are enough 742*7c478bd9Sstevel@tonic-gate * aiocb's to satisfy request. 743*7c478bd9Sstevel@tonic-gate * We return also if all requests are already done 744*7c478bd9Sstevel@tonic-gate * and we picked up the whole done queue. 745*7c478bd9Sstevel@tonic-gate */ 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate if ((cnt >= waitcnt) || (cnt > 0 && aiop->aio_pending == 0 && 748*7c478bd9Sstevel@tonic-gate aiop->aio_doneq == NULL)) { 749*7c478bd9Sstevel@tonic-gate error = 0; 750*7c478bd9Sstevel@tonic-gate break; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate if ((cnt < waitcnt) && blocking) { 754*7c478bd9Sstevel@tonic-gate int rval = cv_waituntil_sig(&aiop->aio_waitcv, 755*7c478bd9Sstevel@tonic-gate &aiop->aio_mutex, rqtp, timecheck); 756*7c478bd9Sstevel@tonic-gate if (rval > 0) 757*7c478bd9Sstevel@tonic-gate continue; 758*7c478bd9Sstevel@tonic-gate if (rval < 0) { 759*7c478bd9Sstevel@tonic-gate error = ETIME; 760*7c478bd9Sstevel@tonic-gate blocking = 0; 761*7c478bd9Sstevel@tonic-gate continue; 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate error = EINTR; 764*7c478bd9Sstevel@tonic-gate } 765*7c478bd9Sstevel@tonic-gate break; 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate if (cnt > 0) { 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate iocb_index = aio_unlock_requests(iocblist, iocb_index, reqlist, 773*7c478bd9Sstevel@tonic-gate aiop, model); 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 776*7c478bd9Sstevel@tonic-gate riocbsz = (sizeof (aiocb_t *) * cnt); 777*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 778*7c478bd9Sstevel@tonic-gate else 779*7c478bd9Sstevel@tonic-gate riocbsz = (sizeof (caddr32_t) * cnt); 780*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate if (copyout(iocblist, uiocb, riocbsz) || 783*7c478bd9Sstevel@tonic-gate copyout(&cnt, nwait, sizeof (uint_t))) 784*7c478bd9Sstevel@tonic-gate error = EFAULT; 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate if (aiop->aio_iocbsz > AIO_IOCB_MAX) { 788*7c478bd9Sstevel@tonic-gate kmem_free(iocblist, aiop->aio_iocbsz); 789*7c478bd9Sstevel@tonic-gate aiop->aio_iocb = NULL; 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate /* check if there is another thread waiting for execution */ 793*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 794*7c478bd9Sstevel@tonic-gate aiop->aio_flags &= ~AIO_WAITN; 795*7c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_WAITN_PENDING) { 796*7c478bd9Sstevel@tonic-gate aiop->aio_flags &= ~AIO_WAITN_PENDING; 797*7c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_waitncv); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate return (error); 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* 805*7c478bd9Sstevel@tonic-gate * aio_unlock_requests 806*7c478bd9Sstevel@tonic-gate * copyouts the result of the request as well as the return value. 807*7c478bd9Sstevel@tonic-gate * It builds the list of completed asynchronous requests, 808*7c478bd9Sstevel@tonic-gate * unlocks the allocated memory ranges and 809*7c478bd9Sstevel@tonic-gate * put the aio request structure back into the free list. 810*7c478bd9Sstevel@tonic-gate */ 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate static int 813*7c478bd9Sstevel@tonic-gate aio_unlock_requests( 814*7c478bd9Sstevel@tonic-gate caddr_t iocblist, 815*7c478bd9Sstevel@tonic-gate int iocb_index, 816*7c478bd9Sstevel@tonic-gate aio_req_t *reqlist, 817*7c478bd9Sstevel@tonic-gate aio_t *aiop, 818*7c478bd9Sstevel@tonic-gate model_t model) 819*7c478bd9Sstevel@tonic-gate { 820*7c478bd9Sstevel@tonic-gate aio_req_t *reqp, *nreqp; 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) { 823*7c478bd9Sstevel@tonic-gate for (reqp = reqlist; reqp != NULL; reqp = nreqp) { 824*7c478bd9Sstevel@tonic-gate (((caddr_t *)iocblist)[iocb_index++]) = 825*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb; 826*7c478bd9Sstevel@tonic-gate nreqp = reqp->aio_req_next; 827*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); 828*7c478bd9Sstevel@tonic-gate aio_copyout_result(reqp); 829*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 830*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 831*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 835*7c478bd9Sstevel@tonic-gate else { 836*7c478bd9Sstevel@tonic-gate for (reqp = reqlist; reqp != NULL; reqp = nreqp) { 837*7c478bd9Sstevel@tonic-gate ((caddr32_t *)iocblist)[iocb_index++] = 838*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32; 839*7c478bd9Sstevel@tonic-gate nreqp = reqp->aio_req_next; 840*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); 841*7c478bd9Sstevel@tonic-gate aio_copyout_result(reqp); 842*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 843*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 844*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 848*7c478bd9Sstevel@tonic-gate return (iocb_index); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate /* 852*7c478bd9Sstevel@tonic-gate * aio_reqlist_concat 853*7c478bd9Sstevel@tonic-gate * moves "max" elements from the done queue to the reqlist queue and removes 854*7c478bd9Sstevel@tonic-gate * the AIO_DONEQ flag. 855*7c478bd9Sstevel@tonic-gate * - reqlist queue is a simple linked list 856*7c478bd9Sstevel@tonic-gate * - done queue is a double linked list 857*7c478bd9Sstevel@tonic-gate */ 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate static int 860*7c478bd9Sstevel@tonic-gate aio_reqlist_concat(aio_t *aiop, aio_req_t **reqlist, int max) 861*7c478bd9Sstevel@tonic-gate { 862*7c478bd9Sstevel@tonic-gate aio_req_t *q2, *q2work, *list; 863*7c478bd9Sstevel@tonic-gate int count = 0; 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate list = *reqlist; 866*7c478bd9Sstevel@tonic-gate q2 = aiop->aio_doneq; 867*7c478bd9Sstevel@tonic-gate q2work = q2; 868*7c478bd9Sstevel@tonic-gate while (max-- > 0) { 869*7c478bd9Sstevel@tonic-gate q2work->aio_req_flags &= ~AIO_DONEQ; 870*7c478bd9Sstevel@tonic-gate q2work = q2work->aio_req_next; 871*7c478bd9Sstevel@tonic-gate count++; 872*7c478bd9Sstevel@tonic-gate if (q2work == q2) 873*7c478bd9Sstevel@tonic-gate break; 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate if (q2work == q2) { 877*7c478bd9Sstevel@tonic-gate /* all elements revised */ 878*7c478bd9Sstevel@tonic-gate q2->aio_req_prev->aio_req_next = list; 879*7c478bd9Sstevel@tonic-gate list = q2; 880*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL; 881*7c478bd9Sstevel@tonic-gate } else { 882*7c478bd9Sstevel@tonic-gate /* 883*7c478bd9Sstevel@tonic-gate * max < elements in the doneq 884*7c478bd9Sstevel@tonic-gate * detach only the required amount of elements 885*7c478bd9Sstevel@tonic-gate * out of the doneq 886*7c478bd9Sstevel@tonic-gate */ 887*7c478bd9Sstevel@tonic-gate q2work->aio_req_prev->aio_req_next = list; 888*7c478bd9Sstevel@tonic-gate list = q2; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = q2work; 891*7c478bd9Sstevel@tonic-gate q2work->aio_req_prev = q2->aio_req_prev; 892*7c478bd9Sstevel@tonic-gate q2->aio_req_prev->aio_req_next = q2work; 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate *reqlist = list; 895*7c478bd9Sstevel@tonic-gate return (count); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 899*7c478bd9Sstevel@tonic-gate static int 900*7c478bd9Sstevel@tonic-gate aiosuspend( 901*7c478bd9Sstevel@tonic-gate void *aiocb, 902*7c478bd9Sstevel@tonic-gate int nent, 903*7c478bd9Sstevel@tonic-gate struct timespec *timout, 904*7c478bd9Sstevel@tonic-gate int flag, 905*7c478bd9Sstevel@tonic-gate long *rval, 906*7c478bd9Sstevel@tonic-gate int run_mode) 907*7c478bd9Sstevel@tonic-gate { 908*7c478bd9Sstevel@tonic-gate int error; 909*7c478bd9Sstevel@tonic-gate aio_t *aiop; 910*7c478bd9Sstevel@tonic-gate aio_req_t *reqp, *found, *next; 911*7c478bd9Sstevel@tonic-gate caddr_t cbplist = NULL; 912*7c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp; 913*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 914*7c478bd9Sstevel@tonic-gate aiocb32_t *cbp32; 915*7c478bd9Sstevel@tonic-gate caddr32_t *ucbp32; 916*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 917*7c478bd9Sstevel@tonic-gate aiocb64_32_t *cbp64; 918*7c478bd9Sstevel@tonic-gate int rv; 919*7c478bd9Sstevel@tonic-gate int i; 920*7c478bd9Sstevel@tonic-gate size_t ssize; 921*7c478bd9Sstevel@tonic-gate model_t model = get_udatamodel(); 922*7c478bd9Sstevel@tonic-gate int blocking; 923*7c478bd9Sstevel@tonic-gate int timecheck; 924*7c478bd9Sstevel@tonic-gate timestruc_t rqtime; 925*7c478bd9Sstevel@tonic-gate timestruc_t *rqtp; 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 928*7c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0) 929*7c478bd9Sstevel@tonic-gate return (EINVAL); 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate /* 932*7c478bd9Sstevel@tonic-gate * Establish the absolute future time for the timeout. 933*7c478bd9Sstevel@tonic-gate */ 934*7c478bd9Sstevel@tonic-gate error = timespec2reltime(timout, &rqtime, &rqtp, &blocking); 935*7c478bd9Sstevel@tonic-gate if (error) 936*7c478bd9Sstevel@tonic-gate return (error); 937*7c478bd9Sstevel@tonic-gate if (rqtp) { 938*7c478bd9Sstevel@tonic-gate timestruc_t now; 939*7c478bd9Sstevel@tonic-gate timecheck = timechanged; 940*7c478bd9Sstevel@tonic-gate gethrestime(&now); 941*7c478bd9Sstevel@tonic-gate timespecadd(rqtp, &now); 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate /* 945*7c478bd9Sstevel@tonic-gate * If we are not blocking and there's no IO complete 946*7c478bd9Sstevel@tonic-gate * skip aiocb copyin. 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate if (!blocking && (aiop->aio_pollq == NULL) && 949*7c478bd9Sstevel@tonic-gate (aiop->aio_doneq == NULL)) { 950*7c478bd9Sstevel@tonic-gate return (EAGAIN); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 954*7c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent); 955*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 956*7c478bd9Sstevel@tonic-gate else 957*7c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent); 958*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_NOSLEEP); 961*7c478bd9Sstevel@tonic-gate if (cbplist == NULL) 962*7c478bd9Sstevel@tonic-gate return (ENOMEM); 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate if (copyin(aiocb, cbplist, ssize)) { 965*7c478bd9Sstevel@tonic-gate error = EFAULT; 966*7c478bd9Sstevel@tonic-gate goto done; 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate found = NULL; 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * we need to get the aio_cleanupq_mutex since we call 972*7c478bd9Sstevel@tonic-gate * aio_req_done(). 973*7c478bd9Sstevel@tonic-gate */ 974*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex); 975*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 976*7c478bd9Sstevel@tonic-gate for (;;) { 977*7c478bd9Sstevel@tonic-gate /* push requests on poll queue to done queue */ 978*7c478bd9Sstevel@tonic-gate if (aiop->aio_pollq) { 979*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 980*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 981*7c478bd9Sstevel@tonic-gate aio_cleanup(0); 982*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex); 983*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate /* check for requests on done queue */ 986*7c478bd9Sstevel@tonic-gate if (aiop->aio_doneq) { 987*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 988*7c478bd9Sstevel@tonic-gate ucbp = (aiocb_t **)cbplist; 989*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 990*7c478bd9Sstevel@tonic-gate else 991*7c478bd9Sstevel@tonic-gate ucbp32 = (caddr32_t *)cbplist; 992*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 993*7c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++) { 994*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) { 995*7c478bd9Sstevel@tonic-gate if ((cbp = *ucbp++) == NULL) 996*7c478bd9Sstevel@tonic-gate continue; 997*7c478bd9Sstevel@tonic-gate if (run_mode != AIO_LARGEFILE) 998*7c478bd9Sstevel@tonic-gate reqp = aio_req_done( 999*7c478bd9Sstevel@tonic-gate &cbp->aio_resultp); 1000*7c478bd9Sstevel@tonic-gate else { 1001*7c478bd9Sstevel@tonic-gate cbp64 = (aiocb64_32_t *)cbp; 1002*7c478bd9Sstevel@tonic-gate reqp = aio_req_done( 1003*7c478bd9Sstevel@tonic-gate &cbp64->aio_resultp); 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate } 1006*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1007*7c478bd9Sstevel@tonic-gate else { 1008*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_32) { 1009*7c478bd9Sstevel@tonic-gate if ((cbp32 = 1010*7c478bd9Sstevel@tonic-gate (aiocb32_t *)(uintptr_t) 1011*7c478bd9Sstevel@tonic-gate *ucbp32++) == NULL) 1012*7c478bd9Sstevel@tonic-gate continue; 1013*7c478bd9Sstevel@tonic-gate reqp = aio_req_done( 1014*7c478bd9Sstevel@tonic-gate &cbp32->aio_resultp); 1015*7c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_LARGEFILE) { 1016*7c478bd9Sstevel@tonic-gate if ((cbp64 = 1017*7c478bd9Sstevel@tonic-gate (aiocb64_32_t *)(uintptr_t) 1018*7c478bd9Sstevel@tonic-gate *ucbp32++) == NULL) 1019*7c478bd9Sstevel@tonic-gate continue; 1020*7c478bd9Sstevel@tonic-gate reqp = aio_req_done( 1021*7c478bd9Sstevel@tonic-gate &cbp64->aio_resultp); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1026*7c478bd9Sstevel@tonic-gate if (reqp) { 1027*7c478bd9Sstevel@tonic-gate reqp->aio_req_next = found; 1028*7c478bd9Sstevel@tonic-gate found = reqp; 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate if (aiop->aio_doneq == NULL) 1031*7c478bd9Sstevel@tonic-gate break; 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate if (found) 1034*7c478bd9Sstevel@tonic-gate break; 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate if (aiop->aio_notifycnt > 0) { 1037*7c478bd9Sstevel@tonic-gate /* 1038*7c478bd9Sstevel@tonic-gate * nothing on the kernel's queue. the user 1039*7c478bd9Sstevel@tonic-gate * has notified the kernel that it has items 1040*7c478bd9Sstevel@tonic-gate * on a user-level queue. 1041*7c478bd9Sstevel@tonic-gate */ 1042*7c478bd9Sstevel@tonic-gate aiop->aio_notifycnt--; 1043*7c478bd9Sstevel@tonic-gate *rval = 1; 1044*7c478bd9Sstevel@tonic-gate error = 0; 1045*7c478bd9Sstevel@tonic-gate break; 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate /* don't block if nothing is outstanding */ 1048*7c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0) { 1049*7c478bd9Sstevel@tonic-gate error = EAGAIN; 1050*7c478bd9Sstevel@tonic-gate break; 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate if (blocking) { 1053*7c478bd9Sstevel@tonic-gate /* 1054*7c478bd9Sstevel@tonic-gate * drop the aio_cleanupq_mutex as we are 1055*7c478bd9Sstevel@tonic-gate * going to block. 1056*7c478bd9Sstevel@tonic-gate */ 1057*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 1058*7c478bd9Sstevel@tonic-gate rv = cv_waituntil_sig(&aiop->aio_waitcv, 1059*7c478bd9Sstevel@tonic-gate &aiop->aio_mutex, rqtp, timecheck); 1060*7c478bd9Sstevel@tonic-gate /* 1061*7c478bd9Sstevel@tonic-gate * we have to drop aio_mutex and 1062*7c478bd9Sstevel@tonic-gate * grab it in the right order. 1063*7c478bd9Sstevel@tonic-gate */ 1064*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1065*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex); 1066*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1067*7c478bd9Sstevel@tonic-gate if (rv > 0) /* check done queue again */ 1068*7c478bd9Sstevel@tonic-gate continue; 1069*7c478bd9Sstevel@tonic-gate if (rv == 0) /* interrupted by a signal */ 1070*7c478bd9Sstevel@tonic-gate error = EINTR; 1071*7c478bd9Sstevel@tonic-gate else /* timer expired */ 1072*7c478bd9Sstevel@tonic-gate error = ETIME; 1073*7c478bd9Sstevel@tonic-gate } else { 1074*7c478bd9Sstevel@tonic-gate error = EAGAIN; 1075*7c478bd9Sstevel@tonic-gate } 1076*7c478bd9Sstevel@tonic-gate break; 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1079*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 1080*7c478bd9Sstevel@tonic-gate for (reqp = found; reqp != NULL; reqp = next) { 1081*7c478bd9Sstevel@tonic-gate next = reqp->aio_req_next; 1082*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); 1083*7c478bd9Sstevel@tonic-gate aio_copyout_result(reqp); 1084*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1085*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 1086*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1087*7c478bd9Sstevel@tonic-gate } 1088*7c478bd9Sstevel@tonic-gate done: 1089*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1090*7c478bd9Sstevel@tonic-gate return (error); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate /* 1094*7c478bd9Sstevel@tonic-gate * initialize aio by allocating an aio_t struct for this 1095*7c478bd9Sstevel@tonic-gate * process. 1096*7c478bd9Sstevel@tonic-gate */ 1097*7c478bd9Sstevel@tonic-gate static int 1098*7c478bd9Sstevel@tonic-gate aioinit(void) 1099*7c478bd9Sstevel@tonic-gate { 1100*7c478bd9Sstevel@tonic-gate proc_t *p = curproc; 1101*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1102*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1103*7c478bd9Sstevel@tonic-gate if ((aiop = p->p_aio) == NULL) { 1104*7c478bd9Sstevel@tonic-gate aiop = aio_aiop_alloc(); 1105*7c478bd9Sstevel@tonic-gate p->p_aio = aiop; 1106*7c478bd9Sstevel@tonic-gate } 1107*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1108*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 1109*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1110*7c478bd9Sstevel@tonic-gate return (0); 1111*7c478bd9Sstevel@tonic-gate } 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate /* 1114*7c478bd9Sstevel@tonic-gate * start a special thread that will cleanup after aio requests 1115*7c478bd9Sstevel@tonic-gate * that are preventing a segment from being unmapped. as_unmap() 1116*7c478bd9Sstevel@tonic-gate * blocks until all phsyio to this segment is completed. this 1117*7c478bd9Sstevel@tonic-gate * doesn't happen until all the pages in this segment are not 1118*7c478bd9Sstevel@tonic-gate * SOFTLOCKed. Some pages will be SOFTLOCKed when there are aio 1119*7c478bd9Sstevel@tonic-gate * requests still outstanding. this special thread will make sure 1120*7c478bd9Sstevel@tonic-gate * that these SOFTLOCKed pages will eventually be SOFTUNLOCKed. 1121*7c478bd9Sstevel@tonic-gate * 1122*7c478bd9Sstevel@tonic-gate * this function will return an error if the process has only 1123*7c478bd9Sstevel@tonic-gate * one LWP. the assumption is that the caller is a separate LWP 1124*7c478bd9Sstevel@tonic-gate * that remains blocked in the kernel for the life of this process. 1125*7c478bd9Sstevel@tonic-gate */ 1126*7c478bd9Sstevel@tonic-gate static int 1127*7c478bd9Sstevel@tonic-gate aiostart(void) 1128*7c478bd9Sstevel@tonic-gate { 1129*7c478bd9Sstevel@tonic-gate proc_t *p = curproc; 1130*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1131*7c478bd9Sstevel@tonic-gate int first, error = 0; 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate if (p->p_lwpcnt == 1) 1134*7c478bd9Sstevel@tonic-gate return (EDEADLK); 1135*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1136*7c478bd9Sstevel@tonic-gate if ((aiop = p->p_aio) == NULL) 1137*7c478bd9Sstevel@tonic-gate error = EINVAL; 1138*7c478bd9Sstevel@tonic-gate else { 1139*7c478bd9Sstevel@tonic-gate first = aiop->aio_ok; 1140*7c478bd9Sstevel@tonic-gate if (aiop->aio_ok == 0) 1141*7c478bd9Sstevel@tonic-gate aiop->aio_ok = 1; 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1144*7c478bd9Sstevel@tonic-gate if (error == 0 && first == 0) { 1145*7c478bd9Sstevel@tonic-gate return (aio_cleanup_thread(aiop)); 1146*7c478bd9Sstevel@tonic-gate /* should return only to exit */ 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate return (error); 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate /* 1152*7c478bd9Sstevel@tonic-gate * Associate an aiocb with a port. 1153*7c478bd9Sstevel@tonic-gate * This function is used by aiorw() to associate a transaction with a port. 1154*7c478bd9Sstevel@tonic-gate * Allocate an event port structure (port_alloc_event()) and store the 1155*7c478bd9Sstevel@tonic-gate * delivered user pointer (portnfy_user) in the portkev_user field of the 1156*7c478bd9Sstevel@tonic-gate * port_kevent_t structure.. 1157*7c478bd9Sstevel@tonic-gate * The aio_req_portkev pointer in the aio_req_t structure was added to identify 1158*7c478bd9Sstevel@tonic-gate * the port association. 1159*7c478bd9Sstevel@tonic-gate */ 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate static int 1162*7c478bd9Sstevel@tonic-gate aio_req_assoc_port_rw(port_notify_t *pntfy, aiocb_t *cbp, aio_req_t *reqp) 1163*7c478bd9Sstevel@tonic-gate { 1164*7c478bd9Sstevel@tonic-gate port_kevent_t *pkevp = NULL; 1165*7c478bd9Sstevel@tonic-gate int error; 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate error = port_alloc_event(pntfy->portnfy_port, PORT_ALLOC_DEFAULT, 1168*7c478bd9Sstevel@tonic-gate PORT_SOURCE_AIO, &pkevp); 1169*7c478bd9Sstevel@tonic-gate if (error) { 1170*7c478bd9Sstevel@tonic-gate if ((error == ENOMEM) || (error == EAGAIN)) 1171*7c478bd9Sstevel@tonic-gate error = EAGAIN; 1172*7c478bd9Sstevel@tonic-gate else 1173*7c478bd9Sstevel@tonic-gate error = EINVAL; 1174*7c478bd9Sstevel@tonic-gate } else { 1175*7c478bd9Sstevel@tonic-gate port_init_event(pkevp, (uintptr_t)cbp, pntfy->portnfy_user, 1176*7c478bd9Sstevel@tonic-gate aio_port_callback, reqp); 1177*7c478bd9Sstevel@tonic-gate reqp->aio_req_portkev = pkevp; 1178*7c478bd9Sstevel@tonic-gate reqp->aio_req_port = pntfy->portnfy_port; 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate return (error); 1181*7c478bd9Sstevel@tonic-gate } 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate /* 1184*7c478bd9Sstevel@tonic-gate * Associate an aiocb with a port. 1185*7c478bd9Sstevel@tonic-gate * This function is used by lio_listio() to associate a transaction with a port. 1186*7c478bd9Sstevel@tonic-gate * Allocate an event port structure (port_alloc_event()) and store the 1187*7c478bd9Sstevel@tonic-gate * delivered user pointer (portnfy_user) in the portkev_user field of the 1188*7c478bd9Sstevel@tonic-gate * The aio_req_portkev pointer in the aio_req_t structure was added to identify 1189*7c478bd9Sstevel@tonic-gate * the port association. 1190*7c478bd9Sstevel@tonic-gate * The event port notification can be requested attaching the port_notify_t 1191*7c478bd9Sstevel@tonic-gate * structure to the sigevent argument of lio_listio() or attaching the 1192*7c478bd9Sstevel@tonic-gate * port_notify_t structure to the sigevent structure which is embedded in the 1193*7c478bd9Sstevel@tonic-gate * aiocb. 1194*7c478bd9Sstevel@tonic-gate * The attachement to the global sigevent structure is valid for all aiocbs 1195*7c478bd9Sstevel@tonic-gate * in the list. 1196*7c478bd9Sstevel@tonic-gate */ 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate static int 1199*7c478bd9Sstevel@tonic-gate aio_req_assoc_port(struct sigevent *sigev, void *user, aiocb_t *cbp, 1200*7c478bd9Sstevel@tonic-gate aio_req_t *reqp, port_kevent_t *pkevtp) 1201*7c478bd9Sstevel@tonic-gate { 1202*7c478bd9Sstevel@tonic-gate port_kevent_t *pkevp = NULL; 1203*7c478bd9Sstevel@tonic-gate port_notify_t pntfy; 1204*7c478bd9Sstevel@tonic-gate int error; 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate if (sigev->sigev_notify == SIGEV_PORT) { 1207*7c478bd9Sstevel@tonic-gate /* aiocb has an own port notification embedded */ 1208*7c478bd9Sstevel@tonic-gate if (copyin((void *)sigev->sigev_value.sival_ptr, &pntfy, 1209*7c478bd9Sstevel@tonic-gate sizeof (port_notify_t))) 1210*7c478bd9Sstevel@tonic-gate return (EFAULT); 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate error = port_alloc_event(pntfy.portnfy_port, PORT_ALLOC_DEFAULT, 1213*7c478bd9Sstevel@tonic-gate PORT_SOURCE_AIO, &pkevp); 1214*7c478bd9Sstevel@tonic-gate if (error) { 1215*7c478bd9Sstevel@tonic-gate if ((error == ENOMEM) || (error == EAGAIN)) 1216*7c478bd9Sstevel@tonic-gate return (EAGAIN); 1217*7c478bd9Sstevel@tonic-gate else 1218*7c478bd9Sstevel@tonic-gate return (EINVAL); 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate /* use this values instead of the global values in port */ 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate port_init_event(pkevp, (uintptr_t)cbp, pntfy.portnfy_user, 1223*7c478bd9Sstevel@tonic-gate aio_port_callback, reqp); 1224*7c478bd9Sstevel@tonic-gate reqp->aio_req_port = pntfy.portnfy_port; 1225*7c478bd9Sstevel@tonic-gate } else { 1226*7c478bd9Sstevel@tonic-gate /* use global port notification */ 1227*7c478bd9Sstevel@tonic-gate error = port_dup_event(pkevtp, &pkevp, PORT_ALLOC_DEFAULT); 1228*7c478bd9Sstevel@tonic-gate if (error) 1229*7c478bd9Sstevel@tonic-gate return (EAGAIN); 1230*7c478bd9Sstevel@tonic-gate port_init_event(pkevp, (uintptr_t)cbp, user, aio_port_callback, 1231*7c478bd9Sstevel@tonic-gate reqp); 1232*7c478bd9Sstevel@tonic-gate } 1233*7c478bd9Sstevel@tonic-gate reqp->aio_req_portkev = pkevp; 1234*7c478bd9Sstevel@tonic-gate return (0); 1235*7c478bd9Sstevel@tonic-gate } 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate /* 1238*7c478bd9Sstevel@tonic-gate * Same comments as in aio_req_assoc_port(), see above. 1239*7c478bd9Sstevel@tonic-gate */ 1240*7c478bd9Sstevel@tonic-gate 1241*7c478bd9Sstevel@tonic-gate static int 1242*7c478bd9Sstevel@tonic-gate aio_req_assoc_port32(struct sigevent32 *sigev, void *user, aiocb_t *cbp, 1243*7c478bd9Sstevel@tonic-gate aio_req_t *reqp, port_kevent_t *pkevtp) 1244*7c478bd9Sstevel@tonic-gate { 1245*7c478bd9Sstevel@tonic-gate port_kevent_t *pkevp = NULL; 1246*7c478bd9Sstevel@tonic-gate port_notify32_t pntfy; 1247*7c478bd9Sstevel@tonic-gate int error; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate if (sigev->sigev_notify == SIGEV_PORT) { 1250*7c478bd9Sstevel@tonic-gate if (copyin((void *)(uintptr_t)sigev->sigev_value.sival_int, 1251*7c478bd9Sstevel@tonic-gate &pntfy, sizeof (port_notify32_t))) 1252*7c478bd9Sstevel@tonic-gate return (EFAULT); 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate error = port_alloc_event(pntfy.portnfy_port, 1255*7c478bd9Sstevel@tonic-gate PORT_ALLOC_DEFAULT, PORT_SOURCE_AIO, &pkevp); 1256*7c478bd9Sstevel@tonic-gate if (error) { 1257*7c478bd9Sstevel@tonic-gate if ((error == ENOMEM) || (error == EAGAIN)) 1258*7c478bd9Sstevel@tonic-gate return (EAGAIN); 1259*7c478bd9Sstevel@tonic-gate else 1260*7c478bd9Sstevel@tonic-gate return (EINVAL); 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate /* use this values instead of the global values in port */ 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate port_init_event(pkevp, (uintptr_t)cbp, 1265*7c478bd9Sstevel@tonic-gate (void *)(uintptr_t)pntfy.portnfy_user, 1266*7c478bd9Sstevel@tonic-gate aio_port_callback, reqp); 1267*7c478bd9Sstevel@tonic-gate reqp->aio_req_port = pntfy.portnfy_port; 1268*7c478bd9Sstevel@tonic-gate } else { 1269*7c478bd9Sstevel@tonic-gate error = port_dup_event(pkevtp, &pkevp, PORT_ALLOC_DEFAULT); 1270*7c478bd9Sstevel@tonic-gate if (error) 1271*7c478bd9Sstevel@tonic-gate return (EAGAIN); 1272*7c478bd9Sstevel@tonic-gate port_init_event(pkevp, (uintptr_t)cbp, user, aio_port_callback, 1273*7c478bd9Sstevel@tonic-gate reqp); 1274*7c478bd9Sstevel@tonic-gate } 1275*7c478bd9Sstevel@tonic-gate reqp->aio_req_portkev = pkevp; 1276*7c478bd9Sstevel@tonic-gate return (0); 1277*7c478bd9Sstevel@tonic-gate } 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate #ifdef _LP64 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate /* 1283*7c478bd9Sstevel@tonic-gate * Asynchronous list IO. A chain of aiocb's are copied in 1284*7c478bd9Sstevel@tonic-gate * one at a time. If the aiocb is invalid, it is skipped. 1285*7c478bd9Sstevel@tonic-gate * For each aiocb, the appropriate driver entry point is 1286*7c478bd9Sstevel@tonic-gate * called. Optimize for the common case where the list 1287*7c478bd9Sstevel@tonic-gate * of requests is to the same file descriptor. 1288*7c478bd9Sstevel@tonic-gate * 1289*7c478bd9Sstevel@tonic-gate * One possible optimization is to define a new driver entry 1290*7c478bd9Sstevel@tonic-gate * point that supports a list of IO requests. Whether this 1291*7c478bd9Sstevel@tonic-gate * improves performance depends somewhat on the driver's 1292*7c478bd9Sstevel@tonic-gate * locking strategy. Processing a list could adversely impact 1293*7c478bd9Sstevel@tonic-gate * the driver's interrupt latency. 1294*7c478bd9Sstevel@tonic-gate */ 1295*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1296*7c478bd9Sstevel@tonic-gate static int 1297*7c478bd9Sstevel@tonic-gate alio( 1298*7c478bd9Sstevel@tonic-gate int opcode, 1299*7c478bd9Sstevel@tonic-gate int mode_arg, 1300*7c478bd9Sstevel@tonic-gate aiocb_t **aiocb_arg, 1301*7c478bd9Sstevel@tonic-gate int nent, 1302*7c478bd9Sstevel@tonic-gate struct sigevent *sigev) 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate { 1305*7c478bd9Sstevel@tonic-gate file_t *fp; 1306*7c478bd9Sstevel@tonic-gate file_t *prev_fp = NULL; 1307*7c478bd9Sstevel@tonic-gate int prev_mode = -1; 1308*7c478bd9Sstevel@tonic-gate struct vnode *vp; 1309*7c478bd9Sstevel@tonic-gate aio_lio_t *head; 1310*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 1311*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1312*7c478bd9Sstevel@tonic-gate caddr_t cbplist; 1313*7c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp; 1314*7c478bd9Sstevel@tonic-gate aiocb_t cb; 1315*7c478bd9Sstevel@tonic-gate aiocb_t *aiocb = &cb; 1316*7c478bd9Sstevel@tonic-gate struct sigevent sigevk; 1317*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 1318*7c478bd9Sstevel@tonic-gate int (*aio_func)(); 1319*7c478bd9Sstevel@tonic-gate int mode; 1320*7c478bd9Sstevel@tonic-gate int error = 0; 1321*7c478bd9Sstevel@tonic-gate int aio_errors = 0; 1322*7c478bd9Sstevel@tonic-gate int i; 1323*7c478bd9Sstevel@tonic-gate size_t ssize; 1324*7c478bd9Sstevel@tonic-gate int deadhead = 0; 1325*7c478bd9Sstevel@tonic-gate int aio_notsupported = 0; 1326*7c478bd9Sstevel@tonic-gate int aio_use_port = 0; 1327*7c478bd9Sstevel@tonic-gate port_kevent_t *pkevtp = NULL; 1328*7c478bd9Sstevel@tonic-gate port_notify_t pnotify; 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 1331*7c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX) 1332*7c478bd9Sstevel@tonic-gate return (EINVAL); 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent); 1335*7c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP); 1336*7c478bd9Sstevel@tonic-gate ucbp = (aiocb_t **)cbplist; 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, cbplist, sizeof (aiocb_t *) * nent)) { 1339*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1340*7c478bd9Sstevel@tonic-gate return (EFAULT); 1341*7c478bd9Sstevel@tonic-gate } 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate if (sigev) { 1344*7c478bd9Sstevel@tonic-gate if (copyin(sigev, &sigevk, sizeof (struct sigevent))) { 1345*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1346*7c478bd9Sstevel@tonic-gate return (EFAULT); 1347*7c478bd9Sstevel@tonic-gate } 1348*7c478bd9Sstevel@tonic-gate } 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate /* 1351*7c478bd9Sstevel@tonic-gate * a list head should be allocated if notification is 1352*7c478bd9Sstevel@tonic-gate * enabled for this list. 1353*7c478bd9Sstevel@tonic-gate */ 1354*7c478bd9Sstevel@tonic-gate head = NULL; 1355*7c478bd9Sstevel@tonic-gate 1356*7c478bd9Sstevel@tonic-gate /* Event Ports */ 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate if (sigev && sigevk.sigev_notify == SIGEV_PORT) { 1359*7c478bd9Sstevel@tonic-gate /* Use port for completion notification */ 1360*7c478bd9Sstevel@tonic-gate if (copyin(sigevk.sigev_value.sival_ptr, &pnotify, 1361*7c478bd9Sstevel@tonic-gate sizeof (port_notify_t))) { 1362*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1363*7c478bd9Sstevel@tonic-gate return (EFAULT); 1364*7c478bd9Sstevel@tonic-gate } 1365*7c478bd9Sstevel@tonic-gate /* use event ports for the list of aiocbs */ 1366*7c478bd9Sstevel@tonic-gate aio_use_port = 1; 1367*7c478bd9Sstevel@tonic-gate error = port_alloc_event(pnotify.portnfy_port, 1368*7c478bd9Sstevel@tonic-gate PORT_ALLOC_PRIVATE, PORT_SOURCE_AIO, &pkevtp); 1369*7c478bd9Sstevel@tonic-gate if (error) { 1370*7c478bd9Sstevel@tonic-gate if ((error == ENOMEM) || (error == EAGAIN)) 1371*7c478bd9Sstevel@tonic-gate error = EAGAIN; 1372*7c478bd9Sstevel@tonic-gate else 1373*7c478bd9Sstevel@tonic-gate error = EINVAL; 1374*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1375*7c478bd9Sstevel@tonic-gate return (error); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate } else if ((mode_arg == LIO_WAIT) || sigev) { 1378*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1379*7c478bd9Sstevel@tonic-gate error = aio_lio_alloc(&head); 1380*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1381*7c478bd9Sstevel@tonic-gate if (error) 1382*7c478bd9Sstevel@tonic-gate goto done; 1383*7c478bd9Sstevel@tonic-gate deadhead = 1; 1384*7c478bd9Sstevel@tonic-gate head->lio_nent = nent; 1385*7c478bd9Sstevel@tonic-gate head->lio_refcnt = nent; 1386*7c478bd9Sstevel@tonic-gate if (sigev && (sigevk.sigev_notify == SIGEV_SIGNAL) && 1387*7c478bd9Sstevel@tonic-gate (sigevk.sigev_signo > 0 && sigevk.sigev_signo < NSIG)) { 1388*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP); 1389*7c478bd9Sstevel@tonic-gate if (sqp == NULL) { 1390*7c478bd9Sstevel@tonic-gate error = EAGAIN; 1391*7c478bd9Sstevel@tonic-gate goto done; 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate sqp->sq_func = NULL; 1394*7c478bd9Sstevel@tonic-gate sqp->sq_next = NULL; 1395*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO; 1396*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid; 1397*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc); 1398*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 1399*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred); 1400*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigevk.sigev_signo; 1401*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_value = sigevk.sigev_value; 1402*7c478bd9Sstevel@tonic-gate head->lio_sigqp = sqp; 1403*7c478bd9Sstevel@tonic-gate } else { 1404*7c478bd9Sstevel@tonic-gate head->lio_sigqp = NULL; 1405*7c478bd9Sstevel@tonic-gate } 1406*7c478bd9Sstevel@tonic-gate } 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++, ucbp++) { 1409*7c478bd9Sstevel@tonic-gate 1410*7c478bd9Sstevel@tonic-gate cbp = *ucbp; 1411*7c478bd9Sstevel@tonic-gate /* skip entry if it can't be copied. */ 1412*7c478bd9Sstevel@tonic-gate if (cbp == NULL || copyin(cbp, aiocb, sizeof (aiocb_t))) { 1413*7c478bd9Sstevel@tonic-gate if (head) { 1414*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1415*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1416*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1417*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1418*7c478bd9Sstevel@tonic-gate } 1419*7c478bd9Sstevel@tonic-gate continue; 1420*7c478bd9Sstevel@tonic-gate } 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate /* skip if opcode for aiocb is LIO_NOP */ 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode; 1425*7c478bd9Sstevel@tonic-gate if (mode == LIO_NOP) { 1426*7c478bd9Sstevel@tonic-gate cbp = NULL; 1427*7c478bd9Sstevel@tonic-gate if (head) { 1428*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1429*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1430*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1431*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate continue; 1434*7c478bd9Sstevel@tonic-gate } 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate /* increment file descriptor's ref count. */ 1437*7c478bd9Sstevel@tonic-gate if ((fp = getf(aiocb->aio_fildes)) == NULL) { 1438*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF); 1439*7c478bd9Sstevel@tonic-gate if (head) { 1440*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1441*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1442*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1443*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1444*7c478bd9Sstevel@tonic-gate } 1445*7c478bd9Sstevel@tonic-gate aio_errors++; 1446*7c478bd9Sstevel@tonic-gate continue; 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate vp = fp->f_vnode; 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate /* 1452*7c478bd9Sstevel@tonic-gate * check the permission of the partition 1453*7c478bd9Sstevel@tonic-gate */ 1454*7c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode; 1455*7c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) { 1456*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 1457*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF); 1458*7c478bd9Sstevel@tonic-gate if (head) { 1459*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1460*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1461*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1462*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1463*7c478bd9Sstevel@tonic-gate } 1464*7c478bd9Sstevel@tonic-gate aio_errors++; 1465*7c478bd9Sstevel@tonic-gate continue; 1466*7c478bd9Sstevel@tonic-gate } 1467*7c478bd9Sstevel@tonic-gate 1468*7c478bd9Sstevel@tonic-gate /* 1469*7c478bd9Sstevel@tonic-gate * common case where requests are to the same fd for the 1470*7c478bd9Sstevel@tonic-gate * same r/w operation. 1471*7c478bd9Sstevel@tonic-gate * for UFS, need to set EBADFD 1472*7c478bd9Sstevel@tonic-gate */ 1473*7c478bd9Sstevel@tonic-gate if ((fp != prev_fp) || (mode != prev_mode)) { 1474*7c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode); 1475*7c478bd9Sstevel@tonic-gate if (aio_func == NULL) { 1476*7c478bd9Sstevel@tonic-gate prev_fp = NULL; 1477*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 1478*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADFD); 1479*7c478bd9Sstevel@tonic-gate aio_notsupported++; 1480*7c478bd9Sstevel@tonic-gate if (head) { 1481*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1482*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1483*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1484*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate continue; 1487*7c478bd9Sstevel@tonic-gate } else { 1488*7c478bd9Sstevel@tonic-gate prev_fp = fp; 1489*7c478bd9Sstevel@tonic-gate prev_mode = mode; 1490*7c478bd9Sstevel@tonic-gate } 1491*7c478bd9Sstevel@tonic-gate } 1492*7c478bd9Sstevel@tonic-gate 1493*7c478bd9Sstevel@tonic-gate if (error = aio_req_setup(&reqp, aiop, aiocb, 1494*7c478bd9Sstevel@tonic-gate &cbp->aio_resultp, aio_use_port, vp)) { 1495*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 1496*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error); 1497*7c478bd9Sstevel@tonic-gate if (head) { 1498*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1499*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1500*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1501*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate aio_errors++; 1504*7c478bd9Sstevel@tonic-gate continue; 1505*7c478bd9Sstevel@tonic-gate } 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate reqp->aio_req_lio = head; 1508*7c478bd9Sstevel@tonic-gate deadhead = 0; 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate /* 1511*7c478bd9Sstevel@tonic-gate * Set the errno field now before sending the request to 1512*7c478bd9Sstevel@tonic-gate * the driver to avoid a race condition 1513*7c478bd9Sstevel@tonic-gate */ 1514*7c478bd9Sstevel@tonic-gate (void) suword32(&cbp->aio_resultp.aio_errno, 1515*7c478bd9Sstevel@tonic-gate EINPROGRESS); 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = (caddr_t)cbp; 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate if (aio_use_port) { 1520*7c478bd9Sstevel@tonic-gate reqp->aio_req_port = pnotify.portnfy_port; 1521*7c478bd9Sstevel@tonic-gate error = aio_req_assoc_port(&aiocb->aio_sigevent, 1522*7c478bd9Sstevel@tonic-gate pnotify.portnfy_user, cbp, reqp, pkevtp); 1523*7c478bd9Sstevel@tonic-gate } 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate /* 1526*7c478bd9Sstevel@tonic-gate * send the request to driver. 1527*7c478bd9Sstevel@tonic-gate * Clustering: If PXFS vnode, call PXFS function. 1528*7c478bd9Sstevel@tonic-gate */ 1529*7c478bd9Sstevel@tonic-gate if (error == 0) { 1530*7c478bd9Sstevel@tonic-gate if (aiocb->aio_nbytes == 0) { 1531*7c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes); 1532*7c478bd9Sstevel@tonic-gate aio_zerolen(reqp); 1533*7c478bd9Sstevel@tonic-gate continue; 1534*7c478bd9Sstevel@tonic-gate } 1535*7c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, 1536*7c478bd9Sstevel@tonic-gate CRED()); 1537*7c478bd9Sstevel@tonic-gate } 1538*7c478bd9Sstevel@tonic-gate /* 1539*7c478bd9Sstevel@tonic-gate * the fd's ref count is not decremented until the IO has 1540*7c478bd9Sstevel@tonic-gate * completed unless there was an error. 1541*7c478bd9Sstevel@tonic-gate */ 1542*7c478bd9Sstevel@tonic-gate if (error) { 1543*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 1544*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error); 1545*7c478bd9Sstevel@tonic-gate if (head) { 1546*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1547*7c478bd9Sstevel@tonic-gate head->lio_nent--; 1548*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 1549*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1550*7c478bd9Sstevel@tonic-gate } 1551*7c478bd9Sstevel@tonic-gate if (error == ENOTSUP) 1552*7c478bd9Sstevel@tonic-gate aio_notsupported++; 1553*7c478bd9Sstevel@tonic-gate else 1554*7c478bd9Sstevel@tonic-gate aio_errors++; 1555*7c478bd9Sstevel@tonic-gate lio_set_error(reqp); 1556*7c478bd9Sstevel@tonic-gate } else { 1557*7c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes); 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate } 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate if (pkevtp) 1562*7c478bd9Sstevel@tonic-gate port_free_event(pkevtp); 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate if (aio_notsupported) { 1565*7c478bd9Sstevel@tonic-gate error = ENOTSUP; 1566*7c478bd9Sstevel@tonic-gate } else if (aio_errors) { 1567*7c478bd9Sstevel@tonic-gate /* 1568*7c478bd9Sstevel@tonic-gate * return EIO if any request failed 1569*7c478bd9Sstevel@tonic-gate */ 1570*7c478bd9Sstevel@tonic-gate error = EIO; 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate if (mode_arg == LIO_WAIT) { 1574*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1575*7c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) { 1576*7c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) { 1577*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1578*7c478bd9Sstevel@tonic-gate error = EINTR; 1579*7c478bd9Sstevel@tonic-gate goto done; 1580*7c478bd9Sstevel@tonic-gate } 1581*7c478bd9Sstevel@tonic-gate } 1582*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1583*7c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, AIO_64); 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate done: 1587*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1588*7c478bd9Sstevel@tonic-gate if (deadhead) { 1589*7c478bd9Sstevel@tonic-gate if (head->lio_sigqp) 1590*7c478bd9Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t)); 1591*7c478bd9Sstevel@tonic-gate kmem_free(head, sizeof (aio_lio_t)); 1592*7c478bd9Sstevel@tonic-gate } 1593*7c478bd9Sstevel@tonic-gate return (error); 1594*7c478bd9Sstevel@tonic-gate } 1595*7c478bd9Sstevel@tonic-gate 1596*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 1597*7c478bd9Sstevel@tonic-gate 1598*7c478bd9Sstevel@tonic-gate /* 1599*7c478bd9Sstevel@tonic-gate * Asynchronous list IO. 1600*7c478bd9Sstevel@tonic-gate * If list I/O is called with LIO_WAIT it can still return 1601*7c478bd9Sstevel@tonic-gate * before all the I/O's are completed if a signal is caught 1602*7c478bd9Sstevel@tonic-gate * or if the list include UFS I/O requests. If this happens, 1603*7c478bd9Sstevel@tonic-gate * libaio will call aliowait() to wait for the I/O's to 1604*7c478bd9Sstevel@tonic-gate * complete 1605*7c478bd9Sstevel@tonic-gate */ 1606*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1607*7c478bd9Sstevel@tonic-gate static int 1608*7c478bd9Sstevel@tonic-gate aliowait( 1609*7c478bd9Sstevel@tonic-gate int mode, 1610*7c478bd9Sstevel@tonic-gate void *aiocb, 1611*7c478bd9Sstevel@tonic-gate int nent, 1612*7c478bd9Sstevel@tonic-gate void *sigev, 1613*7c478bd9Sstevel@tonic-gate int run_mode) 1614*7c478bd9Sstevel@tonic-gate { 1615*7c478bd9Sstevel@tonic-gate aio_lio_t *head; 1616*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1617*7c478bd9Sstevel@tonic-gate caddr_t cbplist; 1618*7c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp; 1619*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1620*7c478bd9Sstevel@tonic-gate aiocb32_t *cbp32; 1621*7c478bd9Sstevel@tonic-gate caddr32_t *ucbp32; 1622*7c478bd9Sstevel@tonic-gate aiocb64_32_t *cbp64; 1623*7c478bd9Sstevel@tonic-gate #endif 1624*7c478bd9Sstevel@tonic-gate int error = 0; 1625*7c478bd9Sstevel@tonic-gate int i; 1626*7c478bd9Sstevel@tonic-gate size_t ssize = 0; 1627*7c478bd9Sstevel@tonic-gate model_t model = get_udatamodel(); 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 1630*7c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX) 1631*7c478bd9Sstevel@tonic-gate return (EINVAL); 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 1634*7c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent); 1635*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1636*7c478bd9Sstevel@tonic-gate else 1637*7c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent); 1638*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate if (ssize == 0) 1641*7c478bd9Sstevel@tonic-gate return (EINVAL); 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP); 1644*7c478bd9Sstevel@tonic-gate 1645*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 1646*7c478bd9Sstevel@tonic-gate ucbp = (aiocb_t **)cbplist; 1647*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1648*7c478bd9Sstevel@tonic-gate else 1649*7c478bd9Sstevel@tonic-gate ucbp32 = (caddr32_t *)cbplist; 1650*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate if (copyin(aiocb, cbplist, ssize)) { 1653*7c478bd9Sstevel@tonic-gate error = EFAULT; 1654*7c478bd9Sstevel@tonic-gate goto done; 1655*7c478bd9Sstevel@tonic-gate } 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate /* 1658*7c478bd9Sstevel@tonic-gate * To find the list head, we go through the 1659*7c478bd9Sstevel@tonic-gate * list of aiocb structs, find the request 1660*7c478bd9Sstevel@tonic-gate * its for, then get the list head that reqp 1661*7c478bd9Sstevel@tonic-gate * points to 1662*7c478bd9Sstevel@tonic-gate */ 1663*7c478bd9Sstevel@tonic-gate head = NULL; 1664*7c478bd9Sstevel@tonic-gate 1665*7c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++) { 1666*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) { 1667*7c478bd9Sstevel@tonic-gate /* 1668*7c478bd9Sstevel@tonic-gate * Since we are only checking for a NULL pointer 1669*7c478bd9Sstevel@tonic-gate * Following should work on both native data sizes 1670*7c478bd9Sstevel@tonic-gate * as well as for largefile aiocb. 1671*7c478bd9Sstevel@tonic-gate */ 1672*7c478bd9Sstevel@tonic-gate if ((cbp = *ucbp++) == NULL) 1673*7c478bd9Sstevel@tonic-gate continue; 1674*7c478bd9Sstevel@tonic-gate if (run_mode != AIO_LARGEFILE) 1675*7c478bd9Sstevel@tonic-gate if (head = aio_list_get(&cbp->aio_resultp)) 1676*7c478bd9Sstevel@tonic-gate break; 1677*7c478bd9Sstevel@tonic-gate else { 1678*7c478bd9Sstevel@tonic-gate /* 1679*7c478bd9Sstevel@tonic-gate * This is a case when largefile call is 1680*7c478bd9Sstevel@tonic-gate * made on 32 bit kernel. 1681*7c478bd9Sstevel@tonic-gate * Treat each pointer as pointer to 1682*7c478bd9Sstevel@tonic-gate * aiocb64_32 1683*7c478bd9Sstevel@tonic-gate */ 1684*7c478bd9Sstevel@tonic-gate if (head = aio_list_get((aio_result_t *) 1685*7c478bd9Sstevel@tonic-gate &(((aiocb64_32_t *)cbp)->aio_resultp))) 1686*7c478bd9Sstevel@tonic-gate break; 1687*7c478bd9Sstevel@tonic-gate } 1688*7c478bd9Sstevel@tonic-gate } 1689*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1690*7c478bd9Sstevel@tonic-gate else { 1691*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) { 1692*7c478bd9Sstevel@tonic-gate if ((cbp64 = (aiocb64_32_t *) 1693*7c478bd9Sstevel@tonic-gate (uintptr_t)*ucbp32++) == NULL) 1694*7c478bd9Sstevel@tonic-gate continue; 1695*7c478bd9Sstevel@tonic-gate if (head = aio_list_get((aio_result_t *) 1696*7c478bd9Sstevel@tonic-gate &cbp64->aio_resultp)) 1697*7c478bd9Sstevel@tonic-gate break; 1698*7c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_32) { 1699*7c478bd9Sstevel@tonic-gate if ((cbp32 = (aiocb32_t *) 1700*7c478bd9Sstevel@tonic-gate (uintptr_t)*ucbp32++) == NULL) 1701*7c478bd9Sstevel@tonic-gate continue; 1702*7c478bd9Sstevel@tonic-gate if (head = aio_list_get((aio_result_t *) 1703*7c478bd9Sstevel@tonic-gate &cbp32->aio_resultp)) 1704*7c478bd9Sstevel@tonic-gate break; 1705*7c478bd9Sstevel@tonic-gate } 1706*7c478bd9Sstevel@tonic-gate } 1707*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1708*7c478bd9Sstevel@tonic-gate } 1709*7c478bd9Sstevel@tonic-gate 1710*7c478bd9Sstevel@tonic-gate if (head == NULL) { 1711*7c478bd9Sstevel@tonic-gate error = EINVAL; 1712*7c478bd9Sstevel@tonic-gate goto done; 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate 1715*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1716*7c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) { 1717*7c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) { 1718*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1719*7c478bd9Sstevel@tonic-gate error = EINTR; 1720*7c478bd9Sstevel@tonic-gate goto done; 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate } 1723*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1724*7c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, run_mode); 1725*7c478bd9Sstevel@tonic-gate done: 1726*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 1727*7c478bd9Sstevel@tonic-gate return (error); 1728*7c478bd9Sstevel@tonic-gate } 1729*7c478bd9Sstevel@tonic-gate 1730*7c478bd9Sstevel@tonic-gate aio_lio_t * 1731*7c478bd9Sstevel@tonic-gate aio_list_get(aio_result_t *resultp) 1732*7c478bd9Sstevel@tonic-gate { 1733*7c478bd9Sstevel@tonic-gate aio_lio_t *head = NULL; 1734*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1735*7c478bd9Sstevel@tonic-gate aio_req_t **bucket; 1736*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 1737*7c478bd9Sstevel@tonic-gate long index; 1738*7c478bd9Sstevel@tonic-gate 1739*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 1740*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 1741*7c478bd9Sstevel@tonic-gate return (NULL); 1742*7c478bd9Sstevel@tonic-gate 1743*7c478bd9Sstevel@tonic-gate if (resultp) { 1744*7c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp); 1745*7c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index]; 1746*7c478bd9Sstevel@tonic-gate for (reqp = *bucket; reqp != NULL; 1747*7c478bd9Sstevel@tonic-gate reqp = reqp->aio_hash_next) { 1748*7c478bd9Sstevel@tonic-gate if (reqp->aio_req_resultp == resultp) { 1749*7c478bd9Sstevel@tonic-gate head = reqp->aio_req_lio; 1750*7c478bd9Sstevel@tonic-gate return (head); 1751*7c478bd9Sstevel@tonic-gate } 1752*7c478bd9Sstevel@tonic-gate } 1753*7c478bd9Sstevel@tonic-gate } 1754*7c478bd9Sstevel@tonic-gate return (NULL); 1755*7c478bd9Sstevel@tonic-gate } 1756*7c478bd9Sstevel@tonic-gate 1757*7c478bd9Sstevel@tonic-gate 1758*7c478bd9Sstevel@tonic-gate static void 1759*7c478bd9Sstevel@tonic-gate lio_set_uerror(void *resultp, int error) 1760*7c478bd9Sstevel@tonic-gate { 1761*7c478bd9Sstevel@tonic-gate /* 1762*7c478bd9Sstevel@tonic-gate * the resultp field is a pointer to where the 1763*7c478bd9Sstevel@tonic-gate * error should be written out to the user's 1764*7c478bd9Sstevel@tonic-gate * aiocb. 1765*7c478bd9Sstevel@tonic-gate * 1766*7c478bd9Sstevel@tonic-gate */ 1767*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 1768*7c478bd9Sstevel@tonic-gate (void) sulword(&((aio_result_t *)resultp)->aio_return, 1769*7c478bd9Sstevel@tonic-gate (ssize_t)-1); 1770*7c478bd9Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_errno, error); 1771*7c478bd9Sstevel@tonic-gate } 1772*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1773*7c478bd9Sstevel@tonic-gate else { 1774*7c478bd9Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_return, 1775*7c478bd9Sstevel@tonic-gate (uint_t)-1); 1776*7c478bd9Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_errno, error); 1777*7c478bd9Sstevel@tonic-gate } 1778*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate /* 1782*7c478bd9Sstevel@tonic-gate * do cleanup completion for all requests in list. memory for 1783*7c478bd9Sstevel@tonic-gate * each request is also freed. 1784*7c478bd9Sstevel@tonic-gate */ 1785*7c478bd9Sstevel@tonic-gate static void 1786*7c478bd9Sstevel@tonic-gate alio_cleanup(aio_t *aiop, aiocb_t **cbp, int nent, int run_mode) 1787*7c478bd9Sstevel@tonic-gate { 1788*7c478bd9Sstevel@tonic-gate int i; 1789*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 1790*7c478bd9Sstevel@tonic-gate aio_result_t *resultp; 1791*7c478bd9Sstevel@tonic-gate aiocb64_32_t *aiocb_64; 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++) { 1794*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 1795*7c478bd9Sstevel@tonic-gate if (cbp[i] == NULL) 1796*7c478bd9Sstevel@tonic-gate continue; 1797*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) { 1798*7c478bd9Sstevel@tonic-gate aiocb_64 = (aiocb64_32_t *)cbp[i]; 1799*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&aiocb_64-> 1800*7c478bd9Sstevel@tonic-gate aio_resultp; 1801*7c478bd9Sstevel@tonic-gate } else 1802*7c478bd9Sstevel@tonic-gate resultp = &cbp[i]->aio_resultp; 1803*7c478bd9Sstevel@tonic-gate } 1804*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1805*7c478bd9Sstevel@tonic-gate else { 1806*7c478bd9Sstevel@tonic-gate aiocb32_t *aiocb_32; 1807*7c478bd9Sstevel@tonic-gate caddr32_t *cbp32; 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate cbp32 = (caddr32_t *)cbp; 1810*7c478bd9Sstevel@tonic-gate if (cbp32[i] == NULL) 1811*7c478bd9Sstevel@tonic-gate continue; 1812*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_32) { 1813*7c478bd9Sstevel@tonic-gate aiocb_32 = (aiocb32_t *)(uintptr_t)cbp32[i]; 1814*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&aiocb_32-> 1815*7c478bd9Sstevel@tonic-gate aio_resultp; 1816*7c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_LARGEFILE) { 1817*7c478bd9Sstevel@tonic-gate aiocb_64 = (aiocb64_32_t *)(uintptr_t)cbp32[i]; 1818*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&aiocb_64-> 1819*7c478bd9Sstevel@tonic-gate aio_resultp; 1820*7c478bd9Sstevel@tonic-gate } 1821*7c478bd9Sstevel@tonic-gate } 1822*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1823*7c478bd9Sstevel@tonic-gate /* 1824*7c478bd9Sstevel@tonic-gate * we need to get the aio_cleanupq_mutex since we call 1825*7c478bd9Sstevel@tonic-gate * aio_req_done(). 1826*7c478bd9Sstevel@tonic-gate */ 1827*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex); 1828*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1829*7c478bd9Sstevel@tonic-gate reqp = aio_req_done(resultp); 1830*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1831*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 1832*7c478bd9Sstevel@tonic-gate if (reqp != NULL) { 1833*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); 1834*7c478bd9Sstevel@tonic-gate aio_copyout_result(reqp); 1835*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1836*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 1837*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1838*7c478bd9Sstevel@tonic-gate } 1839*7c478bd9Sstevel@tonic-gate } 1840*7c478bd9Sstevel@tonic-gate } 1841*7c478bd9Sstevel@tonic-gate 1842*7c478bd9Sstevel@tonic-gate /* 1843*7c478bd9Sstevel@tonic-gate * write out the results for an aio request that is 1844*7c478bd9Sstevel@tonic-gate * done. 1845*7c478bd9Sstevel@tonic-gate */ 1846*7c478bd9Sstevel@tonic-gate static int 1847*7c478bd9Sstevel@tonic-gate aioerror(void *cb, int run_mode) 1848*7c478bd9Sstevel@tonic-gate { 1849*7c478bd9Sstevel@tonic-gate aio_result_t *resultp; 1850*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1851*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 1852*7c478bd9Sstevel@tonic-gate int retval; 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 1855*7c478bd9Sstevel@tonic-gate if (aiop == NULL || cb == NULL) 1856*7c478bd9Sstevel@tonic-gate return (EINVAL); 1857*7c478bd9Sstevel@tonic-gate 1858*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 1859*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) 1860*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb)-> 1861*7c478bd9Sstevel@tonic-gate aio_resultp; 1862*7c478bd9Sstevel@tonic-gate else 1863*7c478bd9Sstevel@tonic-gate resultp = &((aiocb_t *)cb)->aio_resultp; 1864*7c478bd9Sstevel@tonic-gate } 1865*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1866*7c478bd9Sstevel@tonic-gate else { 1867*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) 1868*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb)-> 1869*7c478bd9Sstevel@tonic-gate aio_resultp; 1870*7c478bd9Sstevel@tonic-gate else if (run_mode == AIO_32) 1871*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb32_t *)cb)-> 1872*7c478bd9Sstevel@tonic-gate aio_resultp; 1873*7c478bd9Sstevel@tonic-gate } 1874*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1875*7c478bd9Sstevel@tonic-gate /* 1876*7c478bd9Sstevel@tonic-gate * we need to get the aio_cleanupq_mutex since we call 1877*7c478bd9Sstevel@tonic-gate * aio_req_find(). 1878*7c478bd9Sstevel@tonic-gate */ 1879*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex); 1880*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1881*7c478bd9Sstevel@tonic-gate retval = aio_req_find(resultp, &reqp); 1882*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1883*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 1884*7c478bd9Sstevel@tonic-gate if (retval == 0) { 1885*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); 1886*7c478bd9Sstevel@tonic-gate aio_copyout_result(reqp); 1887*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1888*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 1889*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1890*7c478bd9Sstevel@tonic-gate return (0); 1891*7c478bd9Sstevel@tonic-gate } else if (retval == 1) 1892*7c478bd9Sstevel@tonic-gate return (EINPROGRESS); 1893*7c478bd9Sstevel@tonic-gate else if (retval == 2) 1894*7c478bd9Sstevel@tonic-gate return (EINVAL); 1895*7c478bd9Sstevel@tonic-gate return (0); 1896*7c478bd9Sstevel@tonic-gate } 1897*7c478bd9Sstevel@tonic-gate 1898*7c478bd9Sstevel@tonic-gate /* 1899*7c478bd9Sstevel@tonic-gate * aio_cancel - if no requests outstanding, 1900*7c478bd9Sstevel@tonic-gate * return AIO_ALLDONE 1901*7c478bd9Sstevel@tonic-gate * else 1902*7c478bd9Sstevel@tonic-gate * return AIO_NOTCANCELED 1903*7c478bd9Sstevel@tonic-gate */ 1904*7c478bd9Sstevel@tonic-gate static int 1905*7c478bd9Sstevel@tonic-gate aio_cancel( 1906*7c478bd9Sstevel@tonic-gate int fildes, 1907*7c478bd9Sstevel@tonic-gate void *cb, 1908*7c478bd9Sstevel@tonic-gate long *rval, 1909*7c478bd9Sstevel@tonic-gate int run_mode) 1910*7c478bd9Sstevel@tonic-gate { 1911*7c478bd9Sstevel@tonic-gate aio_t *aiop; 1912*7c478bd9Sstevel@tonic-gate void *resultp; 1913*7c478bd9Sstevel@tonic-gate int index; 1914*7c478bd9Sstevel@tonic-gate aio_req_t **bucket; 1915*7c478bd9Sstevel@tonic-gate aio_req_t *ent; 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate 1918*7c478bd9Sstevel@tonic-gate /* 1919*7c478bd9Sstevel@tonic-gate * Verify valid file descriptor 1920*7c478bd9Sstevel@tonic-gate */ 1921*7c478bd9Sstevel@tonic-gate if ((getf(fildes)) == NULL) { 1922*7c478bd9Sstevel@tonic-gate return (EBADF); 1923*7c478bd9Sstevel@tonic-gate } 1924*7c478bd9Sstevel@tonic-gate releasef(fildes); 1925*7c478bd9Sstevel@tonic-gate 1926*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 1927*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 1928*7c478bd9Sstevel@tonic-gate return (EINVAL); 1929*7c478bd9Sstevel@tonic-gate 1930*7c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding == 0) { 1931*7c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE; 1932*7c478bd9Sstevel@tonic-gate return (0); 1933*7c478bd9Sstevel@tonic-gate } 1934*7c478bd9Sstevel@tonic-gate 1935*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 1936*7c478bd9Sstevel@tonic-gate if (cb != NULL) { 1937*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 1938*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) 1939*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb) 1940*7c478bd9Sstevel@tonic-gate ->aio_resultp; 1941*7c478bd9Sstevel@tonic-gate else 1942*7c478bd9Sstevel@tonic-gate resultp = &((aiocb_t *)cb)->aio_resultp; 1943*7c478bd9Sstevel@tonic-gate } 1944*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1945*7c478bd9Sstevel@tonic-gate else { 1946*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_LARGEFILE) 1947*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb64_32_t *)cb) 1948*7c478bd9Sstevel@tonic-gate ->aio_resultp; 1949*7c478bd9Sstevel@tonic-gate else if (run_mode == AIO_32) 1950*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&((aiocb32_t *)cb) 1951*7c478bd9Sstevel@tonic-gate ->aio_resultp; 1952*7c478bd9Sstevel@tonic-gate } 1953*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1954*7c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp); 1955*7c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index]; 1956*7c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) { 1957*7c478bd9Sstevel@tonic-gate if (ent->aio_req_resultp == resultp) { 1958*7c478bd9Sstevel@tonic-gate if ((ent->aio_req_flags & AIO_PENDING) == 0) { 1959*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1960*7c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE; 1961*7c478bd9Sstevel@tonic-gate return (0); 1962*7c478bd9Sstevel@tonic-gate } 1963*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1964*7c478bd9Sstevel@tonic-gate *rval = AIO_NOTCANCELED; 1965*7c478bd9Sstevel@tonic-gate return (0); 1966*7c478bd9Sstevel@tonic-gate } 1967*7c478bd9Sstevel@tonic-gate } 1968*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1969*7c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE; 1970*7c478bd9Sstevel@tonic-gate return (0); 1971*7c478bd9Sstevel@tonic-gate } 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate for (index = 0; index < AIO_HASHSZ; index++) { 1974*7c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index]; 1975*7c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) { 1976*7c478bd9Sstevel@tonic-gate if (ent->aio_req_fd == fildes) { 1977*7c478bd9Sstevel@tonic-gate if ((ent->aio_req_flags & AIO_PENDING) != 0) { 1978*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1979*7c478bd9Sstevel@tonic-gate *rval = AIO_NOTCANCELED; 1980*7c478bd9Sstevel@tonic-gate return (0); 1981*7c478bd9Sstevel@tonic-gate } 1982*7c478bd9Sstevel@tonic-gate } 1983*7c478bd9Sstevel@tonic-gate } 1984*7c478bd9Sstevel@tonic-gate } 1985*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 1986*7c478bd9Sstevel@tonic-gate *rval = AIO_ALLDONE; 1987*7c478bd9Sstevel@tonic-gate return (0); 1988*7c478bd9Sstevel@tonic-gate } 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate /* 1991*7c478bd9Sstevel@tonic-gate * solaris version of asynchronous read and write 1992*7c478bd9Sstevel@tonic-gate */ 1993*7c478bd9Sstevel@tonic-gate static int 1994*7c478bd9Sstevel@tonic-gate arw( 1995*7c478bd9Sstevel@tonic-gate int opcode, 1996*7c478bd9Sstevel@tonic-gate int fdes, 1997*7c478bd9Sstevel@tonic-gate char *bufp, 1998*7c478bd9Sstevel@tonic-gate int bufsize, 1999*7c478bd9Sstevel@tonic-gate offset_t offset, 2000*7c478bd9Sstevel@tonic-gate aio_result_t *resultp, 2001*7c478bd9Sstevel@tonic-gate int mode) 2002*7c478bd9Sstevel@tonic-gate { 2003*7c478bd9Sstevel@tonic-gate file_t *fp; 2004*7c478bd9Sstevel@tonic-gate int error; 2005*7c478bd9Sstevel@tonic-gate struct vnode *vp; 2006*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 2007*7c478bd9Sstevel@tonic-gate aio_t *aiop; 2008*7c478bd9Sstevel@tonic-gate int (*aio_func)(); 2009*7c478bd9Sstevel@tonic-gate #ifdef _LP64 2010*7c478bd9Sstevel@tonic-gate aiocb_t aiocb; 2011*7c478bd9Sstevel@tonic-gate #else 2012*7c478bd9Sstevel@tonic-gate aiocb64_32_t aiocb64; 2013*7c478bd9Sstevel@tonic-gate #endif 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 2016*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 2017*7c478bd9Sstevel@tonic-gate return (EINVAL); 2018*7c478bd9Sstevel@tonic-gate 2019*7c478bd9Sstevel@tonic-gate if ((fp = getf(fdes)) == NULL) { 2020*7c478bd9Sstevel@tonic-gate return (EBADF); 2021*7c478bd9Sstevel@tonic-gate } 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate /* 2024*7c478bd9Sstevel@tonic-gate * check the permission of the partition 2025*7c478bd9Sstevel@tonic-gate */ 2026*7c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) { 2027*7c478bd9Sstevel@tonic-gate releasef(fdes); 2028*7c478bd9Sstevel@tonic-gate return (EBADF); 2029*7c478bd9Sstevel@tonic-gate } 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate vp = fp->f_vnode; 2032*7c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode); 2033*7c478bd9Sstevel@tonic-gate if (aio_func == NULL) { 2034*7c478bd9Sstevel@tonic-gate releasef(fdes); 2035*7c478bd9Sstevel@tonic-gate return (EBADFD); 2036*7c478bd9Sstevel@tonic-gate } 2037*7c478bd9Sstevel@tonic-gate #ifdef _LP64 2038*7c478bd9Sstevel@tonic-gate aiocb.aio_fildes = fdes; 2039*7c478bd9Sstevel@tonic-gate aiocb.aio_buf = bufp; 2040*7c478bd9Sstevel@tonic-gate aiocb.aio_nbytes = bufsize; 2041*7c478bd9Sstevel@tonic-gate aiocb.aio_offset = offset; 2042*7c478bd9Sstevel@tonic-gate aiocb.aio_sigevent.sigev_notify = 0; 2043*7c478bd9Sstevel@tonic-gate error = aio_req_setup(&reqp, aiop, &aiocb, resultp, 0, vp); 2044*7c478bd9Sstevel@tonic-gate #else 2045*7c478bd9Sstevel@tonic-gate aiocb64.aio_fildes = fdes; 2046*7c478bd9Sstevel@tonic-gate aiocb64.aio_buf = (caddr32_t)bufp; 2047*7c478bd9Sstevel@tonic-gate aiocb64.aio_nbytes = bufsize; 2048*7c478bd9Sstevel@tonic-gate aiocb64.aio_offset = offset; 2049*7c478bd9Sstevel@tonic-gate aiocb64.aio_sigevent.sigev_notify = 0; 2050*7c478bd9Sstevel@tonic-gate error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, 0, vp); 2051*7c478bd9Sstevel@tonic-gate #endif 2052*7c478bd9Sstevel@tonic-gate if (error) { 2053*7c478bd9Sstevel@tonic-gate releasef(fdes); 2054*7c478bd9Sstevel@tonic-gate return (error); 2055*7c478bd9Sstevel@tonic-gate } 2056*7c478bd9Sstevel@tonic-gate 2057*7c478bd9Sstevel@tonic-gate /* 2058*7c478bd9Sstevel@tonic-gate * enable polling on this request if the opcode has 2059*7c478bd9Sstevel@tonic-gate * the AIO poll bit set 2060*7c478bd9Sstevel@tonic-gate */ 2061*7c478bd9Sstevel@tonic-gate if (opcode & AIO_POLL_BIT) 2062*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags |= AIO_POLL; 2063*7c478bd9Sstevel@tonic-gate 2064*7c478bd9Sstevel@tonic-gate if (bufsize == 0) { 2065*7c478bd9Sstevel@tonic-gate clear_active_fd(fdes); 2066*7c478bd9Sstevel@tonic-gate aio_zerolen(reqp); 2067*7c478bd9Sstevel@tonic-gate return (0); 2068*7c478bd9Sstevel@tonic-gate } 2069*7c478bd9Sstevel@tonic-gate /* 2070*7c478bd9Sstevel@tonic-gate * send the request to driver. 2071*7c478bd9Sstevel@tonic-gate * Clustering: If PXFS vnode, call PXFS function. 2072*7c478bd9Sstevel@tonic-gate */ 2073*7c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, CRED()); 2074*7c478bd9Sstevel@tonic-gate /* 2075*7c478bd9Sstevel@tonic-gate * the fd is stored in the aio_req_t by aio_req_setup(), and 2076*7c478bd9Sstevel@tonic-gate * is released by the aio_cleanup_thread() when the IO has 2077*7c478bd9Sstevel@tonic-gate * completed. 2078*7c478bd9Sstevel@tonic-gate */ 2079*7c478bd9Sstevel@tonic-gate if (error) { 2080*7c478bd9Sstevel@tonic-gate releasef(fdes); 2081*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2082*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 2083*7c478bd9Sstevel@tonic-gate aiop->aio_pending--; 2084*7c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) 2085*7c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv); 2086*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2087*7c478bd9Sstevel@tonic-gate return (error); 2088*7c478bd9Sstevel@tonic-gate } 2089*7c478bd9Sstevel@tonic-gate clear_active_fd(fdes); 2090*7c478bd9Sstevel@tonic-gate return (0); 2091*7c478bd9Sstevel@tonic-gate } 2092*7c478bd9Sstevel@tonic-gate 2093*7c478bd9Sstevel@tonic-gate /* 2094*7c478bd9Sstevel@tonic-gate * Take request out of the port pending queue ... 2095*7c478bd9Sstevel@tonic-gate */ 2096*7c478bd9Sstevel@tonic-gate 2097*7c478bd9Sstevel@tonic-gate void 2098*7c478bd9Sstevel@tonic-gate aio_deq_port_pending(aio_t *aiop, aio_req_t *reqp) 2099*7c478bd9Sstevel@tonic-gate { 2100*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 2101*7c478bd9Sstevel@tonic-gate if (reqp->aio_req_prev == NULL) 2102*7c478bd9Sstevel@tonic-gate /* first request */ 2103*7c478bd9Sstevel@tonic-gate aiop->aio_portpending = reqp->aio_req_next; 2104*7c478bd9Sstevel@tonic-gate else 2105*7c478bd9Sstevel@tonic-gate reqp->aio_req_prev->aio_req_next = reqp->aio_req_next; 2106*7c478bd9Sstevel@tonic-gate if (reqp->aio_req_next != NULL) 2107*7c478bd9Sstevel@tonic-gate reqp->aio_req_next->aio_req_prev = reqp->aio_req_prev; 2108*7c478bd9Sstevel@tonic-gate } 2109*7c478bd9Sstevel@tonic-gate 2110*7c478bd9Sstevel@tonic-gate /* 2111*7c478bd9Sstevel@tonic-gate * posix version of asynchronous read and write 2112*7c478bd9Sstevel@tonic-gate */ 2113*7c478bd9Sstevel@tonic-gate static int 2114*7c478bd9Sstevel@tonic-gate aiorw( 2115*7c478bd9Sstevel@tonic-gate int opcode, 2116*7c478bd9Sstevel@tonic-gate void *aiocb_arg, 2117*7c478bd9Sstevel@tonic-gate int mode, 2118*7c478bd9Sstevel@tonic-gate int run_mode) 2119*7c478bd9Sstevel@tonic-gate { 2120*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 2121*7c478bd9Sstevel@tonic-gate aiocb32_t aiocb32; 2122*7c478bd9Sstevel@tonic-gate struct sigevent32 *sigev32; 2123*7c478bd9Sstevel@tonic-gate port_notify32_t pntfy32; 2124*7c478bd9Sstevel@tonic-gate #endif 2125*7c478bd9Sstevel@tonic-gate aiocb64_32_t aiocb64; 2126*7c478bd9Sstevel@tonic-gate aiocb_t aiocb; 2127*7c478bd9Sstevel@tonic-gate file_t *fp; 2128*7c478bd9Sstevel@tonic-gate int error, fd; 2129*7c478bd9Sstevel@tonic-gate size_t bufsize; 2130*7c478bd9Sstevel@tonic-gate struct vnode *vp; 2131*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 2132*7c478bd9Sstevel@tonic-gate aio_t *aiop; 2133*7c478bd9Sstevel@tonic-gate int (*aio_func)(); 2134*7c478bd9Sstevel@tonic-gate aio_result_t *resultp; 2135*7c478bd9Sstevel@tonic-gate struct sigevent *sigev; 2136*7c478bd9Sstevel@tonic-gate model_t model; 2137*7c478bd9Sstevel@tonic-gate int aio_use_port = 0; 2138*7c478bd9Sstevel@tonic-gate port_notify_t pntfy; 2139*7c478bd9Sstevel@tonic-gate 2140*7c478bd9Sstevel@tonic-gate model = get_udatamodel(); 2141*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 2142*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 2143*7c478bd9Sstevel@tonic-gate return (EINVAL); 2144*7c478bd9Sstevel@tonic-gate 2145*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) { 2146*7c478bd9Sstevel@tonic-gate if (run_mode != AIO_LARGEFILE) { 2147*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb, sizeof (aiocb_t))) 2148*7c478bd9Sstevel@tonic-gate return (EFAULT); 2149*7c478bd9Sstevel@tonic-gate bufsize = aiocb.aio_nbytes; 2150*7c478bd9Sstevel@tonic-gate resultp = &(((aiocb_t *)aiocb_arg)->aio_resultp); 2151*7c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb.aio_fildes)) == NULL) { 2152*7c478bd9Sstevel@tonic-gate return (EBADF); 2153*7c478bd9Sstevel@tonic-gate } 2154*7c478bd9Sstevel@tonic-gate sigev = &aiocb.aio_sigevent; 2155*7c478bd9Sstevel@tonic-gate } else { 2156*7c478bd9Sstevel@tonic-gate /* 2157*7c478bd9Sstevel@tonic-gate * We come here only when we make largefile 2158*7c478bd9Sstevel@tonic-gate * call on 32 bit kernel using 32 bit library. 2159*7c478bd9Sstevel@tonic-gate */ 2160*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb64, sizeof (aiocb64_32_t))) 2161*7c478bd9Sstevel@tonic-gate return (EFAULT); 2162*7c478bd9Sstevel@tonic-gate bufsize = aiocb64.aio_nbytes; 2163*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&(((aiocb64_32_t *)aiocb_arg) 2164*7c478bd9Sstevel@tonic-gate ->aio_resultp); 2165*7c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb64.aio_fildes)) == NULL) { 2166*7c478bd9Sstevel@tonic-gate return (EBADF); 2167*7c478bd9Sstevel@tonic-gate } 2168*7c478bd9Sstevel@tonic-gate sigev = (struct sigevent *)&aiocb64.aio_sigevent; 2169*7c478bd9Sstevel@tonic-gate } 2170*7c478bd9Sstevel@tonic-gate 2171*7c478bd9Sstevel@tonic-gate if (sigev->sigev_notify == SIGEV_PORT) { 2172*7c478bd9Sstevel@tonic-gate if (copyin((void *)sigev->sigev_value.sival_ptr, 2173*7c478bd9Sstevel@tonic-gate &pntfy, sizeof (port_notify_t))) { 2174*7c478bd9Sstevel@tonic-gate releasef(fd); 2175*7c478bd9Sstevel@tonic-gate return (EFAULT); 2176*7c478bd9Sstevel@tonic-gate } 2177*7c478bd9Sstevel@tonic-gate aio_use_port = 1; 2178*7c478bd9Sstevel@tonic-gate } 2179*7c478bd9Sstevel@tonic-gate } 2180*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 2181*7c478bd9Sstevel@tonic-gate else { 2182*7c478bd9Sstevel@tonic-gate if (run_mode == AIO_32) { 2183*7c478bd9Sstevel@tonic-gate /* 32 bit system call is being made on 64 bit kernel */ 2184*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb32, sizeof (aiocb32_t))) 2185*7c478bd9Sstevel@tonic-gate return (EFAULT); 2186*7c478bd9Sstevel@tonic-gate 2187*7c478bd9Sstevel@tonic-gate bufsize = aiocb32.aio_nbytes; 2188*7c478bd9Sstevel@tonic-gate aiocb_32ton(&aiocb32, &aiocb); 2189*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&(((aiocb32_t *)aiocb_arg)-> 2190*7c478bd9Sstevel@tonic-gate aio_resultp); 2191*7c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb32.aio_fildes)) == NULL) { 2192*7c478bd9Sstevel@tonic-gate return (EBADF); 2193*7c478bd9Sstevel@tonic-gate } 2194*7c478bd9Sstevel@tonic-gate sigev32 = &aiocb32.aio_sigevent; 2195*7c478bd9Sstevel@tonic-gate } else if (run_mode == AIO_LARGEFILE) { 2196*7c478bd9Sstevel@tonic-gate /* 2197*7c478bd9Sstevel@tonic-gate * We come here only when we make largefile 2198*7c478bd9Sstevel@tonic-gate * call on 64 bit kernel using 32 bit library. 2199*7c478bd9Sstevel@tonic-gate */ 2200*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, &aiocb64, sizeof (aiocb64_32_t))) 2201*7c478bd9Sstevel@tonic-gate return (EFAULT); 2202*7c478bd9Sstevel@tonic-gate bufsize = aiocb64.aio_nbytes; 2203*7c478bd9Sstevel@tonic-gate aiocb_LFton(&aiocb64, &aiocb); 2204*7c478bd9Sstevel@tonic-gate resultp = (aio_result_t *)&(((aiocb64_32_t *)aiocb_arg) 2205*7c478bd9Sstevel@tonic-gate ->aio_resultp); 2206*7c478bd9Sstevel@tonic-gate if ((fp = getf(fd = aiocb64.aio_fildes)) == NULL) 2207*7c478bd9Sstevel@tonic-gate return (EBADF); 2208*7c478bd9Sstevel@tonic-gate sigev32 = &aiocb64.aio_sigevent; 2209*7c478bd9Sstevel@tonic-gate } 2210*7c478bd9Sstevel@tonic-gate 2211*7c478bd9Sstevel@tonic-gate if (sigev32->sigev_notify == SIGEV_PORT) { 2212*7c478bd9Sstevel@tonic-gate if (copyin( 2213*7c478bd9Sstevel@tonic-gate (void *)(uintptr_t)sigev32->sigev_value.sival_ptr, 2214*7c478bd9Sstevel@tonic-gate &pntfy32, sizeof (port_notify32_t))) { 2215*7c478bd9Sstevel@tonic-gate releasef(fd); 2216*7c478bd9Sstevel@tonic-gate return (EFAULT); 2217*7c478bd9Sstevel@tonic-gate } 2218*7c478bd9Sstevel@tonic-gate pntfy.portnfy_port = pntfy32.portnfy_port; 2219*7c478bd9Sstevel@tonic-gate pntfy.portnfy_user = 2220*7c478bd9Sstevel@tonic-gate (void *)(uintptr_t)pntfy32.portnfy_user; 2221*7c478bd9Sstevel@tonic-gate aio_use_port = 1; 2222*7c478bd9Sstevel@tonic-gate } 2223*7c478bd9Sstevel@tonic-gate } 2224*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 2225*7c478bd9Sstevel@tonic-gate 2226*7c478bd9Sstevel@tonic-gate /* 2227*7c478bd9Sstevel@tonic-gate * check the permission of the partition 2228*7c478bd9Sstevel@tonic-gate */ 2229*7c478bd9Sstevel@tonic-gate 2230*7c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) { 2231*7c478bd9Sstevel@tonic-gate releasef(fd); 2232*7c478bd9Sstevel@tonic-gate return (EBADF); 2233*7c478bd9Sstevel@tonic-gate } 2234*7c478bd9Sstevel@tonic-gate 2235*7c478bd9Sstevel@tonic-gate vp = fp->f_vnode; 2236*7c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode); 2237*7c478bd9Sstevel@tonic-gate if (aio_func == NULL) { 2238*7c478bd9Sstevel@tonic-gate releasef(fd); 2239*7c478bd9Sstevel@tonic-gate return (EBADFD); 2240*7c478bd9Sstevel@tonic-gate } 2241*7c478bd9Sstevel@tonic-gate if ((model == DATAMODEL_NATIVE) && (run_mode == AIO_LARGEFILE)) 2242*7c478bd9Sstevel@tonic-gate error = aio_req_setupLF(&reqp, aiop, &aiocb64, resultp, 2243*7c478bd9Sstevel@tonic-gate aio_use_port, vp); 2244*7c478bd9Sstevel@tonic-gate else 2245*7c478bd9Sstevel@tonic-gate error = aio_req_setup(&reqp, aiop, &aiocb, resultp, 2246*7c478bd9Sstevel@tonic-gate aio_use_port, vp); 2247*7c478bd9Sstevel@tonic-gate 2248*7c478bd9Sstevel@tonic-gate if (error) { 2249*7c478bd9Sstevel@tonic-gate releasef(fd); 2250*7c478bd9Sstevel@tonic-gate return (error); 2251*7c478bd9Sstevel@tonic-gate } 2252*7c478bd9Sstevel@tonic-gate /* 2253*7c478bd9Sstevel@tonic-gate * enable polling on this request if the opcode has 2254*7c478bd9Sstevel@tonic-gate * the AIO poll bit set 2255*7c478bd9Sstevel@tonic-gate */ 2256*7c478bd9Sstevel@tonic-gate if (opcode & AIO_POLL_BIT) 2257*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags |= AIO_POLL; 2258*7c478bd9Sstevel@tonic-gate 2259*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_NATIVE) 2260*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = aiocb_arg; 2261*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 2262*7c478bd9Sstevel@tonic-gate else 2263*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32 = (caddr32_t)(uintptr_t)aiocb_arg; 2264*7c478bd9Sstevel@tonic-gate #endif 2265*7c478bd9Sstevel@tonic-gate 2266*7c478bd9Sstevel@tonic-gate if (aio_use_port) 2267*7c478bd9Sstevel@tonic-gate error = aio_req_assoc_port_rw(&pntfy, aiocb_arg, reqp); 2268*7c478bd9Sstevel@tonic-gate 2269*7c478bd9Sstevel@tonic-gate /* 2270*7c478bd9Sstevel@tonic-gate * send the request to driver. 2271*7c478bd9Sstevel@tonic-gate * Clustering: If PXFS vnode, call PXFS function. 2272*7c478bd9Sstevel@tonic-gate */ 2273*7c478bd9Sstevel@tonic-gate if (error == 0) { 2274*7c478bd9Sstevel@tonic-gate if (bufsize == 0) { 2275*7c478bd9Sstevel@tonic-gate clear_active_fd(fd); 2276*7c478bd9Sstevel@tonic-gate aio_zerolen(reqp); 2277*7c478bd9Sstevel@tonic-gate return (0); 2278*7c478bd9Sstevel@tonic-gate } 2279*7c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, CRED()); 2280*7c478bd9Sstevel@tonic-gate } 2281*7c478bd9Sstevel@tonic-gate 2282*7c478bd9Sstevel@tonic-gate /* 2283*7c478bd9Sstevel@tonic-gate * the fd is stored in the aio_req_t by aio_req_setup(), and 2284*7c478bd9Sstevel@tonic-gate * is released by the aio_cleanup_thread() when the IO has 2285*7c478bd9Sstevel@tonic-gate * completed. 2286*7c478bd9Sstevel@tonic-gate */ 2287*7c478bd9Sstevel@tonic-gate if (error) { 2288*7c478bd9Sstevel@tonic-gate releasef(fd); 2289*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2290*7c478bd9Sstevel@tonic-gate aio_deq_port_pending(aiop, reqp); 2291*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 2292*7c478bd9Sstevel@tonic-gate aiop->aio_pending--; 2293*7c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) 2294*7c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv); 2295*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2296*7c478bd9Sstevel@tonic-gate return (error); 2297*7c478bd9Sstevel@tonic-gate } 2298*7c478bd9Sstevel@tonic-gate clear_active_fd(fd); 2299*7c478bd9Sstevel@tonic-gate return (0); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate 2303*7c478bd9Sstevel@tonic-gate /* 2304*7c478bd9Sstevel@tonic-gate * set error for a list IO entry that failed. 2305*7c478bd9Sstevel@tonic-gate */ 2306*7c478bd9Sstevel@tonic-gate static void 2307*7c478bd9Sstevel@tonic-gate lio_set_error(aio_req_t *reqp) 2308*7c478bd9Sstevel@tonic-gate { 2309*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 2310*7c478bd9Sstevel@tonic-gate 2311*7c478bd9Sstevel@tonic-gate if (aiop == NULL) 2312*7c478bd9Sstevel@tonic-gate return; 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2315*7c478bd9Sstevel@tonic-gate aio_deq_port_pending(aiop, reqp); 2316*7c478bd9Sstevel@tonic-gate aiop->aio_pending--; 2317*7c478bd9Sstevel@tonic-gate /* request failed, AIO_PHYSIODONE set to aviod physio cleanup. */ 2318*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags |= AIO_PHYSIODONE; 2319*7c478bd9Sstevel@tonic-gate /* 2320*7c478bd9Sstevel@tonic-gate * Need to free the request now as its never 2321*7c478bd9Sstevel@tonic-gate * going to get on the done queue 2322*7c478bd9Sstevel@tonic-gate * 2323*7c478bd9Sstevel@tonic-gate * Note: aio_outstanding is decremented in 2324*7c478bd9Sstevel@tonic-gate * aio_req_free() 2325*7c478bd9Sstevel@tonic-gate */ 2326*7c478bd9Sstevel@tonic-gate aio_req_free(aiop, reqp); 2327*7c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) 2328*7c478bd9Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv); 2329*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2330*7c478bd9Sstevel@tonic-gate } 2331*7c478bd9Sstevel@tonic-gate 2332*7c478bd9Sstevel@tonic-gate /* 2333*7c478bd9Sstevel@tonic-gate * check if a specified request is done, and remove it from 2334*7c478bd9Sstevel@tonic-gate * the done queue. otherwise remove anybody from the done queue 2335*7c478bd9Sstevel@tonic-gate * if NULL is specified. 2336*7c478bd9Sstevel@tonic-gate */ 2337*7c478bd9Sstevel@tonic-gate static aio_req_t * 2338*7c478bd9Sstevel@tonic-gate aio_req_done(void *resultp) 2339*7c478bd9Sstevel@tonic-gate { 2340*7c478bd9Sstevel@tonic-gate aio_req_t **bucket; 2341*7c478bd9Sstevel@tonic-gate aio_req_t *ent; 2342*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 2343*7c478bd9Sstevel@tonic-gate long index; 2344*7c478bd9Sstevel@tonic-gate 2345*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_cleanupq_mutex)); 2346*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 2347*7c478bd9Sstevel@tonic-gate 2348*7c478bd9Sstevel@tonic-gate if (resultp) { 2349*7c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp); 2350*7c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index]; 2351*7c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) { 2352*7c478bd9Sstevel@tonic-gate if (ent->aio_req_resultp == (aio_result_t *)resultp) { 2353*7c478bd9Sstevel@tonic-gate if (ent->aio_req_flags & AIO_DONEQ) { 2354*7c478bd9Sstevel@tonic-gate return (aio_req_remove(ent)); 2355*7c478bd9Sstevel@tonic-gate } 2356*7c478bd9Sstevel@tonic-gate return (NULL); 2357*7c478bd9Sstevel@tonic-gate } 2358*7c478bd9Sstevel@tonic-gate } 2359*7c478bd9Sstevel@tonic-gate /* no match, resultp is invalid */ 2360*7c478bd9Sstevel@tonic-gate return (NULL); 2361*7c478bd9Sstevel@tonic-gate } 2362*7c478bd9Sstevel@tonic-gate return (aio_req_remove(NULL)); 2363*7c478bd9Sstevel@tonic-gate } 2364*7c478bd9Sstevel@tonic-gate 2365*7c478bd9Sstevel@tonic-gate /* 2366*7c478bd9Sstevel@tonic-gate * determine if a user-level resultp pointer is associated with an 2367*7c478bd9Sstevel@tonic-gate * active IO request. Zero is returned when the request is done, 2368*7c478bd9Sstevel@tonic-gate * and the request is removed from the done queue. Only when the 2369*7c478bd9Sstevel@tonic-gate * return value is zero, is the "reqp" pointer valid. One is returned 2370*7c478bd9Sstevel@tonic-gate * when the request is inprogress. Two is returned when the request 2371*7c478bd9Sstevel@tonic-gate * is invalid. 2372*7c478bd9Sstevel@tonic-gate */ 2373*7c478bd9Sstevel@tonic-gate static int 2374*7c478bd9Sstevel@tonic-gate aio_req_find(aio_result_t *resultp, aio_req_t **reqp) 2375*7c478bd9Sstevel@tonic-gate { 2376*7c478bd9Sstevel@tonic-gate aio_req_t **bucket; 2377*7c478bd9Sstevel@tonic-gate aio_req_t *ent; 2378*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 2379*7c478bd9Sstevel@tonic-gate long index; 2380*7c478bd9Sstevel@tonic-gate 2381*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_cleanupq_mutex)); 2382*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 2383*7c478bd9Sstevel@tonic-gate 2384*7c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp); 2385*7c478bd9Sstevel@tonic-gate bucket = &aiop->aio_hash[index]; 2386*7c478bd9Sstevel@tonic-gate for (ent = *bucket; ent != NULL; ent = ent->aio_hash_next) { 2387*7c478bd9Sstevel@tonic-gate if (ent->aio_req_resultp == resultp) { 2388*7c478bd9Sstevel@tonic-gate if (ent->aio_req_flags & AIO_DONEQ) { 2389*7c478bd9Sstevel@tonic-gate *reqp = aio_req_remove(ent); 2390*7c478bd9Sstevel@tonic-gate return (0); 2391*7c478bd9Sstevel@tonic-gate } 2392*7c478bd9Sstevel@tonic-gate return (1); 2393*7c478bd9Sstevel@tonic-gate } 2394*7c478bd9Sstevel@tonic-gate } 2395*7c478bd9Sstevel@tonic-gate /* no match, resultp is invalid */ 2396*7c478bd9Sstevel@tonic-gate return (2); 2397*7c478bd9Sstevel@tonic-gate } 2398*7c478bd9Sstevel@tonic-gate 2399*7c478bd9Sstevel@tonic-gate /* 2400*7c478bd9Sstevel@tonic-gate * remove a request from the done queue. 2401*7c478bd9Sstevel@tonic-gate */ 2402*7c478bd9Sstevel@tonic-gate static aio_req_t * 2403*7c478bd9Sstevel@tonic-gate aio_req_remove(aio_req_t *reqp) 2404*7c478bd9Sstevel@tonic-gate { 2405*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 2406*7c478bd9Sstevel@tonic-gate aio_req_t *head; 2407*7c478bd9Sstevel@tonic-gate 2408*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 2409*7c478bd9Sstevel@tonic-gate 2410*7c478bd9Sstevel@tonic-gate if (reqp) { 2411*7c478bd9Sstevel@tonic-gate ASSERT(reqp->aio_req_flags & AIO_DONEQ); 2412*7c478bd9Sstevel@tonic-gate if (reqp->aio_req_next == reqp) { 2413*7c478bd9Sstevel@tonic-gate /* only one request on queue */ 2414*7c478bd9Sstevel@tonic-gate if (reqp == aiop->aio_doneq) { 2415*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL; 2416*7c478bd9Sstevel@tonic-gate } else { 2417*7c478bd9Sstevel@tonic-gate ASSERT(reqp == aiop->aio_cleanupq); 2418*7c478bd9Sstevel@tonic-gate aiop->aio_cleanupq = NULL; 2419*7c478bd9Sstevel@tonic-gate } 2420*7c478bd9Sstevel@tonic-gate } else { 2421*7c478bd9Sstevel@tonic-gate reqp->aio_req_next->aio_req_prev = reqp->aio_req_prev; 2422*7c478bd9Sstevel@tonic-gate reqp->aio_req_prev->aio_req_next = reqp->aio_req_next; 2423*7c478bd9Sstevel@tonic-gate /* 2424*7c478bd9Sstevel@tonic-gate * The request can be either on the aio_doneq or the 2425*7c478bd9Sstevel@tonic-gate * aio_cleanupq 2426*7c478bd9Sstevel@tonic-gate */ 2427*7c478bd9Sstevel@tonic-gate if (reqp == aiop->aio_doneq) 2428*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = reqp->aio_req_next; 2429*7c478bd9Sstevel@tonic-gate 2430*7c478bd9Sstevel@tonic-gate if (reqp == aiop->aio_cleanupq) 2431*7c478bd9Sstevel@tonic-gate aiop->aio_cleanupq = reqp->aio_req_next; 2432*7c478bd9Sstevel@tonic-gate } 2433*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags &= ~AIO_DONEQ; 2434*7c478bd9Sstevel@tonic-gate return (reqp); 2435*7c478bd9Sstevel@tonic-gate } 2436*7c478bd9Sstevel@tonic-gate 2437*7c478bd9Sstevel@tonic-gate if (aiop->aio_doneq) { 2438*7c478bd9Sstevel@tonic-gate head = aiop->aio_doneq; 2439*7c478bd9Sstevel@tonic-gate ASSERT(head->aio_req_flags & AIO_DONEQ); 2440*7c478bd9Sstevel@tonic-gate if (head == head->aio_req_next) { 2441*7c478bd9Sstevel@tonic-gate /* only one request on queue */ 2442*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL; 2443*7c478bd9Sstevel@tonic-gate } else { 2444*7c478bd9Sstevel@tonic-gate head->aio_req_prev->aio_req_next = head->aio_req_next; 2445*7c478bd9Sstevel@tonic-gate head->aio_req_next->aio_req_prev = head->aio_req_prev; 2446*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = head->aio_req_next; 2447*7c478bd9Sstevel@tonic-gate } 2448*7c478bd9Sstevel@tonic-gate head->aio_req_flags &= ~AIO_DONEQ; 2449*7c478bd9Sstevel@tonic-gate return (head); 2450*7c478bd9Sstevel@tonic-gate } 2451*7c478bd9Sstevel@tonic-gate return (NULL); 2452*7c478bd9Sstevel@tonic-gate } 2453*7c478bd9Sstevel@tonic-gate 2454*7c478bd9Sstevel@tonic-gate static int 2455*7c478bd9Sstevel@tonic-gate aio_req_setup( 2456*7c478bd9Sstevel@tonic-gate aio_req_t **reqpp, 2457*7c478bd9Sstevel@tonic-gate aio_t *aiop, 2458*7c478bd9Sstevel@tonic-gate aiocb_t *arg, 2459*7c478bd9Sstevel@tonic-gate aio_result_t *resultp, 2460*7c478bd9Sstevel@tonic-gate int port, 2461*7c478bd9Sstevel@tonic-gate vnode_t *vp) 2462*7c478bd9Sstevel@tonic-gate { 2463*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 2464*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 2465*7c478bd9Sstevel@tonic-gate struct uio *uio; 2466*7c478bd9Sstevel@tonic-gate 2467*7c478bd9Sstevel@tonic-gate struct sigevent *sigev; 2468*7c478bd9Sstevel@tonic-gate int error; 2469*7c478bd9Sstevel@tonic-gate 2470*7c478bd9Sstevel@tonic-gate sigev = &arg->aio_sigevent; 2471*7c478bd9Sstevel@tonic-gate if ((sigev->sigev_notify == SIGEV_SIGNAL) && 2472*7c478bd9Sstevel@tonic-gate (sigev->sigev_signo > 0 && sigev->sigev_signo < NSIG)) { 2473*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP); 2474*7c478bd9Sstevel@tonic-gate if (sqp == NULL) 2475*7c478bd9Sstevel@tonic-gate return (EAGAIN); 2476*7c478bd9Sstevel@tonic-gate sqp->sq_func = NULL; 2477*7c478bd9Sstevel@tonic-gate sqp->sq_next = NULL; 2478*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO; 2479*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid; 2480*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc); 2481*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 2482*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred); 2483*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigev->sigev_signo; 2484*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_value = sigev->sigev_value; 2485*7c478bd9Sstevel@tonic-gate } else 2486*7c478bd9Sstevel@tonic-gate sqp = NULL; 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2489*7c478bd9Sstevel@tonic-gate 2490*7c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) { 2491*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2492*7c478bd9Sstevel@tonic-gate if (sqp) 2493*7c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t)); 2494*7c478bd9Sstevel@tonic-gate return (EIO); 2495*7c478bd9Sstevel@tonic-gate } 2496*7c478bd9Sstevel@tonic-gate /* 2497*7c478bd9Sstevel@tonic-gate * get an aio_reqp from the free list or allocate one 2498*7c478bd9Sstevel@tonic-gate * from dynamic memory. 2499*7c478bd9Sstevel@tonic-gate */ 2500*7c478bd9Sstevel@tonic-gate if (error = aio_req_alloc(&reqp, resultp)) { 2501*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2502*7c478bd9Sstevel@tonic-gate if (sqp) 2503*7c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t)); 2504*7c478bd9Sstevel@tonic-gate return (error); 2505*7c478bd9Sstevel@tonic-gate } 2506*7c478bd9Sstevel@tonic-gate aiop->aio_pending++; 2507*7c478bd9Sstevel@tonic-gate aiop->aio_outstanding++; 2508*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags = AIO_PENDING; 2509*7c478bd9Sstevel@tonic-gate if (port) 2510*7c478bd9Sstevel@tonic-gate aio_enq_port_pending(aiop, reqp); 2511*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2512*7c478bd9Sstevel@tonic-gate /* 2513*7c478bd9Sstevel@tonic-gate * initialize aio request. 2514*7c478bd9Sstevel@tonic-gate */ 2515*7c478bd9Sstevel@tonic-gate reqp->aio_req_fd = arg->aio_fildes; 2516*7c478bd9Sstevel@tonic-gate reqp->aio_req_sigqp = sqp; 2517*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = NULL; 2518*7c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_file = vp; 2519*7c478bd9Sstevel@tonic-gate uio = reqp->aio_req.aio_uio; 2520*7c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1; 2521*7c478bd9Sstevel@tonic-gate uio->uio_iov->iov_base = (caddr_t)arg->aio_buf; 2522*7c478bd9Sstevel@tonic-gate uio->uio_iov->iov_len = arg->aio_nbytes; 2523*7c478bd9Sstevel@tonic-gate uio->uio_loffset = arg->aio_offset; 2524*7c478bd9Sstevel@tonic-gate *reqpp = reqp; 2525*7c478bd9Sstevel@tonic-gate return (0); 2526*7c478bd9Sstevel@tonic-gate } 2527*7c478bd9Sstevel@tonic-gate 2528*7c478bd9Sstevel@tonic-gate /* 2529*7c478bd9Sstevel@tonic-gate * Allocate p_aio struct. 2530*7c478bd9Sstevel@tonic-gate */ 2531*7c478bd9Sstevel@tonic-gate static aio_t * 2532*7c478bd9Sstevel@tonic-gate aio_aiop_alloc(void) 2533*7c478bd9Sstevel@tonic-gate { 2534*7c478bd9Sstevel@tonic-gate aio_t *aiop; 2535*7c478bd9Sstevel@tonic-gate 2536*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&curproc->p_lock)); 2537*7c478bd9Sstevel@tonic-gate 2538*7c478bd9Sstevel@tonic-gate aiop = kmem_zalloc(sizeof (struct aio), KM_NOSLEEP); 2539*7c478bd9Sstevel@tonic-gate if (aiop) { 2540*7c478bd9Sstevel@tonic-gate mutex_init(&aiop->aio_mutex, NULL, MUTEX_DEFAULT, NULL); 2541*7c478bd9Sstevel@tonic-gate mutex_init(&aiop->aio_cleanupq_mutex, NULL, MUTEX_DEFAULT, 2542*7c478bd9Sstevel@tonic-gate NULL); 2543*7c478bd9Sstevel@tonic-gate mutex_init(&aiop->aio_portq_mutex, NULL, MUTEX_DEFAULT, NULL); 2544*7c478bd9Sstevel@tonic-gate } 2545*7c478bd9Sstevel@tonic-gate return (aiop); 2546*7c478bd9Sstevel@tonic-gate } 2547*7c478bd9Sstevel@tonic-gate 2548*7c478bd9Sstevel@tonic-gate /* 2549*7c478bd9Sstevel@tonic-gate * Allocate an aio_req struct. 2550*7c478bd9Sstevel@tonic-gate */ 2551*7c478bd9Sstevel@tonic-gate static int 2552*7c478bd9Sstevel@tonic-gate aio_req_alloc(aio_req_t **nreqp, aio_result_t *resultp) 2553*7c478bd9Sstevel@tonic-gate { 2554*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 2555*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 2556*7c478bd9Sstevel@tonic-gate 2557*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 2558*7c478bd9Sstevel@tonic-gate 2559*7c478bd9Sstevel@tonic-gate if ((reqp = aiop->aio_free) != NULL) { 2560*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags = 0; 2561*7c478bd9Sstevel@tonic-gate aiop->aio_free = reqp->aio_req_next; 2562*7c478bd9Sstevel@tonic-gate /* 2563*7c478bd9Sstevel@tonic-gate * Clustering:This field has to be specifically 2564*7c478bd9Sstevel@tonic-gate * set to null so that the right thing can be 2565*7c478bd9Sstevel@tonic-gate * done in aphysio() 2566*7c478bd9Sstevel@tonic-gate */ 2567*7c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_iodone = NULL; 2568*7c478bd9Sstevel@tonic-gate } else { 2569*7c478bd9Sstevel@tonic-gate /* 2570*7c478bd9Sstevel@tonic-gate * Check whether memory is getting tight. 2571*7c478bd9Sstevel@tonic-gate * This is a temporary mechanism to avoid memory 2572*7c478bd9Sstevel@tonic-gate * exhaustion by a single process until we come up 2573*7c478bd9Sstevel@tonic-gate * with a per process solution such as setrlimit(). 2574*7c478bd9Sstevel@tonic-gate */ 2575*7c478bd9Sstevel@tonic-gate if (freemem < desfree) 2576*7c478bd9Sstevel@tonic-gate return (EAGAIN); 2577*7c478bd9Sstevel@tonic-gate 2578*7c478bd9Sstevel@tonic-gate reqp = kmem_zalloc(sizeof (struct aio_req_t), KM_NOSLEEP); 2579*7c478bd9Sstevel@tonic-gate if (reqp == NULL) 2580*7c478bd9Sstevel@tonic-gate return (EAGAIN); 2581*7c478bd9Sstevel@tonic-gate reqp->aio_req.aio_uio = &(reqp->aio_req_uio); 2582*7c478bd9Sstevel@tonic-gate reqp->aio_req.aio_uio->uio_iov = &(reqp->aio_req_iov); 2583*7c478bd9Sstevel@tonic-gate reqp->aio_req.aio_private = reqp; 2584*7c478bd9Sstevel@tonic-gate } 2585*7c478bd9Sstevel@tonic-gate 2586*7c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_offset = -1; 2587*7c478bd9Sstevel@tonic-gate reqp->aio_req_resultp = resultp; 2588*7c478bd9Sstevel@tonic-gate if (aio_hash_insert(reqp, aiop)) { 2589*7c478bd9Sstevel@tonic-gate reqp->aio_req_next = aiop->aio_free; 2590*7c478bd9Sstevel@tonic-gate aiop->aio_free = reqp; 2591*7c478bd9Sstevel@tonic-gate return (EINVAL); 2592*7c478bd9Sstevel@tonic-gate } 2593*7c478bd9Sstevel@tonic-gate *nreqp = reqp; 2594*7c478bd9Sstevel@tonic-gate return (0); 2595*7c478bd9Sstevel@tonic-gate } 2596*7c478bd9Sstevel@tonic-gate 2597*7c478bd9Sstevel@tonic-gate /* 2598*7c478bd9Sstevel@tonic-gate * Allocate an aio_lio_t struct. 2599*7c478bd9Sstevel@tonic-gate */ 2600*7c478bd9Sstevel@tonic-gate static int 2601*7c478bd9Sstevel@tonic-gate aio_lio_alloc(aio_lio_t **head) 2602*7c478bd9Sstevel@tonic-gate { 2603*7c478bd9Sstevel@tonic-gate aio_lio_t *liop; 2604*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 2607*7c478bd9Sstevel@tonic-gate 2608*7c478bd9Sstevel@tonic-gate if ((liop = aiop->aio_lio_free) != NULL) { 2609*7c478bd9Sstevel@tonic-gate aiop->aio_lio_free = liop->lio_next; 2610*7c478bd9Sstevel@tonic-gate } else { 2611*7c478bd9Sstevel@tonic-gate /* 2612*7c478bd9Sstevel@tonic-gate * Check whether memory is getting tight. 2613*7c478bd9Sstevel@tonic-gate * This is a temporary mechanism to avoid memory 2614*7c478bd9Sstevel@tonic-gate * exhaustion by a single process until we come up 2615*7c478bd9Sstevel@tonic-gate * with a per process solution such as setrlimit(). 2616*7c478bd9Sstevel@tonic-gate */ 2617*7c478bd9Sstevel@tonic-gate if (freemem < desfree) 2618*7c478bd9Sstevel@tonic-gate return (EAGAIN); 2619*7c478bd9Sstevel@tonic-gate 2620*7c478bd9Sstevel@tonic-gate liop = kmem_zalloc(sizeof (aio_lio_t), KM_NOSLEEP); 2621*7c478bd9Sstevel@tonic-gate if (liop == NULL) 2622*7c478bd9Sstevel@tonic-gate return (EAGAIN); 2623*7c478bd9Sstevel@tonic-gate } 2624*7c478bd9Sstevel@tonic-gate *head = liop; 2625*7c478bd9Sstevel@tonic-gate return (0); 2626*7c478bd9Sstevel@tonic-gate } 2627*7c478bd9Sstevel@tonic-gate 2628*7c478bd9Sstevel@tonic-gate /* 2629*7c478bd9Sstevel@tonic-gate * this is a special per-process thread that is only activated if 2630*7c478bd9Sstevel@tonic-gate * the process is unmapping a segment with outstanding aio. normally, 2631*7c478bd9Sstevel@tonic-gate * the process will have completed the aio before unmapping the 2632*7c478bd9Sstevel@tonic-gate * segment. If the process does unmap a segment with outstanding aio, 2633*7c478bd9Sstevel@tonic-gate * this special thread will guarentee that the locked pages due to 2634*7c478bd9Sstevel@tonic-gate * aphysio() are released, thereby permitting the segment to be 2635*7c478bd9Sstevel@tonic-gate * unmapped. 2636*7c478bd9Sstevel@tonic-gate */ 2637*7c478bd9Sstevel@tonic-gate 2638*7c478bd9Sstevel@tonic-gate static int 2639*7c478bd9Sstevel@tonic-gate aio_cleanup_thread(aio_t *aiop) 2640*7c478bd9Sstevel@tonic-gate { 2641*7c478bd9Sstevel@tonic-gate proc_t *p = curproc; 2642*7c478bd9Sstevel@tonic-gate struct as *as = p->p_as; 2643*7c478bd9Sstevel@tonic-gate int poked = 0; 2644*7c478bd9Sstevel@tonic-gate kcondvar_t *cvp; 2645*7c478bd9Sstevel@tonic-gate int exit_flag = 0; 2646*7c478bd9Sstevel@tonic-gate 2647*7c478bd9Sstevel@tonic-gate sigfillset(&curthread->t_hold); 2648*7c478bd9Sstevel@tonic-gate sigdiffset(&curthread->t_hold, &cantmask); 2649*7c478bd9Sstevel@tonic-gate for (;;) { 2650*7c478bd9Sstevel@tonic-gate /* 2651*7c478bd9Sstevel@tonic-gate * if a segment is being unmapped, and the current 2652*7c478bd9Sstevel@tonic-gate * process's done queue is not empty, then every request 2653*7c478bd9Sstevel@tonic-gate * on the doneq with locked resources should be forced 2654*7c478bd9Sstevel@tonic-gate * to release their locks. By moving the doneq request 2655*7c478bd9Sstevel@tonic-gate * to the cleanupq, aio_cleanup() will process the cleanupq, 2656*7c478bd9Sstevel@tonic-gate * and place requests back onto the doneq. All requests 2657*7c478bd9Sstevel@tonic-gate * processed by aio_cleanup() will have their physical 2658*7c478bd9Sstevel@tonic-gate * resources unlocked. 2659*7c478bd9Sstevel@tonic-gate */ 2660*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2661*7c478bd9Sstevel@tonic-gate if ((aiop->aio_flags & AIO_CLEANUP) == 0) { 2662*7c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_CLEANUP; 2663*7c478bd9Sstevel@tonic-gate mutex_enter(&as->a_contents); 2664*7c478bd9Sstevel@tonic-gate if (AS_ISUNMAPWAIT(as) && aiop->aio_doneq) { 2665*7c478bd9Sstevel@tonic-gate aio_req_t *doneqhead = aiop->aio_doneq; 2666*7c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents); 2667*7c478bd9Sstevel@tonic-gate aiop->aio_doneq = NULL; 2668*7c478bd9Sstevel@tonic-gate aio_cleanupq_concat(aiop, doneqhead, AIO_DONEQ); 2669*7c478bd9Sstevel@tonic-gate } else { 2670*7c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents); 2671*7c478bd9Sstevel@tonic-gate } 2672*7c478bd9Sstevel@tonic-gate } 2673*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2674*7c478bd9Sstevel@tonic-gate aio_cleanup(AIO_CLEANUP_THREAD); 2675*7c478bd9Sstevel@tonic-gate /* 2676*7c478bd9Sstevel@tonic-gate * thread should block on the cleanupcv while 2677*7c478bd9Sstevel@tonic-gate * AIO_CLEANUP is set. 2678*7c478bd9Sstevel@tonic-gate */ 2679*7c478bd9Sstevel@tonic-gate cvp = &aiop->aio_cleanupcv; 2680*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2681*7c478bd9Sstevel@tonic-gate 2682*7c478bd9Sstevel@tonic-gate if (aiop->aio_pollq != NULL || aiop->aio_cleanupq != NULL || 2683*7c478bd9Sstevel@tonic-gate aiop->aio_notifyq != NULL || 2684*7c478bd9Sstevel@tonic-gate aiop->aio_portcleanupq != NULL) { 2685*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2686*7c478bd9Sstevel@tonic-gate continue; 2687*7c478bd9Sstevel@tonic-gate } 2688*7c478bd9Sstevel@tonic-gate mutex_enter(&as->a_contents); 2689*7c478bd9Sstevel@tonic-gate 2690*7c478bd9Sstevel@tonic-gate /* 2691*7c478bd9Sstevel@tonic-gate * AIO_CLEANUP determines when the cleanup thread 2692*7c478bd9Sstevel@tonic-gate * should be active. This flag is only set when 2693*7c478bd9Sstevel@tonic-gate * the cleanup thread is awakened by as_unmap(). 2694*7c478bd9Sstevel@tonic-gate * The flag is cleared when the blocking as_unmap() 2695*7c478bd9Sstevel@tonic-gate * that originally awakened us is allowed to 2696*7c478bd9Sstevel@tonic-gate * complete. as_unmap() blocks when trying to 2697*7c478bd9Sstevel@tonic-gate * unmap a segment that has SOFTLOCKed pages. when 2698*7c478bd9Sstevel@tonic-gate * the segment's pages are all SOFTUNLOCKed, 2699*7c478bd9Sstevel@tonic-gate * as->a_flags & AS_UNMAPWAIT should be zero. The flag 2700*7c478bd9Sstevel@tonic-gate * shouldn't be cleared right away if the cleanup thread 2701*7c478bd9Sstevel@tonic-gate * was interrupted because the process is doing forkall(). 2702*7c478bd9Sstevel@tonic-gate * This happens when cv_wait_sig() returns zero, 2703*7c478bd9Sstevel@tonic-gate * because it was awakened by a pokelwps(). If the 2704*7c478bd9Sstevel@tonic-gate * process is not exiting, it must be doing forkall(). 2705*7c478bd9Sstevel@tonic-gate */ 2706*7c478bd9Sstevel@tonic-gate if ((poked == 0) && 2707*7c478bd9Sstevel@tonic-gate ((AS_ISUNMAPWAIT(as) == 0) || (aiop->aio_pending == 0))) { 2708*7c478bd9Sstevel@tonic-gate aiop->aio_flags &= ~(AIO_CLEANUP | AIO_CLEANUP_PORT); 2709*7c478bd9Sstevel@tonic-gate cvp = &as->a_cv; 2710*7c478bd9Sstevel@tonic-gate } 2711*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2712*7c478bd9Sstevel@tonic-gate if (poked) { 2713*7c478bd9Sstevel@tonic-gate /* 2714*7c478bd9Sstevel@tonic-gate * If the process is exiting/killed, don't return 2715*7c478bd9Sstevel@tonic-gate * immediately without waiting for pending I/O's 2716*7c478bd9Sstevel@tonic-gate * and releasing the page locks. 2717*7c478bd9Sstevel@tonic-gate */ 2718*7c478bd9Sstevel@tonic-gate if (p->p_flag & (SEXITLWPS|SKILLED)) { 2719*7c478bd9Sstevel@tonic-gate /* 2720*7c478bd9Sstevel@tonic-gate * If exit_flag is set, then it is 2721*7c478bd9Sstevel@tonic-gate * safe to exit because we have released 2722*7c478bd9Sstevel@tonic-gate * page locks of completed I/O's. 2723*7c478bd9Sstevel@tonic-gate */ 2724*7c478bd9Sstevel@tonic-gate if (exit_flag) 2725*7c478bd9Sstevel@tonic-gate break; 2726*7c478bd9Sstevel@tonic-gate 2727*7c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents); 2728*7c478bd9Sstevel@tonic-gate 2729*7c478bd9Sstevel@tonic-gate /* 2730*7c478bd9Sstevel@tonic-gate * Wait for all the pending aio to complete. 2731*7c478bd9Sstevel@tonic-gate */ 2732*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 2733*7c478bd9Sstevel@tonic-gate aiop->aio_flags |= AIO_REQ_BLOCK; 2734*7c478bd9Sstevel@tonic-gate while (aiop->aio_pending != 0) 2735*7c478bd9Sstevel@tonic-gate cv_wait(&aiop->aio_cleanupcv, 2736*7c478bd9Sstevel@tonic-gate &aiop->aio_mutex); 2737*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2738*7c478bd9Sstevel@tonic-gate exit_flag = 1; 2739*7c478bd9Sstevel@tonic-gate continue; 2740*7c478bd9Sstevel@tonic-gate } else if (p->p_flag & 2741*7c478bd9Sstevel@tonic-gate (SHOLDFORK|SHOLDFORK1|SHOLDWATCH)) { 2742*7c478bd9Sstevel@tonic-gate /* 2743*7c478bd9Sstevel@tonic-gate * hold LWP until it 2744*7c478bd9Sstevel@tonic-gate * is continued. 2745*7c478bd9Sstevel@tonic-gate */ 2746*7c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents); 2747*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2748*7c478bd9Sstevel@tonic-gate stop(PR_SUSPENDED, SUSPEND_NORMAL); 2749*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2750*7c478bd9Sstevel@tonic-gate poked = 0; 2751*7c478bd9Sstevel@tonic-gate continue; 2752*7c478bd9Sstevel@tonic-gate } 2753*7c478bd9Sstevel@tonic-gate } else { 2754*7c478bd9Sstevel@tonic-gate /* 2755*7c478bd9Sstevel@tonic-gate * When started this thread will sleep on as->a_cv. 2756*7c478bd9Sstevel@tonic-gate * as_unmap will awake this thread if the 2757*7c478bd9Sstevel@tonic-gate * segment has SOFTLOCKed pages (poked = 0). 2758*7c478bd9Sstevel@tonic-gate * 1. pokelwps() awakes this thread => 2759*7c478bd9Sstevel@tonic-gate * break the loop to check SEXITLWPS, SHOLDFORK, etc 2760*7c478bd9Sstevel@tonic-gate * 2. as_unmap awakes this thread => 2761*7c478bd9Sstevel@tonic-gate * to break the loop it is necessary that 2762*7c478bd9Sstevel@tonic-gate * - AS_UNMAPWAIT is set (as_unmap is waiting for 2763*7c478bd9Sstevel@tonic-gate * memory to be unlocked) 2764*7c478bd9Sstevel@tonic-gate * - some transactions are still pending 2765*7c478bd9Sstevel@tonic-gate * - AIO_CLEANUP is not set 2766*7c478bd9Sstevel@tonic-gate * (if AIO_CLEANUP is set we have to wait for 2767*7c478bd9Sstevel@tonic-gate * pending requests. aio_done will send a signal 2768*7c478bd9Sstevel@tonic-gate * for every request which completes to continue 2769*7c478bd9Sstevel@tonic-gate * unmapping the corresponding address range) 2770*7c478bd9Sstevel@tonic-gate */ 2771*7c478bd9Sstevel@tonic-gate while (poked == 0) { 2772*7c478bd9Sstevel@tonic-gate if ((AS_ISUNMAPWAIT(as) != 0) && 2773*7c478bd9Sstevel@tonic-gate (aiop->aio_pending != 0) && 2774*7c478bd9Sstevel@tonic-gate ((aiop->aio_flags & AIO_CLEANUP) == 0)) 2775*7c478bd9Sstevel@tonic-gate break; 2776*7c478bd9Sstevel@tonic-gate poked = !cv_wait_sig(cvp, &as->a_contents); 2777*7c478bd9Sstevel@tonic-gate if (AS_ISUNMAPWAIT(as) == 0) 2778*7c478bd9Sstevel@tonic-gate cv_signal(cvp); 2779*7c478bd9Sstevel@tonic-gate if (aiop->aio_outstanding != 0) 2780*7c478bd9Sstevel@tonic-gate break; 2781*7c478bd9Sstevel@tonic-gate } 2782*7c478bd9Sstevel@tonic-gate } 2783*7c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents); 2784*7c478bd9Sstevel@tonic-gate } 2785*7c478bd9Sstevel@tonic-gate exit: 2786*7c478bd9Sstevel@tonic-gate mutex_exit(&as->a_contents); 2787*7c478bd9Sstevel@tonic-gate ASSERT((curproc->p_flag & (SEXITLWPS|SKILLED))); 2788*7c478bd9Sstevel@tonic-gate aston(curthread); /* make thread do post_syscall */ 2789*7c478bd9Sstevel@tonic-gate return (0); 2790*7c478bd9Sstevel@tonic-gate } 2791*7c478bd9Sstevel@tonic-gate 2792*7c478bd9Sstevel@tonic-gate /* 2793*7c478bd9Sstevel@tonic-gate * save a reference to a user's outstanding aio in a hash list. 2794*7c478bd9Sstevel@tonic-gate */ 2795*7c478bd9Sstevel@tonic-gate static int 2796*7c478bd9Sstevel@tonic-gate aio_hash_insert( 2797*7c478bd9Sstevel@tonic-gate aio_req_t *aio_reqp, 2798*7c478bd9Sstevel@tonic-gate aio_t *aiop) 2799*7c478bd9Sstevel@tonic-gate { 2800*7c478bd9Sstevel@tonic-gate long index; 2801*7c478bd9Sstevel@tonic-gate aio_result_t *resultp = aio_reqp->aio_req_resultp; 2802*7c478bd9Sstevel@tonic-gate aio_req_t *current; 2803*7c478bd9Sstevel@tonic-gate aio_req_t **nextp; 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate index = AIO_HASH(resultp); 2806*7c478bd9Sstevel@tonic-gate nextp = &aiop->aio_hash[index]; 2807*7c478bd9Sstevel@tonic-gate while ((current = *nextp) != NULL) { 2808*7c478bd9Sstevel@tonic-gate if (current->aio_req_resultp == resultp) 2809*7c478bd9Sstevel@tonic-gate return (DUPLICATE); 2810*7c478bd9Sstevel@tonic-gate nextp = ¤t->aio_hash_next; 2811*7c478bd9Sstevel@tonic-gate } 2812*7c478bd9Sstevel@tonic-gate *nextp = aio_reqp; 2813*7c478bd9Sstevel@tonic-gate aio_reqp->aio_hash_next = NULL; 2814*7c478bd9Sstevel@tonic-gate return (0); 2815*7c478bd9Sstevel@tonic-gate } 2816*7c478bd9Sstevel@tonic-gate 2817*7c478bd9Sstevel@tonic-gate static int 2818*7c478bd9Sstevel@tonic-gate (*check_vp(struct vnode *vp, int mode))(vnode_t *, struct aio_req *, 2819*7c478bd9Sstevel@tonic-gate cred_t *) 2820*7c478bd9Sstevel@tonic-gate { 2821*7c478bd9Sstevel@tonic-gate struct snode *sp; 2822*7c478bd9Sstevel@tonic-gate dev_t dev; 2823*7c478bd9Sstevel@tonic-gate struct cb_ops *cb; 2824*7c478bd9Sstevel@tonic-gate major_t major; 2825*7c478bd9Sstevel@tonic-gate int (*aio_func)(); 2826*7c478bd9Sstevel@tonic-gate 2827*7c478bd9Sstevel@tonic-gate dev = vp->v_rdev; 2828*7c478bd9Sstevel@tonic-gate major = getmajor(dev); 2829*7c478bd9Sstevel@tonic-gate 2830*7c478bd9Sstevel@tonic-gate /* 2831*7c478bd9Sstevel@tonic-gate * return NULL for requests to files and STREAMs so 2832*7c478bd9Sstevel@tonic-gate * that libaio takes care of them. 2833*7c478bd9Sstevel@tonic-gate */ 2834*7c478bd9Sstevel@tonic-gate if (vp->v_type == VCHR) { 2835*7c478bd9Sstevel@tonic-gate /* no stream device for kaio */ 2836*7c478bd9Sstevel@tonic-gate if (STREAMSTAB(major)) { 2837*7c478bd9Sstevel@tonic-gate return (NULL); 2838*7c478bd9Sstevel@tonic-gate } 2839*7c478bd9Sstevel@tonic-gate } else { 2840*7c478bd9Sstevel@tonic-gate return (NULL); 2841*7c478bd9Sstevel@tonic-gate } 2842*7c478bd9Sstevel@tonic-gate 2843*7c478bd9Sstevel@tonic-gate /* 2844*7c478bd9Sstevel@tonic-gate * Check old drivers which do not have async I/O entry points. 2845*7c478bd9Sstevel@tonic-gate */ 2846*7c478bd9Sstevel@tonic-gate if (devopsp[major]->devo_rev < 3) 2847*7c478bd9Sstevel@tonic-gate return (NULL); 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate cb = devopsp[major]->devo_cb_ops; 2850*7c478bd9Sstevel@tonic-gate 2851*7c478bd9Sstevel@tonic-gate if (cb->cb_rev < 1) 2852*7c478bd9Sstevel@tonic-gate return (NULL); 2853*7c478bd9Sstevel@tonic-gate 2854*7c478bd9Sstevel@tonic-gate /* 2855*7c478bd9Sstevel@tonic-gate * Check whether this device is a block device. 2856*7c478bd9Sstevel@tonic-gate * Kaio is not supported for devices like tty. 2857*7c478bd9Sstevel@tonic-gate */ 2858*7c478bd9Sstevel@tonic-gate if (cb->cb_strategy == nodev || cb->cb_strategy == NULL) 2859*7c478bd9Sstevel@tonic-gate return (NULL); 2860*7c478bd9Sstevel@tonic-gate 2861*7c478bd9Sstevel@tonic-gate /* 2862*7c478bd9Sstevel@tonic-gate * Clustering: If vnode is a PXFS vnode, then the device may be remote. 2863*7c478bd9Sstevel@tonic-gate * We cannot call the driver directly. Instead return the 2864*7c478bd9Sstevel@tonic-gate * PXFS functions. 2865*7c478bd9Sstevel@tonic-gate */ 2866*7c478bd9Sstevel@tonic-gate 2867*7c478bd9Sstevel@tonic-gate if (IS_PXFSVP(vp)) { 2868*7c478bd9Sstevel@tonic-gate if (mode & FREAD) 2869*7c478bd9Sstevel@tonic-gate return (clpxfs_aio_read); 2870*7c478bd9Sstevel@tonic-gate else 2871*7c478bd9Sstevel@tonic-gate return (clpxfs_aio_write); 2872*7c478bd9Sstevel@tonic-gate } 2873*7c478bd9Sstevel@tonic-gate if (mode & FREAD) 2874*7c478bd9Sstevel@tonic-gate aio_func = (cb->cb_aread == nodev) ? NULL : driver_aio_read; 2875*7c478bd9Sstevel@tonic-gate else 2876*7c478bd9Sstevel@tonic-gate aio_func = (cb->cb_awrite == nodev) ? NULL : driver_aio_write; 2877*7c478bd9Sstevel@tonic-gate 2878*7c478bd9Sstevel@tonic-gate /* 2879*7c478bd9Sstevel@tonic-gate * Do we need this ? 2880*7c478bd9Sstevel@tonic-gate * nodev returns ENXIO anyway. 2881*7c478bd9Sstevel@tonic-gate */ 2882*7c478bd9Sstevel@tonic-gate if (aio_func == nodev) 2883*7c478bd9Sstevel@tonic-gate return (NULL); 2884*7c478bd9Sstevel@tonic-gate 2885*7c478bd9Sstevel@tonic-gate sp = VTOS(vp); 2886*7c478bd9Sstevel@tonic-gate smark(sp, SACC); 2887*7c478bd9Sstevel@tonic-gate return (aio_func); 2888*7c478bd9Sstevel@tonic-gate } 2889*7c478bd9Sstevel@tonic-gate 2890*7c478bd9Sstevel@tonic-gate /* 2891*7c478bd9Sstevel@tonic-gate * Clustering: We want check_vp to return a function prototyped 2892*7c478bd9Sstevel@tonic-gate * correctly that will be common to both PXFS and regular case. 2893*7c478bd9Sstevel@tonic-gate * We define this intermediate function that will do the right 2894*7c478bd9Sstevel@tonic-gate * thing for driver cases. 2895*7c478bd9Sstevel@tonic-gate */ 2896*7c478bd9Sstevel@tonic-gate 2897*7c478bd9Sstevel@tonic-gate static int 2898*7c478bd9Sstevel@tonic-gate driver_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p) 2899*7c478bd9Sstevel@tonic-gate { 2900*7c478bd9Sstevel@tonic-gate dev_t dev; 2901*7c478bd9Sstevel@tonic-gate struct cb_ops *cb; 2902*7c478bd9Sstevel@tonic-gate 2903*7c478bd9Sstevel@tonic-gate ASSERT(vp->v_type == VCHR); 2904*7c478bd9Sstevel@tonic-gate ASSERT(!IS_PXFSVP(vp)); 2905*7c478bd9Sstevel@tonic-gate dev = VTOS(vp)->s_dev; 2906*7c478bd9Sstevel@tonic-gate ASSERT(STREAMSTAB(getmajor(dev)) == NULL); 2907*7c478bd9Sstevel@tonic-gate 2908*7c478bd9Sstevel@tonic-gate cb = devopsp[getmajor(dev)]->devo_cb_ops; 2909*7c478bd9Sstevel@tonic-gate 2910*7c478bd9Sstevel@tonic-gate ASSERT(cb->cb_awrite != nodev); 2911*7c478bd9Sstevel@tonic-gate return ((*cb->cb_awrite)(dev, aio, cred_p)); 2912*7c478bd9Sstevel@tonic-gate } 2913*7c478bd9Sstevel@tonic-gate 2914*7c478bd9Sstevel@tonic-gate /* 2915*7c478bd9Sstevel@tonic-gate * Clustering: We want check_vp to return a function prototyped 2916*7c478bd9Sstevel@tonic-gate * correctly that will be common to both PXFS and regular case. 2917*7c478bd9Sstevel@tonic-gate * We define this intermediate function that will do the right 2918*7c478bd9Sstevel@tonic-gate * thing for driver cases. 2919*7c478bd9Sstevel@tonic-gate */ 2920*7c478bd9Sstevel@tonic-gate 2921*7c478bd9Sstevel@tonic-gate static int 2922*7c478bd9Sstevel@tonic-gate driver_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p) 2923*7c478bd9Sstevel@tonic-gate { 2924*7c478bd9Sstevel@tonic-gate dev_t dev; 2925*7c478bd9Sstevel@tonic-gate struct cb_ops *cb; 2926*7c478bd9Sstevel@tonic-gate 2927*7c478bd9Sstevel@tonic-gate ASSERT(vp->v_type == VCHR); 2928*7c478bd9Sstevel@tonic-gate ASSERT(!IS_PXFSVP(vp)); 2929*7c478bd9Sstevel@tonic-gate dev = VTOS(vp)->s_dev; 2930*7c478bd9Sstevel@tonic-gate ASSERT(!STREAMSTAB(getmajor(dev))); 2931*7c478bd9Sstevel@tonic-gate 2932*7c478bd9Sstevel@tonic-gate cb = devopsp[getmajor(dev)]->devo_cb_ops; 2933*7c478bd9Sstevel@tonic-gate 2934*7c478bd9Sstevel@tonic-gate ASSERT(cb->cb_aread != nodev); 2935*7c478bd9Sstevel@tonic-gate return ((*cb->cb_aread)(dev, aio, cred_p)); 2936*7c478bd9Sstevel@tonic-gate } 2937*7c478bd9Sstevel@tonic-gate 2938*7c478bd9Sstevel@tonic-gate /* 2939*7c478bd9Sstevel@tonic-gate * This routine is called when a largefile call is made by a 32bit 2940*7c478bd9Sstevel@tonic-gate * process on a ILP32 or LP64 kernel. All 64bit processes are large 2941*7c478bd9Sstevel@tonic-gate * file by definition and will call alio() instead. 2942*7c478bd9Sstevel@tonic-gate */ 2943*7c478bd9Sstevel@tonic-gate static int 2944*7c478bd9Sstevel@tonic-gate alioLF( 2945*7c478bd9Sstevel@tonic-gate int mode_arg, 2946*7c478bd9Sstevel@tonic-gate void *aiocb_arg, 2947*7c478bd9Sstevel@tonic-gate int nent, 2948*7c478bd9Sstevel@tonic-gate void *sigev) 2949*7c478bd9Sstevel@tonic-gate { 2950*7c478bd9Sstevel@tonic-gate file_t *fp; 2951*7c478bd9Sstevel@tonic-gate file_t *prev_fp = NULL; 2952*7c478bd9Sstevel@tonic-gate int prev_mode = -1; 2953*7c478bd9Sstevel@tonic-gate struct vnode *vp; 2954*7c478bd9Sstevel@tonic-gate aio_lio_t *head; 2955*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 2956*7c478bd9Sstevel@tonic-gate aio_t *aiop; 2957*7c478bd9Sstevel@tonic-gate caddr_t cbplist; 2958*7c478bd9Sstevel@tonic-gate aiocb64_32_t *cbp; 2959*7c478bd9Sstevel@tonic-gate caddr32_t *ucbp; 2960*7c478bd9Sstevel@tonic-gate aiocb64_32_t cb64; 2961*7c478bd9Sstevel@tonic-gate aiocb64_32_t *aiocb = &cb64; 2962*7c478bd9Sstevel@tonic-gate #ifdef _LP64 2963*7c478bd9Sstevel@tonic-gate aiocb_t aiocb_n; 2964*7c478bd9Sstevel@tonic-gate #endif 2965*7c478bd9Sstevel@tonic-gate struct sigevent32 sigevk; 2966*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 2967*7c478bd9Sstevel@tonic-gate int (*aio_func)(); 2968*7c478bd9Sstevel@tonic-gate int mode; 2969*7c478bd9Sstevel@tonic-gate int error = 0, aio_errors = 0; 2970*7c478bd9Sstevel@tonic-gate int i; 2971*7c478bd9Sstevel@tonic-gate size_t ssize; 2972*7c478bd9Sstevel@tonic-gate int deadhead = 0; 2973*7c478bd9Sstevel@tonic-gate int aio_notsupported = 0; 2974*7c478bd9Sstevel@tonic-gate int aio_use_port = 0; 2975*7c478bd9Sstevel@tonic-gate port_kevent_t *pkevtp = NULL; 2976*7c478bd9Sstevel@tonic-gate port_notify32_t pnotify; 2977*7c478bd9Sstevel@tonic-gate 2978*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 2979*7c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX) 2980*7c478bd9Sstevel@tonic-gate return (EINVAL); 2981*7c478bd9Sstevel@tonic-gate 2982*7c478bd9Sstevel@tonic-gate ASSERT(get_udatamodel() == DATAMODEL_ILP32); 2983*7c478bd9Sstevel@tonic-gate 2984*7c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent); 2985*7c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP); 2986*7c478bd9Sstevel@tonic-gate ucbp = (caddr32_t *)cbplist; 2987*7c478bd9Sstevel@tonic-gate 2988*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, cbplist, ssize)) { 2989*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 2990*7c478bd9Sstevel@tonic-gate return (EFAULT); 2991*7c478bd9Sstevel@tonic-gate } 2992*7c478bd9Sstevel@tonic-gate 2993*7c478bd9Sstevel@tonic-gate if (sigev) { 2994*7c478bd9Sstevel@tonic-gate if (copyin(sigev, &sigevk, sizeof (sigevk))) { 2995*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 2996*7c478bd9Sstevel@tonic-gate return (EFAULT); 2997*7c478bd9Sstevel@tonic-gate } 2998*7c478bd9Sstevel@tonic-gate } 2999*7c478bd9Sstevel@tonic-gate 3000*7c478bd9Sstevel@tonic-gate /* 3001*7c478bd9Sstevel@tonic-gate * a list head should be allocated if notification is 3002*7c478bd9Sstevel@tonic-gate * enabled for this list. 3003*7c478bd9Sstevel@tonic-gate */ 3004*7c478bd9Sstevel@tonic-gate head = NULL; 3005*7c478bd9Sstevel@tonic-gate 3006*7c478bd9Sstevel@tonic-gate /* Event Ports */ 3007*7c478bd9Sstevel@tonic-gate 3008*7c478bd9Sstevel@tonic-gate if (sigev && sigevk.sigev_notify == SIGEV_PORT) { 3009*7c478bd9Sstevel@tonic-gate /* Use PORT for completion notification */ 3010*7c478bd9Sstevel@tonic-gate if (copyin((void *)(uintptr_t)sigevk.sigev_value.sival_ptr, 3011*7c478bd9Sstevel@tonic-gate &pnotify, sizeof (port_notify32_t))) { 3012*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3013*7c478bd9Sstevel@tonic-gate return (EFAULT); 3014*7c478bd9Sstevel@tonic-gate } 3015*7c478bd9Sstevel@tonic-gate /* use event ports for the list of aiocbs */ 3016*7c478bd9Sstevel@tonic-gate aio_use_port = 1; 3017*7c478bd9Sstevel@tonic-gate error = port_alloc_event(pnotify.portnfy_port, 3018*7c478bd9Sstevel@tonic-gate PORT_ALLOC_PRIVATE, PORT_SOURCE_AIO, &pkevtp); 3019*7c478bd9Sstevel@tonic-gate if (error) { 3020*7c478bd9Sstevel@tonic-gate if (error == ENOMEM) 3021*7c478bd9Sstevel@tonic-gate error = EAGAIN; 3022*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3023*7c478bd9Sstevel@tonic-gate return (error); 3024*7c478bd9Sstevel@tonic-gate } 3025*7c478bd9Sstevel@tonic-gate } else if ((mode_arg == LIO_WAIT) || sigev) { 3026*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3027*7c478bd9Sstevel@tonic-gate error = aio_lio_alloc(&head); 3028*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3029*7c478bd9Sstevel@tonic-gate if (error) 3030*7c478bd9Sstevel@tonic-gate goto done; 3031*7c478bd9Sstevel@tonic-gate deadhead = 1; 3032*7c478bd9Sstevel@tonic-gate head->lio_nent = nent; 3033*7c478bd9Sstevel@tonic-gate head->lio_refcnt = nent; 3034*7c478bd9Sstevel@tonic-gate if (sigev && (sigevk.sigev_notify == SIGEV_SIGNAL) && 3035*7c478bd9Sstevel@tonic-gate (sigevk.sigev_signo > 0 && sigevk.sigev_signo < NSIG)) { 3036*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP); 3037*7c478bd9Sstevel@tonic-gate if (sqp == NULL) { 3038*7c478bd9Sstevel@tonic-gate error = EAGAIN; 3039*7c478bd9Sstevel@tonic-gate goto done; 3040*7c478bd9Sstevel@tonic-gate } 3041*7c478bd9Sstevel@tonic-gate sqp->sq_func = NULL; 3042*7c478bd9Sstevel@tonic-gate sqp->sq_next = NULL; 3043*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO; 3044*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid; 3045*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc); 3046*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 3047*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred); 3048*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigevk.sigev_signo; 3049*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_value.sival_int = 3050*7c478bd9Sstevel@tonic-gate sigevk.sigev_value.sival_int; 3051*7c478bd9Sstevel@tonic-gate head->lio_sigqp = sqp; 3052*7c478bd9Sstevel@tonic-gate } else { 3053*7c478bd9Sstevel@tonic-gate head->lio_sigqp = NULL; 3054*7c478bd9Sstevel@tonic-gate } 3055*7c478bd9Sstevel@tonic-gate } 3056*7c478bd9Sstevel@tonic-gate 3057*7c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++, ucbp++) { 3058*7c478bd9Sstevel@tonic-gate 3059*7c478bd9Sstevel@tonic-gate cbp = (aiocb64_32_t *)(uintptr_t)*ucbp; 3060*7c478bd9Sstevel@tonic-gate /* skip entry if it can't be copied. */ 3061*7c478bd9Sstevel@tonic-gate if (cbp == NULL || copyin(cbp, aiocb, sizeof (aiocb64_32_t))) { 3062*7c478bd9Sstevel@tonic-gate if (head) { 3063*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3064*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3065*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3066*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3067*7c478bd9Sstevel@tonic-gate } 3068*7c478bd9Sstevel@tonic-gate continue; 3069*7c478bd9Sstevel@tonic-gate } 3070*7c478bd9Sstevel@tonic-gate 3071*7c478bd9Sstevel@tonic-gate /* skip if opcode for aiocb is LIO_NOP */ 3072*7c478bd9Sstevel@tonic-gate 3073*7c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode; 3074*7c478bd9Sstevel@tonic-gate if (mode == LIO_NOP) { 3075*7c478bd9Sstevel@tonic-gate cbp = NULL; 3076*7c478bd9Sstevel@tonic-gate if (head) { 3077*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3078*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3079*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3080*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3081*7c478bd9Sstevel@tonic-gate } 3082*7c478bd9Sstevel@tonic-gate continue; 3083*7c478bd9Sstevel@tonic-gate } 3084*7c478bd9Sstevel@tonic-gate 3085*7c478bd9Sstevel@tonic-gate /* increment file descriptor's ref count. */ 3086*7c478bd9Sstevel@tonic-gate if ((fp = getf(aiocb->aio_fildes)) == NULL) { 3087*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF); 3088*7c478bd9Sstevel@tonic-gate if (head) { 3089*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3090*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3091*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3092*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3093*7c478bd9Sstevel@tonic-gate } 3094*7c478bd9Sstevel@tonic-gate aio_errors++; 3095*7c478bd9Sstevel@tonic-gate continue; 3096*7c478bd9Sstevel@tonic-gate } 3097*7c478bd9Sstevel@tonic-gate 3098*7c478bd9Sstevel@tonic-gate vp = fp->f_vnode; 3099*7c478bd9Sstevel@tonic-gate 3100*7c478bd9Sstevel@tonic-gate /* 3101*7c478bd9Sstevel@tonic-gate * check the permission of the partition 3102*7c478bd9Sstevel@tonic-gate */ 3103*7c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode; 3104*7c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) { 3105*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3106*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF); 3107*7c478bd9Sstevel@tonic-gate if (head) { 3108*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3109*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3110*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3111*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3112*7c478bd9Sstevel@tonic-gate } 3113*7c478bd9Sstevel@tonic-gate aio_errors++; 3114*7c478bd9Sstevel@tonic-gate continue; 3115*7c478bd9Sstevel@tonic-gate } 3116*7c478bd9Sstevel@tonic-gate 3117*7c478bd9Sstevel@tonic-gate /* 3118*7c478bd9Sstevel@tonic-gate * common case where requests are to the same fd 3119*7c478bd9Sstevel@tonic-gate * for the same r/w operation 3120*7c478bd9Sstevel@tonic-gate * for UFS, need to set EBADFD 3121*7c478bd9Sstevel@tonic-gate */ 3122*7c478bd9Sstevel@tonic-gate if ((fp != prev_fp) || (mode != prev_mode)) { 3123*7c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode); 3124*7c478bd9Sstevel@tonic-gate if (aio_func == NULL) { 3125*7c478bd9Sstevel@tonic-gate prev_fp = NULL; 3126*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3127*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADFD); 3128*7c478bd9Sstevel@tonic-gate aio_notsupported++; 3129*7c478bd9Sstevel@tonic-gate if (head) { 3130*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3131*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3132*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3133*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3134*7c478bd9Sstevel@tonic-gate } 3135*7c478bd9Sstevel@tonic-gate continue; 3136*7c478bd9Sstevel@tonic-gate } else { 3137*7c478bd9Sstevel@tonic-gate prev_fp = fp; 3138*7c478bd9Sstevel@tonic-gate prev_mode = mode; 3139*7c478bd9Sstevel@tonic-gate } 3140*7c478bd9Sstevel@tonic-gate } 3141*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3142*7c478bd9Sstevel@tonic-gate aiocb_LFton(aiocb, &aiocb_n); 3143*7c478bd9Sstevel@tonic-gate error = aio_req_setup(&reqp, aiop, &aiocb_n, 3144*7c478bd9Sstevel@tonic-gate (aio_result_t *)&cbp->aio_resultp, aio_use_port, vp); 3145*7c478bd9Sstevel@tonic-gate #else 3146*7c478bd9Sstevel@tonic-gate error = aio_req_setupLF(&reqp, aiop, aiocb, 3147*7c478bd9Sstevel@tonic-gate (aio_result_t *)&cbp->aio_resultp, aio_use_port, vp); 3148*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 3149*7c478bd9Sstevel@tonic-gate if (error) { 3150*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3151*7c478bd9Sstevel@tonic-gate if (head) { 3152*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3153*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3154*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3155*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3156*7c478bd9Sstevel@tonic-gate } 3157*7c478bd9Sstevel@tonic-gate aio_errors++; 3158*7c478bd9Sstevel@tonic-gate continue; 3159*7c478bd9Sstevel@tonic-gate } 3160*7c478bd9Sstevel@tonic-gate 3161*7c478bd9Sstevel@tonic-gate reqp->aio_req_lio = head; 3162*7c478bd9Sstevel@tonic-gate deadhead = 0; 3163*7c478bd9Sstevel@tonic-gate 3164*7c478bd9Sstevel@tonic-gate /* 3165*7c478bd9Sstevel@tonic-gate * Set the errno field now before sending the request to 3166*7c478bd9Sstevel@tonic-gate * the driver to avoid a race condition 3167*7c478bd9Sstevel@tonic-gate */ 3168*7c478bd9Sstevel@tonic-gate (void) suword32(&cbp->aio_resultp.aio_errno, 3169*7c478bd9Sstevel@tonic-gate EINPROGRESS); 3170*7c478bd9Sstevel@tonic-gate 3171*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32 = *ucbp; 3172*7c478bd9Sstevel@tonic-gate 3173*7c478bd9Sstevel@tonic-gate if (aio_use_port) { 3174*7c478bd9Sstevel@tonic-gate reqp->aio_req_port = pnotify.portnfy_port; 3175*7c478bd9Sstevel@tonic-gate error = aio_req_assoc_port32(&aiocb->aio_sigevent, 3176*7c478bd9Sstevel@tonic-gate (void *)(uintptr_t)pnotify.portnfy_user, 3177*7c478bd9Sstevel@tonic-gate (aiocb_t *)(uintptr_t)*ucbp, reqp, pkevtp); 3178*7c478bd9Sstevel@tonic-gate } 3179*7c478bd9Sstevel@tonic-gate 3180*7c478bd9Sstevel@tonic-gate /* 3181*7c478bd9Sstevel@tonic-gate * send the request to driver. 3182*7c478bd9Sstevel@tonic-gate * Clustering: If PXFS vnode, call PXFS function. 3183*7c478bd9Sstevel@tonic-gate */ 3184*7c478bd9Sstevel@tonic-gate if (error == 0) { 3185*7c478bd9Sstevel@tonic-gate if (aiocb->aio_nbytes == 0) { 3186*7c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes); 3187*7c478bd9Sstevel@tonic-gate aio_zerolen(reqp); 3188*7c478bd9Sstevel@tonic-gate continue; 3189*7c478bd9Sstevel@tonic-gate } 3190*7c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, 3191*7c478bd9Sstevel@tonic-gate CRED()); 3192*7c478bd9Sstevel@tonic-gate } 3193*7c478bd9Sstevel@tonic-gate 3194*7c478bd9Sstevel@tonic-gate /* 3195*7c478bd9Sstevel@tonic-gate * the fd's ref count is not decremented until the IO has 3196*7c478bd9Sstevel@tonic-gate * completed unless there was an error. 3197*7c478bd9Sstevel@tonic-gate */ 3198*7c478bd9Sstevel@tonic-gate if (error) { 3199*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3200*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error); 3201*7c478bd9Sstevel@tonic-gate if (head) { 3202*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3203*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3204*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3205*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3206*7c478bd9Sstevel@tonic-gate } 3207*7c478bd9Sstevel@tonic-gate if (error == ENOTSUP) 3208*7c478bd9Sstevel@tonic-gate aio_notsupported++; 3209*7c478bd9Sstevel@tonic-gate else 3210*7c478bd9Sstevel@tonic-gate aio_errors++; 3211*7c478bd9Sstevel@tonic-gate lio_set_error(reqp); 3212*7c478bd9Sstevel@tonic-gate } else { 3213*7c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes); 3214*7c478bd9Sstevel@tonic-gate } 3215*7c478bd9Sstevel@tonic-gate } 3216*7c478bd9Sstevel@tonic-gate 3217*7c478bd9Sstevel@tonic-gate if (pkevtp) 3218*7c478bd9Sstevel@tonic-gate port_free_event(pkevtp); 3219*7c478bd9Sstevel@tonic-gate 3220*7c478bd9Sstevel@tonic-gate if (aio_notsupported) { 3221*7c478bd9Sstevel@tonic-gate error = ENOTSUP; 3222*7c478bd9Sstevel@tonic-gate } else if (aio_errors) { 3223*7c478bd9Sstevel@tonic-gate /* 3224*7c478bd9Sstevel@tonic-gate * return EIO if any request failed 3225*7c478bd9Sstevel@tonic-gate */ 3226*7c478bd9Sstevel@tonic-gate error = EIO; 3227*7c478bd9Sstevel@tonic-gate } 3228*7c478bd9Sstevel@tonic-gate 3229*7c478bd9Sstevel@tonic-gate if (mode_arg == LIO_WAIT) { 3230*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3231*7c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) { 3232*7c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) { 3233*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3234*7c478bd9Sstevel@tonic-gate error = EINTR; 3235*7c478bd9Sstevel@tonic-gate goto done; 3236*7c478bd9Sstevel@tonic-gate } 3237*7c478bd9Sstevel@tonic-gate } 3238*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3239*7c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, AIO_LARGEFILE); 3240*7c478bd9Sstevel@tonic-gate } 3241*7c478bd9Sstevel@tonic-gate 3242*7c478bd9Sstevel@tonic-gate done: 3243*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3244*7c478bd9Sstevel@tonic-gate if (deadhead) { 3245*7c478bd9Sstevel@tonic-gate if (head->lio_sigqp) 3246*7c478bd9Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t)); 3247*7c478bd9Sstevel@tonic-gate kmem_free(head, sizeof (aio_lio_t)); 3248*7c478bd9Sstevel@tonic-gate } 3249*7c478bd9Sstevel@tonic-gate return (error); 3250*7c478bd9Sstevel@tonic-gate } 3251*7c478bd9Sstevel@tonic-gate 3252*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 3253*7c478bd9Sstevel@tonic-gate static void 3254*7c478bd9Sstevel@tonic-gate aiocb_LFton(aiocb64_32_t *src, aiocb_t *dest) 3255*7c478bd9Sstevel@tonic-gate { 3256*7c478bd9Sstevel@tonic-gate dest->aio_fildes = src->aio_fildes; 3257*7c478bd9Sstevel@tonic-gate dest->aio_buf = (void *)(uintptr_t)src->aio_buf; 3258*7c478bd9Sstevel@tonic-gate dest->aio_nbytes = (size_t)src->aio_nbytes; 3259*7c478bd9Sstevel@tonic-gate dest->aio_offset = (off_t)src->aio_offset; 3260*7c478bd9Sstevel@tonic-gate dest->aio_reqprio = src->aio_reqprio; 3261*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify = src->aio_sigevent.sigev_notify; 3262*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_signo = src->aio_sigevent.sigev_signo; 3263*7c478bd9Sstevel@tonic-gate 3264*7c478bd9Sstevel@tonic-gate /* 3265*7c478bd9Sstevel@tonic-gate * See comment in sigqueue32() on handling of 32-bit 3266*7c478bd9Sstevel@tonic-gate * sigvals in a 64-bit kernel. 3267*7c478bd9Sstevel@tonic-gate */ 3268*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_value.sival_int = 3269*7c478bd9Sstevel@tonic-gate (int)src->aio_sigevent.sigev_value.sival_int; 3270*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_function = (void (*)(union sigval)) 3271*7c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_function; 3272*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_attributes = (pthread_attr_t *) 3273*7c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_attributes; 3274*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.__sigev_pad2 = src->aio_sigevent.__sigev_pad2; 3275*7c478bd9Sstevel@tonic-gate dest->aio_lio_opcode = src->aio_lio_opcode; 3276*7c478bd9Sstevel@tonic-gate dest->aio_state = src->aio_state; 3277*7c478bd9Sstevel@tonic-gate dest->aio__pad[0] = src->aio__pad[0]; 3278*7c478bd9Sstevel@tonic-gate } 3279*7c478bd9Sstevel@tonic-gate #endif 3280*7c478bd9Sstevel@tonic-gate 3281*7c478bd9Sstevel@tonic-gate /* 3282*7c478bd9Sstevel@tonic-gate * This function is used only for largefile calls made by 3283*7c478bd9Sstevel@tonic-gate * 32 bit applications on 32 bit kernel. 3284*7c478bd9Sstevel@tonic-gate */ 3285*7c478bd9Sstevel@tonic-gate static int 3286*7c478bd9Sstevel@tonic-gate aio_req_setupLF( 3287*7c478bd9Sstevel@tonic-gate aio_req_t **reqpp, 3288*7c478bd9Sstevel@tonic-gate aio_t *aiop, 3289*7c478bd9Sstevel@tonic-gate aiocb64_32_t *arg, 3290*7c478bd9Sstevel@tonic-gate aio_result_t *resultp, 3291*7c478bd9Sstevel@tonic-gate int port, 3292*7c478bd9Sstevel@tonic-gate vnode_t *vp) 3293*7c478bd9Sstevel@tonic-gate { 3294*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 3295*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 3296*7c478bd9Sstevel@tonic-gate struct uio *uio; 3297*7c478bd9Sstevel@tonic-gate 3298*7c478bd9Sstevel@tonic-gate struct sigevent *sigev; 3299*7c478bd9Sstevel@tonic-gate int error; 3300*7c478bd9Sstevel@tonic-gate 3301*7c478bd9Sstevel@tonic-gate sigev = (struct sigevent *)&arg->aio_sigevent; 3302*7c478bd9Sstevel@tonic-gate if ((sigev->sigev_notify == SIGEV_SIGNAL) && 3303*7c478bd9Sstevel@tonic-gate (sigev->sigev_signo > 0 && sigev->sigev_signo < NSIG)) { 3304*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP); 3305*7c478bd9Sstevel@tonic-gate if (sqp == NULL) 3306*7c478bd9Sstevel@tonic-gate return (EAGAIN); 3307*7c478bd9Sstevel@tonic-gate sqp->sq_func = NULL; 3308*7c478bd9Sstevel@tonic-gate sqp->sq_next = NULL; 3309*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO; 3310*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid; 3311*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc); 3312*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 3313*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred); 3314*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigev->sigev_signo; 3315*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_value = sigev->sigev_value; 3316*7c478bd9Sstevel@tonic-gate } else 3317*7c478bd9Sstevel@tonic-gate sqp = NULL; 3318*7c478bd9Sstevel@tonic-gate 3319*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3320*7c478bd9Sstevel@tonic-gate 3321*7c478bd9Sstevel@tonic-gate if (aiop->aio_flags & AIO_REQ_BLOCK) { 3322*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3323*7c478bd9Sstevel@tonic-gate if (sqp) 3324*7c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t)); 3325*7c478bd9Sstevel@tonic-gate return (EIO); 3326*7c478bd9Sstevel@tonic-gate } 3327*7c478bd9Sstevel@tonic-gate /* 3328*7c478bd9Sstevel@tonic-gate * get an aio_reqp from the free list or allocate one 3329*7c478bd9Sstevel@tonic-gate * from dynamic memory. 3330*7c478bd9Sstevel@tonic-gate */ 3331*7c478bd9Sstevel@tonic-gate if (error = aio_req_alloc(&reqp, resultp)) { 3332*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3333*7c478bd9Sstevel@tonic-gate if (sqp) 3334*7c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t)); 3335*7c478bd9Sstevel@tonic-gate return (error); 3336*7c478bd9Sstevel@tonic-gate } 3337*7c478bd9Sstevel@tonic-gate aiop->aio_pending++; 3338*7c478bd9Sstevel@tonic-gate aiop->aio_outstanding++; 3339*7c478bd9Sstevel@tonic-gate reqp->aio_req_flags = AIO_PENDING; 3340*7c478bd9Sstevel@tonic-gate if (port) 3341*7c478bd9Sstevel@tonic-gate aio_enq_port_pending(aiop, reqp); 3342*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3343*7c478bd9Sstevel@tonic-gate /* 3344*7c478bd9Sstevel@tonic-gate * initialize aio request. 3345*7c478bd9Sstevel@tonic-gate */ 3346*7c478bd9Sstevel@tonic-gate reqp->aio_req_fd = arg->aio_fildes; 3347*7c478bd9Sstevel@tonic-gate reqp->aio_req_sigqp = sqp; 3348*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb = NULL; 3349*7c478bd9Sstevel@tonic-gate reqp->aio_req_buf.b_file = vp; 3350*7c478bd9Sstevel@tonic-gate uio = reqp->aio_req.aio_uio; 3351*7c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1; 3352*7c478bd9Sstevel@tonic-gate uio->uio_iov->iov_base = (caddr_t)(uintptr_t)arg->aio_buf; 3353*7c478bd9Sstevel@tonic-gate uio->uio_iov->iov_len = arg->aio_nbytes; 3354*7c478bd9Sstevel@tonic-gate uio->uio_loffset = arg->aio_offset; 3355*7c478bd9Sstevel@tonic-gate *reqpp = reqp; 3356*7c478bd9Sstevel@tonic-gate return (0); 3357*7c478bd9Sstevel@tonic-gate } 3358*7c478bd9Sstevel@tonic-gate 3359*7c478bd9Sstevel@tonic-gate /* 3360*7c478bd9Sstevel@tonic-gate * This routine is called when a non largefile call is made by a 32bit 3361*7c478bd9Sstevel@tonic-gate * process on a ILP32 or LP64 kernel. 3362*7c478bd9Sstevel@tonic-gate */ 3363*7c478bd9Sstevel@tonic-gate static int 3364*7c478bd9Sstevel@tonic-gate alio32( 3365*7c478bd9Sstevel@tonic-gate int mode_arg, 3366*7c478bd9Sstevel@tonic-gate void *aiocb_arg, 3367*7c478bd9Sstevel@tonic-gate int nent, 3368*7c478bd9Sstevel@tonic-gate void *sigev_arg) 3369*7c478bd9Sstevel@tonic-gate { 3370*7c478bd9Sstevel@tonic-gate file_t *fp; 3371*7c478bd9Sstevel@tonic-gate file_t *prev_fp = NULL; 3372*7c478bd9Sstevel@tonic-gate int prev_mode = -1; 3373*7c478bd9Sstevel@tonic-gate struct vnode *vp; 3374*7c478bd9Sstevel@tonic-gate aio_lio_t *head; 3375*7c478bd9Sstevel@tonic-gate aio_req_t *reqp; 3376*7c478bd9Sstevel@tonic-gate aio_t *aiop; 3377*7c478bd9Sstevel@tonic-gate aiocb_t cb; 3378*7c478bd9Sstevel@tonic-gate aiocb_t *aiocb = &cb; 3379*7c478bd9Sstevel@tonic-gate caddr_t cbplist; 3380*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3381*7c478bd9Sstevel@tonic-gate aiocb32_t *cbp; 3382*7c478bd9Sstevel@tonic-gate caddr32_t *ucbp; 3383*7c478bd9Sstevel@tonic-gate aiocb32_t cb32; 3384*7c478bd9Sstevel@tonic-gate aiocb32_t *aiocb32 = &cb32; 3385*7c478bd9Sstevel@tonic-gate struct sigevent32 sigev; 3386*7c478bd9Sstevel@tonic-gate #else 3387*7c478bd9Sstevel@tonic-gate aiocb_t *cbp, **ucbp; 3388*7c478bd9Sstevel@tonic-gate struct sigevent sigev; 3389*7c478bd9Sstevel@tonic-gate #endif 3390*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 3391*7c478bd9Sstevel@tonic-gate int (*aio_func)(); 3392*7c478bd9Sstevel@tonic-gate int mode; 3393*7c478bd9Sstevel@tonic-gate int error = 0, aio_errors = 0; 3394*7c478bd9Sstevel@tonic-gate int i; 3395*7c478bd9Sstevel@tonic-gate size_t ssize; 3396*7c478bd9Sstevel@tonic-gate int deadhead = 0; 3397*7c478bd9Sstevel@tonic-gate int aio_notsupported = 0; 3398*7c478bd9Sstevel@tonic-gate int aio_use_port = 0; 3399*7c478bd9Sstevel@tonic-gate port_kevent_t *pkevtp = NULL; 3400*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3401*7c478bd9Sstevel@tonic-gate port_notify32_t pnotify; 3402*7c478bd9Sstevel@tonic-gate #else 3403*7c478bd9Sstevel@tonic-gate port_notify_t pnotify; 3404*7c478bd9Sstevel@tonic-gate #endif 3405*7c478bd9Sstevel@tonic-gate aiop = curproc->p_aio; 3406*7c478bd9Sstevel@tonic-gate if (aiop == NULL || nent <= 0 || nent > _AIO_LISTIO_MAX) 3407*7c478bd9Sstevel@tonic-gate return (EINVAL); 3408*7c478bd9Sstevel@tonic-gate 3409*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3410*7c478bd9Sstevel@tonic-gate ssize = (sizeof (caddr32_t) * nent); 3411*7c478bd9Sstevel@tonic-gate #else 3412*7c478bd9Sstevel@tonic-gate ssize = (sizeof (aiocb_t *) * nent); 3413*7c478bd9Sstevel@tonic-gate #endif 3414*7c478bd9Sstevel@tonic-gate cbplist = kmem_alloc(ssize, KM_SLEEP); 3415*7c478bd9Sstevel@tonic-gate ucbp = (void *)cbplist; 3416*7c478bd9Sstevel@tonic-gate 3417*7c478bd9Sstevel@tonic-gate if (copyin(aiocb_arg, cbplist, ssize)) { 3418*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3419*7c478bd9Sstevel@tonic-gate return (EFAULT); 3420*7c478bd9Sstevel@tonic-gate } 3421*7c478bd9Sstevel@tonic-gate 3422*7c478bd9Sstevel@tonic-gate if (sigev_arg) { 3423*7c478bd9Sstevel@tonic-gate if (copyin(sigev_arg, &sigev, sizeof (struct sigevent32))) { 3424*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3425*7c478bd9Sstevel@tonic-gate return (EFAULT); 3426*7c478bd9Sstevel@tonic-gate } 3427*7c478bd9Sstevel@tonic-gate } 3428*7c478bd9Sstevel@tonic-gate 3429*7c478bd9Sstevel@tonic-gate /* 3430*7c478bd9Sstevel@tonic-gate * a list head should be allocated if notification is 3431*7c478bd9Sstevel@tonic-gate * enabled for this list. 3432*7c478bd9Sstevel@tonic-gate */ 3433*7c478bd9Sstevel@tonic-gate head = NULL; 3434*7c478bd9Sstevel@tonic-gate 3435*7c478bd9Sstevel@tonic-gate /* Event Ports */ 3436*7c478bd9Sstevel@tonic-gate 3437*7c478bd9Sstevel@tonic-gate if (sigev_arg && sigev.sigev_notify == SIGEV_PORT) { 3438*7c478bd9Sstevel@tonic-gate /* Use PORT for completion notification */ 3439*7c478bd9Sstevel@tonic-gate if (copyin((void *)(uintptr_t)sigev.sigev_value.sival_ptr, 3440*7c478bd9Sstevel@tonic-gate &pnotify, sizeof (port_notify32_t))) { 3441*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3442*7c478bd9Sstevel@tonic-gate return (EFAULT); 3443*7c478bd9Sstevel@tonic-gate } 3444*7c478bd9Sstevel@tonic-gate /* use event ports for the list of aiocbs */ 3445*7c478bd9Sstevel@tonic-gate aio_use_port = 1; 3446*7c478bd9Sstevel@tonic-gate error = port_alloc_event(pnotify.portnfy_port, 3447*7c478bd9Sstevel@tonic-gate PORT_ALLOC_PRIVATE, PORT_SOURCE_AIO, &pkevtp); 3448*7c478bd9Sstevel@tonic-gate if (error) { 3449*7c478bd9Sstevel@tonic-gate if ((error == ENOMEM) || (error == EAGAIN)) 3450*7c478bd9Sstevel@tonic-gate error = EAGAIN; 3451*7c478bd9Sstevel@tonic-gate else 3452*7c478bd9Sstevel@tonic-gate error = EINVAL; 3453*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3454*7c478bd9Sstevel@tonic-gate return (error); 3455*7c478bd9Sstevel@tonic-gate } 3456*7c478bd9Sstevel@tonic-gate } else if ((mode_arg == LIO_WAIT) || sigev_arg) { 3457*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3458*7c478bd9Sstevel@tonic-gate error = aio_lio_alloc(&head); 3459*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3460*7c478bd9Sstevel@tonic-gate if (error) 3461*7c478bd9Sstevel@tonic-gate goto done; 3462*7c478bd9Sstevel@tonic-gate deadhead = 1; 3463*7c478bd9Sstevel@tonic-gate head->lio_nent = nent; 3464*7c478bd9Sstevel@tonic-gate head->lio_refcnt = nent; 3465*7c478bd9Sstevel@tonic-gate if (sigev_arg && (sigev.sigev_notify == SIGEV_SIGNAL) && 3466*7c478bd9Sstevel@tonic-gate (sigev.sigev_signo > 0 && sigev.sigev_signo < NSIG)) { 3467*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_NOSLEEP); 3468*7c478bd9Sstevel@tonic-gate if (sqp == NULL) { 3469*7c478bd9Sstevel@tonic-gate error = EAGAIN; 3470*7c478bd9Sstevel@tonic-gate goto done; 3471*7c478bd9Sstevel@tonic-gate } 3472*7c478bd9Sstevel@tonic-gate sqp->sq_func = NULL; 3473*7c478bd9Sstevel@tonic-gate sqp->sq_next = NULL; 3474*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = SI_ASYNCIO; 3475*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = curproc->p_pid; 3476*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(curproc); 3477*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 3478*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetuid(curproc->p_cred); 3479*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = sigev.sigev_signo; 3480*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_value.sival_int = 3481*7c478bd9Sstevel@tonic-gate sigev.sigev_value.sival_int; 3482*7c478bd9Sstevel@tonic-gate head->lio_sigqp = sqp; 3483*7c478bd9Sstevel@tonic-gate } else { 3484*7c478bd9Sstevel@tonic-gate head->lio_sigqp = NULL; 3485*7c478bd9Sstevel@tonic-gate } 3486*7c478bd9Sstevel@tonic-gate } 3487*7c478bd9Sstevel@tonic-gate 3488*7c478bd9Sstevel@tonic-gate for (i = 0; i < nent; i++, ucbp++) { 3489*7c478bd9Sstevel@tonic-gate 3490*7c478bd9Sstevel@tonic-gate /* skip entry if it can't be copied. */ 3491*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3492*7c478bd9Sstevel@tonic-gate cbp = (aiocb32_t *)(uintptr_t)*ucbp; 3493*7c478bd9Sstevel@tonic-gate if (cbp == NULL || copyin(cbp, aiocb32, sizeof (aiocb32_t))) { 3494*7c478bd9Sstevel@tonic-gate #else 3495*7c478bd9Sstevel@tonic-gate cbp = (aiocb_t *)*ucbp; 3496*7c478bd9Sstevel@tonic-gate if (cbp == NULL || copyin(cbp, aiocb, sizeof (aiocb_t))) { 3497*7c478bd9Sstevel@tonic-gate #endif 3498*7c478bd9Sstevel@tonic-gate if (head) { 3499*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3500*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3501*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3502*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3503*7c478bd9Sstevel@tonic-gate } 3504*7c478bd9Sstevel@tonic-gate continue; 3505*7c478bd9Sstevel@tonic-gate } 3506*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3507*7c478bd9Sstevel@tonic-gate /* 3508*7c478bd9Sstevel@tonic-gate * copy 32 bit structure into 64 bit structure 3509*7c478bd9Sstevel@tonic-gate */ 3510*7c478bd9Sstevel@tonic-gate aiocb_32ton(aiocb32, aiocb); 3511*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 3512*7c478bd9Sstevel@tonic-gate 3513*7c478bd9Sstevel@tonic-gate /* skip if opcode for aiocb is LIO_NOP */ 3514*7c478bd9Sstevel@tonic-gate 3515*7c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode; 3516*7c478bd9Sstevel@tonic-gate if (mode == LIO_NOP) { 3517*7c478bd9Sstevel@tonic-gate cbp = NULL; 3518*7c478bd9Sstevel@tonic-gate if (head) { 3519*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3520*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3521*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3522*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3523*7c478bd9Sstevel@tonic-gate } 3524*7c478bd9Sstevel@tonic-gate continue; 3525*7c478bd9Sstevel@tonic-gate } 3526*7c478bd9Sstevel@tonic-gate 3527*7c478bd9Sstevel@tonic-gate /* increment file descriptor's ref count. */ 3528*7c478bd9Sstevel@tonic-gate if ((fp = getf(aiocb->aio_fildes)) == NULL) { 3529*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF); 3530*7c478bd9Sstevel@tonic-gate if (head) { 3531*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3532*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3533*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3534*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3535*7c478bd9Sstevel@tonic-gate } 3536*7c478bd9Sstevel@tonic-gate aio_errors++; 3537*7c478bd9Sstevel@tonic-gate continue; 3538*7c478bd9Sstevel@tonic-gate } 3539*7c478bd9Sstevel@tonic-gate 3540*7c478bd9Sstevel@tonic-gate vp = fp->f_vnode; 3541*7c478bd9Sstevel@tonic-gate 3542*7c478bd9Sstevel@tonic-gate /* 3543*7c478bd9Sstevel@tonic-gate * check the permission of the partition 3544*7c478bd9Sstevel@tonic-gate */ 3545*7c478bd9Sstevel@tonic-gate mode = aiocb->aio_lio_opcode; 3546*7c478bd9Sstevel@tonic-gate if ((fp->f_flag & mode) == 0) { 3547*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3548*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, EBADF); 3549*7c478bd9Sstevel@tonic-gate if (head) { 3550*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3551*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3552*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3553*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3554*7c478bd9Sstevel@tonic-gate } 3555*7c478bd9Sstevel@tonic-gate aio_errors++; 3556*7c478bd9Sstevel@tonic-gate continue; 3557*7c478bd9Sstevel@tonic-gate } 3558*7c478bd9Sstevel@tonic-gate 3559*7c478bd9Sstevel@tonic-gate /* 3560*7c478bd9Sstevel@tonic-gate * common case where requests are to the same fd 3561*7c478bd9Sstevel@tonic-gate * for the same r/w operation 3562*7c478bd9Sstevel@tonic-gate * for UFS, need to set EBADFD 3563*7c478bd9Sstevel@tonic-gate */ 3564*7c478bd9Sstevel@tonic-gate if ((fp != prev_fp) || (mode != prev_mode)) { 3565*7c478bd9Sstevel@tonic-gate aio_func = check_vp(vp, mode); 3566*7c478bd9Sstevel@tonic-gate if (aio_func == NULL) { 3567*7c478bd9Sstevel@tonic-gate prev_fp = NULL; 3568*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3569*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, 3570*7c478bd9Sstevel@tonic-gate EBADFD); 3571*7c478bd9Sstevel@tonic-gate aio_notsupported++; 3572*7c478bd9Sstevel@tonic-gate if (head) { 3573*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3574*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3575*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3576*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3577*7c478bd9Sstevel@tonic-gate } 3578*7c478bd9Sstevel@tonic-gate continue; 3579*7c478bd9Sstevel@tonic-gate } else { 3580*7c478bd9Sstevel@tonic-gate prev_fp = fp; 3581*7c478bd9Sstevel@tonic-gate prev_mode = mode; 3582*7c478bd9Sstevel@tonic-gate } 3583*7c478bd9Sstevel@tonic-gate } 3584*7c478bd9Sstevel@tonic-gate if (error = aio_req_setup(&reqp, aiop, aiocb, 3585*7c478bd9Sstevel@tonic-gate (aio_result_t *)&cbp->aio_resultp, aio_use_port, vp)) { 3586*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3587*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error); 3588*7c478bd9Sstevel@tonic-gate if (head) { 3589*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3590*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3591*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3592*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3593*7c478bd9Sstevel@tonic-gate } 3594*7c478bd9Sstevel@tonic-gate aio_errors++; 3595*7c478bd9Sstevel@tonic-gate continue; 3596*7c478bd9Sstevel@tonic-gate } 3597*7c478bd9Sstevel@tonic-gate 3598*7c478bd9Sstevel@tonic-gate reqp->aio_req_lio = head; 3599*7c478bd9Sstevel@tonic-gate deadhead = 0; 3600*7c478bd9Sstevel@tonic-gate 3601*7c478bd9Sstevel@tonic-gate /* 3602*7c478bd9Sstevel@tonic-gate * Set the errno field now before sending the request to 3603*7c478bd9Sstevel@tonic-gate * the driver to avoid a race condition 3604*7c478bd9Sstevel@tonic-gate */ 3605*7c478bd9Sstevel@tonic-gate (void) suword32(&cbp->aio_resultp.aio_errno, 3606*7c478bd9Sstevel@tonic-gate EINPROGRESS); 3607*7c478bd9Sstevel@tonic-gate 3608*7c478bd9Sstevel@tonic-gate reqp->aio_req_iocb.iocb32 = ((caddr32_t *)cbplist)[i]; 3609*7c478bd9Sstevel@tonic-gate 3610*7c478bd9Sstevel@tonic-gate if (aio_use_port) { 3611*7c478bd9Sstevel@tonic-gate reqp->aio_req_port = pnotify.portnfy_port; 3612*7c478bd9Sstevel@tonic-gate #ifdef _LP64 3613*7c478bd9Sstevel@tonic-gate error = aio_req_assoc_port32(&aiocb32->aio_sigevent, 3614*7c478bd9Sstevel@tonic-gate (void *)(uintptr_t)pnotify.portnfy_user, 3615*7c478bd9Sstevel@tonic-gate (aiocb_t *)(uintptr_t)(((caddr32_t *)cbplist)[i]), 3616*7c478bd9Sstevel@tonic-gate reqp, pkevtp); 3617*7c478bd9Sstevel@tonic-gate #else 3618*7c478bd9Sstevel@tonic-gate error = aio_req_assoc_port(&aiocb->aio_sigevent, 3619*7c478bd9Sstevel@tonic-gate pnotify.portnfy_user, 3620*7c478bd9Sstevel@tonic-gate (aiocb_t *)(((caddr32_t *)cbplist)[i]), 3621*7c478bd9Sstevel@tonic-gate reqp, pkevtp); 3622*7c478bd9Sstevel@tonic-gate #endif 3623*7c478bd9Sstevel@tonic-gate } 3624*7c478bd9Sstevel@tonic-gate 3625*7c478bd9Sstevel@tonic-gate /* 3626*7c478bd9Sstevel@tonic-gate * send the request to driver. 3627*7c478bd9Sstevel@tonic-gate * Clustering: If PXFS vnode, call PXFS function. 3628*7c478bd9Sstevel@tonic-gate */ 3629*7c478bd9Sstevel@tonic-gate if (error == 0) { 3630*7c478bd9Sstevel@tonic-gate if (aiocb->aio_nbytes == 0) { 3631*7c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes); 3632*7c478bd9Sstevel@tonic-gate aio_zerolen(reqp); 3633*7c478bd9Sstevel@tonic-gate continue; 3634*7c478bd9Sstevel@tonic-gate } 3635*7c478bd9Sstevel@tonic-gate error = (*aio_func)(vp, (aio_req_t *)&reqp->aio_req, 3636*7c478bd9Sstevel@tonic-gate CRED()); 3637*7c478bd9Sstevel@tonic-gate } 3638*7c478bd9Sstevel@tonic-gate 3639*7c478bd9Sstevel@tonic-gate /* 3640*7c478bd9Sstevel@tonic-gate * the fd's ref count is not decremented until the IO has 3641*7c478bd9Sstevel@tonic-gate * completed unless there was an error. 3642*7c478bd9Sstevel@tonic-gate */ 3643*7c478bd9Sstevel@tonic-gate if (error) { 3644*7c478bd9Sstevel@tonic-gate releasef(aiocb->aio_fildes); 3645*7c478bd9Sstevel@tonic-gate lio_set_uerror(&cbp->aio_resultp, error); 3646*7c478bd9Sstevel@tonic-gate if (head) { 3647*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3648*7c478bd9Sstevel@tonic-gate head->lio_nent--; 3649*7c478bd9Sstevel@tonic-gate head->lio_refcnt--; 3650*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3651*7c478bd9Sstevel@tonic-gate } 3652*7c478bd9Sstevel@tonic-gate if (error == ENOTSUP) 3653*7c478bd9Sstevel@tonic-gate aio_notsupported++; 3654*7c478bd9Sstevel@tonic-gate else 3655*7c478bd9Sstevel@tonic-gate aio_errors++; 3656*7c478bd9Sstevel@tonic-gate lio_set_error(reqp); 3657*7c478bd9Sstevel@tonic-gate } else { 3658*7c478bd9Sstevel@tonic-gate clear_active_fd(aiocb->aio_fildes); 3659*7c478bd9Sstevel@tonic-gate } 3660*7c478bd9Sstevel@tonic-gate } 3661*7c478bd9Sstevel@tonic-gate 3662*7c478bd9Sstevel@tonic-gate if (pkevtp) 3663*7c478bd9Sstevel@tonic-gate port_free_event(pkevtp); 3664*7c478bd9Sstevel@tonic-gate 3665*7c478bd9Sstevel@tonic-gate if (aio_notsupported) { 3666*7c478bd9Sstevel@tonic-gate error = ENOTSUP; 3667*7c478bd9Sstevel@tonic-gate } else if (aio_errors) { 3668*7c478bd9Sstevel@tonic-gate /* 3669*7c478bd9Sstevel@tonic-gate * return EIO if any request failed 3670*7c478bd9Sstevel@tonic-gate */ 3671*7c478bd9Sstevel@tonic-gate error = EIO; 3672*7c478bd9Sstevel@tonic-gate } 3673*7c478bd9Sstevel@tonic-gate 3674*7c478bd9Sstevel@tonic-gate if (mode_arg == LIO_WAIT) { 3675*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3676*7c478bd9Sstevel@tonic-gate while (head->lio_refcnt > 0) { 3677*7c478bd9Sstevel@tonic-gate if (!cv_wait_sig(&head->lio_notify, &aiop->aio_mutex)) { 3678*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3679*7c478bd9Sstevel@tonic-gate error = EINTR; 3680*7c478bd9Sstevel@tonic-gate goto done; 3681*7c478bd9Sstevel@tonic-gate } 3682*7c478bd9Sstevel@tonic-gate } 3683*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3684*7c478bd9Sstevel@tonic-gate alio_cleanup(aiop, (aiocb_t **)cbplist, nent, AIO_32); 3685*7c478bd9Sstevel@tonic-gate } 3686*7c478bd9Sstevel@tonic-gate 3687*7c478bd9Sstevel@tonic-gate done: 3688*7c478bd9Sstevel@tonic-gate kmem_free(cbplist, ssize); 3689*7c478bd9Sstevel@tonic-gate if (deadhead) { 3690*7c478bd9Sstevel@tonic-gate if (head->lio_sigqp) 3691*7c478bd9Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t)); 3692*7c478bd9Sstevel@tonic-gate kmem_free(head, sizeof (aio_lio_t)); 3693*7c478bd9Sstevel@tonic-gate } 3694*7c478bd9Sstevel@tonic-gate return (error); 3695*7c478bd9Sstevel@tonic-gate } 3696*7c478bd9Sstevel@tonic-gate 3697*7c478bd9Sstevel@tonic-gate 3698*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 3699*7c478bd9Sstevel@tonic-gate void 3700*7c478bd9Sstevel@tonic-gate aiocb_32ton(aiocb32_t *src, aiocb_t *dest) 3701*7c478bd9Sstevel@tonic-gate { 3702*7c478bd9Sstevel@tonic-gate dest->aio_fildes = src->aio_fildes; 3703*7c478bd9Sstevel@tonic-gate dest->aio_buf = (caddr_t)(uintptr_t)src->aio_buf; 3704*7c478bd9Sstevel@tonic-gate dest->aio_nbytes = (size_t)src->aio_nbytes; 3705*7c478bd9Sstevel@tonic-gate dest->aio_offset = (off_t)src->aio_offset; 3706*7c478bd9Sstevel@tonic-gate dest->aio_reqprio = src->aio_reqprio; 3707*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify = src->aio_sigevent.sigev_notify; 3708*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_signo = src->aio_sigevent.sigev_signo; 3709*7c478bd9Sstevel@tonic-gate 3710*7c478bd9Sstevel@tonic-gate /* 3711*7c478bd9Sstevel@tonic-gate * See comment in sigqueue32() on handling of 32-bit 3712*7c478bd9Sstevel@tonic-gate * sigvals in a 64-bit kernel. 3713*7c478bd9Sstevel@tonic-gate */ 3714*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_value.sival_int = 3715*7c478bd9Sstevel@tonic-gate (int)src->aio_sigevent.sigev_value.sival_int; 3716*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_function = (void (*)(union sigval)) 3717*7c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_function; 3718*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.sigev_notify_attributes = (pthread_attr_t *) 3719*7c478bd9Sstevel@tonic-gate (uintptr_t)src->aio_sigevent.sigev_notify_attributes; 3720*7c478bd9Sstevel@tonic-gate dest->aio_sigevent.__sigev_pad2 = src->aio_sigevent.__sigev_pad2; 3721*7c478bd9Sstevel@tonic-gate dest->aio_lio_opcode = src->aio_lio_opcode; 3722*7c478bd9Sstevel@tonic-gate dest->aio_state = src->aio_state; 3723*7c478bd9Sstevel@tonic-gate dest->aio__pad[0] = src->aio__pad[0]; 3724*7c478bd9Sstevel@tonic-gate } 3725*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 3726*7c478bd9Sstevel@tonic-gate 3727*7c478bd9Sstevel@tonic-gate /* 3728*7c478bd9Sstevel@tonic-gate * aio_port_callback() is called just before the event is retrieved from the 3729*7c478bd9Sstevel@tonic-gate * port. The task of this callback function is to finish the work of the 3730*7c478bd9Sstevel@tonic-gate * transaction for the application, it means : 3731*7c478bd9Sstevel@tonic-gate * - copyout transaction data to the application 3732*7c478bd9Sstevel@tonic-gate * (this thread is running in the right process context) 3733*7c478bd9Sstevel@tonic-gate * - keep trace of the transaction (update of counters). 3734*7c478bd9Sstevel@tonic-gate * - free allocated buffers 3735*7c478bd9Sstevel@tonic-gate * The aiocb pointer is the object element of the port_kevent_t structure. 3736*7c478bd9Sstevel@tonic-gate * 3737*7c478bd9Sstevel@tonic-gate * flag : 3738*7c478bd9Sstevel@tonic-gate * PORT_CALLBACK_DEFAULT : do copyout and free resources 3739*7c478bd9Sstevel@tonic-gate * PORT_CALLBACK_CLOSE : don't do copyout, free resources 3740*7c478bd9Sstevel@tonic-gate */ 3741*7c478bd9Sstevel@tonic-gate 3742*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3743*7c478bd9Sstevel@tonic-gate int 3744*7c478bd9Sstevel@tonic-gate aio_port_callback(void *arg, int *events, pid_t pid, int flag, void *evp) 3745*7c478bd9Sstevel@tonic-gate { 3746*7c478bd9Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 3747*7c478bd9Sstevel@tonic-gate aio_req_t *reqp = arg; 3748*7c478bd9Sstevel@tonic-gate struct iovec *iov; 3749*7c478bd9Sstevel@tonic-gate struct buf *bp; 3750*7c478bd9Sstevel@tonic-gate void *resultp; 3751*7c478bd9Sstevel@tonic-gate 3752*7c478bd9Sstevel@tonic-gate if (pid != curproc->p_pid) { 3753*7c478bd9Sstevel@tonic-gate /* wrong proc !!, can not deliver data here ... */ 3754*7c478bd9Sstevel@tonic-gate return (EACCES); 3755*7c478bd9Sstevel@tonic-gate } 3756*7c478bd9Sstevel@tonic-gate 3757*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_portq_mutex); 3758*7c478bd9Sstevel@tonic-gate reqp->aio_req_portkev = NULL; 3759*7c478bd9Sstevel@tonic-gate aio_req_remove_portq(aiop, reqp); /* remove request from portq */ 3760*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 3761*7c478bd9Sstevel@tonic-gate aphysio_unlock(reqp); /* unlock used pages */ 3762*7c478bd9Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 3763*7c478bd9Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_COPYOUTDONE) { 3764*7c478bd9Sstevel@tonic-gate aio_req_free_port(aiop, reqp); /* back to free list */ 3765*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3766*7c478bd9Sstevel@tonic-gate return (0); 3767*7c478bd9Sstevel@tonic-gate } 3768*7c478bd9Sstevel@tonic-gate 3769*7c478bd9Sstevel@tonic-gate iov = reqp->aio_req_uio.uio_iov; 3770*7c478bd9Sstevel@tonic-gate bp = &reqp->aio_req_buf; 3771*7c478bd9Sstevel@tonic-gate resultp = (void *)reqp->aio_req_resultp; 3772*7c478bd9Sstevel@tonic-gate aio_req_free_port(aiop, reqp); /* request struct back to free list */ 3773*7c478bd9Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3774*7c478bd9Sstevel@tonic-gate if (flag == PORT_CALLBACK_DEFAULT) 3775*7c478bd9Sstevel@tonic-gate aio_copyout_result_port(iov, bp, resultp); 3776*7c478bd9Sstevel@tonic-gate return (0); 3777*7c478bd9Sstevel@tonic-gate } 3778