Deleted Added
full compact
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}