1 /* This file contains the procedures for creating, opening, closing, and 2 * seeking on files. 3 * 4 * The entry points into this file are 5 * do_open: perform the OPEN system call 6 * do_mknod: perform the MKNOD system call 7 * do_mkdir: perform the MKDIR system call 8 * do_close: perform the CLOSE system call 9 * do_lseek: perform the LSEEK system call 10 */ 11 12 #include "fs.h" 13 #include <sys/stat.h> 14 #include <fcntl.h> 15 #include <string.h> 16 #include <unistd.h> 17 #include <minix/callnr.h> 18 #include <minix/com.h> 19 #include <minix/u64.h> 20 #include "file.h" 21 #include "lock.h" 22 #include <sys/dirent.h> 23 #include <assert.h> 24 #include <minix/vfsif.h> 25 #include "vnode.h" 26 #include "vmnt.h" 27 #include "path.h" 28 29 static char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0}; 30 31 static struct vnode *new_node(struct lookup *resolve, int oflags, 32 mode_t bits); 33 static int pipe_open(struct vnode *vp, mode_t bits, int oflags); 34 35 /*===========================================================================* 36 * do_open * 37 *===========================================================================*/ 38 int do_open(void) 39 { 40 /* Perform the open(name, flags) system call with O_CREAT *not* set. */ 41 int open_flags; 42 char fullpath[PATH_MAX]; 43 44 open_flags = job_m_in.m_lc_vfs_path.flags; 45 46 if (open_flags & O_CREAT) 47 return EINVAL; 48 49 if (copy_path(fullpath, sizeof(fullpath)) != OK) 50 return(err_code); 51 52 return common_open(fullpath, open_flags, 0 /*omode*/, FALSE /*for_exec*/); 53 } 54 55 /*===========================================================================* 56 * do_creat * 57 *===========================================================================*/ 58 int do_creat(void) 59 { 60 /* Perform the open(name, flags, mode) system call with O_CREAT set. */ 61 int open_flags, create_mode; 62 char fullpath[PATH_MAX]; 63 vir_bytes vname; 64 size_t vname_length; 65 66 vname = job_m_in.m_lc_vfs_creat.name; 67 vname_length = job_m_in.m_lc_vfs_creat.len; 68 open_flags = job_m_in.m_lc_vfs_creat.flags; 69 create_mode = job_m_in.m_lc_vfs_creat.mode; 70 71 if (!(open_flags & O_CREAT)) 72 return(EINVAL); 73 74 if (fetch_name(vname, vname_length, fullpath) != OK) 75 return(err_code); 76 77 return common_open(fullpath, open_flags, create_mode, FALSE /*for_exec*/); 78 } 79 80 /*===========================================================================* 81 * common_open * 82 *===========================================================================*/ 83 int common_open(char path[PATH_MAX], int oflags, mode_t omode, int for_exec) 84 { 85 /* Common code from do_creat and do_open. */ 86 int b, r, exist = TRUE; 87 devmajor_t major_dev; 88 dev_t dev; 89 mode_t bits; 90 struct filp *filp, *filp2; 91 struct vnode *vp; 92 struct vmnt *vmp; 93 struct dmap *dp; 94 struct lookup resolve; 95 int start = 0; 96 97 /* Remap the bottom two bits of oflags. */ 98 bits = (mode_t) mode_map[oflags & O_ACCMODE]; 99 if (!bits) return(EINVAL); 100 101 /* See if file descriptor and filp slots are available. */ 102 if ((r = get_fd(fp, start, bits, &fp->fp_fd, &filp)) != OK) 103 return(r); 104 105 lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); 106 107 /* If O_CREATE is set, try to make the file. */ 108 if (oflags & O_CREAT) { 109 omode = I_REGULAR | (omode & ALLPERMS & fp->fp_umask); 110 vp = new_node(&resolve, oflags, omode); 111 r = err_code; 112 if (r == OK) exist = FALSE; /* We just created the file */ 113 else if (r != EEXIST) { /* other error */ 114 if (vp) unlock_vnode(vp); 115 unlock_filp(filp); 116 return(r); 117 } 118 else exist = !(oflags & O_EXCL);/* file exists, if the O_EXCL 119 flag is set this is an error */ 120 } else { 121 /* Scan path name */ 122 resolve.l_vmnt_lock = VMNT_READ; 123 resolve.l_vnode_lock = VNODE_OPCL; 124 if ((vp = eat_path(&resolve, fp)) == NULL) { 125 unlock_filp(filp); 126 return(err_code); 127 } 128 129 if (vmp != NULL) unlock_vmnt(vmp); 130 } 131 132 /* Claim the file descriptor and filp slot and fill them in. */ 133 fp->fp_filp[fp->fp_fd] = filp; 134 filp->filp_count = 1; 135 filp->filp_vno = vp; 136 filp->filp_flags = oflags; 137 if (oflags & O_CLOEXEC) 138 FD_SET(fp->fp_fd, &fp->fp_cloexec_set); 139 140 /* Only do the normal open code if we didn't just create the file. */ 141 if (exist) { 142 /* Check permissions based on the given open flags, except when we are 143 * opening an executable for the purpose of passing a file descriptor 144 * to its interpreter for execution, in which case we check the X bit. 145 */ 146 if ((r = forbidden(fp, vp, for_exec ? X_BIT : bits)) == OK) { 147 /* Opening reg. files, directories, and special files differ */ 148 switch (vp->v_mode & S_IFMT) { 149 case S_IFREG: 150 /* Truncate regular file if O_TRUNC. */ 151 if (oflags & O_TRUNC) { 152 if ((r = forbidden(fp, vp, W_BIT)) != OK) 153 break; 154 upgrade_vnode_lock(vp); 155 truncate_vnode(vp, 0); 156 } 157 break; 158 case S_IFDIR: 159 /* Directories may be read but not written. */ 160 r = (bits & W_BIT ? EISDIR : OK); 161 break; 162 case S_IFCHR: 163 /* Invoke the driver for special processing. */ 164 dev = vp->v_sdev; 165 /* TTY needs to know about the O_NOCTTY flag. */ 166 r = cdev_open(dev, bits | (oflags & O_NOCTTY)); 167 vp = filp->filp_vno; /* Might be updated by 168 * cdev_open after cloning */ 169 break; 170 case S_IFBLK: 171 172 lock_bsf(); 173 174 /* Invoke the driver for special processing. */ 175 dev = vp->v_sdev; 176 r = bdev_open(dev, bits); 177 if (r != OK) { 178 unlock_bsf(); 179 break; 180 } 181 182 major_dev = major(vp->v_sdev); 183 dp = &dmap[major_dev]; 184 if (dp->dmap_driver == NONE) { 185 printf("VFS: block driver disappeared!\n"); 186 unlock_bsf(); 187 r = ENXIO; 188 break; 189 } 190 191 /* Check whether the device is mounted or not. If so, 192 * then that FS is responsible for this device. 193 * Otherwise we default to ROOT_FS. 194 */ 195 vp->v_bfs_e = ROOT_FS_E; /* By default */ 196 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) 197 if (vmp->m_dev == vp->v_sdev && 198 !(vmp->m_flags & VMNT_FORCEROOTBSF)) { 199 vp->v_bfs_e = vmp->m_fs_e; 200 } 201 202 /* Send the driver label to the file system that will 203 * handle the block I/O requests (even when its label 204 * and endpoint are known already), but only when it is 205 * the root file system. Other file systems will 206 * already have it anyway. 207 */ 208 if (vp->v_bfs_e != ROOT_FS_E) { 209 unlock_bsf(); 210 break; 211 } 212 213 if (req_newdriver(vp->v_bfs_e, vp->v_sdev, 214 dp->dmap_label) != OK) { 215 printf("VFS: error sending driver label\n"); 216 bdev_close(dev); 217 r = ENXIO; 218 } 219 unlock_bsf(); 220 break; 221 222 case S_IFIFO: 223 /* Create a mapped inode on PFS which handles reads 224 and writes to this named pipe. */ 225 upgrade_vnode_lock(vp); 226 r = map_vnode(vp, PFS_PROC_NR); 227 if (r == OK) { 228 if (vp->v_ref_count == 1) { 229 if (vp->v_size != 0) 230 r = truncate_vnode(vp, 0); 231 } 232 oflags |= O_APPEND; /* force append mode */ 233 filp->filp_flags = oflags; 234 } 235 if (r == OK) { 236 r = pipe_open(vp, bits, oflags); 237 } 238 if (r != ENXIO) { 239 /* See if someone else is doing a rd or wt on 240 * the FIFO. If so, use its filp entry so the 241 * file position will be automatically shared. 242 */ 243 b = (bits & R_BIT ? R_BIT : W_BIT); 244 filp->filp_count = 0; /* don't find self */ 245 if ((filp2 = find_filp(vp, b)) != NULL) { 246 /* Co-reader or writer found. Use it.*/ 247 fp->fp_filp[fp->fp_fd] = filp2; 248 filp2->filp_count++; 249 filp2->filp_vno = vp; 250 filp2->filp_flags = oflags; 251 252 /* v_count was incremented after the vnode 253 * has been found. i_count was incremented 254 * incorrectly in FS, not knowing that we 255 * were going to use an existing filp 256 * entry. Correct this error. 257 */ 258 unlock_vnode(vp); 259 put_vnode(vp); 260 } else { 261 /* Nobody else found. Restore filp. */ 262 filp->filp_count = 1; 263 } 264 } 265 break; 266 } 267 } 268 } 269 270 unlock_filp(filp); 271 272 /* If error, release inode. */ 273 if (r != OK) { 274 if (r != SUSPEND) { 275 fp->fp_filp[fp->fp_fd] = NULL; 276 filp->filp_count = 0; 277 filp->filp_vno = NULL; 278 put_vnode(vp); 279 } 280 } else { 281 r = fp->fp_fd; 282 } 283 284 return(r); 285 } 286 287 288 /*===========================================================================* 289 * new_node * 290 *===========================================================================*/ 291 static struct vnode *new_node(struct lookup *resolve, int oflags, mode_t bits) 292 { 293 /* Try to create a new inode and return a pointer to it. If the inode already 294 exists, return a pointer to it as well, but set err_code accordingly. 295 NULL is returned if the path cannot be resolved up to the last 296 directory, or when the inode cannot be created due to permissions or 297 otherwise. */ 298 struct vnode *dirp, *vp; 299 struct vmnt *dir_vmp, *vp_vmp; 300 int r; 301 struct node_details res; 302 struct lookup findnode; 303 char *path; 304 305 path = resolve->l_path; /* For easy access */ 306 307 lookup_init(&findnode, path, resolve->l_flags, &dir_vmp, &dirp); 308 findnode.l_vmnt_lock = VMNT_WRITE; 309 findnode.l_vnode_lock = VNODE_WRITE; /* dir node */ 310 311 /* When O_CREAT and O_EXCL flags are set, the path may not be named by a 312 * symbolic link. */ 313 if (oflags & O_EXCL) findnode.l_flags |= PATH_RET_SYMLINK; 314 315 /* See if the path can be opened down to the last directory. */ 316 if ((dirp = last_dir(&findnode, fp)) == NULL) return(NULL); 317 318 /* The final directory is accessible. Get final component of the path. */ 319 lookup_init(&findnode, findnode.l_path, findnode.l_flags, &vp_vmp, &vp); 320 findnode.l_vmnt_lock = VMNT_WRITE; 321 findnode.l_vnode_lock = (oflags & O_TRUNC) ? VNODE_WRITE : VNODE_OPCL; 322 vp = advance(dirp, &findnode, fp); 323 assert(vp_vmp == NULL); /* Lookup to last dir should have yielded lock 324 * on vmp or final component does not exist. 325 * Either way, vp_vmp ought to be not set. 326 */ 327 328 /* The combination of a symlink with absolute path followed by a danglink 329 * symlink results in a new path that needs to be re-resolved entirely. */ 330 if (path[0] == '/') { 331 unlock_vnode(dirp); 332 unlock_vmnt(dir_vmp); 333 put_vnode(dirp); 334 if (vp != NULL) { 335 unlock_vnode(vp); 336 put_vnode(vp); 337 } 338 return new_node(resolve, oflags, bits); 339 } 340 341 if (vp == NULL && err_code == ENOENT) { 342 /* Last path component does not exist. Make a new directory entry. */ 343 if ((vp = get_free_vnode()) == NULL) { 344 /* Can't create new entry: out of vnodes. */ 345 unlock_vnode(dirp); 346 unlock_vmnt(dir_vmp); 347 put_vnode(dirp); 348 return(NULL); 349 } 350 351 lock_vnode(vp, VNODE_OPCL); 352 upgrade_vmnt_lock(dir_vmp); /* Creating file, need exclusive access */ 353 354 if ((r = forbidden(fp, dirp, W_BIT|X_BIT)) != OK || 355 (r = req_create(dirp->v_fs_e, dirp->v_inode_nr,bits, fp->fp_effuid, 356 fp->fp_effgid, path, &res)) != OK ) { 357 /* Can't create inode either due to permissions or some other 358 * problem. In case r is EEXIST, we might be dealing with a 359 * dangling symlink.*/ 360 361 /* Downgrade lock to prevent deadlock during symlink resolving*/ 362 downgrade_vmnt_lock(dir_vmp); 363 364 if (r == EEXIST) { 365 struct vnode *slp, *old_wd; 366 367 368 /* Resolve path up to symlink */ 369 findnode.l_flags = PATH_RET_SYMLINK; 370 findnode.l_vnode_lock = VNODE_READ; 371 findnode.l_vnode = &slp; 372 slp = advance(dirp, &findnode, fp); 373 if (slp != NULL) { 374 if (S_ISLNK(slp->v_mode)) { 375 /* Get contents of link */ 376 377 r = req_rdlink(slp->v_fs_e, 378 slp->v_inode_nr, 379 VFS_PROC_NR, 380 (vir_bytes) path, 381 PATH_MAX - 1, 0); 382 if (r < 0) { 383 /* Failed to read link */ 384 unlock_vnode(slp); 385 unlock_vnode(dirp); 386 unlock_vmnt(dir_vmp); 387 put_vnode(slp); 388 put_vnode(dirp); 389 err_code = r; 390 return(NULL); 391 } 392 path[r] = '\0'; /* Terminate path */ 393 } 394 unlock_vnode(slp); 395 put_vnode(slp); 396 } 397 398 /* Try to create the inode the dangling symlink was 399 * pointing to. We have to use dirp as starting point 400 * as there might be multiple successive symlinks 401 * crossing multiple mountpoints. 402 * Unlock vnodes and vmnts as we're going to recurse. 403 */ 404 unlock_vnode(dirp); 405 unlock_vnode(vp); 406 unlock_vmnt(dir_vmp); 407 408 old_wd = fp->fp_wd; /* Save orig. working dirp */ 409 fp->fp_wd = dirp; 410 vp = new_node(resolve, oflags, bits); 411 fp->fp_wd = old_wd; /* Restore */ 412 413 if (vp != NULL) { 414 put_vnode(dirp); 415 *(resolve->l_vnode) = vp; 416 return(vp); 417 } 418 r = err_code; 419 } 420 421 if (r == EEXIST) 422 err_code = EIO; /* Impossible, we have verified that 423 * the last component doesn't exist and 424 * is not a dangling symlink. */ 425 else 426 err_code = r; 427 428 unlock_vmnt(dir_vmp); 429 unlock_vnode(dirp); 430 unlock_vnode(vp); 431 put_vnode(dirp); 432 return(NULL); 433 } 434 435 /* Store results and mark vnode in use */ 436 437 vp->v_fs_e = res.fs_e; 438 vp->v_inode_nr = res.inode_nr; 439 vp->v_mode = res.fmode; 440 vp->v_size = res.fsize; 441 vp->v_uid = res.uid; 442 vp->v_gid = res.gid; 443 vp->v_sdev = res.dev; 444 vp->v_vmnt = dirp->v_vmnt; 445 vp->v_dev = vp->v_vmnt->m_dev; 446 vp->v_fs_count = 1; 447 vp->v_ref_count = 1; 448 } else { 449 /* Either last component exists, or there is some other problem. */ 450 if (vp != NULL) { 451 r = EEXIST; /* File exists or a symlink names a file while 452 * O_EXCL is set. */ 453 } else 454 r = err_code; /* Other problem. */ 455 } 456 457 err_code = r; 458 /* When dirp equals vp, we shouldn't release the lock as a vp is locked only 459 * once. Releasing the lock would cause the resulting vp not be locked and 460 * cause mayhem later on. */ 461 if (dirp != vp) { 462 unlock_vnode(dirp); 463 } 464 unlock_vmnt(dir_vmp); 465 put_vnode(dirp); 466 467 *(resolve->l_vnode) = vp; 468 return(vp); 469 } 470 471 472 /*===========================================================================* 473 * pipe_open * 474 *===========================================================================*/ 475 static int pipe_open(struct vnode *vp, mode_t bits, int oflags) 476 { 477 /* This function is called from common_open. It checks if 478 * there is at least one reader/writer pair for the pipe, if not 479 * it suspends the caller, otherwise it revives all other blocked 480 * processes hanging on the pipe. 481 */ 482 483 if ((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO); 484 485 /* Find the reader/writer at the other end of the pipe */ 486 if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NULL) { 487 /* Not found */ 488 if (oflags & O_NONBLOCK) { 489 if (bits & W_BIT) return(ENXIO); 490 } else { 491 /* Let's wait for the other side to show up */ 492 suspend(FP_BLOCKED_ON_POPEN); 493 return(SUSPEND); 494 } 495 } else if (susp_count > 0) { /* revive blocked processes */ 496 release(vp, VFS_OPEN, susp_count); 497 } 498 return(OK); 499 } 500 501 502 /*===========================================================================* 503 * do_mknod * 504 *===========================================================================*/ 505 int do_mknod(void) 506 { 507 /* Perform the mknod(name, mode, addr) system call. */ 508 register mode_t bits, mode_bits; 509 int r; 510 struct vnode *vp; 511 struct vmnt *vmp; 512 char fullpath[PATH_MAX]; 513 struct lookup resolve; 514 vir_bytes vname1; 515 size_t vname1_length; 516 dev_t dev; 517 518 vname1 = job_m_in.m_lc_vfs_mknod.name; 519 vname1_length = job_m_in.m_lc_vfs_mknod.len; 520 mode_bits = job_m_in.m_lc_vfs_mknod.mode; 521 dev = job_m_in.m_lc_vfs_mknod.device; 522 523 lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); 524 resolve.l_vmnt_lock = VMNT_WRITE; 525 resolve.l_vnode_lock = VNODE_WRITE; 526 527 /* Only the super_user may make nodes other than fifos. */ 528 if (!super_user && (!S_ISFIFO(mode_bits) && !S_ISSOCK(mode_bits))) { 529 return(EPERM); 530 } 531 bits = (mode_bits & S_IFMT) | (mode_bits & ACCESSPERMS & fp->fp_umask); 532 533 /* Open directory that's going to hold the new node. */ 534 if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); 535 if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); 536 537 /* Make sure that the object is a directory */ 538 if (!S_ISDIR(vp->v_mode)) { 539 r = ENOTDIR; 540 } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { 541 r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, 542 fp->fp_effgid, bits, dev); 543 } 544 545 unlock_vnode(vp); 546 unlock_vmnt(vmp); 547 put_vnode(vp); 548 return(r); 549 } 550 551 /*===========================================================================* 552 * do_mkdir * 553 *===========================================================================*/ 554 int do_mkdir(void) 555 { 556 /* Perform the mkdir(name, mode) system call. */ 557 mode_t bits; /* mode bits for the new inode */ 558 int r; 559 struct vnode *vp; 560 struct vmnt *vmp; 561 char fullpath[PATH_MAX]; 562 struct lookup resolve; 563 mode_t dirmode; 564 565 if (copy_path(fullpath, sizeof(fullpath)) != OK) 566 return(err_code); 567 dirmode = job_m_in.m_lc_vfs_path.mode; 568 569 lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); 570 resolve.l_vmnt_lock = VMNT_WRITE; 571 resolve.l_vnode_lock = VNODE_WRITE; 572 573 bits = I_DIRECTORY | (dirmode & RWX_MODES & fp->fp_umask); 574 if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); 575 576 /* Make sure that the object is a directory */ 577 if (!S_ISDIR(vp->v_mode)) { 578 r = ENOTDIR; 579 } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { 580 r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, 581 fp->fp_effgid, bits); 582 } 583 584 unlock_vnode(vp); 585 unlock_vmnt(vmp); 586 put_vnode(vp); 587 return(r); 588 } 589 590 /*===========================================================================* 591 * actual_lseek * 592 *===========================================================================*/ 593 int actual_lseek(struct fproc *rfp, int seekfd, int seekwhence, off_t offset, 594 off_t *newposp) 595 { 596 register struct filp *rfilp; 597 int r = OK; 598 off_t pos, newpos; 599 600 /* Check to see if the file descriptor is valid. */ 601 if ( (rfilp = get_filp2(rfp, seekfd, VNODE_READ)) == NULL) { 602 return(err_code); 603 } 604 605 /* No lseek on pipes. */ 606 if (S_ISFIFO(rfilp->filp_vno->v_mode)) { 607 unlock_filp(rfilp); 608 return(ESPIPE); 609 } 610 611 /* The value of 'whence' determines the start position to use. */ 612 switch(seekwhence) { 613 case SEEK_SET: pos = 0; break; 614 case SEEK_CUR: pos = rfilp->filp_pos; break; 615 case SEEK_END: pos = rfilp->filp_vno->v_size; break; 616 default: unlock_filp(rfilp); return(EINVAL); 617 } 618 619 newpos = pos + offset; 620 621 /* Check for overflow. */ 622 if ((offset > 0) && (newpos <= pos)) { 623 r = EOVERFLOW; 624 } else if ((offset < 0) && (newpos >= pos)) { 625 r = EOVERFLOW; 626 } else { 627 if (newposp != NULL) *newposp = newpos; 628 629 if (newpos != rfilp->filp_pos) { 630 rfilp->filp_pos = newpos; 631 632 /* Inhibit read ahead request */ 633 r = req_inhibread(rfilp->filp_vno->v_fs_e, 634 rfilp->filp_vno->v_inode_nr); 635 } 636 } 637 638 unlock_filp(rfilp); 639 return(r); 640 } 641 642 /*===========================================================================* 643 * do_lseek * 644 *===========================================================================*/ 645 int do_lseek(void) 646 { 647 /* Perform the lseek(2) system call. */ 648 off_t newpos = 0; 649 int r; 650 651 if ((r = actual_lseek(fp, job_m_in.m_lc_vfs_lseek.fd, 652 job_m_in.m_lc_vfs_lseek.whence, job_m_in.m_lc_vfs_lseek.offset, 653 &newpos)) != OK) 654 return r; 655 656 /* insert the new position into the output message */ 657 job_m_out.m_vfs_lc_lseek.offset = newpos; 658 return OK; 659 } 660 661 /*===========================================================================* 662 * do_close * 663 *===========================================================================*/ 664 int do_close(void) 665 { 666 /* Perform the close(fd) system call. */ 667 int thefd = job_m_in.m_lc_vfs_close.fd; 668 return close_fd(fp, thefd); 669 } 670 671 672 /*===========================================================================* 673 * close_fd * 674 *===========================================================================*/ 675 int close_fd(rfp, fd_nr) 676 struct fproc *rfp; 677 int fd_nr; 678 { 679 /* Perform the close(fd) system call. */ 680 register struct filp *rfilp; 681 register struct vnode *vp; 682 struct file_lock *flp; 683 int lock_count; 684 685 /* First locate the vnode that belongs to the file descriptor. */ 686 if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_OPCL)) == NULL) return(err_code); 687 688 vp = rfilp->filp_vno; 689 690 /* first, make all future get_filp2()'s fail; otherwise 691 * we might try to close the same fd in different threads 692 */ 693 rfp->fp_filp[fd_nr] = NULL; 694 695 close_filp(rfilp); 696 697 FD_CLR(fd_nr, &rfp->fp_cloexec_set); 698 699 /* Check to see if the file is locked. If so, release all locks. */ 700 if (nr_locks > 0) { 701 lock_count = nr_locks; /* save count of locks */ 702 for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) { 703 if (flp->lock_type == 0) continue; /* slot not in use */ 704 if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) { 705 flp->lock_type = 0; 706 nr_locks--; 707 } 708 } 709 if (nr_locks < lock_count) 710 lock_revive(); /* one or more locks released */ 711 } 712 713 return(OK); 714 } 715