xref: /titanic_41/usr/src/cmd/lvm/metassist/layout/layout_dlist_util.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 2004 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 #define	_LAYOUT_DLIST_UTIL_C
30 
31 #include <assert.h>
32 #include <string.h>
33 
34 #include <libintl.h>
35 #include <libdiskmgt.h>
36 
37 #include "volume_devconfig.h"
38 #include "volume_dlist.h"
39 #include "volume_output.h"
40 
41 #include "layout_device_cache.h"
42 #include "layout_dlist_util.h"
43 #include "layout_request.h"
44 
45 #include "layout_slice.h"  /* destroy_new_slice */
46 #include "layout_svm_util.h"
47 
48 /*
49  * FUNCTION:	compare_strings(void *str1, void *str2)
50  *
51  * INPUT:	str1	- opaque pointer to a char *
52  * 		str2	- opaque pointer to a char *
53  *
54  * RETURNS:	int	- <0 - if str1 < str2
55  *			   0 - if str1 == str2
56  *			  >0 - if str1 > str2
57  *
58  * PURPOSE:	dlist_t helper which compares the two input strings.
59  *
60  *		Comparison is done with string_case_compare()
61  */
62 int
compare_strings(void * str1,void * str2)63 compare_strings(
64 	void	*str1,
65 	void	*str2)
66 {
67 	assert(str1 != NULL);
68 	assert(str2 != NULL);
69 
70 	return (string_case_compare((char *)str1, (char *)str2));
71 }
72 
73 /*
74  * FUNCTION:	compare_devconfig_sizes(void *devconf1, void *devconf2)
75  *
76  * INPUT:	devconf1	- opaque pointer
77  * 		devconf2	- opaque pointer
78  *
79  * RETURNS:	int	- <0 - if devconf1.size_in_blks < devconf2.size_in_blks
80  *			   0 - if devconf1.size_in_blks == devconf2.size_in_blks
81  *			  >0 - if devconf1.size.in_blks > devconf2.size_in_blks
82  *
83  * PURPOSE:	dlist_t helper which compares the sizes of two devconfig_t
84  *		structs.
85  *
86  *		Both input objects are assumed to be devconfig_t pointers.
87  */
88 int
compare_devconfig_sizes(void * devconf1,void * devconf2)89 compare_devconfig_sizes(
90 	void		*devconf1,
91 	void		*devconf2)
92 {
93 	uint64_t	size1 = 0;
94 	uint64_t	size2 = 0;
95 
96 	assert(devconf1 != NULL);
97 	assert(devconf2 != NULL);
98 
99 	(void) devconfig_get_size_in_blocks((devconfig_t *)devconf1, &size1);
100 	(void) devconfig_get_size_in_blocks((devconfig_t *)devconf2, &size2);
101 
102 	return (size1 - size2);
103 }
104 
105 /*
106  * FUNCTION:	compare_slice_sizes(void *desc1, void *desc2)
107  *
108  * INPUT:	desc1	- opaque pointer to a dm_descriptor_t slice handle
109  * 		desc2	- opaque pointer to a dm_descriptor_t slice handle
110  *
111  * RETURNS:	int	- <0 - if desc1.slicesize < desc2.slicesize
112  *			   0 - if desc1.slicesize == desc2.slicesize
113  *			  >0 - if desc1.slicesize > desc2.slicesize
114  *
115  * PURPOSE:	dlist_t helper which compares the sizes of two slices
116  *		represented as dm_descriptor_t handles.
117  */
118 int
compare_slice_sizes(void * desc1,void * desc2)119 compare_slice_sizes(
120 	void		*desc1,
121 	void		*desc2)
122 {
123 	uint64_t	size1 = 0;
124 	uint64_t	size2 = 0;
125 
126 	assert(desc1 != NULL);
127 	assert(desc2 != NULL);
128 
129 	(void) slice_get_size((uintptr_t)desc1, &size1);
130 	(void) slice_get_size((uintptr_t)desc2, &size2);
131 
132 	return (size1 - size2);
133 }
134 
135 /*
136  * FUNCTION:	compare_devconfig_and_descriptor_names(void *devconf,
137  *			void *desc)
138  *
139  * INPUT:	devconf	- opaque pointer to a devconfig_t
140  * 		desc	- opaque pointer to a dm_descriptor_t
141  *
142  * RETURNS:	int	- <0 - if devconf name is "less than" descr name
143  *			   0 - if devconf name is "equal to" descr name
144  *			  >0 - if devconf name is "greater than" desc name
145  *
146  * PURPOSE:	dlist_t helper which compares the name of a devconfig_t
147  *		struct to the name for a dm_descriptor_t.
148  *
149  *		Note that the order of the arguments is important.
150  *		This function is intended to be passed into the various
151  *		dlist_* functions which take a comparison function.
152  */
153 int
compare_devconfig_and_descriptor_names(void * devconf,void * desc)154 compare_devconfig_and_descriptor_names(
155 	void	*devconf,
156 	void	*desc)
157 {
158 	char	*volname = NULL;
159 	char	*descname = NULL;
160 
161 	assert(devconf != NULL);
162 	assert(desc != NULL);
163 
164 	(void) devconfig_get_name((devconfig_t *)devconf, &volname);
165 	(void) get_display_name((uintptr_t)desc, &descname);
166 
167 	return (string_case_compare(volname, descname));
168 }
169 
170 /*
171  * FUNCTION:	compare_string_to_devconfig_name(void *str, void *devconf)
172  *
173  * INPUT:	str	- opaque pointer to a char *str
174  *		devconf	- opaque pointer to a devconfig_t
175  *
176  * RETURNS:	int	- <0 - if devconf name is "less than" str
177  *			   0 - if devconf name is "equal to" str
178  *			  >0 - if devconf name is "greater than" str
179  *
180  * PURPOSE:	dlist_t helper which compares a string to the name of
181  *		a devconfig_t struct.
182  */
183 int
compare_string_to_devconfig_name(void * str,void * devconf)184 compare_string_to_devconfig_name(
185 	void	*str,
186 	void	*devconf)
187 {
188 	char	*volname = NULL;
189 
190 	assert(str != NULL);
191 	assert(devconf != NULL);
192 
193 	(void) devconfig_get_name((devconfig_t *)devconf, &volname);
194 	if (volname == NULL) {
195 	    /* no memory for new string(s) */
196 	    return (-1);
197 	}
198 
199 	return (string_case_compare(volname, (char *)str));
200 }
201 
202 /*
203  * FUNCTION:	free_devconfig_object(void *obj)
204  *
205  * INPUT:	obj	- an opaque pointer
206  *
207  * RETURNS:	void
208  *
209  * PURPOSE:	helper which decomposes a devconfig_t struct after a
210  *		failed layout attempt.
211  *
212  *		reclaims allocated space.
213  *		releases reserved volume/HSP names
214  *		undoes slicing
215  */
216 void
free_devconfig_object(void * obj)217 free_devconfig_object(
218 	void		*obj)
219 {
220 	devconfig_t	*dev = NULL;
221 	char		*name = NULL;
222 	dlist_t		*iter = NULL;
223 	component_type_t	type = TYPE_UNKNOWN;
224 
225 	if (obj == NULL) {
226 	    return;
227 	}
228 
229 	dev = (devconfig_t *)obj;
230 
231 	(void) devconfig_get_type(dev, &type);
232 	(void) devconfig_get_name(dev, &name);
233 
234 	oprintf(OUTPUT_DEBUG,
235 		gettext("  -->decomposing %s\n"), name);
236 
237 	switch (type) {
238 	case TYPE_MIRROR:
239 	case TYPE_CONCAT:
240 	case TYPE_RAID5:
241 	case TYPE_HSP:
242 	case TYPE_STRIPE:
243 
244 	    /* release name */
245 	    if (devconfig_isA(dev, TYPE_HSP)) {
246 		release_hsp_name(name);
247 	    } else {
248 		release_volume_name(name);
249 	    }
250 
251 	    /* decompose volume's components */
252 	    iter = devconfig_get_components(dev);
253 	    dlist_free_items(iter, free_devconfig_object);
254 
255 	    (void) devconfig_set_components(dev, NULL);
256 
257 	    break;
258 
259 	case TYPE_SLICE:
260 
261 	    (void) destroy_new_slice(dev);
262 
263 	    break;
264 
265 	default:
266 	    break;
267 
268 	}
269 
270 	free_devconfig(dev);
271 }
272 
273 /*
274  * FUNCTION:	compare_device_names(
275  *			void *str1, void *str2)
276  *
277  * INPUT:	str1	- opaque pointer
278  * 		str2	- opaque pointer
279  *
280  * RETURNS:	int	- <0 - if str1 < str2
281  *			   0 - if str1 == str2
282  *			  >0 - if str1 > str2
283  *
284  * PURPOSE:	dlist_t helper which compares two device name strings.
285  *
286  *		Both names are assumed to be in CTD form.
287  *
288  *		Either name may be fully qualified by an absolute
289  *		path.  If only one name is fully qualified, the
290  *		leading path with be stripped off prior to the
291  *		comparison.
292  *
293  *		Uses string_case_compare() to compare the names.
294  */
295 int
compare_device_names(void * str1,void * str2)296 compare_device_names(
297 	void	*str1,
298 	void	*str2)
299 {
300 	char 	*name1 = (char *)str1;
301 	char	*name2 = (char *)str2;
302 
303 	int	val = 0;
304 
305 	assert(str1 != NULL);
306 	assert(str2 != NULL);
307 
308 	/* if one doesn't start with '/', just compare device names */
309 	if (*name1 != '/' || *name2 != '/') {
310 
311 	    char *short1 = strrchr(name1, '/');
312 	    char *short2 = strrchr(name2, '/');
313 
314 	    if (short1 == NULL) {
315 		short1 = name1;
316 	    } else {
317 		++short1;
318 	    }
319 
320 	    if (short2 == NULL) {
321 		short2 = name2;
322 	    } else {
323 		++short2;
324 	    }
325 
326 	    val = string_case_compare(short2, short1);
327 
328 	} else {
329 
330 	    /* if they both start with '/', assume they're full paths */
331 	    val = string_case_compare(name2, name1);
332 	}
333 
334 	return (val);
335 }
336 
337 /*
338  * FUNCTION:	compare_descriptors(
339  *			void *desc1, void *desc2)
340  *
341  * INPUT:	desc1	- opaque pointer
342  * 		desc2	- opaque pointer
343  *
344  * RETURNS:	int	- <0 - if desc1 < desc2
345  *			   0 - if desc1 == desc2
346  *			  >0 - if desc1 > desc2
347  *
348  * PURPOSE:	dlist_t helper which compares two dm_descriptor_t handles.
349  */
350 int
compare_descriptors(void * desc1,void * desc2)351 compare_descriptors(
352 	void	*desc1,
353 	void	*desc2)
354 {
355 	assert(desc1 != NULL);
356 	assert(desc2 != NULL);
357 
358 	return ((uintptr_t)desc1 - (uintptr_t)desc2);
359 }
360 
361 /*
362  * FUNCTION:	compare_descriptor_names(
363  *			void *desc1, void *desc2)
364  *
365  * INPUT:	desc1	- opaque pointer
366  * 		desc2	- opaque pointer
367  *
368  * RETURNS:	int	- <0 - if desc1.name < desc2.name
369  *			   0 - if desc1.name == desc2.name
370  *			  >0 - if desc1.name > desc2.name
371  *
372  * PURPOSE:	dlist_t helper which compares the names associated
373  *		with the input dm_descriptor_t handles.
374  *
375  *		Retrieves the names associated with both descriptors
376  *		and compares them using string_case_compare.
377  */
378 int
compare_descriptor_names(void * desc1,void * desc2)379 compare_descriptor_names(
380 	void	*desc1,
381 	void	*desc2)
382 {
383 	char	*name1 = NULL;
384 	char	*name2 = NULL;
385 
386 	assert(desc1 != NULL);
387 	assert(desc2 != NULL);
388 
389 	(void) get_name((uintptr_t)desc1, &name1);
390 	(void) get_name((uintptr_t)desc2, &name2);
391 
392 	return (string_case_compare(name1, name2));
393 }
394 
395 /*
396  * FUNCTION:	compare_slices_on_same_hba(
397  *			void *slice1, void *slice2)
398  *
399  * INPUT:	slice1	- opaque pointer
400  * 		slice2	- opaque pointer
401  *
402  * RETURNS:	int -  0 - if slice1 is on the same hba as slice2
403  *		      !0 - otherwise
404  *
405  * PURPOSE:	dlist_t helper which checks whether slice1 is on the
406  *		same hba as slice2
407  */
408 int
compare_slices_on_same_hba(void * slice1,void * slice2)409 compare_slices_on_same_hba(
410 	void	*slice1,
411 	void	*slice2)
412 {
413 	char *name1, *name2;
414 
415 	/* Retrieve the names of the slices */
416 	if (devconfig_get_name((devconfig_t *)slice1, &name1) == 0 &&
417 	    devconfig_get_name((devconfig_t *)slice2, &name2) == 0) {
418 
419 	    dm_descriptor_t desc1, desc2;
420 
421 	    /* Retrieve the disk descriptors for the slices */
422 	    if (get_disk_for_named_slice(name1, &desc1) == 0 &&
423 		get_disk_for_named_slice(name2, &desc2) == 0) {
424 
425 		dlist_t *hbas1 = NULL;
426 		dlist_t *hbas2 = NULL;
427 
428 		assert(desc1 != (dm_descriptor_t)0);
429 		assert(desc2 != (dm_descriptor_t)0);
430 
431 		/* Retrieve list of HBA descriptors for the slices */
432 		if (disk_get_hbas(desc1, &hbas1) == 0 &&
433 		    disk_get_hbas(desc2, &hbas2) == 0) {
434 
435 		    dlist_t *itr1;
436 
437 		    for (itr1 = hbas1; itr1 != NULL; itr1 = itr1->next) {
438 			dm_descriptor_t hba1 = (uintptr_t)itr1->obj;
439 			dlist_t *itr2;
440 
441 			for (itr2 = hbas2; itr2 != NULL; itr2 = itr2->next) {
442 			    dm_descriptor_t hba2 = (uintptr_t)itr2->obj;
443 
444 			    if (hba1 == hba2) {
445 				return (0);
446 			    }
447 			}
448 		    }
449 		}
450 	    }
451 	}
452 
453 	return (1);
454 }
455