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

📄 fs_native.c

📁 非常经典的一个分布式系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *    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 */#ifdef __linux__#define _BSD_SOURCE#endif#include <stdio.h>					/* for NULL */#include <stdlib.h>#ifdef __linux__#include <string.h>#endif#include <unistd.h>#if !(defined(REDSTORM) || defined(MAX_IOVEC))#include <limits.h>#endif#include <errno.h>#include <assert.h>#include <syscall.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/fcntl.h>#if 0#include <sys/vfs.h>#endif#ifdef _HAVE_STATVFS#include <sys/statvfs.h>#include <sys/statfs.h>#endif#include <utime.h>#include <sys/uio.h>#include <sys/queue.h>#include "sysio.h"#include "xtio.h"#include "native.h"#include "fs.h"#include "mount.h"#include "inode.h"#include "fs_native.h"#ifdef REDSTORM#include <sys/uio.h>#endif#if defined(SYSIO_SYS_getdirentries)#define DIR_CVT_64 0#elif defined(SYSIO_SYS_getdents64)#define DIR_CVT_64 0#elif defined(SYSIO_SYS_getdents)#if defined(_LARGEFILE64_SOURCE)#define DIR_CVT_64 1/* * Kernel version of directory entry. */struct linux_dirent {	unsigned long ld_ino;	unsigned long ld_off;	unsigned short ld_reclen;	char	ld_name[1];};#include <dirent.h>#else /* !defined(_LARGEFILE64_SOURCE) */#define DIR_CVT_64 0#endif /* defined(_LARGEFILE64_SOURCE) */#else /* catch-none */#error No usable directory fill entries interface available#endif/* * Native file system information we keep per FS. */struct native_filesystem {	time_t	nfs_atimo;				/* attr timeout (sec) */};/* * Given fs, return driver private part. */#define FS2NFS(fs) \	((struct native_filesystem *)(fs)->fs_private)/* * Native file identifiers format. */struct native_inode_identifier {	dev_t	dev;					/* device number */	ino_t	ino;					/* i-number */#ifdef HAVE_GENERATION	unsigned int gen;                               /* generation number */#endif};/* * Driver-private i-node information we keep about local host file * system objects. */struct native_inode {	unsigned		ni_seekok		: 1,		/* can seek? */		ni_attrvalid		: 1,		/* cached attrs ok? */		ni_resetfpos		: 1;		/* reset fpos? */	struct native_inode_identifier ni_ident;	/* unique identifier */	struct file_identifier ni_fileid;		/* ditto */	int	ni_fd;					/* host fildes */	int	ni_oflags;				/* flags, from open */	unsigned ni_nopens;				/* soft ref count */	_SYSIO_OFF_T ni_fpos;				/* current pos */	time_t	ni_attrtim;				/* attrs expire time */};/* * Cached attributes usable? */#define NATIVE_ATTRS_VALID(nino, t) \	((nino)->ni_attrtim && (t) < (nino)->ni_attrtim)/* * Native IO path arguments. */struct native_io {	char	nio_op;					/* 'r' or 'w' */	struct native_inode *nio_nino;			/* native ino */};static int native_inop_lookup(struct pnode *pno,			      struct inode **inop,			      struct intent *intnt,			      const char *path);static int native_inop_getattr(struct pnode *pno,			       struct inode *ino,			       struct intnl_stat *stbuf);static int native_inop_setattr(struct pnode *pno,			       struct inode *ino,			       unsigned mask,			       struct intnl_stat *stbuf);static ssize_t native_filldirentries(struct inode *ino,				     _SYSIO_OFF_T *posp,				     char *buf,				     size_t nbytes);static int native_inop_mkdir(struct pnode *pno, mode_t mode);static int native_inop_rmdir(struct pnode *pno);static int native_inop_symlink(struct pnode *pno, const char *data);static int native_inop_readlink(struct pnode *pno, char *buf, size_t bufsiz);static int native_inop_open(struct pnode *pno, int flags, mode_t mode);static int native_inop_close(struct inode *ino);static int native_inop_link(struct pnode *old, struct pnode *new);static int native_inop_unlink(struct pnode *pno);static int native_inop_rename(struct pnode *old, struct pnode *new);static int native_inop_read(struct inode *ino, struct ioctx *ioctx);static int native_inop_write(struct inode *ino, struct ioctx *ioctx);static _SYSIO_OFF_T native_inop_pos(struct inode *ino, _SYSIO_OFF_T off);static int native_inop_iodone(struct ioctx *ioctx);static int native_inop_fcntl(struct inode *ino, int cmd, va_list ap, int *rtn);static int native_inop_sync(struct inode *ino);static int native_inop_datasync(struct inode *ino);static int native_inop_ioctl(struct inode *ino,			     unsigned long int request,			     va_list ap);static int native_inop_mknod(struct pnode *pno, mode_t mode, dev_t dev);#ifdef _HAVE_STATVFSstatic int native_inop_statvfs(struct pnode *pno,			       struct inode *ino,			       struct intnl_statvfs *buf);#endifstatic void native_inop_gone(struct inode *ino);static struct inode_ops native_i_ops = {	native_inop_lookup,	native_inop_getattr,	native_inop_setattr,	native_filldirentries,	native_inop_mkdir,	native_inop_rmdir,	native_inop_symlink,	native_inop_readlink,	native_inop_open,	native_inop_close,	native_inop_link,	native_inop_unlink,	native_inop_rename,	native_inop_read,	native_inop_write,	native_inop_pos,	native_inop_iodone,	native_inop_fcntl,	native_inop_sync,	native_inop_datasync,	native_inop_ioctl,	native_inop_mknod,#ifdef _HAVE_STATVFS	native_inop_statvfs,#endif	native_inop_gone};static int native_fsswop_mount(const char *source,			       unsigned flags,			       const void *data,			       struct pnode *tocover,			       struct mount **mntp);static struct fssw_ops native_fssw_ops = {	native_fsswop_mount};static void native_fsop_gone(struct filesys *fs);static struct filesys_ops native_inodesys_ops = {	native_fsop_gone,};/* * This example driver plays a strange game. It maintains a private, * internal mount -- It's own separate, rooted, name space. The local * file system's entire name space is available via this tree. * * This simplifies the implementation. At mount time, we need to generate * a path-node to be used as a root. This allows us to look up the needed * node in the host name space and leverage a whole lot of support from * the system. */static struct mount *native_internal_mount = NULL;/* * Given i-node, return driver private part. */#define I2NI(ino)	((struct native_inode *)((ino)->i_private))/* * stat -- by path. */static intnative_stat(const char *path,	    struct inode *ino,	    time_t t,	    struct intnl_stat *buf){	struct native_inode *nino;	int	err;	struct _sysio_native_stat stbuf;	nino = ino ? I2NI(ino) : NULL;	if (path)		err = syscall(SYSIO_SYS_stat, path, &stbuf);	else if (nino && nino->ni_fd >= 0)		err = syscall(SYSIO_SYS_fstat, nino->ni_fd, &stbuf);	else		abort();	if (err) {		if (nino)			nino->ni_attrtim = 0;		return -errno;	}	if (nino) {		nino->ni_attrtim = t;		SYSIO_COPY_STAT(&stbuf, &ino->i_stbuf);		if (buf)			*buf = ino->i_stbuf;		return 0;	}	if (!buf)		return 0;	SYSIO_COPY_STAT(&stbuf, buf);	return 0;}/* * Introduce an i-node to the system. */static struct inode *native_i_new(struct filesys *fs, time_t expiration, struct intnl_stat *buf){	struct native_inode *nino;	struct inode *ino;	nino = malloc(sizeof(struct native_inode));	if (!nino)		return NULL;	bzero(&nino->ni_ident, sizeof(nino->ni_ident));	nino->ni_seekok = 0;	nino->ni_attrvalid = 0;	nino->ni_resetfpos = 0;	nino->ni_ident.dev = buf->st_dev;	nino->ni_ident.ino = buf->st_ino;#ifdef HAVE_GENERATION	nino->ni_ident.gen = buf->st_gen;#endif	nino->ni_fileid.fid_data = &nino->ni_ident;	nino->ni_fileid.fid_len = sizeof(nino->ni_ident);	nino->ni_fd = -1;	nino->ni_oflags = 0;	nino->ni_nopens = 0;	nino->ni_fpos = 0;	nino->ni_attrtim = expiration;	ino =	    _sysio_i_new(fs,			 &nino->ni_fileid,			 buf,			 0,			 &native_i_ops,			 nino);	if (!ino)		free(nino);	return ino;}/* * Initialize this driver. */int_sysio_native_init(){	/*	 * Capture current process umask and reset our process umask to	 * zero. All permission bits to open/creat/setattr are absolute --	 * They've already had a umask applied, when appropriate.	 */#ifndef REDSTORM        _sysio_umask = syscall(SYSIO_SYS_umask, 0);        /*         *      For Red Storm, this functionality is handled in cstart.         *      The mask to be "captured" has been sent already.         *      This eliminates a system call from every node!         */#endif  /* REDSTORM  */	return _sysio_fssw_register("native", &native_fssw_ops);}/* * Create private, internal, view of the hosts name space. */static intcreate_internal_namespace(const void *data){	char	*opts;	ssize_t	len;	char	*cp;	struct native_filesystem *nfs;	int	err;	struct mount *mnt;	struct inode *rootino;	struct pnode_base *rootpb;	static struct qstr noname = { NULL, 0, 0 };	struct filesys *fs;	time_t	t;	struct intnl_stat stbuf;	unsigned long ul;	static struct option_value_info v[] = {		{ "atimo",	"30" },		{ NULL,		NULL }	};	if (native_internal_mount) {		/*		 * Reentered!		 */		abort();	}	/*	 * Get mount options.	 */	opts = NULL;	if (data && (len = strlen((char *)data))) {		opts = malloc(len + 1);		if (!opts)			return -ENOMEM;		(void )strcpy(opts, data);		if (_sysio_get_args(opts, v) - opts != (ssize_t )len)			return -EINVAL;	}	ul = strtoul(v[0].ovi_value, &cp, 0);	if (*cp != '\0' || ul >= UINT_MAX)		return -EINVAL;	if (opts) {		free(opts);		opts = NULL;	}	/*	 * We maintain an artificial, internal, name space in order to	 * have access to fully qualified path names in the various routines.	 * Initialize that name space now.	 */	fs = NULL;	mnt = NULL;	rootino = NULL;	rootpb = NULL;	/*	 * This really should be per-mount. Hmm, but that's best done	 * as proper sub-mounts in the core and not this driver. We reconcile	 * now, here, by putting the mount options on the file system. That	 * means they are global and only can be passed at the initial mount.	 *	 * Maybe do it right some day?	 */	nfs = malloc(sizeof(struct native_filesystem));	if (!nfs) {		err = -ENOMEM;		goto error;	}	nfs->nfs_atimo = ul;	if ((unsigned long)nfs->nfs_atimo != ul) {		err = -EINVAL;		goto error;	}	fs = _sysio_fs_new(&native_inodesys_ops, 0, nfs);	if (!fs) {		err = -ENOMEM;		goto error;	}	/*	 * Get root i-node.	 */	t = _SYSIO_LOCAL_TIME();	err = native_stat("/", NULL, 0, &stbuf);	if (err)		goto error;	rootino = native_i_new(fs, t + FS2NFS(fs)->nfs_atimo, &stbuf);	if (!rootino) {		err = -ENOMEM;		goto error;	}	/*	 * Generate base path-node for root.	 */	rootpb = _sysio_pb_new(&noname, NULL, rootino);	if (!rootpb) {		err = -ENOMEM;		goto error;	}	/*	 * Mount it. This name space is disconnected from the	 * rest of the system -- Only available within this driver.	 */	err = _sysio_do_mount(fs, rootpb, 0, NULL, &mnt);	if (err)		goto error;	native_internal_mount = mnt;	return 0;error:	if (mnt) {		if (_sysio_do_unmount(mnt) != 0)			abort();		nfs = NULL;		fs = NULL;		rootpb = NULL;		rootino = NULL;	}	if (rootpb)		_sysio_pb_gone(rootpb);	if (fs) {		FS_RELE(fs);		nfs = NULL;	}	if (nfs)		free(nfs);	if (opts)		free(opts);	return err;}static intnative_fsswop_mount(const char *source,		    unsigned flags,		    const void *data,		    struct pnode *tocover,		    struct mount **mntp){	int	err;	struct nameidata nameidata;	struct mount *mnt;	/*	 * Caller must use fully qualified path names when specifying	 * the source.	 */	if (*source != '/')		return -ENOENT;	if (!native_internal_mount) {		err = create_internal_namespace(data);		if (err)			return err;	} else if (data && *(char *)data)		return -EINVAL;	/*	 * Lookup the source in the internally maintained name space.	 */	ND_INIT(&nameidata, 0, source, native_internal_mount->mnt_root, NULL);	err = _sysio_path_walk(native_internal_mount->mnt_root, &nameidata);	if (err)		return err;	/*	 * Have path-node specified by the given source argument. Let the	 * system finish the job, now.	 */	err =	    _sysio_do_mount(native_internal_mount->mnt_fs,			    nameidata.nd_pno->p_base,			    flags,			    tocover,			    &mnt);	/*	 * Release the internal name space pnode and clean up any	 * aliases we might have generated. We really don't need to cache them	 * as they are only used at mount time..	 */	P_RELE(nameidata.nd_pno);	(void )_sysio_p_prune(native_internal_mount->mnt_root);	if (!err) {		FS_REF(native_internal_mount->mnt_fs);		*mntp = mnt;	}	return err;}static intnative_i_invalid(struct inode *inop, struct intnl_stat *stat){	struct native_inode *nino;	/*	 * Validate passed in inode against stat struct info	 */	nino = I2NI(inop);		if (!nino->ni_attrtim ||	    (nino->ni_ident.dev != stat->st_dev ||	     nino->ni_ident.ino != stat->st_ino ||#ifdef HAVE_GENERATION	     nino->ni_ident.gen != stat->st_gen ||#endif	     ((inop)->i_stbuf.st_mode & S_IFMT) != (stat->st_mode & S_IFMT)) ||	    (((inop)->i_stbuf.st_rdev != stat->st_rdev) &&	       (S_ISCHR((inop)->i_stbuf.st_mode) ||	        S_ISBLK((inop)->i_stbuf.st_mode)))) {		nino->ni_attrtim = 0;			/* invalidate attrs */		return 1;	}	return 0;}static struct inode *native_iget(struct filesys *fs, time_t expire, struct intnl_stat *stbp){	struct inode *ino;	struct native_inode_identifier ident;	struct file_identifier fileid;	bzero(&ident, sizeof(ident)); 

⌨️ 快捷键说明

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