vfs_aio.c (91140) | vfs_aio.c (91690) |
---|---|
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 91140 2002-02-23 11:12:57Z tanimura $ | 16 * $FreeBSD: head/sys/kern/vfs_aio.c 91690 2002-03-05 15:38:49Z eivind $ |
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> --- 27 unchanged lines hidden (view full) --- 52#include <vm/vm_map.h> 53#include <vm/vm_zone.h> 54#include <sys/aio.h> 55 56#include <machine/limits.h> 57 58#include "opt_vfs_aio.h" 59 | 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> --- 27 unchanged lines hidden (view full) --- 52#include <vm/vm_map.h> 53#include <vm/vm_zone.h> 54#include <sys/aio.h> 55 56#include <machine/limits.h> 57 58#include "opt_vfs_aio.h" 59 |
60/* 61 * Counter for allocating reference ids to new jobs. Wrapped to 1 on 62 * overflow. 63 */ |
|
60static long jobrefid; 61 62#define JOBST_NULL 0x0 63#define JOBST_JOBQGLOBAL 0x2 64#define JOBST_JOBRUNNING 0x3 65#define JOBST_JOBFINISHED 0x4 66#define JOBST_JOBQBUF 0x5 67#define JOBST_JOBBFINISHED 0x6 --- 25 unchanged lines hidden (view full) --- 93#ifndef AIOD_TIMEOUT_DEFAULT 94#define AIOD_TIMEOUT_DEFAULT (10 * hz) 95#endif 96 97#ifndef AIOD_LIFETIME_DEFAULT 98#define AIOD_LIFETIME_DEFAULT (30 * hz) 99#endif 100 | 64static long jobrefid; 65 66#define JOBST_NULL 0x0 67#define JOBST_JOBQGLOBAL 0x2 68#define JOBST_JOBRUNNING 0x3 69#define JOBST_JOBFINISHED 0x4 70#define JOBST_JOBQBUF 0x5 71#define JOBST_JOBBFINISHED 0x6 --- 25 unchanged lines hidden (view full) --- 97#ifndef AIOD_TIMEOUT_DEFAULT 98#define AIOD_TIMEOUT_DEFAULT (10 * hz) 99#endif 100 101#ifndef AIOD_LIFETIME_DEFAULT 102#define AIOD_LIFETIME_DEFAULT (30 * hz) 103#endif 104 |
101static int max_aio_procs = MAX_AIO_PROCS; 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; | 105SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "Async IO management"); |
111 | 106 |
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, 119 CTLFLAG_RW, &max_aio_per_proc, 0, ""); 120 121SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, 122 CTLFLAG_RW, &max_aio_queue_per_proc, 0, ""); 123 | 107static int max_aio_procs = MAX_AIO_PROCS; |
124SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs, | 108SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs, |
125 CTLFLAG_RW, &max_aio_procs, 0, ""); | 109 CTLFLAG_RW, &max_aio_procs, 0, 110 "Maximum number of kernel threads to use for handling async IO "); |
126 | 111 |
112static int num_aio_procs = 0; |
|
127SYSCTL_INT(_vfs_aio, OID_AUTO, num_aio_procs, | 113SYSCTL_INT(_vfs_aio, OID_AUTO, num_aio_procs, |
128 CTLFLAG_RD, &num_aio_procs, 0, ""); | 114 CTLFLAG_RD, &num_aio_procs, 0, 115 "Number of presently active kernel threads for async IO"); |
129 | 116 |
130SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count, 131 CTLFLAG_RD, &num_queue_count, 0, ""); | 117/* 118 * The code will adjust the actual number of AIO processes towards this 119 * number when it gets a chance. 120 */ 121static int target_aio_procs = TARGET_AIO_PROCS; 122SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs, CTLFLAG_RW, &target_aio_procs, 123 0, "Preferred number of ready kernel threads for async IO"); |
132 | 124 |
133SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue, 134 CTLFLAG_RW, &max_queue_count, 0, ""); | 125static int max_queue_count = MAX_AIO_QUEUE; 126SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue, CTLFLAG_RW, &max_queue_count, 0, 127 "Maximum number of aio requests to queue, globally"); |
135 | 128 |
136SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs, 137 CTLFLAG_RW, &target_aio_procs, 0, ""); | 129static int num_queue_count = 0; 130SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count, CTLFLAG_RD, &num_queue_count, 0, 131 "Number of queued aio requests"); |
138 | 132 |
139SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, 140 CTLFLAG_RW, &max_buf_aio, 0, ""); | 133static int num_buf_aio = 0; 134SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, CTLFLAG_RD, &num_buf_aio, 0, 135 "Number of aio requests presently handled by the buf subsystem"); |
141 | 136 |
142SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, 143 CTLFLAG_RD, &num_buf_aio, 0, ""); | 137/* Number of async I/O thread in the process of being started */ 138/* XXX This should be local to _aio_aqueue() */ 139static int num_aio_resv_start = 0; |
144 | 140 |
145SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, 146 CTLFLAG_RW, &aiod_lifetime, 0, ""); | 141static int aiod_timeout; 142SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, CTLFLAG_RW, &aiod_timeout, 0, 143 "Timeout value for synchronous aio operations"); |
147 | 144 |
148SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, 149 CTLFLAG_RW, &aiod_timeout, 0, ""); | 145static int aiod_lifetime; 146SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, CTLFLAG_RW, &aiod_lifetime, 0, 147 "Maximum lifetime for idle aiod"); |
150 | 148 |
149static int unloadable = 0; |
|
151SYSCTL_INT(_vfs_aio, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0, 152 "Allow unload of aio (not recommended)"); 153 | 150SYSCTL_INT(_vfs_aio, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0, 151 "Allow unload of aio (not recommended)"); 152 |
153 154static int max_aio_per_proc = MAX_AIO_PER_PROC; 155SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, CTLFLAG_RW, &max_aio_per_proc, 156 0, "Maximum active aio requests per process (stored in the process)"); 157 158static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC; 159SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, CTLFLAG_RW, 160 &max_aio_queue_per_proc, 0, 161 "Maximum queued aio requests per process (stored in the process)"); 162 163static int max_buf_aio = MAX_BUF_AIO; 164SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, CTLFLAG_RW, &max_buf_aio, 0, 165 "Maximum buf aio requests per process (stored in the process)"); 166 |
|
154struct aiocblist { 155 TAILQ_ENTRY(aiocblist) list; /* List of jobs */ 156 TAILQ_ENTRY(aiocblist) plist; /* List of jobs for proc */ 157 int jobflags; 158 int jobstate; 159 int inputcharge; 160 int outputcharge; 161 struct callout_handle timeouthandle; --- 60 unchanged lines hidden (view full) --- 222 TAILQ_HEAD(,aiocblist) kaio_bufqueue; /* buffer job queue for process */ 223 TAILQ_HEAD(,aiocblist) kaio_bufdone; /* buffer done queue for process */ 224 TAILQ_HEAD(,aiocblist) kaio_sockqueue; /* queue for aios waiting on sockets */ 225}; 226 227#define KAIO_RUNDOWN 0x1 /* process is being run down */ 228#define KAIO_WAKEUP 0x2 /* wakeup process when there is a significant event */ 229 | 167struct aiocblist { 168 TAILQ_ENTRY(aiocblist) list; /* List of jobs */ 169 TAILQ_ENTRY(aiocblist) plist; /* List of jobs for proc */ 170 int jobflags; 171 int jobstate; 172 int inputcharge; 173 int outputcharge; 174 struct callout_handle timeouthandle; --- 60 unchanged lines hidden (view full) --- 235 TAILQ_HEAD(,aiocblist) kaio_bufqueue; /* buffer job queue for process */ 236 TAILQ_HEAD(,aiocblist) kaio_bufdone; /* buffer done queue for process */ 237 TAILQ_HEAD(,aiocblist) kaio_sockqueue; /* queue for aios waiting on sockets */ 238}; 239 240#define KAIO_RUNDOWN 0x1 /* process is being run down */ 241#define KAIO_WAKEUP 0x2 /* wakeup process when there is a significant event */ 242 |
230static TAILQ_HEAD(,aiothreadlist) aio_freeproc, aio_activeproc; | 243static TAILQ_HEAD(,aiothreadlist) aio_activeproc; /* Active daemons */ 244static TAILQ_HEAD(,aiothreadlist) aio_freeproc; /* Idle daemons */ |
231static TAILQ_HEAD(,aiocblist) aio_jobs; /* Async job list */ 232static TAILQ_HEAD(,aiocblist) aio_bufjobs; /* Phys I/O job list */ 233 234static void aio_init_aioinfo(struct proc *p); 235static void aio_onceonly(void); 236static int aio_free_entry(struct aiocblist *aiocbe); 237static void aio_process(struct aiocblist *aiocbe); 238static int aio_newproc(void); --- 5 unchanged lines hidden (view full) --- 244static void aio_daemon(void *uproc); 245static void aio_swake_cb(struct socket *, struct sockbuf *); 246static int aio_unload(void); 247static void process_signal(void *aioj); 248static int filt_aioattach(struct knote *kn); 249static void filt_aiodetach(struct knote *kn); 250static int filt_aio(struct knote *kn, long hint); 251 | 245static TAILQ_HEAD(,aiocblist) aio_jobs; /* Async job list */ 246static TAILQ_HEAD(,aiocblist) aio_bufjobs; /* Phys I/O job list */ 247 248static void aio_init_aioinfo(struct proc *p); 249static void aio_onceonly(void); 250static int aio_free_entry(struct aiocblist *aiocbe); 251static void aio_process(struct aiocblist *aiocbe); 252static int aio_newproc(void); --- 5 unchanged lines hidden (view full) --- 258static void aio_daemon(void *uproc); 259static void aio_swake_cb(struct socket *, struct sockbuf *); 260static int aio_unload(void); 261static void process_signal(void *aioj); 262static int filt_aioattach(struct knote *kn); 263static void filt_aiodetach(struct knote *kn); 264static int filt_aio(struct knote *kn, long hint); 265 |
252static vm_zone_t kaio_zone, aiop_zone, aiocb_zone, aiol_zone; 253static vm_zone_t aiolio_zone; | 266/* 267 * Zones for: 268 * kaio Per process async io info 269 * aiop async io thread data 270 * aiocb async io jobs 271 * aiol list io job pointer - internal to aio_suspend XXX 272 * aiolio list io jobs 273 */ 274static vm_zone_t kaio_zone, aiop_zone, aiocb_zone, aiol_zone, aiolio_zone; |
254 | 275 |
276/* kqueue filters for aio */ |
|
255static struct filterops aio_filtops = 256 { 0, filt_aioattach, filt_aiodetach, filt_aio }; 257 | 277static struct filterops aio_filtops = 278 { 0, filt_aioattach, filt_aiodetach, filt_aio }; 279 |
280/* 281 * Main operations function for use as a kernel module. 282 */ |
|
258static int 259aio_modload(struct module *module, int cmd, void *arg) 260{ 261 int error = 0; 262 263 switch (cmd) { 264 case MOD_LOAD: 265 aio_onceonly(); --- 50 unchanged lines hidden (view full) --- 316 aiocb_zone = zinit("AIOCB", sizeof(struct aiocblist), 0, 0, 1); 317 aiol_zone = zinit("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t), 0, 0, 1); 318 aiolio_zone = zinit("AIOLIO", sizeof(struct aio_liojob), 0, 0, 1); 319 aiod_timeout = AIOD_TIMEOUT_DEFAULT; 320 aiod_lifetime = AIOD_LIFETIME_DEFAULT; 321 jobrefid = 1; 322} 323 | 283static int 284aio_modload(struct module *module, int cmd, void *arg) 285{ 286 int error = 0; 287 288 switch (cmd) { 289 case MOD_LOAD: 290 aio_onceonly(); --- 50 unchanged lines hidden (view full) --- 341 aiocb_zone = zinit("AIOCB", sizeof(struct aiocblist), 0, 0, 1); 342 aiol_zone = zinit("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t), 0, 0, 1); 343 aiolio_zone = zinit("AIOLIO", sizeof(struct aio_liojob), 0, 0, 1); 344 aiod_timeout = AIOD_TIMEOUT_DEFAULT; 345 aiod_lifetime = AIOD_LIFETIME_DEFAULT; 346 jobrefid = 1; 347} 348 |
349/* 350 * Callback for unload of AIO when used as a module. 351 */ |
|
324static int 325aio_unload(void) 326{ 327 328 /* 329 * XXX: no unloads by default, it's too dangerous. 330 * perhaps we could do it if locked out callers and then 331 * did an aio_proc_rundown() on each process. --- 447 unchanged lines hidden (view full) --- 779 /* 780 * Get rid of our current filedescriptors. AIOD's don't need any 781 * filedescriptors, except as temporarily inherited from the client. 782 */ 783 fdfree(td); 784 mycp->p_fd = NULL; 785 786 /* The daemon resides in its own pgrp. */ | 352static int 353aio_unload(void) 354{ 355 356 /* 357 * XXX: no unloads by default, it's too dangerous. 358 * perhaps we could do it if locked out callers and then 359 * did an aio_proc_rundown() on each process. --- 447 unchanged lines hidden (view full) --- 807 /* 808 * Get rid of our current filedescriptors. AIOD's don't need any 809 * filedescriptors, except as temporarily inherited from the client. 810 */ 811 fdfree(td); 812 mycp->p_fd = NULL; 813 814 /* The daemon resides in its own pgrp. */ |
787 MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 788 MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); | 815 MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 816 M_WAITOK | M_ZERO); 817 MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, 818 M_WAITOK | M_ZERO); |
789 790 PGRPSESS_XLOCK(); 791 enterpgrp(mycp, mycp->p_pid, newpgrp, newsess); 792 PGRPSESS_XUNLOCK(); 793 794 /* Mark special process type. */ 795 mycp->p_flag |= P_SYSTEM; 796 --- 1129 unchanged lines hidden (view full) --- 1926 */ 1927 status = fuword(&uap->aiocbp->_aiocb_private.status); 1928 if (status == -1) 1929 return fuword(&uap->aiocbp->_aiocb_private.error); 1930#endif 1931 return EINVAL; 1932} 1933 | 819 820 PGRPSESS_XLOCK(); 821 enterpgrp(mycp, mycp->p_pid, newpgrp, newsess); 822 PGRPSESS_XUNLOCK(); 823 824 /* Mark special process type. */ 825 mycp->p_flag |= P_SYSTEM; 826 --- 1129 unchanged lines hidden (view full) --- 1956 */ 1957 status = fuword(&uap->aiocbp->_aiocb_private.status); 1958 if (status == -1) 1959 return fuword(&uap->aiocbp->_aiocb_private.error); 1960#endif 1961 return EINVAL; 1962} 1963 |
1964/* syscall - asynchronous read from a file (REALTIME) */ |
|
1934int 1935aio_read(struct thread *td, struct aio_read_args *uap) 1936{ 1937 1938 return aio_aqueue(td, uap->aiocbp, LIO_READ); 1939} 1940 | 1965int 1966aio_read(struct thread *td, struct aio_read_args *uap) 1967{ 1968 1969 return aio_aqueue(td, uap->aiocbp, LIO_READ); 1970} 1971 |
1972/* syscall - asynchronous write to a file (REALTIME) */ |
|
1941int 1942aio_write(struct thread *td, struct aio_write_args *uap) 1943{ 1944 1945 return aio_aqueue(td, uap->aiocbp, LIO_WRITE); 1946} 1947 | 1973int 1974aio_write(struct thread *td, struct aio_write_args *uap) 1975{ 1976 1977 return aio_aqueue(td, uap->aiocbp, LIO_WRITE); 1978} 1979 |
1980/* syscall - XXX undocumented */ |
|
1948int 1949lio_listio(struct thread *td, struct lio_listio_args *uap) 1950{ 1951 struct proc *p = td->td_proc; 1952 int nent, nentqueued; 1953 struct aiocb *iocb, * const *cbptr; 1954 struct aiocblist *cb; 1955 struct kaioinfo *ki; --- 249 unchanged lines hidden (view full) --- 2205 } 2206 2207 if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL) 2208 aiocbe->timeouthandle = 2209 timeout(process_signal, aiocbe, 0); 2210 } 2211} 2212 | 1981int 1982lio_listio(struct thread *td, struct lio_listio_args *uap) 1983{ 1984 struct proc *p = td->td_proc; 1985 int nent, nentqueued; 1986 struct aiocb *iocb, * const *cbptr; 1987 struct aiocblist *cb; 1988 struct kaioinfo *ki; --- 249 unchanged lines hidden (view full) --- 2238 } 2239 2240 if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL) 2241 aiocbe->timeouthandle = 2242 timeout(process_signal, aiocbe, 0); 2243 } 2244} 2245 |
2246/* syscall - wait for the next completion of an aio request */ |
|
2213int 2214aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) 2215{ 2216 struct proc *p = td->td_proc; 2217 struct timeval atv; 2218 struct timespec ts; 2219 struct aiocb **cbptr; 2220 struct kaioinfo *ki; --- 59 unchanged lines hidden (view full) --- 2280 return error; 2281 else if (error == EINTR) 2282 return EINTR; 2283 else if (error == EWOULDBLOCK) 2284 return EAGAIN; 2285 } 2286} 2287 | 2247int 2248aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) 2249{ 2250 struct proc *p = td->td_proc; 2251 struct timeval atv; 2252 struct timespec ts; 2253 struct aiocb **cbptr; 2254 struct kaioinfo *ki; --- 59 unchanged lines hidden (view full) --- 2314 return error; 2315 else if (error == EINTR) 2316 return EINTR; 2317 else if (error == EWOULDBLOCK) 2318 return EAGAIN; 2319 } 2320} 2321 |
2322/* kqueue attach function */ |
|
2288static int 2289filt_aioattach(struct knote *kn) 2290{ 2291 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2292 2293 /* 2294 * The aiocbe pointer must be validated before using it, so 2295 * registration is restricted to the kernel; the user cannot 2296 * set EV_FLAG1. 2297 */ 2298 if ((kn->kn_flags & EV_FLAG1) == 0) 2299 return (EPERM); 2300 kn->kn_flags &= ~EV_FLAG1; 2301 2302 SLIST_INSERT_HEAD(&aiocbe->klist, kn, kn_selnext); 2303 2304 return (0); 2305} 2306 | 2323static int 2324filt_aioattach(struct knote *kn) 2325{ 2326 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2327 2328 /* 2329 * The aiocbe pointer must be validated before using it, so 2330 * registration is restricted to the kernel; the user cannot 2331 * set EV_FLAG1. 2332 */ 2333 if ((kn->kn_flags & EV_FLAG1) == 0) 2334 return (EPERM); 2335 kn->kn_flags &= ~EV_FLAG1; 2336 2337 SLIST_INSERT_HEAD(&aiocbe->klist, kn, kn_selnext); 2338 2339 return (0); 2340} 2341 |
2342/* kqueue detach function */ |
|
2307static void 2308filt_aiodetach(struct knote *kn) 2309{ 2310 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2311 2312 SLIST_REMOVE(&aiocbe->klist, kn, knote, kn_selnext); 2313} 2314 | 2343static void 2344filt_aiodetach(struct knote *kn) 2345{ 2346 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2347 2348 SLIST_REMOVE(&aiocbe->klist, kn, knote, kn_selnext); 2349} 2350 |
2351/* kqueue filter function */ |
|
2315/*ARGSUSED*/ 2316static int 2317filt_aio(struct knote *kn, long hint) 2318{ 2319 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2320 2321 kn->kn_data = aiocbe->uaiocb._aiocb_private.error; 2322 if (aiocbe->jobstate != JOBST_JOBFINISHED && 2323 aiocbe->jobstate != JOBST_JOBBFINISHED) 2324 return (0); 2325 kn->kn_flags |= EV_EOF; 2326 return (1); 2327} | 2352/*ARGSUSED*/ 2353static int 2354filt_aio(struct knote *kn, long hint) 2355{ 2356 struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id; 2357 2358 kn->kn_data = aiocbe->uaiocb._aiocb_private.error; 2359 if (aiocbe->jobstate != JOBST_JOBFINISHED && 2360 aiocbe->jobstate != JOBST_JOBBFINISHED) 2361 return (0); 2362 kn->kn_flags |= EV_EOF; 2363 return (1); 2364} |