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