📄 ufs_gnodeops.c
字号:
#ifndef lintstatic char *sccsid = "@(#)ufs_gnodeops.c 4.5 (ULTRIX) 2/28/91";#endif lint/************************************************************************ * * * Copyright (c) 1986, 1987 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 * * 27 Feb 91 -- chet * Fix filesystem timestamping. * * 22-Jan-91 - prs * Added fast symbolic link support. * * 27 Sep 90 -- prs * Protect ufs_rwgp() from a negative uio_offset * being passed to it. * * 7 Jul 90 -- chet * Make call to ufs_gupdat() in all cases in ufs_rwgp() instead * of only when updating meta-data. * * 7 Feb 89 -- prs * Returned number of bytes written from a call to ufs_rwgp() * if part of request is successful. * * 10 Dec 89 -- chet * Add age_wbuffers policy switch. * * 25 Jul 89 -- chet * Changes for new buffer cache organization and syncronous filesystems * * 25 Jul 88 -- jmartin * Lock mfind/munhash operation with lk_cmap. * * 4 Apr 88 -- Fred G. * Modify ufs_rlock () to declare kernel_locking as external. * * 2 Mar 88 -- chet * Added age_buffers and stickyhack switches in ufs_rwgp(). * * 26 Jan 88 -- chet * add access check in ufs_getdirent() * * 26 Jan 88 -- fglover * create ufs_rlock, which will support both kernal and daemon * based Sys-V region locking * * 14 Jan 88 -- chet * return gennum in stat structure from stat() and fstat() * * 14 Jul 87 -- cb * Added dev_t to mknod * * * 10 Jun 87 -- prs * Initialized structure member in ufs_open. * * 11 May 87 -- chet * Changed ufs_bmap() interface to get feedback about * on-disk structure changes. Avoid doing synchronous * disk inode updates unless this structure changes. * * 28 Apr 87 -- prs * Changed ufs_rwgp to use the ucred real uid instead of * the real uid in the user structure * * 29 Jan 87 -- chet * add new arg to bdwrite() calls. * * 15 Dec 86 -- depp * Returned to rdwri() the munhashing of text blocks on write. * This caused the "panic: chgd c_page". * * 04 Dec 86 -- prs * Fixed code in ufs_open. Code now closes the file is an * attempt was made to open with write mode a write locked * device. Also ufs_open will return after the open call to * the driver if the NDELAY flag is set. * * 23 Oct 86 -- chet * implemented IO_SYNC operation in ufs_rwgp(); made sure * that gnode was updated before return. * * 23 Oct 86 -- prs * Added code to return EROFS in ufs_open, if an attempt is being * made to open a write locked block or character special file for * writing. * * 11 Sep 86 -- koehler * introduced bmap function, made changes to fsdata so that it * returned the correct data * * 11 Mar 86 -- lp * Added n-buffered hooks to rwip & ioctl routines. * * 23 Dec 85 -- Shaughnessy * Added code to set/reset the syncronous write flag in * the inode. Also made sure inode was updated immediately after * syncronous write is performed. * * 11 Nov 85 -- depp * Removed all conditional compiles for System V IPC. * * 16 Apr 85 -- depp * Fixed routine "openi"; It didn't return error correctly when * routine "openp" was called * * * 15 Mar 85 -- funding * * Added named pipe support (re. System V named pipes) * * * * I added some fixes from berkeley to fix the inode reference * count from going negative. * Rich * * Modified 25-Oct-84 -- jrs * Add various bug fixes */#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/gnode_common.h" #include "../ufs/ufs_inode.h"#include "../h/gnode.h"#include "../h/proc.h"#include "../ufs/fs.h"#include "../h/conf.h"#include "../h/buf.h"#include "../h/mount.h"#include "../h/file.h"#include "../h/text.h"#include "../h/uio.h"#include "../h/ioctl.h"#include "../h/devio.h"#include "../h/tty.h"#include "../h/cmap.h"#include "../h/stat.h"#include "../h/kernel.h"#include "../h/exec.h"#define OSF_FASTLINK 0x0001/* * Don't cache blocks in non-executable files with the sticky bit * set. Used to keep swap files from cluttering up the data cache. */int stickyhack = 0; extern int kernel_locking; /* Sys-V locking: default is kernel */ /* kernel == 1; daemon == 0 */ufs_rwgp(gp, uio, rw, ioflag, cred) register struct gnode *gp; register struct uio *uio; enum uio_rw rw; int ioflag; struct ucred *cred;{ dev_t dev = (dev_t)gp->g_rdev; struct buf *bp; struct fs *fs; daddr_t lbn, bn; register int n, on, type; int size; long bsize; extern int mem_no; int error = 0; int transfer_count = uio->uio_resid; u_short execmask = (GEXEC | (GEXEC >> 3) | (GEXEC >> 6)); extern int delay_wbuffers; /* * update_flag is a strange beast. If called to do a * synchronous write (ioflag == IO_SYNC), then we must * flush the gnode to disk after doing the write * when any on-disk structures have changed. * For performance reasons, we want to * avoid this expensive operation if they haven't changed. * Since ufs_bmap() can change these structures, we must * be able to tell when it did. This is done by sending * ufs_bmap() the address of update_flag as the sync flag * when we are doing a synchronous write, and 0 otherwise. * ufs_bmap() will set update_flag to 1 when we must * flush the gnode, and will leave it unchanged otherwise * We set update_flag ourselves whenever the file is extended, * since the new size must be put out to disk. */ int update_flag = 0; type = gp->g_mode & GFMT; if (uio->uio_resid == 0) return (0); if (uio->uio_offset < 0) { u.u_error = EINVAL; return(EINVAL); } dev = gp->g_dev; fs = FS(gp); bsize = fs->fs_bsize; do { lbn = uio->uio_offset / bsize; on = uio->uio_offset % bsize; n = MIN((unsigned)(bsize - on), uio->uio_resid); if (rw == UIO_READ) { register int diff = gp->g_size - uio->uio_offset; if (diff <= 0) return (0); if (diff < n) n = diff; } bn = ufs_bmap(gp, (int)lbn, rw==UIO_WRITE ? B_WRITE : B_READ, (int)(on+n), (ioflag & IO_SYNC) ? &update_flag : 0); if (u.u_error || rw == UIO_WRITE && (long)bn<0) { /* * In POSIX mode, if part of this write request * was successful, return no error so the actual * number of bytes written can be calculated in * rwuio(). Setting u_error to zero here ensures * the number of bytes transfered will be returned * and syscall() won't overwrite with a -1; */ if ((u.u_procp->p_progenv == A_POSIX) && (rw == UIO_WRITE) && (transfer_count != uio->uio_resid)) u.u_error = 0; return (u.u_error); } if (rw == UIO_WRITE && uio->uio_offset + n > gp->g_size && (type == GFDIR || type == GFREG || type == GFLNK)) { gp->g_size = uio->uio_offset + n; if (ioflag & IO_SYNC) /* we must flush gnode before return */ update_flag = 1; } size = blksize(fs, gp, lbn); if (rw == UIO_READ) { if ((long)bn<0) { bp = geteblk(size); clrbuf(bp); } else if (gp->g_lastr + 1 == lbn) bp = breada(dev, bn, size, rablock, rasize, (struct gnode *) NULL); else bp = bread(dev, bn, size, (struct gnode *) NULL); gp->g_lastr = lbn; } else { int i, count; struct text *xp = gp->g_textp; extern struct cmap *mfind(); int s; count = howmany(size, DEV_BSIZE); /* * mfind/munhash can be a lengthy operation, so we * lock/unlock through each circuit of the loop. */ s = splimp(); for (i = 0; i < count; i += CLSIZE) { smp_lock(&lk_cmap, LK_RETRY); if (mfind(dev, bn + i, gp)) munhash(dev, bn + i, gp); smp_unlock(&lk_cmap); } (void)splx(s); if (xp) { /* sanity check the structs */ if (xp->x_gptr != gp) { printf("ufs_rwgp: messed up gp, xp"); printf("gp %X xp %X\n",gp,xp); panic("ufs_rwgp: messed up gp, xp"); } if (xp->x_count > 1 || (gp->g_flag & GSVTX)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -