Print this page
6474 getupeercred causes spurious event port wakeups on FIFOs
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/fifofs/fifovnops.c
+++ new/usr/src/uts/common/fs/fifofs/fifovnops.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.
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
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 -/* All rights reserved. */
22 +/* All rights reserved. */
23 23
24 24
25 25 /*
26 26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
27 27 * Use is subject to license terms.
28 28 */
29 29
30 30 /*
31 31 * Copyright 2015, Joyent, Inc.
32 32 * Copyright (c) 2017 by Delphix. All rights reserved.
33 33 */
34 34
35 35 /*
36 36 * FIFOFS file system vnode operations. This file system
37 37 * type supports STREAMS-based pipes and FIFOs.
38 38 */
39 39 #include <sys/types.h>
40 40 #include <sys/param.h>
41 41 #include <sys/systm.h>
42 42 #include <sys/sysmacros.h>
43 43 #include <sys/cred.h>
44 44 #include <sys/errno.h>
45 45 #include <sys/time.h>
46 46 #include <sys/file.h>
47 47 #include <sys/fcntl.h>
48 48 #include <sys/kmem.h>
49 49 #include <sys/uio.h>
50 50 #include <sys/vfs.h>
51 51 #include <sys/vnode.h>
52 52 #include <sys/vfs_opreg.h>
53 53 #include <sys/pathname.h>
54 54 #include <sys/signal.h>
55 55 #include <sys/user.h>
56 56 #include <sys/strsubr.h>
57 57 #include <sys/stream.h>
58 58 #include <sys/strsun.h>
59 59 #include <sys/strredir.h>
60 60 #include <sys/fs/fifonode.h>
61 61 #include <sys/fs/namenode.h>
62 62 #include <sys/stropts.h>
63 63 #include <sys/proc.h>
64 64 #include <sys/unistd.h>
65 65 #include <sys/debug.h>
66 66 #include <fs/fs_subr.h>
67 67 #include <sys/filio.h>
68 68 #include <sys/termio.h>
69 69 #include <sys/ddi.h>
70 70 #include <sys/vtrace.h>
71 71 #include <sys/policy.h>
72 72 #include <sys/tsol/label.h>
73 73
74 74 /*
75 75 * Define the routines/data structures used in this file.
76 76 */
77 77 static int fifo_read(vnode_t *, uio_t *, int, cred_t *, caller_context_t *);
78 78 static int fifo_write(vnode_t *, uio_t *, int, cred_t *, caller_context_t *);
79 79 static int fifo_getattr(vnode_t *, vattr_t *, int, cred_t *,
80 80 caller_context_t *);
81 81 static int fifo_setattr(vnode_t *, vattr_t *, int, cred_t *,
82 82 caller_context_t *);
83 83 static int fifo_realvp(vnode_t *, vnode_t **, caller_context_t *);
84 84 static int fifo_access(vnode_t *, int, int, cred_t *, caller_context_t *);
85 85 static int fifo_create(struct vnode *, char *, vattr_t *, enum vcexcl,
86 86 int, struct vnode **, struct cred *, int, caller_context_t *,
87 87 vsecattr_t *);
88 88 static int fifo_fid(vnode_t *, fid_t *, caller_context_t *);
89 89 static int fifo_fsync(vnode_t *, int, cred_t *, caller_context_t *);
90 90 static int fifo_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
91 91 static int fifo_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
92 92 caller_context_t *);
93 93 static int fifo_fastioctl(vnode_t *, int, intptr_t, int, cred_t *, int *);
94 94 static int fifo_strioctl(vnode_t *, int, intptr_t, int, cred_t *, int *);
95 95 static int fifo_poll(vnode_t *, short, int, short *, pollhead_t **,
96 96 caller_context_t *);
97 97 static int fifo_pathconf(vnode_t *, int, ulong_t *, cred_t *,
98 98 caller_context_t *);
99 99 static void fifo_inactive(vnode_t *, cred_t *, caller_context_t *);
100 100 static int fifo_rwlock(vnode_t *, int, caller_context_t *);
101 101 static void fifo_rwunlock(vnode_t *, int, caller_context_t *);
102 102 static int fifo_setsecattr(struct vnode *, vsecattr_t *, int, struct cred *,
103 103 caller_context_t *);
104 104 static int fifo_getsecattr(struct vnode *, vsecattr_t *, int, struct cred *,
105 105 caller_context_t *);
106 106
107 107 /* functions local to this file */
108 108 static boolean_t fifo_stayfast_enter(fifonode_t *);
109 109 static void fifo_stayfast_exit(fifonode_t *);
110 110
111 111 /*
112 112 * Define the data structures external to this file.
113 113 */
114 114 extern dev_t fifodev;
115 115 extern struct qinit fifo_stwdata;
116 116 extern struct qinit fifo_strdata;
117 117 extern kmutex_t ftable_lock;
118 118
119 119 struct streamtab fifoinfo = { &fifo_strdata, &fifo_stwdata, NULL, NULL };
120 120
121 121 struct vnodeops *fifo_vnodeops;
122 122
123 123 const fs_operation_def_t fifo_vnodeops_template[] = {
124 124 VOPNAME_OPEN, { .vop_open = fifo_open },
125 125 VOPNAME_CLOSE, { .vop_close = fifo_close },
126 126 VOPNAME_READ, { .vop_read = fifo_read },
127 127 VOPNAME_WRITE, { .vop_write = fifo_write },
128 128 VOPNAME_IOCTL, { .vop_ioctl = fifo_ioctl },
129 129 VOPNAME_GETATTR, { .vop_getattr = fifo_getattr },
130 130 VOPNAME_SETATTR, { .vop_setattr = fifo_setattr },
131 131 VOPNAME_ACCESS, { .vop_access = fifo_access },
132 132 VOPNAME_CREATE, { .vop_create = fifo_create },
133 133 VOPNAME_FSYNC, { .vop_fsync = fifo_fsync },
134 134 VOPNAME_INACTIVE, { .vop_inactive = fifo_inactive },
135 135 VOPNAME_FID, { .vop_fid = fifo_fid },
136 136 VOPNAME_RWLOCK, { .vop_rwlock = fifo_rwlock },
137 137 VOPNAME_RWUNLOCK, { .vop_rwunlock = fifo_rwunlock },
138 138 VOPNAME_SEEK, { .vop_seek = fifo_seek },
139 139 VOPNAME_REALVP, { .vop_realvp = fifo_realvp },
140 140 VOPNAME_POLL, { .vop_poll = fifo_poll },
141 141 VOPNAME_PATHCONF, { .vop_pathconf = fifo_pathconf },
142 142 VOPNAME_DISPOSE, { .error = fs_error },
143 143 VOPNAME_SETSECATTR, { .vop_setsecattr = fifo_setsecattr },
144 144 VOPNAME_GETSECATTR, { .vop_getsecattr = fifo_getsecattr },
145 145 NULL, NULL
146 146 };
147 147
148 148 /*
149 149 * Return the fifoinfo structure.
150 150 */
151 151 struct streamtab *
152 152 fifo_getinfo()
153 153 {
154 154 return (&fifoinfo);
155 155 }
156 156
157 157 /*
158 158 * Trusted Extensions enforces a restrictive policy for
159 159 * writing via cross-zone named pipes. A privileged global
160 160 * zone process may expose a named pipe by loopback mounting
161 161 * it from a lower-level zone to a higher-level zone. The
162 162 * kernel-enforced mount policy for lofs mounts ensures
163 163 * that such mounts are read-only in the higher-level
164 164 * zone. But this is not sufficient to prevent writing
165 165 * down via fifos. This function prevents writing down
166 166 * by comparing the zone of the process which is requesting
167 167 * write access with the zone owning the named pipe rendezvous.
168 168 * For write access the zone of the named pipe must equal the
169 169 * zone of the writing process. Writing up is possible since
170 170 * the named pipe can be opened for read by a process in a
171 171 * higher level zone.
172 172 *
173 173 * An exception is made for the global zone to support trusted
174 174 * processes which enforce their own data flow policies.
175 175 */
176 176 static boolean_t
177 177 tsol_fifo_access(vnode_t *vp, int flag, cred_t *crp)
178 178 {
179 179 fifonode_t *fnp = VTOF(vp);
180 180
181 181 if (is_system_labeled() &&
182 182 (flag & FWRITE) &&
183 183 (!(fnp->fn_flag & ISPIPE))) {
184 184 zone_t *proc_zone;
185 185
186 186 proc_zone = crgetzone(crp);
187 187 if (proc_zone != global_zone) {
188 188 char vpath[MAXPATHLEN];
189 189 zone_t *fifo_zone;
190 190
191 191 /*
192 192 * Get the pathname and use it to find
193 193 * the zone of the fifo.
194 194 */
195 195 if (vnodetopath(rootdir, vp, vpath, sizeof (vpath),
196 196 kcred) == 0) {
197 197 fifo_zone = zone_find_by_path(vpath);
198 198 zone_rele(fifo_zone);
199 199
200 200 if (fifo_zone != global_zone &&
201 201 fifo_zone != proc_zone) {
202 202 return (B_FALSE);
203 203 }
204 204 } else {
205 205 return (B_FALSE);
206 206 }
207 207 }
208 208 }
209 209 return (B_TRUE);
210 210 }
211 211
212 212 /*
213 213 * Open and stream a FIFO.
214 214 * If this is the first open of the file (FIFO is not streaming),
215 215 * initialize the fifonode and attach a stream to the vnode.
216 216 *
217 217 * Each end of a fifo must be synchronized with the other end.
218 218 * If not, the mated end may complete an open, I/O, close sequence
219 219 * before the end waiting in open ever wakes up.
220 220 * Note: namefs pipes come through this routine too.
221 221 */
222 222 int
223 223 fifo_open(vnode_t **vpp, int flag, cred_t *crp, caller_context_t *ct)
224 224 {
225 225 vnode_t *vp = *vpp;
226 226 fifonode_t *fnp = VTOF(vp);
227 227 fifolock_t *fn_lock = fnp->fn_lock;
228 228 int error;
229 229
230 230 ASSERT(vp->v_type == VFIFO);
231 231 ASSERT(vn_matchops(vp, fifo_vnodeops));
232 232
233 233 if (!tsol_fifo_access(vp, flag, crp))
234 234 return (EACCES);
235 235
236 236 mutex_enter(&fn_lock->flk_lock);
237 237 /*
238 238 * If we are the first reader, wake up any writers that
239 239 * may be waiting around. wait for all of them to
240 240 * wake up before proceeding (i.e. fn_wsynccnt == 0)
241 241 */
242 242 if (flag & FREAD) {
243 243 fnp->fn_rcnt++; /* record reader present */
244 244 if (! (fnp->fn_flag & ISPIPE))
245 245 fnp->fn_rsynccnt++; /* record reader in open */
246 246 }
247 247
248 248 /*
249 249 * If we are the first writer, wake up any readers that
250 250 * may be waiting around. wait for all of them to
251 251 * wake up before proceeding (i.e. fn_rsynccnt == 0)
252 252 */
253 253 if (flag & FWRITE) {
254 254 fnp->fn_wcnt++; /* record writer present */
255 255 if (! (fnp->fn_flag & ISPIPE))
256 256 fnp->fn_wsynccnt++; /* record writer in open */
257 257 }
258 258 /*
259 259 * fifo_stropen will take care of twisting the queues on the first
260 260 * open. The 1 being passed in means twist the queues on the first
261 261 * open.
262 262 */
263 263 error = fifo_stropen(vpp, flag, crp, 1, 1);
264 264 /*
265 265 * fifo_stropen() could have replaced vpp
266 266 * since fifo's are the only thing we need to sync up,
267 267 * everything else just returns;
268 268 * Note: don't need to hold lock since ISPIPE can't change
269 269 * and both old and new vp need to be pipes
270 270 */
271 271 ASSERT(MUTEX_HELD(&VTOF(*vpp)->fn_lock->flk_lock));
272 272 if (fnp->fn_flag & ISPIPE) {
273 273 ASSERT(VTOF(*vpp)->fn_flag & ISPIPE);
274 274 ASSERT(VTOF(*vpp)->fn_rsynccnt == 0);
275 275 ASSERT(VTOF(*vpp)->fn_rsynccnt == 0);
276 276 /*
277 277 * XXX note: should probably hold locks, but
278 278 * These values should not be changing
279 279 */
280 280 ASSERT(fnp->fn_rsynccnt == 0);
281 281 ASSERT(fnp->fn_wsynccnt == 0);
282 282 mutex_exit(&VTOF(*vpp)->fn_lock->flk_lock);
283 283 return (error);
284 284 }
285 285 /*
286 286 * vp can't change for FIFOS
287 287 */
288 288 ASSERT(vp == *vpp);
289 289 /*
290 290 * If we are opening for read (or writer)
291 291 * indicate that the reader (or writer) is done with open
292 292 * if there is a writer (or reader) waiting for us, wake them up
293 293 * and indicate that at least 1 read (or write) open has occurred
294 294 * this is need in the event the read (or write) side closes
295 295 * before the writer (or reader) has a chance to wake up
296 296 * i.e. it sees that a reader (or writer) was once there
297 297 */
298 298 if (flag & FREAD) {
299 299 fnp->fn_rsynccnt--; /* reader done with open */
300 300 if (fnp->fn_flag & FIFOSYNC) {
301 301 /*
302 302 * This indicates that a read open has occurred
303 303 * Only need to set if writer is actually asleep
304 304 * Flag will be consumed by writer.
305 305 */
306 306 fnp->fn_flag |= FIFOROCR;
307 307 cv_broadcast(&fnp->fn_wait_cv);
308 308 }
309 309 }
310 310 if (flag & FWRITE) {
311 311 fnp->fn_wsynccnt--; /* writer done with open */
312 312 if (fnp->fn_flag & FIFOSYNC) {
313 313 /*
314 314 * This indicates that a write open has occurred
315 315 * Only need to set if reader is actually asleep
316 316 * Flag will be consumed by reader.
317 317 */
318 318 fnp->fn_flag |= FIFOWOCR;
319 319 cv_broadcast(&fnp->fn_wait_cv);
320 320 }
321 321 }
322 322
323 323 fnp->fn_flag &= ~FIFOSYNC;
324 324
325 325 /*
326 326 * errors don't wait around.. just return
327 327 * Note: XXX other end will wake up and continue despite error.
328 328 * There is no defined semantic on the correct course of option
329 329 * so we do what we've done in the past
330 330 */
331 331 if (error != 0) {
332 332 mutex_exit(&fnp->fn_lock->flk_lock);
333 333 goto done;
334 334 }
335 335 ASSERT(fnp->fn_rsynccnt <= fnp->fn_rcnt);
336 336 ASSERT(fnp->fn_wsynccnt <= fnp->fn_wcnt);
337 337 /*
338 338 * FIFOWOCR (or FIFOROCR) indicates that the writer (or reader)
339 339 * has woken us up and is done with open (this way, if the other
340 340 * end has made it to close, we don't block forever in open)
341 341 * fn_wnct == fn_wsynccnt (or fn_rcnt == fn_rsynccnt) indicates
342 342 * that no writer (or reader) has yet made it through open
343 343 * This has the side benefit of that the first
344 344 * reader (or writer) will wait until the other end finishes open
345 345 */
346 346 if (flag & FREAD) {
347 347 while ((fnp->fn_flag & FIFOWOCR) == 0 &&
348 348 fnp->fn_wcnt == fnp->fn_wsynccnt) {
349 349 if (flag & (FNDELAY|FNONBLOCK)) {
350 350 mutex_exit(&fnp->fn_lock->flk_lock);
351 351 goto done;
352 352 }
353 353 fnp->fn_insync++;
354 354 fnp->fn_flag |= FIFOSYNC;
355 355 if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
356 356 &fnp->fn_lock->flk_lock)) {
357 357 /*
358 358 * Last reader to wakeup clear writer
359 359 * Clear both writer and reader open
360 360 * occurred flag incase other end is O_RDWR
361 361 */
362 362 if (--fnp->fn_insync == 0 &&
363 363 fnp->fn_flag & FIFOWOCR) {
364 364 fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
365 365 }
366 366 mutex_exit(&fnp->fn_lock->flk_lock);
367 367 (void) fifo_close(*vpp, flag, 1, 0, crp, ct);
368 368 error = EINTR;
369 369 goto done;
370 370 }
371 371 /*
372 372 * Last reader to wakeup clear writer open occurred flag
373 373 * Clear both writer and reader open occurred flag
374 374 * incase other end is O_RDWR
375 375 */
376 376 if (--fnp->fn_insync == 0 &&
377 377 fnp->fn_flag & FIFOWOCR) {
378 378 fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
379 379 break;
380 380 }
381 381 }
382 382 } else if (flag & FWRITE) {
383 383 while ((fnp->fn_flag & FIFOROCR) == 0 &&
384 384 fnp->fn_rcnt == fnp->fn_rsynccnt) {
385 385 if ((flag & (FNDELAY|FNONBLOCK)) && fnp->fn_rcnt == 0) {
386 386 mutex_exit(&fnp->fn_lock->flk_lock);
387 387 (void) fifo_close(*vpp, flag, 1, 0, crp, ct);
388 388 error = ENXIO;
389 389 goto done;
390 390 }
391 391 fnp->fn_flag |= FIFOSYNC;
392 392 fnp->fn_insync++;
393 393 if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
394 394 &fnp->fn_lock->flk_lock)) {
395 395 /*
396 396 * Last writer to wakeup clear
397 397 * Clear both writer and reader open
398 398 * occurred flag in case other end is O_RDWR
399 399 */
400 400 if (--fnp->fn_insync == 0 &&
401 401 (fnp->fn_flag & FIFOROCR) != 0) {
402 402 fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
403 403 }
404 404 mutex_exit(&fnp->fn_lock->flk_lock);
405 405 (void) fifo_close(*vpp, flag, 1, 0, crp, ct);
406 406 error = EINTR;
407 407 goto done;
408 408 }
409 409 /*
410 410 * Last writer to wakeup clear reader open occurred flag
411 411 * Clear both writer and reader open
412 412 * occurred flag in case other end is O_RDWR
413 413 */
414 414 if (--fnp->fn_insync == 0 &&
415 415 (fnp->fn_flag & FIFOROCR) != 0) {
416 416 fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
417 417 break;
418 418 }
419 419 }
420 420 }
421 421 mutex_exit(&fn_lock->flk_lock);
422 422 done:
423 423 return (error);
424 424 }
425 425
426 426 /*
427 427 * Close down a stream.
428 428 * Call cleanlocks() and strclean() on every close.
429 429 * For last close send hangup message and force
430 430 * the other end of a named pipe to be unmounted.
431 431 * Mount guarantees that the mounted end will only call fifo_close()
432 432 * with a count of 1 when the unmount occurs.
433 433 * This routine will close down one end of a pipe or FIFO
434 434 * and free the stream head via strclose()
435 435 */
436 436 /*ARGSUSED*/
437 437 int
438 438 fifo_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *crp,
439 439 caller_context_t *ct)
440 440 {
441 441 fifonode_t *fnp = VTOF(vp);
442 442 fifonode_t *fn_dest = fnp->fn_dest;
443 443 int error = 0;
444 444 fifolock_t *fn_lock = fnp->fn_lock;
445 445 queue_t *sd_wrq;
446 446 vnode_t *fn_dest_vp;
447 447 int senthang = 0;
448 448
449 449 ASSERT(vp->v_stream != NULL);
450 450 /*
451 451 * clean locks and clear events.
452 452 */
453 453 (void) cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
454 454 cleanshares(vp, ttoproc(curthread)->p_pid);
455 455 strclean(vp);
456 456
457 457 /*
458 458 * If a file still has the pipe/FIFO open, return.
459 459 */
460 460 if (count > 1)
461 461 return (0);
462 462
463 463
464 464 sd_wrq = strvp2wq(vp);
465 465 mutex_enter(&fn_lock->flk_lock);
466 466
467 467 /*
468 468 * wait for pending opens to finish up
469 469 * note: this also has the side effect of single threading closes
470 470 */
471 471 while (fn_lock->flk_ocsync)
472 472 cv_wait(&fn_lock->flk_wait_cv, &fn_lock->flk_lock);
473 473
474 474 fn_lock->flk_ocsync = 1;
475 475
476 476 if (flag & FREAD) {
477 477 fnp->fn_rcnt--;
478 478 }
479 479 /*
480 480 * If we are last writer wake up sleeping readers
481 481 * (They'll figure out that there are no more writers
482 482 * and do the right thing)
483 483 * send hangup down stream so that stream head will do the
484 484 * right thing.
485 485 */
486 486 if (flag & FWRITE) {
487 487 if (--fnp->fn_wcnt == 0 && fn_dest->fn_rcnt > 0) {
488 488 if ((fn_dest->fn_flag & (FIFOFAST | FIFOWANTR)) ==
489 489 (FIFOFAST | FIFOWANTR)) {
490 490 /*
491 491 * While we're at it, clear FIFOWANTW too
492 492 * Wake up any sleeping readers or
493 493 * writers.
494 494 */
495 495 fn_dest->fn_flag &= ~(FIFOWANTR | FIFOWANTW);
496 496 cv_broadcast(&fn_dest->fn_wait_cv);
497 497 }
498 498 /*
499 499 * This is needed incase the other side
500 500 * was opened non-blocking. It is the
501 501 * only way we can tell that wcnt is 0 because
502 502 * of close instead of never having a writer
503 503 */
504 504 if (!(fnp->fn_flag & ISPIPE))
505 505 fnp->fn_flag |= FIFOCLOSE;
506 506 /*
507 507 * Note: sending hangup effectively shuts down
508 508 * both reader and writer at other end.
509 509 */
510 510 (void) putnextctl_wait(sd_wrq, M_HANGUP);
511 511 senthang = 1;
512 512 }
513 513 }
514 514
515 515 /*
516 516 * For FIFOs we need to indicate to stream head that last reader
517 517 * has gone away so that an error is generated
518 518 * Pipes just need to wake up the other end so that it can
519 519 * notice this end has gone away.
520 520 */
521 521
522 522 if (fnp->fn_rcnt == 0 && fn_dest->fn_wcnt > 0) {
523 523 if ((fn_dest->fn_flag & (FIFOFAST | FIFOWANTW)) ==
524 524 (FIFOFAST | FIFOWANTW)) {
525 525 /*
526 526 * wake up any sleeping writers
527 527 */
528 528 fn_dest->fn_flag &= ~FIFOWANTW;
529 529 cv_broadcast(&fn_dest->fn_wait_cv);
530 530 }
531 531 }
532 532
533 533 /*
534 534 * if there are still processes with this FIFO open
535 535 * clear open/close sync flag
536 536 * and just return;
537 537 */
538 538 if (--fnp->fn_open > 0) {
539 539 ASSERT((fnp->fn_rcnt + fnp->fn_wcnt) != 0);
540 540 fn_lock->flk_ocsync = 0;
541 541 cv_broadcast(&fn_lock->flk_wait_cv);
542 542 mutex_exit(&fn_lock->flk_lock);
543 543 return (0);
544 544 }
545 545
546 546 /*
547 547 * Need to send HANGUP if other side is still open
548 548 * (fnp->fn_rcnt or fnp->fn_wcnt may not be zero (some thread
549 549 * on this end of the pipe may still be in fifo_open())
550 550 *
551 551 * Note: we can get here with fn_rcnt and fn_wcnt != 0 if some
552 552 * thread is blocked somewhere in the fifo_open() path prior to
553 553 * fifo_stropen() incrementing fn_open. This can occur for
554 554 * normal FIFOs as well as named pipes. fn_rcnt and
555 555 * fn_wcnt only indicate attempts to open. fn_open indicates
556 556 * successful opens. Partially opened FIFOs should proceed
557 557 * normally; i.e. they will appear to be new opens. Partially
↓ open down ↓ |
525 lines elided |
↑ open up ↑ |
558 558 * opened pipes will probably fail.
559 559 */
560 560
561 561 if (fn_dest->fn_open && senthang == 0)
562 562 (void) putnextctl_wait(sd_wrq, M_HANGUP);
563 563
564 564
565 565 /*
566 566 * If this a pipe and this is the first end to close,
567 567 * then we have a bit of cleanup work to do.
568 - * Mark both ends of pipe as closed.
569 - * Wake up anybody blocked at the other end and for named pipes,
568 + * Mark both ends of pipe as closed.
569 + * Wake up anybody blocked at the other end and for named pipes,
570 570 * Close down this end of the stream
571 571 * Allow other opens/closes to continue
572 - * force an unmount of other end.
572 + * force an unmount of other end.
573 573 * Otherwise if this is last close,
574 574 * flush messages,
575 575 * close down the stream
576 576 * allow other opens/closes to continue
577 577 */
578 578 fnp->fn_flag &= ~FIFOISOPEN;
579 579 if ((fnp->fn_flag & ISPIPE) && !(fnp->fn_flag & FIFOCLOSE)) {
580 580 fnp->fn_flag |= FIFOCLOSE;
581 581 fn_dest->fn_flag |= FIFOCLOSE;
582 582 if (fnp->fn_flag & FIFOFAST)
583 583 fifo_fastflush(fnp);
584 584 if (vp->v_stream != NULL) {
585 585 mutex_exit(&fn_lock->flk_lock);
586 586 (void) strclose(vp, flag, crp);
587 587 mutex_enter(&fn_lock->flk_lock);
588 588 }
589 589 cv_broadcast(&fn_dest->fn_wait_cv);
590 590 /*
591 591 * allow opens and closes to proceed
592 592 * Since this end is now closed down, any attempt
593 593 * to do anything with this end will fail
594 594 */
595 595 fn_lock->flk_ocsync = 0;
596 596 cv_broadcast(&fn_lock->flk_wait_cv);
597 597 fn_dest_vp = FTOV(fn_dest);
598 598 /*
599 599 * if other end of pipe has been opened and it's
600 600 * a named pipe, unmount it
601 601 */
602 602 if (fn_dest_vp->v_stream &&
603 603 (fn_dest_vp->v_stream->sd_flag & STRMOUNT)) {
604 604 /*
605 605 * We must hold the destination vnode because
606 606 * nm_unmountall() causes close to be called
607 607 * for the other end of named pipe. This
608 608 * could free the vnode before we are ready.
609 609 */
610 610 VN_HOLD(fn_dest_vp);
611 611 mutex_exit(&fn_lock->flk_lock);
612 612 error = nm_unmountall(fn_dest_vp, crp);
613 613 ASSERT(error == 0);
614 614 VN_RELE(fn_dest_vp);
615 615 } else {
616 616 ASSERT(vp->v_count >= 1);
617 617 mutex_exit(&fn_lock->flk_lock);
618 618 }
619 619 } else {
620 620 if (fnp->fn_flag & FIFOFAST)
621 621 fifo_fastflush(fnp);
622 622 #if DEBUG
623 623 fn_dest_vp = FTOV(fn_dest);
624 624 if (fn_dest_vp->v_stream)
625 625 ASSERT((fn_dest_vp->v_stream->sd_flag & STRMOUNT) == 0);
626 626 #endif
627 627 if (vp->v_stream != NULL) {
628 628 mutex_exit(&fn_lock->flk_lock);
629 629 (void) strclose(vp, flag, crp);
630 630 mutex_enter(&fn_lock->flk_lock);
631 631 }
632 632 fn_lock->flk_ocsync = 0;
633 633 cv_broadcast(&fn_lock->flk_wait_cv);
634 634 cv_broadcast(&fn_dest->fn_wait_cv);
635 635 mutex_exit(&fn_lock->flk_lock);
636 636 }
637 637 return (error);
638 638 }
639 639
640 640 /*
641 641 * Read from a pipe or FIFO.
642 642 * return 0 if....
643 643 * (1) user read request is 0 or no stream
644 644 * (2) broken pipe with no data
645 645 * (3) write-only FIFO with no data
646 646 * (4) no data and FNDELAY flag is set.
647 647 * Otherwise return
648 648 * EAGAIN if FNONBLOCK is set and no data to read
649 649 * EINTR if signal received while waiting for data
650 650 *
651 651 * While there is no data to read....
652 652 * - if the NDELAY/NONBLOCK flag is set, return 0/EAGAIN.
653 653 * - wait for a write.
654 654 *
655 655 */
656 656 /*ARGSUSED*/
657 657
658 658 static int
659 659 fifo_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *crp,
660 660 caller_context_t *ct)
661 661 {
662 662 fifonode_t *fnp = VTOF(vp);
663 663 fifonode_t *fn_dest;
664 664 fifolock_t *fn_lock = fnp->fn_lock;
665 665 int error = 0;
666 666 mblk_t *bp;
667 667
668 668 ASSERT(vp->v_stream != NULL);
669 669 if (uiop->uio_resid == 0)
670 670 return (0);
671 671
672 672 mutex_enter(&fn_lock->flk_lock);
673 673
674 674 TRACE_2(TR_FAC_FIFO, TR_FIFOREAD_IN, "fifo_read in:%p fnp %p", vp, fnp);
675 675
676 676 if (! (fnp->fn_flag & FIFOFAST))
677 677 goto stream_mode;
678 678
679 679 fn_dest = fnp->fn_dest;
680 680 /*
681 681 * Check for data on our input queue
682 682 */
683 683
684 684 while (fnp->fn_count == 0) {
685 685 /*
686 686 * No data on first attempt and no writer, then EOF
687 687 */
688 688 if (fn_dest->fn_wcnt == 0 || fn_dest->fn_rcnt == 0) {
689 689 mutex_exit(&fn_lock->flk_lock);
690 690 return (0);
691 691 }
692 692 /*
693 693 * no data found.. if non-blocking, return EAGAIN
694 694 * otherwise 0.
695 695 */
696 696 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
697 697 mutex_exit(&fn_lock->flk_lock);
698 698 if (uiop->uio_fmode & FNONBLOCK)
699 699 return (EAGAIN);
700 700 return (0);
701 701 }
702 702
703 703 /*
704 704 * Note: FIFOs can get here with FIFOCLOSE set if
705 705 * write side is in the middle of opeining after
706 706 * it once closed. Pipes better not have FIFOCLOSE set
707 707 */
708 708 ASSERT((fnp->fn_flag & (ISPIPE|FIFOCLOSE)) !=
709 709 (ISPIPE|FIFOCLOSE));
710 710 /*
711 711 * wait for data
712 712 */
713 713 fnp->fn_flag |= FIFOWANTR;
714 714
715 715 TRACE_1(TR_FAC_FIFO, TR_FIFOREAD_WAIT, "fiforead wait: %p", vp);
716 716
717 717 if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
718 718 &fn_lock->flk_lock)) {
719 719 error = EINTR;
720 720 goto done;
721 721 }
722 722
723 723 TRACE_1(TR_FAC_FIFO, TR_FIFOREAD_WAKE,
724 724 "fiforead awake: %p", vp);
725 725
726 726 /*
727 727 * check to make sure we are still in fast mode
728 728 */
729 729 if (!(fnp->fn_flag & FIFOFAST))
730 730 goto stream_mode;
731 731 }
732 732
733 733 ASSERT(fnp->fn_mp != NULL);
734 734
735 735 /* For pipes copy should not bypass cache */
736 736 uiop->uio_extflg |= UIO_COPY_CACHED;
737 737
738 738 do {
739 739 int bpsize = MBLKL(fnp->fn_mp);
740 740 int uiosize = MIN(bpsize, uiop->uio_resid);
741 741
742 742 error = uiomove(fnp->fn_mp->b_rptr, uiosize, UIO_READ, uiop);
743 743 if (error != 0)
744 744 break;
745 745
746 746 fnp->fn_count -= uiosize;
747 747
748 748 if (bpsize <= uiosize) {
749 749 bp = fnp->fn_mp;
750 750 fnp->fn_mp = fnp->fn_mp->b_cont;
751 751 freeb(bp);
752 752
753 753 if (uiop->uio_resid == 0)
754 754 break;
755 755
756 756 while (fnp->fn_mp == NULL && fn_dest->fn_wwaitcnt > 0) {
757 757 ASSERT(fnp->fn_count == 0);
758 758
759 759 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
760 760 goto trywake;
761 761
762 762 /*
763 763 * We've consumed all available data but there
764 764 * are threads waiting to write more, let them
765 765 * proceed before bailing.
766 766 */
767 767
768 768 fnp->fn_flag |= FIFOWANTR;
769 769 fifo_wakewriter(fn_dest, fn_lock);
770 770
771 771 if (!cv_wait_sig(&fnp->fn_wait_cv,
772 772 &fn_lock->flk_lock))
773 773 goto trywake;
774 774
775 775 if (!(fnp->fn_flag & FIFOFAST))
776 776 goto stream_mode;
777 777 }
778 778 } else {
779 779 fnp->fn_mp->b_rptr += uiosize;
780 780 ASSERT(uiop->uio_resid == 0);
781 781 }
782 782 } while (uiop->uio_resid != 0 && fnp->fn_mp != NULL);
783 783
784 784 trywake:
785 785 ASSERT(msgdsize(fnp->fn_mp) == fnp->fn_count);
786 786
787 787 /*
788 788 * wake up any blocked writers, processes
789 789 * sleeping on POLLWRNORM, or processes waiting for SIGPOLL
790 790 * Note: checking for fn_count < Fifohiwat emulates
791 791 * STREAMS functionality when low water mark is 0
792 792 */
793 793 if (fn_dest->fn_flag & (FIFOWANTW | FIFOHIWATW) &&
794 794 fnp->fn_count < Fifohiwat) {
795 795 fifo_wakewriter(fn_dest, fn_lock);
796 796 }
797 797 goto done;
798 798
799 799 /*
800 800 * FIFO is in streams mode.. let the stream head handle it
801 801 */
802 802 stream_mode:
803 803
804 804 mutex_exit(&fn_lock->flk_lock);
805 805 TRACE_1(TR_FAC_FIFO,
806 806 TR_FIFOREAD_STREAM, "fifo_read stream_mode:%p", vp);
807 807
808 808 error = strread(vp, uiop, crp);
809 809
810 810 mutex_enter(&fn_lock->flk_lock);
811 811
812 812 done:
813 813 /*
814 814 * vnode update access time
815 815 */
816 816 if (error == 0) {
817 817 time_t now = gethrestime_sec();
818 818
819 819 if (fnp->fn_flag & ISPIPE)
820 820 fnp->fn_dest->fn_atime = now;
821 821 fnp->fn_atime = now;
822 822 }
823 823 TRACE_2(TR_FAC_FIFO, TR_FIFOREAD_OUT,
824 824 "fifo_read out:%p error %d", vp, error);
825 825 mutex_exit(&fn_lock->flk_lock);
826 826 return (error);
827 827 }
828 828
829 829 /*
830 830 * send SIGPIPE and return EPIPE if ...
831 831 * (1) broken pipe (essentially, reader is gone)
832 832 * (2) FIFO is not open for reading
833 833 * return 0 if...
834 834 * (1) no stream
835 835 * (2) user write request is for 0 bytes and SW_SNDZERO is not set
836 836 * Note: SW_SNDZERO can't be set in fast mode
837 837 * While the stream is flow controlled....
838 838 * - if the NDELAY/NONBLOCK flag is set, return 0/EAGAIN.
839 839 * - unlock the fifonode and sleep waiting for a reader.
840 840 * - if a pipe and it has a mate, sleep waiting for its mate
841 841 * to read.
842 842 */
843 843 /*ARGSUSED*/
844 844 static int
845 845 fifo_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *crp,
846 846 caller_context_t *ct)
847 847 {
848 848 struct fifonode *fnp, *fn_dest;
849 849 fifolock_t *fn_lock;
850 850 struct stdata *stp;
851 851 int error = 0;
852 852 int write_size;
853 853 int size;
854 854 int fmode;
855 855 mblk_t *bp;
856 856 boolean_t hotread;
857 857
858 858 ASSERT(vp->v_stream);
859 859 uiop->uio_loffset = 0;
860 860 stp = vp->v_stream;
861 861
862 862 /*
863 863 * remember original number of bytes requested. Used to determine if
864 864 * we actually have written anything at all
865 865 */
866 866 write_size = uiop->uio_resid;
867 867
868 868 /*
869 869 * only send zero-length messages if SW_SNDZERO is set
870 870 * Note: we will be in streams mode if SW_SNDZERO is set
871 871 * XXX this streams interface should not be exposed
872 872 */
873 873 if ((write_size == 0) && !(stp->sd_wput_opt & SW_SNDZERO))
874 874 return (0);
875 875
876 876 fnp = VTOF(vp);
877 877 fn_lock = fnp->fn_lock;
878 878 fn_dest = fnp->fn_dest;
879 879
880 880 mutex_enter(&fn_lock->flk_lock);
881 881
882 882 TRACE_3(TR_FAC_FIFO, TR_FIFOWRITE_IN,
883 883 "fifo_write in:%p fnp %p size %d", vp, fnp, write_size);
884 884
885 885 /*
886 886 * oops, no readers, error
887 887 */
888 888 if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
889 889 goto epipe;
890 890 }
891 891
892 892 /*
893 893 * if we are not in fast mode, let streams handle it
894 894 */
895 895 if (!(fnp->fn_flag & FIFOFAST))
896 896 goto stream_mode;
897 897
898 898 fmode = uiop->uio_fmode & (FNDELAY|FNONBLOCK);
899 899
900 900 /* For pipes copy should not bypass cache */
901 901 uiop->uio_extflg |= UIO_COPY_CACHED;
902 902
903 903 do {
904 904 /*
905 905 * check to make sure we are not over high water mark
906 906 */
907 907 while (fn_dest->fn_count >= Fifohiwat) {
908 908 /*
909 909 * Indicate that we have gone over high
910 910 * water mark
911 911 */
912 912 /*
913 913 * if non-blocking, return
914 914 * only happens first time through loop
915 915 */
916 916 if (fmode) {
917 917 fnp->fn_flag |= FIFOHIWATW;
918 918 if (uiop->uio_resid == write_size) {
919 919 mutex_exit(&fn_lock->flk_lock);
920 920 if (fmode & FNDELAY)
921 921 return (0);
922 922 else
923 923 return (EAGAIN);
924 924 }
925 925 goto done;
926 926 }
927 927
928 928 /*
929 929 * wait for things to drain
930 930 */
931 931 fnp->fn_flag |= FIFOWANTW;
932 932 fnp->fn_wwaitcnt++;
933 933 TRACE_1(TR_FAC_FIFO, TR_FIFOWRITE_WAIT,
934 934 "fifo_write wait: %p", vp);
935 935 if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
936 936 &fn_lock->flk_lock)) {
937 937 error = EINTR;
938 938 fnp->fn_wwaitcnt--;
939 939 fifo_wakereader(fn_dest, fn_lock);
940 940 goto done;
941 941 }
942 942 fnp->fn_wwaitcnt--;
943 943
944 944 TRACE_1(TR_FAC_FIFO, TR_FIFOWRITE_WAKE,
945 945 "fifo_write wake: %p", vp);
946 946
947 947 /*
948 948 * check to make sure we're still in fast mode
949 949 */
950 950 if (!(fnp->fn_flag & FIFOFAST))
951 951 goto stream_mode;
952 952
953 953 /*
954 954 * make sure readers didn't go away
955 955 */
956 956 if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
957 957 goto epipe;
958 958 }
959 959 }
960 960 /*
961 961 * If the write will put us over the high water mark,
962 962 * then we must break the message up into PIPE_BUF
963 963 * chunks to stay compliant with STREAMS
964 964 */
965 965 if (uiop->uio_resid + fn_dest->fn_count > Fifohiwat)
966 966 size = MIN(uiop->uio_resid, PIPE_BUF);
967 967 else
968 968 size = uiop->uio_resid;
969 969
970 970 /*
971 971 * We don't need to hold flk_lock across the allocb() and
972 972 * uiomove(). However, on a multiprocessor machine where both
973 973 * the reader and writer thread are on cpu's, we must be
974 974 * careful to only drop the lock if there's data to be read.
975 975 * This forces threads entering fifo_read() to spin or block
976 976 * on flk_lock, rather than acquiring flk_lock only to
977 977 * discover there's no data to read and being forced to go
978 978 * back to sleep, only to be woken up microseconds later by
979 979 * this writer thread.
980 980 */
981 981 hotread = fn_dest->fn_count > 0;
982 982 if (hotread) {
983 983 if (!fifo_stayfast_enter(fnp))
984 984 goto stream_mode;
985 985 mutex_exit(&fn_lock->flk_lock);
986 986 }
987 987
988 988 ASSERT(size != 0);
989 989 /*
990 990 * Align the mblk with the user data so that
991 991 * copying in the data can take advantage of
992 992 * the double word alignment
993 993 */
994 994 if ((bp = allocb(size + 8, BPRI_MED)) == NULL) {
995 995 if (!hotread)
996 996 mutex_exit(&fn_lock->flk_lock);
997 997
998 998 error = strwaitbuf(size, BPRI_MED);
999 999
1000 1000 mutex_enter(&fn_lock->flk_lock);
1001 1001
1002 1002 if (hotread) {
1003 1003 /*
1004 1004 * As we dropped the mutex for a moment, we
1005 1005 * need to wake up any thread waiting to be
1006 1006 * allowed to go from fast mode to stream mode.
1007 1007 */
1008 1008 fifo_stayfast_exit(fnp);
1009 1009 }
1010 1010 if (error != 0) {
1011 1011 goto done;
1012 1012 }
1013 1013 /*
1014 1014 * check to make sure we're still in fast mode
1015 1015 */
1016 1016 if (!(fnp->fn_flag & FIFOFAST))
1017 1017 goto stream_mode;
1018 1018
1019 1019 /*
1020 1020 * make sure readers didn't go away
1021 1021 */
1022 1022 if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
1023 1023 goto epipe;
1024 1024 }
1025 1025 /*
1026 1026 * some other thread could have gotten in
1027 1027 * need to go back and check hi water mark
1028 1028 */
1029 1029 continue;
1030 1030 }
1031 1031 bp->b_rptr += ((uintptr_t)uiop->uio_iov->iov_base & 0x7);
1032 1032 bp->b_wptr = bp->b_rptr + size;
1033 1033 error = uiomove((caddr_t)bp->b_rptr, size, UIO_WRITE, uiop);
1034 1034 if (hotread) {
1035 1035 mutex_enter(&fn_lock->flk_lock);
1036 1036 /*
1037 1037 * As we dropped the mutex for a moment, we need to:
1038 1038 * - wake up any thread waiting to be allowed to go
1039 1039 * from fast mode to stream mode,
1040 1040 * - make sure readers didn't go away.
1041 1041 */
1042 1042 fifo_stayfast_exit(fnp);
1043 1043 if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
1044 1044 freeb(bp);
1045 1045 goto epipe;
1046 1046 }
1047 1047 }
1048 1048
1049 1049 if (error != 0) {
1050 1050 freeb(bp);
1051 1051 goto done;
1052 1052 }
1053 1053
1054 1054 fn_dest->fn_count += size;
1055 1055 if (fn_dest->fn_mp != NULL) {
1056 1056 fn_dest->fn_tail->b_cont = bp;
1057 1057 fn_dest->fn_tail = bp;
1058 1058 } else {
1059 1059 fn_dest->fn_mp = fn_dest->fn_tail = bp;
1060 1060 /*
1061 1061 * This is the first bit of data; wake up any sleeping
1062 1062 * readers, processes blocked in poll, and those
1063 1063 * expecting a SIGPOLL.
1064 1064 */
1065 1065 fifo_wakereader(fn_dest, fn_lock);
1066 1066 }
1067 1067 } while (uiop->uio_resid != 0);
1068 1068
1069 1069 goto done;
1070 1070
1071 1071 stream_mode:
1072 1072 /*
1073 1073 * streams mode
1074 1074 * let the stream head handle the write
1075 1075 */
1076 1076 ASSERT(MUTEX_HELD(&fn_lock->flk_lock));
1077 1077
1078 1078 mutex_exit(&fn_lock->flk_lock);
1079 1079 TRACE_1(TR_FAC_FIFO,
1080 1080 TR_FIFOWRITE_STREAM, "fifo_write stream_mode:%p", vp);
1081 1081
1082 1082 error = strwrite(vp, uiop, crp);
1083 1083
1084 1084 mutex_enter(&fn_lock->flk_lock);
1085 1085
1086 1086 done:
1087 1087 /*
1088 1088 * update vnode modification and change times
1089 1089 * make sure there were no errors and some data was transferred
1090 1090 */
1091 1091 if (error == 0 && write_size != uiop->uio_resid) {
1092 1092 time_t now = gethrestime_sec();
1093 1093
1094 1094 if (fnp->fn_flag & ISPIPE) {
1095 1095 fn_dest->fn_mtime = fn_dest->fn_ctime = now;
1096 1096 }
1097 1097 fnp->fn_mtime = fnp->fn_ctime = now;
1098 1098 } else if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
1099 1099 goto epipe;
1100 1100 }
1101 1101 TRACE_3(TR_FAC_FIFO, TR_FIFOWRITE_OUT,
1102 1102 "fifo_write out: vp %p error %d fnp %p", vp, error, fnp);
1103 1103 mutex_exit(&fn_lock->flk_lock);
1104 1104 return (error);
1105 1105 epipe:
1106 1106 error = EPIPE;
1107 1107 TRACE_3(TR_FAC_FIFO, TR_FIFOWRITE_OUT,
1108 1108 "fifo_write out: vp %p error %d fnp %p", vp, error, fnp);
1109 1109 mutex_exit(&fn_lock->flk_lock);
1110 1110 tsignal(curthread, SIGPIPE);
1111 1111 return (error);
1112 1112 }
1113 1113
1114 1114 /*ARGSUSED6*/
1115 1115 static int
1116 1116 fifo_ioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
1117 1117 int *rvalp, caller_context_t *ct)
1118 1118 {
1119 1119 /*
↓ open down ↓ |
537 lines elided |
↑ open up ↑ |
1120 1120 * Just a quick check
1121 1121 * Once we go to streams mode we don't ever revert back
1122 1122 * So we do this quick check so as not to incur the overhead
1123 1123 * associated with acquiring the lock
1124 1124 */
1125 1125 return ((VTOF(vp)->fn_flag & FIFOFAST) ?
1126 1126 fifo_fastioctl(vp, cmd, arg, mode, cr, rvalp) :
1127 1127 fifo_strioctl(vp, cmd, arg, mode, cr, rvalp));
1128 1128 }
1129 1129
1130 +static inline int
1131 +fifo_ioctl_getpeercred(fifonode_t *fnp, intptr_t arg, int mode)
1132 +{
1133 + k_peercred_t *kp = (k_peercred_t *)arg;
1134 +
1135 + if (mode == FKIOCTL && fnp->fn_pcredp != NULL) {
1136 + crhold(fnp->fn_pcredp);
1137 + kp->pc_cr = fnp->fn_pcredp;
1138 + kp->pc_cpid = fnp->fn_cpid;
1139 + return (0);
1140 + } else {
1141 + return (ENOTSUP);
1142 + }
1143 +}
1144 +
1130 1145 static int
1131 1146 fifo_fastioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
1132 1147 int *rvalp)
1133 1148 {
1134 1149 fifonode_t *fnp = VTOF(vp);
1135 1150 fifonode_t *fn_dest;
1136 1151 int error = 0;
1137 1152 fifolock_t *fn_lock = fnp->fn_lock;
1138 1153 int cnt;
1139 1154
1140 1155 /*
1141 1156 * tty operations not allowed
1142 1157 */
1143 1158 if (((cmd & IOCTYPE) == LDIOC) ||
1144 1159 ((cmd & IOCTYPE) == tIOC) ||
1145 1160 ((cmd & IOCTYPE) == TIOC)) {
1146 1161 return (EINVAL);
1147 1162 }
1148 1163
1149 1164 mutex_enter(&fn_lock->flk_lock);
1150 1165
1151 1166 if (!(fnp->fn_flag & FIFOFAST)) {
1152 1167 goto stream_mode;
1153 1168 }
1154 1169
1155 1170 switch (cmd) {
1156 1171
1157 1172 /*
1158 1173 * Things we can't handle
1159 1174 * These will switch us to streams mode.
1160 1175 */
1161 1176 default:
1162 1177 case I_STR:
1163 1178 case I_SRDOPT:
1164 1179 case I_PUSH:
1165 1180 case I_FDINSERT:
1166 1181 case I_SENDFD:
1167 1182 case I_RECVFD:
1168 1183 case I_E_RECVFD:
1169 1184 case I_ATMARK:
1170 1185 case I_CKBAND:
1171 1186 case I_GETBAND:
1172 1187 case I_SWROPT:
1173 1188 goto turn_fastoff;
1174 1189
1175 1190 /*
1176 1191 * Things that don't do damage
1177 1192 * These things don't adjust the state of the
1178 1193 * stream head (i_setcltime does, but we don't care)
1179 1194 */
1180 1195 case I_FIND:
1181 1196 case I_GETSIG:
1182 1197 case FIONBIO:
1183 1198 case FIOASYNC:
1184 1199 case I_GRDOPT: /* probably should not get this, but no harm */
1185 1200 case I_GWROPT:
1186 1201 case I_LIST:
1187 1202 case I_SETCLTIME:
1188 1203 case I_GETCLTIME:
1189 1204 mutex_exit(&fn_lock->flk_lock);
1190 1205 return (strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp));
1191 1206
1192 1207 case I_CANPUT:
1193 1208 /*
1194 1209 * We can only handle normal band canputs.
1195 1210 * XXX : We could just always go to stream mode; after all
1196 1211 * canput is a streams semantics type thing
1197 1212 */
1198 1213 if (arg != 0) {
1199 1214 goto turn_fastoff;
1200 1215 }
1201 1216 *rvalp = (fnp->fn_dest->fn_count < Fifohiwat) ? 1 : 0;
1202 1217 mutex_exit(&fn_lock->flk_lock);
1203 1218 return (0);
1204 1219
1205 1220 case I_NREAD:
1206 1221 /*
1207 1222 * This may seem a bit silly for non-streams semantics,
1208 1223 * (After all, if they really want a message, they'll
1209 1224 * probably use getmsg() anyway). but it doesn't hurt
1210 1225 */
1211 1226 error = copyout((caddr_t)&fnp->fn_count, (caddr_t)arg,
1212 1227 sizeof (cnt));
1213 1228 if (error == 0) {
1214 1229 *rvalp = (fnp->fn_count == 0) ? 0 : 1;
1215 1230 }
1216 1231 break;
1217 1232
1218 1233 case FIORDCHK:
1219 1234 *rvalp = fnp->fn_count;
1220 1235 break;
1221 1236
1222 1237 case I_PEEK:
1223 1238 {
1224 1239 STRUCT_DECL(strpeek, strpeek);
1225 1240 struct uio uio;
1226 1241 struct iovec iov;
1227 1242 int count;
1228 1243 mblk_t *bp;
1229 1244 int len;
1230 1245
1231 1246 STRUCT_INIT(strpeek, mode);
1232 1247
1233 1248 if (fnp->fn_count == 0) {
1234 1249 *rvalp = 0;
1235 1250 break;
1236 1251 }
1237 1252
1238 1253 error = copyin((caddr_t)arg, STRUCT_BUF(strpeek),
1239 1254 STRUCT_SIZE(strpeek));
1240 1255 if (error)
1241 1256 break;
1242 1257
1243 1258 /*
1244 1259 * can't have any high priority message when in fast mode
1245 1260 */
1246 1261 if (STRUCT_FGET(strpeek, flags) & RS_HIPRI) {
1247 1262 *rvalp = 0;
1248 1263 break;
1249 1264 }
1250 1265
1251 1266 len = STRUCT_FGET(strpeek, databuf.maxlen);
1252 1267 if (len <= 0) {
1253 1268 STRUCT_FSET(strpeek, databuf.len, len);
1254 1269 } else {
1255 1270 iov.iov_base = STRUCT_FGETP(strpeek, databuf.buf);
1256 1271 iov.iov_len = len;
1257 1272 uio.uio_iov = &iov;
1258 1273 uio.uio_iovcnt = 1;
1259 1274 uio.uio_loffset = 0;
1260 1275 uio.uio_segflg = UIO_USERSPACE;
1261 1276 uio.uio_fmode = 0;
1262 1277 /* For pipes copy should not bypass cache */
1263 1278 uio.uio_extflg = UIO_COPY_CACHED;
1264 1279 uio.uio_resid = iov.iov_len;
1265 1280 count = fnp->fn_count;
1266 1281 bp = fnp->fn_mp;
1267 1282 while (count > 0 && uio.uio_resid) {
1268 1283 cnt = MIN(uio.uio_resid, MBLKL(bp));
1269 1284 if ((error = uiomove((char *)bp->b_rptr, cnt,
1270 1285 UIO_READ, &uio)) != 0) {
1271 1286 break;
1272 1287 }
1273 1288 count -= cnt;
1274 1289 bp = bp->b_cont;
1275 1290 }
1276 1291 STRUCT_FSET(strpeek, databuf.len, len - uio.uio_resid);
1277 1292 }
1278 1293 STRUCT_FSET(strpeek, flags, 0);
1279 1294 STRUCT_FSET(strpeek, ctlbuf.len, -1);
1280 1295
1281 1296 error = copyout(STRUCT_BUF(strpeek), (caddr_t)arg,
1282 1297 STRUCT_SIZE(strpeek));
1283 1298 if (error == 0 && len >= 0)
1284 1299 *rvalp = 1;
1285 1300 break;
1286 1301 }
1287 1302
1288 1303 case FIONREAD:
1289 1304 /*
1290 1305 * let user know total number of bytes in message queue
1291 1306 */
1292 1307 error = copyout((caddr_t)&fnp->fn_count, (caddr_t)arg,
1293 1308 sizeof (fnp->fn_count));
1294 1309 if (error == 0)
1295 1310 *rvalp = 0;
1296 1311 break;
1297 1312
1298 1313 case I_SETSIG:
1299 1314 /*
1300 1315 * let streams set up the signal masking for us
1301 1316 * we just check to see if it's set
1302 1317 * XXX : this interface should not be visible
1303 1318 * i.e. STREAM's framework is exposed.
1304 1319 */
1305 1320 error = strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp);
1306 1321 if (vp->v_stream->sd_sigflags & (S_INPUT|S_RDNORM|S_WRNORM))
1307 1322 fnp->fn_flag |= FIFOSETSIG;
1308 1323 else
1309 1324 fnp->fn_flag &= ~FIFOSETSIG;
1310 1325 break;
1311 1326
1312 1327 case I_FLUSH:
1313 1328 /*
1314 1329 * flush them message queues
1315 1330 */
1316 1331 if (arg & ~FLUSHRW) {
1317 1332 error = EINVAL;
1318 1333 break;
1319 1334 }
1320 1335 if (arg & FLUSHR) {
1321 1336 fifo_fastflush(fnp);
1322 1337 }
1323 1338 fn_dest = fnp->fn_dest;
1324 1339 if ((arg & FLUSHW)) {
1325 1340 fifo_fastflush(fn_dest);
1326 1341 }
1327 1342 /*
1328 1343 * wake up any sleeping readers or writers
1329 1344 * (waking readers probably doesn't make sense, but it
1330 1345 * doesn't hurt; i.e. we just got rid of all the data
1331 1346 * what's to read ?)
1332 1347 */
1333 1348 if (fn_dest->fn_flag & (FIFOWANTW | FIFOWANTR)) {
1334 1349 fn_dest->fn_flag &= ~(FIFOWANTW | FIFOWANTR);
1335 1350 cv_broadcast(&fn_dest->fn_wait_cv);
1336 1351 }
1337 1352 *rvalp = 0;
1338 1353 break;
↓ open down ↓ |
199 lines elided |
↑ open up ↑ |
1339 1354
1340 1355 /*
1341 1356 * Since no band data can ever get on a fifo in fast mode
1342 1357 * just return 0.
1343 1358 */
1344 1359 case I_FLUSHBAND:
1345 1360 error = 0;
1346 1361 *rvalp = 0;
1347 1362 break;
1348 1363
1364 + case _I_GETPEERCRED:
1365 + error = fifo_ioctl_getpeercred(fnp, arg, mode);
1366 + break;
1367 +
1349 1368 /*
1350 1369 * invalid calls for stream head or fifos
1351 1370 */
1352 1371
1353 1372 case I_POP: /* shouldn't happen */
1354 1373 case I_LOOK:
1355 1374 case I_LINK:
1356 1375 case I_PLINK:
1357 1376 case I_UNLINK:
1358 1377 case I_PUNLINK:
1359 1378
1360 1379 /*
1361 1380 * more invalid tty type of ioctls
1362 1381 */
1363 1382
1364 1383 case SRIOCSREDIR:
1365 1384 case SRIOCISREDIR:
1366 1385 error = EINVAL;
1367 1386 break;
1368 1387
1369 1388 }
1370 1389 mutex_exit(&fn_lock->flk_lock);
1371 1390 return (error);
1372 1391
1373 1392 turn_fastoff:
1374 1393 fifo_fastoff(fnp);
1375 1394
1376 1395 stream_mode:
1377 1396 /*
1378 1397 * streams mode
1379 1398 */
1380 1399 mutex_exit(&fn_lock->flk_lock);
1381 1400 return (fifo_strioctl(vp, cmd, arg, mode, cr, rvalp));
1382 1401
1383 1402 }
1384 1403
1385 1404 /*
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
1386 1405 * FIFO is in STREAMS mode; STREAMS framework does most of the work.
1387 1406 */
1388 1407 static int
1389 1408 fifo_strioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
1390 1409 int *rvalp)
1391 1410 {
1392 1411 fifonode_t *fnp = VTOF(vp);
1393 1412 int error;
1394 1413 fifolock_t *fn_lock;
1395 1414
1396 - if (cmd == _I_GETPEERCRED) {
1397 - if (mode == FKIOCTL && fnp->fn_pcredp != NULL) {
1398 - k_peercred_t *kp = (k_peercred_t *)arg;
1399 - crhold(fnp->fn_pcredp);
1400 - kp->pc_cr = fnp->fn_pcredp;
1401 - kp->pc_cpid = fnp->fn_cpid;
1402 - return (0);
1403 - } else {
1404 - return (ENOTSUP);
1405 - }
1406 - }
1415 + if (cmd == _I_GETPEERCRED)
1416 + return (fifo_ioctl_getpeercred(fnp, arg, mode));
1407 1417
1408 1418 error = strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp);
1409 1419
1410 1420 switch (cmd) {
1411 1421 /*
1412 1422 * The FIFOSEND flag is set to inform other processes that a file
1413 1423 * descriptor is pending at the stream head of this pipe.
1414 1424 * The flag is cleared and the sending process is awoken when
1415 1425 * this process has completed receiving the file descriptor.
1416 1426 * XXX This could become out of sync if the process does I_SENDFDs
1417 1427 * and opens on connld attached to the same pipe.
1418 1428 */
1419 1429 case I_RECVFD:
1420 1430 case I_E_RECVFD:
1421 1431 if (error == 0) {
1422 1432 fn_lock = fnp->fn_lock;
1423 1433 mutex_enter(&fn_lock->flk_lock);
1424 1434 if (fnp->fn_flag & FIFOSEND) {
1425 1435 fnp->fn_flag &= ~FIFOSEND;
1426 1436 cv_broadcast(&fnp->fn_dest->fn_wait_cv);
1427 1437 }
1428 1438 mutex_exit(&fn_lock->flk_lock);
1429 1439 }
1430 1440 break;
1431 1441 default:
1432 1442 break;
1433 1443 }
1434 1444
1435 1445 return (error);
1436 1446 }
1437 1447
1438 1448 /*
1439 1449 * If shadowing a vnode (FIFOs), apply the VOP_GETATTR to the shadowed
1440 1450 * vnode to Obtain the node information. If not shadowing (pipes), obtain
1441 1451 * the node information from the credentials structure.
1442 1452 */
1443 1453 int
1444 1454 fifo_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *crp,
1445 1455 caller_context_t *ct)
1446 1456 {
1447 1457 int error = 0;
1448 1458 fifonode_t *fnp = VTOF(vp);
1449 1459 queue_t *qp;
1450 1460 qband_t *bandp;
1451 1461 fifolock_t *fn_lock = fnp->fn_lock;
1452 1462
1453 1463 if (fnp->fn_realvp) {
1454 1464 /*
1455 1465 * for FIFOs or mounted pipes
1456 1466 */
1457 1467 if (error = VOP_GETATTR(fnp->fn_realvp, vap, flags, crp, ct))
1458 1468 return (error);
1459 1469 mutex_enter(&fn_lock->flk_lock);
1460 1470 /* set current times from fnode, even if older than vnode */
1461 1471 vap->va_atime.tv_sec = fnp->fn_atime;
1462 1472 vap->va_atime.tv_nsec = 0;
1463 1473 vap->va_mtime.tv_sec = fnp->fn_mtime;
1464 1474 vap->va_mtime.tv_nsec = 0;
1465 1475 vap->va_ctime.tv_sec = fnp->fn_ctime;
1466 1476 vap->va_ctime.tv_nsec = 0;
1467 1477 } else {
1468 1478 /*
1469 1479 * for non-attached/ordinary pipes
1470 1480 */
1471 1481 vap->va_mode = 0;
1472 1482 mutex_enter(&fn_lock->flk_lock);
1473 1483 vap->va_atime.tv_sec = fnp->fn_atime;
1474 1484 vap->va_atime.tv_nsec = 0;
1475 1485 vap->va_mtime.tv_sec = fnp->fn_mtime;
1476 1486 vap->va_mtime.tv_nsec = 0;
1477 1487 vap->va_ctime.tv_sec = fnp->fn_ctime;
1478 1488 vap->va_ctime.tv_nsec = 0;
1479 1489 vap->va_uid = crgetuid(crp);
1480 1490 vap->va_gid = crgetgid(crp);
1481 1491 vap->va_nlink = 0;
1482 1492 vap->va_fsid = fifodev;
1483 1493 vap->va_nodeid = (ino64_t)fnp->fn_ino;
1484 1494 vap->va_rdev = 0;
1485 1495 }
1486 1496 vap->va_type = VFIFO;
1487 1497 vap->va_blksize = PIPE_BUF;
1488 1498 /*
1489 1499 * Size is number of un-read bytes at the stream head and
1490 1500 * nblocks is the unread bytes expressed in blocks.
1491 1501 */
1492 1502 if (vp->v_stream && (fnp->fn_flag & FIFOISOPEN)) {
1493 1503 if ((fnp->fn_flag & FIFOFAST)) {
1494 1504 vap->va_size = (u_offset_t)fnp->fn_count;
1495 1505 } else {
1496 1506 qp = RD((strvp2wq(vp)));
1497 1507 vap->va_size = (u_offset_t)qp->q_count;
1498 1508 if (qp->q_nband != 0) {
1499 1509 mutex_enter(QLOCK(qp));
1500 1510 for (bandp = qp->q_bandp; bandp;
1501 1511 bandp = bandp->qb_next)
1502 1512 vap->va_size += bandp->qb_count;
1503 1513 mutex_exit(QLOCK(qp));
1504 1514 }
1505 1515 }
1506 1516 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
1507 1517 } else {
1508 1518 vap->va_size = (u_offset_t)0;
1509 1519 vap->va_nblocks = (fsblkcnt64_t)0;
1510 1520 }
1511 1521 mutex_exit(&fn_lock->flk_lock);
1512 1522 vap->va_seq = 0;
1513 1523 return (0);
1514 1524 }
1515 1525
1516 1526 /*
1517 1527 * If shadowing a vnode, apply the VOP_SETATTR to it, and to the fnode.
1518 1528 * Otherwise, set the time and return 0.
1519 1529 */
1520 1530 int
1521 1531 fifo_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *crp,
1522 1532 caller_context_t *ctp)
1523 1533 {
1524 1534 fifonode_t *fnp = VTOF(vp);
1525 1535 int error = 0;
1526 1536 fifolock_t *fn_lock;
1527 1537
1528 1538 if (fnp->fn_realvp)
1529 1539 error = VOP_SETATTR(fnp->fn_realvp, vap, flags, crp, ctp);
1530 1540 if (error == 0) {
1531 1541 fn_lock = fnp->fn_lock;
1532 1542 mutex_enter(&fn_lock->flk_lock);
1533 1543 if (vap->va_mask & AT_ATIME)
1534 1544 fnp->fn_atime = vap->va_atime.tv_sec;
1535 1545 if (vap->va_mask & AT_MTIME)
1536 1546 fnp->fn_mtime = vap->va_mtime.tv_sec;
1537 1547 fnp->fn_ctime = gethrestime_sec();
1538 1548 mutex_exit(&fn_lock->flk_lock);
1539 1549 }
1540 1550 return (error);
1541 1551 }
1542 1552
1543 1553 /*
1544 1554 * If shadowing a vnode, apply VOP_ACCESS to it.
1545 1555 * Otherwise, return 0 (allow all access).
1546 1556 */
1547 1557 int
1548 1558 fifo_access(vnode_t *vp, int mode, int flags, cred_t *crp, caller_context_t *ct)
1549 1559 {
1550 1560 if (VTOF(vp)->fn_realvp)
1551 1561 return (VOP_ACCESS(VTOF(vp)->fn_realvp, mode, flags, crp, ct));
1552 1562 else
1553 1563 return (0);
1554 1564 }
1555 1565
1556 1566 /*
1557 1567 * This can be called if creat or an open with O_CREAT is done on the root
1558 1568 * of a lofs mount where the mounted entity is a fifo.
1559 1569 */
1560 1570 /*ARGSUSED*/
1561 1571 static int
1562 1572 fifo_create(struct vnode *dvp, char *name, vattr_t *vap, enum vcexcl excl,
1563 1573 int mode, struct vnode **vpp, struct cred *cr, int flag,
1564 1574 caller_context_t *ct, vsecattr_t *vsecp)
1565 1575 {
1566 1576 int error;
1567 1577
1568 1578 ASSERT(dvp && (dvp->v_flag & VROOT) && *name == '\0');
1569 1579 if (excl == NONEXCL) {
1570 1580 if (mode && (error = fifo_access(dvp, mode, 0, cr, ct)))
1571 1581 return (error);
1572 1582 VN_HOLD(dvp);
1573 1583 return (0);
1574 1584 }
1575 1585 return (EEXIST);
1576 1586 }
1577 1587
1578 1588 /*
1579 1589 * If shadowing a vnode, apply the VOP_FSYNC to it.
1580 1590 * Otherwise, return 0.
1581 1591 */
1582 1592 int
1583 1593 fifo_fsync(vnode_t *vp, int syncflag, cred_t *crp, caller_context_t *ct)
1584 1594 {
1585 1595 fifonode_t *fnp = VTOF(vp);
1586 1596 vattr_t va;
1587 1597
1588 1598 if (fnp->fn_realvp == NULL)
1589 1599 return (0);
1590 1600
1591 1601 bzero((caddr_t)&va, sizeof (va));
1592 1602 va.va_mask = AT_MTIME | AT_ATIME;
1593 1603 if (VOP_GETATTR(fnp->fn_realvp, &va, 0, crp, ct) == 0) {
1594 1604 va.va_mask = 0;
1595 1605 if (fnp->fn_mtime > va.va_mtime.tv_sec) {
1596 1606 va.va_mtime.tv_sec = fnp->fn_mtime;
1597 1607 va.va_mask = AT_MTIME;
1598 1608 }
1599 1609 if (fnp->fn_atime > va.va_atime.tv_sec) {
1600 1610 va.va_atime.tv_sec = fnp->fn_atime;
1601 1611 va.va_mask |= AT_ATIME;
1602 1612 }
1603 1613 if (va.va_mask != 0)
1604 1614 (void) VOP_SETATTR(fnp->fn_realvp, &va, 0, crp, ct);
1605 1615 }
1606 1616 return (VOP_FSYNC(fnp->fn_realvp, syncflag, crp, ct));
1607 1617 }
1608 1618
1609 1619 /*
1610 1620 * Called when the upper level no longer holds references to the
1611 1621 * vnode. Sync the file system and free the fifonode.
1612 1622 */
1613 1623 void
1614 1624 fifo_inactive(vnode_t *vp, cred_t *crp, caller_context_t *ct)
1615 1625 {
1616 1626 fifonode_t *fnp;
1617 1627 fifolock_t *fn_lock;
1618 1628
1619 1629 mutex_enter(&ftable_lock);
1620 1630 mutex_enter(&vp->v_lock);
1621 1631 ASSERT(vp->v_count >= 1);
1622 1632 VN_RELE_LOCKED(vp);
1623 1633 if (vp->v_count != 0) {
1624 1634 /*
1625 1635 * Somebody accessed the fifo before we got a chance to
1626 1636 * remove it. They will remove it when they do a vn_rele.
1627 1637 */
1628 1638 mutex_exit(&vp->v_lock);
1629 1639 mutex_exit(&ftable_lock);
1630 1640 return;
1631 1641 }
1632 1642 mutex_exit(&vp->v_lock);
1633 1643
1634 1644 fnp = VTOF(vp);
1635 1645
1636 1646 /*
1637 1647 * remove fifo from fifo list so that no other process
1638 1648 * can grab it.
1639 1649 * Drop the reference count on the fifo node's
1640 1650 * underlying vfs.
1641 1651 */
1642 1652 if (fnp->fn_realvp) {
1643 1653 (void) fiforemove(fnp);
1644 1654 mutex_exit(&ftable_lock);
1645 1655 (void) fifo_fsync(vp, FSYNC, crp, ct);
1646 1656 VN_RELE(fnp->fn_realvp);
1647 1657 VFS_RELE(vp->v_vfsp);
1648 1658 vp->v_vfsp = NULL;
1649 1659 } else
1650 1660 mutex_exit(&ftable_lock);
1651 1661
1652 1662 fn_lock = fnp->fn_lock;
1653 1663
1654 1664 mutex_enter(&fn_lock->flk_lock);
1655 1665 ASSERT(vp->v_stream == NULL);
1656 1666 ASSERT(vp->v_count == 0);
1657 1667 /*
1658 1668 * if this is last reference to the lock, then we can
1659 1669 * free everything up.
1660 1670 */
1661 1671 if (--fn_lock->flk_ref == 0) {
1662 1672 mutex_exit(&fn_lock->flk_lock);
1663 1673 ASSERT(fnp->fn_open == 0);
1664 1674 ASSERT(fnp->fn_dest->fn_open == 0);
1665 1675 if (fnp->fn_mp) {
1666 1676 freemsg(fnp->fn_mp);
1667 1677 fnp->fn_mp = NULL;
1668 1678 fnp->fn_count = 0;
1669 1679 }
1670 1680 if (fnp->fn_pcredp != NULL) {
1671 1681 crfree(fnp->fn_pcredp);
1672 1682 fnp->fn_pcredp = NULL;
1673 1683 }
1674 1684 if (fnp->fn_flag & ISPIPE) {
1675 1685 fifonode_t *fn_dest = fnp->fn_dest;
1676 1686
1677 1687 vp = FTOV(fn_dest);
1678 1688 if (fn_dest->fn_mp) {
1679 1689 freemsg(fn_dest->fn_mp);
1680 1690 fn_dest->fn_mp = NULL;
1681 1691 fn_dest->fn_count = 0;
1682 1692 }
1683 1693 if (fn_dest->fn_pcredp != NULL) {
1684 1694 crfree(fn_dest->fn_pcredp);
1685 1695 fn_dest->fn_pcredp = NULL;
1686 1696 }
1687 1697 kmem_cache_free(pipe_cache, (fifodata_t *)fn_lock);
1688 1698 } else
1689 1699 kmem_cache_free(fnode_cache, (fifodata_t *)fn_lock);
1690 1700 } else {
1691 1701 mutex_exit(&fn_lock->flk_lock);
1692 1702 }
1693 1703 }
1694 1704
1695 1705 /*
1696 1706 * If shadowing a vnode, apply the VOP_FID to it.
1697 1707 * Otherwise, return EINVAL.
1698 1708 */
1699 1709 int
1700 1710 fifo_fid(vnode_t *vp, fid_t *fidfnp, caller_context_t *ct)
1701 1711 {
1702 1712 if (VTOF(vp)->fn_realvp)
1703 1713 return (VOP_FID(VTOF(vp)->fn_realvp, fidfnp, ct));
1704 1714 else
1705 1715 return (EINVAL);
1706 1716 }
1707 1717
1708 1718 /*
1709 1719 * Lock a fifonode.
1710 1720 */
1711 1721 /* ARGSUSED */
1712 1722 int
1713 1723 fifo_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
1714 1724 {
1715 1725 return (-1);
1716 1726 }
1717 1727
1718 1728 /*
1719 1729 * Unlock a fifonode.
1720 1730 */
1721 1731 /* ARGSUSED */
1722 1732 void
1723 1733 fifo_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
1724 1734 {
1725 1735 }
1726 1736
1727 1737 /*
1728 1738 * Return error since seeks are not allowed on pipes.
1729 1739 */
1730 1740 /*ARGSUSED*/
1731 1741 int
1732 1742 fifo_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
1733 1743 {
1734 1744 return (ESPIPE);
1735 1745 }
1736 1746
1737 1747 /*
1738 1748 * If there is a realvp associated with vp, return it.
1739 1749 */
1740 1750 int
1741 1751 fifo_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
1742 1752 {
1743 1753 vnode_t *rvp;
1744 1754
1745 1755 if ((rvp = VTOF(vp)->fn_realvp) != NULL) {
1746 1756 vp = rvp;
1747 1757 if (VOP_REALVP(vp, &rvp, ct) == 0)
1748 1758 vp = rvp;
1749 1759 }
1750 1760
1751 1761 *vpp = vp;
1752 1762 return (0);
1753 1763 }
1754 1764
1755 1765 /*
1756 1766 * Poll for interesting events on a stream pipe
1757 1767 */
1758 1768 /* ARGSUSED */
1759 1769 int
1760 1770 fifo_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
1761 1771 pollhead_t **phpp, caller_context_t *ct)
1762 1772 {
1763 1773 fifonode_t *fnp, *fn_dest;
1764 1774 fifolock_t *fn_lock;
1765 1775 int retevents;
1766 1776 struct stdata *stp;
1767 1777
1768 1778 ASSERT(vp->v_stream != NULL);
1769 1779
1770 1780 stp = vp->v_stream;
1771 1781 retevents = 0;
1772 1782 fnp = VTOF(vp);
1773 1783 fn_dest = fnp->fn_dest;
1774 1784 fn_lock = fnp->fn_lock;
1775 1785
1776 1786 if (polllock(&stp->sd_pollist, &fn_lock->flk_lock) != 0) {
1777 1787 *reventsp = POLLNVAL;
1778 1788 return (0);
1779 1789 }
1780 1790
1781 1791 /*
1782 1792 * see if FIFO/pipe open
1783 1793 */
1784 1794 if ((fnp->fn_flag & FIFOISOPEN) == 0) {
1785 1795 if (((events & (POLLIN | POLLRDNORM | POLLPRI | POLLRDBAND)) &&
1786 1796 fnp->fn_rcnt == 0) ||
1787 1797 ((events & (POLLWRNORM | POLLWRBAND)) &&
1788 1798 fnp->fn_wcnt == 0)) {
1789 1799 mutex_exit(&fnp->fn_lock->flk_lock);
1790 1800 *reventsp = POLLERR;
1791 1801 return (0);
1792 1802 }
1793 1803 }
1794 1804
1795 1805 /*
1796 1806 * if not in fast mode, let the stream head take care of it
1797 1807 */
1798 1808 if (!(fnp->fn_flag & FIFOFAST)) {
1799 1809 mutex_exit(&fnp->fn_lock->flk_lock);
1800 1810 goto stream_mode;
1801 1811 }
1802 1812
1803 1813 /*
1804 1814 * If this is a pipe.. check to see if the other
1805 1815 * end is gone. If we are a fifo, check to see
1806 1816 * if write end is gone.
1807 1817 */
1808 1818
1809 1819 if ((fnp->fn_flag & ISPIPE) && (fn_dest->fn_open == 0)) {
1810 1820 retevents = POLLHUP;
1811 1821 } else if ((fnp->fn_flag & (FIFOCLOSE | ISPIPE)) == FIFOCLOSE &&
1812 1822 (fn_dest->fn_wcnt == 0)) {
1813 1823 /*
1814 1824 * no writer at other end.
1815 1825 * it was closed (versus yet to be opened)
1816 1826 */
1817 1827 retevents = POLLHUP;
1818 1828 } else if (events & (POLLWRNORM | POLLWRBAND)) {
1819 1829 if (events & POLLWRNORM) {
1820 1830 if (fn_dest->fn_count < Fifohiwat)
1821 1831 retevents = POLLWRNORM;
1822 1832 else
1823 1833 fnp->fn_flag |= FIFOHIWATW;
1824 1834 }
1825 1835 /*
1826 1836 * This is always true for fast pipes
1827 1837 * (Note: will go to STREAMS mode if band data is written)
1828 1838 */
1829 1839 if (events & POLLWRBAND)
1830 1840 retevents |= POLLWRBAND;
1831 1841 }
1832 1842 if (events & (POLLIN | POLLRDNORM)) {
1833 1843 if (fnp->fn_count)
1834 1844 retevents |= (events & (POLLIN | POLLRDNORM));
1835 1845 }
1836 1846
1837 1847 /*
1838 1848 * if we happened to get something and we're not edge-triggered, return
1839 1849 */
1840 1850 if ((*reventsp = (short)retevents) != 0 && !(events & POLLET)) {
1841 1851 mutex_exit(&fnp->fn_lock->flk_lock);
1842 1852 return (0);
1843 1853 }
1844 1854
1845 1855 /*
1846 1856 * If poll() has not found any events yet or we're edge-triggered, set
1847 1857 * up event cell to wake up the poll if a requested event occurs on this
1848 1858 * pipe/fifo.
1849 1859 */
1850 1860 if (!anyyet) {
1851 1861 if (events & POLLWRNORM)
1852 1862 fnp->fn_flag |= FIFOPOLLW;
1853 1863 if (events & (POLLIN | POLLRDNORM))
1854 1864 fnp->fn_flag |= FIFOPOLLR;
1855 1865 if (events & POLLRDBAND)
1856 1866 fnp->fn_flag |= FIFOPOLLRBAND;
1857 1867 /*
1858 1868 * XXX Don't like exposing this from streams
1859 1869 */
1860 1870 *phpp = &stp->sd_pollist;
1861 1871 }
1862 1872 mutex_exit(&fnp->fn_lock->flk_lock);
1863 1873 return (0);
1864 1874 stream_mode:
1865 1875 return (strpoll(stp, events, anyyet, reventsp, phpp));
1866 1876 }
1867 1877
1868 1878 /*
1869 1879 * POSIX pathconf() support.
1870 1880 */
1871 1881 /* ARGSUSED */
1872 1882 int
1873 1883 fifo_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
1874 1884 caller_context_t *ct)
1875 1885 {
1876 1886 ulong_t val;
1877 1887 int error = 0;
1878 1888
1879 1889 switch (cmd) {
1880 1890
1881 1891 case _PC_LINK_MAX:
1882 1892 val = MAXLINK;
1883 1893 break;
1884 1894
1885 1895 case _PC_MAX_CANON:
1886 1896 val = MAX_CANON;
1887 1897 break;
1888 1898
1889 1899 case _PC_MAX_INPUT:
1890 1900 val = MAX_INPUT;
1891 1901 break;
1892 1902
1893 1903 case _PC_NAME_MAX:
1894 1904 error = EINVAL;
1895 1905 break;
1896 1906
1897 1907 case _PC_PATH_MAX:
1898 1908 case _PC_SYMLINK_MAX:
1899 1909 val = MAXPATHLEN;
1900 1910 break;
1901 1911
1902 1912 case _PC_PIPE_BUF:
1903 1913 val = PIPE_BUF;
1904 1914 break;
1905 1915
1906 1916 case _PC_NO_TRUNC:
1907 1917 if (vp->v_vfsp->vfs_flag & VFS_NOTRUNC)
1908 1918 val = 1; /* NOTRUNC is enabled for vp */
1909 1919 else
1910 1920 val = (ulong_t)-1;
1911 1921 break;
1912 1922
1913 1923 case _PC_VDISABLE:
1914 1924 val = _POSIX_VDISABLE;
1915 1925 break;
1916 1926
1917 1927 case _PC_CHOWN_RESTRICTED:
1918 1928 if (rstchown)
1919 1929 val = rstchown; /* chown restricted enabled */
1920 1930 else
1921 1931 val = (ulong_t)-1;
1922 1932 break;
1923 1933
1924 1934 case _PC_FILESIZEBITS:
1925 1935 val = (ulong_t)-1;
1926 1936 break;
1927 1937
1928 1938 default:
1929 1939 if (VTOF(vp)->fn_realvp)
1930 1940 error = VOP_PATHCONF(VTOF(vp)->fn_realvp, cmd,
1931 1941 &val, cr, ct);
1932 1942 else
1933 1943 error = EINVAL;
1934 1944 break;
1935 1945 }
1936 1946
1937 1947 if (error == 0)
1938 1948 *valp = val;
1939 1949 return (error);
1940 1950 }
1941 1951
1942 1952 /*
1943 1953 * If shadowing a vnode, apply VOP_SETSECATTR to it.
1944 1954 * Otherwise, return NOSYS.
1945 1955 */
1946 1956 int
1947 1957 fifo_setsecattr(struct vnode *vp, vsecattr_t *vsap, int flag, struct cred *crp,
1948 1958 caller_context_t *ct)
1949 1959 {
1950 1960 int error;
1951 1961
1952 1962 /*
1953 1963 * The acl(2) system call tries to grab the write lock on the
1954 1964 * file when setting an ACL, but fifofs does not implement
1955 1965 * VOP_RWLOCK or VOP_RWUNLOCK, so we do it here instead.
1956 1966 */
1957 1967 if (VTOF(vp)->fn_realvp) {
1958 1968 (void) VOP_RWLOCK(VTOF(vp)->fn_realvp, V_WRITELOCK_TRUE, ct);
1959 1969 error = VOP_SETSECATTR(VTOF(vp)->fn_realvp, vsap, flag,
1960 1970 crp, ct);
1961 1971 VOP_RWUNLOCK(VTOF(vp)->fn_realvp, V_WRITELOCK_TRUE, ct);
1962 1972 return (error);
1963 1973 } else
1964 1974 return (fs_nosys());
1965 1975 }
1966 1976
1967 1977 /*
1968 1978 * If shadowing a vnode, apply VOP_GETSECATTR to it. Otherwise, fabricate
1969 1979 * an ACL from the permission bits that fifo_getattr() makes up.
1970 1980 */
1971 1981 int
1972 1982 fifo_getsecattr(struct vnode *vp, vsecattr_t *vsap, int flag, struct cred *crp,
1973 1983 caller_context_t *ct)
1974 1984 {
1975 1985 if (VTOF(vp)->fn_realvp)
1976 1986 return (VOP_GETSECATTR(VTOF(vp)->fn_realvp, vsap, flag,
1977 1987 crp, ct));
1978 1988 else
1979 1989 return (fs_fab_acl(vp, vsap, flag, crp, ct));
1980 1990 }
1981 1991
1982 1992
1983 1993 /*
1984 1994 * Set the FIFOSTAYFAST flag so nobody can turn the fifo into stream mode.
1985 1995 * If the flag is already set then wait until it is removed - releasing
1986 1996 * the lock.
1987 1997 * If the fifo switches into stream mode while we are waiting, return failure.
1988 1998 */
1989 1999 static boolean_t
1990 2000 fifo_stayfast_enter(fifonode_t *fnp)
1991 2001 {
1992 2002 ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
1993 2003 while (fnp->fn_flag & FIFOSTAYFAST) {
1994 2004 fnp->fn_flag |= FIFOWAITMODE;
1995 2005 cv_wait(&fnp->fn_wait_cv, &fnp->fn_lock->flk_lock);
1996 2006 fnp->fn_flag &= ~FIFOWAITMODE;
1997 2007 }
1998 2008 if (!(fnp->fn_flag & FIFOFAST))
1999 2009 return (B_FALSE);
2000 2010
2001 2011 fnp->fn_flag |= FIFOSTAYFAST;
2002 2012 return (B_TRUE);
2003 2013 }
2004 2014
2005 2015 /*
2006 2016 * Unset the FIFOSTAYFAST flag and notify anybody waiting for this flag
2007 2017 * to be removed:
2008 2018 * - threads wanting to turn into stream mode waiting in fifo_fastoff(),
2009 2019 * - other writers threads waiting in fifo_stayfast_enter().
2010 2020 */
2011 2021 static void
2012 2022 fifo_stayfast_exit(fifonode_t *fnp)
2013 2023 {
2014 2024 fifonode_t *fn_dest = fnp->fn_dest;
2015 2025
2016 2026 ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
2017 2027
2018 2028 fnp->fn_flag &= ~FIFOSTAYFAST;
2019 2029
2020 2030 if (fnp->fn_flag & FIFOWAITMODE)
2021 2031 cv_broadcast(&fnp->fn_wait_cv);
2022 2032
2023 2033 if ((fnp->fn_flag & ISPIPE) && (fn_dest->fn_flag & FIFOWAITMODE))
2024 2034 cv_broadcast(&fn_dest->fn_wait_cv);
2025 2035 }
↓ open down ↓ |
609 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX