1 /* $NetBSD: aio.h,v 1.14 2025/10/10 15:53:55 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2025 The NetBSD Foundation, Inc. 5 * Copyright (c) 2007, Mindaugas Rasiukevicius <rmind at NetBSD org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef _SYS_AIO_H_ 31 #define _SYS_AIO_H_ 32 33 #include <sys/types.h> 34 #include <sys/signal.h> 35 #include <sys/tree.h> 36 37 /* Returned by aio_cancel() */ 38 #define AIO_CANCELED 0x1 39 #define AIO_NOTCANCELED 0x2 40 #define AIO_ALLDONE 0x3 41 42 /* LIO opcodes */ 43 #define LIO_NOP 0x0 44 #define LIO_WRITE 0x1 45 #define LIO_READ 0x2 46 47 /* LIO modes */ 48 #define LIO_NOWAIT 0x0 49 #define LIO_WAIT 0x1 50 51 /* 52 * Asynchronous I/O structure. 53 * Defined in the Base Definitions volume of IEEE Std 1003.1-2001 . 54 */ 55 struct aiocb { 56 off_t aio_offset; /* File offset */ 57 void *aio_buf; /* I/O buffer in process space */ 58 size_t aio_nbytes; /* Length of transfer */ 59 int aio_fildes; /* File descriptor */ 60 int aio_lio_opcode; /* LIO opcode */ 61 int aio_reqprio; /* Request priority offset */ 62 struct sigevent aio_sigevent; /* Signal to deliver */ 63 64 /* Internal kernel variables */ 65 int _state; /* State of the job */ 66 int _errno; /* Error value */ 67 ssize_t _retval; /* Return value */ 68 }; 69 70 /* Internal kernel data */ 71 #ifdef _KERNEL 72 73 /* Default limits of allowed AIO operations */ 74 #define AIO_LISTIO_MAX 512 75 #define AIO_MAX (AIO_LISTIO_MAX * 16) 76 77 #include <sys/condvar.h> 78 #include <sys/lwp.h> 79 #include <sys/mutex.h> 80 #include <sys/pool.h> 81 #include <sys/queue.h> 82 83 /* Operations (as flags) */ 84 #define AIO_LIO 0x00 85 #define AIO_READ 0x01 86 #define AIO_WRITE 0x02 87 #define AIO_SYNC 0x04 88 #define AIO_DSYNC 0x08 89 90 /* Job states */ 91 #define JOB_NONE 0x0 92 #define JOB_WIP 0x1 93 #define JOB_DONE 0x2 94 95 /* Structure for tracking the status of a collection of OPS */ 96 struct aiowaitgroup { 97 kmutex_t mtx; /* Protects entire structure */ 98 kcondvar_t done_cv; /* Signaled when job completes */ 99 size_t completed; /* Number of completed jobs in this wait group */ 100 size_t total; /* Total jobs being waited on */ 101 bool active; /* False after suspend returns/times out */ 102 int refcnt; /* Reference count */ 103 }; 104 105 /* */ 106 struct aiowaitgrouplk { 107 kmutex_t mtx; /* Protects wgs array modifications */ 108 void **wgs; /* Dynamic array of waiting aiowaitgroups */ 109 size_t s; /* Allocated size of wgs array */ 110 size_t n; /* Current number of waitgroups */ 111 }; 112 113 /* Structure of AIO job */ 114 struct aiost; 115 struct buf; 116 struct aio_job { 117 kmutex_t mtx; /* Protects completed flag */ 118 int aio_op; /* Operation type (AIO_READ/WRITE/SYNC) */ 119 struct aiocb aiocbp; /* User-visible AIO control block */ 120 void *aiocb_uptr; /* User pointer for job identification */ 121 struct proc *p; /* Originating process */ 122 bool completed; /* Job completion status */ 123 bool on_queue; /* Whether or not this job is on sp->jobs */ 124 struct file *fp; /* File pointer associated with the job */ 125 struct aiowaitgrouplk lk; /* List of waitgroups waiting on this job */ 126 TAILQ_ENTRY(aio_job) list; 127 struct lio_req *lio; /* List I/O request (if part of lio_listio) */ 128 }; 129 130 #define AIOST_STATE_NONE 0x1 131 #define AIOST_STATE_OPERATION 0x2 132 #define AIOST_STATE_TERMINATE 0x4 133 134 #define AIOSP_SUSPEND_ANY 0x1 135 #define AIOSP_SUSPEND_ALL 0x2 136 137 struct aiost; 138 struct aiost_file_group { 139 RB_ENTRY(aiost_file_group) tree; 140 struct file *fp; 141 struct aiost *aiost; 142 kmutex_t mtx; 143 TAILQ_HEAD(, aio_job) queue; 144 size_t queue_size; 145 }; 146 147 /* Structure for AIO servicing thread */ 148 struct aiosp; 149 struct aiost { 150 TAILQ_ENTRY(aiost) list; 151 struct aiosp *aiosp; /* Servicing pool of this thread */ 152 kmutex_t mtx; /* Protects this structure */ 153 kcondvar_t service_cv; /* Signal to activate thread */ 154 struct lwp *lwp; /* Servicing thread LWP */ 155 int state; /* The state of the thread */ 156 bool freelist; /* Whether or not aiost is on freelist */ 157 struct aiost_file_group *fg; /* File group associated with the thread */ 158 struct aio_job *job; /* Singleton job */ 159 }; 160 161 struct aiocbp { 162 TAILQ_ENTRY(aiocbp) list; 163 const void *uptr; 164 struct aio_job *job; 165 }; 166 167 /* Structure for AIO servicing pool */ 168 TAILQ_HEAD(aiost_list, aiost); 169 TAILQ_HEAD(aiocbp_list, aiocbp); 170 struct aiost_file_tree; 171 struct aiosp { 172 struct aiost_list freelist; /* Available service threads */ 173 size_t nthreads_free; /* Length of freelist */ 174 struct aiost_list active; /* Active servicing threads */ 175 size_t nthreads_active; /* length of active list */ 176 TAILQ_HEAD(, aio_job) jobs; /* Queue of pending jobs */ 177 size_t jobs_pending; /* Number of pending jobs */ 178 kmutex_t mtx; /* Protects structure */ 179 size_t nthreads_total; /* Number of total servicing threads */ 180 volatile u_long njobs_processing;/* Number of total jobs currently being processed*/ 181 struct aiocbp_list *aio_hash; /* Aiocbp hash root */ 182 kmutex_t aio_hash_mtx; /* Protects the hash table */ 183 size_t aio_hash_size; /* Total number of buckets */ 184 u_int aio_hash_mask; /* Hash mask */ 185 struct aiost_file_tree *fg_root;/* RB tree of file groups */ 186 }; 187 188 /* LIO structure */ 189 struct lio_req { 190 u_int refcnt; /* Reference counter */ 191 struct sigevent sig; /* Signal of lio_listio() calls */ 192 }; 193 194 /* Structure of AIO data for process */ 195 struct aioproc { 196 kmutex_t aio_mtx; /* Protects the entire structure */ 197 unsigned int jobs_count; /* Count of the jobs */ 198 struct aiosp aiosp; /* Per-process service pool */ 199 }; 200 201 extern u_int aio_listio_max; 202 203 /* 204 * Prototypes 205 */ 206 207 void aio_print_jobs(void (*)(const char *, ...) __printflike(1, 2)); 208 int aio_suspend1(struct lwp *, struct aiocb **, int, struct timespec *); 209 210 int aiosp_initialize(struct aiosp *); 211 int aiosp_destroy(struct aiosp *, int *); 212 int aiosp_distribute_jobs(struct aiosp *); 213 int aiosp_enqueue_job(struct aiosp *, struct aio_job *); 214 int aiosp_suspend(struct aiosp *, struct aiocb **, int, struct timespec *, 215 int); 216 int aiosp_flush(struct aiosp *); 217 int aiosp_validate_conflicts(struct aiosp *, const void *); 218 int aiosp_error(struct aiosp *, const void *, register_t *); 219 int aiosp_return(struct aiosp *, const void *, register_t *); 220 221 void aiowaitgroup_init(struct aiowaitgroup *); 222 void aiowaitgroup_fini(struct aiowaitgroup *); 223 int aiowaitgroup_wait(struct aiowaitgroup *, int); 224 void aiowaitgroup_done(struct aiowaitgroup *); 225 void aiowaitgroup_join(struct aiowaitgroup *, struct aiowaitgrouplk *); 226 void aiowaitgrouplk_init(struct aiowaitgrouplk *); 227 void aiowaitgrouplk_fini(struct aiowaitgrouplk *); 228 void aiowaitgrouplk_flush(struct aiowaitgrouplk *); 229 230 231 #endif /* _KERNEL */ 232 233 #endif /* _SYS_AIO_H_ */ 234