/*===========================================================================*
 *				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);
}
Пример #2
0
/*===========================================================================*
 *				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);
}