⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gfs_gnodeops.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
				goto done;			}		}		if (mode == GFBLK) {			/*			 * On last close of a block device (that isn't mounted)			 * we must invalidate any in core blocks, so that			 * we can, for instance, change floppy disks.			 */			GETMP(mp, dev);			/*			 * If GETMP returns a mp, then the block device			 * is mounted on, so return.			 */			if (mp != NULL) {				/*				 * Decrement ref count in gnode				 */				grele(gp);				goto done;			}			bflush(dev, (struct gnode *) 0, 0);			binval(dev, (struct gnode *) 0);		}		if (setjmp(&u.u_qsave)) {			/*			 * If device close routine is interrupted,			 * must return so closef can clean up.			 */			 if (u.u_error == 0)			 	u.u_error = EINTR;	/* ??? */			 goto done;		}	}	if (GCLOSE(gp, flag) == GNOFUNC)		u.u_error = EOPNOTSUPP;	if (mode == GFBLK || mode == GFCHR)		divorce_dev(gp->g_rdev, mode);	gfs_lock(gp);	gput(gp);done:	return(u.u_error);}/* * Place an advisory lock on an inode. */gno_lock(fp, cmd)	register struct file *fp;	register int cmd;{	register int priority = PLOCK;	register struct gnode *gp = (struct gnode *)fp->f_data;	if ((cmd & LOCK_EX) == 0)		priority++;	if (setjmp(&u.u_qsave)) {                if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)                        return(EINTR);		u.u_eosys = RESTARTSYS;                return (0);        }	/*	 * If there's a exclusive lock currently applied	 * to the file, then we've gotta wait for the	 * lock with everyone else.	 */again:	/* SMP lock gnode during locking operation */	gfs_lock(gp);	while (gp->g_flag & GEXLOCK) {		/*		 * If we're holding an exclusive		 * lock, then release it.		 */		if (fp->f_flag & FEXLOCK) {			gno_unlock(fp, FEXLOCK);			continue;		}		if (cmd & LOCK_NB) {			gfs_unlock(gp);                        return (EWOULDBLOCK);		}		gp->g_flag |= GLWAIT;		sleep_unlock((caddr_t)&gp->g_exlockc, priority, &gp->g_lk);		gfs_lock(gp);	}	if (cmd & LOCK_EX && (gp->g_flag & GSHLOCK)) {		/*		 * Must wait for any shared locks to finish		 * before we try to apply a exclusive lock.		 *                 * If we're holding a shared                 * lock, then release it.		 */		if (fp->f_flag & FSHLOCK) {			gno_unlock(fp, FSHLOCK);			gfs_unlock(gp);			goto again;		}		if (cmd & LOCK_NB) {			gfs_unlock(gp);                        return (EWOULDBLOCK);		}		gp->g_flag |= GLWAIT;		sleep_unlock((caddr_t)&gp->g_shlockc, PLOCK, &gp->g_lk);		goto again;	}	if (fp->f_flag & FEXLOCK)		panic("gno_lock");	if (cmd & LOCK_EX) {		cmd &= ~LOCK_SH;		gp->g_exlockc++;		gp->g_flag |= GEXLOCK;		fp->f_flag |= FEXLOCK;	}	if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {		gp->g_shlockc++;		gp->g_flag |= GSHLOCK;		fp->f_flag |= FSHLOCK;	}	gfs_unlock(gp);	return (0);}/* * Unlock a file. */gno_unlock(fp, kind)	register struct file *fp;	register int kind;{	register struct gnode *gp = (struct gnode *)fp->f_data;	register int flags;	register int unlck = 0;	kind &= fp->f_flag;	if (gp == NULL || kind == 0)		return;	/* Will be true when gno_unlock is called from flock()	*/	if (!smp_owner(&gp->g_lk)) {		unlck = 1;		gfs_lock(gp);	}	flags = gp->g_flag;	if (kind & FSHLOCK) {		if ((flags & GSHLOCK) == 0)			panic("gno_unlock: SHLOCK");		if (--gp->g_shlockc == 0) {			gp->g_flag &= ~GSHLOCK;			if (flags & GLWAIT)				wakeup((caddr_t)&gp->g_shlockc);		}		fp->f_flag &= ~FSHLOCK;	}	if (kind & FEXLOCK) {		if ((flags & GEXLOCK) == 0)			panic("gno_unlock: EXLOCK");		if (--gp->g_exlockc == 0) {			gp->g_flag &= ~(GEXLOCK|GLWAIT);			if (flags & GLWAIT)				wakeup((caddr_t)&gp->g_exlockc);		}		fp->f_flag &= ~FEXLOCK;	}	if (unlck)		gfs_unlock(gp);}/* * Revoke access the current tty by all processes. * Used only by the super-user in init * to give ``clean'' terminals at login. */vhangup(){	struct tty *tp;	if (!suser())		return;	if ((tp = u.u_procp->p_ttyp) == NULL)		return;	forceclose(u.u_ttyd);	if ((tp->t_state) & TS_ISOPEN)		gsignal(tp->t_pgrp, SIGHUP);}/* * vhangup() is called when a terminal line is to be cleared of any * references by any other process when a login is attempted. This * handles the case where a terminal line is open and a login occured * on the same line, any write (or read or select or....) will be * handled by the divorceops.  */#define	D_TO_TTY(dev) \		(cdevsw[major((dev))].d_ttys \		? (struct tty *)&cdevsw[major(dev)].d_ttys[minor(dev)] \		: (struct tty *)0)forceclose(dev)	dev_t dev;{	struct tty *tp = D_TO_TTY(dev);	int saveaffinity;	int flag;	if (flag = divorce_dev(dev, GFCHR)) {		CALL_TO_NONSMP_DRIVER(cdevsw[major(dev)], saveaffinity);		(*cdevsw[major(dev)].d_close) (dev, flag);		RETURN_FROM_NONSMP_DRIVER(cdevsw[major(dev)], saveaffinity);	}	/*	 *  zap ctltty so /dev/tty connection is broken	 */	if (tp) {	    FORALLPROC(		if (pp->p_ttyp == tp && proc_get(pp->p_pid) == pp) {		    if (pp->p_ttyp == tp)	/* change during proc_get? */			pp->p_ttyp = (struct tty *)0;		    proc_rele(pp);	    }		       )	}	/*	 * Since a call to the drivers close routine can take a real	 * long time, lets do it again for any file table enties that	 * were being opened while we were blocked closing the device.	 */	divorce_dev(dev, GFCHR);}/* * divorce_dev() will walk through the file table. setting the file ops * vector array to divorce_ops. Any further requests with the file * descriptor will result in an error. When the file descriptor is closed, * the gnode reference count will be decremented as always. */divorce_dev(dev, mode)	dev_t dev;	int mode;{	register struct file *fp;	register struct gnode *gp;	register caddr_t value;	int flag = 0;top:	/*	 * We hold the file table througout the search because	 * f_data is now protected with it (if f_type == DTYPE_INODE).	 */	smp_lock(&lk_file, LK_RETRY);	for (fp = file; fp < fileNFILE; fp++) {		if (fp->f_count == 0)			continue;		if (fp->f_type != DTYPE_INODE)			continue;		if (fp->f_ops == &divorceops)			continue;		gp = (struct gnode *)fp->f_data;		if (gp == 0)			continue;		if ((gp->g_mode & GFMT) != mode)			continue;		if (gp->g_rdev != dev)			continue;		if (gp->g_flag & GINUSE) {			smp_unlock(&lk_file);			(*fp->f_ops->fo_ioctl)(fp, FIOCINUSE, value, 					       fp->f_cred);			wakeup((caddr_t)&gp->g_flag);			gfs_lock(gp);			gp->g_flag &= ~(GINUSE);			gfs_unlock(gp);			goto top;		}		fp->f_ops = &divorceops;		flag = fp->f_flag;	}	smp_unlock(&lk_file);	return(flag);}divorce_rw(fp, rw, uio)	register struct file *fp;	register enum uio_rw rw;	register struct uio *uio;{	return(EBADF);}divorce_ioctl(fp, com, data)	register struct file *fp;	register int com;	register caddr_t data;{	return(EBADF);}divorce_select(fp, which)	register struct file *fp;	register int which;{	return(EBADF);}divorce_close(fp)	register struct file *fp;{	register struct gnode *gp = (struct gnode *)fp->f_data;	/*	 * We don't have to hold the file table lock here,	 * because nobody cares about file table entries with	 * divorceops.	 */	gfs_lock(gp);	gput(gp);	return(0);}/* * Remove a gnode from the gnode cache (make the gnode active ) */voidgremque(gp)	register struct gnode *gp;{	register struct gnode *gq;	gq = gp->g_freef;	*(gp->g_freeb) = gq;	if (gq)		gq->g_freeb = gp->g_freeb;	else		gfreet = gp->g_freeb;	gp->g_freef = NULL;	gp->g_freeb = NULL;}/* * This routine is called for every file close (excluding kernel processes * that call closef() directly) in order to implement the * SVID 'feature' that the FIRST close of a descriptor that refers to * a locked object causes all the locks to be released for that object. * It is called, for example, by close(), exit(), exec(), & dup2(). * * NOTE: If the SVID ever changes to hold locks until the LAST close, *       then this routine might be moved to closef(). * */intgno_lockrelease(fp)	register struct file *fp;{	/*	 * Only do extra work if the process has done record-locking.	 */	if (u.u_procp->p_file & SLKDONE) {		register struct gnode *gp;		register struct file *ufp;		register int i;		register int locked;		struct flock ld;		locked = 0;			u.u_procp->p_file &= ~SLKDONE;	/* reset process flag */		gp = (struct gnode *)fp->f_data;		/*		 * Check all open files to see if there's a lock		 * possibly held for this gnode.		 */		for (i = u.u_omax; i-- > 0; ) {			if (((ufp = U_OFILE(i)) != NULL) &&			    (U_POFILE(i) & UF_FDLOCK)) {				/* the current file has an active lock */				if ((struct gnode *)ufp->f_data == gp) {					/* release this lock */					locked = 1;	/* (later) */					U_POFILE_SET(i, 						     U_POFILE(i) & ~UF_FDLOCK);				} else {					/* another file is locked */					u.u_procp->p_file |= SLKDONE;				}			}		}	/* for all files */		/*		 * If 'locked' is set, release any locks that this process		 * is holding on this file.  If record-locking on any other		 * files was detected, the process was marked (SLKDONE) to		 * run thru this loop again at the next file close.		 */		 if (locked) {			ld.l_type = F_UNLCK;	/* set to unlock entire file */			ld.l_whence = 0;	/* unlock from start of file */			ld.l_start = 0;			ld.l_len = 0;		/* do entire file */			return (GRLOCK(gp, &ld, F_SETLK, fp));		 }	}	return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -