Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/namefs/namevno.c
+++ new/usr/src/uts/common/fs/namefs/namevno.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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 22 /* All Rights Reserved */
23 23
24 24
25 25 /*
26 26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27 27 */
28 28
29 29 /*
30 30 * This file defines the vnode operations for mounted file descriptors.
31 31 * The routines in this file act as a layer between the NAMEFS file
32 32 * system and SPECFS/FIFOFS. With the exception of nm_open(), nm_setattr(),
33 33 * nm_getattr() and nm_access(), the routines simply apply the VOP operation
34 34 * to the vnode representing the file descriptor. This switches control
35 35 * to the underlying file system to which the file descriptor belongs.
36 36 */
37 37 #include <sys/types.h>
38 38 #include <sys/param.h>
39 39 #include <sys/systm.h>
40 40 #include <sys/cred.h>
41 41 #include <sys/errno.h>
42 42 #include <sys/time.h>
43 43 #include <sys/file.h>
44 44 #include <sys/fcntl.h>
45 45 #include <sys/flock.h>
46 46 #include <sys/kmem.h>
47 47 #include <sys/uio.h>
48 48 #include <sys/vfs.h>
49 49 #include <sys/vfs_opreg.h>
50 50 #include <sys/vnode.h>
51 51 #include <sys/pcb.h>
52 52 #include <sys/signal.h>
53 53 #include <sys/user.h>
54 54 #include <sys/proc.h>
55 55 #include <sys/conf.h>
56 56 #include <sys/debug.h>
57 57 #include <vm/seg.h>
58 58 #include <sys/fs/namenode.h>
59 59 #include <sys/stream.h>
60 60 #include <fs/fs_subr.h>
61 61 #include <sys/policy.h>
62 62
63 63 /*
64 64 * Create a reference to the vnode representing the file descriptor.
65 65 * Then, apply the VOP_OPEN operation to that vnode.
66 66 *
67 67 * The vnode for the file descriptor may be switched under you.
68 68 * If it is, search the hash list for an nodep - nodep->nm_filevp
69 69 * pair. If it exists, return that nodep to the user.
70 70 * If it does not exist, create a new namenode to attach
71 71 * to the nodep->nm_filevp then place the pair on the hash list.
72 72 *
73 73 * Newly created objects are like children/nodes in the mounted
74 74 * file system, with the parent being the initial mount.
75 75 */
76 76 int
77 77 nm_open(vnode_t **vpp, int flag, cred_t *crp, caller_context_t *ct)
78 78 {
79 79 struct namenode *nodep = VTONM(*vpp);
80 80 int error = 0;
81 81 struct namenode *newnamep;
82 82 struct vnode *newvp;
83 83 struct vnode *infilevp;
84 84 struct vnode *outfilevp;
85 85
86 86 /*
87 87 * If the vnode is switched under us, the corresponding
88 88 * VN_RELE for this VN_HOLD will be done by the file system
89 89 * performing the switch. Otherwise, the corresponding
90 90 * VN_RELE will be done by nm_close().
91 91 */
92 92 infilevp = outfilevp = nodep->nm_filevp;
93 93 VN_HOLD(outfilevp);
94 94
95 95 if ((error = VOP_OPEN(&outfilevp, flag, crp, ct)) != 0) {
96 96 VN_RELE(outfilevp);
97 97 return (error);
98 98 }
99 99 if (infilevp != outfilevp) {
100 100 /*
101 101 * See if the new filevp (outfilevp) is already associated
102 102 * with the mount point. If it is, then it already has a
103 103 * namenode associated with it.
104 104 */
105 105 mutex_enter(&ntable_lock);
106 106 if ((newnamep =
107 107 namefind(outfilevp, nodep->nm_mountpt)) != NULL) {
108 108 struct vnode *vp = NMTOV(newnamep);
109 109
110 110 VN_HOLD(vp);
111 111 goto gotit;
112 112 }
113 113
114 114 newnamep = kmem_zalloc(sizeof (struct namenode), KM_SLEEP);
115 115 newvp = vn_alloc(KM_SLEEP);
116 116 newnamep->nm_vnode = newvp;
117 117
118 118 mutex_init(&newnamep->nm_lock, NULL, MUTEX_DEFAULT, NULL);
119 119
120 120 mutex_enter(&nodep->nm_lock);
121 121 newvp->v_flag = ((*vpp)->v_flag | VNOMAP | VNOSWAP) & ~VROOT;
122 122 vn_setops(newvp, vn_getops(*vpp));
123 123 newvp->v_vfsp = &namevfs;
124 124 newvp->v_stream = outfilevp->v_stream;
125 125 newvp->v_type = outfilevp->v_type;
126 126 newvp->v_rdev = outfilevp->v_rdev;
127 127 newvp->v_data = (caddr_t)newnamep;
128 128 vn_exists(newvp);
129 129 bcopy(&nodep->nm_vattr, &newnamep->nm_vattr, sizeof (vattr_t));
130 130 newnamep->nm_vattr.va_type = outfilevp->v_type;
131 131 newnamep->nm_vattr.va_nodeid = namenodeno_alloc();
132 132 newnamep->nm_vattr.va_size = (u_offset_t)0;
133 133 newnamep->nm_vattr.va_rdev = outfilevp->v_rdev;
134 134 newnamep->nm_flag = NMNMNT;
135 135 newnamep->nm_filevp = outfilevp;
136 136 newnamep->nm_filep = nodep->nm_filep;
137 137 newnamep->nm_mountpt = nodep->nm_mountpt;
138 138 mutex_exit(&nodep->nm_lock);
139 139
140 140 /*
141 141 * Insert the new namenode into the hash list.
142 142 */
143 143 nameinsert(newnamep);
144 144 gotit:
145 145 mutex_exit(&ntable_lock);
146 146 /*
147 147 * Release the above reference to the infilevp, the reference
148 148 * to the NAMEFS vnode, create a reference to the new vnode
149 149 * and return the new vnode to the user.
150 150 */
151 151 VN_RELE(*vpp);
152 152 *vpp = NMTOV(newnamep);
153 153 }
154 154 return (0);
155 155 }
156 156
157 157 /*
158 158 * Close a mounted file descriptor.
159 159 * Remove any locks and apply the VOP_CLOSE operation to the vnode for
160 160 * the file descriptor.
161 161 */
162 162 static int
163 163 nm_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *crp,
164 164 caller_context_t *ct)
165 165 {
166 166 struct namenode *nodep = VTONM(vp);
167 167 int error = 0;
168 168
169 169 (void) cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
170 170 cleanshares(vp, ttoproc(curthread)->p_pid);
171 171 error = VOP_CLOSE(nodep->nm_filevp, flag, count, offset, crp, ct);
172 172 if (count == 1) {
173 173 (void) VOP_FSYNC(nodep->nm_filevp, FSYNC, crp, ct);
174 174 /*
175 175 * Before VN_RELE() we need to remove the vnode from
176 176 * the hash table. We should only do so in the NMNMNT case.
177 177 * In other cases, nodep->nm_filep keeps a reference
178 178 * to nm_filevp and the entry in the hash table doesn't
179 179 * hurt.
180 180 */
181 181 if ((nodep->nm_flag & NMNMNT) != 0) {
182 182 mutex_enter(&ntable_lock);
183 183 nameremove(nodep);
184 184 mutex_exit(&ntable_lock);
185 185 }
186 186 VN_RELE(nodep->nm_filevp);
187 187 }
188 188 return (error);
189 189 }
190 190
191 191 static int
192 192 nm_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *crp,
193 193 caller_context_t *ct)
194 194 {
195 195 return (VOP_READ(VTONM(vp)->nm_filevp, uiop, ioflag, crp, ct));
196 196 }
197 197
198 198 static int
199 199 nm_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *crp,
200 200 caller_context_t *ct)
201 201 {
202 202 return (VOP_WRITE(VTONM(vp)->nm_filevp, uiop, ioflag, crp, ct));
203 203 }
204 204
205 205 static int
206 206 nm_ioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr, int *rvalp,
207 207 caller_context_t *ct)
208 208 {
209 209 return (VOP_IOCTL(VTONM(vp)->nm_filevp, cmd, arg, mode, cr, rvalp, ct));
210 210 }
211 211
212 212 /*
213 213 * Return in vap the attributes that are stored in the namenode
214 214 * structure. Only the size is taken from the mounted object.
215 215 */
216 216 /* ARGSUSED */
217 217 static int
218 218 nm_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *crp,
219 219 caller_context_t *ct)
220 220 {
221 221 struct namenode *nodep = VTONM(vp);
222 222 struct vattr va;
223 223 int error;
224 224
225 225 mutex_enter(&nodep->nm_lock);
226 226 bcopy(&nodep->nm_vattr, vap, sizeof (vattr_t));
227 227 mutex_exit(&nodep->nm_lock);
228 228
229 229 if ((va.va_mask = vap->va_mask & AT_SIZE) != 0) {
230 230 if (error = VOP_GETATTR(nodep->nm_filevp, &va, flags, crp, ct))
231 231 return (error);
232 232 vap->va_size = va.va_size;
233 233 }
234 234
235 235 return (0);
236 236 }
237 237
238 238 /*
239 239 * Standard access() like check. Figure out which mode bits apply
240 240 * to the caller then pass the missing mode bits to the secpolicy function.
241 241 */
242 242 static int
243 243 nm_access_unlocked(void *vnp, int mode, cred_t *crp)
244 244 {
245 245 struct namenode *nodep = vnp;
246 246 int shift = 0;
247 247
248 248 if (crgetuid(crp) != nodep->nm_vattr.va_uid) {
249 249 shift += 3;
250 250 if (!groupmember(nodep->nm_vattr.va_gid, crp))
251 251 shift += 3;
252 252 }
253 253
254 254 return (secpolicy_vnode_access2(crp, NMTOV(nodep),
255 255 nodep->nm_vattr.va_uid, nodep->nm_vattr.va_mode << shift,
256 256 mode));
257 257 }
258 258 /*
259 259 * Set the attributes of the namenode from the attributes in vap.
260 260 */
261 261 /* ARGSUSED */
262 262 static int
263 263 nm_setattr(
264 264 vnode_t *vp,
265 265 vattr_t *vap,
266 266 int flags,
267 267 cred_t *crp,
268 268 caller_context_t *ctp)
269 269 {
270 270 struct namenode *nodep = VTONM(vp);
271 271 struct vattr *nmvap = &nodep->nm_vattr;
272 272 long mask = vap->va_mask;
273 273 int error = 0;
274 274
275 275 /*
276 276 * Cannot set these attributes.
277 277 */
278 278 if (mask & (AT_NOSET|AT_SIZE))
279 279 return (EINVAL);
280 280
281 281 (void) VOP_RWLOCK(nodep->nm_filevp, V_WRITELOCK_TRUE, ctp);
282 282 mutex_enter(&nodep->nm_lock);
283 283
284 284 /*
285 285 * Change ownership/group/time/access mode of mounted file
286 286 * descriptor.
287 287 */
288 288
289 289 error = secpolicy_vnode_setattr(crp, vp, vap, nmvap, flags,
290 290 nm_access_unlocked, nodep);
291 291 if (error)
292 292 goto out;
293 293
294 294 mask = vap->va_mask;
295 295 /*
296 296 * If request to change mode, copy new
297 297 * mode into existing attribute structure.
298 298 */
299 299 if (mask & AT_MODE)
300 300 nmvap->va_mode = vap->va_mode & ~VSVTX;
301 301
302 302 /*
303 303 * If request was to change user or group, turn off suid and sgid
304 304 * bits.
305 305 * If the system was configured with the "rstchown" option, the
306 306 * owner is not permitted to give away the file, and can change
307 307 * the group id only to a group of which he or she is a member.
308 308 */
309 309 if (mask & AT_UID)
310 310 nmvap->va_uid = vap->va_uid;
311 311 if (mask & AT_GID)
312 312 nmvap->va_gid = vap->va_gid;
313 313 /*
314 314 * If request is to modify times, make sure user has write
315 315 * permissions on the file.
316 316 */
317 317 if (mask & AT_ATIME)
318 318 nmvap->va_atime = vap->va_atime;
319 319 if (mask & AT_MTIME) {
320 320 nmvap->va_mtime = vap->va_mtime;
321 321 gethrestime(&nmvap->va_ctime);
322 322 }
323 323 out:
324 324 mutex_exit(&nodep->nm_lock);
325 325 VOP_RWUNLOCK(nodep->nm_filevp, V_WRITELOCK_TRUE, ctp);
326 326 return (error);
327 327 }
328 328
329 329 /*
330 330 * Check mode permission on the namenode. First nm_access_unlocked()
331 331 * checks the bits on the name node, then an access check is performed
332 332 * on the underlying file.
333 333 */
334 334 /* ARGSUSED */
335 335 static int
336 336 nm_access(vnode_t *vp, int mode, int flags, cred_t *crp,
337 337 caller_context_t *ct)
338 338 {
339 339 struct namenode *nodep = VTONM(vp);
340 340 int error;
341 341
342 342 mutex_enter(&nodep->nm_lock);
343 343 error = nm_access_unlocked(nodep, mode, crp);
344 344 mutex_exit(&nodep->nm_lock);
345 345 if (error == 0)
346 346 return (VOP_ACCESS(nodep->nm_filevp, mode, flags, crp, ct));
347 347 else
348 348 return (error);
349 349 }
350 350
351 351 /*
352 352 * We can get here if a creat or open with O_CREAT is done on a namefs
353 353 * mount point, for example, as the object of a shell output redirection to
354 354 * the mount point.
355 355 */
356 356 /*ARGSUSED*/
357 357 static int
358 358 nm_create(vnode_t *dvp, char *name, vattr_t *vap, enum vcexcl excl,
359 359 int mode, vnode_t **vpp, cred_t *cr, int flag,
360 360 caller_context_t *ct, vsecattr_t *vsecp)
361 361 {
362 362 int error;
363 363
364 364 ASSERT(dvp && *name == '\0');
365 365 if (excl == NONEXCL) {
366 366 if (mode && (error = nm_access(dvp, mode, 0, cr, ct)) != 0)
367 367 return (error);
368 368 VN_HOLD(dvp);
369 369 return (0);
370 370 }
371 371 return (EEXIST);
372 372 }
373 373
374 374 /*
375 375 * Links are not allowed on mounted file descriptors.
376 376 */
377 377 /*ARGSUSED*/
378 378 static int
379 379 nm_link(vnode_t *tdvp, vnode_t *vp, char *tnm, cred_t *crp,
380 380 caller_context_t *ct, int flags)
381 381 {
382 382 return (EXDEV);
383 383 }
384 384
385 385 static int
386 386 nm_fsync(vnode_t *vp, int syncflag, cred_t *crp, caller_context_t *ct)
387 387 {
388 388 return (VOP_FSYNC(VTONM(vp)->nm_filevp, syncflag, crp, ct));
389 389 }
390 390
391 391 /* Free the namenode */
392 392 /* ARGSUSED */
393 393 static void
394 394 nm_inactive(vnode_t *vp, cred_t *crp, caller_context_t *ct)
395 395 {
396 396 struct namenode *nodep = VTONM(vp);
397 397 vfs_t *vfsp = vp->v_vfsp;
398 398
399 399 mutex_enter(&vp->v_lock);
400 400 ASSERT(vp->v_count >= 1);
401 401 if (--vp->v_count != 0) {
402 402 mutex_exit(&vp->v_lock);
403 403 return;
404 404 }
405 405 mutex_exit(&vp->v_lock);
406 406 if (!(nodep->nm_flag & NMNMNT)) {
407 407 ASSERT(nodep->nm_filep->f_vnode == nodep->nm_filevp);
408 408 (void) closef(nodep->nm_filep);
409 409 }
410 410 vn_invalid(vp);
411 411 vn_free(vp);
412 412 if (vfsp != &namevfs)
413 413 VFS_RELE(vfsp);
414 414 namenodeno_free(nodep->nm_vattr.va_nodeid);
415 415 kmem_free(nodep, sizeof (struct namenode));
416 416 }
417 417
418 418 static int
419 419 nm_fid(vnode_t *vp, struct fid *fidnodep, caller_context_t *ct)
420 420 {
421 421 return (VOP_FID(VTONM(vp)->nm_filevp, fidnodep, ct));
422 422 }
423 423
424 424 static int
425 425 nm_rwlock(vnode_t *vp, int write, caller_context_t *ctp)
426 426 {
427 427 return (VOP_RWLOCK(VTONM(vp)->nm_filevp, write, ctp));
428 428 }
429 429
430 430 static void
431 431 nm_rwunlock(vnode_t *vp, int write, caller_context_t *ctp)
432 432 {
433 433 VOP_RWUNLOCK(VTONM(vp)->nm_filevp, write, ctp);
434 434 }
435 435
436 436 static int
437 437 nm_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
438 438 {
439 439 return (VOP_SEEK(VTONM(vp)->nm_filevp, ooff, noffp, ct));
440 440 }
441 441
442 442 /*
443 443 * Return the vnode representing the file descriptor in vpp.
444 444 */
445 445 static int
446 446 nm_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
447 447 {
448 448 struct vnode *rvp;
449 449
450 450 vp = VTONM(vp)->nm_filevp;
451 451 if (VOP_REALVP(vp, &rvp, ct) == 0)
452 452 vp = rvp;
453 453 *vpp = vp;
454 454 return (0);
455 455 }
456 456
457 457 static int
↓ open down ↓ |
457 lines elided |
↑ open up ↑ |
458 458 nm_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
459 459 pollhead_t **phpp, caller_context_t *ct)
460 460 {
461 461 return (VOP_POLL(VTONM(vp)->nm_filevp, events, anyyet, reventsp,
462 462 phpp, ct));
463 463 }
464 464
465 465 struct vnodeops *nm_vnodeops;
466 466
467 467 const fs_operation_def_t nm_vnodeops_template[] = {
468 - VOPNAME_OPEN, { .vop_open = nm_open },
469 - VOPNAME_CLOSE, { .vop_close = nm_close },
470 - VOPNAME_READ, { .vop_read = nm_read },
471 - VOPNAME_WRITE, { .vop_write = nm_write },
472 - VOPNAME_IOCTL, { .vop_ioctl = nm_ioctl },
473 - VOPNAME_GETATTR, { .vop_getattr = nm_getattr },
474 - VOPNAME_SETATTR, { .vop_setattr = nm_setattr },
475 - VOPNAME_ACCESS, { .vop_access = nm_access },
476 - VOPNAME_CREATE, { .vop_create = nm_create },
477 - VOPNAME_LINK, { .vop_link = nm_link },
478 - VOPNAME_FSYNC, { .vop_fsync = nm_fsync },
479 - VOPNAME_INACTIVE, { .vop_inactive = nm_inactive },
480 - VOPNAME_FID, { .vop_fid = nm_fid },
481 - VOPNAME_RWLOCK, { .vop_rwlock = nm_rwlock },
482 - VOPNAME_RWUNLOCK, { .vop_rwunlock = nm_rwunlock },
483 - VOPNAME_SEEK, { .vop_seek = nm_seek },
484 - VOPNAME_REALVP, { .vop_realvp = nm_realvp },
485 - VOPNAME_POLL, { .vop_poll = nm_poll },
486 - VOPNAME_DISPOSE, { .error = fs_error },
487 - NULL, NULL
468 + { VOPNAME_OPEN, { .vop_open = nm_open } },
469 + { VOPNAME_CLOSE, { .vop_close = nm_close } },
470 + { VOPNAME_READ, { .vop_read = nm_read } },
471 + { VOPNAME_WRITE, { .vop_write = nm_write } },
472 + { VOPNAME_IOCTL, { .vop_ioctl = nm_ioctl } },
473 + { VOPNAME_GETATTR, { .vop_getattr = nm_getattr } },
474 + { VOPNAME_SETATTR, { .vop_setattr = nm_setattr } },
475 + { VOPNAME_ACCESS, { .vop_access = nm_access } },
476 + { VOPNAME_CREATE, { .vop_create = nm_create } },
477 + { VOPNAME_LINK, { .vop_link = nm_link } },
478 + { VOPNAME_FSYNC, { .vop_fsync = nm_fsync } },
479 + { VOPNAME_INACTIVE, { .vop_inactive = nm_inactive } },
480 + { VOPNAME_FID, { .vop_fid = nm_fid } },
481 + { VOPNAME_RWLOCK, { .vop_rwlock = nm_rwlock } },
482 + { VOPNAME_RWUNLOCK, { .vop_rwunlock = nm_rwunlock } },
483 + { VOPNAME_SEEK, { .vop_seek = nm_seek } },
484 + { VOPNAME_REALVP, { .vop_realvp = nm_realvp } },
485 + { VOPNAME_POLL, { .vop_poll = nm_poll } },
486 + { VOPNAME_DISPOSE, { .error = fs_error } },
487 + { NULL, { NULL } }
488 488 };
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX