1 /* This file deals with the suspension and revival of processes. A process can 2 * be suspended because it wants to read or write from a pipe and can't, or 3 * because it wants to read or write from a special file and can't. When a 4 * process can't continue it is suspended, and revived later when it is able 5 * to continue. 6 * 7 * The entry points into this file are 8 * do_pipe2: perform the PIPE2 system call 9 * pipe_check: check to see that a read or write on a pipe is feasible now 10 * suspend: suspend a process that cannot do a requested read or write 11 * release: check to see if a suspended process can be released and do 12 * it 13 * revive: mark a suspended process as able to run again 14 * unsuspend_by_endpt: revive all processes blocking on a given process 15 * do_unpause: a signal has been sent to a process; see if it suspended 16 */ 17 18 #include "fs.h" 19 #include <fcntl.h> 20 #include <signal.h> 21 #include <string.h> 22 #include <assert.h> 23 #include <minix/callnr.h> 24 #include <minix/endpoint.h> 25 #include <minix/com.h> 26 #include <minix/u64.h> 27 #include <sys/select.h> 28 #include <sys/time.h> 29 #include "file.h" 30 #include <minix/vfsif.h> 31 #include "vnode.h" 32 #include "vmnt.h" 33 34 static int create_pipe(int fil_des[2], int flags); 35 36 /*===========================================================================* 37 * do_pipe2 * 38 *===========================================================================*/ 39 int do_pipe2(void) 40 { 41 /* Perform the pipe2(fil_des[2], flags) system call. */ 42 int r, flags; 43 int fil_des[2]; /* reply goes here */ 44 45 flags = job_m_in.m_lc_vfs_pipe2.flags; 46 flags |= job_m_in.m_lc_vfs_pipe2.oflags; /* backward compatibility */ 47 48 r = create_pipe(fil_des, flags); 49 if (r == OK) { 50 job_m_out.m_vfs_lc_fdpair.fd0 = fil_des[0]; 51 job_m_out.m_vfs_lc_fdpair.fd1 = fil_des[1]; 52 } 53 54 return r; 55 } 56 57 /*===========================================================================* 58 * create_pipe * 59 *===========================================================================*/ 60 static int create_pipe(int fil_des[2], int flags) 61 { 62 register struct fproc *rfp; 63 int r; 64 struct filp *fil_ptr0, *fil_ptr1; 65 struct vnode *vp; 66 struct vmnt *vmp; 67 struct node_details res; 68 69 /* Get a lock on PFS */ 70 if ((vmp = find_vmnt(PFS_PROC_NR)) == NULL) panic("PFS gone"); 71 if ((r = lock_vmnt(vmp, VMNT_READ)) != OK) return(r); 72 73 /* See if a free vnode is available */ 74 if ((vp = get_free_vnode()) == NULL) { 75 unlock_vmnt(vmp); 76 return(err_code); 77 } 78 lock_vnode(vp, VNODE_OPCL); 79 80 /* Acquire two file descriptors. */ 81 rfp = fp; 82 if ((r = get_fd(fp, 0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) { 83 unlock_vnode(vp); 84 unlock_vmnt(vmp); 85 return(r); 86 } 87 rfp->fp_filp[fil_des[0]] = fil_ptr0; 88 fil_ptr0->filp_count = 1; /* mark filp in use */ 89 if ((r = get_fd(fp, 0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) { 90 rfp->fp_filp[fil_des[0]] = NULL; 91 fil_ptr0->filp_count = 0; /* mark filp free */ 92 unlock_filp(fil_ptr0); 93 unlock_vnode(vp); 94 unlock_vmnt(vmp); 95 return(r); 96 } 97 rfp->fp_filp[fil_des[1]] = fil_ptr1; 98 fil_ptr1->filp_count = 1; 99 100 /* Create a named pipe inode on PipeFS */ 101 r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE, 102 NO_DEV, &res); 103 104 if (r != OK) { 105 rfp->fp_filp[fil_des[0]] = NULL; 106 fil_ptr0->filp_count = 0; 107 rfp->fp_filp[fil_des[1]] = NULL; 108 fil_ptr1->filp_count = 0; 109 unlock_filp(fil_ptr1); 110 unlock_filp(fil_ptr0); 111 unlock_vnode(vp); 112 unlock_vmnt(vmp); 113 return(r); 114 } 115 116 /* Fill in vnode */ 117 vp->v_fs_e = res.fs_e; 118 vp->v_mapfs_e = res.fs_e; 119 vp->v_inode_nr = res.inode_nr; 120 vp->v_mapinode_nr = res.inode_nr; 121 vp->v_mode = res.fmode; 122 vp->v_fs_count = 1; 123 vp->v_mapfs_count = 1; 124 vp->v_ref_count = 1; 125 vp->v_size = 0; 126 vp->v_vmnt = NULL; 127 vp->v_dev = NO_DEV; 128 129 /* Fill in filp objects */ 130 fil_ptr0->filp_vno = vp; 131 dup_vnode(vp); 132 fil_ptr1->filp_vno = vp; 133 fil_ptr0->filp_flags = O_RDONLY | (flags & ~O_ACCMODE); 134 fil_ptr1->filp_flags = O_WRONLY | (flags & ~O_ACCMODE); 135 if (flags & O_CLOEXEC) { 136 FD_SET(fil_des[0], &rfp->fp_cloexec_set); 137 FD_SET(fil_des[1], &rfp->fp_cloexec_set); 138 } 139 140 unlock_filps(fil_ptr0, fil_ptr1); 141 unlock_vmnt(vmp); 142 143 return(OK); 144 } 145 146 147 /*===========================================================================* 148 * map_vnode * 149 *===========================================================================*/ 150 int map_vnode(vp, map_to_fs_e) 151 struct vnode *vp; 152 endpoint_t map_to_fs_e; 153 { 154 int r; 155 struct vmnt *vmp; 156 struct node_details res; 157 158 if(vp->v_mapfs_e != NONE) return(OK); /* Already mapped; nothing to do. */ 159 160 if ((vmp = find_vmnt(map_to_fs_e)) == NULL) 161 panic("Can't map to unknown endpoint"); 162 if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) { 163 if (r == EBUSY) 164 vmp = NULL; /* Already locked, do not unlock */ 165 else 166 return(r); 167 168 } 169 170 /* Create a temporary mapping of this inode to another FS. Read and write 171 * operations on data will be handled by that FS. The rest by the 'original' 172 * FS that holds the inode. */ 173 if ((r = req_newnode(map_to_fs_e, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE, 174 vp->v_dev, &res)) == OK) { 175 vp->v_mapfs_e = res.fs_e; 176 vp->v_mapinode_nr = res.inode_nr; 177 vp->v_mapfs_count = 1; 178 } 179 180 if (vmp) unlock_vmnt(vmp); 181 182 return(r); 183 } 184 185 /*===========================================================================* 186 * pipe_check * 187 *===========================================================================*/ 188 int pipe_check( 189 struct filp *filp, /* the filp of the pipe */ 190 int rw_flag, /* READING or WRITING */ 191 int oflags, /* flags set by open or fcntl */ 192 int bytes, /* bytes to be read or written (all chunks) */ 193 int notouch /* check only */ 194 ) 195 { 196 /* Pipes are a little different. If a process reads from an empty pipe for 197 * which a writer still exists, suspend the reader. If the pipe is empty 198 * and there is no writer, return 0 bytes. If a process is writing to a 199 * pipe and no one is reading from it, give a broken pipe error. 200 */ 201 struct vnode *vp; 202 off_t pos; 203 int r = OK; 204 205 vp = filp->filp_vno; 206 207 /* Reads start at the beginning; writes append to pipes */ 208 if (notouch) /* In this case we don't actually care whether data transfer 209 * would succeed. See POSIX 1003.1-2008 */ 210 pos = 0; 211 else if (rw_flag == READING) 212 pos = 0; 213 else { 214 pos = vp->v_size; 215 } 216 217 /* If reading, check for empty pipe. */ 218 if (rw_flag == READING) { 219 if (vp->v_size == 0) { 220 /* Process is reading from an empty pipe. */ 221 if (find_filp(vp, W_BIT) != NULL) { 222 /* Writer exists */ 223 if (oflags & O_NONBLOCK) 224 r = EAGAIN; 225 else 226 r = SUSPEND; 227 228 /* If need be, activate sleeping writers. */ 229 /* We ignore notouch voluntary here. */ 230 if (susp_count > 0) 231 release(vp, VFS_WRITE, susp_count); 232 } 233 return(r); 234 } 235 return(bytes); 236 } 237 238 /* Process is writing to a pipe. */ 239 if (find_filp(vp, R_BIT) == NULL) { 240 return(EPIPE); 241 } 242 243 /* Calculate how many bytes can be written. */ 244 if (pos + bytes > PIPE_BUF) { 245 if (oflags & O_NONBLOCK) { 246 if (bytes <= PIPE_BUF) { 247 /* Write has to be atomic */ 248 return(EAGAIN); 249 } 250 251 /* Compute available space */ 252 bytes = PIPE_BUF - pos; 253 254 if (bytes > 0) { 255 /* Do a partial write. Need to wakeup reader */ 256 if (!notouch) 257 release(vp, VFS_READ, susp_count); 258 return(bytes); 259 } else { 260 /* Pipe is full */ 261 return(EAGAIN); 262 } 263 } 264 265 if (bytes > PIPE_BUF) { 266 /* Compute available space */ 267 bytes = PIPE_BUF - pos; 268 269 if (bytes > 0) { 270 /* Do a partial write. Need to wakeup reader 271 * since we'll suspend ourself in read_write() 272 */ 273 if (!notouch) 274 release(vp, VFS_READ, susp_count); 275 return(bytes); 276 } 277 } 278 279 /* Pipe is full */ 280 return(SUSPEND); 281 } 282 283 /* Writing to an empty pipe. Search for suspended reader. */ 284 if (pos == 0 && !notouch) 285 release(vp, VFS_READ, susp_count); 286 287 /* Requested amount fits */ 288 return(bytes); 289 } 290 291 292 /*===========================================================================* 293 * suspend * 294 *===========================================================================*/ 295 void suspend(int why) 296 { 297 /* Take measures to suspend the processing of the present system call. The 298 * caller must store the parameters to be used upon resuming in the process 299 * table as appropriate. The SUSPEND pseudo error should be returned after 300 * calling suspend(). 301 */ 302 303 assert(fp->fp_blocked_on == FP_BLOCKED_ON_NONE); 304 305 if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_PIPE) 306 /* #procs susp'ed on pipe*/ 307 susp_count++; 308 309 fp->fp_blocked_on = why; 310 } 311 312 313 /*===========================================================================* 314 * pipe_suspend * 315 *===========================================================================*/ 316 void pipe_suspend(int callnr, int fd, vir_bytes buf, size_t size, 317 size_t cum_io) 318 { 319 /* Take measures to suspend the processing of the present system call. 320 * Store the parameters to be used upon resuming in the process table. 321 */ 322 323 fp->fp_pipe.callnr = callnr; 324 fp->fp_pipe.fd = fd; 325 fp->fp_pipe.buf = buf; 326 fp->fp_pipe.nbytes = size; 327 fp->fp_pipe.cum_io = cum_io; 328 suspend(FP_BLOCKED_ON_PIPE); 329 } 330 331 332 /*===========================================================================* 333 * unsuspend_by_endpt * 334 *===========================================================================*/ 335 void unsuspend_by_endpt(endpoint_t proc_e) 336 { 337 /* Revive processes waiting for drivers (SUSPENDed) that have disappeared, with 338 * return code EIO. 339 */ 340 struct fproc *rp; 341 342 for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) { 343 if (rp->fp_pid == PID_FREE) continue; 344 if (rp->fp_blocked_on == FP_BLOCKED_ON_CDEV && 345 rp->fp_cdev.endpt == proc_e) 346 revive(rp->fp_endpoint, EIO); 347 } 348 349 /* Revive processes waiting in drivers on select()s with EAGAIN too */ 350 select_unsuspend_by_endpt(proc_e); 351 352 return; 353 } 354 355 356 /*===========================================================================* 357 * release * 358 *===========================================================================*/ 359 void release(struct vnode * vp, int op, int count) 360 { 361 /* Check to see if any process is hanging on pipe vnode 'vp'. If one is, and it 362 * was trying to perform the call indicated by 'op' - one of VFS_OPEN, 363 * VFS_READ, or VFS_WRITE - release it. The 'count' parameter indicates the 364 * maximum number of processes to release, which allows us to stop searching 365 * early in some cases. 366 */ 367 368 register struct fproc *rp; 369 struct filp *f; 370 int fd, selop; 371 372 /* Trying to perform the call also includes SELECTing on it with that 373 * operation. 374 */ 375 if (op == VFS_READ || op == VFS_WRITE) { 376 if (op == VFS_READ) 377 selop = SEL_RD; 378 else 379 selop = SEL_WR; 380 381 for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { 382 if (f->filp_count < 1 || !(f->filp_pipe_select_ops & selop) || 383 f->filp_vno != vp) 384 continue; 385 386 select_callback(f, selop); 387 388 f->filp_pipe_select_ops &= ~selop; 389 } 390 } 391 392 /* Search the proc table. */ 393 for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) { 394 /* Just to make sure: 395 * - FP_BLOCKED_ON_POPEN implies the original request was VFS_OPEN; 396 * - FP_BLOCKED_ON_PIPE may be the result of VFS_READ and VFS_WRITE, 397 * and one of those two numbers is stored in fp_pipe.callnr. 398 */ 399 if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) && 400 !(rp->fp_flags & FP_REVIVED) && 401 ((op == VFS_OPEN && rp->fp_blocked_on == FP_BLOCKED_ON_POPEN) || 402 (op != VFS_OPEN && rp->fp_blocked_on == FP_BLOCKED_ON_PIPE && 403 op == rp->fp_pipe.callnr))) { 404 /* Find the vnode. Depending on the reason the process was 405 * suspended, there are different ways of finding it. 406 */ 407 if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN) 408 fd = rp->fp_popen.fd; 409 else 410 fd = rp->fp_pipe.fd; 411 f = rp->fp_filp[fd]; 412 if (f == NULL || f->filp_mode == FILP_CLOSED) 413 continue; 414 if (f->filp_vno != vp) 415 continue; 416 417 /* We found the vnode. Revive process. */ 418 revive(rp->fp_endpoint, 0); 419 susp_count--; /* keep track of who is suspended */ 420 if(susp_count < 0) 421 panic("susp_count now negative: %d", susp_count); 422 if (--count == 0) return; 423 } 424 } 425 } 426 427 428 /*===========================================================================* 429 * revive * 430 *===========================================================================*/ 431 void revive(endpoint_t proc_e, int returned) 432 { 433 /* Revive a previously blocked process. When a process hangs on tty, this 434 * is the way it is eventually released. For processes blocked on _SELECT and 435 * _CDEV, this function MUST NOT block its calling thread. 436 */ 437 struct fproc *rfp; 438 int blocked_on; 439 int slot; 440 441 if (proc_e == NONE || isokendpt(proc_e, &slot) != OK) return; 442 443 rfp = &fproc[slot]; 444 if (!fp_is_blocked(rfp) || (rfp->fp_flags & FP_REVIVED)) return; 445 446 /* The 'reviving' flag applies to pipe I/O and file locks. Processes waiting 447 * on those suspension types need more processing, and will be unblocked from 448 * the main loop later. Processes suspended for other reasons get a reply 449 * right away, and as such, have their suspension cleared right here as well. 450 */ 451 blocked_on = rfp->fp_blocked_on; 452 if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_FLOCK) { 453 /* Revive a process suspended on a pipe or lock. */ 454 rfp->fp_flags |= FP_REVIVED; 455 reviving++; /* process was waiting on pipe or lock */ 456 } else { 457 rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; 458 if (blocked_on == FP_BLOCKED_ON_POPEN) { 459 /* process blocked in open or create */ 460 replycode(proc_e, rfp->fp_popen.fd); 461 } else if (blocked_on == FP_BLOCKED_ON_SELECT) { 462 replycode(proc_e, returned); 463 } else { 464 assert(blocked_on == FP_BLOCKED_ON_CDEV); 465 /* If a grant has been issued by FS for this I/O, revoke 466 * it again now that I/O is done. 467 */ 468 if (GRANT_VALID(rfp->fp_cdev.grant)) { 469 if (cpf_revoke(rfp->fp_cdev.grant) == -1) { 470 panic("VFS: revoke failed for grant: %d", 471 rfp->fp_cdev.grant); 472 } 473 } 474 replycode(proc_e, returned);/* unblock the process */ 475 } 476 } 477 } 478 479 480 /*===========================================================================* 481 * unpause * 482 *===========================================================================*/ 483 void unpause(void) 484 { 485 /* A signal has been sent to a user who is paused on the file system. 486 * Abort the system call with the EINTR error message. 487 */ 488 int blocked_on, status = EINTR; 489 int wasreviving = 0; 490 491 if (!fp_is_blocked(fp)) return; 492 blocked_on = fp->fp_blocked_on; 493 494 /* Clear the block status now. The procedure below might make blocking calls 495 * and it is imperative that while at least cdev_cancel() is executing, other 496 * parts of VFS do not perceive this process as blocked on something. 497 */ 498 fp->fp_blocked_on = FP_BLOCKED_ON_NONE; 499 500 if (fp->fp_flags & FP_REVIVED) { 501 fp->fp_flags &= ~FP_REVIVED; 502 reviving--; 503 wasreviving = 1; 504 } 505 506 switch (blocked_on) { 507 case FP_BLOCKED_ON_PIPE:/* process trying to read or write a pipe */ 508 /* If the operation succeeded partially, return the bytes 509 * processed so far. Otherwise, return EINTR as usual. 510 */ 511 if (fp->fp_pipe.cum_io > 0) 512 status = fp->fp_pipe.cum_io; 513 break; 514 515 case FP_BLOCKED_ON_FLOCK:/* process trying to set a lock with FCNTL */ 516 break; 517 518 case FP_BLOCKED_ON_SELECT:/* process blocking on select() */ 519 select_forget(); 520 break; 521 522 case FP_BLOCKED_ON_POPEN: /* process trying to open a fifo */ 523 break; 524 525 case FP_BLOCKED_ON_CDEV: /* process blocked on character device I/O */ 526 status = cdev_cancel(fp->fp_cdev.dev, fp->fp_cdev.endpt, 527 fp->fp_cdev.grant); 528 529 break; 530 default : 531 panic("VFS: unknown block reason: %d", blocked_on); 532 } 533 534 if ((blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_POPEN)&& 535 !wasreviving) { 536 susp_count--; 537 } 538 539 replycode(fp->fp_endpoint, status); /* signal interrupted call */ 540 } 541