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