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. 298 * Store the parameters to be used upon resuming in the process table. 299 * (Actually they are not used when a process is waiting for an I/O device, 300 * but they are needed for pipes, and it is not worth making the distinction.) 301 * The SUSPEND pseudo error should be returned after calling suspend(). 302 */ 303 304 if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_PIPE) 305 /* #procs susp'ed on pipe*/ 306 susp_count++; 307 308 fp->fp_blocked_on = why; 309 assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant)); 310 fp->fp_block_callnr = job_call_nr; 311 } 312 313 /*===========================================================================* 314 * wait_for * 315 *===========================================================================*/ 316 void wait_for(endpoint_t who) 317 { 318 if(who == NONE || who == ANY) 319 panic("suspend on NONE or ANY"); 320 suspend(FP_BLOCKED_ON_OTHER); 321 fp->fp_task = who; 322 } 323 324 325 /*===========================================================================* 326 * pipe_suspend * 327 *===========================================================================*/ 328 void pipe_suspend(struct filp * filp __unused, vir_bytes buf, size_t size) 329 { 330 /* Take measures to suspend the processing of the present system call. 331 * Store the parameters to be used upon resuming in the process table. 332 */ 333 334 /* We can only get here through an I/O call, which comes with a file 335 * descriptor, and that file descriptor must therefore correspond to the 336 * target file pointer of the I/O request. The process is blocked on the I/O 337 * call, and thus, the file descriptor will remain valid. Therefore, we can, 338 * and will, use the file descriptor to get the file pointer again later. 339 */ 340 assert(fp->fp_filp[fp->fp_fd] == filp); 341 342 fp->fp_io_buffer = buf; 343 fp->fp_io_nbytes = size; 344 suspend(FP_BLOCKED_ON_PIPE); 345 } 346 347 348 /*===========================================================================* 349 * unsuspend_by_endpt * 350 *===========================================================================*/ 351 void unsuspend_by_endpt(endpoint_t proc_e) 352 { 353 /* Revive processes waiting for drivers (SUSPENDed) that have disappeared with 354 * return code EAGAIN. 355 */ 356 struct fproc *rp; 357 358 for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) { 359 if (rp->fp_pid == PID_FREE) continue; 360 if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e) 361 revive(rp->fp_endpoint, EIO); 362 } 363 364 /* Revive processes waiting in drivers on select()s with EAGAIN too */ 365 select_unsuspend_by_endpt(proc_e); 366 367 return; 368 } 369 370 371 /*===========================================================================* 372 * release * 373 *===========================================================================*/ 374 void release(vp, op, count) 375 register struct vnode *vp; /* inode of pipe */ 376 int op; /* VFS_READ, VFS_WRITE, or VFS_OPEN */ 377 int count; /* max number of processes to release */ 378 { 379 /* Check to see if any process is hanging on vnode 'vp'. If one is, and it 380 * was trying to perform the call indicated by 'op', release it. 381 */ 382 383 register struct fproc *rp; 384 struct filp *f; 385 int selop; 386 387 /* Trying to perform the call also includes SELECTing on it with that 388 * operation. 389 */ 390 if (op == VFS_READ || op == VFS_WRITE) { 391 if (op == VFS_READ) 392 selop = SEL_RD; 393 else 394 selop = SEL_WR; 395 396 for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { 397 if (f->filp_count < 1 || !(f->filp_pipe_select_ops & selop) || 398 f->filp_vno != vp) 399 continue; 400 401 select_callback(f, selop); 402 403 f->filp_pipe_select_ops &= ~selop; 404 } 405 } 406 407 /* Search the proc table. */ 408 for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) { 409 if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) && 410 !(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op) { 411 /* Find the vnode. Depending on the reason the process was 412 * suspended, there are different ways of finding it. 413 */ 414 415 if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN || 416 rp->fp_blocked_on == FP_BLOCKED_ON_PIPE || 417 rp->fp_blocked_on == FP_BLOCKED_ON_LOCK || 418 rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) { 419 f = rp->fp_filp[rp->fp_fd]; 420 if (f == NULL || f->filp_mode == FILP_CLOSED) 421 continue; 422 if (f->filp_vno != vp) 423 continue; 424 } else 425 continue; 426 427 /* We found the vnode. Revive process. */ 428 revive(rp->fp_endpoint, 0); 429 susp_count--; /* keep track of who is suspended */ 430 if(susp_count < 0) 431 panic("susp_count now negative: %d", susp_count); 432 if (--count == 0) return; 433 } 434 } 435 } 436 437 438 /*===========================================================================* 439 * revive * 440 *===========================================================================*/ 441 void revive(endpoint_t proc_e, int returned) 442 { 443 /* Revive a previously blocked process. When a process hangs on tty, this 444 * is the way it is eventually released. For processes blocked on _SELECT and 445 * _OTHER, this function MUST NOT block its calling thread. 446 */ 447 struct fproc *rfp; 448 int blocked_on; 449 int fd_nr, slot; 450 451 if (proc_e == NONE || isokendpt(proc_e, &slot) != OK) return; 452 453 rfp = &fproc[slot]; 454 if (!fp_is_blocked(rfp) || (rfp->fp_flags & FP_REVIVED)) return; 455 456 /* The 'reviving' flag only applies to pipes. Processes waiting for TTY get 457 * a message right away. The revival process is different for TTY and pipes. 458 * For select and TTY revival, the work is already done, for pipes it is not: 459 * the proc must be restarted so it can try again. 460 */ 461 blocked_on = rfp->fp_blocked_on; 462 fd_nr = rfp->fp_fd; 463 if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_LOCK) { 464 /* Revive a process suspended on a pipe or lock. */ 465 rfp->fp_flags |= FP_REVIVED; 466 reviving++; /* process was waiting on pipe or lock */ 467 } else { 468 rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; 469 /* TODO: we could reset rfp->fp_fd to (e.g.) -1 here, but since its 470 * value is not always bounds checked elsewhere, this might do more 471 * harm than good right now. 472 */ 473 if (blocked_on == FP_BLOCKED_ON_POPEN) { 474 /* process blocked in open or create */ 475 replycode(proc_e, fd_nr); 476 } else if (blocked_on == FP_BLOCKED_ON_SELECT) { 477 replycode(proc_e, returned); 478 } else { 479 /* Revive a process suspended on TTY or other device. 480 * Pretend it wants only what there is. 481 */ 482 rfp->fp_io_nbytes = returned; 483 /* If a grant has been issued by FS for this I/O, revoke 484 * it again now that I/O is done. 485 */ 486 if (GRANT_VALID(rfp->fp_grant)) { 487 if(cpf_revoke(rfp->fp_grant) == -1) { 488 panic("VFS: revoke failed for grant: %d", 489 rfp->fp_grant); 490 } 491 rfp->fp_grant = GRANT_INVALID; 492 } 493 replycode(proc_e, returned);/* unblock the process */ 494 } 495 } 496 } 497 498 499 /*===========================================================================* 500 * unpause * 501 *===========================================================================*/ 502 void unpause(void) 503 { 504 /* A signal has been sent to a user who is paused on the file system. 505 * Abort the system call with the EINTR error message. 506 */ 507 int blocked_on, fild, status = EINTR; 508 struct filp *f; 509 dev_t dev; 510 int wasreviving = 0; 511 512 if (!fp_is_blocked(fp)) return; 513 blocked_on = fp->fp_blocked_on; 514 515 /* Clear the block status now. The procedure below might make blocking calls 516 * and it is imperative that while at least cdev_cancel() is executing, other 517 * parts of VFS do not perceive this process as blocked on something. 518 */ 519 fp->fp_blocked_on = FP_BLOCKED_ON_NONE; 520 521 if (fp->fp_flags & FP_REVIVED) { 522 fp->fp_flags &= ~FP_REVIVED; 523 reviving--; 524 wasreviving = 1; 525 } 526 527 switch (blocked_on) { 528 case FP_BLOCKED_ON_PIPE:/* process trying to read or write a pipe */ 529 /* If the operation succeeded partially, return the bytes 530 * processed so far, and clear the remembered state. Otherwise, 531 * return EINTR as usual. 532 */ 533 if (fp->fp_cum_io_partial > 0) { 534 status = fp->fp_cum_io_partial; 535 536 fp->fp_cum_io_partial = 0; 537 } 538 break; 539 540 case FP_BLOCKED_ON_LOCK:/* process trying to set a lock with FCNTL */ 541 break; 542 543 case FP_BLOCKED_ON_SELECT:/* process blocking on select() */ 544 select_forget(); 545 break; 546 547 case FP_BLOCKED_ON_POPEN: /* process trying to open a fifo */ 548 break; 549 550 case FP_BLOCKED_ON_OTHER:/* process trying to do device I/O (e.g. tty)*/ 551 fild = fp->fp_fd; 552 if (fild < 0 || fild >= OPEN_MAX) 553 panic("file descriptor out-of-range"); 554 f = fp->fp_filp[fild]; 555 if(!f) { 556 sys_diagctl_stacktrace(fp->fp_endpoint); 557 panic("process %d blocked on empty fd %d", 558 fp->fp_endpoint, fild); 559 } 560 dev = f->filp_vno->v_sdev; /* device hung on */ 561 562 status = cdev_cancel(dev); 563 564 break; 565 default : 566 panic("VFS: unknown block reason: %d", blocked_on); 567 } 568 569 if ((blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_POPEN)&& 570 !wasreviving) { 571 susp_count--; 572 } 573 574 replycode(fp->fp_endpoint, status); /* signal interrupted call */ 575 } 576