Home | History | Annotate | Download | only in diskomizer
      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