xref: /onnv-gate/usr/src/cmd/devfsadm/md_link.c (revision 6507:e9fe7cad0646)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51623Stw21770  * Common Development and Distribution License (the "License").
61623Stw21770  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*6507Sps216548  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
281623Stw21770 #include <meta.h>
290Sstevel@tonic-gate #include <regex.h>
300Sstevel@tonic-gate #include <devfsadm.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <strings.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <limits.h>
350Sstevel@tonic-gate #include <sys/mkdev.h>
362291Stn143363 #include <sdssc.h>
370Sstevel@tonic-gate 
381623Stw21770 #define	MD_LINK_RE_DEVICES	"^md/r?dsk/.+$"
391623Stw21770 #define	MD_LINK_RE_SHARED	"^md/shared/[0-9]+/r?dsk/.+$"
400Sstevel@tonic-gate #define	MD_LINK_RE_ADMIN	"^md/admin"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate  * The devfsadm link module require the next section to
440Sstevel@tonic-gate  * be defined in order to know what and when to call functions
450Sstevel@tonic-gate  * in the module on device creation and removal.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /* setup for device creation */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate static int md_create(di_minor_t minor, di_node_t node);
510Sstevel@tonic-gate 
520Sstevel@tonic-gate static devfsadm_create_t md_cbt[] = {
530Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "md",
540Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, md_create,
550Sstevel@tonic-gate 	},
560Sstevel@tonic-gate };
570Sstevel@tonic-gate 
580Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(md_cbt);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate  * remove devices - always allow disks to be dynamically removed. Only allow
620Sstevel@tonic-gate  *		    admin device to be removed at reboot.
630Sstevel@tonic-gate  */
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static devfsadm_remove_t md_remove_cbt[] = {
660Sstevel@tonic-gate 	{"pseudo", MD_LINK_RE_DEVICES, RM_ALWAYS | RM_PRE | RM_HOT,
670Sstevel@tonic-gate 	    ILEVEL_0, devfsadm_rm_all},
680Sstevel@tonic-gate 	{"pseudo", MD_LINK_RE_SHARED, RM_ALWAYS | RM_PRE | RM_HOT,
690Sstevel@tonic-gate 	    ILEVEL_0, devfsadm_rm_all},
700Sstevel@tonic-gate 	{"pseudo", MD_LINK_RE_ADMIN, RM_ALWAYS | RM_PRE,
710Sstevel@tonic-gate 	    ILEVEL_0, devfsadm_rm_all},
720Sstevel@tonic-gate };
730Sstevel@tonic-gate 
740Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(md_remove_cbt);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /*
78*6507Sps216548  * minor_fini - module cleanup routine
79*6507Sps216548  */
80*6507Sps216548 int
minor_fini(void)81*6507Sps216548 minor_fini(void)
82*6507Sps216548 {
83*6507Sps216548 	metarpccloseall();
84*6507Sps216548 	return (DEVFSADM_SUCCESS);
85*6507Sps216548 }
86*6507Sps216548 
87*6507Sps216548 /*
880Sstevel@tonic-gate  * For the admin device:
890Sstevel@tonic-gate  *	/dev/md/admin -> /devices/pseudo/md@0:admin
900Sstevel@tonic-gate  *
911623Stw21770  * For metadevice:
921623Stw21770  *	/dev/md/dsk/foobar --> /devices/pseudo/md@0:0,100,blk
931623Stw21770  *	/dev/md/rdsk/foobar --> /devices/pseudo/md@0:0,100,raw
941623Stw21770  *
951623Stw21770  * Where 'foobar' is user specified arbitrary name and '100'
961623Stw21770  * is the minor number returned by MD_IOCMAKE_DEV ioctl
971623Stw21770  *
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate static int
md_create(di_minor_t minor,di_node_t node)1000Sstevel@tonic-gate md_create(di_minor_t minor, di_node_t node)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	char mn[MAXNAMELEN + 1];
1030Sstevel@tonic-gate 	char path[PATH_MAX + 1];
1042099Stn143363 	char set_path[PATH_MAX +1];
1052099Stn143363 	char sym_path[PATH_MAX + 1];
1061623Stw21770 	int set = -1, ret;
1070Sstevel@tonic-gate 	char *type, *dir;
1081623Stw21770 	char *device_name;
1091623Stw21770 	dev_t minor_devt = di_minor_devt(minor);
1101623Stw21770 	int key;
1112099Stn143363 	mdsetname_t	*sp = NULL;
1121623Stw21770 	md_error_t ep;
1130Sstevel@tonic-gate 
1142291Stn143363 	/*
1152291Stn143363 	 * Initialize sdssc entry points. Don't worry about the return
1162291Stn143363 	 * value here since the interface functions will get initialized
1172291Stn143363 	 * correctly regardless.
1182291Stn143363 	 */
1192291Stn143363 	(void) sdssc_bind_library();
1202291Stn143363 
1210Sstevel@tonic-gate 	(void) strcpy(mn, di_minor_name(minor));
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	/*
1240Sstevel@tonic-gate 	 * Check whether we are being requested to setup the admin
1250Sstevel@tonic-gate 	 * device link or one of the metadevice links. They need
1260Sstevel@tonic-gate 	 * to be treated differently.
1270Sstevel@tonic-gate 	 */
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	if (strcmp(mn, "admin") == 0) {
1300Sstevel@tonic-gate 		/* there is only one admin link and always in /dev/md/admin */
1310Sstevel@tonic-gate 		(void) devfsadm_mklink("md/admin", node, minor, 0);
1320Sstevel@tonic-gate 	} else {
1330Sstevel@tonic-gate 		/*
1340Sstevel@tonic-gate 		 * Extract out the minor components and create the
1350Sstevel@tonic-gate 		 * appropriate links. The node looks like:
1360Sstevel@tonic-gate 		 * md@<set>,<mdev>,<type>
1370Sstevel@tonic-gate 		 * where the <set> number is the named diskset,
1380Sstevel@tonic-gate 		 * <mdev> is the metadevice number, and <type>
1390Sstevel@tonic-gate 		 * is the trailing "blk" or "raw" indication.
1400Sstevel@tonic-gate 		 *
1410Sstevel@tonic-gate 		 * NOTE: when <set> is non-zero, we need to create
1420Sstevel@tonic-gate 		 * under the "shared" directory entry instead of linking
1430Sstevel@tonic-gate 		 * into the top level dsk/rdsk directories.
1440Sstevel@tonic-gate 		 */
1451623Stw21770 		ret = sscanf(mn, "%d,", &set);
1461623Stw21770 		if (ret == 1 && (type = strrchr(mn, ',')) != NULL) {
1471623Stw21770 			type++;
1480Sstevel@tonic-gate 			if (strcmp(type, "blk") == 0) {
1490Sstevel@tonic-gate 				dir = "dsk";
1500Sstevel@tonic-gate 			} else {
1510Sstevel@tonic-gate 				dir = "rdsk";
1520Sstevel@tonic-gate 			}
1531623Stw21770 
1541623Stw21770 			(void) memset(&ep, '\0', sizeof (ep));
1551623Stw21770 			if ((device_name = meta_getnmentbydev(set,
1561623Stw21770 			    MD_SIDEWILD, minor_devt, NULL, NULL,
1571623Stw21770 			    &key, &ep)) == NULL) {
1581623Stw21770 				(void) close_admin(&ep);
1591623Stw21770 				return (DEVFSADM_CONTINUE);
1601623Stw21770 			}
1611623Stw21770 
1620Sstevel@tonic-gate 			if (set == 0) {
1630Sstevel@tonic-gate 				/* this is a simple md */
1640Sstevel@tonic-gate 				(void) snprintf(path, sizeof (path),
165*6507Sps216548 				    "md/%s/%s", dir, basename(device_name));
1660Sstevel@tonic-gate 			} else {
1670Sstevel@tonic-gate 				/* this is a shared md */
1680Sstevel@tonic-gate 				(void) snprintf(path, sizeof (path),
169*6507Sps216548 				    "md/shared/%d/%s/%s", set, dir,
170*6507Sps216548 				    basename(device_name));
1712099Stn143363 
1722099Stn143363 				/*
1732099Stn143363 				 * flush the caches so the next call to
1742099Stn143363 				 * metasetnosetname will get us the
1752099Stn143363 				 * updated cache.
1762099Stn143363 				 */
1772099Stn143363 				metaflushnames(0);
1782099Stn143363 				if ((sp = metasetnosetname(set, &ep))
1792099Stn143363 				    != NULL) {
1802099Stn143363 					(void) snprintf(set_path,
1812099Stn143363 					    sizeof (set_path), "md/shared/%d",
1822099Stn143363 					    sp->setno);
1832099Stn143363 					(void) snprintf(sym_path,
1842099Stn143363 					    sizeof (sym_path), "md/%s",
1852099Stn143363 					    sp->setname);
1862099Stn143363 				}
1870Sstevel@tonic-gate 			}
1880Sstevel@tonic-gate 			(void) devfsadm_mklink(path, node, minor, 0);
1891623Stw21770 			Free(device_name);
1902099Stn143363 
1912099Stn143363 			if (sp != NULL) {
1922099Stn143363 				(void) devfsadm_secondary_link(sym_path,
1932099Stn143363 				    set_path, 0);
1942099Stn143363 			}
1950Sstevel@tonic-gate 		}
1960Sstevel@tonic-gate 	}
1971623Stw21770 
1981623Stw21770 	(void) close_admin(&ep);
1990Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
2000Sstevel@tonic-gate }
201