xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_namespace.c (revision d58fda4376e4bf67072ce2e69f6f47036f9dbb68)
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  * namespace utilities
31  */
32 
33 #include <meta.h>
34 
35 typedef struct deviceinfo {
36 	char	*bname;		/* block name of the device */
37 	char	*dname;		/* driver for the device */
38 	minor_t	mnum;		/* minor number for the device */
39 } deviceinfo_t;
40 
41 static	deviceinfo_t	devlist[MD_MNMAXSIDES];
42 
43 /*
44  * Ask the driver for the device name, driver name, and minor number;
45  * which has been stored in the metadevice state database
46  * (on behalf of the utilities).
47  * (by key)
48  */
49 char *
50 meta_getnmentbykey(
51 	set_t		setno,
52 	side_t		sideno,
53 	mdkey_t		key,
54 	char		**drvnm,
55 	minor_t		*mnum,
56 	md_dev64_t	*dev,
57 	md_error_t	*ep
58 )
59 {
60 	struct mdnm_params	nm;
61 	static char		device_name[MAXPATHLEN];
62 
63 	(void) memset(&nm, '\0', sizeof (nm));
64 	nm.setno = setno;
65 	nm.side = sideno;
66 	nm.key = key;
67 	nm.devname = (uint64_t)device_name;
68 
69 	if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde, NULL) != 0) {
70 		(void) mdstealerror(ep, &nm.mde);
71 		return (NULL);
72 	}
73 
74 	if (drvnm != NULL)
75 		*drvnm = Strdup(nm.drvnm);
76 
77 	if (mnum != NULL)
78 		*mnum = nm.mnum;
79 
80 	if (dev != NULL)
81 		*dev = meta_expldev(makedevice(nm.major, nm.mnum));
82 
83 	return (Strdup(device_name));
84 }
85 
86 /*
87  * Ask the driver for the minor name which has been stored in the
88  * metadevice state database.
89  * (by key)
90  */
91 char *
92 meta_getdidminorbykey(
93 	set_t		setno,
94 	side_t		sideno,
95 	mdkey_t		key,
96 	md_error_t	*ep
97 )
98 {
99 	struct mdnm_params	nm;
100 	static char		minorname[MAXPATHLEN];
101 
102 	(void) memset(&nm, '\0', sizeof (nm));
103 	nm.setno = setno;
104 	nm.side = sideno;
105 	nm.key = key;
106 	nm.minorname = (uint64_t)minorname;
107 
108 	if (metaioctl(MD_IOCGET_DIDMIN, &nm, &nm.mde, NULL) != 0) {
109 		(void) mdstealerror(ep, &nm.mde);
110 		return (NULL);
111 	}
112 
113 	return (Strdup(minorname));
114 }
115 
116 /*
117  * Ask the driver for the device id string which has been stored in the
118  * metadevice state database (on behalf of the utilities).
119  * (by key)
120  */
121 ddi_devid_t
122 meta_getdidbykey(
123 	set_t		setno,
124 	side_t		sideno,
125 	mdkey_t		key,
126 	md_error_t	*ep
127 )
128 {
129 	struct mdnm_params	nm;
130 
131 	(void) memset(&nm, '\0', sizeof (nm));
132 	nm.setno = setno;
133 	nm.side = sideno;
134 	nm.key = key;
135 
136 	/*
137 	 * First ask the driver for the size of the device id string.  This is
138 	 * signaled by passing the driver a devid_size of zero.
139 	 */
140 	nm.devid_size = 0;
141 	if (metaioctl(MD_IOCGET_DID, &nm, &nm.mde, NULL) != 0) {
142 		(void) mdstealerror(ep, &nm.mde);
143 		return (NULL);
144 	}
145 
146 	/*
147 	 * If the devid_size is still zero then something is wrong.
148 	 */
149 	if (nm.devid_size == 0) {
150 		(void) mdstealerror(ep, &nm.mde);
151 		return (NULL);
152 	}
153 
154 	/*
155 	 * Now go get the actual device id string.  Caller is responsible for
156 	 * free'ing device id memory buffer.
157 	 */
158 	if ((nm.devid = (uintptr_t)malloc(nm.devid_size)) == NULL) {
159 		return (NULL);
160 	}
161 	if (metaioctl(MD_IOCGET_DID, &nm, &nm.mde, NULL) != 0) {
162 		(void) mdstealerror(ep, &nm.mde);
163 		(void) free((void *)(uintptr_t)nm.devid);
164 		return (NULL);
165 	}
166 
167 	return ((void *)(uintptr_t)nm.devid);
168 }
169 
170 /*
171  * set the devid.
172  */
173 int
174 meta_setdid(
175 	set_t		setno,
176 	side_t		sideno,
177 	mdkey_t		key,
178 	md_error_t	*ep
179 )
180 {
181 	struct mdnm_params	nm;
182 	int			i;
183 
184 	(void) memset(&nm, '\0', sizeof (nm));
185 	nm.setno = setno;
186 	nm.side = sideno;
187 	nm.key = key;
188 
189 	if (metaioctl(MD_IOCSET_DID, &nm, &nm.mde, NULL) != 0) {
190 		(void) mdstealerror(ep, &nm.mde);
191 		return (-1);
192 	}
193 
194 	if (setno == MD_LOCAL_SET) {
195 		/*
196 		 * If this is the local set then we are adding in the devids
197 		 * for the disks in the diskset and so this means adding
198 		 * a reference count for each side. Need to do this after
199 		 * the initial add so that the correct devid is picked up.
200 		 * The key is the key of the drive record and as such this
201 		 * means the minor number of the device which is used to
202 		 * get the devid. If the wrong side is used then it would
203 		 * be possible to get the wrong devid in the namespace, hence
204 		 * the requirement to process the local side first of all.
205 		 */
206 		for (i = 0 + SKEW; i < MD_MAXSIDES; i++) {
207 			/*
208 			 * We can just call the ioctl again because it will
209 			 * fail with ENOENT if the side does not exist, and
210 			 * more importantly does not increment the usage count
211 			 * on the devid.
212 			 */
213 			nm.side = (side_t)i;
214 			if (nm.side == sideno)
215 				continue;
216 			if (metaioctl(MD_IOCSET_DID, &nm, &nm.mde, NULL) != 0) {
217 				if (mdissyserror(&nm.mde, ENODEV)) {
218 					mdclrerror(&nm.mde);
219 				} else {
220 					(void) mdstealerror(ep, &nm.mde);
221 					return (-1);
222 				}
223 			}
224 		}
225 	}
226 	return (0);
227 }
228 /*
229  * Ask the driver for the name, which has been stored in the
230  * metadevice state database (on behalf of the utilities).
231  * (by key)
232  */
233 char *
234 meta_getnmbykey(
235 	set_t		setno,
236 	side_t		sideno,
237 	mdkey_t		key,
238 	md_error_t	*ep
239 )
240 {
241 	return (meta_getnmentbykey(setno, sideno, key, NULL, NULL, NULL, ep));
242 }
243 
244 /*
245  * Ask the driver for the device name, driver name, minor number, and key;
246  * which has been stored in the metadevice state database
247  * (on behalf of the utilities).
248  * (by md_dev64_t)
249  */
250 char *
251 meta_getnmentbydev(
252 	set_t		setno,
253 	side_t		sideno,
254 	md_dev64_t	dev,
255 	char		**drvnm,
256 	minor_t		*mnum,
257 	mdkey_t		*key,
258 	md_error_t	*ep
259 )
260 {
261 	struct mdnm_params	nm;
262 	static char		device_name[MAXPATHLEN];
263 
264 	/* must have a dev */
265 	assert(dev != NODEV64);
266 
267 	(void) memset(&nm, '\0', sizeof (nm));
268 	nm.setno = setno;
269 	nm.side = sideno;
270 	nm.key = MD_KEYWILD;
271 	nm.major = meta_getmajor(dev);
272 	nm.mnum = meta_getminor(dev);
273 	nm.devname = (uint64_t)device_name;
274 
275 	if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde, NULL) != 0) {
276 		(void) mdstealerror(ep, &nm.mde);
277 		return (NULL);
278 	}
279 
280 	if (drvnm != NULL)
281 		*drvnm = Strdup(nm.drvnm);
282 	if (mnum != NULL)
283 		*mnum = nm.mnum;
284 
285 	if (key != NULL)
286 		*key = nm.retkey;
287 
288 	return (Strdup(device_name));
289 }
290 
291 int
292 add_name(
293 	mdsetname_t	*sp,
294 	side_t		sideno,
295 	mdkey_t		key,
296 	char		*dname,
297 	minor_t		mnum,
298 	char		*bname,
299 	md_error_t	*ep
300 )
301 {
302 	struct mdnm_params	nm;
303 
304 	(void) memset(&nm, '\0', sizeof (nm));
305 	nm.setno = sp->setno;
306 	nm.side = sideno;
307 	nm.key = key;
308 	nm.mnum = mnum;
309 	(void) strncpy(nm.drvnm, dname, sizeof (nm.drvnm));
310 	nm.devname_len = strlen(bname) + 1;
311 	nm.devname = (uintptr_t)bname;
312 
313 	if (metaioctl(MD_IOCSET_NM, &nm, &nm.mde, bname) < 0)
314 		return (mdstealerror(ep, &nm.mde));
315 
316 	return (nm.key);
317 }
318 
319 /*
320  * Remove the device name which corresponds to the given device number.
321  */
322 int
323 del_name(
324 	mdsetname_t	*sp,
325 	side_t		sideno,
326 	mdkey_t		key,
327 	md_error_t	*ep
328 )
329 {
330 	struct mdnm_params	nm;
331 
332 	(void) memset(&nm, '\0', sizeof (nm));
333 	nm.setno = sp->setno;
334 	nm.side = sideno;
335 	nm.key = key;
336 
337 	if (metaioctl(MD_IOCREM_NM, &nm, &nm.mde, NULL) != 0)
338 		return (mdstealerror(ep, &nm.mde));
339 
340 	return (0);
341 }
342 
343 static void
344 empty_devicelist()
345 {
346 	side_t	sideno;
347 
348 	for (sideno = 0; sideno < MD_MNMAXSIDES; sideno++) {
349 		if (devlist[sideno].bname != (char *)NULL) {
350 			Free(devlist[sideno].bname);
351 			Free(devlist[sideno].dname);
352 			devlist[sideno].mnum = NODEV;
353 		}
354 	}
355 }
356 
357 static void
358 add_to_devicelist(
359 	side_t		sideno,
360 	char		*bname,
361 	char		*dname,
362 	minor_t		mnum
363 )
364 {
365 	devlist[sideno].bname = Strdup(bname);
366 	devlist[sideno].dname = Strdup(dname);
367 
368 	devlist[sideno].mnum = mnum;
369 }
370 
371 /*
372  * Build a list of the names on the systems, if this fails the caller
373  * will tidy up the entries in the devlist.
374  */
375 static int
376 build_sidenamelist(
377 	mdsetname_t	*sp,
378 	mdname_t	*np,
379 	md_error_t	*ep
380 )
381 {
382 	side_t		sideno = MD_SIDEWILD;
383 	minor_t		mnum = NODEV;
384 	char		*bname = NULL;
385 	char		*dname = NULL;
386 	int		err;
387 
388 	/*CONSTCOND*/
389 	while (1) {
390 
391 		if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno,
392 		    &bname, &dname, &mnum, ep)) == -1)
393 			return (-1);
394 
395 		if (err == 0)
396 			break;
397 
398 		/* the sideno gives us the index into the array */
399 		add_to_devicelist(sideno, bname, dname, mnum);
400 	}
401 	return (0);
402 }
403 
404 /*
405  * add name key
406  * the meta_create* functions should be the only ones using this. The
407  * adding of a name to the namespace must be done in a particular order
408  * to devid support for the disksets. The order is: add the 'local' side
409  * first of all, so the devid lookup in the kernel will use the correct
410  * device information and then add in the other sides.
411  */
412 int
413 add_key_name(
414 	mdsetname_t	*sp,
415 	mdname_t	*np,
416 	mdnamelist_t	**nlpp,
417 	md_error_t	*ep
418 )
419 {
420 	int		err;
421 	side_t		sideno = MD_SIDEWILD;
422 	side_t		thisside;
423 	mdkey_t		key = MD_KEYWILD;
424 	md_set_desc	*sd;
425 	int		maxsides;
426 
427 	/* should have a set */
428 	assert(sp != NULL);
429 
430 	if (! metaislocalset(sp)) {
431 		if ((sd = metaget_setdesc(sp, ep)) == NULL) {
432 			return (-1);
433 		}
434 	}
435 
436 	if (build_sidenamelist(sp, np, ep) == -1) {
437 		empty_devicelist();
438 		return (-1);
439 	}
440 
441 	/*
442 	 * When a disk is added into the namespace the local information for
443 	 * that disk is added in first of all. For the local set this is not
444 	 * a concern and for the host that owns the diskset it is not a concern
445 	 * but when a disk is added in the remote namespace we *must* use the
446 	 * local information for that disk first of all. This is because when
447 	 * in the kernel (md_setdevname) the passed in dev_t is used to find
448 	 * the devid of the disk. This means we have to cater for the following:
449 	 *
450 	 * - a disk on the remote host having the dev_t that has been passed
451 	 *   into the kernel and this disk is not actually the disk that is
452 	 *   being added into the diskset.
453 	 * - the dev_t does not exist on this node
454 	 *
455 	 * So putting in the local information first of all makes sure that the
456 	 * dev_t passed into the kernel is correct with respect to that node
457 	 * and then any further additions for that name match on the key
458 	 * passed back.
459 	 */
460 	thisside = getmyside(sp, ep);
461 
462 	if (devlist[thisside].dname == NULL ||
463 	    strlen(devlist[thisside].dname) == 0) {
464 		/*
465 		 * Did not find the disk information for the disk. This can
466 		 * be because of an inconsistancy in the namespace: that is the
467 		 * devid we have in the namespace does not exist on the
468 		 * system and thus when looking up the disk information
469 		 * using this devid we fail to find anything.
470 		 */
471 		(void) mdcomperror(ep, MDE_SP_COMP_OPEN_ERR, 0, np->dev,
472 		    np->cname);
473 		empty_devicelist();
474 		return (-1);
475 	}
476 
477 	if ((err = add_name(sp, thisside, key, devlist[thisside].dname,
478 	    devlist[thisside].mnum, devlist[thisside].bname, ep)) == -1) {
479 		empty_devicelist();
480 		return (-1);
481 	}
482 
483 	/* We now have a 'key' so add in the other sides */
484 	key = (mdkey_t)err;
485 
486 	if (metaislocalset(sp))
487 		goto done;
488 
489 	if (MD_MNSET_DESC(sd))
490 		maxsides = MD_MNMAXSIDES;
491 	else
492 		maxsides = MD_MAXSIDES;
493 
494 	for (sideno = 0; sideno < maxsides; sideno++) {
495 		/* ignore thisside, as it has been added above */
496 		if (sideno == thisside)
497 			continue;
498 
499 		if (devlist[sideno].dname != NULL) {
500 			err = add_name(sp, sideno, key, devlist[sideno].dname,
501 			    devlist[sideno].mnum, devlist[sideno].bname, ep);
502 			if (err == -1) {
503 				empty_devicelist();
504 				return (-1);
505 			}
506 		}
507 	}
508 
509 done:
510 	empty_devicelist();
511 	/* save key, return success */
512 	np->key = key;
513 	if (nlpp != NULL)
514 		(void) metanamelist_append(nlpp, np);
515 	return (0);
516 }
517 
518 /*
519  * delete name key
520  * the meta_create* functions should be the only ones using this. The
521  * removal of the names must be done in a particular order: remove the
522  * non-local entries first of all and then finally the local entry.
523  */
524 int
525 del_key_name(
526 	mdsetname_t	*sp,
527 	mdname_t	*np,
528 	md_error_t	*ep
529 )
530 {
531 	side_t		sideno = MD_SIDEWILD;
532 	int		err;
533 	int		retval = 0;
534 	side_t		thisside;
535 
536 	/* should have a set */
537 	assert(sp != NULL);
538 
539 	/* should have a key */
540 	assert((np->key != MD_KEYWILD) && (np->key != MD_KEYBAD));
541 
542 	thisside = getmyside(sp, ep);
543 
544 	/* remove the remote sides first of all */
545 	for (;;) {
546 		if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno,
547 		    NULL, NULL, NULL, ep)) == -1)
548 			return (-1);
549 
550 		if (err == 0)
551 			break;
552 
553 		/* ignore thisside */
554 		if (thisside == sideno) {
555 			continue;
556 		}
557 		if ((err = del_name(sp, sideno, np->key, ep)) == -1)
558 			retval = -1;
559 	}
560 
561 	/* now remove this side */
562 	if (retval == 0)
563 		if ((err = del_name(sp, thisside, np->key, ep)) == -1)
564 			retval = -1;
565 
566 	np->key = MD_KEYBAD;
567 	return (retval);
568 }
569 
570 /*
571  * delete namelist keys
572  * the meta_create* functions should be the only ones using this
573  */
574 int
575 del_key_names(
576 	mdsetname_t	*sp,
577 	mdnamelist_t	*nlp,
578 	md_error_t	*ep
579 )
580 {
581 	mdnamelist_t	*p;
582 	md_error_t	status = mdnullerror;
583 	int		rval = 0;
584 
585 	/* if ignoring errors */
586 	if (ep == NULL)
587 		ep = &status;
588 
589 	/* delete names */
590 	for (p = nlp; (p != NULL); p = p->next) {
591 		mdname_t	*np = p->namep;
592 
593 		if (del_key_name(sp, np, ep) != 0)
594 			rval = -1;
595 	}
596 
597 	/* cleanup, return success */
598 	if (ep == &status)
599 		mdclrerror(&status);
600 	return (rval);
601 }
602