📄 gfs_gnodeops.c
字号:
#ifndef lintstatic char *sccsid = "@(#)gfs_gnodeops.c 4.5 (ULTRIX) 2/28/91";#endif lint/************************************************************************ * * * Copyright (c) 1986,87,88,89 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//*********************************************************************** * * Modification History * * 28 Feb 91 -- prs * Added support for a configurable number of open * file descriptors. * * 27 Feb 91 -- chet * Fix filesystem timestamping * * 21 Jan 91 -- prs * Added routine divorce_dev() to disassociate gnode from file * table entry. The gnode pointer is no longer zeroed, it will * simply stay around until the file table entry goes away, but * any I/O requests with the file table entry will result in an * error return. Once divorce_dev runs, the physical device will * not be called with any open file descriptors. vhangup() and * gno_close() call divirce_dev(). * * 06 Mar 90 -- scott * allow negative uio_offset for AUD_NO * * 9 Feb 90 -- prs * Fixed a bug in gno_lock() where a branch to `again' didn't * unlock the gp. * * 12 Jan 90 -- prs * Changed gno_close() to not check pipes or fifos for file * table references before calling sfs close routine. * * 14 Nov 89 -- prs * Removed setting u_error to zero from gno_close(). * * 09 nov 89 -- fran * Add logic to forceclose to break connection to controlling * terminal. * * 25 Jul 89 -- chet * Use new bflush() interface in gno_close() * * 14 Jun 89 -- prs * Enhanced vhangup() logic to interoperate with closef(). * * 09 Feb 89 -- prs * Initialized the stack variable `type' in rwgp(). This fixes the * problem with the routine failing to check if a write would exceed * the current rlimit for the user. * * 04 Jan 89 -- prs * Removed the DTYPE_PORT check in gno_close(). Skipping named pipes * allows the code to only check special devices for multiple file * table references for the same device. This fixes a bug where the * fifo close routine would only be called on the last reference to * the fifo, instead of every call propagating to the sfs close. * * 28 Sep 88 -- chet * Add cacheinvalall in unlikely event that nextgnodeid wraps. * * 9 Sep 88 -- condylis * Added SMP changes to gno_lock and gno_unlock * * 19 Jul 88 -- prs * Cleared g_fifo field in getegnode() routine, to fix a problem * with fifo gnode reclaiming a non fifo gnode over nfs. * * 11 Jul 88 -- prs * Modified gno_ioctl to pass the flags filed of a file pointer * to the fifo ioctl routine. * * 8 Jul 88 -- condylis * All gnode types except regular file and directory will now call * rwgp from gno_rw without the gnode lock held. * Test added to end of rwgp to insure that gnode lock is held * while setting GACC bit in gnode flag. * * 19 May 88 -- cb * Changed GFS interface - SMP safe gnode manipulation. * * 15 Feb 88 -- Tim Burke * Added field to uio structure called uio_flag. This field will be used * pass the file descriptor modes down into the device driver on reads * and writes to distinguish POSIX nonblocking I/O/ * * 10 Feb 88 -- prs * Modified to handle the new fifo code. * * 10 Feb 88 -- map * Don't send SIGXFSZ if in System V mode. * * 08 Feb 88 -- prs * Changed getegnode to process g_dquot field in gnode. * Now, gnode returned has this field nulled out, as routine * name suggests. * * 12 Jan 88 -- Fred Glover * Add gno_lockrelease routine for Sys-V lock cleanup upon file * close or process termination * * 28 Dec 87 -- Tim Burke * Moved u.u_ttyp to u.u_procp->p_ttyp. * * 23 Mar 87 -- prs * Fixed gno_close to decrement reference count in gnode * before returning from special cases. * * 03 Mar 87 -- chase * refresh gnode attributes before an append mode write * * 03 Mar 87 -- prs * Changed gno_close to verify block device was not mounted before * flushing and invalidating all its buffers. * * 29 Jan 87 -- chet * moved gput() after GCLOSE in gno_close(). * * 19 Sep 86 -- lp * fixed bug in ioctl code when enabling n-buff. * 11 Sep 86 -- koehler * fixed close routine * ***********************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/gnode.h"#include "../h/proc.h"#include "../h/conf.h"#include "../h/buf.h"#include "../h/mount.h"#include "../h/file.h"#include "../h/uio.h"#include "../h/ioctl.h"#include "../h/tty.h"#include "../h/cmap.h"#include "../h/stat.h"#include "../h/kernel.h"#include "../h/exec.h"#include "../h/cpudata.h"#ifdef QUOTA#include "../h/quota.h"#endifint gno_rw(), gno_ioctl(), gno_select(), gno_close();struct fileops gnodeops = { gno_rw, gno_ioctl, gno_select, gno_close };int divorce_rw(), divorce_ioctl(), divorce_select(), divorce_close();struct fileops divorceops = { divorce_rw, divorce_ioctl, divorce_select, divorce_close };gno_rw(fp, rw, uio) register struct file *fp; register enum uio_rw rw; register struct uio *uio;{ register struct gnode *gp = (struct gnode *)fp->f_data; register int error; if ((gp->g_mode&GFMT) == GFREG) { gfs_lock(gp); if (fp->f_flag&FAPPEND && rw == UIO_WRITE) { (void)GGETVAL(gp); uio->uio_offset = fp->f_offset = gp->g_size; } /* * If synchronous write flag was passed in the file * pointer from the open or fcntl system calls, * then do a synchronous write. */ if (fp->f_flag & O_FSYNC) error = rwgp(gp, uio, rw, IO_SYNC, fp->f_cred); else error = rwgp(gp, uio, rw, IO_ASYNC, fp->f_cred); gfs_unlock(gp); } else { uio->uio_flag = fp->f_flag; if ((fp->f_flag & FNBLOCK) || (fp->f_flag & FNDELAY)) error = rwgp(gp, uio, rw, IO_ASYNC|FNDELAY, fp->f_cred); else error = rwgp(gp, uio, rw, IO_ASYNC, fp->f_cred); } return (error);}rdwri(rw, gp, base, len, offset, segflg, aresid) register struct gnode *gp; register caddr_t base; int len, offset, segflg; register int *aresid; enum uio_rw rw;{ struct uio _auio; register struct uio *auio = &_auio; struct iovec _aiov; register struct iovec *aiov = &_aiov; register int error; auio->uio_iov = aiov; auio->uio_iovcnt = 1; aiov->iov_base = base; aiov->iov_len = len; auio->uio_resid = len; auio->uio_offset = offset; auio->uio_segflg = segflg; error = rwgp(gp, auio, rw, IO_ASYNC, u.u_cred); if (aresid) *aresid = auio->uio_resid; else if (auio->uio_resid) error = EIO; return (error);}rwgp(gp, uio, rw, ioflag, cred) register struct gnode *gp; register struct uio *uio; register enum uio_rw rw; int ioflag; struct ucred *cred;{ dev_t dev = (dev_t)gp->g_rdev; register int type = (gp->g_mode & GFMT); extern int mem_no; register int ret; if (rw != UIO_READ && rw != UIO_WRITE) panic("rwgp"); if (rw == UIO_READ && uio->uio_resid == 0) return (0); if (uio->uio_offset < 0 && (type != GFCHR || (mem_no != major(dev) && major(dev) != AUD_NO))) return (EINVAL); if (rw == UIO_WRITE && type == GFREG && uio->uio_offset + uio->uio_resid > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { if (u.u_procp->p_progenv == A_BSD) /* BSD baggage */ psignal(u.u_procp, SIGXFSZ); return (EFBIG); } ret = GRWGP(gp, uio, rw, ioflag, cred); if (!ret && rw == UIO_READ) { if (ISLOCAL(gp->g_mp)) { if (smp_owner(&gp->g_lk)) gp->g_flag |= GACC; else { gfs_lock(gp); gp->g_flag |= GACC; gfs_unlock(gp); } } } return(ret);}gno_ioctl(fp, com, data, cred) register struct file *fp; register int com; register caddr_t data; struct ucred *cred;{ register struct gnode *gp = ((struct gnode *)fp->f_data); register int fmt = gp->g_mode & GFMT; dev_t dev; register int flag; switch (fmt) { case GFREG: case GFDIR: if (com == FIONREAD) flag = fp->f_offset; break; case GFPIPE: case GFPORT: flag = fp->f_flag; break; case GFCHR: flag = fp->f_flag; dev = gp->g_rdev; /* * cdevsw[].d_strat implies this device can * do multi-buffered operations. Otherwise * just fall into device ioctl. */ if (cdevsw[major(dev)].d_strat) { if (com == FIONBUF) { int *acount = (int *)data; if (*acount < 0) return(ENXIO); if (*acount > 0) { fp->f_flag |= FNBUF; gp->g_flag |= ASYNC; startasync(dev, acount, fp->f_flag); } else if (fp->f_flag&FNBUF) { if (!asyncclose(dev, fp->f_flag)) gp->g_flag &= ~ASYNC; fp->f_flag &= ~FNBUF; } return(0); } if (com == FIONBDONE) return(aiodone(dev, *(int *)data, fp->f_flag)); if (com == FIONBIO || com == FIOASYNC) return(0); } else if (com == FIONBUF) return(ENXIO); } if ((flag = GFNCTL(gp, com, data, flag, fp->f_cred)) == GNOFUNC) flag = EOPNOTSUPP; return(flag);}gno_select(fp, which) register struct file *fp; register int which;{ register struct gnode *gp = (struct gnode *)fp->f_data; return (GSELECT(gp, which, fp->f_cred));}#ifdef notdefgno_clone(){ return (EOPNOTSUPP);}#endifgno_stat(gp, sb) register struct gnode *gp; register struct stat *sb;{ return (GSTAT(gp, sb));}gno_close(fp) register struct file *fp;{ register struct file *ffp; register struct gnode *gp = (struct gnode *)fp->f_data; register int flag; dev_t dev; register int mode; register struct gnode *tgp; register struct mount *mp; flag = fp->f_flag; if (flag & (FSHLOCK|FEXLOCK)) gno_unlock(fp, FSHLOCK|FEXLOCK); fp->f_ops = &divorceops; /* So we wont be looked at ! */ dev = (dev_t)gp->g_rdev; mode = gp->g_mode & GFMT; if (mode == GFCHR || mode == GFBLK) { /* * Check for references to the device. If the device is * referenced by another process, simply remove our * reference to the gnode. However, if we are the last * reference to the device, call spec_close() which will * call the drivers close routine, shutting down the device. */ for (ffp = file; ffp < fileNFILE; ffp++) { if (ffp->f_count == 0) continue; if (ffp->f_type != DTYPE_INODE) /* XXX */ continue; if (ffp->f_ops == &divorceops) continue; if ((tgp = (struct gnode *)ffp->f_data) && tgp->g_rdev == dev && (tgp->g_mode&GFMT) == mode) { /* * Decrement ref count in gnode */ grele(gp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -