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