Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/ctfs/ctfs_root.c
+++ new/usr/src/uts/common/fs/ctfs/ctfs_root.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <sys/modctl.h>
26 26 #include <sys/types.h>
27 27 #include <sys/param.h>
28 28 #include <sys/time.h>
29 29 #include <sys/cred.h>
30 30 #include <sys/vfs.h>
31 31 #include <sys/vfs_opreg.h>
32 32 #include <sys/gfs.h>
33 33 #include <sys/vnode.h>
34 34 #include <sys/systm.h>
35 35 #include <sys/cmn_err.h>
36 36 #include <sys/errno.h>
37 37 #include <sys/sysmacros.h>
38 38 #include <sys/policy.h>
39 39 #include <sys/mount.h>
40 40 #include <sys/pathname.h>
41 41 #include <sys/dirent.h>
42 42 #include <fs/fs_subr.h>
43 43 #include <sys/contract.h>
44 44 #include <sys/contract_impl.h>
45 45 #include <sys/ctfs.h>
46 46 #include <sys/ctfs_impl.h>
47 47 #include <sys/uio.h>
48 48 #include <sys/file.h>
49 49 #include <sys/atomic.h>
50 50 #include <sys/sunddi.h>
51 51
52 52 /*
53 53 * ctfs, the contract filesystem.
54 54 *
55 55 * Exposes the construct subsystem to userland. The structure of the
56 56 * filesytem is a public interface, but the behavior of the files is
57 57 * private and unstable. Contract consumers are expected to use
58 58 * libcontract(3lib) to operate on ctfs file descriptors.
59 59 *
60 60 * We're trying something a little different here. Rather than make
61 61 * each vnode op itself call into a vector of file type operations, we
62 62 * actually use different vnode types (gasp!), the implementations of
63 63 * which may call into routines providing common functionality. This
64 64 * design should hopefully make it easier to factor and maintain the
65 65 * code. For the most part, there is a separate file for each vnode
66 66 * type's implementation. The exceptions to this are the ctl/stat
67 67 * nodes, which are very similar, and the three event endpoint types.
68 68 *
69 69 * This file contains common routines used by some or all of the vnode
70 70 * types, the filesystem's module linkage and VFS operations, and the
71 71 * implementation of the root vnode.
72 72 */
73 73
74 74 /*
75 75 * Ops vectors for all the vnode types; they have to be defined
76 76 * somewhere. See gfs_make_opsvec for thoughts on how this could be
77 77 * done differently.
78 78 */
79 79 vnodeops_t *ctfs_ops_root;
80 80 vnodeops_t *ctfs_ops_adir;
81 81 vnodeops_t *ctfs_ops_sym;
82 82 vnodeops_t *ctfs_ops_tdir;
83 83 vnodeops_t *ctfs_ops_tmpl;
84 84 vnodeops_t *ctfs_ops_cdir;
85 85 vnodeops_t *ctfs_ops_ctl;
86 86 vnodeops_t *ctfs_ops_stat;
87 87 vnodeops_t *ctfs_ops_event;
88 88 vnodeops_t *ctfs_ops_bundle;
89 89 vnodeops_t *ctfs_ops_latest;
90 90
91 91 static const fs_operation_def_t ctfs_vfstops[];
92 92 static gfs_opsvec_t ctfs_opsvec[];
93 93
94 94 static int ctfs_init(int, char *);
95 95
96 96 static ino64_t ctfs_root_do_inode(vnode_t *, int);
97 97
98 98
99 99 /*
100 100 * File system module linkage
101 101 */
102 102 static mntopts_t ctfs_mntopts = {
103 103 0,
104 104 NULL
105 105 };
106 106
107 107 static vfsdef_t vfw = {
108 108 VFSDEF_VERSION,
109 109 "ctfs",
110 110 ctfs_init,
111 111 VSW_HASPROTO|VSW_ZMOUNT,
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
112 112 &ctfs_mntopts,
113 113 };
114 114
115 115 extern struct mod_ops mod_fsops;
116 116
117 117 static struct modlfs modlfs = {
118 118 &mod_fsops, "contract filesystem", &vfw
119 119 };
120 120
121 121 static struct modlinkage modlinkage = {
122 - MODREV_1, (void *)&modlfs, NULL
122 + MODREV_1, { (void *)&modlfs, NULL }
123 123 };
124 124
125 125 int
126 126 _init(void)
127 127 {
128 128 return (mod_install(&modlinkage));
129 129 }
130 130
131 131 int
132 132 _info(struct modinfo *modinfop)
133 133 {
134 134 return (mod_info(&modlinkage, modinfop));
135 135 }
136 136
137 137 int
138 138 _fini(void)
139 139 {
140 140 /*
141 141 * As unloading filesystem modules isn't completely safe, we
142 142 * don't allow it.
143 143 */
144 144 return (EBUSY);
145 145 }
146 146
147 147 static int ctfs_fstype;
148 148 static major_t ctfs_major;
149 149 static minor_t ctfs_minor = 0;
150 150
151 151 /*
152 152 * The ops vector vector.
153 153 */
154 154 static const fs_operation_def_t ctfs_tops_root[];
155 155 extern const fs_operation_def_t ctfs_tops_tmpl[];
156 156 extern const fs_operation_def_t ctfs_tops_ctl[];
157 157 extern const fs_operation_def_t ctfs_tops_adir[];
158 158 extern const fs_operation_def_t ctfs_tops_cdir[];
159 159 extern const fs_operation_def_t ctfs_tops_tdir[];
160 160 extern const fs_operation_def_t ctfs_tops_latest[];
161 161 extern const fs_operation_def_t ctfs_tops_stat[];
162 162 extern const fs_operation_def_t ctfs_tops_sym[];
163 163 extern const fs_operation_def_t ctfs_tops_event[];
164 164 extern const fs_operation_def_t ctfs_tops_bundle[];
165 165 static gfs_opsvec_t ctfs_opsvec[] = {
166 166 { "ctfs root directory", ctfs_tops_root, &ctfs_ops_root },
167 167 { "ctfs all directory", ctfs_tops_adir, &ctfs_ops_adir },
168 168 { "ctfs all symlink", ctfs_tops_sym, &ctfs_ops_sym },
169 169 { "ctfs template directory", ctfs_tops_tdir, &ctfs_ops_tdir },
170 170 { "ctfs template file", ctfs_tops_tmpl, &ctfs_ops_tmpl },
171 171 { "ctfs contract directory", ctfs_tops_cdir, &ctfs_ops_cdir },
172 172 { "ctfs ctl file", ctfs_tops_ctl, &ctfs_ops_ctl },
173 173 { "ctfs status file", ctfs_tops_stat, &ctfs_ops_stat },
174 174 { "ctfs events file", ctfs_tops_event, &ctfs_ops_event },
175 175 { "ctfs bundle file", ctfs_tops_bundle, &ctfs_ops_bundle },
176 176 { "ctfs latest file", ctfs_tops_latest, &ctfs_ops_latest },
177 177 { NULL }
178 178 };
179 179
180 180
181 181 /*
182 182 * ctfs_init - the vfsdef_t init entry point
183 183 *
184 184 * Sets the VFS ops, builds all the vnode ops, and allocates a device
185 185 * number.
186 186 */
187 187 /* ARGSUSED */
188 188 static int
189 189 ctfs_init(int fstype, char *name)
190 190 {
191 191 vfsops_t *vfsops;
192 192 int error;
193 193
194 194 ctfs_fstype = fstype;
195 195 if (error = vfs_setfsops(fstype, ctfs_vfstops, &vfsops)) {
196 196 cmn_err(CE_WARN, "ctfs_init: bad vfs ops template");
197 197 return (error);
198 198 }
199 199
200 200 if (error = gfs_make_opsvec(ctfs_opsvec)) {
201 201 (void) vfs_freevfsops(vfsops);
202 202 return (error);
203 203 }
204 204
205 205 if ((ctfs_major = getudev()) == (major_t)-1) {
206 206 cmn_err(CE_WARN, "ctfs_init: can't get unique device number");
207 207 ctfs_major = 0;
208 208 }
209 209
210 210 return (0);
211 211 }
212 212
213 213 /*
214 214 * ctfs_mount - the VFS_MOUNT entry point
215 215 */
216 216 static int
217 217 ctfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
218 218 {
219 219 ctfs_vfs_t *data;
220 220 dev_t dev;
221 221 gfs_dirent_t *dirent;
222 222 int i;
223 223
224 224 if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
225 225 return (EPERM);
226 226
227 227 if (mvp->v_type != VDIR)
228 228 return (ENOTDIR);
229 229
230 230 if ((uap->flags & MS_OVERLAY) == 0 &&
231 231 (mvp->v_count > 1 || (mvp->v_flag & VROOT)))
232 232 return (EBUSY);
233 233
234 234 data = kmem_alloc(sizeof (ctfs_vfs_t), KM_SLEEP);
235 235
236 236 /*
237 237 * Initialize vfs fields not initialized by VFS_INIT/domount
238 238 */
239 239 vfsp->vfs_bsize = DEV_BSIZE;
240 240 vfsp->vfs_fstype = ctfs_fstype;
241 241 do {
242 242 dev = makedevice(ctfs_major,
243 243 atomic_inc_32_nv(&ctfs_minor) & L_MAXMIN32);
244 244 } while (vfs_devismounted(dev));
245 245 vfs_make_fsid(&vfsp->vfs_fsid, dev, ctfs_fstype);
246 246 vfsp->vfs_data = data;
247 247 vfsp->vfs_dev = dev;
248 248
249 249 /*
250 250 * Dynamically create gfs_dirent_t array for the root directory.
251 251 */
252 252 dirent = kmem_zalloc((ct_ntypes + 2) * sizeof (gfs_dirent_t), KM_SLEEP);
253 253 for (i = 0; i < ct_ntypes; i++) {
254 254 dirent[i].gfse_name = (char *)ct_types[i]->ct_type_name;
255 255 dirent[i].gfse_ctor = ctfs_create_tdirnode;
256 256 dirent[i].gfse_flags = GFS_CACHE_VNODE;
257 257 }
258 258 dirent[i].gfse_name = "all";
259 259 dirent[i].gfse_ctor = ctfs_create_adirnode;
260 260 dirent[i].gfse_flags = GFS_CACHE_VNODE;
261 261 dirent[i+1].gfse_name = NULL;
262 262
263 263 /*
264 264 * Create root vnode
265 265 */
266 266 data->ctvfs_root = gfs_root_create(sizeof (ctfs_rootnode_t),
267 267 vfsp, ctfs_ops_root, CTFS_INO_ROOT, dirent, ctfs_root_do_inode,
268 268 CTFS_NAME_MAX, NULL, NULL);
269 269
270 270 kmem_free(dirent, (ct_ntypes + 2) * sizeof (gfs_dirent_t));
271 271
272 272 return (0);
273 273 }
274 274
275 275 /*
276 276 * ctfs_unmount - the VFS_UNMOUNT entry point
277 277 */
278 278 static int
279 279 ctfs_unmount(vfs_t *vfsp, int flag, struct cred *cr)
280 280 {
281 281 ctfs_vfs_t *data;
282 282
283 283 if (secpolicy_fs_unmount(cr, vfsp) != 0)
284 284 return (EPERM);
285 285
286 286 /*
287 287 * Supporting forced unmounts would be nice to do at some
288 288 * point.
289 289 */
290 290 if (flag & MS_FORCE)
291 291 return (ENOTSUP);
292 292
293 293 /*
294 294 * We should never have a reference count less than 2: one for
295 295 * the caller, one for the root vnode.
296 296 */
297 297 ASSERT(vfsp->vfs_count >= 2);
298 298
299 299 /*
300 300 * If we have any active vnodes, they will (transitively) have
301 301 * holds on the root vnode.
302 302 */
303 303 data = vfsp->vfs_data;
304 304 if (data->ctvfs_root->v_count > 1)
305 305 return (EBUSY);
306 306
307 307 /*
308 308 * Release the last hold on the root vnode. It will, in turn,
309 309 * release its hold on us.
310 310 */
311 311 VN_RELE(data->ctvfs_root);
312 312
313 313 /*
314 314 * Disappear.
315 315 */
316 316 kmem_free(data, sizeof (ctfs_vfs_t));
317 317
318 318 return (0);
319 319 }
320 320
321 321 /*
322 322 * ctfs_root - the VFS_ROOT entry point
323 323 */
324 324 static int
325 325 ctfs_root(vfs_t *vfsp, vnode_t **vpp)
326 326 {
327 327 vnode_t *vp;
328 328
329 329 vp = ((ctfs_vfs_t *)vfsp->vfs_data)->ctvfs_root;
330 330 VN_HOLD(vp);
331 331 *vpp = vp;
332 332
333 333 return (0);
334 334 }
335 335
336 336 /*
337 337 * ctfs_statvfs - the VFS_STATVFS entry point
338 338 */
339 339 static int
340 340 ctfs_statvfs(vfs_t *vfsp, statvfs64_t *sp)
341 341 {
342 342 dev32_t d32;
343 343 int total, i;
344 344
345 345 bzero(sp, sizeof (*sp));
346 346 sp->f_bsize = DEV_BSIZE;
347 347 sp->f_frsize = DEV_BSIZE;
348 348 for (i = 0, total = 0; i < ct_ntypes; i++)
349 349 total += contract_type_count(ct_types[i]);
350 350 sp->f_files = total;
351 351 sp->f_favail = sp->f_ffree = INT_MAX - total;
352 352 (void) cmpldev(&d32, vfsp->vfs_dev);
353 353 sp->f_fsid = d32;
354 354 (void) strlcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name,
355 355 sizeof (sp->f_basetype));
356 356 sp->f_flag = vf_to_stf(vfsp->vfs_flag);
357 357 sp->f_namemax = CTFS_NAME_MAX;
↓ open down ↓ |
225 lines elided |
↑ open up ↑ |
358 358 (void) strlcpy(sp->f_fstr, "contract", sizeof (sp->f_fstr));
359 359
360 360 return (0);
361 361 }
362 362
363 363 static const fs_operation_def_t ctfs_vfstops[] = {
364 364 { VFSNAME_MOUNT, { .vfs_mount = ctfs_mount } },
365 365 { VFSNAME_UNMOUNT, { .vfs_unmount = ctfs_unmount } },
366 366 { VFSNAME_ROOT, { .vfs_root = ctfs_root } },
367 367 { VFSNAME_STATVFS, { .vfs_statvfs = ctfs_statvfs } },
368 - { NULL, NULL }
368 + { NULL, { NULL } }
369 369 };
370 370
371 371 /*
372 372 * ctfs_common_getattr
373 373 *
374 374 * Implements functionality common to all ctfs VOP_GETATTR entry
375 375 * points. It assumes vap->va_size is set.
376 376 */
377 377 void
378 378 ctfs_common_getattr(vnode_t *vp, vattr_t *vap)
379 379 {
380 380 vap->va_uid = 0;
381 381 vap->va_gid = 0;
382 382 vap->va_rdev = 0;
383 383 vap->va_blksize = DEV_BSIZE;
384 384 vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
385 385 vap->va_seq = 0;
386 386 vap->va_fsid = vp->v_vfsp->vfs_dev;
387 387 vap->va_nodeid = gfs_file_inode(vp);
388 388 }
389 389
390 390 /*
391 391 * ctfs_open - common VOP_OPEN entry point
392 392 *
393 393 * Used by all ctfs directories; just verifies we are using large-file
394 394 * aware interfaces and we aren't trying to open the directories
395 395 * writable.
396 396 */
397 397 /* ARGSUSED */
398 398 int
399 399 ctfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
400 400 {
401 401 if ((flag & (FOFFMAX | FWRITE)) != FOFFMAX)
402 402 return (EINVAL);
403 403
404 404 return (0);
405 405 }
406 406
407 407 /*
408 408 * ctfs_close - common VOP_CLOSE entry point
409 409 *
410 410 * For all ctfs vnode types which have no close-time clean-up to do.
411 411 */
412 412 /* ARGSUSED */
413 413 int
414 414 ctfs_close(
415 415 vnode_t *vp,
416 416 int flag,
417 417 int count,
418 418 offset_t offset,
419 419 cred_t *cr,
420 420 caller_context_t *ct)
421 421 {
422 422 return (0);
423 423 }
424 424
425 425 /*
426 426 * ctfs_access_dir - common VOP_ACCESS entry point for directories
427 427 */
428 428 /* ARGSUSED */
429 429 int
430 430 ctfs_access_dir(
431 431 vnode_t *vp,
432 432 int mode,
433 433 int flags,
434 434 cred_t *cr,
435 435 caller_context_t *ct)
436 436 {
437 437 if (mode & VWRITE)
438 438 return (EACCES);
439 439
440 440 return (0);
441 441 }
442 442
443 443 /*
444 444 * ctfs_access_dir - common VOP_ACCESS entry point for read-only files
445 445 */
446 446 /* ARGSUSED */
447 447 int
448 448 ctfs_access_readonly(
449 449 vnode_t *vp,
450 450 int mode,
451 451 int flags,
452 452 cred_t *cr,
453 453 caller_context_t *ct)
454 454 {
455 455 if (mode & (VWRITE | VEXEC))
456 456 return (EACCES);
457 457
458 458 return (0);
459 459 }
460 460
461 461 /*
462 462 * ctfs_access_dir - common VOP_ACCESS entry point for read-write files
463 463 */
464 464 /* ARGSUSED */
465 465 int
466 466 ctfs_access_readwrite(
467 467 vnode_t *vp,
468 468 int mode,
469 469 int flags,
470 470 cred_t *cr,
471 471 caller_context_t *ct)
472 472 {
473 473 if (mode & VEXEC)
474 474 return (EACCES);
475 475
476 476 return (0);
477 477 }
478 478
479 479 /*
480 480 * ctfs_root_getattr - VOP_GETATTR entry point
481 481 */
482 482 /* ARGSUSED */
483 483 static int
484 484 ctfs_root_getattr(
485 485 vnode_t *vp,
486 486 vattr_t *vap,
487 487 int flags,
488 488 cred_t *cr,
489 489 caller_context_t *ct)
490 490 {
491 491 vap->va_type = VDIR;
492 492 vap->va_mode = 0555;
493 493 vap->va_nlink = 2 + ct_ntypes + 1;
494 494 vap->va_size = vap->va_nlink;
495 495 vap->va_atime.tv_sec = vp->v_vfsp->vfs_mtime;
496 496 vap->va_atime.tv_nsec = 0;
497 497 vap->va_mtime = vap->va_ctime = vap->va_atime;
498 498 ctfs_common_getattr(vp, vap);
499 499
500 500 return (0);
501 501 }
502 502
503 503 /* ARGSUSED */
504 504 static ino64_t
505 505 ctfs_root_do_inode(vnode_t *vp, int index)
506 506 {
507 507 return (CTFS_INO_TYPE_DIR(index));
508 508 }
509 509
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
510 510 static const fs_operation_def_t ctfs_tops_root[] = {
511 511 { VOPNAME_OPEN, { .vop_open = ctfs_open } },
512 512 { VOPNAME_CLOSE, { .vop_close = ctfs_close } },
513 513 { VOPNAME_IOCTL, { .error = fs_inval } },
514 514 { VOPNAME_GETATTR, { .vop_getattr = ctfs_root_getattr } },
515 515 { VOPNAME_ACCESS, { .vop_access = ctfs_access_dir } },
516 516 { VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } },
517 517 { VOPNAME_LOOKUP, { .vop_lookup = gfs_vop_lookup } },
518 518 { VOPNAME_SEEK, { .vop_seek = fs_seek } },
519 519 { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } },
520 - { NULL, NULL }
520 + { NULL, { NULL } }
521 521 };
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX