Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/bootfs/bootfs_construct.c
+++ new/usr/src/uts/common/fs/bootfs/bootfs_construct.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright (c) 2015 Joyent, Inc. All rights reserved.
14 14 */
15 15
16 16 /*
17 17 * This file takes care of reading the boot time modules and constructing them
18 18 * into the appropriate series of vnodes.
19 19 */
20 20
21 21 #include <sys/conf.h>
22 22 #include <sys/ddi.h>
23 23 #include <sys/sunddi.h>
24 24 #include <sys/vfs.h>
25 25 #include <sys/sysmacros.h>
26 26 #include <sys/stat.h>
27 27
28 28 #include <sys/fs/bootfs_impl.h>
29 29
30 30 kmem_cache_t *bootfs_node_cache;
31 31
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
32 32 static const vattr_t bootfs_vattr_dir = {
33 33 AT_ALL, /* va_mask */
34 34 VDIR, /* va_type */
35 35 S_IFDIR | 0555, /* va_mode */
36 36 0, /* va_uid */
37 37 0, /* va_gid */
38 38 0, /* va_fsid */
39 39 0, /* va_nodeid */
40 40 1, /* va_nlink */
41 41 0, /* va_size */
42 - 0, /* va_atime */
43 - 0, /* va_mtime */
44 - 0, /* va_ctime */
42 + {0}, /* va_atime */
43 + {0}, /* va_mtime */
44 + {0}, /* va_ctime */
45 45 0, /* va_rdev */
46 46 0, /* va_blksize */
47 47 0, /* va_nblocks */
48 48 0 /* va_seq */
49 49 };
50 50
51 51 static const vattr_t bootfs_vattr_reg = {
52 52 AT_ALL, /* va_mask */
53 53 VREG, /* va_type */
54 54 S_IFREG | 0555, /* va_mode */
55 55 0, /* va_uid */
56 56 0, /* va_gid */
57 57 0, /* va_fsid */
58 58 0, /* va_nodeid */
59 59 1, /* va_nlink */
60 60 0, /* va_size */
61 - 0, /* va_atime */
62 - 0, /* va_mtime */
63 - 0, /* va_ctime */
61 + {0}, /* va_atime */
62 + {0}, /* va_mtime */
63 + {0}, /* va_ctime */
64 64 0, /* va_rdev */
65 65 0, /* va_blksize */
66 66 0, /* va_nblocks */
67 67 0 /* va_seq */
68 68 };
69 69
70 70 /*ARGSUSED*/
71 71 int
72 72 bootfs_node_constructor(void *buf, void *arg, int kmflags)
73 73 {
74 74 bootfs_node_t *bnp = buf;
75 75
76 76 bnp->bvn_vnp = vn_alloc(kmflags);
77 77 if (bnp->bvn_vnp == NULL)
78 78 return (-1);
79 79
80 80 return (0);
81 81 }
82 82
83 83 /*ARGSUSED*/
84 84 void
85 85 bootfs_node_destructor(void *buf, void *arg)
86 86 {
87 87 bootfs_node_t *bnp = buf;
88 88
89 89 vn_free(bnp->bvn_vnp);
90 90 }
91 91
92 92 static int
93 93 bootfs_comparator(const void *a, const void *b)
94 94 {
95 95 const bootfs_node_t *lfs, *rfs;
96 96 int ret;
97 97
98 98 lfs = a;
99 99 rfs = b;
100 100
101 101 ret = strcmp(lfs->bvn_name, rfs->bvn_name);
102 102 if (ret > 0)
103 103 ret = 1;
104 104 if (ret < 0)
105 105 ret = -1;
106 106 return (ret);
107 107 }
108 108
109 109 static void
110 110 bootfs_node_init(bootfs_t *bfs, bootfs_node_t *bnp, const struct vattr *vap,
111 111 const char *name, size_t namelen)
112 112 {
113 113 timestruc_t now;
114 114
115 115 vn_reinit(bnp->bvn_vnp);
116 116
117 117 bnp->bvn_vnp->v_flag |= VNOSWAP;
118 118 bnp->bvn_vnp->v_type = vap->va_type;
119 119 bnp->bvn_vnp->v_vfsp = bfs->bfs_vfsp;
120 120 bnp->bvn_vnp->v_rdev = 0;
121 121 bnp->bvn_vnp->v_data = (caddr_t)bnp;
122 122 vn_setops(bnp->bvn_vnp, bootfs_vnodeops);
123 123
124 124 bnp->bvn_name = kmem_alloc(namelen + 1, KM_SLEEP);
125 125 bcopy(name, bnp->bvn_name, namelen);
126 126 bnp->bvn_name[namelen] = '\0';
127 127 if (vap->va_type == VDIR) {
128 128 avl_create(&bnp->bvn_dir, bootfs_comparator,
129 129 sizeof (bootfs_node_t),
130 130 offsetof(bootfs_node_t, bvn_link));
131 131 }
132 132 bzero(&bnp->bvn_link, sizeof (avl_node_t));
133 133 bcopy(vap, &bnp->bvn_attr, sizeof (vattr_t));
134 134
135 135 gethrestime(&now);
136 136 bnp->bvn_attr.va_atime = now;
137 137 bnp->bvn_attr.va_ctime = now;
138 138 bnp->bvn_attr.va_mtime = now;
139 139 bnp->bvn_attr.va_fsid = makedevice(bootfs_major, bfs->bfs_minor);
140 140 bnp->bvn_attr.va_nodeid = bfs->bfs_ninode;
141 141 bnp->bvn_attr.va_blksize = PAGESIZE;
142 142 bfs->bfs_ninode++;
143 143 list_insert_tail(&bfs->bfs_nodes, bnp);
144 144 }
145 145
146 146 static void
147 147 bootfs_mkroot(bootfs_t *bfs)
148 148 {
149 149 bootfs_node_t *bnp;
150 150
151 151 bnp = kmem_cache_alloc(bootfs_node_cache, KM_SLEEP);
152 152 bootfs_node_init(bfs, bnp, &bootfs_vattr_dir, "/", 1);
153 153 bnp->bvn_vnp->v_flag |= VROOT;
154 154 bnp->bvn_parent = bnp;
155 155 bfs->bfs_rootvn = bnp;
156 156 bfs->bfs_stat.bfss_ndirs.value.ui32++;
157 157 vn_exists(bnp->bvn_vnp);
158 158 }
159 159
160 160 static int
161 161 bootfs_mknode(bootfs_t *bfs, bootfs_node_t *parent, bootfs_node_t **outp,
162 162 const char *name, size_t namelen, const vattr_t *vap, uintptr_t addr,
163 163 uint64_t size)
164 164 {
165 165 bootfs_node_t *bnp;
166 166 bootfs_node_t sn;
167 167 avl_index_t where;
168 168 char *buf;
169 169
170 170 ASSERT(parent->bvn_attr.va_type == VDIR);
171 171 buf = kmem_alloc(namelen + 1, KM_SLEEP);
172 172 bcopy(name, buf, namelen);
173 173 buf[namelen] = '\0';
174 174 sn.bvn_name = buf;
175 175 if ((bnp = avl_find(&parent->bvn_dir, &sn, &where)) != NULL) {
176 176 kmem_free(buf, namelen + 1);
177 177 /* Directories can collide, files cannot */
178 178 if (vap->va_type == VDIR) {
179 179 *outp = bnp;
180 180 return (0);
181 181 }
182 182 return (EEXIST);
183 183 }
184 184 kmem_free(buf, namelen + 1);
185 185
186 186 bnp = kmem_cache_alloc(bootfs_node_cache, KM_SLEEP);
187 187 bootfs_node_init(bfs, bnp, vap, name, namelen);
188 188 bnp->bvn_parent = parent;
189 189 avl_add(&parent->bvn_dir, bnp);
190 190 *outp = bnp;
191 191
192 192 if (vap->va_type == VDIR) {
193 193 parent->bvn_attr.va_size++;
194 194 parent->bvn_attr.va_nlink++;
195 195 bfs->bfs_stat.bfss_ndirs.value.ui32++;
196 196 } else {
197 197 bnp->bvn_addr = addr;
198 198 bnp->bvn_size = size;
199 199 bfs->bfs_stat.bfss_nfiles.value.ui32++;
200 200 bfs->bfs_stat.bfss_nbytes.value.ui64 += size;
201 201 bnp->bvn_attr.va_nblocks = P2ROUNDUP(size, 512) >> 9;
202 202 bnp->bvn_attr.va_size = size;
203 203 }
204 204
205 205 vn_exists(bnp->bvn_vnp);
206 206
207 207 return (0);
208 208 }
209 209
210 210 /*
211 211 * Given the address, size, and path a boot-time module would like, go through
212 212 * and create all of the directory entries that are required and then the file
213 213 * itself. If someone has passed in a module that has the same name as another
214 214 * one, we honor the first one.
215 215 */
216 216 static int
217 217 bootfs_construct_entry(bootfs_t *bfs, uintptr_t addr, uint64_t size,
218 218 const char *mname)
219 219 {
220 220 char *sp;
221 221 size_t nlen;
222 222 int ret;
223 223 bootfs_node_t *nbnp;
224 224
225 225 const char *p = mname;
226 226 bootfs_node_t *bnp = bfs->bfs_rootvn;
227 227
228 228 if (*p == '\0')
229 229 return (EINVAL);
230 230
231 231 for (;;) {
232 232 /* First eliminate all leading / characters. */
233 233 while (*p == '/')
234 234 p++;
235 235
236 236 /* A name with all slashes or ending in a / */
237 237 if (*p == '\0')
238 238 return (EINVAL);
239 239
240 240 sp = strchr(p, '/');
241 241 if (sp == NULL)
242 242 break;
243 243 nlen = (ptrdiff_t)sp - (ptrdiff_t)p;
244 244 if (strncmp(p, ".", nlen) == 0) {
245 245 p = sp + 1;
246 246 continue;
247 247 }
248 248
249 249 if (strncmp(p, "..", nlen) == 0) {
250 250 bnp = bnp->bvn_parent;
251 251 p = sp + 1;
252 252 continue;
253 253 }
254 254
255 255 VERIFY(bootfs_mknode(bfs, bnp, &nbnp, p, nlen,
256 256 &bootfs_vattr_dir, addr, size) == 0);
257 257 p = sp + 1;
258 258 bnp = nbnp;
259 259 }
260 260
261 261 nlen = strlen(p);
262 262 ret = bootfs_mknode(bfs, bnp, &nbnp, p, nlen, &bootfs_vattr_reg,
263 263 addr, size);
264 264 if (ret != 0)
265 265 return (ret);
266 266
267 267 return (0);
268 268 }
269 269
270 270 /*
271 271 * We're going to go through every boot time module and construct the
272 272 * appropriate vnodes for them now. Because there are very few of these that
273 273 * exist, generally on the order of a handful, we're going to create them all
274 274 * when the file system is initialized and then tear them all down when the
275 275 * module gets unloaded.
276 276 *
277 277 * The information about the modules is contained in properties on the root of
278 278 * the devinfo tree. Specifically there are three properties per module:
279 279 *
280 280 * - module-size-%d int64_t size, in bytes, of the boot time module.
281 281 * - module-addr-%d The address of the boot time module
282 282 * - module-name-%d The string name of the boot time module
283 283 *
284 284 * Note that the module-size and module-addr fields are always 64-bit values
285 285 * regardless of being on a 32-bit or 64-bit kernel. module-name is a string
286 286 * property.
287 287 *
288 288 * There is no property that indicates the total number of such modules. Modules
289 289 * start at 0 and work their way up incrementally. The first time we can't find
290 290 * a module or a property, then we stop.
291 291 */
292 292 void
293 293 bootfs_construct(bootfs_t *bfs)
294 294 {
295 295 uint_t id = 0, ndata;
296 296 char paddr[64], psize[64], pname[64], *mname;
297 297 dev_info_t *root;
298 298 uchar_t *datap;
299 299 uint64_t size = 0, addr = 0;
300 300 int ret;
301 301
302 302 bootfs_mkroot(bfs);
303 303 root = ddi_root_node();
304 304
305 305 for (;;) {
306 306 if (id == UINT32_MAX)
307 307 break;
308 308
309 309 if (snprintf(paddr, sizeof (paddr), "module-addr-%d", id) >
310 310 sizeof (paddr))
311 311 break;
312 312
313 313 if (snprintf(psize, sizeof (paddr), "module-size-%d", id) >
314 314 sizeof (paddr))
315 315 break;
316 316
317 317 if (snprintf(pname, sizeof (paddr), "module-name-%d", id) >
318 318 sizeof (paddr))
319 319 break;
320 320
321 321 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, root,
322 322 DDI_PROP_DONTPASS, paddr, &datap, &ndata) !=
323 323 DDI_PROP_SUCCESS)
324 324 break;
325 325
326 326 if (ndata == 8)
327 327 bcopy(datap, &addr, sizeof (uint64_t));
328 328 ddi_prop_free(datap);
329 329 if (ndata != 8)
330 330 break;
331 331
332 332 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, root,
333 333 DDI_PROP_DONTPASS, psize, &datap, &ndata) !=
334 334 DDI_PROP_SUCCESS)
335 335 break;
336 336 if (ndata == 8)
337 337 bcopy(datap, &size, sizeof (uint64_t));
338 338 ddi_prop_free(datap);
339 339 if (ndata != 8)
340 340 break;
341 341
342 342 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
343 343 DDI_PROP_DONTPASS, pname, &mname) != DDI_PROP_SUCCESS)
344 344 break;
345 345
346 346 ret = bootfs_construct_entry(bfs, addr, size, mname);
347 347 if (ret == EINVAL)
348 348 bfs->bfs_stat.bfss_ndiscards.value.ui32++;
349 349 if (ret == EEXIST)
350 350 bfs->bfs_stat.bfss_ndups.value.ui32++;
351 351 ddi_prop_free(mname);
352 352
353 353 id++;
354 354 }
355 355 }
356 356
357 357 void
358 358 bootfs_destruct(bootfs_t *bfs)
359 359 {
360 360 bootfs_node_t *bnp;
361 361
362 362 while ((bnp = list_remove_head(&bfs->bfs_nodes)) != NULL) {
363 363 ASSERT(bnp->bvn_vnp->v_count == 1);
364 364 VN_RELE(bnp->bvn_vnp);
365 365 kmem_free(bnp->bvn_name, strlen(bnp->bvn_name) + 1);
366 366 kmem_cache_free(bootfs_node_cache, bnp);
367 367 }
368 368 }
↓ open down ↓ |
295 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX