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

📄 gfs_mount.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic	char	*sccsid = "@(#)gfs_mount.c	4.3	(ULTRIX)	2/28/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1986,87 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. *	Add dev argument to gfs_gupdat(). * * 09 Nov 89 -- jaw *	remove support for asymmetric system calls.  Had to add code to  *	mount to force control to boot_cpu.  This is unfinished work *	in SMP. * * 25 Jul 89 -- chet *	Changes for new bflush() interface and redo update() routine * * 14 Jun 89 -- condylis *	Modified getpdev() to return a dev number that does not *	currently exist in the mount table. * * 06 Feb 89 -- prs *	Changed return value from EPERM to EACCES if a user level *	mount is attempted on a device with no execute permission in *	getmdev(). * * 09 Jan 89 -- condylis *	Modified smount and umount to run on any processor.  Added *	mteinit() to initialize mount table entry SMP locks. * * 07 Dec 88 -- condylis *	Changed gfs_gupdat to insure it has a valid ref on a gnode *	before calling GUPDATE and to call grele to release the ref. * * 05 May 88 -- prs *	SMP - Added initialization of m_lk lock, that protects local *	file system data in super block. * * 12-11-87	Robin L. and Larry C. *	Added new kmalloc memory allocation to system. * * 29 Oct 87 -- chet *	add u.uerror value set in check_mountp() * * 12 May 87 -- prs *	Removed call to namei in smount. Created a new routine * 	check_mountp to perform namei and checking of the local *	mount point which is called from sfs mount routines * * 28 Apr 87 -- prs *	Turned on user level mount. Fixed smount to verify *	local mount point exists after call to sfs mount *	routine * * 10 Apr 87 -- logcher *	Added Charlie Brigg's fix to if statement in gfs_gupdat *	to update specfs * * 10 Mar 87 -- chet *	turn off user-level mounts unless GFSDEBUG is on * * 13 Feb 87 -- prs *	Changed call to bflush in update to only pass the mp parameter * * 15 Jan 87 -- prs *	Added nulling out the fs_data pointer in the mount structure if *	the sfs mount call fails * * 11 Sep 86 -- koehler *	changed name interface, allow the new options, fix umount  *	problems * * 16 Oct 86 -- koehler *	fixed a problem with mounting hp0a (major/minor 0/0) * ***********************************************************************/#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/buf.h"#include "../h/mount.h"#include "../h/file.h"#include "../h/kernel.h"#include "../h/conf.h"#include "../h/kmalloc.h"#include "../h/limits.h"#include "../h/cpudata.h"int turn_off_usrmnt = 0;int nmount = 0;extern struct lock_t lk_gnode;struct lock_t lk_mount_table;check_mountp(mp, pathname)struct mount *mp;char *pathname;{	register struct gnode	*gp;	register struct nameidata *ndp = &u.u_nd;	char *temp_pathname;	temp_pathname = pathname;	ndp->ni_nameiop = LOOKUP | FOLLOW | NOCACHE;	ndp->ni_dirp = pathname;	if ((gp = GNAMEI(ndp)) == NULL) {		if (!u.u_error)			u.u_error = EIO; /* just in case it wasn't set */		return(NULL);	}	if (gp->g_count != 1) {		/* someone has this inode open */		u.u_error = EBUSY;		nchinval(gp->g_dev);		gput(gp);		return(NULL);	}	if ((gp->g_mode & GFMT) != GFDIR) { /* this mount point is not a dir */		u.u_error = ENOTDIR;		nchinval(gp->g_dev);				gput(gp);		return(NULL);	}	if (u.u_uid) 		if (turn_off_usrmnt || (gp->g_uid != u.u_uid)) {			u.u_error = EPERM;			nchinval(gp->g_dev);					gput(gp);			return(NULL);		}	mp->m_gnodp = gp;	return(1);}smount(){	register struct a {		char	*fspecial;		char	*fpathname;		int	ronly;		int	fs_type;	/* new gfs entry */		char	*opts;		/* new gfs entry */	} *uap;	register struct mount	*mp;	register struct fs_data *fs_data;	int			num;	struct mount		*(*mountsfs)();	char *pathname;	char *devname;	int saveaffinity;	extern struct gnode *rootdir;		uap = (struct a *)u.u_ap;	KM_ALLOC(pathname, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (pathname == NULL)	{		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->fpathname, pathname, MAXPATHLEN,				  (u_int *) 0)) {		KM_FREE(pathname, KM_NAMEI);		return;	}	if (*pathname != '/') {		/* we must have absolute pathnames */		u.u_error = EINVAL;		KM_FREE(pathname, KM_NAMEI);		return;	}	KM_ALLOC(devname, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (devname == NULL) {		KM_FREE(pathname, KM_NAMEI);		u.u_error = EIO;		return;	}	if (u.u_error = copyinstr(uap->fspecial, devname, MAXPATHLEN,				  (u_int *) 0)) {		KM_FREE(devname, KM_NAMEI);		KM_FREE(pathname, KM_NAMEI);		return;	}	/* system call not smp safe */	saveaffinity = switch_affinity(boot_cpu_mask);		for (mp = mount; mp < &mount[NMOUNT]; mp++) {		if (mp->m_bufp == 0) {			smp_lock(&mp->m_lk, LK_RETRY);			if (mp->m_bufp == 0) {				/* for reservation */				mp->m_bufp = (struct buf *) NODEV;				mp->m_dev = NODEV;				smp_unlock(&mp->m_lk);				break;			}			smp_unlock(&mp->m_lk);       		}	}		if (mp == &mount[NMOUNT]) {		u.u_error = EMFILE;		KM_FREE(pathname, KM_NAMEI);		KM_FREE(devname, KM_NAMEI);		switch_affinity(saveaffinity);		return;	}		num = uap->fs_type;	if (num < 0 || num >= NUM_FS) {	/* fs_type not in range 0-0xff */		u.u_error = ENXIO;	/* this is a new error return */		mp->m_bufp = NULL;		KM_FREE(pathname, KM_NAMEI);		KM_FREE(devname, KM_NAMEI);		switch_affinity(saveaffinity);		return;	}	mountsfs = MOUNTFS(num);	if (!mountsfs) {			/* fs_type not configured */		u.u_error = EOPNOTSUPP;	/* this is another new error */		mp->m_bufp = NULL;		KM_FREE(pathname, KM_NAMEI);		KM_FREE(devname, KM_NAMEI);		switch_affinity(saveaffinity);		return;	}	KM_ALLOC(mp->m_fs_data, struct fs_data *, sizeof(struct fs_data), 		 KM_MOUNT, KM_CLEAR);	fs_data = mp->m_fs_data;	if (mp == &mount[nmount])		nmount++;	fs_data->fd_uid = u.u_uid;		/* who is mounting */	mp->m_gnodp = NULL;	if (mp != (*mountsfs)(devname, pathname, uap->ronly, mp, uap->opts)) {	        /*		 *  something went wrong in the sfs, it will return		 *  the error		 */		mp->m_dev = NODEV;		KM_FREE(mp->m_fs_data, KM_MOUNT);		mp->m_fs_data = NULL;		if (mp == &mount[nmount - 1])			nmount--;		if (mp->m_gnodp) {			nchinval(mp->m_gnodp->g_dev);			gput(mp->m_gnodp);			mp->m_gnodp = NULL;		}		mp->m_bufp = NULL;		KM_FREE(devname, KM_NAMEI);		KM_FREE(pathname, KM_NAMEI);		switch_affinity(saveaffinity);		return;	}	/* 	 * Because of relative links, 	 * we have to put what the user typed into the mount table 	 */ 	copyinstr(uap->fpathname, fs_data->fd_path, MAXPATHLEN, (u_int *) 0); 	bcopy(devname, fs_data->fd_devname, MAXPATHLEN);	KM_FREE(devname, KM_NAMEI);	KM_FREE(pathname, KM_NAMEI);	fs_data->fd_dev = mp->m_dev;		if (u.u_uid)		mp->m_flags |= M_USRMNT;	/* nosuid & nodev */	mp->m_gnodp->g_mpp = mp;	mp->m_fstype = num;	mp->m_gnodp->g_flag |= GMOUNT;	gfs_unlock(mp->m_gnodp);	mp->m_flgs |= MTE_DONE;	switch_affinity(saveaffinity);}umount(){	register struct a {		dev_t	fdev;	} *uap = (struct a *) u.u_ap;	dev_t	 		dev = uap->fdev;		register struct mount	*mp;	GETMP(mp, dev);	if ((mp == NULL) || (mp == (struct mount *) MSWAPX)) {		u.u_error = EINVAL;		return;	}	/* check perm and allow user level mount and umount */	if (u.u_uid) {		if (u.u_uid != mp->m_fs_data->fd_uid) {			u.u_error = EPERM;			return;		}	}	/*	 * Stop concurrent umounts on same mount table entry here.	 * If we still have the correct mount table entry and	 * this entry in mounted on and there isn't a umount	 * already in progress on this entry.	 */	smp_lock(&mp->m_lk, LK_RETRY);	if ((mp->m_dev == dev) && (mp->m_flgs & MTE_DONE) &&	    !(mp->m_flgs & MTE_UMOUNT)) {		mp->m_flgs |= MTE_UMOUNT;		smp_unlock(&mp->m_lk);	}	else {		smp_unlock(&mp->m_lk);		u.u_error = EBUSY;		return;	}	gfs_gupdat(mp->m_dev);	bflush(mp->m_dev, (struct gnode *) 0, 0);	if ((u.u_error = GUMOUNT(mp, 0)) == 0) {		if (mp->m_bufp != (struct buf *) (NODEV))			brelse(mp->m_bufp);		KM_FREE(mp->m_fs_data, KM_MOUNT);		mpurge(mp - &mount[0]);		mp->m_dev = NODEV;		mp->m_forw[0] = NULL;		mp->m_forw[1] = NULL;		mp->m_pad = 0;		mp->m_fs_data = NULL;		mp->m_gnodp = NULL;		mp->m_rootgp = NULL;		mp->m_qinod = NULL;		mp->m_ops = NULL;		mp->iostrat = NULL;		smp_lock(&mp->m_lk, LK_RETRY);		mp->m_flgs = 0;		mp->m_bufp = NULL;		smp_unlock(&mp->m_lk);		binval(dev, (struct gnode *) 0);		if ((mp - mount) == (nmount - 1))			nmount--;	} else {		/*		 * Allow umounts on this mount table entry again		 */		smp_lock(&mp->m_lk, LK_RETRY);		mp->m_flgs &= ~MTE_UMOUNT;		smp_unlock(&mp->m_lk);	}}update(){	register struct mount *mp;	register struct gnode *rgp;	register int ret;	extern	struct gnode *fref();		for (mp = mount; mp < &mount[nmount]; mp++) {		if (mp->m_dev == (dev_t) NODEV)			continue;		/*		 * mount table entry is active		 */		if ((rgp = fref(mp, (dev_t)0)) != NULL) {			if (mp->m_flags & M_MOD) {				if (ISREADONLY(mp)) {					printf("fs= %s\n",mp->m_path);					panic("update: Read only file system");				}				ret = GSBUPDATE(mp, 0);			} 			grele(rgp);		}	}	bflush(NODEV, (struct gnode *) 0, 0); /* flush 'em all */}/* * Note: this routine is called *ONLY* by sync() and umount() */gfs_gupdat(dev)	dev_t dev;{        register struct gnode *gp;	register int ret;		for (gp = gnode; gp < gnodeNGNODE; gp++) {		if (smp_lock(&gp->g_lk, 0) == LK_WON) {			if (gp->g_count == 0 ||			    !gisready(gp) ||			    ((gp->g_flag & (GMOD|GACC|GUPD|GCHG)) == 0))				goto skip;			if (dev != NODEV && gp->g_dev != dev)				goto skip;			if (!ISLOCAL(gp->g_mp) && 			    (((gp->g_mode & GFMT) == GFREG) || 			     ((gp->g_mode & GFMT) == GFDIR))) 				goto skip;					smp_lock(&lk_gnode, LK_RETRY);			if (gp->g_count && gisready(gp)) {				gp->g_count++;				smp_unlock(&lk_gnode);			}			else {				smp_unlock(&lk_gnode);				goto skip;			}			ret = GUPDATE(gp, &time, &time, 0, u.u_cred);			smp_unlock(&gp->g_lk);			grele(gp);			continue;			skip:	      		smp_unlock(&gp->g_lk);		}	}}int pdev_major = 0;int pdev_minor = 0;dev_tgetpdev(){	register int i = SHRT_MAX - (nblkdev+nchrdev+1);	register int tnmount = nmount;	register struct mount *tmp;	register dev_t tdev;	while  (i--) {		if (pdev_major == 0) pdev_major = (nblkdev+nchrdev+1);		/*		 * minor 0 - 255		 */		if (++pdev_minor > (1<<8)-1) {			/*			 * major 0 - 127 (dev_t is short)			 */			if (++pdev_major > (1<<7)-1)				pdev_major = (nblkdev+nchrdev+1);			pdev_minor=0;		}		tdev = makedev(pdev_major,pdev_minor);		/* Search mount table for entry using tdev */		for (tmp = mount; tmp < &mount[tnmount]; tmp++) {			if (tmp->m_dev == tdev)				break;		}		/* Found a dev number not in use */		if (tmp == &mount[tnmount])			return(tdev);	}	return((dev_t)0);}/* * Common code for ufs_mount, ufs_umount and setquota. * Check that the user's argument is a reasonable * thing on which to mount, and return the device number if so. */getmdev(pdev, fname, usr)	dev_t *pdev;	char *fname;	int usr;{	register dev_t dev;	register struct gnode *gp; 	register struct nameidata *ndp = &u.u_nd;	if (u.u_uid && !usr) {		u.u_error = EPERM;		return (EPERM);	} 	ndp->ni_nameiop = LOOKUP | FOLLOW; 	ndp->ni_dirp = fname; 	if ((gp = GNAMEI(ndp)) == NULL)		return (u.u_error);	/* user level mount -- user must have execute permission on dev */	if (usr)		if (access(gp, GEXEC)) {			gput(gp);			return(EACCES);		}	if ((gp->g_mode&GFMT) != GFBLK) {		gput(gp);		return (ENOTBLK);	}	dev = gp->g_rdev;	if (major(dev) >= nblkdev) {		gput(gp);		return (ENXIO);	}	gput(gp);	*pdev = dev;	return (0);}/* * Initializes per mount entry smp locks */mteinit(){	register struct mount *mp;	lockinit(&lk_mount_table, &lock_eachfs_d);	for (mp = mount; mp < &mount[NMOUNT]; mp++) {		lockinit(&mp->m_lk, &lock_eachfs_d);	}}

⌨️ 快捷键说明

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