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	"@(#)buf_init.c	1.8	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 /*
     30  * Routines for inializing read and write buffers.
     31  */
     32 #include <sys/types.h>
     33 #include <sys/isa_defs.h>
     34 #include <search.h>
     35 #include "args.h"
     36 #include "diskomizer64mpism.h"
     37 #include "buf_init.h"
     38 
     39 static uchar_t seq8(int, int);
     40 static uchar_t rseq8(int, int);
     41 static uchar_t seq16(int, int);
     42 static uchar_t rseq16(int, int);
     43 static uchar_t seq32(int, int);
     44 static uchar_t rseq32(int, int);
     45 static uchar_t seq64(int, int);
     46 static uchar_t rseq64(int, int);
     47 static uchar_t random_value(int, int);
     48 static uchar_t fixed_value_func(int, int);
     49 static uchar_t cjtpat_func(int, int);
     50 static uchar_t isipat_func(int, int);
     51 static uchar_t cjt_and_isi_func(int bufno, int i);
     52 static uchar_t userpat_func(int, int);
     53 
     54 static void rbufinit_init(uchar_t *, ulong_t len, const uchar_t * const);
     55 static void zero_init(uchar_t *, ulong_t len, const uchar_t * const);
     56 static void xor_init(uchar_t *, ulong_t len, const uchar_t * const);
     57 static int rinit_init(uint64_t value);
     58 static int cinit_init(uint64_t value);
     59 static int userpat_init(struct ilist  *, int *, int);
     60 
     61 static uint64_t *read_buf_source;
     62 
     63 static struct ilist fixed_value;
     64 
     65 typedef int (*init_init_t)(struct ilist  *, int *, int);
     66 
     67 struct write_buf_initializers {
     68 	const char *name;
     69 	write_buf_initializer_t func; /* error handleing function */
     70 	init_init_t init;
     71 	int val;
     72 };
     73 
     74 typedef int (*rinit_init_t)(uint64_t);
     75 
     76 struct read_buf_initializers {
     77 	const char *name;
     78 	read_buf_initializer_t func;
     79 	rinit_init_t init;
     80 	uint64_t val;
     81 };
     82 
     83 struct write_buf_initializers write_buf_initializers[] = {
     84 	{"ONES", fixed_value_func, load_ilist, ~0},
     85 	{"ZEROS", fixed_value_func, load_ilist, 0},
     86 	{"SUPPLIED_VALUE", fixed_value_func, NULL, 0},
     87 	{"SEQ", seq8, NULL, 0}, /* for compatability */
     88 	{"RSEQ", rseq8, NULL, 0}, /* for compatability */
     89 	{"SEQ8", seq8, NULL, 0},
     90 	{"SREQ8", rseq8, NULL, 0},
     91 	{"SEQ16", seq16, NULL, 0},
     92 	{"SREQ16", rseq16, NULL, 0},
     93 	{"SEQ32", seq32, NULL, 0},
     94 	{"SREQ32", rseq32, NULL, 0},
     95 	{"SEQ64", seq64, NULL, 0},
     96 	{"SREQ64", rseq64, NULL, 0},
     97 	{"RANDOM", random_value, NULL, 0},
     98 	{"CJTPAT", cjtpat_func, NULL, 0},
     99 	{"ISIPAT", isipat_func, NULL, 0},
    100 	{"ISI_AND_CJT_PAT", cjt_and_isi_func, NULL, 0},
    101 	{"USERPAT", userpat_func, userpat_init, 0}
    102 };
    103 
    104 static size_t nel_write_buf_initializers = ARRAY_LEN(write_buf_initializers);
    105 
    106 struct read_buf_initializers read_buf_initializers[] = {
    107 	{"DEADBEEF", rbufinit_init, rinit_init, 0xDEADBEEFDEADBEEFULL},
    108 	{"DEADBEEF_64", rbufinit_init, rinit_init, 0xDEADBEEFULL},
    109 	{"SUPPLIED_VALUE", rbufinit_init, cinit_init, 0ULL},
    110 	{"ZERO", zero_init, NULL, 0ULL},
    111 	{"ZERO_ONE", rbufinit_init, rinit_init, 0x5555555555555555ULL},
    112 	{"ONE_ZERO", rbufinit_init, rinit_init, 0xAAAAAAAAAAAAAAAAULL},
    113 	{"XOR", xor_init, NULL, 0ULL},
    114 	{"NOP", (read_buf_initializer_t)nop, NULL, 0ULL},
    115 	{"NONE", (read_buf_initializer_t)nop, NULL, 0ULL}
    116 };
    117 
    118 static size_t nel_read_buf_initializers = ARRAY_LEN(read_buf_initializers);
    119 
    120 struct {
    121 	uchar_t *buf;
    122 	size_t len;
    123 } userpat_data;
    124 
    125 /*
    126  * Macro to return the correct char to give bigendian data all the time.
    127  */
    128 #ifdef _BIG_ENDIAN
    129 
    130 #define	RETURN_CHAR(X, I) return (X.c[(I) % sizeof (X)])
    131 
    132 #elif defined(_LITTLE_ENDIAN)
    133 
    134 #define	RETURN_CHAR(X, I) return (X.c[(sizeof (X) - 1) - ((I) % sizeof (X))])
    135 
    136 #else
    137 
    138 /* This "can't" happen! */
    139 #error "niether _BIG_ENDIAN or _LITTLE_ENDIAN defined"
    140 
    141 #endif
    142 
    143 /*
    144  * Seq8().  Returns an 8 bit quantity. Each
    145  * of the 8 bit quantinites are set following a standard pattern, which in
    146  * its simplest would be  just a sequence from 0 to 255. However since the
    147  * by initialising from 0 to 250, giving 251 values, we make the combination
    148  * of pattern and position of the pattern in a block not repeat for 251
    149  * blocks.  By then shifting each value by a variable amount between 0 and 4
    150  * depending on each block we move the number of blocks before the pattern
    151  * posistion pair repeats up to 1255 blocks.
    152  *
    153  * You end up with 5 blocks of X-Y inclusive:
    154  *
    155  *	0-250
    156  *	1-251
    157  *	2-252
    158  *	3-253
    159  *	4-254
    160  *
    161  *	The final pattern you see in the data is of this form:
    162  *
    163  *	0-250
    164  *	1-251
    165  *	2-252
    166  *	3-253
    167  *	4-254
    168  *	0-250
    169  *	1-251
    170  *	2-252
    171  *	3-253
    172  *	4-254
    173  *
    174  *
    175  * 251 and 5 are used as 251 is the largest prime less than or equal to
    176  * 256 and 5 is the largest prime that when added to to 251 gives less than 256.
    177  */
    178 static uchar_t
    179 seq8(int bufno, int i)
    180 {
    181 	uchar_t x, y, c;
    182 	ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len);
    183 	ulong_t bufoff = (bufno * len) + i;
    184 
    185 	x = bufoff % 251;
    186 	y = (bufoff / 251) % 5;
    187 
    188 	c = x + y;
    189 	return (c);
    190 }
    191 
    192 static uchar_t
    193 rseq8(int bufno, int i)
    194 {
    195 	return (0xff - seq8(bufno, i));
    196 }
    197 /*
    198  * the key primes for 16 bit numbers are 13 and 65521. Apart from
    199  * that the theory is the same as for the 8 bit numbers.
    200  */
    201 static uint16_t
    202 seq16gen(int bufno, int i)
    203 {
    204 	uint16_t x, y, s;
    205 	ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len);
    206 	ulong_t bufoff = ((bufno * len) + i) / sizeof (uint16_t);
    207 
    208 	x = bufoff % 65521;
    209 	y = (bufoff / 65521) % 13;
    210 
    211 	s = x + y;
    212 	return (s);
    213 }
    214 
    215 static uchar_t
    216 seq16(int bufno, int i)
    217 {
    218 	union {
    219 		uchar_t c[sizeof (uint16_t)];
    220 		uint16_t s;
    221 	} u;
    222 
    223 	u.s = seq16gen(bufno, i);
    224 
    225 	RETURN_CHAR(u, i);
    226 }
    227 
    228 static uchar_t
    229 rseq16(int bufno, int i)
    230 {
    231 	union {
    232 		uchar_t c[sizeof (uint16_t)];
    233 		uint16_t s;
    234 	} u;
    235 
    236 	u.s = USHRT_MAX - seq16gen(bufno, i);
    237 
    238 	RETURN_CHAR(u, i);
    239 }
    240 
    241 /*
    242  * For 32 bit numbers the primes are: 4294967291 and 3
    243  */
    244 static uint32_t
    245 seq32gen(int bufno, int i)
    246 {
    247 	uint32_t x, y, s;
    248 	ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len);
    249 	ulong_t bufoff = ((bufno * len) + i) / sizeof (uint32_t);
    250 
    251 	x = bufoff % 4294967291LL;
    252 	y = (bufoff / 4294967291LL) % 3;
    253 
    254 	s = x + y;
    255 	return (s);
    256 }
    257 
    258 static uchar_t
    259 seq32(int bufno, int i)
    260 {
    261 	union {
    262 		uchar_t c[sizeof (uint32_t)];
    263 		uint32_t i;
    264 	} u;
    265 
    266 	u.i = seq32gen(bufno, i);
    267 
    268 	RETURN_CHAR(u, i);
    269 }
    270 
    271 static uchar_t
    272 rseq32(int bufno, int i)
    273 {
    274 	union {
    275 		uchar_t c[sizeof (uint32_t)];
    276 		uint32_t i;
    277 	} u;
    278 
    279 	u.i = UINT_MAX - seq32gen(bufno, i);
    280 
    281 	RETURN_CHAR(u, i);
    282 }
    283 
    284 /*
    285  * For 64 bit numbers we are just not going to repeat so don't
    286  * do the prime bit.
    287  */
    288 static uint64_t
    289 seq64gen(int bufno, int i)
    290 {
    291 	uint64_t len = INDEX_TO_DIOLEN(max_disk_io_len);
    292 	uint64_t bufoff = ((bufno * len) + i) / sizeof (uint64_t);
    293 
    294 	return (bufoff);
    295 }
    296 
    297 static uchar_t
    298 seq64(int bufno, int i)
    299 {
    300 	union {
    301 		uchar_t c[sizeof (uint64_t)];
    302 		uint64_t l;
    303 	} u;
    304 
    305 	u.l = seq64gen(bufno, i);
    306 
    307 	RETURN_CHAR(u, i);
    308 }
    309 
    310 static uchar_t
    311 rseq64(int bufno, int i)
    312 {
    313 	union {
    314 		uchar_t c[sizeof (uint64_t)];
    315 		uint64_t l;
    316 	} u;
    317 
    318 	u.l = 0xffffffffffffffffULL - seq64gen(bufno, i);
    319 
    320 	RETURN_CHAR(u, i);
    321 }
    322 
    323 /*ARGSUSED*/
    324 static uchar_t
    325 random_value(int bufno, int i)
    326 {
    327 	return ((uchar_t)(lrand48() >> 8));
    328 }
    329 
    330 static uint_t
    331 get_fixed_value(int bufno)
    332 {
    333 	if (fixed_value.weightings == NULL)
    334 		return (fixed_value.vals[bufno % fixed_value.wlen]);
    335 	else
    336 		return (fixed_value.vals[fixed_value.weightings[bufno
    337 		    % fixed_value.wlen]]);
    338 }
    339 
    340 /*
    341  * Users can supply 32 bit fixed values. So this function has to give
    342  * them back in the correct way.
    343  */
    344 /*ARGSUSED*/
    345 static uchar_t
    346 fixed_value_func(int bufno, int i)
    347 {
    348 	union {
    349 		uchar_t c[sizeof (uint32_t)];
    350 		uint32_t i;
    351 	} u;
    352 
    353 	u.i = get_fixed_value(bufno);
    354 
    355 	return (u.c[i % sizeof (uint32_t)]);
    356 }
    357 
    358 static int
    359 wb_key_cmp(const void *k, const void *v)
    360 {
    361 	return (strcasecmp((char *)k,
    362 	    ((struct write_buf_initializers *)v)->name));
    363 }
    364 
    365 write_buf_initializer_t
    366 setup_write_buf_initializer(void)
    367 {
    368 	struct write_buf_initializers *r;
    369 
    370 	fixed_value = opts.write_buffer_supplied_value;
    371 
    372 	r = (struct write_buf_initializers *)lfind(
    373 	    opts.initializer, write_buf_initializers,
    374 	    &nel_write_buf_initializers,
    375 	    sizeof (write_buf_initializers[0]),
    376 	    wb_key_cmp);
    377 
    378 	if (r != NULL) {
    379 		if (r->init != NULL) {
    380 			if (r->init(&fixed_value, &r->val, 1) == 0) {
    381 				return (NULL);
    382 			}
    383 		}
    384 		return (r->func);
    385 	}
    386 	return (NULL);
    387 }
    388 
    389 /*ARGSUSED2*/
    390 static void
    391 zero_init(uchar_t *buf, ulong_t len, const uchar_t * const foo)
    392 {
    393 	(void) memset(buf, NULL, len);
    394 }
    395 /*ARGSUSED2*/
    396 static void
    397 deadbeef64_init(uchar_t *buf, ulong_t len, const uchar_t * const foo)
    398 {
    399 	ulong_t i;
    400 
    401 	for (i = 0; i < len; i += 64) {
    402 		uint32_t *ptr;
    403 
    404 		/*LINTED*/
    405 		ptr = (uint32_t *)(buf + i);
    406 		*ptr = 0xdeadbeef;
    407 	}
    408 }
    409 
    410 static void
    411 uint32_init(uchar_t *buf, ulong_t len, uint32_t value)
    412 {
    413 	ulong_t i;
    414 
    415 	for (i = 0; i < len; i += sizeof (uint32_t)) {
    416 		uint32_t *ptr;
    417 
    418 		/*LINTED*/
    419 		ptr = (uint32_t *)(buf + i);
    420 		*ptr = value;
    421 	}
    422 }
    423 
    424 /*ARGSUSED2*/
    425 static void
    426 rbufinit_init(uchar_t *buf, ulong_t len, const uchar_t * const foo)
    427 {
    428 	memcpy(buf, read_buf_source, len);
    429 }
    430 
    431 static void
    432 xor_init(uchar_t *buf, ulong_t len, const uchar_t * const data_written)
    433 {
    434 	ulong_t i;
    435 
    436 	for (i = 0; i < len; i += sizeof (uint32_t)) {
    437 		uint32_t *to;
    438 		uint32_t *from;
    439 
    440 		/*LINTED*/
    441 		to = (uint32_t *)(buf + i);
    442 		/*LINTED*/
    443 		from = (uint32_t *)(data_written + i);
    444 		*to = 0xffffffff ^ *from;
    445 	}
    446 }
    447 
    448 static int
    449 rb_key_cmp(const void *k, const void *v)
    450 {
    451 	return (strcasecmp((char *)k,
    452 	    ((struct read_buf_initializers *)v)->name));
    453 }
    454 
    455 read_buf_initializer_t
    456 setup_read_buf_initializer(void)
    457 {
    458 	struct read_buf_initializers *r;
    459 
    460 	if ((r = (struct read_buf_initializers *)lfind(
    461 	    opts.read_buffer_init, read_buf_initializers,
    462 	    &nel_read_buf_initializers,
    463 	    sizeof (read_buf_initializers[0]), rb_key_cmp)) != NULL) {
    464 		if (r->init != NULL) {
    465 			if (r->init(r->val) == 0) {
    466 				return (NULL);
    467 			}
    468 		}
    469 		return (r->func);
    470 	} else {
    471 		return (NULL);
    472 	}
    473 }
    474 
    475 
    476 static int
    477 rinit_init(uint64_t value)
    478 {
    479 	uint64_t *x;
    480 	int i;
    481 	int fd;
    482 
    483 	if ((fd = open("/dev/zero", O_RDWR)) == -1)
    484 		return (NULL);
    485 
    486 	x = (uint64_t *)mmap(NULL, INDEX_TO_DIOLEN(max_disk_io_len),
    487 	    PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    488 	close(fd);
    489 	if (x == MAP_FAILED)
    490 		return (NULL);
    491 	read_buf_source = x;
    492 
    493 	for (i = 0; i < INDEX_TO_DIOLEN(max_disk_io_len);
    494 	    i += sizeof (uint64_t)) {
    495 		*(x++) = value;
    496 	}
    497 
    498 	mprotect((char *)read_buf_source, INDEX_TO_DIOLEN(max_disk_io_len),
    499 	    PROT_READ);
    500 
    501 	return (1);
    502 }
    503 
    504 static int
    505 vinit_init(uint32_t value)
    506 {
    507 	union {
    508 		uint64_t ll;
    509 		uint32_t i[sizeof (uint64_t)/sizeof (uint32_t)];
    510 	} u;
    511 	int i;
    512 
    513 	for (i = 0; i < ARRAY_LEN(u.i); i++) {
    514 		u.i[i] = value;
    515 	}
    516 	return (rinit_init(u.ll));
    517 }
    518 
    519 static int
    520 cinit_init(uint64_t value)
    521 {
    522 	return (vinit_init(opts.read_buffer_supplied_value));
    523 }
    524 
    525 static uchar_t
    526 pat_func(int bufno, int i, uchar_t *pat, int plen)
    527 {
    528 	ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len);
    529 	ulong_t off = ((bufno * len) + i) % plen;
    530 
    531 	return (pat[off]);
    532 }
    533 /*
    534  * CJTPAT Payload pattern is:
    535  *	167 7E's
    536  *	1 74
    537  *	1 7E
    538  *	1 AB
    539  *	51 B5's
    540  *	1 5E
    541  *	1 4A
    542  *	4 7E's
    543  *	1 FE
    544  */
    545 static uchar_t cjtpat[] = {
    546 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 1 */
    547 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 2 */
    548 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 3 */
    549 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 4 */
    550 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 5 */
    551 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 6 */
    552 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 7 */
    553 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 8 */
    554 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 9 */
    555 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 10 */
    556 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 11 */
    557 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 12 */
    558 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 13 */
    559 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 14 */
    560 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 15 */
    561 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 16 */
    562 	0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x74, 0x7e, 0xab, /* 17 */
    563 	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 18 */
    564 	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 19 */
    565 	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 20 */
    566 	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 21 */
    567 	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 22 */
    568 	0xb5, 0x5e, 0x4A, 0x7e, 0x7e, 0x7e, 0x7e, 0xfe /* 23 */
    569 };
    570 
    571 static uchar_t
    572 cjtpat_func(int bufno, int i)
    573 {
    574 	assert(sizeof (cjtpat) == 228);
    575 
    576 	return (pat_func(bufno, i, cjtpat, sizeof (cjtpat)));
    577 }
    578 
    579 /*
    580  * ISI "Killer" pattern
    581  *
    582  * 00101101, = 0x2d
    583  * 11110100, = 0xf4
    584  * 10000010, = 0x82
    585  * 11011111, = 0xdf
    586  * 01001000, = 0x48
    587  */
    588 static uchar_t isipat[] = {
    589 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    590 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    591 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    592 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    593 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    594 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    595 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    596 	0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb,
    597 	0xf4, 0x2d, 0xf4, 0x82, 0xdf, 0x48
    598 };
    599 
    600 static uchar_t
    601 isipat_func(int bufno, int i)
    602 {
    603 	return (pat_func(bufno, i, isipat, sizeof (isipat)));
    604 }
    605 
    606 static int
    607 userpat_init(struct ilist  *a, int *b, int c)
    608 {
    609 
    610 	int fd;
    611 	struct stat buf;
    612 
    613 	if ((fd = open(opts.expert_userpat_file, O_RDONLY)) == -1) {
    614 		return (1);
    615 	}
    616 	if (fstat(fd, &buf) == -1) {
    617 		close(fd);
    618 		return (1);
    619 	}
    620 
    621 	userpat_data.buf = (uchar_t *)mmap(0, buf.st_size,
    622 	    PROT_READ, MAP_PRIVATE, fd, 0);
    623 	close(fd);
    624 
    625 	if (userpat_data.buf == MAP_FAILED) {
    626 		return (1);
    627 	}
    628 	userpat_data.len = buf.st_size;
    629 }
    630 
    631 static uchar_t
    632 userpat_func(int bufno, int i)
    633 {
    634 	return (pat_func(bufno, i, userpat_data.buf, userpat_data.len));
    635 }
    636 
    637 static uchar_t
    638 cjt_and_isi_func(int bufno, int i)
    639 {
    640 	ulong_t plen = sizeof (isipat) + sizeof (cjtpat);
    641 	ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len);
    642 	ulong_t off = ((bufno * len) + i) % plen;
    643 
    644 	if (off > sizeof (isipat)) {
    645 		return (cjtpat[off - sizeof (isipat)]);
    646 	} else {
    647 		return (isipat[off]);
    648 	}
    649 }
    650