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

📄 mount.c

📁 lustre 1.6.5 source code
💻 C
字号:
/* *    This Cplant(TM) source code is the property of Sandia National *    Laboratories. * *    This Cplant(TM) source code is copyrighted by Sandia National *    Laboratories. * *    The redistribution of this Cplant(TM) source code is subject to the *    terms of the GNU Lesser General Public License *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * *    Cplant(TM) Copyright 1998-2004 Sandia Corporation.  *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive *    license for use of this work by or on behalf of the US Government. *    Export of this program may require a license from the United States *    Government. *//* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Questions or comments about this library should be sent to: * * Lee Ward * Sandia National Laboratories, New Mexico * P.O. Box 5800 * Albuquerque, NM 87185-1110 * * lee@sandia.gov */#include <stdlib.h>#include <string.h>#include <errno.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#ifdef AUTOMOUNT_FILE_NAME#include <fcntl.h>#include <sys/uio.h>#endif#include <sys/queue.h>#include "sysio.h"#include "xtio.h"#include "fs.h"#include "mount.h"#include "inode.h"/* * File system and volume mount support. */#ifdef AUTOMOUNT_FILE_NAME/* * Name of autmount specification file in a directory with * the sticky-bit set. */struct qstr _sysio_mount_file_name = { "", 0, 0 };#endif/* * Active mounts. */static LIST_HEAD(, mount) mounts;static int _sysio_sub_fsswop_mount(const char *source,				   unsigned flags,				   const void *data,				   struct pnode *tocover,				   struct mount **mntp);static struct fssw_ops _sysio_sub_fssw_ops = {	_sysio_sub_fsswop_mount};/* * Initialization. Must be called before any other routine in this module. */int_sysio_mount_init(){	int	err;	LIST_INIT(&mounts);#ifdef AUTOMOUNT_FILE_NAME	_sysio_next_component(AUTOMOUNT_FILE_NAME, &_sysio_mount_file_name);#endif	/*	 * Register the sub-trees "file system" driver.	 */	err = _sysio_fssw_register("sub", &_sysio_sub_fssw_ops);	if (err)		return err;	return 0;}/* * Mount rooted sub-tree somewhere in the existing name space. */int_sysio_do_mount(struct filesys *fs,		struct pnode_base *rootpb,		unsigned flags,		struct pnode *tocover,		struct mount **mntp){	struct mount *mnt;	int	err;	/*	 * It's really poor form to allow the new root to be a	 * descendant of the pnode being covered.	 */	if (tocover) {		struct pnode_base *pb;		for (pb = rootpb;		     pb && pb != tocover->p_base;		     pb = pb->pb_parent)			;		if (pb == tocover->p_base)			return -EBUSY;	}	/*	 * Alloc	 */	mnt = malloc(sizeof(struct mount));	if (!mnt)		return -ENOMEM;	err = 0;	/*	 * Init enough to make the mount record usable to the path node	 * generation routines.	 */	mnt->mnt_fs = fs;	if (fs->fs_flags & FS_F_RO) {		/*		 * Propagate the read-only flag -- Whether they set it or not.		 */		flags |= MOUNT_F_RO;	}	mnt->mnt_flags = flags;	/*	 * Get alias for the new root.	 */	mnt->mnt_root =	    _sysio_p_new_alias(tocover ? tocover->p_parent : NULL, rootpb, mnt);	if (!mnt->mnt_root) {		err = -ENOMEM;		goto error;	}	/*	 * It may have been a while since the root inode was validated;	 * better validate again.  And it better be a directory!	 */	err = _sysio_p_validate(mnt->mnt_root, NULL, NULL);	if (err)		goto error;	if (!S_ISDIR(mnt->mnt_root->p_base->pb_ino->i_stbuf.st_mode)) {		err = -ENOTDIR;		goto error;	}	/*	 * Cover up the mount point.	 */	mnt->mnt_covers = tocover;	if (!mnt->mnt_covers) {		/*		 * New graph; It covers itself.		 */		mnt->mnt_covers = tocover = mnt->mnt_root;	}	assert(!tocover->p_cover);	tocover->p_cover = mnt->mnt_root;	LIST_INSERT_HEAD(&mounts, mnt, mnt_link);	*mntp = mnt;	return 0;error:	if (mnt->mnt_root) {		P_RELE(mnt->mnt_root);		_sysio_p_prune(mnt->mnt_root);	}	free(mnt);	return err;}/* * Remove mounted sub-tree from the system. */int_sysio_do_unmount(struct mount *mnt){	struct pnode *root;	struct filesys *fs;	root = mnt->mnt_root;	if (root->p_cover && root->p_cover != root) {		/*		 * Active mount.		 */		return -EBUSY;	}	assert(mnt->mnt_covers->p_cover == root);	if (_sysio_p_prune(root) != 1) {		/*		 * Active aliases.		 */		return -EBUSY;	}	/*	 * We're committed.	 *	 * Drop ref of covered pnode and break linkage in name space.	 */	if (root->p_cover != root)		P_RELE(mnt->mnt_covers);	mnt->mnt_covers->p_cover = NULL;	LIST_REMOVE(mnt, mnt_link);	/*	 * Kill the root.	 */	P_RELE(root);	root->p_cover = NULL;	_sysio_p_gone(root);	/*	 * Release mount record resource.	 */	fs = mnt->mnt_fs;	free(mnt);	FS_RELE(fs);	return 0;}/* * Establish the system name space. */int_sysio_mount_root(const char *source,		  const char *fstype,		  unsigned flags,		  const void *data){	struct fsswent *fssw;	int	err;	struct mount *mnt;	if (_sysio_root)		return -EBUSY;	fssw = _sysio_fssw_lookup(fstype);	if (!fssw)		return -ENODEV;	err = (*fssw->fssw_ops.fsswop_mount)(source, flags, data, NULL, &mnt);	if (err)		return err;	_sysio_root = mnt->mnt_root;#ifndef DEFER_INIT_CWD	/*	 * It is very annoying to have to set the current working directory.	 * So... If it isn't set, make it the root now.	 */	if (!_sysio_cwd) {		_sysio_cwd = _sysio_root;		P_REF(_sysio_cwd);	}#endif	return 0;}int_sysio_mount(struct pnode *cwd,	     const char *source,	     const char *target,	     const char *filesystemtype,	     unsigned long mountflags,	     const void *data){	int	err;	struct fsswent *fssw;	struct intent intent;	struct pnode *tgt;	struct mount *mnt;	/*	 * Find the file system switch entry specified.	 */	fssw = _sysio_fssw_lookup(filesystemtype);	if (!fssw)		return -ENODEV;	/*	 * Look up the target path node.	 */        INTENT_INIT(&intent, INT_GETATTR, NULL, NULL);	err = _sysio_namei(cwd, target, 0, &intent, &tgt);	if (err)		return err;	if (tgt == _sysio_root) {		/*		 * Attempting to mount over root.		 */		err = -EBUSY;	} else {		/*		 * Do the deed.		 */		err =		    (*fssw->fssw_ops.fsswop_mount)(source,						   mountflags,						   data,						   tgt,						   &mnt);	}	if (err)		P_RELE(tgt);	return err;}intSYSIO_INTERFACE_NAME(mount)(const char *source,      const char *target,      const char *filesystemtype,      unsigned long mountflags,      const void *data){	int	err;	SYSIO_INTERFACE_DISPLAY_BLOCK;	SYSIO_INTERFACE_ENTER;	err =	    _sysio_mount(_sysio_cwd,			 source,			 target,			 filesystemtype,			 mountflags,			 data);	SYSIO_INTERFACE_RETURN(err ? -1 : 0, err);}intSYSIO_INTERFACE_NAME(umount)(const char *target){	int	err;	struct pnode *pno;	SYSIO_INTERFACE_DISPLAY_BLOCK;	SYSIO_INTERFACE_ENTER;	/*	 * Look up the target path node.	 */	err = _sysio_namei(_sysio_cwd, target, 0, NULL, &pno);	if (err)		goto out;	P_RELE(pno);				/* was ref'd */	/*	 * Do the deed.	 */#if 0		if (!pno->p_cover) {		err = -EINVAL;		goto error;	}#endif	assert(pno->p_mount);	err = _sysio_do_unmount(pno->p_mount);out:	SYSIO_INTERFACE_RETURN(err ? -1 : 0, err);}/* * Unmount all file systems -- Usually as part of shutting everything down. */int_sysio_unmount_all(){	int	err;	struct mount *mnt, *nxt;	struct pnode *pno;	err = 0;	nxt = mounts.lh_first;	while ((mnt = nxt)) {		nxt = mnt->mnt_link.le_next;		pno = mnt->mnt_root;		/*		 * If this is an automount generated mount, the root		 * has no reference. We can cause the dismount with a		 * simple prune.		 */		if (!_sysio_p_prune(pno))			continue;#ifdef notdef		/*		 * Need a ref but only if this is not the root of a		 * disconnected graph. If it is, then it is covered by itself		 * and, so, already referenced.		 */		if (pno->p_cover != pno)			P_REF(pno);#endif		err = _sysio_do_unmount(mnt);		if (err) {#ifdef notdef			if (pno->p_cover != pno)				P_RELE(pno);#endif			break;		}		if (pno == _sysio_root)			_sysio_root = NULL;	}	return err;}static int_sysio_sub_fsswop_mount(const char *source,			unsigned flags,			const void *data __IS_UNUSED,			struct pnode *tocover,			struct mount **mntp){	int	err;	struct nameidata nameidata;	struct mount *mnt;	/*	 * How can we make a sub-mount from nothing?	 */	if (!_sysio_root)		return -EBUSY;	/*	 * Lookup the source.	 */	ND_INIT(&nameidata, 0, source, _sysio_root, NULL);	err = _sysio_path_walk(_sysio_root, &nameidata);	if (err)		return err;	/*	 * Mount the rooted sub-tree at the given position.	 */	err =	    _sysio_do_mount(nameidata.nd_pno->p_mount->mnt_fs,			    nameidata.nd_pno->p_base,			    nameidata.nd_pno->p_mount->mnt_flags & flags,			    tocover,			    &mnt);	/*	 * Clean up and return.	 */	if (!err) {		FS_REF(nameidata.nd_pno->p_mount->mnt_fs);		*mntp = mnt;	}	P_RELE(nameidata.nd_pno);	return err;}#ifdef AUTOMOUNT_FILE_NAME/* * Parse automount specification formatted as: * * <fstype>:<source>[[ \t]+<comma-separated-mount-options>] * * NB: * The buffer sent is (almost) always modified. */static intparse_automount_spec(char *s, char **fstyp, char **srcp, char **optsp){	int	err;	char	*cp;	char	*fsty, *src, *opts;	err = 0;	/*	 * Eat leading white.	 */	while (*s && *s == ' ' && *s == '\t')		s++;	/*	 * Get fstype.	 */	fsty = cp = s;	while (*cp &&	       *cp != ':' &&	       *cp != ' ' &&	       *cp != '\t' &&	       *cp != '\r' &&	       *cp != '\n')		cp++;	if (fsty == cp || *cp != ':')		goto error;	*cp++ = '\0';	s = cp;	/*	 * Eat leading white.	 */	while (*s && *s == ' ' && *s == '\t')		s++;	/*	 * Get source.	 */	src = cp = s;	while (*cp &&	       *cp != ' ' &&	       *cp != '\t' &&	       *cp != '\r' &&	       *cp != '\n')		cp++;	if (src == cp)		goto error;	if (*cp)		*cp++ = '\0';	s = cp;	/*	 * Eat leading white.	 */	while (*s && *s == ' ' && *s == '\t')		s++;	/*	 * Get opts.	 */	opts = cp = s;	while (*cp &&	       *cp != ' ' &&	       *cp != '\t' &&	       *cp != '\r' &&	       *cp != '\n')		cp++;	if (opts == cp)		opts = NULL;	if (*cp)		*cp++ = '\0';	if (*cp)		goto error;	*fstyp = fsty;	*srcp = src;	*optsp = opts;	return 0;error:	return -EINVAL;}/* * Parse (and strip) system mount options. */static char *parse_opts(char *opts, unsigned *flagsp){	unsigned flags;	char	*src, *dst;	char	*cp;	flags = 0;	src = dst = opts;	for (;;) {		cp = src;		while (*cp && *cp != ',')			cp++;		if (src + 2 == cp && strncmp(src, "rw", 2) == 0) {			/*			 * Do nothing. This is the default.			 */			src += 2;		} else if (src + 2 == cp && strncmp(src, "ro", 2) == 0) {			/*			 * Read-only.			 */			flags |= MOUNT_F_RO;			src += 2;		}		else if (src + 4 == cp && strncmp(src, "auto", 4) == 0) {			/*			 * Enable automounts.			 */			flags |= MOUNT_F_AUTO;			src += 4;		}		if (src < cp) {			/*			 * Copy what we didn't consume.			 */			if (dst != opts)				*dst++ = ',';			do				*dst++ = *src++;			while (src != cp);		}		if (!*src)			break;		*dst = '\0';		src++;					/* skip comma */	}	*dst = '\0';	*flagsp = flags;	return opts;}/* * Attempt automount over the given directory. */int_sysio_automount(struct pnode *mntpno){	int	err;	struct inode *ino;	struct iovec iovec;	struct ioctx iocontext;	struct intnl_xtvec xtvec;	ssize_t	cc;	char	*fstype, *source, *opts;	unsigned flags;	struct fsswent *fssw;	struct mount *mnt;	/*	 * Revalidate -- Paranoia.	 */	err = _sysio_p_validate(mntpno, NULL, NULL);	if (err)		return err;	/*	 * Read file content.	 */	ino = mntpno->p_base->pb_ino;	if (ino->i_stbuf.st_size > 64 * 1024) {		/*		 * Let's be reasonable.		 */		return -EINVAL;	}	iovec.iov_base = malloc(ino->i_stbuf.st_size + 1);	if (!iovec.iov_base)		return -ENOMEM;	iovec.iov_len = ino->i_stbuf.st_size;	err = _sysio_open(mntpno, O_RDONLY, 0);	if (err)		goto out;	xtvec.xtv_off = 0;	xtvec.xtv_len = ino->i_stbuf.st_size;	IOCTX_INIT(&iocontext,		   1,		   0,		   ino,		   &iovec, 1,		   &xtvec, 1);	_sysio_ioctx_enter(&iocontext);	err = (*ino->i_ops.inop_read)(ino, &iocontext);	if (err) {		_sysio_ioctx_complete(&iocontext);		(void )(*ino->i_ops.inop_close)(ino);		goto out;	}	cc = _sysio_ioctx_wait(&iocontext);	err = (*ino->i_ops.inop_close)(ino);	if (err)		goto out;	if (cc < 0) {		err = (int )cc;		goto out;	}	((char *)iovec.iov_base)[cc] = '\0';	/*	 * Parse.	 */	err = parse_automount_spec(iovec.iov_base, &fstype, &source, &opts);	if (err)		goto out;	flags = 0;	if (opts)		opts = parse_opts(opts, &flags);	/*	 * Find the file system switch entry specified.	 */	fssw = _sysio_fssw_lookup(fstype);	if (!fssw) {		err = -ENODEV;		goto out;	}	/*	 * Do the deed.	 */	P_REF(mntpno->p_parent);	err =	    (*fssw->fssw_ops.fsswop_mount)(source,					   flags,					   opts,					   mntpno->p_parent,					   &mnt);	if (err)		P_RELE(mntpno->p_parent);out:	if (iovec.iov_base)		free(iovec.iov_base);	return err;}#endif

⌨️ 快捷键说明

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