vfs_aio.c (87590) | vfs_aio.c (88633) |
---|---|
1/* 2 * Copyright (c) 1997 John S. Dyson. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. John S. Dyson's name may not be used to endorse or promote products 10 * derived from this software without specific prior written permission. 11 * 12 * DISCLAIMER: This code isn't warranted to do anything useful. Anything 13 * bad that happens because of using this software isn't the responsibility 14 * of the author. This software is distributed AS-IS. 15 * | 1/* 2 * Copyright (c) 1997 John S. Dyson. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. John S. Dyson's name may not be used to endorse or promote products 10 * derived from this software without specific prior written permission. 11 * 12 * DISCLAIMER: This code isn't warranted to do anything useful. Anything 13 * bad that happens because of using this software isn't the responsibility 14 * of the author. This software is distributed AS-IS. 15 * |
16 * $FreeBSD: head/sys/kern/vfs_aio.c 87590 2001-12-10 03:34:06Z alc $ | 16 * $FreeBSD: head/sys/kern/vfs_aio.c 88633 2001-12-29 07:13:47Z alfred $ |
17 */ 18 19/* 20 * This file contains support for the POSIX 1003.1B AIO/LIO facility. 21 */ 22 23#include <sys/param.h> 24#include <sys/systm.h> --- 8 unchanged lines hidden (view full) --- 33#include <sys/lock.h> 34#include <sys/mutex.h> 35#include <sys/unistd.h> 36#include <sys/proc.h> 37#include <sys/resourcevar.h> 38#include <sys/signalvar.h> 39#include <sys/protosw.h> 40#include <sys/socketvar.h> | 17 */ 18 19/* 20 * This file contains support for the POSIX 1003.1B AIO/LIO facility. 21 */ 22 23#include <sys/param.h> 24#include <sys/systm.h> --- 8 unchanged lines hidden (view full) --- 33#include <sys/lock.h> 34#include <sys/mutex.h> 35#include <sys/unistd.h> 36#include <sys/proc.h> 37#include <sys/resourcevar.h> 38#include <sys/signalvar.h> 39#include <sys/protosw.h> 40#include <sys/socketvar.h> |
41#include <sys/syscall.h> 42#include <sys/sysent.h> |
|
41#include <sys/sysctl.h> 42#include <sys/vnode.h> 43#include <sys/conf.h> 44#include <sys/event.h> 45 46#include <vm/vm.h> 47#include <vm/vm_extern.h> 48#include <vm/pmap.h> 49#include <vm/vm_map.h> 50#include <vm/vm_zone.h> 51#include <sys/aio.h> 52 53#include <machine/limits.h> 54 55#include "opt_vfs_aio.h" 56 | 43#include <sys/sysctl.h> 44#include <sys/vnode.h> 45#include <sys/conf.h> 46#include <sys/event.h> 47 48#include <vm/vm.h> 49#include <vm/vm_extern.h> 50#include <vm/pmap.h> 51#include <vm/vm_map.h> 52#include <vm/vm_zone.h> 53#include <sys/aio.h> 54 55#include <machine/limits.h> 56 57#include "opt_vfs_aio.h" 58 |
57#ifdef VFS_AIO 58 | |
59static long jobrefid; 60 61#define JOBST_NULL 0x0 62#define JOBST_JOBQPROC 0x1 63#define JOBST_JOBQGLOBAL 0x2 64#define JOBST_JOBRUNNING 0x3 65#define JOBST_JOBFINISHED 0x4 66#define JOBST_JOBQBUF 0x5 --- 35 unchanged lines hidden (view full) --- 102static int num_aio_procs = 0; 103static int target_aio_procs = TARGET_AIO_PROCS; 104static int max_queue_count = MAX_AIO_QUEUE; 105static int num_queue_count = 0; 106static int num_buf_aio = 0; 107static int num_aio_resv_start = 0; 108static int aiod_timeout; 109static int aiod_lifetime; | 59static long jobrefid; 60 61#define JOBST_NULL 0x0 62#define JOBST_JOBQPROC 0x1 63#define JOBST_JOBQGLOBAL 0x2 64#define JOBST_JOBRUNNING 0x3 65#define JOBST_JOBFINISHED 0x4 66#define JOBST_JOBQBUF 0x5 --- 35 unchanged lines hidden (view full) --- 102static int num_aio_procs = 0; 103static int target_aio_procs = TARGET_AIO_PROCS; 104static int max_queue_count = MAX_AIO_QUEUE; 105static int num_queue_count = 0; 106static int num_buf_aio = 0; 107static int num_aio_resv_start = 0; 108static int aiod_timeout; 109static int aiod_lifetime; |
110static int unloadable = 0; |
|
110 111static int max_aio_per_proc = MAX_AIO_PER_PROC; 112static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC; 113static int max_buf_aio = MAX_BUF_AIO; 114 115SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "AIO mgmt"); 116 117SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, --- 24 unchanged lines hidden (view full) --- 142 CTLFLAG_RD, &num_buf_aio, 0, ""); 143 144SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, 145 CTLFLAG_RW, &aiod_lifetime, 0, ""); 146 147SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, 148 CTLFLAG_RW, &aiod_timeout, 0, ""); 149 | 111 112static int max_aio_per_proc = MAX_AIO_PER_PROC; 113static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC; 114static int max_buf_aio = MAX_BUF_AIO; 115 116SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "AIO mgmt"); 117 118SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, --- 24 unchanged lines hidden (view full) --- 143 CTLFLAG_RD, &num_buf_aio, 0, ""); 144 145SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, 146 CTLFLAG_RW, &aiod_lifetime, 0, ""); 147 148SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, 149 CTLFLAG_RW, &aiod_timeout, 0, ""); 150 |
151SYSCTL_INT(_vfs_aio, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0, 152 "Allow unload of aio (not recommended)"); 153 |
|
150/* 151 * AIO process info 152 */ 153#define AIOP_FREE 0x1 /* proc on free queue */ 154#define AIOP_SCHED 0x2 /* proc explicitly scheduled */ 155 156struct aiothreadlist { 157 int aiothreadflags; /* AIO proc flags */ --- 43 unchanged lines hidden (view full) --- 201#define KAIO_RUNDOWN 0x1 /* process is being run down */ 202#define KAIO_WAKEUP 0x2 /* wakeup process when there is a significant event */ 203 204static TAILQ_HEAD(,aiothreadlist) aio_freeproc, aio_activeproc; 205static TAILQ_HEAD(,aiocblist) aio_jobs; /* Async job list */ 206static TAILQ_HEAD(,aiocblist) aio_bufjobs; /* Phys I/O job list */ 207 208static void aio_init_aioinfo(struct proc *p); | 154/* 155 * AIO process info 156 */ 157#define AIOP_FREE 0x1 /* proc on free queue */ 158#define AIOP_SCHED 0x2 /* proc explicitly scheduled */ 159 160struct aiothreadlist { 161 int aiothreadflags; /* AIO proc flags */ --- 43 unchanged lines hidden (view full) --- 205#define KAIO_RUNDOWN 0x1 /* process is being run down */ 206#define KAIO_WAKEUP 0x2 /* wakeup process when there is a significant event */ 207 208static TAILQ_HEAD(,aiothreadlist) aio_freeproc, aio_activeproc; 209static TAILQ_HEAD(,aiocblist) aio_jobs; /* Async job list */ 210static TAILQ_HEAD(,aiocblist) aio_bufjobs; /* Phys I/O job list */ 211 212static void aio_init_aioinfo(struct proc *p); |
209static void aio_onceonly(void *); | 213static void aio_onceonly(void); |
210static int aio_free_entry(struct aiocblist *aiocbe); 211static void aio_process(struct aiocblist *aiocbe); 212static int aio_newproc(void); 213static int aio_aqueue(struct thread *td, struct aiocb *job, int type); 214static void aio_physwakeup(struct buf *bp); | 214static int aio_free_entry(struct aiocblist *aiocbe); 215static void aio_process(struct aiocblist *aiocbe); 216static int aio_newproc(void); 217static int aio_aqueue(struct thread *td, struct aiocb *job, int type); 218static void aio_physwakeup(struct buf *bp); |
219static void aio_proc_rundown(struct proc *p); |
|
215static int aio_fphysio(struct proc *p, struct aiocblist *aiocbe); 216static int aio_qphysio(struct proc *p, struct aiocblist *iocb); 217static void aio_daemon(void *uproc); | 220static int aio_fphysio(struct proc *p, struct aiocblist *aiocbe); 221static int aio_qphysio(struct proc *p, struct aiocblist *iocb); 222static void aio_daemon(void *uproc); |
223static int aio_unload(void); |
|
218static void process_signal(void *aioj); | 224static void process_signal(void *aioj); |
225static int filt_aioattach(struct knote *kn); 226static void filt_aiodetach(struct knote *kn); 227static int filt_aio(struct knote *kn, long hint); |
|
219 | 228 |
220SYSINIT(aio, SI_SUB_VFS, SI_ORDER_ANY, aio_onceonly, NULL); 221 | |
222static vm_zone_t kaio_zone = 0, aiop_zone = 0, aiocb_zone = 0, aiol_zone = 0; 223static vm_zone_t aiolio_zone = 0; 224 | 229static vm_zone_t kaio_zone = 0, aiop_zone = 0, aiocb_zone = 0, aiol_zone = 0; 230static vm_zone_t aiolio_zone = 0; 231 |
232static struct filterops aio_filtops = 233 { 0, filt_aioattach, filt_aiodetach, filt_aio }; 234 235static int 236aio_modload(struct module *module, int cmd, void *arg) 237{ 238 int error = 0; 239 240 switch (cmd) { 241 case MOD_LOAD: 242 aio_onceonly(); 243 break; 244 case MOD_UNLOAD: 245 error = aio_unload(); 246 break; 247 case MOD_SHUTDOWN: 248 break; 249 default: 250 error = EINVAL; 251 break; 252 } 253 return (error); 254} 255 256static moduledata_t aio_mod = { 257 "aio", 258 &aio_modload, 259 NULL 260}; 261 262SYSCALL_MODULE_HELPER(aio_return); 263SYSCALL_MODULE_HELPER(aio_suspend); 264SYSCALL_MODULE_HELPER(aio_cancel); 265SYSCALL_MODULE_HELPER(aio_error); 266SYSCALL_MODULE_HELPER(aio_read); 267SYSCALL_MODULE_HELPER(aio_write); 268SYSCALL_MODULE_HELPER(aio_waitcomplete); 269SYSCALL_MODULE_HELPER(lio_listio); 270 271DECLARE_MODULE(aio, aio_mod, 272 SI_SUB_VFS, SI_ORDER_ANY); 273MODULE_VERSION(aio, 1); 274 |
|
225/* 226 * Startup initialization 227 */ 228static void | 275/* 276 * Startup initialization 277 */ 278static void |
229aio_onceonly(void *na) | 279aio_onceonly(void) |
230{ | 280{ |
281 282 /* XXX: should probably just use so->callback */ 283 aio_swake = &aio_swake_cb; 284 at_exit(aio_proc_rundown); 285 at_exec(aio_proc_rundown); 286 kqueue_add_filteropts(EVFILT_AIO, &aio_filtops); |
|
231 TAILQ_INIT(&aio_freeproc); 232 TAILQ_INIT(&aio_activeproc); 233 TAILQ_INIT(&aio_jobs); 234 TAILQ_INIT(&aio_bufjobs); 235 kaio_zone = zinit("AIO", sizeof (struct kaioinfo), 0, 0, 1); 236 aiop_zone = zinit("AIOP", sizeof (struct aiothreadlist), 0, 0, 1); 237 aiocb_zone = zinit("AIOCB", sizeof (struct aiocblist), 0, 0, 1); 238 aiol_zone = zinit("AIOL", AIO_LISTIO_MAX * sizeof (int), 0, 0, 1); 239 aiolio_zone = zinit("AIOLIO", AIO_LISTIO_MAX * sizeof (struct 240 aio_liojob), 0, 0, 1); 241 aiod_timeout = AIOD_TIMEOUT_DEFAULT; 242 aiod_lifetime = AIOD_LIFETIME_DEFAULT; 243 jobrefid = 1; 244} 245 | 287 TAILQ_INIT(&aio_freeproc); 288 TAILQ_INIT(&aio_activeproc); 289 TAILQ_INIT(&aio_jobs); 290 TAILQ_INIT(&aio_bufjobs); 291 kaio_zone = zinit("AIO", sizeof (struct kaioinfo), 0, 0, 1); 292 aiop_zone = zinit("AIOP", sizeof (struct aiothreadlist), 0, 0, 1); 293 aiocb_zone = zinit("AIOCB", sizeof (struct aiocblist), 0, 0, 1); 294 aiol_zone = zinit("AIOL", AIO_LISTIO_MAX * sizeof (int), 0, 0, 1); 295 aiolio_zone = zinit("AIOLIO", AIO_LISTIO_MAX * sizeof (struct 296 aio_liojob), 0, 0, 1); 297 aiod_timeout = AIOD_TIMEOUT_DEFAULT; 298 aiod_lifetime = AIOD_LIFETIME_DEFAULT; 299 jobrefid = 1; 300} 301 |
302static int 303aio_unload(void) 304{ 305 306 /* 307 * XXX: no unloads by default, it's too dangerous. 308 * perhaps we could do it if locked out callers and then 309 * did an aio_proc_rundown() on each process. 310 */ 311 if (!unloadable) 312 return (EOPNOTSUPP); 313 314 aio_swake = NULL; 315 rm_at_exit(aio_proc_rundown); 316 rm_at_exec(aio_proc_rundown); 317 kqueue_del_filteropts(EVFILT_AIO); 318 return (0); 319} 320 |
|
246/* 247 * Init the per-process aioinfo structure. The aioinfo limits are set 248 * per-process for user limit (resource) management. 249 */ 250static void 251aio_init_aioinfo(struct proc *p) 252{ 253 struct kaioinfo *ki; --- 125 unchanged lines hidden (view full) --- 379 TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list); 380 zfree(aiolio_zone, lj); 381 } 382 aiocbe->jobstate = JOBST_NULL; 383 untimeout(process_signal, aiocbe, aiocbe->timeouthandle); 384 zfree(aiocb_zone, aiocbe); 385 return 0; 386} | 321/* 322 * Init the per-process aioinfo structure. The aioinfo limits are set 323 * per-process for user limit (resource) management. 324 */ 325static void 326aio_init_aioinfo(struct proc *p) 327{ 328 struct kaioinfo *ki; --- 125 unchanged lines hidden (view full) --- 454 TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list); 455 zfree(aiolio_zone, lj); 456 } 457 aiocbe->jobstate = JOBST_NULL; 458 untimeout(process_signal, aiocbe, aiocbe->timeouthandle); 459 zfree(aiocb_zone, aiocbe); 460 return 0; 461} |
387#endif /* VFS_AIO */ | |
388 389/* 390 * Rundown the jobs for a given process. 391 */ | 462 463/* 464 * Rundown the jobs for a given process. 465 */ |
392void | 466static void |
393aio_proc_rundown(struct proc *p) 394{ | 467aio_proc_rundown(struct proc *p) 468{ |
395#ifndef VFS_AIO 396 return; 397#else | |
398 int s; 399 struct kaioinfo *ki; 400 struct aio_liojob *lj, *ljn; 401 struct aiocblist *aiocbe, *aiocbn; 402 struct file *fp; 403 struct filedesc *fdp; 404 struct socket *so; 405 --- 108 unchanged lines hidden (view full) --- 514 lj->lioj_queue_count, 515 lj->lioj_queue_finished_count); 516#endif 517 } 518 } 519 520 zfree(kaio_zone, ki); 521 p->p_aioinfo = NULL; | 469 int s; 470 struct kaioinfo *ki; 471 struct aio_liojob *lj, *ljn; 472 struct aiocblist *aiocbe, *aiocbn; 473 struct file *fp; 474 struct filedesc *fdp; 475 struct socket *so; 476 --- 108 unchanged lines hidden (view full) --- 585 lj->lioj_queue_count, 586 lj->lioj_queue_finished_count); 587#endif 588 } 589 } 590 591 zfree(kaio_zone, ki); 592 p->p_aioinfo = NULL; |
522#endif /* VFS_AIO */ | |
523} 524 | 593} 594 |
525#ifdef VFS_AIO | |
526/* 527 * Select a job to run (called by an AIO daemon). 528 */ 529static struct aiocblist * 530aio_selectjob(struct aiothreadlist *aiop) 531{ 532 int s; 533 struct aiocblist *aiocbe; --- 611 unchanged lines hidden (view full) --- 1145 1146 /* Check for an error. */ 1147 if (bp->b_ioflags & BIO_ERROR) 1148 error = bp->b_error; 1149 1150 relpbuf(bp, NULL); 1151 return (error); 1152} | 595/* 596 * Select a job to run (called by an AIO daemon). 597 */ 598static struct aiocblist * 599aio_selectjob(struct aiothreadlist *aiop) 600{ 601 int s; 602 struct aiocblist *aiocbe; --- 611 unchanged lines hidden (view full) --- 1214 1215 /* Check for an error. */ 1216 if (bp->b_ioflags & BIO_ERROR) 1217 error = bp->b_error; 1218 1219 relpbuf(bp, NULL); 1220 return (error); 1221} |
1153#endif /* VFS_AIO */ | |
1154 1155/* 1156 * Wake up aio requests that may be serviceable now. 1157 */ 1158void | 1222 1223/* 1224 * Wake up aio requests that may be serviceable now. 1225 */ 1226void |
1159aio_swake(struct socket *so, struct sockbuf *sb) | 1227aio_swake_cb(struct socket *so, struct sockbuf *sb) |
1160{ | 1228{ |
1161#ifndef VFS_AIO 1162 return; 1163#else | |
1164 struct aiocblist *cb,*cbn; 1165 struct proc *p; 1166 struct kaioinfo *ki = NULL; 1167 int opcode, wakecount = 0; 1168 struct aiothreadlist *aiop; 1169 1170 if (sb == &so->so_snd) { 1171 opcode = LIO_WRITE; --- 21 unchanged lines hidden (view full) --- 1193 while (wakecount--) { 1194 if ((aiop = TAILQ_FIRST(&aio_freeproc)) != 0) { 1195 TAILQ_REMOVE(&aio_freeproc, aiop, list); 1196 TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list); 1197 aiop->aiothreadflags &= ~AIOP_FREE; 1198 wakeup(aiop->aiothread); 1199 } 1200 } | 1229 struct aiocblist *cb,*cbn; 1230 struct proc *p; 1231 struct kaioinfo *ki = NULL; 1232 int opcode, wakecount = 0; 1233 struct aiothreadlist *aiop; 1234 1235 if (sb == &so->so_snd) { 1236 opcode = LIO_WRITE; --- 21 unchanged lines hidden (view full) --- 1258 while (wakecount--) { 1259 if ((aiop = TAILQ_FIRST(&aio_freeproc)) != 0) { 1260 TAILQ_REMOVE(&aio_freeproc, aiop, list); 1261 TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list); 1262 aiop->aiothreadflags &= ~AIOP_FREE; 1263 wakeup(aiop->aiothread); 1264 } 1265 } |
1201#endif /* VFS_AIO */ | |
1202} 1203 | 1266} 1267 |
1204#ifdef VFS_AIO | |
1205/* 1206 * Queue a new AIO request. Choosing either the threaded or direct physio VCHR 1207 * technique is done in this code. 1208 */ 1209static int 1210_aio_aqueue(struct thread *td, struct aiocb *job, struct aio_liojob *lj, int type) 1211{ 1212 struct proc *p = td->td_proc; --- 256 unchanged lines hidden (view full) --- 1469 return EAGAIN; 1470 1471 ki = p->p_aioinfo; 1472 if (ki->kaio_queue_count >= ki->kaio_qallowed_count) 1473 return EAGAIN; 1474 1475 return _aio_aqueue(td, job, NULL, type); 1476} | 1268/* 1269 * Queue a new AIO request. Choosing either the threaded or direct physio VCHR 1270 * technique is done in this code. 1271 */ 1272static int 1273_aio_aqueue(struct thread *td, struct aiocb *job, struct aio_liojob *lj, int type) 1274{ 1275 struct proc *p = td->td_proc; --- 256 unchanged lines hidden (view full) --- 1532 return EAGAIN; 1533 1534 ki = p->p_aioinfo; 1535 if (ki->kaio_queue_count >= ki->kaio_qallowed_count) 1536 return EAGAIN; 1537 1538 return _aio_aqueue(td, job, NULL, type); 1539} |
1477#endif /* VFS_AIO */ | |
1478 1479/* 1480 * Support the aio_return system call, as a side-effect, kernel resources are 1481 * released. 1482 */ 1483int 1484aio_return(struct thread *td, struct aio_return_args *uap) 1485{ | 1540 1541/* 1542 * Support the aio_return system call, as a side-effect, kernel resources are 1543 * released. 1544 */ 1545int 1546aio_return(struct thread *td, struct aio_return_args *uap) 1547{ |
1486#ifndef VFS_AIO 1487 return ENOSYS; 1488#else | |
1489 struct proc *p = td->td_proc; 1490 int s; 1491 int jobref; 1492 struct aiocblist *cb, *ncb; 1493 struct aiocb *ujob; 1494 struct kaioinfo *ki; 1495 1496 ki = p->p_aioinfo; --- 45 unchanged lines hidden (view full) --- 1542 td->td_retval[0] = EFAULT; 1543 aio_free_entry(cb); 1544 return 0; 1545 } 1546 } 1547 splx(s); 1548 1549 return (EINVAL); | 1548 struct proc *p = td->td_proc; 1549 int s; 1550 int jobref; 1551 struct aiocblist *cb, *ncb; 1552 struct aiocb *ujob; 1553 struct kaioinfo *ki; 1554 1555 ki = p->p_aioinfo; --- 45 unchanged lines hidden (view full) --- 1601 td->td_retval[0] = EFAULT; 1602 aio_free_entry(cb); 1603 return 0; 1604 } 1605 } 1606 splx(s); 1607 1608 return (EINVAL); |
1550#endif /* VFS_AIO */ | |
1551} 1552 1553/* 1554 * Allow a process to wakeup when any of the I/O requests are completed. 1555 */ 1556int 1557aio_suspend(struct thread *td, struct aio_suspend_args *uap) 1558{ | 1609} 1610 1611/* 1612 * Allow a process to wakeup when any of the I/O requests are completed. 1613 */ 1614int 1615aio_suspend(struct thread *td, struct aio_suspend_args *uap) 1616{ |
1559#ifndef VFS_AIO 1560 return ENOSYS; 1561#else | |
1562 struct proc *p = td->td_proc; 1563 struct timeval atv; 1564 struct timespec ts; 1565 struct aiocb *const *cbptr, *cbp; 1566 struct kaioinfo *ki; 1567 struct aiocblist *cb; 1568 int i; 1569 int njoblist; --- 89 unchanged lines hidden (view full) --- 1659 zfree(aiol_zone, ijoblist); 1660 zfree(aiol_zone, ujoblist); 1661 return EAGAIN; 1662 } 1663 } 1664 1665/* NOTREACHED */ 1666 return EINVAL; | 1617 struct proc *p = td->td_proc; 1618 struct timeval atv; 1619 struct timespec ts; 1620 struct aiocb *const *cbptr, *cbp; 1621 struct kaioinfo *ki; 1622 struct aiocblist *cb; 1623 int i; 1624 int njoblist; --- 89 unchanged lines hidden (view full) --- 1714 zfree(aiol_zone, ijoblist); 1715 zfree(aiol_zone, ujoblist); 1716 return EAGAIN; 1717 } 1718 } 1719 1720/* NOTREACHED */ 1721 return EINVAL; |
1667#endif /* VFS_AIO */ | |
1668} 1669 1670/* 1671 * aio_cancel cancels any non-physio aio operations not currently in 1672 * progress. 1673 */ 1674int 1675aio_cancel(struct thread *td, struct aio_cancel_args *uap) 1676{ | 1722} 1723 1724/* 1725 * aio_cancel cancels any non-physio aio operations not currently in 1726 * progress. 1727 */ 1728int 1729aio_cancel(struct thread *td, struct aio_cancel_args *uap) 1730{ |
1677#ifndef VFS_AIO 1678 return ENOSYS; 1679#else | |
1680 struct proc *p = td->td_proc; 1681 struct kaioinfo *ki; 1682 struct aiocblist *cbe, *cbn; 1683 struct file *fp; 1684 struct filedesc *fdp; 1685 struct socket *so; 1686 struct proc *po; 1687 int s,error; --- 103 unchanged lines hidden (view full) --- 1791 if (cancelled) { 1792 td->td_retval[0] = AIO_CANCELED; 1793 return 0; 1794 } 1795 1796 td->td_retval[0] = AIO_ALLDONE; 1797 1798 return 0; | 1731 struct proc *p = td->td_proc; 1732 struct kaioinfo *ki; 1733 struct aiocblist *cbe, *cbn; 1734 struct file *fp; 1735 struct filedesc *fdp; 1736 struct socket *so; 1737 struct proc *po; 1738 int s,error; --- 103 unchanged lines hidden (view full) --- 1842 if (cancelled) { 1843 td->td_retval[0] = AIO_CANCELED; 1844 return 0; 1845 } 1846 1847 td->td_retval[0] = AIO_ALLDONE; 1848 1849 return 0; |
1799#endif /* VFS_AIO */ | |
1800} 1801 1802/* 1803 * aio_error is implemented in the kernel level for compatibility purposes only. 1804 * For a user mode async implementation, it would be best to do it in a userland 1805 * subroutine. 1806 */ 1807int 1808aio_error(struct thread *td, struct aio_error_args *uap) 1809{ | 1850} 1851 1852/* 1853 * aio_error is implemented in the kernel level for compatibility purposes only. 1854 * For a user mode async implementation, it would be best to do it in a userland 1855 * subroutine. 1856 */ 1857int 1858aio_error(struct thread *td, struct aio_error_args *uap) 1859{ |
1810#ifndef VFS_AIO 1811 return ENOSYS; 1812#else | |
1813 struct proc *p = td->td_proc; 1814 int s; 1815 struct aiocblist *cb; 1816 struct kaioinfo *ki; 1817 int jobref; 1818 1819 ki = p->p_aioinfo; 1820 if (ki == NULL) --- 61 unchanged lines hidden (view full) --- 1882 /* 1883 * Hack for lio. 1884 */ 1885 status = fuword(&uap->aiocbp->_aiocb_private.status); 1886 if (status == -1) 1887 return fuword(&uap->aiocbp->_aiocb_private.error); 1888#endif 1889 return EINVAL; | 1860 struct proc *p = td->td_proc; 1861 int s; 1862 struct aiocblist *cb; 1863 struct kaioinfo *ki; 1864 int jobref; 1865 1866 ki = p->p_aioinfo; 1867 if (ki == NULL) --- 61 unchanged lines hidden (view full) --- 1929 /* 1930 * Hack for lio. 1931 */ 1932 status = fuword(&uap->aiocbp->_aiocb_private.status); 1933 if (status == -1) 1934 return fuword(&uap->aiocbp->_aiocb_private.error); 1935#endif 1936 return EINVAL; |
1890#endif /* VFS_AIO */ | |
1891} 1892 1893int 1894aio_read(struct thread *td, struct aio_read_args *uap) 1895{ | 1937} 1938 1939int 1940aio_read(struct thread *td, struct aio_read_args *uap) 1941{ |
1896#ifndef VFS_AIO 1897 return ENOSYS; 1898#else | 1942 |
1899 return aio_aqueue(td, uap->aiocbp, LIO_READ); | 1943 return aio_aqueue(td, uap->aiocbp, LIO_READ); |
1900#endif /* VFS_AIO */ | |
1901} 1902 1903int 1904aio_write(struct thread *td, struct aio_write_args *uap) 1905{ | 1944} 1945 1946int 1947aio_write(struct thread *td, struct aio_write_args *uap) 1948{ |
1906#ifndef VFS_AIO 1907 return ENOSYS; 1908#else | 1949 |
1909 return aio_aqueue(td, uap->aiocbp, LIO_WRITE); | 1950 return aio_aqueue(td, uap->aiocbp, LIO_WRITE); |
1910#endif /* VFS_AIO */ | |
1911} 1912 1913int 1914lio_listio(struct thread *td, struct lio_listio_args *uap) 1915{ | 1951} 1952 1953int 1954lio_listio(struct thread *td, struct lio_listio_args *uap) 1955{ |
1916#ifndef VFS_AIO 1917 return ENOSYS; 1918#else | |
1919 struct proc *p = td->td_proc; 1920 int nent, nentqueued; 1921 struct aiocb *iocb, * const *cbptr; 1922 struct aiocblist *cb; 1923 struct kaioinfo *ki; 1924 struct aio_liojob *lj; 1925 int error, runningcode; 1926 int nerror; --- 148 unchanged lines hidden (view full) --- 2075 if (error == EINTR) 2076 return EINTR; 2077 else if (error == EWOULDBLOCK) 2078 return EAGAIN; 2079 } 2080 } 2081 2082 return runningcode; | 1956 struct proc *p = td->td_proc; 1957 int nent, nentqueued; 1958 struct aiocb *iocb, * const *cbptr; 1959 struct aiocblist *cb; 1960 struct kaioinfo *ki; 1961 struct aio_liojob *lj; 1962 int error, runningcode; 1963 int nerror; --- 148 unchanged lines hidden (view full) --- 2112 if (error == EINTR) 2113 return EINTR; 2114 else if (error == EWOULDBLOCK) 2115 return EAGAIN; 2116 } 2117 } 2118 2119 return runningcode; |
2083#endif /* VFS_AIO */ | |
2084} 2085 | 2120} 2121 |
2086#ifdef VFS_AIO | |
2087/* 2088 * This is a weird hack so that we can post a signal. It is safe to do so from 2089 * a timeout routine, but *not* from an interrupt routine. 2090 */ 2091static void 2092process_signal(void *aioj) 2093{ 2094 struct aiocblist *aiocbe = aioj; --- 79 unchanged lines hidden (view full) --- 2174 } 2175 } 2176 2177 if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL) 2178 aiocbe->timeouthandle = 2179 timeout(process_signal, aiocbe, 0); 2180 } 2181} | 2122/* 2123 * This is a weird hack so that we can post a signal. It is safe to do so from 2124 * a timeout routine, but *not* from an interrupt routine. 2125 */ 2126static void 2127process_signal(void *aioj) 2128{ 2129 struct aiocblist *aiocbe = aioj; --- 79 unchanged lines hidden (view full) --- 2209 } 2210 } 2211 2212 if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL) 2213 aiocbe->timeouthandle = 2214 timeout(process_signal, aiocbe, 0); 2215 } 2216} |
2182#endif /* VFS_AIO */ | |
2183 2184int 2185aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) 2186{ | 2217 2218int 2219aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) 2220{ |
2187#ifndef VFS_AIO 2188 return ENOSYS; 2189#else | |
2190 struct proc *p = td->td_proc; 2191 struct timeval atv; 2192 struct timespec ts; 2193 struct aiocb **cbptr; 2194 struct kaioinfo *ki; 2195 struct aiocblist *cb = NULL; 2196 int error, s, timo; 2197 --- 55 unchanged lines hidden (view full) --- 2253 return EINTR; 2254 else if (error < 0) 2255 return error; 2256 else if (error == EINTR) 2257 return EINTR; 2258 else if (error == EWOULDBLOCK) 2259 return EAGAIN; 2260 } | 2221 struct proc *p = td->td_proc; 2222 struct timeval atv; 2223 struct timespec ts; 2224 struct aiocb **cbptr; 2225 struct kaioinfo *ki; 2226 struct aiocblist *cb = NULL; 2227 int error, s, timo; 2228 --- 55 unchanged lines hidden (view full) --- 2284 return EINTR; 2285 else if (error < 0) 2286 return error; 2287 else if (error == EINTR) 2288 return EINTR; 2289 else if (error == EWOULDBLOCK) 2290 return EAGAIN; 2291 } |
2261#endif /* VFS_AIO */ | |
2262} 2263 | 2292} 2293 |
2264 2265#ifndef VFS_AIO | |
2266static int 2267filt_aioattach(struct knote *kn) 2268{ | 2294static int 2295filt_aioattach(struct knote *kn) 2296{ |
2269 2270 return (ENXIO); 2271} 2272 2273struct filterops aio_filtops = 2274 { 0, filt_aioattach, NULL, NULL }; 2275 2276#else 2277static int 2278filt_aioattach(struct knote *kn) 2279{ | |
2280 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2281 2282 /* 2283 * The aiocbe pointer must be validated before using it, so 2284 * registration is restricted to the kernel; the user cannot 2285 * set EV_FLAG1. 2286 */ 2287 if ((kn->kn_flags & EV_FLAG1) == 0) --- 21 unchanged lines hidden (view full) --- 2309 2310 kn->kn_data = aiocbe->uaiocb._aiocb_private.error; 2311 if (aiocbe->jobstate != JOBST_JOBFINISHED && 2312 aiocbe->jobstate != JOBST_JOBBFINISHED) 2313 return (0); 2314 kn->kn_flags |= EV_EOF; 2315 return (1); 2316} | 2297 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2298 2299 /* 2300 * The aiocbe pointer must be validated before using it, so 2301 * registration is restricted to the kernel; the user cannot 2302 * set EV_FLAG1. 2303 */ 2304 if ((kn->kn_flags & EV_FLAG1) == 0) --- 21 unchanged lines hidden (view full) --- 2326 2327 kn->kn_data = aiocbe->uaiocb._aiocb_private.error; 2328 if (aiocbe->jobstate != JOBST_JOBFINISHED && 2329 aiocbe->jobstate != JOBST_JOBBFINISHED) 2330 return (0); 2331 kn->kn_flags |= EV_EOF; 2332 return (1); 2333} |
2317 2318struct filterops aio_filtops = 2319 { 0, filt_aioattach, filt_aiodetach, filt_aio }; 2320#endif /* VFS_AIO */ | |