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 /*
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * modctl system call for loadable module support.
28 */
29
30 #include <sys/param.h>
31 #include <sys/user.h>
32 #include <sys/systm.h>
33 #include <sys/exec.h>
34 #include <sys/file.h>
35 #include <sys/stat.h>
36 #include <sys/conf.h>
37 #include <sys/time.h>
38 #include <sys/reboot.h>
39 #include <sys/fs/ufs_fsdir.h>
40 #include <sys/kmem.h>
41 #include <sys/sysconf.h>
42 #include <sys/cmn_err.h>
43 #include <sys/ddi.h>
47 #include <sys/ddi_impldefs.h>
48 #include <sys/ddi_implfuncs.h>
49 #include <sys/bootconf.h>
50 #include <sys/dc_ki.h>
51 #include <sys/cladm.h>
52 #include <sys/dtrace.h>
53 #include <sys/kdi.h>
54
55 #include <sys/devpolicy.h>
56 #include <sys/modctl.h>
57 #include <sys/kobj.h>
58 #include <sys/devops.h>
59 #include <sys/autoconf.h>
60 #include <sys/hwconf.h>
61 #include <sys/callb.h>
62 #include <sys/debug.h>
63 #include <sys/cpuvar.h>
64 #include <sys/sysmacros.h>
65 #include <sys/sysevent.h>
66 #include <sys/sysevent_impl.h>
67 #include <sys/instance.h>
68 #include <sys/modhash.h>
69 #include <sys/modhash_impl.h>
70 #include <sys/dacf_impl.h>
71 #include <sys/vfs.h>
72 #include <sys/pathname.h>
73 #include <sys/console.h>
74 #include <sys/policy.h>
75 #include <ipp/ipp_impl.h>
76 #include <sys/fs/dv_node.h>
77 #include <sys/strsubr.h>
78 #include <sys/fs/sdev_impl.h>
79
80 static int mod_circdep(struct modctl *);
81 static int modinfo(modid_t, struct modinfo *);
82
83 static void mod_uninstall_all(void);
84 static int mod_getinfo(struct modctl *, struct modinfo *);
85 static struct modctl *allocate_modp(const char *, const char *);
86
115 static void modload_thread(struct loadmt *);
116
117 kcondvar_t mod_cv;
118 kcondvar_t mod_uninstall_cv; /* Communication between swapper */
119 /* and the uninstall daemon. */
120 kmutex_t mod_lock; /* protects &modules insert linkage, */
121 /* mod_busy, mod_want, and mod_ref. */
122 /* blocking operations while holding */
123 /* mod_lock should be avoided */
124 kmutex_t mod_uninstall_lock; /* protects mod_uninstall_cv */
125 kthread_id_t mod_aul_thread;
126
127 int modunload_wait;
128 kmutex_t modunload_wait_mutex;
129 kcondvar_t modunload_wait_cv;
130 int modunload_active_count;
131 int modunload_disable_count;
132
133 int isminiroot; /* set if running as miniroot */
134 int modrootloaded; /* set after root driver and fs are loaded */
135 int moddebug = 0x0; /* debug flags for module writers */
136 int swaploaded; /* set after swap driver and fs are loaded */
137 int bop_io_quiesced = 0; /* set when BOP I/O can no longer be used */
138 int last_module_id;
139 clock_t mod_uninstall_interval = 0;
140 int mod_uninstall_pass_max = 6;
141 int mod_uninstall_ref_zero; /* # modules that went mod_ref == 0 */
142 int mod_uninstall_pass_exc; /* mod_uninstall_all left new stuff */
143
144 int ddi_modclose_unload = 1; /* 0 -> just decrement reference */
145
146 int devcnt_incr = 256; /* allow for additional drivers */
147 int devcnt_min = 512; /* and always at least this number */
148
149 struct devnames *devnamesp;
150 struct devnames orphanlist;
151
152 krwlock_t devinfo_tree_lock; /* obsolete, to be removed */
153
154 #define MAJBINDFILE "/etc/name_to_major"
155 #define SYSBINDFILE "/etc/name_to_sysnum"
950 ;
951
952 n = i;
953
954 if (n == 0) {
955 kmem_free(constraints, len);
956 return (NULL);
957 }
958
959 array = kmem_alloc((n + 1) * sizeof (char *), KM_SLEEP);
960
961 for (i = 0, p = constraints; i < n; i++, p += strlen(p) + 1) {
962 array[i] = i_ddi_strdup(p, KM_SLEEP);
963 }
964 array[n] = NULL;
965
966 kmem_free(constraints, len);
967
968 return (array);
969 }
970 /*ARGSUSED*/
971 static int
972 modctl_retire(char *path, char *uconstraints, size_t ulen)
973 {
974 char *pathbuf;
975 char *devpath;
976 size_t pathsz;
977 int retval;
978 char *constraints;
979 char **cons_array;
980
981 if (path == NULL)
982 return (EINVAL);
983
984 if ((uconstraints == NULL) ^ (ulen == 0))
985 return (EINVAL);
986
987 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
988 retval = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
989 if (retval != 0) {
1030 return (ENOTSUP);
1031 }
1032
1033 /*
1034 * Ok, the retire succeeded. Persist the retire.
1035 * If retiring a nexus, we need to only persist the
1036 * nexus retire. Any children of a retired nexus
1037 * are automatically covered by the retire store
1038 * code.
1039 */
1040 retval = e_ddi_retire_persist(devpath);
1041 if (retval != 0) {
1042 cmn_err(CE_WARN, "Failed to persist device retire: error %d: "
1043 "%s", retval, devpath);
1044 kmem_free(devpath, strlen(devpath) + 1);
1045 return (retval);
1046 }
1047 if (moddebug & MODDEBUG_RETIRE)
1048 cmn_err(CE_NOTE, "Persisted retire of device: %s", devpath);
1049
1050 kmem_free(devpath, strlen(devpath) + 1);
1051 return (0);
1052 }
1053
1054 static int
1055 modctl_is_retired(char *path, int *statep)
1056 {
1057 char *pathbuf;
1058 char *devpath;
1059 size_t pathsz;
1060 int error;
1061 int status;
1062
1063 if (path == NULL || statep == NULL)
1064 return (EINVAL);
1065
1066 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1067 error = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
1068 if (error != 0) {
1069 kmem_free(pathbuf, MAXPATHLEN);
1127 cmn_err(CE_NOTE, "Unpersisted retire of device: %s",
1128 devpath);
1129 }
1130
1131 /*
1132 * Check if the device is already unretired. If so,
1133 * the unretire becomes a NOP
1134 */
1135 if (!retired) {
1136 cmn_err(CE_NOTE, "Not retired: %s", devpath);
1137 kmem_free(devpath, strlen(devpath) + 1);
1138 return (0);
1139 }
1140
1141 retval = e_ddi_unretire_device(devpath);
1142 if (retval != 0) {
1143 cmn_err(CE_WARN, "cannot unretire device: error %d, path %s\n",
1144 retval, devpath);
1145 }
1146
1147 kmem_free(devpath, strlen(devpath) + 1);
1148
1149 return (retval);
1150 }
1151
1152 static int
1153 modctl_getname(char *uname, uint_t ulen, int *umajorp)
1154 {
1155 char *name;
1156 major_t major;
1157
1158 if (copyin(umajorp, &major, sizeof (major)) != 0)
1159 return (EFAULT);
1160 if ((name = mod_major_to_name(major)) == NULL)
1161 return (ENODEV);
1162 if ((strlen(name) + 1) > ulen)
1163 return (ENOSPC);
1164 return (copyoutstr(name, uname, ulen, NULL));
1165 }
1166
|
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 /*
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * modctl system call for loadable module support.
29 */
30
31 #include <sys/param.h>
32 #include <sys/user.h>
33 #include <sys/systm.h>
34 #include <sys/exec.h>
35 #include <sys/file.h>
36 #include <sys/stat.h>
37 #include <sys/conf.h>
38 #include <sys/time.h>
39 #include <sys/reboot.h>
40 #include <sys/fs/ufs_fsdir.h>
41 #include <sys/kmem.h>
42 #include <sys/sysconf.h>
43 #include <sys/cmn_err.h>
44 #include <sys/ddi.h>
48 #include <sys/ddi_impldefs.h>
49 #include <sys/ddi_implfuncs.h>
50 #include <sys/bootconf.h>
51 #include <sys/dc_ki.h>
52 #include <sys/cladm.h>
53 #include <sys/dtrace.h>
54 #include <sys/kdi.h>
55
56 #include <sys/devpolicy.h>
57 #include <sys/modctl.h>
58 #include <sys/kobj.h>
59 #include <sys/devops.h>
60 #include <sys/autoconf.h>
61 #include <sys/hwconf.h>
62 #include <sys/callb.h>
63 #include <sys/debug.h>
64 #include <sys/cpuvar.h>
65 #include <sys/sysmacros.h>
66 #include <sys/sysevent.h>
67 #include <sys/sysevent_impl.h>
68 #include <sys/sysevent/eventdefs.h>
69 #include <sys/sysevent/dev.h>
70 #include <sys/instance.h>
71 #include <sys/modhash.h>
72 #include <sys/modhash_impl.h>
73 #include <sys/dacf_impl.h>
74 #include <sys/vfs.h>
75 #include <sys/pathname.h>
76 #include <sys/console.h>
77 #include <sys/policy.h>
78 #include <ipp/ipp_impl.h>
79 #include <sys/fs/dv_node.h>
80 #include <sys/strsubr.h>
81 #include <sys/fs/sdev_impl.h>
82
83 static int mod_circdep(struct modctl *);
84 static int modinfo(modid_t, struct modinfo *);
85
86 static void mod_uninstall_all(void);
87 static int mod_getinfo(struct modctl *, struct modinfo *);
88 static struct modctl *allocate_modp(const char *, const char *);
89
118 static void modload_thread(struct loadmt *);
119
120 kcondvar_t mod_cv;
121 kcondvar_t mod_uninstall_cv; /* Communication between swapper */
122 /* and the uninstall daemon. */
123 kmutex_t mod_lock; /* protects &modules insert linkage, */
124 /* mod_busy, mod_want, and mod_ref. */
125 /* blocking operations while holding */
126 /* mod_lock should be avoided */
127 kmutex_t mod_uninstall_lock; /* protects mod_uninstall_cv */
128 kthread_id_t mod_aul_thread;
129
130 int modunload_wait;
131 kmutex_t modunload_wait_mutex;
132 kcondvar_t modunload_wait_cv;
133 int modunload_active_count;
134 int modunload_disable_count;
135
136 int isminiroot; /* set if running as miniroot */
137 int modrootloaded; /* set after root driver and fs are loaded */
138 volatile int moddebug = 0x0; /* debug flags for module writers */
139 int swaploaded; /* set after swap driver and fs are loaded */
140 int bop_io_quiesced = 0; /* set when BOP I/O can no longer be used */
141 int last_module_id;
142 clock_t mod_uninstall_interval = 0;
143 int mod_uninstall_pass_max = 6;
144 int mod_uninstall_ref_zero; /* # modules that went mod_ref == 0 */
145 int mod_uninstall_pass_exc; /* mod_uninstall_all left new stuff */
146
147 int ddi_modclose_unload = 1; /* 0 -> just decrement reference */
148
149 int devcnt_incr = 256; /* allow for additional drivers */
150 int devcnt_min = 512; /* and always at least this number */
151
152 struct devnames *devnamesp;
153 struct devnames orphanlist;
154
155 krwlock_t devinfo_tree_lock; /* obsolete, to be removed */
156
157 #define MAJBINDFILE "/etc/name_to_major"
158 #define SYSBINDFILE "/etc/name_to_sysnum"
953 ;
954
955 n = i;
956
957 if (n == 0) {
958 kmem_free(constraints, len);
959 return (NULL);
960 }
961
962 array = kmem_alloc((n + 1) * sizeof (char *), KM_SLEEP);
963
964 for (i = 0, p = constraints; i < n; i++, p += strlen(p) + 1) {
965 array[i] = i_ddi_strdup(p, KM_SLEEP);
966 }
967 array[n] = NULL;
968
969 kmem_free(constraints, len);
970
971 return (array);
972 }
973
974 static void
975 publish_retire_event(char *path, int retire)
976 {
977 sysevent_t *ev;
978 sysevent_id_t eid;
979 sysevent_value_t se_val;
980 sysevent_attr_list_t *ev_attr_list = NULL;
981
982 ev = sysevent_alloc(EC_DEV_STATUS,
983 retire ? ESC_DEV_RETIRE : ESC_DEV_UNRETIRE, EC_DEVFS, SE_SLEEP);
984 if (ev == NULL) {
985 goto fail;
986 }
987
988 se_val.value_type = SE_DATA_TYPE_STRING;
989 se_val.value.sv_string = path;
990
991 if (sysevent_add_attr(&ev_attr_list, DEV_PHYS_PATH,
992 &se_val, SE_SLEEP) != 0) {
993 goto fail;
994 }
995
996 if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
997 goto fail;
998 }
999
1000 if (log_sysevent(ev, SE_SLEEP, &eid) != 0) {
1001 goto fail;
1002 }
1003
1004 sysevent_free(ev);
1005 return;
1006
1007 fail:
1008
1009 cmn_err(CE_WARN, "failed to log device %s event for %s",
1010 retire ? "retire" : "unretire", path);
1011
1012 if (ev_attr_list != NULL) {
1013 sysevent_free_attr(ev_attr_list);
1014 }
1015
1016 sysevent_free(ev);
1017 }
1018
1019 /*ARGSUSED*/
1020 static int
1021 modctl_retire(char *path, char *uconstraints, size_t ulen)
1022 {
1023 char *pathbuf;
1024 char *devpath;
1025 size_t pathsz;
1026 int retval;
1027 char *constraints;
1028 char **cons_array;
1029
1030 if (path == NULL)
1031 return (EINVAL);
1032
1033 if ((uconstraints == NULL) ^ (ulen == 0))
1034 return (EINVAL);
1035
1036 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1037 retval = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
1038 if (retval != 0) {
1079 return (ENOTSUP);
1080 }
1081
1082 /*
1083 * Ok, the retire succeeded. Persist the retire.
1084 * If retiring a nexus, we need to only persist the
1085 * nexus retire. Any children of a retired nexus
1086 * are automatically covered by the retire store
1087 * code.
1088 */
1089 retval = e_ddi_retire_persist(devpath);
1090 if (retval != 0) {
1091 cmn_err(CE_WARN, "Failed to persist device retire: error %d: "
1092 "%s", retval, devpath);
1093 kmem_free(devpath, strlen(devpath) + 1);
1094 return (retval);
1095 }
1096 if (moddebug & MODDEBUG_RETIRE)
1097 cmn_err(CE_NOTE, "Persisted retire of device: %s", devpath);
1098
1099 /* Issue sysevent. */
1100 publish_retire_event(devpath, 1);
1101
1102 kmem_free(devpath, strlen(devpath) + 1);
1103 return (0);
1104 }
1105
1106 static int
1107 modctl_is_retired(char *path, int *statep)
1108 {
1109 char *pathbuf;
1110 char *devpath;
1111 size_t pathsz;
1112 int error;
1113 int status;
1114
1115 if (path == NULL || statep == NULL)
1116 return (EINVAL);
1117
1118 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1119 error = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
1120 if (error != 0) {
1121 kmem_free(pathbuf, MAXPATHLEN);
1179 cmn_err(CE_NOTE, "Unpersisted retire of device: %s",
1180 devpath);
1181 }
1182
1183 /*
1184 * Check if the device is already unretired. If so,
1185 * the unretire becomes a NOP
1186 */
1187 if (!retired) {
1188 cmn_err(CE_NOTE, "Not retired: %s", devpath);
1189 kmem_free(devpath, strlen(devpath) + 1);
1190 return (0);
1191 }
1192
1193 retval = e_ddi_unretire_device(devpath);
1194 if (retval != 0) {
1195 cmn_err(CE_WARN, "cannot unretire device: error %d, path %s\n",
1196 retval, devpath);
1197 }
1198
1199 /* Issue sysevent. */
1200 publish_retire_event(devpath, 0);
1201
1202 kmem_free(devpath, strlen(devpath) + 1);
1203
1204 return (retval);
1205 }
1206
1207 static int
1208 modctl_getname(char *uname, uint_t ulen, int *umajorp)
1209 {
1210 char *name;
1211 major_t major;
1212
1213 if (copyin(umajorp, &major, sizeof (major)) != 0)
1214 return (EFAULT);
1215 if ((name = mod_major_to_name(major)) == NULL)
1216 return (ENODEV);
1217 if ((strlen(name) + 1) > ulen)
1218 return (ENOSPC);
1219 return (copyoutstr(name, uname, ulen, NULL));
1220 }
1221
|