/*===========================================================================* * close_fd * *===========================================================================*/ int close_fd(struct fproc * rfp, int fd_nr, int may_suspend) { /* Perform the close(fd) system call. */ register struct filp *rfilp; register struct vnode *vp; struct file_lock *flp; int r, lock_count; /* First locate the vnode that belongs to the file descriptor. */ if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_OPCL)) == NULL) return(err_code); vp = rfilp->filp_vno; /* first, make all future get_filp2()'s fail; otherwise * we might try to close the same fd in different threads */ rfp->fp_filp[fd_nr] = NULL; r = close_filp(rfilp, may_suspend); FD_CLR(fd_nr, &rfp->fp_cloexec_set); /* Check to see if the file is locked. If so, release all locks. */ if (nr_locks > 0) { lock_count = nr_locks; /* save count of locks */ for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) { if (flp->lock_type == 0) continue; /* slot not in use */ if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) { flp->lock_type = 0; nr_locks--; } } if (nr_locks < lock_count) lock_revive(); /* one or more locks released */ } return(r); }
/*===========================================================================* * do_close * *===========================================================================*/ PUBLIC int do_close() { /* Perform the close(fd) system call. */ register struct filp *rfilp; register struct inode *rip; struct file_lock *flp; int rw, mode_word, lock_count; dev_t dev; /* First locate the inode that belongs to the file descriptor. */ if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); rip = rfilp->filp_ino; /* 'rip' points to the inode */ if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) { /* Check to see if the file is special. */ mode_word = rip->i_mode & I_TYPE; if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) { dev = (dev_t) rip->i_zone[0]; if (mode_word == I_BLOCK_SPECIAL) { /* Invalidate cache entries unless special is mounted * or ROOT */ if (!mounted(rip)) { (void) do_sync(); /* purge cache */ invalidate(dev); } } /* Do any special processing on device close. */ dev_close(dev); } } /* If the inode being closed is a pipe, release everyone hanging on it. */ if (rip->i_pipe == I_PIPE) { rw = (rfilp->filp_mode & R_BIT ? WRITE : READ); release(rip, rw, NR_PROCS); } /* If a write has been done, the inode is already marked as DIRTY. */ if (--rfilp->filp_count == 0) { if (rip->i_pipe == I_PIPE && rip->i_count > 1) { /* Save the file position in the i-node in case needed later. * The read and write positions are saved separately. The * last 3 zones in the i-node are not used for (named) pipes. */ if (rfilp->filp_mode == R_BIT) rip->i_zone[V2_NR_DZONES+0] = (zone_t) rfilp->filp_pos; else rip->i_zone[V2_NR_DZONES+1] = (zone_t) rfilp->filp_pos; } put_inode(rip); } fp->fp_cloexec &= ~(1L << m_in.fd); /* turn off close-on-exec bit */ fp->fp_filp[m_in.fd] = NIL_FILP; FD_CLR(m_in.fd, &fp->fp_filp_inuse); /* Check to see if the file is locked. If so, release all locks. */ if (nr_locks == 0) return(OK); lock_count = nr_locks; /* save count of locks */ for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) { if (flp->lock_type == 0) continue; /* slot not in use */ if (flp->lock_inode == rip && flp->lock_pid == fp->fp_pid) { flp->lock_type = 0; nr_locks--; } } if (nr_locks < lock_count) lock_revive(); /* lock released */ return(OK); }