The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_aio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/5.1/sys/kern/vfs_aio.c 114216 2003-04-29 13:36:06Z kan $
   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>
   25 #include <sys/malloc.h>
   26 #include <sys/bio.h>
   27 #include <sys/buf.h>
   28 #include <sys/eventhandler.h>
   29 #include <sys/sysproto.h>
   30 #include <sys/filedesc.h>
   31 #include <sys/kernel.h>
   32 #include <sys/kthread.h>
   33 #include <sys/fcntl.h>
   34 #include <sys/file.h>
   35 #include <sys/limits.h>
   36 #include <sys/lock.h>
   37 #include <sys/mutex.h>
   38 #include <sys/unistd.h>
   39 #include <sys/proc.h>
   40 #include <sys/resourcevar.h>
   41 #include <sys/signalvar.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socketvar.h>
   44 #include <sys/syscall.h>
   45 #include <sys/sysent.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/sx.h>
   48 #include <sys/vnode.h>
   49 #include <sys/conf.h>
   50 #include <sys/event.h>
   51 
   52 #include <posix4/posix4.h>
   53 #include <vm/vm.h>
   54 #include <vm/vm_extern.h>
   55 #include <vm/pmap.h>
   56 #include <vm/vm_map.h>
   57 #include <vm/uma.h>
   58 #include <sys/aio.h>
   59 
   60 #include "opt_vfs_aio.h"
   61 
   62 /*
   63  * Counter for allocating reference ids to new jobs.  Wrapped to 1 on
   64  * overflow.
   65  */
   66 static  long jobrefid;
   67 
   68 #define JOBST_NULL              0x0
   69 #define JOBST_JOBQGLOBAL        0x2
   70 #define JOBST_JOBRUNNING        0x3
   71 #define JOBST_JOBFINISHED       0x4
   72 #define JOBST_JOBQBUF           0x5
   73 #define JOBST_JOBBFINISHED      0x6
   74 
   75 #ifndef MAX_AIO_PER_PROC
   76 #define MAX_AIO_PER_PROC        32
   77 #endif
   78 
   79 #ifndef MAX_AIO_QUEUE_PER_PROC
   80 #define MAX_AIO_QUEUE_PER_PROC  256 /* Bigger than AIO_LISTIO_MAX */
   81 #endif
   82 
   83 #ifndef MAX_AIO_PROCS
   84 #define MAX_AIO_PROCS           32
   85 #endif
   86 
   87 #ifndef MAX_AIO_QUEUE
   88 #define MAX_AIO_QUEUE           1024 /* Bigger than AIO_LISTIO_MAX */
   89 #endif
   90 
   91 #ifndef TARGET_AIO_PROCS
   92 #define TARGET_AIO_PROCS        4
   93 #endif
   94 
   95 #ifndef MAX_BUF_AIO
   96 #define MAX_BUF_AIO             16
   97 #endif
   98 
   99 #ifndef AIOD_TIMEOUT_DEFAULT
  100 #define AIOD_TIMEOUT_DEFAULT    (10 * hz)
  101 #endif
  102 
  103 #ifndef AIOD_LIFETIME_DEFAULT
  104 #define AIOD_LIFETIME_DEFAULT   (30 * hz)
  105 #endif
  106 
  107 SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "Async IO management");
  108 
  109 static int max_aio_procs = MAX_AIO_PROCS;
  110 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs,
  111         CTLFLAG_RW, &max_aio_procs, 0,
  112         "Maximum number of kernel threads to use for handling async IO ");
  113 
  114 static int num_aio_procs = 0;
  115 SYSCTL_INT(_vfs_aio, OID_AUTO, num_aio_procs,
  116         CTLFLAG_RD, &num_aio_procs, 0,
  117         "Number of presently active kernel threads for async IO");
  118 
  119 /*
  120  * The code will adjust the actual number of AIO processes towards this
  121  * number when it gets a chance.
  122  */
  123 static int target_aio_procs = TARGET_AIO_PROCS;
  124 SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs, CTLFLAG_RW, &target_aio_procs,
  125         0, "Preferred number of ready kernel threads for async IO");
  126 
  127 static int max_queue_count = MAX_AIO_QUEUE;
  128 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue, CTLFLAG_RW, &max_queue_count, 0,
  129     "Maximum number of aio requests to queue, globally");
  130 
  131 static int num_queue_count = 0;
  132 SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count, CTLFLAG_RD, &num_queue_count, 0,
  133     "Number of queued aio requests");
  134 
  135 static int num_buf_aio = 0;
  136 SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, CTLFLAG_RD, &num_buf_aio, 0,
  137     "Number of aio requests presently handled by the buf subsystem");
  138 
  139 /* Number of async I/O thread in the process of being started */
  140 /* XXX This should be local to _aio_aqueue() */
  141 static int num_aio_resv_start = 0;
  142 
  143 static int aiod_timeout;
  144 SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, CTLFLAG_RW, &aiod_timeout, 0,
  145     "Timeout value for synchronous aio operations");
  146 
  147 static int aiod_lifetime;
  148 SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, CTLFLAG_RW, &aiod_lifetime, 0,
  149     "Maximum lifetime for idle aiod");
  150 
  151 static int unloadable = 0;
  152 SYSCTL_INT(_vfs_aio, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0,
  153     "Allow unload of aio (not recommended)");
  154 
  155 
  156 static int max_aio_per_proc = MAX_AIO_PER_PROC;
  157 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, CTLFLAG_RW, &max_aio_per_proc,
  158     0, "Maximum active aio requests per process (stored in the process)");
  159 
  160 static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC;
  161 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, CTLFLAG_RW,
  162     &max_aio_queue_per_proc, 0,
  163     "Maximum queued aio requests per process (stored in the process)");
  164 
  165 static int max_buf_aio = MAX_BUF_AIO;
  166 SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, CTLFLAG_RW, &max_buf_aio, 0,
  167     "Maximum buf aio requests per process (stored in the process)");
  168 
  169 struct aiocblist {
  170         TAILQ_ENTRY(aiocblist) list;    /* List of jobs */
  171         TAILQ_ENTRY(aiocblist) plist;   /* List of jobs for proc */
  172         int     jobflags;
  173         int     jobstate;
  174         int     inputcharge;
  175         int     outputcharge;
  176         struct  callout_handle timeouthandle;
  177         struct  buf *bp;                /* Buffer pointer */
  178         struct  proc *userproc;         /* User process */ /* Not td! */
  179         struct  ucred *cred;            /* Active credential when created */
  180         struct  file *fd_file;          /* Pointer to file structure */ 
  181         struct  aio_liojob *lio;        /* Optional lio job */
  182         struct  aiocb *uuaiocb;         /* Pointer in userspace of aiocb */
  183         struct  klist klist;            /* list of knotes */
  184         struct  aiocb uaiocb;           /* Kernel I/O control block */
  185 };
  186 
  187 /* jobflags */
  188 #define AIOCBLIST_RUNDOWN       0x4
  189 #define AIOCBLIST_DONE          0x10
  190 
  191 /*
  192  * AIO process info
  193  */
  194 #define AIOP_FREE       0x1                     /* proc on free queue */
  195 #define AIOP_SCHED      0x2                     /* proc explicitly scheduled */
  196 
  197 struct aiothreadlist {
  198         int aiothreadflags;                     /* AIO proc flags */
  199         TAILQ_ENTRY(aiothreadlist) list;        /* List of processes */
  200         struct thread *aiothread;               /* The AIO thread */
  201 };
  202 
  203 /*
  204  * data-structure for lio signal management
  205  */
  206 struct aio_liojob {
  207         int     lioj_flags;
  208         int     lioj_buffer_count;
  209         int     lioj_buffer_finished_count;
  210         int     lioj_queue_count;
  211         int     lioj_queue_finished_count;
  212         struct  sigevent lioj_signal;   /* signal on all I/O done */
  213         TAILQ_ENTRY(aio_liojob) lioj_list;
  214         struct  kaioinfo *lioj_ki;
  215 };
  216 #define LIOJ_SIGNAL             0x1     /* signal on all done (lio) */
  217 #define LIOJ_SIGNAL_POSTED      0x2     /* signal has been posted */
  218 
  219 /*
  220  * per process aio data structure
  221  */
  222 struct kaioinfo {
  223         int     kaio_flags;             /* per process kaio flags */
  224         int     kaio_maxactive_count;   /* maximum number of AIOs */
  225         int     kaio_active_count;      /* number of currently used AIOs */
  226         int     kaio_qallowed_count;    /* maxiumu size of AIO queue */
  227         int     kaio_queue_count;       /* size of AIO queue */
  228         int     kaio_ballowed_count;    /* maximum number of buffers */
  229         int     kaio_queue_finished_count; /* number of daemon jobs finished */
  230         int     kaio_buffer_count;      /* number of physio buffers */
  231         int     kaio_buffer_finished_count; /* count of I/O done */
  232         struct  proc *kaio_p;           /* process that uses this kaio block */
  233         TAILQ_HEAD(,aio_liojob) kaio_liojoblist; /* list of lio jobs */
  234         TAILQ_HEAD(,aiocblist) kaio_jobqueue;   /* job queue for process */
  235         TAILQ_HEAD(,aiocblist) kaio_jobdone;    /* done queue for process */
  236         TAILQ_HEAD(,aiocblist) kaio_bufqueue;   /* buffer job queue for process */
  237         TAILQ_HEAD(,aiocblist) kaio_bufdone;    /* buffer done queue for process */
  238         TAILQ_HEAD(,aiocblist) kaio_sockqueue;  /* queue for aios waiting on sockets */
  239 };
  240 
  241 #define KAIO_RUNDOWN    0x1     /* process is being run down */
  242 #define KAIO_WAKEUP     0x2     /* wakeup process when there is a significant event */
  243 
  244 static TAILQ_HEAD(,aiothreadlist) aio_activeproc;       /* Active daemons */
  245 static TAILQ_HEAD(,aiothreadlist) aio_freeproc;         /* Idle daemons */
  246 static TAILQ_HEAD(,aiocblist) aio_jobs;                 /* Async job list */
  247 static TAILQ_HEAD(,aiocblist) aio_bufjobs;              /* Phys I/O job list */
  248 
  249 static void     aio_init_aioinfo(struct proc *p);
  250 static void     aio_onceonly(void);
  251 static int      aio_free_entry(struct aiocblist *aiocbe);
  252 static void     aio_process(struct aiocblist *aiocbe);
  253 static int      aio_newproc(void);
  254 static int      aio_aqueue(struct thread *td, struct aiocb *job, int type);
  255 static void     aio_physwakeup(struct buf *bp);
  256 static void     aio_proc_rundown(void *arg, struct proc *p);
  257 static int      aio_fphysio(struct aiocblist *aiocbe);
  258 static int      aio_qphysio(struct proc *p, struct aiocblist *iocb);
  259 static void     aio_daemon(void *uproc);
  260 static void     aio_swake_cb(struct socket *, struct sockbuf *);
  261 static int      aio_unload(void);
  262 static void     process_signal(void *aioj);
  263 static int      filt_aioattach(struct knote *kn);
  264 static void     filt_aiodetach(struct knote *kn);
  265 static int      filt_aio(struct knote *kn, long hint);
  266 
  267 /*
  268  * Zones for:
  269  *      kaio    Per process async io info
  270  *      aiop    async io thread data
  271  *      aiocb   async io jobs
  272  *      aiol    list io job pointer - internal to aio_suspend XXX
  273  *      aiolio  list io jobs
  274  */
  275 static uma_zone_t kaio_zone, aiop_zone, aiocb_zone, aiol_zone, aiolio_zone;
  276 
  277 /* kqueue filters for aio */
  278 static struct filterops aio_filtops =
  279         { 0, filt_aioattach, filt_aiodetach, filt_aio };
  280 
  281 static eventhandler_tag exit_tag, exec_tag;
  282 
  283 /*
  284  * Main operations function for use as a kernel module.
  285  */
  286 static int
  287 aio_modload(struct module *module, int cmd, void *arg)
  288 {
  289         int error = 0;
  290 
  291         switch (cmd) {
  292         case MOD_LOAD:
  293                 aio_onceonly();
  294                 break;
  295         case MOD_UNLOAD:
  296                 error = aio_unload();
  297                 break;
  298         case MOD_SHUTDOWN:
  299                 break;
  300         default:
  301                 error = EINVAL;
  302                 break;
  303         }
  304         return (error);
  305 }
  306 
  307 static moduledata_t aio_mod = {
  308         "aio",
  309         &aio_modload,
  310         NULL
  311 };
  312 
  313 SYSCALL_MODULE_HELPER(aio_return);
  314 SYSCALL_MODULE_HELPER(aio_suspend);
  315 SYSCALL_MODULE_HELPER(aio_cancel);
  316 SYSCALL_MODULE_HELPER(aio_error);
  317 SYSCALL_MODULE_HELPER(aio_read);
  318 SYSCALL_MODULE_HELPER(aio_write);
  319 SYSCALL_MODULE_HELPER(aio_waitcomplete);
  320 SYSCALL_MODULE_HELPER(lio_listio);
  321 
  322 DECLARE_MODULE(aio, aio_mod,
  323         SI_SUB_VFS, SI_ORDER_ANY);
  324 MODULE_VERSION(aio, 1);
  325 
  326 /*
  327  * Startup initialization
  328  */
  329 static void
  330 aio_onceonly(void)
  331 {
  332 
  333         /* XXX: should probably just use so->callback */
  334         aio_swake = &aio_swake_cb;
  335         exit_tag = EVENTHANDLER_REGISTER(process_exit, aio_proc_rundown, NULL,
  336             EVENTHANDLER_PRI_ANY);
  337         exec_tag = EVENTHANDLER_REGISTER(process_exec, aio_proc_rundown, NULL,
  338             EVENTHANDLER_PRI_ANY);
  339         kqueue_add_filteropts(EVFILT_AIO, &aio_filtops);
  340         TAILQ_INIT(&aio_freeproc);
  341         TAILQ_INIT(&aio_activeproc);
  342         TAILQ_INIT(&aio_jobs);
  343         TAILQ_INIT(&aio_bufjobs);
  344         kaio_zone = uma_zcreate("AIO", sizeof(struct kaioinfo), NULL, NULL,
  345             NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
  346         aiop_zone = uma_zcreate("AIOP", sizeof(struct aiothreadlist), NULL,
  347             NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
  348         aiocb_zone = uma_zcreate("AIOCB", sizeof(struct aiocblist), NULL, NULL,
  349             NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
  350         aiol_zone = uma_zcreate("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t) , NULL,
  351             NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
  352         aiolio_zone = uma_zcreate("AIOLIO", sizeof(struct aio_liojob), NULL,
  353             NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
  354         aiod_timeout = AIOD_TIMEOUT_DEFAULT;
  355         aiod_lifetime = AIOD_LIFETIME_DEFAULT;
  356         jobrefid = 1;
  357         async_io_version = _POSIX_VERSION;
  358         p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, AIO_LISTIO_MAX);
  359         p31b_setcfg(CTL_P1003_1B_AIO_MAX, MAX_AIO_QUEUE);
  360         p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, 0);
  361 }
  362 
  363 /*
  364  * Callback for unload of AIO when used as a module.
  365  */
  366 static int
  367 aio_unload(void)
  368 {
  369 
  370         /*
  371          * XXX: no unloads by default, it's too dangerous.
  372          * perhaps we could do it if locked out callers and then
  373          * did an aio_proc_rundown() on each process.
  374          */
  375         if (!unloadable)
  376                 return (EOPNOTSUPP);
  377 
  378         async_io_version = 0;
  379         aio_swake = NULL;
  380         EVENTHANDLER_DEREGISTER(process_exit, exit_tag);
  381         EVENTHANDLER_DEREGISTER(process_exec, exec_tag);
  382         kqueue_del_filteropts(EVFILT_AIO);
  383         p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, -1);
  384         p31b_setcfg(CTL_P1003_1B_AIO_MAX, -1);
  385         p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, -1);
  386         return (0);
  387 }
  388 
  389 /*
  390  * Init the per-process aioinfo structure.  The aioinfo limits are set
  391  * per-process for user limit (resource) management.
  392  */
  393 static void
  394 aio_init_aioinfo(struct proc *p)
  395 {
  396         struct kaioinfo *ki;
  397 
  398         if (p->p_aioinfo == NULL) {
  399                 ki = uma_zalloc(kaio_zone, M_WAITOK);
  400                 p->p_aioinfo = ki;
  401                 ki->kaio_flags = 0;
  402                 ki->kaio_maxactive_count = max_aio_per_proc;
  403                 ki->kaio_active_count = 0;
  404                 ki->kaio_qallowed_count = max_aio_queue_per_proc;
  405                 ki->kaio_queue_count = 0;
  406                 ki->kaio_ballowed_count = max_buf_aio;
  407                 ki->kaio_buffer_count = 0;
  408                 ki->kaio_buffer_finished_count = 0;
  409                 ki->kaio_p = p;
  410                 TAILQ_INIT(&ki->kaio_jobdone);
  411                 TAILQ_INIT(&ki->kaio_jobqueue);
  412                 TAILQ_INIT(&ki->kaio_bufdone);
  413                 TAILQ_INIT(&ki->kaio_bufqueue);
  414                 TAILQ_INIT(&ki->kaio_liojoblist);
  415                 TAILQ_INIT(&ki->kaio_sockqueue);
  416         }
  417         
  418         while (num_aio_procs < target_aio_procs)
  419                 aio_newproc();
  420 }
  421 
  422 /*
  423  * Free a job entry.  Wait for completion if it is currently active, but don't
  424  * delay forever.  If we delay, we return a flag that says that we have to
  425  * restart the queue scan.
  426  */
  427 static int
  428 aio_free_entry(struct aiocblist *aiocbe)
  429 {
  430         struct kaioinfo *ki;
  431         struct aio_liojob *lj;
  432         struct proc *p;
  433         int error;
  434         int s;
  435 
  436         if (aiocbe->jobstate == JOBST_NULL)
  437                 panic("aio_free_entry: freeing already free job");
  438 
  439         p = aiocbe->userproc;
  440         ki = p->p_aioinfo;
  441         lj = aiocbe->lio;
  442         if (ki == NULL)
  443                 panic("aio_free_entry: missing p->p_aioinfo");
  444 
  445         while (aiocbe->jobstate == JOBST_JOBRUNNING) {
  446                 aiocbe->jobflags |= AIOCBLIST_RUNDOWN;
  447                 tsleep(aiocbe, PRIBIO, "jobwai", 0);
  448         }
  449         if (aiocbe->bp == NULL) {
  450                 if (ki->kaio_queue_count <= 0)
  451                         panic("aio_free_entry: process queue size <= 0");
  452                 if (num_queue_count <= 0)
  453                         panic("aio_free_entry: system wide queue size <= 0");
  454         
  455                 if (lj) {
  456                         lj->lioj_queue_count--;
  457                         if (aiocbe->jobflags & AIOCBLIST_DONE)
  458                                 lj->lioj_queue_finished_count--;
  459                 }
  460                 ki->kaio_queue_count--;
  461                 if (aiocbe->jobflags & AIOCBLIST_DONE)
  462                         ki->kaio_queue_finished_count--;
  463                 num_queue_count--;
  464         } else {
  465                 if (lj) {
  466                         lj->lioj_buffer_count--;
  467                         if (aiocbe->jobflags & AIOCBLIST_DONE)
  468                                 lj->lioj_buffer_finished_count--;
  469                 }
  470                 if (aiocbe->jobflags & AIOCBLIST_DONE)
  471                         ki->kaio_buffer_finished_count--;
  472                 ki->kaio_buffer_count--;
  473                 num_buf_aio--;
  474         }
  475 
  476         /* aiocbe is going away, we need to destroy any knotes */
  477         /* XXXKSE Note the thread here is used to eventually find the 
  478          * owning process again, but it is also used to do a fo_close
  479          * and that requires the thread. (but does it require the
  480          * OWNING thread? (or maybe the running thread?)
  481          * There is a semantic problem here... 
  482          */
  483         knote_remove(FIRST_THREAD_IN_PROC(p), &aiocbe->klist); /* XXXKSE */
  484 
  485         if ((ki->kaio_flags & KAIO_WAKEUP) || ((ki->kaio_flags & KAIO_RUNDOWN)
  486             && ((ki->kaio_buffer_count == 0) && (ki->kaio_queue_count == 0)))) {
  487                 ki->kaio_flags &= ~KAIO_WAKEUP;
  488                 wakeup(p);
  489         }
  490 
  491         if (aiocbe->jobstate == JOBST_JOBQBUF) {
  492                 if ((error = aio_fphysio(aiocbe)) != 0)
  493                         return (error);
  494                 if (aiocbe->jobstate != JOBST_JOBBFINISHED)
  495                         panic("aio_free_entry: invalid physio finish-up state");
  496                 s = splbio();
  497                 TAILQ_REMOVE(&ki->kaio_bufdone, aiocbe, plist);
  498                 splx(s);
  499         } else if (aiocbe->jobstate == JOBST_JOBQGLOBAL) {
  500                 s = splnet();
  501                 TAILQ_REMOVE(&aio_jobs, aiocbe, list);
  502                 TAILQ_REMOVE(&ki->kaio_jobqueue, aiocbe, plist);
  503                 splx(s);
  504         } else if (aiocbe->jobstate == JOBST_JOBFINISHED)
  505                 TAILQ_REMOVE(&ki->kaio_jobdone, aiocbe, plist);
  506         else if (aiocbe->jobstate == JOBST_JOBBFINISHED) {
  507                 s = splbio();
  508                 TAILQ_REMOVE(&ki->kaio_bufdone, aiocbe, plist);
  509                 splx(s);
  510                 if (aiocbe->bp) {
  511                         vunmapbuf(aiocbe->bp);
  512                         relpbuf(aiocbe->bp, NULL);
  513                         aiocbe->bp = NULL;
  514                 }
  515         }
  516         if (lj && (lj->lioj_buffer_count == 0) && (lj->lioj_queue_count == 0)) {
  517                 TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list);
  518                 uma_zfree(aiolio_zone, lj);
  519         }
  520         aiocbe->jobstate = JOBST_NULL;
  521         untimeout(process_signal, aiocbe, aiocbe->timeouthandle);
  522         fdrop(aiocbe->fd_file, curthread);
  523         crfree(aiocbe->cred);
  524         uma_zfree(aiocb_zone, aiocbe);
  525         return (0);
  526 }
  527 
  528 /*
  529  * Rundown the jobs for a given process.  
  530  */
  531 static void
  532 aio_proc_rundown(void *arg, struct proc *p)
  533 {
  534         int s;
  535         struct kaioinfo *ki;
  536         struct aio_liojob *lj, *ljn;
  537         struct aiocblist *aiocbe, *aiocbn;
  538         struct file *fp;
  539         struct socket *so;
  540 
  541         ki = p->p_aioinfo;
  542         if (ki == NULL)
  543                 return;
  544 
  545         ki->kaio_flags |= LIOJ_SIGNAL_POSTED;
  546         while ((ki->kaio_active_count > 0) || (ki->kaio_buffer_count >
  547             ki->kaio_buffer_finished_count)) {
  548                 ki->kaio_flags |= KAIO_RUNDOWN;
  549                 if (tsleep(p, PRIBIO, "kaiowt", aiod_timeout))
  550                         break;
  551         }
  552 
  553         /*
  554          * Move any aio ops that are waiting on socket I/O to the normal job
  555          * queues so they are cleaned up with any others.
  556          */
  557         s = splnet();
  558         for (aiocbe = TAILQ_FIRST(&ki->kaio_sockqueue); aiocbe; aiocbe =
  559             aiocbn) {
  560                 aiocbn = TAILQ_NEXT(aiocbe, plist);
  561                 fp = aiocbe->fd_file;
  562                 if (fp != NULL) {
  563                         so = fp->f_data;
  564                         TAILQ_REMOVE(&so->so_aiojobq, aiocbe, list);
  565                         if (TAILQ_EMPTY(&so->so_aiojobq)) {
  566                                 so->so_snd.sb_flags &= ~SB_AIO;
  567                                 so->so_rcv.sb_flags &= ~SB_AIO;
  568                         }
  569                 }
  570                 TAILQ_REMOVE(&ki->kaio_sockqueue, aiocbe, plist);
  571                 TAILQ_INSERT_HEAD(&aio_jobs, aiocbe, list);
  572                 TAILQ_INSERT_HEAD(&ki->kaio_jobqueue, aiocbe, plist);
  573         }
  574         splx(s);
  575 
  576 restart1:
  577         for (aiocbe = TAILQ_FIRST(&ki->kaio_jobdone); aiocbe; aiocbe = aiocbn) {
  578                 aiocbn = TAILQ_NEXT(aiocbe, plist);
  579                 if (aio_free_entry(aiocbe))
  580                         goto restart1;
  581         }
  582 
  583 restart2:
  584         for (aiocbe = TAILQ_FIRST(&ki->kaio_jobqueue); aiocbe; aiocbe =
  585             aiocbn) {
  586                 aiocbn = TAILQ_NEXT(aiocbe, plist);
  587                 if (aio_free_entry(aiocbe))
  588                         goto restart2;
  589         }
  590 
  591 /*
  592  * Note the use of lots of splbio here, trying to avoid splbio for long chains
  593  * of I/O.  Probably unnecessary.
  594  */
  595 restart3:
  596         s = splbio();
  597         while (TAILQ_FIRST(&ki->kaio_bufqueue)) {
  598                 ki->kaio_flags |= KAIO_WAKEUP;
  599                 tsleep(p, PRIBIO, "aioprn", 0);
  600                 splx(s);
  601                 goto restart3;
  602         }
  603         splx(s);
  604 
  605 restart4:
  606         s = splbio();
  607         for (aiocbe = TAILQ_FIRST(&ki->kaio_bufdone); aiocbe; aiocbe = aiocbn) {
  608                 aiocbn = TAILQ_NEXT(aiocbe, plist);
  609                 if (aio_free_entry(aiocbe)) {
  610                         splx(s);
  611                         goto restart4;
  612                 }
  613         }
  614         splx(s);
  615 
  616         /*
  617          * If we've slept, jobs might have moved from one queue to another.
  618          * Retry rundown if we didn't manage to empty the queues.
  619          */
  620         if (TAILQ_FIRST(&ki->kaio_jobdone) != NULL ||
  621             TAILQ_FIRST(&ki->kaio_jobqueue) != NULL ||
  622             TAILQ_FIRST(&ki->kaio_bufqueue) != NULL ||
  623             TAILQ_FIRST(&ki->kaio_bufdone) != NULL)
  624                 goto restart1;
  625 
  626         for (lj = TAILQ_FIRST(&ki->kaio_liojoblist); lj; lj = ljn) {
  627                 ljn = TAILQ_NEXT(lj, lioj_list);
  628                 if ((lj->lioj_buffer_count == 0) && (lj->lioj_queue_count ==
  629                     0)) {
  630                         TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list);
  631                         uma_zfree(aiolio_zone, lj);
  632                 } else {
  633 #ifdef DIAGNOSTIC
  634                         printf("LIO job not cleaned up: B:%d, BF:%d, Q:%d, "
  635                             "QF:%d\n", lj->lioj_buffer_count,
  636                             lj->lioj_buffer_finished_count,
  637                             lj->lioj_queue_count,
  638                             lj->lioj_queue_finished_count);
  639 #endif
  640                 }
  641         }
  642 
  643         uma_zfree(kaio_zone, ki);
  644         p->p_aioinfo = NULL;
  645 }
  646 
  647 /*
  648  * Select a job to run (called by an AIO daemon).
  649  */
  650 static struct aiocblist *
  651 aio_selectjob(struct aiothreadlist *aiop)
  652 {
  653         int s;
  654         struct aiocblist *aiocbe;
  655         struct kaioinfo *ki;
  656         struct proc *userp;
  657 
  658         s = splnet();
  659         for (aiocbe = TAILQ_FIRST(&aio_jobs); aiocbe; aiocbe =
  660             TAILQ_NEXT(aiocbe, list)) {
  661                 userp = aiocbe->userproc;
  662                 ki = userp->p_aioinfo;
  663 
  664                 if (ki->kaio_active_count < ki->kaio_maxactive_count) {
  665                         TAILQ_REMOVE(&aio_jobs, aiocbe, list);
  666                         splx(s);
  667                         return (aiocbe);
  668                 }
  669         }
  670         splx(s);
  671 
  672         return (NULL);
  673 }
  674 
  675 /*
  676  * The AIO processing activity.  This is the code that does the I/O request for
  677  * the non-physio version of the operations.  The normal vn operations are used,
  678  * and this code should work in all instances for every type of file, including
  679  * pipes, sockets, fifos, and regular files.
  680  */
  681 static void
  682 aio_process(struct aiocblist *aiocbe)
  683 {
  684         struct ucred *td_savedcred;
  685         struct thread *td;
  686         struct proc *mycp;
  687         struct aiocb *cb;
  688         struct file *fp;
  689         struct uio auio;
  690         struct iovec aiov;
  691         int cnt;
  692         int error;
  693         int oublock_st, oublock_end;
  694         int inblock_st, inblock_end;
  695 
  696         td = curthread;
  697         td_savedcred = td->td_ucred;
  698         td->td_ucred = aiocbe->cred;
  699         mycp = td->td_proc;
  700         cb = &aiocbe->uaiocb;
  701         fp = aiocbe->fd_file;
  702 
  703         aiov.iov_base = (void *)(uintptr_t)cb->aio_buf;
  704         aiov.iov_len = cb->aio_nbytes;
  705 
  706         auio.uio_iov = &aiov;
  707         auio.uio_iovcnt = 1;
  708         auio.uio_offset = cb->aio_offset;
  709         auio.uio_resid = cb->aio_nbytes;
  710         cnt = cb->aio_nbytes;
  711         auio.uio_segflg = UIO_USERSPACE;
  712         auio.uio_td = td;
  713 
  714         inblock_st = mycp->p_stats->p_ru.ru_inblock;
  715         oublock_st = mycp->p_stats->p_ru.ru_oublock;
  716         /*
  717          * _aio_aqueue() acquires a reference to the file that is
  718          * released in aio_free_entry().
  719          */
  720         if (cb->aio_lio_opcode == LIO_READ) {
  721                 auio.uio_rw = UIO_READ;
  722                 error = fo_read(fp, &auio, fp->f_cred, FOF_OFFSET, td);
  723         } else {
  724                 auio.uio_rw = UIO_WRITE;
  725                 error = fo_write(fp, &auio, fp->f_cred, FOF_OFFSET, td);
  726         }
  727         inblock_end = mycp->p_stats->p_ru.ru_inblock;
  728         oublock_end = mycp->p_stats->p_ru.ru_oublock;
  729 
  730         aiocbe->inputcharge = inblock_end - inblock_st;
  731         aiocbe->outputcharge = oublock_end - oublock_st;
  732 
  733         if ((error) && (auio.uio_resid != cnt)) {
  734                 if (error == ERESTART || error == EINTR || error == EWOULDBLOCK)
  735                         error = 0;
  736                 if ((error == EPIPE) && (cb->aio_lio_opcode == LIO_WRITE)) {
  737                         PROC_LOCK(aiocbe->userproc);
  738                         psignal(aiocbe->userproc, SIGPIPE);
  739                         PROC_UNLOCK(aiocbe->userproc);
  740                 }
  741         }
  742 
  743         cnt -= auio.uio_resid;
  744         cb->_aiocb_private.error = error;
  745         cb->_aiocb_private.status = cnt;
  746         td->td_ucred = td_savedcred;
  747 }
  748 
  749 /*
  750  * The AIO daemon, most of the actual work is done in aio_process,
  751  * but the setup (and address space mgmt) is done in this routine.
  752  */
  753 static void
  754 aio_daemon(void *uproc)
  755 {
  756         int s;
  757         struct aio_liojob *lj;
  758         struct aiocb *cb;
  759         struct aiocblist *aiocbe;
  760         struct aiothreadlist *aiop;
  761         struct kaioinfo *ki;
  762         struct proc *curcp, *mycp, *userp;
  763         struct vmspace *myvm, *tmpvm;
  764         struct thread *td = curthread;
  765         struct pgrp *newpgrp;
  766         struct session *newsess;
  767 
  768         mtx_lock(&Giant);
  769         /*
  770          * Local copies of curproc (cp) and vmspace (myvm)
  771          */
  772         mycp = td->td_proc;
  773         myvm = mycp->p_vmspace;
  774 
  775         KASSERT(mycp->p_textvp == NULL, ("kthread has a textvp"));
  776 
  777         /*
  778          * Allocate and ready the aio control info.  There is one aiop structure
  779          * per daemon.
  780          */
  781         aiop = uma_zalloc(aiop_zone, M_WAITOK);
  782         aiop->aiothread = td;
  783         aiop->aiothreadflags |= AIOP_FREE;
  784 
  785         s = splnet();
  786 
  787         /*
  788          * Place thread (lightweight process) onto the AIO free thread list.
  789          */
  790         if (TAILQ_EMPTY(&aio_freeproc))
  791                 wakeup(&aio_freeproc);
  792         TAILQ_INSERT_HEAD(&aio_freeproc, aiop, list);
  793 
  794         splx(s);
  795 
  796         /*
  797          * Get rid of our current filedescriptors.  AIOD's don't need any
  798          * filedescriptors, except as temporarily inherited from the client.
  799          */
  800         fdfree(td);
  801 
  802         mtx_unlock(&Giant);
  803         /* The daemon resides in its own pgrp. */
  804         MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
  805                 M_WAITOK | M_ZERO);
  806         MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION,
  807                 M_WAITOK | M_ZERO);
  808 
  809         sx_xlock(&proctree_lock);
  810         enterpgrp(mycp, mycp->p_pid, newpgrp, newsess);
  811         sx_xunlock(&proctree_lock);
  812         mtx_lock(&Giant);
  813 
  814         /*
  815          * Wakeup parent process.  (Parent sleeps to keep from blasting away
  816          * and creating too many daemons.)
  817          */
  818         wakeup(mycp);
  819 
  820         for (;;) {
  821                 /*
  822                  * curcp is the current daemon process context.
  823                  * userp is the current user process context.
  824                  */
  825                 curcp = mycp;
  826 
  827                 /*
  828                  * Take daemon off of free queue
  829                  */
  830                 if (aiop->aiothreadflags & AIOP_FREE) {
  831                         s = splnet();
  832                         TAILQ_REMOVE(&aio_freeproc, aiop, list);
  833                         TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list);
  834                         aiop->aiothreadflags &= ~AIOP_FREE;
  835                         splx(s);
  836                 }
  837                 aiop->aiothreadflags &= ~AIOP_SCHED;
  838 
  839                 /*
  840                  * Check for jobs.
  841                  */
  842                 while ((aiocbe = aio_selectjob(aiop)) != NULL) {
  843                         cb = &aiocbe->uaiocb;
  844                         userp = aiocbe->userproc;
  845 
  846                         aiocbe->jobstate = JOBST_JOBRUNNING;
  847 
  848                         /*
  849                          * Connect to process address space for user program.
  850                          */
  851                         if (userp != curcp) {
  852                                 /*
  853                                  * Save the current address space that we are
  854                                  * connected to.
  855                                  */
  856                                 tmpvm = mycp->p_vmspace;
  857                                 
  858                                 /*
  859                                  * Point to the new user address space, and
  860                                  * refer to it.
  861                                  */
  862                                 mycp->p_vmspace = userp->p_vmspace;
  863                                 mycp->p_vmspace->vm_refcnt++;
  864                                 
  865                                 /* Activate the new mapping. */
  866                                 pmap_activate(FIRST_THREAD_IN_PROC(mycp));
  867                                 
  868                                 /*
  869                                  * If the old address space wasn't the daemons
  870                                  * own address space, then we need to remove the
  871                                  * daemon's reference from the other process
  872                                  * that it was acting on behalf of.
  873                                  */
  874                                 if (tmpvm != myvm) {
  875                                         vmspace_free(tmpvm);
  876                                 }
  877                                 curcp = userp;
  878                         }
  879 
  880                         ki = userp->p_aioinfo;
  881                         lj = aiocbe->lio;
  882 
  883                         /* Account for currently active jobs. */
  884                         ki->kaio_active_count++;
  885 
  886                         /* Do the I/O function. */
  887                         aio_process(aiocbe);
  888 
  889                         /* Decrement the active job count. */
  890                         ki->kaio_active_count--;
  891 
  892                         /*
  893                          * Increment the completion count for wakeup/signal
  894                          * comparisons.
  895                          */
  896                         aiocbe->jobflags |= AIOCBLIST_DONE;
  897                         ki->kaio_queue_finished_count++;
  898                         if (lj)
  899                                 lj->lioj_queue_finished_count++;
  900                         if ((ki->kaio_flags & KAIO_WAKEUP) || ((ki->kaio_flags
  901                             & KAIO_RUNDOWN) && (ki->kaio_active_count == 0))) {
  902                                 ki->kaio_flags &= ~KAIO_WAKEUP;
  903                                 wakeup(userp);
  904                         }
  905 
  906                         s = splbio();
  907                         if (lj && (lj->lioj_flags &
  908                             (LIOJ_SIGNAL|LIOJ_SIGNAL_POSTED)) == LIOJ_SIGNAL) {
  909                                 if ((lj->lioj_queue_finished_count ==
  910                                     lj->lioj_queue_count) &&
  911                                     (lj->lioj_buffer_finished_count ==
  912                                     lj->lioj_buffer_count)) {
  913                                         PROC_LOCK(userp);
  914                                         psignal(userp,
  915                                             lj->lioj_signal.sigev_signo);
  916                                         PROC_UNLOCK(userp);
  917                                         lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
  918                                 }
  919                         }
  920                         splx(s);
  921 
  922                         aiocbe->jobstate = JOBST_JOBFINISHED;
  923 
  924                         s = splnet();
  925                         TAILQ_REMOVE(&ki->kaio_jobqueue, aiocbe, plist);
  926                         TAILQ_INSERT_TAIL(&ki->kaio_jobdone, aiocbe, plist);
  927                         splx(s);
  928                         KNOTE(&aiocbe->klist, 0);
  929 
  930                         if (aiocbe->jobflags & AIOCBLIST_RUNDOWN) {
  931                                 wakeup(aiocbe);
  932                                 aiocbe->jobflags &= ~AIOCBLIST_RUNDOWN;
  933                         }
  934 
  935                         if (cb->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
  936                                 PROC_LOCK(userp);
  937                                 psignal(userp, cb->aio_sigevent.sigev_signo);
  938                                 PROC_UNLOCK(userp);
  939                         }
  940                 }
  941 
  942                 /*
  943                  * Disconnect from user address space.
  944                  */
  945                 if (curcp != mycp) {
  946                         /* Get the user address space to disconnect from. */
  947                         tmpvm = mycp->p_vmspace;
  948                         
  949                         /* Get original address space for daemon. */
  950                         mycp->p_vmspace = myvm;
  951                         
  952                         /* Activate the daemon's address space. */
  953                         pmap_activate(FIRST_THREAD_IN_PROC(mycp));
  954 #ifdef DIAGNOSTIC
  955                         if (tmpvm == myvm) {
  956                                 printf("AIOD: vmspace problem -- %d\n",
  957                                     mycp->p_pid);
  958                         }
  959 #endif
  960                         /* Remove our vmspace reference. */
  961                         vmspace_free(tmpvm);
  962                         
  963                         curcp = mycp;
  964                 }
  965 
  966                 /*
  967                  * If we are the first to be put onto the free queue, wakeup
  968                  * anyone waiting for a daemon.
  969                  */
  970                 s = splnet();
  971                 TAILQ_REMOVE(&aio_activeproc, aiop, list);
  972                 if (TAILQ_EMPTY(&aio_freeproc))
  973                         wakeup(&aio_freeproc);
  974                 TAILQ_INSERT_HEAD(&aio_freeproc, aiop, list);
  975                 aiop->aiothreadflags |= AIOP_FREE;
  976                 splx(s);
  977 
  978                 /*
  979                  * If daemon is inactive for a long time, allow it to exit,
  980                  * thereby freeing resources.
  981                  */
  982                 if ((aiop->aiothreadflags & AIOP_SCHED) == 0 &&
  983                     tsleep(aiop->aiothread, PRIBIO, "aiordy", aiod_lifetime)) {
  984                         s = splnet();
  985                         if (TAILQ_EMPTY(&aio_jobs)) {
  986                                 if ((aiop->aiothreadflags & AIOP_FREE) &&
  987                                     (num_aio_procs > target_aio_procs)) {
  988                                         TAILQ_REMOVE(&aio_freeproc, aiop, list);
  989                                         splx(s);
  990                                         uma_zfree(aiop_zone, aiop);
  991                                         num_aio_procs--;
  992 #ifdef DIAGNOSTIC
  993                                         if (mycp->p_vmspace->vm_refcnt <= 1) {
  994                                                 printf("AIOD: bad vm refcnt for"
  995                                                     " exiting daemon: %d\n",
  996                                                     mycp->p_vmspace->vm_refcnt);
  997                                         }
  998 #endif
  999                                         kthread_exit(0);
 1000                                 }
 1001                         }
 1002                         splx(s);
 1003                 }
 1004         }
 1005 }
 1006 
 1007 /*
 1008  * Create a new AIO daemon.  This is mostly a kernel-thread fork routine.  The
 1009  * AIO daemon modifies its environment itself.
 1010  */
 1011 static int
 1012 aio_newproc(void)
 1013 {
 1014         int error;
 1015         struct proc *p;
 1016 
 1017         error = kthread_create(aio_daemon, curproc, &p, RFNOWAIT, 0, "aiod%d",
 1018                                num_aio_procs);
 1019         if (error)
 1020                 return (error);
 1021 
 1022         /*
 1023          * Wait until daemon is started, but continue on just in case to
 1024          * handle error conditions.
 1025          */
 1026         error = tsleep(p, PZERO, "aiosta", aiod_timeout);
 1027 
 1028         num_aio_procs++;
 1029 
 1030         return (error);
 1031 }
 1032 
 1033 /*
 1034  * Try the high-performance, low-overhead physio method for eligible
 1035  * VCHR devices.  This method doesn't use an aio helper thread, and
 1036  * thus has very low overhead. 
 1037  *
 1038  * Assumes that the caller, _aio_aqueue(), has incremented the file
 1039  * structure's reference count, preventing its deallocation for the
 1040  * duration of this call. 
 1041  */
 1042 static int
 1043 aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
 1044 {
 1045         int error;
 1046         struct aiocb *cb;
 1047         struct file *fp;
 1048         struct buf *bp;
 1049         struct vnode *vp;
 1050         struct kaioinfo *ki;
 1051         struct aio_liojob *lj;
 1052         int s;
 1053         int notify;
 1054 
 1055         cb = &aiocbe->uaiocb;
 1056         fp = aiocbe->fd_file;
 1057 
 1058         if (fp->f_type != DTYPE_VNODE) 
 1059                 return (-1);
 1060 
 1061         vp = fp->f_data;
 1062 
 1063         /*
 1064          * If its not a disk, we don't want to return a positive error.
 1065          * It causes the aio code to not fall through to try the thread
 1066          * way when you're talking to a regular file.
 1067          */
 1068         if (!vn_isdisk(vp, &error)) {
 1069                 if (error == ENOTBLK)
 1070                         return (-1);
 1071                 else
 1072                         return (error);
 1073         }
 1074 
 1075         if (cb->aio_nbytes % vp->v_rdev->si_bsize_phys)
 1076                 return (-1);
 1077 
 1078         if (cb->aio_nbytes >
 1079             MAXPHYS - (((vm_offset_t) cb->aio_buf) & PAGE_MASK))
 1080                 return (-1);
 1081 
 1082         ki = p->p_aioinfo;
 1083         if (ki->kaio_buffer_count >= ki->kaio_ballowed_count) 
 1084                 return (-1);
 1085 
 1086         ki->kaio_buffer_count++;
 1087 
 1088         lj = aiocbe->lio;
 1089         if (lj)
 1090                 lj->lioj_buffer_count++;
 1091 
 1092         /* Create and build a buffer header for a transfer. */
 1093         bp = (struct buf *)getpbuf(NULL);
 1094         BUF_KERNPROC(bp);
 1095 
 1096         /*
 1097          * Get a copy of the kva from the physical buffer.
 1098          */
 1099         bp->b_caller1 = p;
 1100         bp->b_dev = vp->v_rdev;
 1101         error = 0;
 1102 
 1103         bp->b_bcount = cb->aio_nbytes;
 1104         bp->b_bufsize = cb->aio_nbytes;
 1105         bp->b_flags = B_PHYS;
 1106         bp->b_iodone = aio_physwakeup;
 1107         bp->b_saveaddr = bp->b_data;
 1108         bp->b_data = (void *)(uintptr_t)cb->aio_buf;
 1109         bp->b_blkno = btodb(cb->aio_offset);
 1110         bp->b_iocmd = cb->aio_lio_opcode == LIO_WRITE ? BIO_WRITE : BIO_READ;
 1111 
 1112         /*
 1113          * Bring buffer into kernel space.
 1114          */
 1115         if (vmapbuf(bp) < 0) {
 1116                 error = EFAULT;
 1117                 goto doerror;
 1118         }
 1119 
 1120         s = splbio();
 1121         aiocbe->bp = bp;
 1122         bp->b_spc = (void *)aiocbe;
 1123         TAILQ_INSERT_TAIL(&aio_bufjobs, aiocbe, list);
 1124         TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, aiocbe, plist);
 1125         aiocbe->jobstate = JOBST_JOBQBUF;
 1126         cb->_aiocb_private.status = cb->aio_nbytes;
 1127         num_buf_aio++;
 1128         bp->b_error = 0;
 1129 
 1130         splx(s);
 1131         
 1132         /* Perform transfer. */
 1133         DEV_STRATEGY(bp);
 1134 
 1135         notify = 0;
 1136         s = splbio();
 1137         
 1138         /*
 1139          * If we had an error invoking the request, or an error in processing
 1140          * the request before we have returned, we process it as an error in
 1141          * transfer.  Note that such an I/O error is not indicated immediately,
 1142          * but is returned using the aio_error mechanism.  In this case,
 1143          * aio_suspend will return immediately.
 1144          */
 1145         if (bp->b_error || (bp->b_ioflags & BIO_ERROR)) {
 1146                 struct aiocb *job = aiocbe->uuaiocb;
 1147 
 1148                 aiocbe->uaiocb._aiocb_private.status = 0;
 1149                 suword(&job->_aiocb_private.status, 0);
 1150                 aiocbe->uaiocb._aiocb_private.error = bp->b_error;
 1151                 suword(&job->_aiocb_private.error, bp->b_error);
 1152 
 1153                 ki->kaio_buffer_finished_count++;
 1154 
 1155                 if (aiocbe->jobstate != JOBST_JOBBFINISHED) {
 1156                         aiocbe->jobstate = JOBST_JOBBFINISHED;
 1157                         aiocbe->jobflags |= AIOCBLIST_DONE;
 1158                         TAILQ_REMOVE(&aio_bufjobs, aiocbe, list);
 1159                         TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist);
 1160                         TAILQ_INSERT_TAIL(&ki->kaio_bufdone, aiocbe, plist);
 1161                         notify = 1;
 1162                 }
 1163         }
 1164         splx(s);
 1165         if (notify)
 1166                 KNOTE(&aiocbe->klist, 0);
 1167         return (0);
 1168 
 1169 doerror:
 1170         ki->kaio_buffer_count--;
 1171         if (lj)
 1172                 lj->lioj_buffer_count--;
 1173         aiocbe->bp = NULL;
 1174         relpbuf(bp, NULL);
 1175         return (error);
 1176 }
 1177 
 1178 /*
 1179  * This waits/tests physio completion.
 1180  */
 1181 static int
 1182 aio_fphysio(struct aiocblist *iocb)
 1183 {
 1184         int s;
 1185         struct buf *bp;
 1186         int error;
 1187 
 1188         bp = iocb->bp;
 1189 
 1190         s = splbio();
 1191         while ((bp->b_flags & B_DONE) == 0) {
 1192                 if (tsleep(bp, PRIBIO, "physstr", aiod_timeout)) {
 1193                         if ((bp->b_flags & B_DONE) == 0) {
 1194                                 splx(s);
 1195                                 return (EINPROGRESS);
 1196                         } else
 1197                                 break;
 1198                 }
 1199         }
 1200         splx(s);
 1201 
 1202         /* Release mapping into kernel space. */
 1203         vunmapbuf(bp);
 1204         iocb->bp = 0;
 1205 
 1206         error = 0;
 1207         
 1208         /* Check for an error. */
 1209         if (bp->b_ioflags & BIO_ERROR)
 1210                 error = bp->b_error;
 1211 
 1212         relpbuf(bp, NULL);
 1213         return (error);
 1214 }
 1215 
 1216 /*
 1217  * Wake up aio requests that may be serviceable now.
 1218  */
 1219 static void
 1220 aio_swake_cb(struct socket *so, struct sockbuf *sb)
 1221 {
 1222         struct aiocblist *cb,*cbn;
 1223         struct proc *p;
 1224         struct kaioinfo *ki = NULL;
 1225         int opcode, wakecount = 0;
 1226         struct aiothreadlist *aiop;
 1227 
 1228         if (sb == &so->so_snd) {
 1229                 opcode = LIO_WRITE;
 1230                 so->so_snd.sb_flags &= ~SB_AIO;
 1231         } else {
 1232                 opcode = LIO_READ;
 1233                 so->so_rcv.sb_flags &= ~SB_AIO;
 1234         }
 1235 
 1236         for (cb = TAILQ_FIRST(&so->so_aiojobq); cb; cb = cbn) {
 1237                 cbn = TAILQ_NEXT(cb, list);
 1238                 if (opcode == cb->uaiocb.aio_lio_opcode) {
 1239                         p = cb->userproc;
 1240                         ki = p->p_aioinfo;
 1241                         TAILQ_REMOVE(&so->so_aiojobq, cb, list);
 1242                         TAILQ_REMOVE(&ki->kaio_sockqueue, cb, plist);
 1243                         TAILQ_INSERT_TAIL(&aio_jobs, cb, list);
 1244                         TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, cb, plist);
 1245                         wakecount++;
 1246                         if (cb->jobstate != JOBST_JOBQGLOBAL)
 1247                                 panic("invalid queue value");
 1248                 }
 1249         }
 1250 
 1251         while (wakecount--) {
 1252                 if ((aiop = TAILQ_FIRST(&aio_freeproc)) != 0) {
 1253                         TAILQ_REMOVE(&aio_freeproc, aiop, list);
 1254                         TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list);
 1255                         aiop->aiothreadflags &= ~AIOP_FREE;
 1256                         wakeup(aiop->aiothread);
 1257                 }
 1258         }
 1259 }
 1260 
 1261 /*
 1262  * Queue a new AIO request.  Choosing either the threaded or direct physio VCHR
 1263  * technique is done in this code.
 1264  */
 1265 static int
 1266 _aio_aqueue(struct thread *td, struct aiocb *job, struct aio_liojob *lj, int type)
 1267 {
 1268         struct proc *p = td->td_proc;
 1269         struct filedesc *fdp;
 1270         struct file *fp;
 1271         unsigned int fd;
 1272         struct socket *so;
 1273         int s;
 1274         int error;
 1275         int opcode, user_opcode;
 1276         struct aiocblist *aiocbe;
 1277         struct aiothreadlist *aiop;
 1278         struct kaioinfo *ki;
 1279         struct kevent kev;
 1280         struct kqueue *kq;
 1281         struct file *kq_fp;
 1282 
 1283         aiocbe = uma_zalloc(aiocb_zone, M_WAITOK);
 1284         aiocbe->inputcharge = 0;
 1285         aiocbe->outputcharge = 0;
 1286         callout_handle_init(&aiocbe->timeouthandle);
 1287         SLIST_INIT(&aiocbe->klist);
 1288 
 1289         suword(&job->_aiocb_private.status, -1);
 1290         suword(&job->_aiocb_private.error, 0);
 1291         suword(&job->_aiocb_private.kernelinfo, -1);
 1292 
 1293         error = copyin(job, &aiocbe->uaiocb, sizeof(aiocbe->uaiocb));
 1294         if (error) {
 1295                 suword(&job->_aiocb_private.error, error);
 1296                 uma_zfree(aiocb_zone, aiocbe);
 1297                 return (error);
 1298         }
 1299         if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL &&
 1300                 !_SIG_VALID(aiocbe->uaiocb.aio_sigevent.sigev_signo)) {
 1301                 uma_zfree(aiocb_zone, aiocbe);
 1302                 return (EINVAL);
 1303         }
 1304 
 1305         /* Save userspace address of the job info. */
 1306         aiocbe->uuaiocb = job;
 1307 
 1308         /* Get the opcode. */
 1309         user_opcode = aiocbe->uaiocb.aio_lio_opcode;
 1310         if (type != LIO_NOP)
 1311                 aiocbe->uaiocb.aio_lio_opcode = type;
 1312         opcode = aiocbe->uaiocb.aio_lio_opcode;
 1313 
 1314         /* Get the fd info for process. */
 1315         fdp = p->p_fd;
 1316 
 1317         /*
 1318          * Range check file descriptor.
 1319          */
 1320         FILEDESC_LOCK(fdp);
 1321         fd = aiocbe->uaiocb.aio_fildes;
 1322         if (fd >= fdp->fd_nfiles) {
 1323                 FILEDESC_UNLOCK(fdp);
 1324                 uma_zfree(aiocb_zone, aiocbe);
 1325                 if (type == 0)
 1326                         suword(&job->_aiocb_private.error, EBADF);
 1327                 return (EBADF);
 1328         }
 1329 
 1330         fp = aiocbe->fd_file = fdp->fd_ofiles[fd];
 1331         if ((fp == NULL) || ((opcode == LIO_WRITE) && ((fp->f_flag & FWRITE) ==
 1332             0))) {
 1333                 FILEDESC_UNLOCK(fdp);
 1334                 uma_zfree(aiocb_zone, aiocbe);
 1335                 if (type == 0)
 1336                         suword(&job->_aiocb_private.error, EBADF);
 1337                 return (EBADF);
 1338         }
 1339         fhold(fp);
 1340         FILEDESC_UNLOCK(fdp);
 1341 
 1342         if (aiocbe->uaiocb.aio_offset == -1LL) {
 1343                 error = EINVAL;
 1344                 goto aqueue_fail;
 1345         }
 1346         error = suword(&job->_aiocb_private.kernelinfo, jobrefid);
 1347         if (error) {
 1348                 error = EINVAL;
 1349                 goto aqueue_fail;
 1350         }
 1351         aiocbe->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jobrefid;
 1352         if (jobrefid == LONG_MAX)
 1353                 jobrefid = 1;
 1354         else
 1355                 jobrefid++;
 1356         
 1357         if (opcode == LIO_NOP) {
 1358                 fdrop(fp, td);
 1359                 uma_zfree(aiocb_zone, aiocbe);
 1360                 if (type == 0) {
 1361                         suword(&job->_aiocb_private.error, 0);
 1362                         suword(&job->_aiocb_private.status, 0);
 1363                         suword(&job->_aiocb_private.kernelinfo, 0);
 1364                 }
 1365                 return (0);
 1366         }
 1367         if ((opcode != LIO_READ) && (opcode != LIO_WRITE)) {
 1368                 if (type == 0)
 1369                         suword(&job->_aiocb_private.status, 0);
 1370                 error = EINVAL;
 1371                 goto aqueue_fail;
 1372         }
 1373 
 1374         if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_KEVENT) {
 1375                 kev.ident = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue;
 1376                 kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sigval_ptr;
 1377         }
 1378         else {
 1379                 /*
 1380                  * This method for requesting kevent-based notification won't
 1381                  * work on the alpha, since we're passing in a pointer
 1382                  * via aio_lio_opcode, which is an int.  Use the SIGEV_KEVENT-
 1383                  * based method instead.
 1384                  */
 1385                 if (user_opcode == LIO_NOP || user_opcode == LIO_READ ||
 1386                     user_opcode == LIO_WRITE)
 1387                         goto no_kqueue;
 1388 
 1389                 error = copyin((struct kevent *)(uintptr_t)user_opcode,
 1390                     &kev, sizeof(kev));
 1391                 if (error)
 1392                         goto aqueue_fail;
 1393         }
 1394         if ((u_int)kev.ident >= fdp->fd_nfiles ||
 1395             (kq_fp = fdp->fd_ofiles[kev.ident]) == NULL ||
 1396             (kq_fp->f_type != DTYPE_KQUEUE)) {
 1397                 error = EBADF;
 1398                 goto aqueue_fail;
 1399         }
 1400         kq = kq_fp->f_data;
 1401         kev.ident = (uintptr_t)aiocbe->uuaiocb;
 1402         kev.filter = EVFILT_AIO;
 1403         kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1;
 1404         kev.data = (intptr_t)aiocbe;
 1405         error = kqueue_register(kq, &kev, td);
 1406 aqueue_fail:
 1407         if (error) {
 1408                 fdrop(fp, td);
 1409                 uma_zfree(aiocb_zone, aiocbe);
 1410                 if (type == 0)
 1411                         suword(&job->_aiocb_private.error, error);
 1412                 goto done;
 1413         }
 1414 no_kqueue:
 1415 
 1416         suword(&job->_aiocb_private.error, EINPROGRESS);
 1417         aiocbe->uaiocb._aiocb_private.error = EINPROGRESS;
 1418         aiocbe->userproc = p;
 1419         aiocbe->cred = crhold(td->td_ucred);
 1420         aiocbe->jobflags = 0;
 1421         aiocbe->lio = lj;
 1422         ki = p->p_aioinfo;
 1423 
 1424         if (fp->f_type == DTYPE_SOCKET) {
 1425                 /*
 1426                  * Alternate queueing for socket ops: Reach down into the
 1427                  * descriptor to get the socket data.  Then check to see if the
 1428                  * socket is ready to be read or written (based on the requested
 1429                  * operation).
 1430                  *
 1431                  * If it is not ready for io, then queue the aiocbe on the
 1432                  * socket, and set the flags so we get a call when sbnotify()
 1433                  * happens.
 1434                  */
 1435                 so = fp->f_data;
 1436                 s = splnet();
 1437                 if (((opcode == LIO_READ) && (!soreadable(so))) || ((opcode ==
 1438                     LIO_WRITE) && (!sowriteable(so)))) {
 1439                         TAILQ_INSERT_TAIL(&so->so_aiojobq, aiocbe, list);
 1440                         TAILQ_INSERT_TAIL(&ki->kaio_sockqueue, aiocbe, plist);
 1441                         if (opcode == LIO_READ)
 1442                                 so->so_rcv.sb_flags |= SB_AIO;
 1443                         else
 1444                                 so->so_snd.sb_flags |= SB_AIO;
 1445                         aiocbe->jobstate = JOBST_JOBQGLOBAL; /* XXX */
 1446                         ki->kaio_queue_count++;
 1447                         num_queue_count++;
 1448                         splx(s);
 1449                         error = 0;
 1450                         goto done;
 1451                 }
 1452                 splx(s);
 1453         }
 1454 
 1455         if ((error = aio_qphysio(p, aiocbe)) == 0)
 1456                 goto done;
 1457         if (error > 0) {
 1458                 suword(&job->_aiocb_private.status, 0);
 1459                 aiocbe->uaiocb._aiocb_private.error = error;
 1460                 suword(&job->_aiocb_private.error, error);
 1461                 goto done;
 1462         }
 1463 
 1464         /* No buffer for daemon I/O. */
 1465         aiocbe->bp = NULL;
 1466 
 1467         ki->kaio_queue_count++;
 1468         if (lj)
 1469                 lj->lioj_queue_count++;
 1470         s = splnet();
 1471         TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist);
 1472         TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list);
 1473         splx(s);
 1474         aiocbe->jobstate = JOBST_JOBQGLOBAL;
 1475 
 1476         num_queue_count++;
 1477         error = 0;
 1478 
 1479         /*
 1480          * If we don't have a free AIO process, and we are below our quota, then
 1481          * start one.  Otherwise, depend on the subsequent I/O completions to
 1482          * pick-up this job.  If we don't sucessfully create the new process
 1483          * (thread) due to resource issues, we return an error for now (EAGAIN),
 1484          * which is likely not the correct thing to do.
 1485          */
 1486         s = splnet();
 1487 retryproc:
 1488         if ((aiop = TAILQ_FIRST(&aio_freeproc)) != NULL) {
 1489                 TAILQ_REMOVE(&aio_freeproc, aiop, list);
 1490                 TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list);
 1491                 aiop->aiothreadflags &= ~AIOP_FREE;
 1492                 wakeup(aiop->aiothread);
 1493         } else if (((num_aio_resv_start + num_aio_procs) < max_aio_procs) &&
 1494             ((ki->kaio_active_count + num_aio_resv_start) <
 1495             ki->kaio_maxactive_count)) {
 1496                 num_aio_resv_start++;
 1497                 if ((error = aio_newproc()) == 0) {
 1498                         num_aio_resv_start--;
 1499                         goto retryproc;
 1500                 }
 1501                 num_aio_resv_start--;
 1502         }
 1503         splx(s);
 1504 done:
 1505         return (error);
 1506 }
 1507 
 1508 /*
 1509  * This routine queues an AIO request, checking for quotas.
 1510  */
 1511 static int
 1512 aio_aqueue(struct thread *td, struct aiocb *job, int type)
 1513 {
 1514         struct proc *p = td->td_proc;
 1515         struct kaioinfo *ki;
 1516 
 1517         if (p->p_aioinfo == NULL)
 1518                 aio_init_aioinfo(p);
 1519 
 1520         if (num_queue_count >= max_queue_count)
 1521                 return (EAGAIN);
 1522 
 1523         ki = p->p_aioinfo;
 1524         if (ki->kaio_queue_count >= ki->kaio_qallowed_count)
 1525                 return (EAGAIN);
 1526 
 1527         return _aio_aqueue(td, job, NULL, type);
 1528 }
 1529 
 1530 /*
 1531  * Support the aio_return system call, as a side-effect, kernel resources are
 1532  * released.
 1533  */
 1534 int
 1535 aio_return(struct thread *td, struct aio_return_args *uap)
 1536 {
 1537         struct proc *p = td->td_proc;
 1538         int s;
 1539         long jobref;
 1540         struct aiocblist *cb, *ncb;
 1541         struct aiocb *ujob;
 1542         struct kaioinfo *ki;
 1543 
 1544         ujob = uap->aiocbp;
 1545         jobref = fuword(&ujob->_aiocb_private.kernelinfo);
 1546         if (jobref == -1 || jobref == 0)
 1547                 return (EINVAL);
 1548 
 1549         ki = p->p_aioinfo;
 1550         if (ki == NULL)
 1551                 return (EINVAL);
 1552         TAILQ_FOREACH(cb, &ki->kaio_jobdone, plist) {
 1553                 if (((intptr_t) cb->uaiocb._aiocb_private.kernelinfo) ==
 1554                     jobref) {
 1555                         if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) {
 1556                                 p->p_stats->p_ru.ru_oublock +=
 1557                                     cb->outputcharge;
 1558                                 cb->outputcharge = 0;
 1559                         } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) {
 1560                                 p->p_stats->p_ru.ru_inblock += cb->inputcharge;
 1561                                 cb->inputcharge = 0;
 1562                         }
 1563                         goto done;
 1564                 }
 1565         }
 1566         s = splbio();
 1567         for (cb = TAILQ_FIRST(&ki->kaio_bufdone); cb; cb = ncb) {
 1568                 ncb = TAILQ_NEXT(cb, plist);
 1569                 if (((intptr_t) cb->uaiocb._aiocb_private.kernelinfo)
 1570                     == jobref) {
 1571                         break;
 1572                 }
 1573         }
 1574         splx(s);
 1575  done:
 1576         if (cb != NULL) {
 1577                 if (ujob == cb->uuaiocb) {
 1578                         td->td_retval[0] =
 1579                             cb->uaiocb._aiocb_private.status;
 1580                 } else
 1581                         td->td_retval[0] = EFAULT;
 1582                 aio_free_entry(cb);
 1583                 return (0);
 1584         }
 1585         return (EINVAL);
 1586 }
 1587 
 1588 /*
 1589  * Allow a process to wakeup when any of the I/O requests are completed.
 1590  */
 1591 int
 1592 aio_suspend(struct thread *td, struct aio_suspend_args *uap)
 1593 {
 1594         struct proc *p = td->td_proc;
 1595         struct timeval atv;
 1596         struct timespec ts;
 1597         struct aiocb *const *cbptr, *cbp;
 1598         struct kaioinfo *ki;
 1599         struct aiocblist *cb;
 1600         int i;
 1601         int njoblist;
 1602         int error, s, timo;
 1603         long *ijoblist;
 1604         struct aiocb **ujoblist;
 1605         
 1606         if (uap->nent < 0 || uap->nent > AIO_LISTIO_MAX)
 1607                 return (EINVAL);
 1608 
 1609         timo = 0;
 1610         if (uap->timeout) {
 1611                 /* Get timespec struct. */
 1612                 if ((error = copyin(uap->timeout, &ts, sizeof(ts))) != 0)
 1613                         return (error);
 1614 
 1615                 if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000)
 1616                         return (EINVAL);
 1617 
 1618                 TIMESPEC_TO_TIMEVAL(&atv, &ts);
 1619                 if (itimerfix(&atv))
 1620                         return (EINVAL);
 1621                 timo = tvtohz(&atv);
 1622         }
 1623 
 1624         ki = p->p_aioinfo;
 1625         if (ki == NULL)
 1626                 return (EAGAIN);
 1627 
 1628         njoblist = 0;
 1629         ijoblist = uma_zalloc(aiol_zone, M_WAITOK);
 1630         ujoblist = uma_zalloc(aiol_zone, M_WAITOK);
 1631         cbptr = uap->aiocbp;
 1632 
 1633         for (i = 0; i < uap->nent; i++) {
 1634                 cbp = (struct aiocb *)(intptr_t)fuword(&cbptr[i]);
 1635                 if (cbp == 0)
 1636                         continue;
 1637                 ujoblist[njoblist] = cbp;
 1638                 ijoblist[njoblist] = fuword(&cbp->_aiocb_private.kernelinfo);
 1639                 njoblist++;
 1640         }
 1641 
 1642         if (njoblist == 0) {
 1643                 uma_zfree(aiol_zone, ijoblist);
 1644                 uma_zfree(aiol_zone, ujoblist);
 1645                 return (0);
 1646         }
 1647 
 1648         error = 0;
 1649         for (;;) {
 1650                 TAILQ_FOREACH(cb, &ki->kaio_jobdone, plist) {
 1651                         for (i = 0; i < njoblist; i++) {
 1652                                 if (((intptr_t)
 1653                                     cb->uaiocb._aiocb_private.kernelinfo) ==
 1654                                     ijoblist[i]) {
 1655                                         if (ujoblist[i] != cb->uuaiocb)
 1656                                                 error = EINVAL;
 1657                                         uma_zfree(aiol_zone, ijoblist);
 1658                                         uma_zfree(aiol_zone, ujoblist);
 1659                                         return (error);
 1660                                 }
 1661                         }
 1662                 }
 1663 
 1664                 s = splbio();
 1665                 for (cb = TAILQ_FIRST(&ki->kaio_bufdone); cb; cb =
 1666                     TAILQ_NEXT(cb, plist)) {
 1667                         for (i = 0; i < njoblist; i++) {
 1668                                 if (((intptr_t)
 1669                                     cb->uaiocb._aiocb_private.kernelinfo) ==
 1670                                     ijoblist[i]) {
 1671                                         splx(s);
 1672                                         if (ujoblist[i] != cb->uuaiocb)
 1673                                                 error = EINVAL;
 1674                                         uma_zfree(aiol_zone, ijoblist);
 1675                                         uma_zfree(aiol_zone, ujoblist);
 1676                                         return (error);
 1677                                 }
 1678                         }
 1679                 }
 1680 
 1681                 ki->kaio_flags |= KAIO_WAKEUP;
 1682                 error = tsleep(p, PRIBIO | PCATCH, "aiospn", timo);
 1683                 splx(s);
 1684 
 1685                 if (error == ERESTART || error == EINTR) {
 1686                         uma_zfree(aiol_zone, ijoblist);
 1687                         uma_zfree(aiol_zone, ujoblist);
 1688                         return (EINTR);
 1689                 } else if (error == EWOULDBLOCK) {
 1690                         uma_zfree(aiol_zone, ijoblist);
 1691                         uma_zfree(aiol_zone, ujoblist);
 1692                         return (EAGAIN);
 1693                 }
 1694         }
 1695 
 1696 /* NOTREACHED */
 1697         return (EINVAL);
 1698 }
 1699 
 1700 /*
 1701  * aio_cancel cancels any non-physio aio operations not currently in
 1702  * progress.
 1703  */
 1704 int
 1705 aio_cancel(struct thread *td, struct aio_cancel_args *uap)
 1706 {
 1707         struct proc *p = td->td_proc;
 1708         struct kaioinfo *ki;
 1709         struct aiocblist *cbe, *cbn;
 1710         struct file *fp;
 1711         struct filedesc *fdp;
 1712         struct socket *so;
 1713         struct proc *po;
 1714         int s,error;
 1715         int cancelled=0;
 1716         int notcancelled=0;
 1717         struct vnode *vp;
 1718 
 1719         fdp = p->p_fd;
 1720         if ((u_int)uap->fd >= fdp->fd_nfiles ||
 1721             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
 1722                 return (EBADF);
 1723 
 1724         if (fp->f_type == DTYPE_VNODE) {
 1725                 vp = fp->f_data;
 1726                 
 1727                 if (vn_isdisk(vp,&error)) {
 1728                         td->td_retval[0] = AIO_NOTCANCELED;
 1729                         return (0);
 1730                 }
 1731         } else if (fp->f_type == DTYPE_SOCKET) {
 1732                 so = fp->f_data;
 1733 
 1734                 s = splnet();
 1735 
 1736                 for (cbe = TAILQ_FIRST(&so->so_aiojobq); cbe; cbe = cbn) {
 1737                         cbn = TAILQ_NEXT(cbe, list);
 1738                         if ((uap->aiocbp == NULL) ||
 1739                                 (uap->aiocbp == cbe->uuaiocb) ) {
 1740                                 po = cbe->userproc;
 1741                                 ki = po->p_aioinfo;
 1742                                 TAILQ_REMOVE(&so->so_aiojobq, cbe, list);
 1743                                 TAILQ_REMOVE(&ki->kaio_sockqueue, cbe, plist);
 1744                                 TAILQ_INSERT_TAIL(&ki->kaio_jobdone, cbe, plist);
 1745                                 if (ki->kaio_flags & KAIO_WAKEUP) {
 1746                                         wakeup(po);
 1747                                 }
 1748                                 cbe->jobstate = JOBST_JOBFINISHED;
 1749                                 cbe->uaiocb._aiocb_private.status=-1;
 1750                                 cbe->uaiocb._aiocb_private.error=ECANCELED;
 1751                                 cancelled++;
 1752 /* XXX cancelled, knote? */
 1753                                 if (cbe->uaiocb.aio_sigevent.sigev_notify ==
 1754                                     SIGEV_SIGNAL) {
 1755                                         PROC_LOCK(cbe->userproc);
 1756                                         psignal(cbe->userproc, cbe->uaiocb.aio_sigevent.sigev_signo);
 1757                                         PROC_UNLOCK(cbe->userproc);
 1758                                 }
 1759                                 if (uap->aiocbp) 
 1760                                         break;
 1761                         }
 1762                 }
 1763                 splx(s);
 1764 
 1765                 if ((cancelled) && (uap->aiocbp)) {
 1766                         td->td_retval[0] = AIO_CANCELED;
 1767                         return (0);
 1768                 }
 1769         }
 1770         ki=p->p_aioinfo;
 1771         if (ki == NULL)
 1772                 goto done;
 1773         s = splnet();
 1774 
 1775         for (cbe = TAILQ_FIRST(&ki->kaio_jobqueue); cbe; cbe = cbn) {
 1776                 cbn = TAILQ_NEXT(cbe, plist);
 1777 
 1778                 if ((uap->fd == cbe->uaiocb.aio_fildes) &&
 1779                     ((uap->aiocbp == NULL ) || 
 1780                      (uap->aiocbp == cbe->uuaiocb))) {
 1781                         
 1782                         if (cbe->jobstate == JOBST_JOBQGLOBAL) {
 1783                                 TAILQ_REMOVE(&aio_jobs, cbe, list);
 1784                                 TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist);
 1785                                 TAILQ_INSERT_TAIL(&ki->kaio_jobdone, cbe,
 1786                                     plist);
 1787                                 cancelled++;
 1788                                 ki->kaio_queue_finished_count++;
 1789                                 cbe->jobstate = JOBST_JOBFINISHED;
 1790                                 cbe->uaiocb._aiocb_private.status = -1;
 1791                                 cbe->uaiocb._aiocb_private.error = ECANCELED;
 1792 /* XXX cancelled, knote? */
 1793                                 if (cbe->uaiocb.aio_sigevent.sigev_notify ==
 1794                                     SIGEV_SIGNAL) {
 1795                                         PROC_LOCK(cbe->userproc);
 1796                                         psignal(cbe->userproc, cbe->uaiocb.aio_sigevent.sigev_signo);
 1797                                         PROC_UNLOCK(cbe->userproc);
 1798                                 }
 1799                         } else {
 1800                                 notcancelled++;
 1801                         }
 1802                 }
 1803         }
 1804         splx(s);
 1805 done:
 1806         if (notcancelled) {
 1807                 td->td_retval[0] = AIO_NOTCANCELED;
 1808                 return (0);
 1809         }
 1810         if (cancelled) {
 1811                 td->td_retval[0] = AIO_CANCELED;
 1812                 return (0);
 1813         }
 1814         td->td_retval[0] = AIO_ALLDONE;
 1815 
 1816         return (0);
 1817 }
 1818 
 1819 /*
 1820  * aio_error is implemented in the kernel level for compatibility purposes only.
 1821  * For a user mode async implementation, it would be best to do it in a userland
 1822  * subroutine.
 1823  */
 1824 int
 1825 aio_error(struct thread *td, struct aio_error_args *uap)
 1826 {
 1827         struct proc *p = td->td_proc;
 1828         int s;
 1829         struct aiocblist *cb;
 1830         struct kaioinfo *ki;
 1831         long jobref;
 1832 
 1833         ki = p->p_aioinfo;
 1834         if (ki == NULL)
 1835                 return (EINVAL);
 1836 
 1837         jobref = fuword(&uap->aiocbp->_aiocb_private.kernelinfo);
 1838         if ((jobref == -1) || (jobref == 0))
 1839                 return (EINVAL);
 1840 
 1841         TAILQ_FOREACH(cb, &ki->kaio_jobdone, plist) {
 1842                 if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo) ==
 1843                     jobref) {
 1844                         td->td_retval[0] = cb->uaiocb._aiocb_private.error;
 1845                         return (0);
 1846                 }
 1847         }
 1848 
 1849         s = splnet();
 1850 
 1851         for (cb = TAILQ_FIRST(&ki->kaio_jobqueue); cb; cb = TAILQ_NEXT(cb,
 1852             plist)) {
 1853                 if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo) ==
 1854                     jobref) {
 1855                         td->td_retval[0] = EINPROGRESS;
 1856                         splx(s);
 1857                         return (0);
 1858                 }
 1859         }
 1860 
 1861         for (cb = TAILQ_FIRST(&ki->kaio_sockqueue); cb; cb = TAILQ_NEXT(cb,
 1862             plist)) {
 1863                 if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo) ==
 1864                     jobref) {
 1865                         td->td_retval[0] = EINPROGRESS;
 1866                         splx(s);
 1867                         return (0);
 1868                 }
 1869         }
 1870         splx(s);
 1871 
 1872         s = splbio();
 1873         for (cb = TAILQ_FIRST(&ki->kaio_bufdone); cb; cb = TAILQ_NEXT(cb,
 1874             plist)) {
 1875                 if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo) ==
 1876                     jobref) {
 1877                         td->td_retval[0] = cb->uaiocb._aiocb_private.error;
 1878                         splx(s);
 1879                         return (0);
 1880                 }
 1881         }
 1882 
 1883         for (cb = TAILQ_FIRST(&ki->kaio_bufqueue); cb; cb = TAILQ_NEXT(cb,
 1884             plist)) {
 1885                 if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo) ==
 1886                     jobref) {
 1887                         td->td_retval[0] = EINPROGRESS;
 1888                         splx(s);
 1889                         return (0);
 1890                 }
 1891         }
 1892         splx(s);
 1893 
 1894 #if (0)
 1895         /*
 1896          * Hack for lio.
 1897          */
 1898         status = fuword(&uap->aiocbp->_aiocb_private.status);
 1899         if (status == -1)
 1900                 return fuword(&uap->aiocbp->_aiocb_private.error);
 1901 #endif
 1902         return (EINVAL);
 1903 }
 1904 
 1905 /* syscall - asynchronous read from a file (REALTIME) */
 1906 int
 1907 aio_read(struct thread *td, struct aio_read_args *uap)
 1908 {
 1909 
 1910         return aio_aqueue(td, uap->aiocbp, LIO_READ);
 1911 }
 1912 
 1913 /* syscall - asynchronous write to a file (REALTIME) */
 1914 int
 1915 aio_write(struct thread *td, struct aio_write_args *uap)
 1916 {
 1917 
 1918         return aio_aqueue(td, uap->aiocbp, LIO_WRITE);
 1919 }
 1920 
 1921 /* syscall - list directed I/O (REALTIME) */
 1922 int
 1923 lio_listio(struct thread *td, struct lio_listio_args *uap)
 1924 {
 1925         struct proc *p = td->td_proc;
 1926         int nent, nentqueued;
 1927         struct aiocb *iocb, * const *cbptr;
 1928         struct aiocblist *cb;
 1929         struct kaioinfo *ki;
 1930         struct aio_liojob *lj;
 1931         int error, runningcode;
 1932         int nerror;
 1933         int i;
 1934         int s;
 1935 
 1936         if ((uap->mode != LIO_NOWAIT) && (uap->mode != LIO_WAIT))
 1937                 return (EINVAL);
 1938 
 1939         nent = uap->nent;
 1940         if (nent < 0 || nent > AIO_LISTIO_MAX)
 1941                 return (EINVAL);
 1942 
 1943         if (p->p_aioinfo == NULL)
 1944                 aio_init_aioinfo(p);
 1945 
 1946         if ((nent + num_queue_count) > max_queue_count)
 1947                 return (EAGAIN);
 1948 
 1949         ki = p->p_aioinfo;
 1950         if ((nent + ki->kaio_queue_count) > ki->kaio_qallowed_count)
 1951                 return (EAGAIN);
 1952 
 1953         lj = uma_zalloc(aiolio_zone, M_WAITOK);
 1954         if (!lj)
 1955                 return (EAGAIN);
 1956 
 1957         lj->lioj_flags = 0;
 1958         lj->lioj_buffer_count = 0;
 1959         lj->lioj_buffer_finished_count = 0;
 1960         lj->lioj_queue_count = 0;
 1961         lj->lioj_queue_finished_count = 0;
 1962         lj->lioj_ki = ki;
 1963 
 1964         /*
 1965          * Setup signal.
 1966          */
 1967         if (uap->sig && (uap->mode == LIO_NOWAIT)) {
 1968                 error = copyin(uap->sig, &lj->lioj_signal,
 1969                                sizeof(lj->lioj_signal));
 1970                 if (error) {
 1971                         uma_zfree(aiolio_zone, lj);
 1972                         return (error);
 1973                 }
 1974                 if (!_SIG_VALID(lj->lioj_signal.sigev_signo)) {
 1975                         uma_zfree(aiolio_zone, lj);
 1976                         return (EINVAL);
 1977                 }
 1978                 lj->lioj_flags |= LIOJ_SIGNAL;
 1979         }
 1980         TAILQ_INSERT_TAIL(&ki->kaio_liojoblist, lj, lioj_list);
 1981         /*
 1982          * Get pointers to the list of I/O requests.
 1983          */
 1984         nerror = 0;
 1985         nentqueued = 0;
 1986         cbptr = uap->acb_list;
 1987         for (i = 0; i < uap->nent; i++) {
 1988                 iocb = (struct aiocb *)(intptr_t)fuword(&cbptr[i]);
 1989                 if (((intptr_t)iocb != -1) && ((intptr_t)iocb != 0)) {
 1990                         error = _aio_aqueue(td, iocb, lj, 0);
 1991                         if (error == 0)
 1992                                 nentqueued++;
 1993                         else
 1994                                 nerror++;
 1995                 }
 1996         }
 1997 
 1998         /*
 1999          * If we haven't queued any, then just return error.
 2000          */
 2001         if (nentqueued == 0)
 2002                 return (0);
 2003 
 2004         /*
 2005          * Calculate the appropriate error return.
 2006          */
 2007         runningcode = 0;
 2008         if (nerror)
 2009                 runningcode = EIO;
 2010 
 2011         if (uap->mode == LIO_WAIT) {
 2012                 int command, found, jobref;
 2013                 
 2014                 for (;;) {
 2015                         found = 0;
 2016                         for (i = 0; i < uap->nent; i++) {
 2017                                 /*
 2018                                  * Fetch address of the control buf pointer in
 2019                                  * user space.
 2020                                  */
 2021                                 iocb = (struct aiocb *)
 2022                                     (intptr_t)fuword(&cbptr[i]);
 2023                                 if (((intptr_t)iocb == -1) || ((intptr_t)iocb
 2024                                     == 0))
 2025                                         continue;
 2026 
 2027                                 /*
 2028                                  * Fetch the associated command from user space.
 2029                                  */
 2030                                 command = fuword(&iocb->aio_lio_opcode);
 2031                                 if (command == LIO_NOP) {
 2032                                         found++;
 2033                                         continue;
 2034                                 }
 2035 
 2036                                 jobref =
 2037                                     fuword(&iocb->_aiocb_private.kernelinfo);
 2038 
 2039                                 TAILQ_FOREACH(cb, &ki->kaio_jobdone, plist) {
 2040                                         if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo)
 2041                                             == jobref) {
 2042                                                 if (cb->uaiocb.aio_lio_opcode
 2043                                                     == LIO_WRITE) {
 2044                                                         p->p_stats->p_ru.ru_oublock
 2045                                                             +=
 2046                                                             cb->outputcharge;
 2047                                                         cb->outputcharge = 0;
 2048                                                 } else if (cb->uaiocb.aio_lio_opcode
 2049                                                     == LIO_READ) {
 2050                                                         p->p_stats->p_ru.ru_inblock
 2051                                                             += cb->inputcharge;
 2052                                                         cb->inputcharge = 0;
 2053                                                 }
 2054                                                 found++;
 2055                                                 break;
 2056                                         }
 2057                                 }
 2058 
 2059                                 s = splbio();
 2060                                 TAILQ_FOREACH(cb, &ki->kaio_bufdone, plist) {
 2061                                         if (((intptr_t)cb->uaiocb._aiocb_private.kernelinfo)
 2062                                             == jobref) {
 2063                                                 found++;
 2064                                                 break;
 2065                                         }
 2066                                 }
 2067                                 splx(s);
 2068                         }
 2069 
 2070                         /*
 2071                          * If all I/Os have been disposed of, then we can
 2072                          * return.
 2073                          */
 2074                         if (found == nentqueued)
 2075                                 return (runningcode);
 2076                         
 2077                         ki->kaio_flags |= KAIO_WAKEUP;
 2078                         error = tsleep(p, PRIBIO | PCATCH, "aiospn", 0);
 2079 
 2080                         if (error == EINTR)
 2081                                 return (EINTR);
 2082                         else if (error == EWOULDBLOCK)
 2083                                 return (EAGAIN);
 2084                 }
 2085         }
 2086 
 2087         return (runningcode);
 2088 }
 2089 
 2090 /*
 2091  * This is a weird hack so that we can post a signal.  It is safe to do so from
 2092  * a timeout routine, but *not* from an interrupt routine.
 2093  */
 2094 static void
 2095 process_signal(void *aioj)
 2096 {
 2097         struct aiocblist *aiocbe = aioj;
 2098         struct aio_liojob *lj = aiocbe->lio;
 2099         struct aiocb *cb = &aiocbe->uaiocb;
 2100 
 2101         if ((lj) && (lj->lioj_signal.sigev_notify == SIGEV_SIGNAL) &&
 2102                 (lj->lioj_queue_count == lj->lioj_queue_finished_count)) {
 2103                 PROC_LOCK(lj->lioj_ki->kaio_p);
 2104                 psignal(lj->lioj_ki->kaio_p, lj->lioj_signal.sigev_signo);
 2105                 PROC_UNLOCK(lj->lioj_ki->kaio_p);
 2106                 lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
 2107         }
 2108 
 2109         if (cb->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
 2110                 PROC_LOCK(aiocbe->userproc);
 2111                 psignal(aiocbe->userproc, cb->aio_sigevent.sigev_signo);
 2112                 PROC_UNLOCK(aiocbe->userproc);
 2113         }
 2114 }
 2115 
 2116 /*
 2117  * Interrupt handler for physio, performs the necessary process wakeups, and
 2118  * signals.
 2119  */
 2120 static void
 2121 aio_physwakeup(struct buf *bp)
 2122 {
 2123         struct aiocblist *aiocbe;
 2124         struct proc *p;
 2125         struct kaioinfo *ki;
 2126         struct aio_liojob *lj;
 2127 
 2128         wakeup(bp);
 2129 
 2130         aiocbe = (struct aiocblist *)bp->b_spc;
 2131         if (aiocbe) {
 2132                 p = bp->b_caller1;
 2133 
 2134                 aiocbe->jobstate = JOBST_JOBBFINISHED;
 2135                 aiocbe->uaiocb._aiocb_private.status -= bp->b_resid;
 2136                 aiocbe->uaiocb._aiocb_private.error = 0;
 2137                 aiocbe->jobflags |= AIOCBLIST_DONE;
 2138 
 2139                 if (bp->b_ioflags & BIO_ERROR)
 2140                         aiocbe->uaiocb._aiocb_private.error = bp->b_error;
 2141 
 2142                 lj = aiocbe->lio;
 2143                 if (lj) {
 2144                         lj->lioj_buffer_finished_count++;
 2145                         
 2146                         /*
 2147                          * wakeup/signal if all of the interrupt jobs are done.
 2148                          */
 2149                         if (lj->lioj_buffer_finished_count ==
 2150                             lj->lioj_buffer_count) {
 2151                                 /*
 2152                                  * Post a signal if it is called for.
 2153                                  */
 2154                                 if ((lj->lioj_flags &
 2155                                     (LIOJ_SIGNAL|LIOJ_SIGNAL_POSTED)) ==
 2156                                     LIOJ_SIGNAL) {
 2157                                         lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
 2158                                         aiocbe->timeouthandle =
 2159                                                 timeout(process_signal,
 2160                                                         aiocbe, 0);
 2161                                 }
 2162                         }
 2163                 }
 2164 
 2165                 ki = p->p_aioinfo;
 2166                 if (ki) {
 2167                         ki->kaio_buffer_finished_count++;
 2168                         TAILQ_REMOVE(&aio_bufjobs, aiocbe, list);
 2169                         TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist);
 2170                         TAILQ_INSERT_TAIL(&ki->kaio_bufdone, aiocbe, plist);
 2171 
 2172                         KNOTE(&aiocbe->klist, 0);
 2173                         /* Do the wakeup. */
 2174                         if (ki->kaio_flags & (KAIO_RUNDOWN|KAIO_WAKEUP)) {
 2175                                 ki->kaio_flags &= ~KAIO_WAKEUP;
 2176                                 wakeup(p);
 2177                         }
 2178                 }
 2179 
 2180                 if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL)
 2181                         aiocbe->timeouthandle =
 2182                                 timeout(process_signal, aiocbe, 0);
 2183         }
 2184 }
 2185 
 2186 /* syscall - wait for the next completion of an aio request */
 2187 int
 2188 aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap)
 2189 {
 2190         struct proc *p = td->td_proc;
 2191         struct timeval atv;
 2192         struct timespec ts;
 2193         struct kaioinfo *ki;
 2194         struct aiocblist *cb = NULL;
 2195         int error, s, timo;
 2196         
 2197         suword(uap->aiocbp, (int)NULL);
 2198 
 2199         timo = 0;
 2200         if (uap->timeout) {
 2201                 /* Get timespec struct. */
 2202                 error = copyin(uap->timeout, &ts, sizeof(ts));
 2203                 if (error)
 2204                         return (error);
 2205 
 2206                 if ((ts.tv_nsec < 0) || (ts.tv_nsec >= 1000000000))
 2207                         return (EINVAL);
 2208 
 2209                 TIMESPEC_TO_TIMEVAL(&atv, &ts);
 2210                 if (itimerfix(&atv))
 2211                         return (EINVAL);
 2212                 timo = tvtohz(&atv);
 2213         }
 2214 
 2215         ki = p->p_aioinfo;
 2216         if (ki == NULL)
 2217                 return (EAGAIN);
 2218 
 2219         for (;;) {
 2220                 if ((cb = TAILQ_FIRST(&ki->kaio_jobdone)) != 0) {
 2221                         suword(uap->aiocbp, (uintptr_t)cb->uuaiocb);
 2222                         td->td_retval[0] = cb->uaiocb._aiocb_private.status;
 2223                         if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) {
 2224                                 p->p_stats->p_ru.ru_oublock +=
 2225                                     cb->outputcharge;
 2226                                 cb->outputcharge = 0;
 2227                         } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) {
 2228                                 p->p_stats->p_ru.ru_inblock += cb->inputcharge;
 2229                                 cb->inputcharge = 0;
 2230                         }
 2231                         aio_free_entry(cb);
 2232                         return (cb->uaiocb._aiocb_private.error);
 2233                 }
 2234 
 2235                 s = splbio();
 2236                 if ((cb = TAILQ_FIRST(&ki->kaio_bufdone)) != 0 ) {
 2237                         splx(s);
 2238                         suword(uap->aiocbp, (uintptr_t)cb->uuaiocb);
 2239                         td->td_retval[0] = cb->uaiocb._aiocb_private.status;
 2240                         aio_free_entry(cb);
 2241                         return (cb->uaiocb._aiocb_private.error);
 2242                 }
 2243 
 2244                 ki->kaio_flags |= KAIO_WAKEUP;
 2245                 error = tsleep(p, PRIBIO | PCATCH, "aiowc", timo);
 2246                 splx(s);
 2247 
 2248                 if (error == ERESTART)
 2249                         return (EINTR);
 2250                 else if (error < 0)
 2251                         return (error);
 2252                 else if (error == EINTR)
 2253                         return (EINTR);
 2254                 else if (error == EWOULDBLOCK)
 2255                         return (EAGAIN);
 2256         }
 2257 }
 2258 
 2259 /* kqueue attach function */
 2260 static int
 2261 filt_aioattach(struct knote *kn)
 2262 {
 2263         struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata;
 2264 
 2265         /*
 2266          * The aiocbe pointer must be validated before using it, so
 2267          * registration is restricted to the kernel; the user cannot
 2268          * set EV_FLAG1.
 2269          */
 2270         if ((kn->kn_flags & EV_FLAG1) == 0)
 2271                 return (EPERM);
 2272         kn->kn_flags &= ~EV_FLAG1;
 2273 
 2274         SLIST_INSERT_HEAD(&aiocbe->klist, kn, kn_selnext);
 2275 
 2276         return (0);
 2277 }
 2278 
 2279 /* kqueue detach function */
 2280 static void
 2281 filt_aiodetach(struct knote *kn)
 2282 {
 2283         struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata;
 2284 
 2285         SLIST_REMOVE(&aiocbe->klist, kn, knote, kn_selnext);
 2286 }
 2287 
 2288 /* kqueue filter function */
 2289 /*ARGSUSED*/
 2290 static int
 2291 filt_aio(struct knote *kn, long hint)
 2292 {
 2293         struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata;
 2294 
 2295         kn->kn_data = aiocbe->uaiocb._aiocb_private.error;
 2296         if (aiocbe->jobstate != JOBST_JOBFINISHED &&
 2297             aiocbe->jobstate != JOBST_JOBBFINISHED)
 2298                 return (0);
 2299         kn->kn_flags |= EV_EOF; 
 2300         return (1);
 2301 }

Cache object: f0ddcd2531667957bcebeaa6ea5a77c8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.