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

📄 ufs_xxx.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic char *sccsid = "@(#)ufs_xxx.c	4.2	ULTRIX	11/9/90";#endif/************************************************************************ *									* *			Copyright (c) 1986, 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 * * 24 Aug 89 -- Tim Burke *	In the ptcmp, ssblk routines when looking for a match of the disk  *	driver ioctl routine between the bdev and cdev switch table entries  *	take into account that an offset may be required for MSCP disks because *	they occupy a range of major numbers. * * 28 Mar 89 -- Tim Burke *	Modified disk unit number calculations to handle the case of MSCP *	devices which use more than one major number. * * 28 Jul 88 -- prs *	Added a check for a read-only mount table entry in ssblk(). *  * 25 Aug 87 -- prs *	Fixed a bug in ssblk that would update the wrong super block *	if it was mounted. * * 14 Jul 87 -- prs *	Fixed ssblk routine to update super blocks of all partitions for *	a device that start at block offset zero. Previously routine *	would only update the incore super block of an "a" partition. * * 11 Sep 86 -- koehler *	registerized a few things * ***********************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/gnode.h"#include "../ufs/fs.h"#include "../h/mount.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/conf.h"#include "../h/file.h"#include "../h/errno.h"#include "../h/ustat.h"/* *	This routine is called by any of the driver routines that need *	to handle the partition table. */ rsblk(strategy, dev, pt )	register int (*strategy)();	dev_t dev;	register struct pt *pt;{	register union sblock {		struct fs fs;		char pad[MAXBSIZE];	} *sblk_addr;				/* ptr to the superblock */	register int unit = minor(dev) >> 3;		/* device unit */	register struct buf *bp;		/* buffer ptr for the I/O */	/*	 *	Get a buffer that will hold a supberblock	 */	bp = geteblk( SBSIZE );	/*	 *	Set up the buf struct to read the superblock from	 *	the "a" partition which is located at SBLOCK	 */	bp->b_flags |= B_READ;	bp->b_bcount = SBSIZE;	bp->b_dev = makedev( major(dev), unit << 3 );	bp->b_blkno = SBLOCK;	/*	 *	Call the driver's strategy routine to read	 *	in the superblock, if one exists	 */	(*strategy)(bp);			/*	 *	Wait for the I/O to complete	 */	biowait(bp);	/*	 *	If we have an error just return	 */	if ( bp->b_flags & B_ERROR ) {		brelse(bp);	 	return (-1);	}	/*	 *	If we have a  valid superblock and a valid partition	 *	table return success	 */	sblk_addr = (union sblock *)bp->b_un.b_fs;	if ( sblk_addr->fs.fs_magic == FS_MAGIC ) {		struct pt *scr_pt;		/*		 *	Get the pointer to the partition table		 */	    	scr_pt = (struct pt*)&sblk_addr->pad[ SBSIZE - sizeof(struct pt ) ];	    	if ( scr_pt->pt_magic == PT_MAGIC ) {			*pt = *scr_pt;			/*			 *	Indicate that we have a valid partition table			 */			pt->pt_valid = PT_VALID;			brelse( bp );		/* 001 release buffer */			return(0);	    	}	 	else {			brelse( bp );		/* 001 release buffer */			return(-1);		}	}	else {		brelse( bp );		/* 001 release buffer */		return(-1);	}}/* *	The purpose of the routine is to make sure that any  partition *	changes will not corrupt the system. * *	There are cases in which a new partition table could corrupt *	the system.  The following are those cases * *	1. If a partition's starting location in the current partition table *	   differ from that of the new partition and there *	   is an open file descr. on the current partition an error *	   is returned. * *	2. If a new partition size decreases from that of the current *	   partition and there is an open file descr. on the current *	   partition an error is returned. * * NOTE: *	This routine should only be called if the device in questioned is *	a partitionable device (disk). The reason is that there are  *	assumptions about the ioctl address being the same for a partitionable *	device be it a raw or block access of the same device. * */ptcmp ( dev, cptbl, nptbl )	dev_t dev;			/* major and minor number */	register struct pt *cptbl, *nptbl;/* ptr to the current and new					 * partition tables 					 */{	register int majno = major(dev);	/* major number */	dev_t bdev, cdev;		/* char and block devices */	int posserr[8];			/* possible error */	register int part;		/* which partition */	int bmajno, bunitno;		/* block's major and minor number */	int cmajno, cunitno;		/* char's major and minor number */	register struct file *fp;	/* pointer to incore file descp*/	register struct mount *mp;	/* ptr to mounted filesystem */	int i;				/* temp variable */	int anyerrors = 0;		/* if set then an error case was found */	register int unit_no;	/*	 *	Before we go through the incore file desc. we must	 *      check to determine if any possible errors exists.	 */	for ( part = 0; part <= 'h' - 'a'; part++) {		/*		 *	If starting locations are different then		 *	a possible error condition exist. 		 */		if ( cptbl->pt_part[part].pi_blkoff !=			 nptbl->pt_part[part].pi_blkoff ) {			posserr[part] = -1;			anyerrors = -1;			continue;		}		/*		 *	If current partition size is going to decrease		 *	a possible error case exists		 */				if ( cptbl->pt_part[part].pi_nblocks >			 nptbl->pt_part[part].pi_nblocks ) {			posserr[part] = -1;			anyerrors = -1;			continue;		}				/*		 *	Since we can not initialize local aggragates we		 *	initialize it here.		 */		 posserr[part] = 0;	}	/*	 *	If no error cases are found then no additional checking is	 *	needed.	 */	if ( !anyerrors )		return(0);	/*	 *	The major and minor number are not unique because the	 *	raw and block device number are not the same for the same	 *	device. We find the the equivalent block number for	 *	the same device.	 */	cdev = dev;	/* 	 *	We know that the ioctl address will be the  	 *	the same for the raw and block device.	 *	For MSCP disks adjust the major number to correspond	 *	to the appropriate unit number. 	 */	for ( i = 0; i < nblkdev ; i++ ) {            	if ( bdevsw[i].d_ioctl == cdevsw[majno].d_ioctl) {			if (MSCP_C_DEV(cdev)) {				i += (majno - MSCP_C_MIN);			}		 	bdev = makedev( i, minor(dev) );			break;		}	}	/*	 *	Do a sanity check to make sure that we did not go over	 *	then end of the block device table	 */	if ( i >= nblkdev )		panic("ptcmp: No matching ioctl address in block device table");	/*	 *	Use local variables for optimization later	 */	cmajno = major(cdev);	cunitno = minor(cdev) >> 3;	bmajno = major(bdev);	bunitno = minor(bdev) >> 3;	 	/*	 * Determine unit number.  MSCP type disks can occupy more than one	 * major number.	 */	if (MSCP_C_DEV(cdev)) {		cunitno += MSCP_C_UNIT_OFFSET(cdev);	}	if (MSCP_B_DEV(bdev)) {		bunitno += MSCP_B_UNIT_OFFSET(bdev);	}	/*	 *	Go through the mounted table to see if we have	 *	and error	 */	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {			/*		 *	Use the major and unit number to determine		 *	if we are looking at the right device		 */		if ( major(mp->m_dev) == bmajno ) {			unit_no = (minor(mp->m_dev) >> 3);			if (MSCP_B_DEV(mp->m_dev))				unit_no += MSCP_B_UNIT_OFFSET(mp->m_dev);			if (unit_no == bunitno ) {				if ( posserr[ minor( mp->m_dev ) & 0x07] ) 					return(EBUSY);			}		}	}	/*	 *	Now go through the kernel open file descriptor table	 *	looking to see if any of the descriptors are open on	 *	the device in question.	 */	for ( fp = file; fp < fileNFILE; fp++) {		struct gnode *gp;		int majorno, unitno;		/*		 *	Make sure that we have an active gnode		 */		if ( fp->f_type == DTYPE_INODE && fp->f_count && 		     (gp = (struct gnode *)fp->f_data ) ) {					/*		 	 *	We only need to check block or char file types		 	 */			if ( ( gp->g_mode & GFMT ) == GFCHR ||				( gp->g_mode & GFMT ) == GFBLK ) {				/*			 	 *	Check to see if the file descriptor			 	 *	in question is the right device by			 	 *	checking the major and unit			 	 *	number.			 	 */				if ( gp->g_mode & GFMT == GFBLK ) {					majorno = bmajno;					unitno = bunitno;				}				else {					majorno = cmajno;					unitno = cunitno;				}				/*				 *	Everything is now ready to check to				 *	see if we have an error				 */				if ( major(gp->g_rdev) == majorno ) {					unit_no = (minor(gp->g_rdev) >> 3);					if (majorno == bmajno) { /* Block */					    if (MSCP_B_DEV(gp->g_rdev))						unit_no += MSCP_B_UNIT_OFFSET(gp->g_rdev);					}					else {			 /* Character */					    if (MSCP_C_DEV(gp->g_rdev))						unit_no += MSCP_C_UNIT_OFFSET(gp->g_rdev);					}					if (unit_no == unitno ) {						if ( posserr[ minor( gp->g_rdev ) & 0x07] ) 							return(EBUSY);					}				}			}		}	}	return(0);}/* *	This routine is used to write out the partition table if the "a" *	paritition of the device is mounted.  The reason for this if *	the partition tables are changes via the "chpt" on the mounted *	"a" paritition the command has no way of changing the incore  *	superblock of the "a" paritition.  This routine enables us to *	modified the superblock. */ssblk ( dev, nptbl )	dev_t dev;	struct pt *nptbl;			/* New partition table */{	register int i;	register int majno = major(dev);	/* Major cdevsw number */	register struct pt *pt;			/* ptr to the part tbl */	int bdev;			/* block device number */	register struct mount *mp;		/* ptr to the mount tbl */	register union sblock {		struct fs fs;		char pad[MAXBSIZE];	} *sblk_addr;	register struct buf *bp;			/* buf ptr */	int blk;	/*	 *	We assume that the dev is of a character device.  We also	 *	assume that the ioctl for both the raw and block device 	 *	are the same.	 */	for ( i = 0; i < nblkdev ; i++ ) {            	if ( bdevsw[i].d_ioctl == cdevsw[majno].d_ioctl) {			/*			 *	Make a bdev with just a unit number			 */			if (MSCP_C_DEV(dev)) {				i += (majno - MSCP_C_MIN);			}		 	bdev = makedev( i, minor(dev) & ~0x07 );			break;		}	}	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {			/*		 *	See if any partition of the disk is mounted		 */		if ( (mp->m_dev & ~0x07) == bdev && mp->m_bufp != NULL ) {			/*			 * 	If the mounted partition does not start 			 *	at sector zero then continue.			 */			if (nptbl->pt_part[minor(mp->m_dev)&0x7].pi_blkoff != 0)				continue;			/*			 * Don't even attempt read-only mounted file systems,			 * because they are not synced out.			 */			if (ISREADONLY(mp))				continue;			/*			 *	We now know that we have a superblock			 *	that must possible need updating. If			 *	updating is required then get the superblock			 *	and copy the user specified data			 */			bp = mp->m_bufp;			sblk_addr = (union sblock *)bp->b_un.b_fs;			pt = ( struct pt *)&sblk_addr->pad[ SBSIZE - sizeof(struct pt ) ];			/*			 *	If the new partition table will overwrite			 *	the rotational table then remove it			 *		Note			 *	I assume that the user will be warned			 *	of this case by a user level command.			 */			blk = sblk_addr->fs.fs_spc * sblk_addr->fs.fs_cpc /				 NSPF(bp->b_un.b_fs);			for (i = 0; i < blk; i += sblk_addr->fs.fs_frag)				/* void */;			if ((struct pt *)(&sblk_addr->fs.fs_rotbl[			(i - sblk_addr->fs.fs_frag) /sblk_addr->fs.fs_frag])				 >= pt) {				sblk_addr->fs.fs_cpc = 0;				mp->m_flags |= M_MOD;			}			/*			 *	If the superblock size is less than the			 *	max. superblock size we will not overwrite			 *	what was put there, so just break out			 */			if( sblk_addr->fs.fs_sbsize < SBSIZE )				break;			/*			 *	Copy the user specified table into the			 *	superblock and indicate that we have			 *	updated the superblock			 */			*pt = *nptbl;			mp->m_flags |= M_MOD;		}	}}

⌨️ 快捷键说明

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