1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #pragma ident "@(#)daio_sunos.c 1.16 09/05/26 SMI" 23 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include <diskomizer/daio.h> 30 #include <diskomizer/checker.h> 31 #include "findap.h" 32 #include <sys/asynch.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <errno.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <diskomizer/daio_dev.h> 41 #include <diskomizer/assert.h> 42 43 static void *daio_sunos_init(int count); 44 static void daio_sunos_init_checker(const char *checker, 45 off64_t max_block_size); 46 static data_checker_t daio_sunos_what_checker(void); 47 static ssize_t daio_sunos_pwrite(int fildes, const uchar_t *bufp, size_t bufs, 48 off_t off, struct daio_id *id); 49 static ssize_t daio_sunos_pread(int fildes, uchar_t *bufp, size_t bufs, 50 off_t off, struct daio_id *id); 51 static int daio_sunos_awrite(int fildes, uchar_t *bufp, int bufs, off_t 52 offset, daio_result_t *resultp, struct daio_id *id); 53 static int daio_sunos_aread(int fildes, uchar_t *bufp, int bufs, off_t 54 offset, daio_result_t *resultp, struct daio_id *id); 55 static daio_status_t daio_sunos_status(daio_result_t *resultp); 56 static hrtime_t daio_sunos_start_time(daio_result_t *resultp); 57 static hrtime_t daio_sunos_end_time(daio_result_t *resultp); 58 static daio_result_t *daio_sunos_wait(const struct timeval *tv); 59 static int daio_sunos_cancel(daio_result_t *resultp); 60 61 static void daio_sunos_fini(void *handle); 62 63 static int (*data_check)(uchar_t *buf, size_t bufs, struct daio_id *id); 64 65 struct daio_sunos_str { 66 daio_result_t res; 67 daio_result_t *resp; 68 int next; 69 struct daio_id *id; 70 uchar_t *bufp; 71 }; 72 struct daio_ops DAIO_OPS = { 73 daio_sunos_init, 74 daio_sunos_init_checker, 75 daio_sunos_what_checker, 76 findap, 77 (daio_open_t)daio_dev_open, 78 daio_dev_close, 79 unlink, 80 stat64, 81 fstat64, 82 ioctl, 83 ftruncate64, 84 daio_dev_directio, 85 read_disko_vtoc, 86 daio_sunos_pwrite, 87 daio_sunos_pread, 88 daio_sunos_awrite, 89 daio_sunos_aread, 90 daio_sunos_status, 91 daio_sunos_start_time, 92 daio_sunos_end_time, 93 daio_sunos_wait, 94 daio_sunos_cancel, 95 daio_sunos_fini, 96 daio_dev_dd 97 }; 98 99 struct daio_sunos_str *daio_sunos_base; 100 int daio_size = -1; 101 int free_list = -1; 102 103 static int 104 push(int list, int entry) 105 { 106 assert(entry < daio_size); 107 assert(free_list < daio_size); 108 daio_sunos_base[entry].next = list; 109 return (entry); 110 } 111 #define pop(list) (list = daio_sunos_base[list].next) 112 #define ADD_TO_FREE(X) free_list = push(free_list, X) 113 static int 114 get_free(void) 115 { 116 int entry = free_list; 117 assert(free_list < daio_size); 118 pop(free_list); 119 assert(free_list < daio_size); 120 daio_sunos_base[entry].next = -1; 121 return (entry); 122 } 123 static int 124 bounds_check(daio_result_t *res) 125 { 126 int x = (int)((long)res->private_data); 127 128 if (x >= 0 && x < daio_size && daio_sunos_base[x].resp == res) { 129 return (x); 130 } else { 131 return (-1); 132 } 133 } 134 135 static void * 136 daio_sunos_init(int count) 137 { 138 int i; 139 daio_sunos_base = calloc(count, sizeof (struct daio_sunos_str)); 140 if (daio_sunos_base == NULL) { 141 return (NULL); 142 } 143 daio_size = count; 144 for (i = 0; i < count; i++) { 145 daio_sunos_base[i].next = -1; 146 ADD_TO_FREE(i); 147 } 148 149 return (daio_sunos_base); 150 } 151 152 /*ARGSUSED*/ 153 static void 154 daio_sunos_init_checker(const char *checker, off64_t max_block_size) 155 { 156 data_check = choose_data_checker(checker); 157 } 158 159 static data_checker_t 160 daio_sunos_what_checker(void) 161 { 162 return (data_check); 163 } 164 165 static int 166 daio_sunos_awrite(int fildes, uchar_t *bufp, int bufs, off_t 167 offset, daio_result_t *resultp, struct daio_id *id) 168 { 169 int i; 170 int result; 171 assert(free_list < daio_size); 172 i = get_free(); 173 174 daio_sunos_base[i].id = id; 175 daio_sunos_base[i].res = *resultp; 176 daio_sunos_base[i].resp = resultp; 177 daio_sunos_base[i].bufp = NULL; 178 resultp->private_data = (void *)((long)i); 179 DAIO_SET_RETURN(daio_sunos_base[i].res, AIO_INPROGRESS); 180 DAIO_SET_START_TIME(daio_sunos_base[i].res, gethrtime()); 181 182 assert(free_list < daio_size); 183 184 result = aiowrite64(fildes, (char *)bufp, bufs, offset, SEEK_SET, 185 (aio_result_t *)&daio_sunos_base[i].res); 186 187 if (result != 0) { 188 ADD_TO_FREE(i); 189 } 190 return (result); 191 } 192 static int 193 daio_sunos_aread(int fildes, uchar_t *bufp, int bufs, off_t 194 offset, daio_result_t *resultp, struct daio_id *id) 195 { 196 int i; 197 int result; 198 i = get_free(); 199 assert(free_list < daio_size); 200 201 daio_sunos_base[i].id = id; 202 daio_sunos_base[i].res = *resultp; 203 daio_sunos_base[i].resp = resultp; 204 daio_sunos_base[i].bufp = bufp; 205 resultp->private_data = (void *)((long)i); 206 DAIO_SET_RETURN(daio_sunos_base[i].res, AIO_INPROGRESS); 207 DAIO_SET_START_TIME(daio_sunos_base[i].res, gethrtime()); 208 209 assert(free_list < daio_size); 210 211 result = aioread64(fildes, (char *)bufp, bufs, offset, SEEK_SET, 212 (aio_result_t *)&daio_sunos_base[i].res); 213 214 if (result != 0) { 215 ADD_TO_FREE(i); 216 } 217 return (result); 218 } 219 static daio_status_t 220 daio_sunos_status(daio_result_t *resultp) 221 { 222 int x; 223 assert(free_list < daio_size || daio_size == -1); 224 if ((x = bounds_check(resultp)) == -1) { 225 return (DAIO_COMPLETE); 226 } else { 227 return (DAIO_RETURN(daio_sunos_base[x].res) == AIO_INPROGRESS ? 228 DAIO_INPROGRESS : DAIO_COMPLETE); 229 } 230 } 231 static daio_result_t * 232 daio_sunos_wait(const struct timeval *timeout) 233 { 234 struct daio_sunos_str *resp; 235 daio_result_t *resultp; 236 assert(free_list < daio_size || daio_size == -1); 237 resp = (struct daio_sunos_str *)aiowait((struct timeval *)timeout); 238 if (resp != NULL && resp != (struct daio_sunos_str *)-1) { 239 resultp = resp->resp; 240 *resultp = resp->res; 241 resp->resp = NULL; 242 DAIO_SET_END_TIME(*resultp, gethrtime()); 243 244 if (resp->bufp != NULL && 245 DAIO_RETURN(*resultp) == resp->id->bufs && 246 data_check(resp->bufp, DAIO_RETURN(*resultp), 247 resp->id) < 0) { 248 DAIO_SET_RETURN(*resultp, DAIO_CORRUPT); 249 } 250 assert(&daio_sunos_base[resp - daio_sunos_base] == resp); 251 ADD_TO_FREE(resp - daio_sunos_base); 252 } else { 253 resultp = (daio_result_t *)resp; 254 } 255 return (resultp); 256 } 257 static int 258 daio_sunos_cancel(daio_result_t *resultp) 259 { 260 struct daio_sunos_str *resp; 261 int ret; 262 int i; 263 264 assert(free_list < daio_size); 265 266 if (daio_sunos_status(resultp) == DAIO_INPROGRESS) { 267 errno = EACCES; 268 return (-1); 269 } 270 i = (int)((long)resultp->private_data); 271 272 resp = &daio_sunos_base[i]; 273 ret = aiocancel((aio_result_t *)&resp->res); 274 275 if (ret == 0) { 276 *resultp = resp->res; 277 ADD_TO_FREE(i); 278 } 279 return (ret); 280 } 281 /*ARGSUSED*/ 282 static void 283 daio_sunos_fini(void *handle) 284 { 285 if (daio_sunos_base && daio_sunos_base == handle) { 286 free(daio_sunos_base); 287 daio_sunos_base = NULL; 288 } 289 } 290 291 static hrtime_t 292 daio_sunos_start_time(daio_result_t *resultp) 293 { 294 int i = (int)((long)resultp->private_data); 295 assert(free_list < daio_size); 296 return (DAIO_GET_START_TIME(daio_sunos_base[i].res)); 297 } 298 299 static hrtime_t 300 daio_sunos_end_time(daio_result_t *resultp) 301 { 302 int i = (int)((long)resultp->private_data); 303 assert(free_list < daio_size); 304 return (DAIO_GET_END_TIME(daio_sunos_base[i].res)); 305 } 306 307 /*ARGSUSED*/ 308 static ssize_t 309 daio_sunos_pwrite(int fildes, const uchar_t *bufp, size_t bufs, off_t off, 310 struct daio_id *id) 311 { 312 return (pwrite(fildes, bufp, bufs, off)); 313 } 314 315 static ssize_t 316 daio_sunos_pread(int fildes, uchar_t *bufp, size_t bufs, off_t off, 317 struct daio_id *id) 318 { 319 ssize_t ret; 320 321 ret = pread(fildes, bufp, bufs, off); 322 323 if (id != NULL && ret == bufs) { 324 if (data_check(bufp, ret, id) < 0) 325 ret = DAIO_CORRUPT; 326 } 327 return (ret); 328 } 329