xref: /titanic_41/usr/src/common/lvm/md_convert.c (revision 74e20cfe817b82802b16fac8690dadcda76f54f5)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * md_convert.c
31  *
32  * As the size of a metadevice used to be stored in 32 bit signed variables,
33  * there was a limit of 1 TB for the size (2^31 * 512 byte).
34  * In order to be able to create larger metadevices, a 2nd set of structures
35  * with wider variables for the size has been created.
36  * There's one structure being shared by all types (mdc_unit_t) and one
37  * for each type of metadevice (mm_unit_t, ms_unit_t, mr_unit_t, ...).
38  * the wide structures are named like mdc_unit_t, mm_unit_t,..
39  * The narrow structures are named like mdc_unit32_od_t, mm_unit32_od_t,...
40  *
41  * The wide structures are used for md's >= 1TB, the narrow structures
42  * are used for md's < 1TB.
43  * Once a metadevice grows from < 1TB to >= 1TB the record has to be
44  * converted from a narrow one to a wide one.
45  *
46  * Incore (commands, libs and drivers) we only use the wide structures,
47  * in order to keep it simple.
48  * This means when we snarf a narrow struct, we have to convert it to a
49  * wide incore instance before we can use the md.
50  *
51  *
52  * This file contains conversion routines for the various metadevices.
53  * All the conversion routines take as input two pointers to memory areas
54  * and a direction. The directions specifies which memory area is the
55  * source and which is the destination.
56  */
57 
58 
59 #include <sys/sysmacros.h>
60 #include <sys/types.h>
61 #include <sys/cmn_err.h>
62 #include <sys/lvm/mdvar.h>
63 #ifdef _KERNEL
64 #include <sys/lvm/md_basic.h>
65 #else /* !_KERNEL */
66 #include <meta_basic.h>
67 #endif /* _KERNEL */
68 #include <sys/lvm/md_convert.h>
69 
70 
71 /*
72  * SVM private devt expansion routine
73  * INPUT:  dev  a 64 bit container holding either a 32 bit or a 64 bit device
74  * OUTPUT: always an expanded 64 bit device, even if we are running in a
75  *              32 bit Kernel.
76  */
77 md_dev64_t
78 md_expldev(md_dev64_t dev)
79 {
80 	minor_t minor;
81 	major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64;
82 
83 	/* Here we were given a 64bit dev, return unchanged */
84 	if (major != (major_t)0)
85 		return (dev);
86 	/* otherwise we were given a 32 bit dev */
87 	major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32;
88 	minor = (minor_t)dev & MAXMIN32;
89 	return (((md_dev64_t)major << NBITSMINOR64) | minor);
90 }
91 
92 /*
93  * SVM private devt compact routine
94  * INPUT:  dev  a 64 bit container holding either a 32 bit or a 64 bit device
95  * OUTPUT: always a compacted 32 bit device, even if we are running in a
96  *              64 bit Kernel.
97  */
98 dev32_t
99 md_cmpldev(md_dev64_t dev)
100 {
101 	minor_t minor;
102 	major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64;
103 
104 	/* Here we were given a 32bit dev, return unchanged */
105 	if (major == 0) {
106 		return ((dev32_t)dev);
107 	}
108 	/* otherwise we were given a 64 bit dev */
109 	minor = (minor_t)dev & MAXMIN32;
110 	return (((dev32_t)major << NBITSMINOR32) | minor);
111 }
112 
113 
114 /*
115  * given a small stripe unit, compute the size of an appropriate
116  * big stripe unit.
117  * if first_comp_only is set just return the offset of the first component
118  * in the new big unit.
119  *
120  * The function:
121  * usr/src/lib/lvm/libmeta/common/meta_statconcise.c:get_stripe_req_size()
122  * contains code derived from this function and thus if any changes are made to
123  * this function get_stripe_req_size() should be evaluated to determine whether
124  * or not code changes will also  be necessary there.
125  *
126  */
127 size_t
128 get_big_stripe_req_size(ms_unit32_od_t *un, int first_comp_only)
129 {
130 	struct ms_row32_od *mdr;
131 	uint_t row;
132 	uint_t ncomps = 0;
133 	size_t mdsize = 0;
134 	size_t first_comp = 0;
135 
136 
137 	/* Compute the offset of the first component */
138 	first_comp = sizeof (ms_unit_t) +
139 			sizeof (struct ms_row) * (un->un_nrows - 1);
140 	first_comp = roundup(first_comp, sizeof (long long));
141 	if (first_comp_only == FIRST_COMP_OFFSET)
142 		return (first_comp);
143 
144 	/*
145 	 * Requestor wants to have the total size, add the sizes of
146 	 * all components
147 	 */
148 	mdr = &un->un_row[0];
149 	for (row = 0; (row < un->un_nrows); row++)
150 		ncomps += mdr[row].un_ncomp;
151 	mdsize = first_comp + sizeof (ms_comp_t) * ncomps;
152 	return (mdsize);
153 }
154 
155 /*
156  * given a big stripe unit, compute the size of an appropriate
157  * small stripe unit.
158  * if first_comp_only is set just return the offset of the first component
159  * in the new small unit.
160  */
161 size_t
162 get_small_stripe_req_size(ms_unit_t *un, int first_comp_only)
163 {
164 	struct ms_row *mdr;
165 	uint_t row;
166 	uint_t ncomps = 0;
167 	size_t mdsize;
168 	size_t first_comp;
169 
170 	/* Compute the size of the new small ms_unit */
171 	first_comp = sizeof (ms_unit32_od_t) +
172 			sizeof (struct ms_row32_od) * (un->un_nrows - 1);
173 	first_comp = roundup(first_comp, sizeof (long long));
174 	if (first_comp_only == FIRST_COMP_OFFSET)
175 		return (first_comp);
176 
177 	/*
178 	 * Requestor wants to have the total size, add the sizes of
179 	 * all components
180 	 */
181 	mdr = &un->un_row[0];
182 	for (row = 0; (row < un->un_nrows); row++)
183 		ncomps += mdr[row].un_ncomp;
184 	mdsize = first_comp + sizeof (ms_comp32_od_t) * ncomps;
185 	return (mdsize);
186 }
187 
188 
189 /*
190  * stripe_convert(small, big, dir)
191  *
192  * Parameters:
193  *	small is the address of a ms_unit32_od_t structure
194  *	big   is the address of a ms_unit_t structure
195  *	dir   is either BIG2SMALL or SMALL2BIG
196  * Return value is void
197  *
198  * what it does:
199  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
200  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
201  *
202  * Caveat emptor: big and small must be well allocated memory areas.
203  */
204 
205 void
206 stripe_convert(caddr_t small, caddr_t big, int direction)
207 {
208 	/*LINTED*/
209 	ms_unit32_od_t *small_un = (ms_unit32_od_t *)small;
210 	/*LINTED*/
211 	ms_unit_t *big_un = (ms_unit_t *)big;
212 
213 	struct ms_row32_od	*small_mdr;
214 	struct ms_row		*big_mdr;
215 	uint_t			row, comp, ncomps = 0;
216 	ms_comp_t		*big_mdcomp;
217 	ms_comp32_od_t		*small_mdcomp;
218 
219 	if (direction == BIG_2_SMALL) {
220 		MDC_UNIT_BIG2SMALL(big_un, small_un);
221 
222 		small_un->un_hsp_id = big_un->un_hsp_id;
223 		small_un->un_nrows  = big_un->un_nrows;
224 		small_un->c.un_size =
225 			get_small_stripe_req_size(big_un, COMPLETE_STRUCTURE);
226 		small_un->un_ocomp  =
227 			get_small_stripe_req_size(big_un, FIRST_COMP_OFFSET);
228 
229 		/* walk through all rows */
230 		big_mdr   = &big_un->un_row[0];
231 		small_mdr = &small_un->un_row[0];
232 
233 		for (row = 0; (row < big_un->un_nrows); row++) {
234 			ncomps += big_mdr[row].un_ncomp;
235 			MSROW_BIG2SMALL((&(big_mdr[row])), (&(small_mdr[row])));
236 		}
237 
238 		/* Now copy the components */
239 		big_mdcomp   = (ms_comp_t *)(void *)&((char *)big_un)
240 				[big_un->un_ocomp];
241 		small_mdcomp = (ms_comp32_od_t *)(void *)&((char *)small_un)
242 				[small_un->un_ocomp];
243 		for (comp = 0; (comp < ncomps); ++comp) {
244 			ms_comp_t	*big_mdcp   = &big_mdcomp[comp];
245 			ms_comp32_od_t	*small_mdcp = &small_mdcomp[comp];
246 
247 			MSCOMP_BIG2SMALL(big_mdcp, small_mdcp);
248 
249 		}
250 	}
251 
252 	if (direction == SMALL_2_BIG) {
253 		MDC_UNIT_SMALL2BIG(small_un, big_un);
254 
255 		big_un->un_hsp_id = small_un->un_hsp_id;
256 		big_un->un_nrows  = small_un->un_nrows;
257 		big_un->c.un_size =
258 			get_big_stripe_req_size(small_un, COMPLETE_STRUCTURE);
259 		big_un->un_ocomp  =
260 			get_big_stripe_req_size(small_un, FIRST_COMP_OFFSET);
261 
262 
263 		/* walk through all rows */
264 		small_mdr = &small_un->un_row[0];
265 		big_mdr   = &big_un->un_row[0];
266 
267 		for (row = 0; (row < small_un->un_nrows); row++) {
268 			ncomps += small_mdr[row].un_ncomp;
269 			MSROW_SMALL2BIG((&(small_mdr[row])), (&(big_mdr[row])));
270 		}
271 		/* Now copy the components */
272 		big_mdcomp = (ms_comp_t *)(void *)&((char *)big_un)
273 				[big_un->un_ocomp];
274 		small_mdcomp = (ms_comp32_od_t *)(void *)&((char *)small_un)
275 				[small_un->un_ocomp];
276 		for (comp = 0; (comp < ncomps); ++comp) {
277 			ms_comp_t *big_mdcp = &big_mdcomp[comp];
278 			ms_comp32_od_t *small_mdcp = &small_mdcomp[comp];
279 
280 			MSCOMP_SMALL2BIG(small_mdcp, big_mdcp);
281 
282 		}
283 	}
284 }
285 
286 /*
287  * mirror_convert(small, big, dir)
288  *
289  * Parameters:
290  *	small is the address of a mm_unit32_od_t structure
291  *	big   is the address of a mm_unit_t structure
292  *	dir   is either BIG2SMALL or SMALL2BIG
293  * Return value is void
294  *
295  * what it does:
296  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
297  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
298  *
299  * Caveat emptor: big and small must be well allocated memory areas.
300  */
301 void
302 mirror_convert(caddr_t small, caddr_t big, int direction)
303 {
304 	/*LINTED*/
305 	mm_unit32_od_t *small_un = (mm_unit32_od_t *)small;
306 	/*LINTED*/
307 	mm_unit_t *big_un = (mm_unit_t *)big;
308 	int i;
309 
310 
311 	if (direction == BIG_2_SMALL) {
312 		MDC_UNIT_BIG2SMALL(big_un, small_un);
313 
314 		small_un->c.un_size =
315 		    roundup(sizeof (mm_unit32_od_t), sizeof (long long));
316 		small_un->un_last_read = big_un->un_last_read;
317 		small_un->un_changecnt = big_un->un_changecnt;
318 		small_un->un_nsm = big_un->un_nsm;
319 		for (i = 0; i < NMIRROR; i++) {
320 			MMSM_BIG2SMALL((&(big_un->un_sm[i])),
321 			    (&(small_un->un_sm[i])));
322 		}
323 		small_un->un_ovrlap_chn_flg = big_un->un_ovrlap_chn_flg;
324 		small_un->un_read_option = big_un->un_read_option;
325 		small_un->un_write_option = big_un->un_write_option;
326 		small_un->un_pass_num = big_un->un_pass_num;
327 		small_un->un_rrd_blksize = big_un->un_rrd_blksize;
328 		small_un->un_rrd_num = big_un->un_rrd_num;
329 		small_un->un_rr_dirty_recid = big_un->un_rr_dirty_recid;
330 		small_un->un_rs_copysize = big_un->un_rs_copysize;
331 		small_un->un_rs_dests = big_un->un_rs_dests;
332 		small_un->un_rs_resync_done =
333 		    (daddr32_t)big_un->un_rs_resync_done;
334 		small_un->un_rs_resync_2_do =
335 		    (daddr32_t)big_un->un_rs_resync_2_do;
336 		small_un->un_rs_dropped_lock = big_un->un_rs_dropped_lock;
337 		small_un->un_rs_type = big_un->un_rs_type;
338 	}
339 
340 	if (direction == SMALL_2_BIG) {
341 		MDC_UNIT_SMALL2BIG(small_un, big_un);
342 		big_un->c.un_size =
343 		    roundup(sizeof (mm_unit_t), sizeof (long long));
344 		big_un->un_last_read = small_un->un_last_read;
345 		big_un->un_changecnt = small_un->un_changecnt;
346 		big_un->un_nsm = small_un->un_nsm;
347 
348 
349 		for (i = 0; i < NMIRROR; i++) {
350 			MMSM_SMALL2BIG((&(small_un->un_sm[i])),
351 			    (&(big_un->un_sm[i])));
352 		}
353 
354 
355 		/* Now back to the simple things again */
356 		big_un->un_ovrlap_chn_flg = small_un->un_ovrlap_chn_flg;
357 		big_un->un_read_option = small_un->un_read_option;
358 		big_un->un_write_option = small_un->un_write_option;
359 		big_un->un_pass_num = small_un->un_pass_num;
360 		big_un->un_rrd_blksize = small_un->un_rrd_blksize;
361 		big_un->un_rrd_num = small_un->un_rrd_num;
362 		big_un->un_rr_dirty_recid = small_un->un_rr_dirty_recid;
363 		big_un->un_rs_copysize = small_un->un_rs_copysize;
364 		big_un->un_rs_dests = small_un->un_rs_dests;
365 		big_un->un_rs_resync_done =
366 		    (diskaddr_t)small_un->un_rs_resync_done;
367 		big_un->un_rs_resync_2_do =
368 		    (diskaddr_t)small_un->un_rs_resync_2_do;
369 		big_un->un_rs_dropped_lock = small_un->un_rs_dropped_lock;
370 		big_un->un_rs_type = small_un->un_rs_type;
371 	}
372 }
373 
374 /*
375  * raid_convert(small, big, dir)
376  *
377  * Parameters:
378  *	small is the address of a mr_unit32_od_t structure
379  *	big   is the address of a mr_unit_t structure
380  *	dir   is either BIG2SMALL or SMALL2BIG
381  * Return value is void
382  *
383  * what it does:
384  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
385  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
386  *
387  * Caveat emptor: big and small must be well allocated memory areas.
388  */
389 void
390 raid_convert(caddr_t small, caddr_t big, int direction)
391 
392 {
393 	/*LINTED*/
394 	mr_unit32_od_t *small_un = (mr_unit32_od_t *)small;
395 	/*LINTED*/
396 	mr_unit_t *big_un = (mr_unit_t *)big;
397 
398 	int i;
399 	uint_t	ncol;
400 
401 	if (direction == BIG_2_SMALL) {
402 		MRUNIT_BIG2SMALL(big_un, small_un);
403 
404 		ncol = small_un->un_totalcolumncnt;
405 		small_un->c.un_size = sizeof (mr_unit32_od_t);
406 		small_un->c.un_size += (ncol - 1) * sizeof (mr_column32_od_t);
407 		for (i = 0; i < ncol; i++) {
408 			MRCOL_BIG2SMALL((&(big_un->un_column[i])),
409 			    (&(small_un->un_column[i])));
410 		}
411 	}
412 
413 	if (direction == SMALL_2_BIG) {
414 		MRUNIT_SMALL2BIG(small_un, big_un);
415 
416 		ncol = big_un->un_totalcolumncnt;
417 		big_un->c.un_size = sizeof (mr_unit_t);
418 		big_un->c.un_size += (ncol - 1) * sizeof (mr_column_t);
419 		for (i = 0; i < ncol; i++) {
420 			MRCOL_SMALL2BIG((&(small_un->un_column[i])),
421 			    (&(big_un->un_column[i])));
422 		}
423 	}
424 }
425 
426 
427 
428 
429 
430 /*
431  * softpart_convert(small, big, dir)
432  *
433  * Parameters:
434  *	small is the address of a mp_unit32_od_t structure
435  *	big   is the address of a mp_unit_t structure
436  *	dir   is either BIG2SMALL or SMALL2BIG
437  * Return value is void
438  *
439  * what it does:
440  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
441  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
442  *
443  * Caveat emptor: big and small must be well allocated memory areas.
444  */
445 void
446 softpart_convert(caddr_t small, caddr_t big, int direction)
447 
448 {
449 	/*LINTED*/
450 	mp_unit32_od_t *small_un = (mp_unit32_od_t *)small;
451 	/*LINTED*/
452 	mp_unit_t *big_un = (mp_unit_t *)big;
453 
454 	if (direction == BIG_2_SMALL) {
455 		MPUNIT_BIG2SMALL(big_un, small_un);
456 		/*
457 		 * Note that there isn't a mp_ext32_od_t, it's right to use
458 		 * mp_ext_t here, too.
459 		 */
460 		small_un->c.un_size = sizeof (mp_unit32_od_t) +
461 			(small_un->un_numexts - 1) * sizeof (mp_ext_t);
462 	}
463 
464 	if (direction == SMALL_2_BIG) {
465 		MPUNIT_SMALL2BIG(small_un, big_un);
466 		big_un->c.un_size = sizeof (mp_unit_t) +
467 			(big_un->un_numexts - 1) * sizeof (mp_ext_t);
468 	}
469 }
470 
471 
472 /*
473  * trans_master_convert(smallp, bigp, dir)
474  *
475  * Parameters:
476  *	smallp is the address of a mt_unit32_od_t structure
477  *	bigp   is the address of a mt_unit_t structure
478  *	dir   is either BIG2SMALL or SMALL2BIG
479  * Return value is void
480  *
481  * what it does:
482  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
483  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
484  *
485  * Caveat emptor: bigp and smallp must be well allocated memory areas.
486  */
487 void
488 trans_master_convert(caddr_t smallp, caddr_t bigp, int direction)
489 {
490 	/*LINTED*/
491 	mt_unit32_od_t *small = (mt_unit32_od_t *)smallp;
492 	/*LINTED*/
493 	mt_unit_t *big = (mt_unit_t *)bigp;
494 
495 	if (direction == SMALL_2_BIG) {
496 		MDC_UNIT_SMALL2BIG(small, big);
497 		big->c.un_size =
498 		    roundup(sizeof (mt_unit_t), sizeof (long long));
499 		big->un_flags		= small->un_flags;
500 		big->un_m_key		= small->un_m_key;
501 		big->un_m_dev		= md_expldev(small->un_m_dev);
502 		big->un_l_key		= small->un_l_key;
503 		big->un_l_dev		= md_expldev(small->un_l_dev);
504 		big->un_l_sblk		= small->un_l_sblk;
505 		big->un_l_pwsblk	= small->un_l_pwsblk;
506 		big->un_l_nblks		= small->un_l_nblks;
507 		big->un_l_tblks		= small->un_l_tblks;
508 		big->un_l_head		= small->un_l_head;
509 		big->un_l_tail		= small->un_l_tail;
510 		big->un_l_resv		= small->un_l_resv;
511 		big->un_l_maxresv	= small->un_l_maxresv;
512 		big->un_l_recid		= small->un_l_recid;
513 		big->un_l_error		= small->un_l_error;
514 		big->un_s_dev		= md_expldev(small->un_s_dev);
515 		big->un_debug		= small->un_debug;
516 		big->un_dev		= md_expldev(small->un_dev);
517 		big->un_logreset	= small->un_logreset;
518 		big->un_l_maxtransfer	= small->un_l_maxtransfer;
519 		big->un_timestamp.tv_sec = small->un_timestamp.tv_sec;
520 		big->un_timestamp.tv_usec = small->un_timestamp.tv_usec;
521 		big->un_l_timestamp.tv_sec = small->un_l_timestamp.tv_sec;
522 		big->un_l_timestamp.tv_usec = small->un_l_timestamp.tv_usec;
523 	}
524 	if (direction == BIG_2_SMALL) {
525 		MDC_UNIT_BIG2SMALL(big, small);
526 		small->c.un_size =
527 		    roundup(sizeof (mt_unit32_od_t), sizeof (long long));
528 		small->un_flags		= big->un_flags;
529 		small->un_m_key		= big->un_m_key;
530 		small->un_m_dev		= md_cmpldev(big->un_m_dev);
531 		small->un_l_key		= big->un_l_key;
532 		small->un_l_dev		= md_cmpldev(big->un_l_dev);
533 		small->un_l_sblk	= big->un_l_sblk;
534 		small->un_l_pwsblk	= big->un_l_pwsblk;
535 		small->un_l_nblks	= big->un_l_nblks;
536 		small->un_l_tblks	= big->un_l_tblks;
537 		small->un_l_head	= big->un_l_head;
538 		small->un_l_tail	= big->un_l_tail;
539 		small->un_l_resv	= big->un_l_resv;
540 		small->un_l_maxresv	= big->un_l_maxresv;
541 		small->un_l_maxtransfer	= big->un_l_maxtransfer;
542 		small->un_l_recid	= big->un_l_recid;
543 		small->un_l_error	= big->un_l_error;
544 		small->un_s_dev		= md_cmpldev(big->un_s_dev);
545 		small->un_debug		= big->un_debug;
546 		small->un_dev		= md_cmpldev(big->un_dev);
547 		small->un_logreset	= big->un_logreset;
548 		small->un_timestamp.tv_sec = big->un_timestamp.tv_sec;
549 		small->un_timestamp.tv_usec = big->un_timestamp.tv_usec;
550 		small->un_l_timestamp.tv_sec = big->un_l_timestamp.tv_sec;
551 		small->un_l_timestamp.tv_usec = big->un_l_timestamp.tv_usec;
552 	}
553 
554 }
555 
556 
557 /*
558  * trans_log_convert(smallp, bigp, dir)
559  *
560  * Parameters:
561  *	smallp is the address of a ml_unit32_od_t structure
562  *	bigp   is the address of a ml_unit_t structure
563  *	dir   is either BIG2SMALL or SMALL2BIG
564  * Return value is void
565  *
566  * what it does:
567  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
568  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
569  *
570  * Caveat emptor: bigp and smallp must be well allocated memory areas.
571  */
572 void
573 trans_log_convert(caddr_t smallp, caddr_t bigp, int direction)
574 {
575 	/*LINTED*/
576 	ml_unit32_od_t *small = (ml_unit32_od_t *)smallp;
577 	/*LINTED*/
578 	ml_unit_t *big = (ml_unit_t *)bigp;
579 
580 	if (direction == SMALL_2_BIG) {
581 		big->un_revision	= small->un_revision;
582 		big->un_recid		= small->un_recid;
583 		big->un_key		= small->un_key;
584 		big->un_dev		= md_expldev(small->un_dev);
585 		big->un_opencnt		= small->un_opencnt;
586 		big->un_transcnt	= small->un_transcnt;
587 		big->un_head_lof	= small->un_head_lof;
588 		big->un_head_ident	= small->un_head_ident;
589 		big->un_tail_lof	= small->un_tail_lof;
590 		big->un_tail_ident	= small->un_tail_ident;
591 		big->un_bol_lof		= small->un_bol_lof;
592 		big->un_eol_lof		= small->un_eol_lof;
593 		big->un_nblks		= small->un_nblks;
594 		big->un_tblks		= small->un_tblks;
595 		big->un_maxtransfer	= small->un_maxtransfer;
596 		big->un_status		= small->un_status;
597 		big->un_maxresv		= small->un_maxresv;
598 		big->un_pwsblk		= small->un_pwsblk;
599 		big->un_devbsize	= small->un_devbsize;
600 		big->un_resv		= small->un_resv;
601 		big->un_resv_wantin	= small->un_resv_wantin;
602 		big->un_error		= small->un_error;
603 		big->un_tid		= small->un_tid;
604 		big->un_head_tid	= small->un_head_tid;
605 		big->un_timestamp.tv_sec = small->un_timestamp.tv_sec;
606 		big->un_timestamp.tv_usec = small->un_timestamp.tv_usec;
607 	}
608 	if (direction == BIG_2_SMALL) {
609 		small->un_revision	= big->un_revision;
610 		small->un_recid		= big->un_recid;
611 		small->un_key		= big->un_key;
612 		small->un_dev		= md_cmpldev(big->un_dev);
613 		small->un_opencnt	= big->un_opencnt;
614 		small->un_transcnt	= big->un_transcnt;
615 		small->un_head_lof	= big->un_head_lof;
616 		small->un_head_ident	= big->un_head_ident;
617 		small->un_tail_lof	= big->un_tail_lof;
618 		small->un_tail_ident	= big->un_tail_ident;
619 		small->un_bol_lof	= big->un_bol_lof;
620 		small->un_eol_lof	= big->un_eol_lof;
621 		small->un_nblks		= big->un_nblks;
622 		small->un_tblks		= big->un_tblks;
623 		small->un_maxtransfer	= big->un_maxtransfer;
624 		small->un_status	= big->un_status;
625 		small->un_maxresv	= big->un_maxresv;
626 		small->un_pwsblk	= big->un_pwsblk;
627 		small->un_devbsize	= big->un_devbsize;
628 		small->un_resv		= big->un_resv;
629 		small->un_resv_wantin	= big->un_resv_wantin;
630 		small->un_error		= big->un_error;
631 		small->un_tid		= big->un_tid;
632 		small->un_head_tid	= big->un_head_tid;
633 		small->un_timestamp.tv_sec = big->un_timestamp.tv_sec;
634 		small->un_timestamp.tv_usec = big->un_timestamp.tv_usec;
635 	}
636 }
637 
638 /*
639  * hs_convert(small, big, dir)
640  *
641  * Parameters:
642  *	small is the address of a hot_spare32_od_t structure
643  *	big   is the address of a hot_spare_t structure
644  *	dir   is either BIG2SMALL or SMALL2BIG
645  * Return value is void
646  *
647  * what it does:
648  * 	if dir is BIG2SMALL, convert from big to small (updating old records)
649  * 	if dir is SMALL2BIG, convert from small to big (snarfing old records)
650  *
651  * Caveat emptor: big and small must be well allocated memory areas.
652  */
653 void
654 hs_convert(caddr_t small, caddr_t big, int direction)
655 
656 {
657 	/*LINTED*/
658 	hot_spare32_od_t *small_un = (hot_spare32_od_t *)small;
659 	/*LINTED*/
660 	hot_spare_t *big_un = (hot_spare_t *)big;
661 
662 	if (direction == BIG_2_SMALL) {
663 		MHS_BIG2SMALL(big_un, small_un);
664 	}
665 
666 	if (direction == SMALL_2_BIG) {
667 		MHS_SMALL2BIG(small_un, big_un);
668 	}
669 }
670