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

📄 fs_native.c

📁 非常经典的一个分布式系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	ident.dev = stbp->st_dev;	ident.ino = stbp->st_ino;#ifdef HAVE_GENERATION	ident.gen = stbp->st_gen;#endif	fileid.fid_data = &ident;	fileid.fid_len = sizeof(ident);	ino = _sysio_i_find(fs, &fileid);	if (ino) {		ino->i_stbuf = *stbp;		I2NI(ino)->ni_attrtim = expire;		return ino;	}	return native_i_new(fs, expire, stbp);}/* * Find, and validate, or create i-node by host-relative path. Returned i-node * is referenced. */static intnative_ibind(struct filesys *fs,	     char *path,	     time_t t,	     struct inode **inop){	struct intnl_stat ostbuf, stbuf;	int	err;	struct inode *ino;	if (*inop)		ostbuf = (*inop)->i_stbuf;	err = native_stat(path, *inop, t, &stbuf);	if (err)		return err;	/* 	 * Validate?	 */	if (*inop) {		if (!native_i_invalid(*inop, &ostbuf))			return 0;		/*		 * Invalidate.		 */		_sysio_i_undead(*inop);		*inop = NULL;	}	if (!(ino = native_iget(fs, t + FS2NFS(fs)->nfs_atimo, &stbuf)))		return -ENOMEM;	*inop = ino;	return 0;}static intnative_inop_lookup(struct pnode *pno,		   struct inode **inop,		   struct intent *intnt __IS_UNUSED,		   const char *path __IS_UNUSED){	time_t	t;	char	*fqpath;	struct filesys *fs;	int	err;	*inop = pno->p_base->pb_ino;	/*	 * Try to use the cached attributes unless the intent	 * indicates we are looking up the last component and	 * caller wants attributes. In that case, force a refresh.	 */	t = _SYSIO_LOCAL_TIME();	if (*inop &&	    (path || !intnt || (intnt->int_opmask & INT_GETATTR) == 0) &&	    NATIVE_ATTRS_VALID(I2NI(*inop), t))		return 0;	/*	 * Don't have an inode yet. Because we translate everything back to	 * a single name space for the host, we will assume the object the	 * caller is looking for has no existing alias in our internal	 * name space. We don't see the same file on different mounts in the	 * underlying host FS as the same file.	 *	 * The file identifier *will* be unique. It's got to have a different	 * dev.	 */	fqpath = _sysio_pb_path(pno->p_base, '/');	if (!fqpath)		return -ENOMEM;	fs = pno->p_mount->mnt_fs;	err = native_ibind(fs, fqpath, t + FS2NFS(fs)->nfs_atimo, inop);	free(fqpath);	if (err)		*inop = NULL;	return err;}static intnative_inop_getattr(struct pnode *pno,		    struct inode *ino,		    struct intnl_stat *stat){	struct native_inode *nino;	int	err;	/*	 * We just cannot use the cached attributes when getattr is	 * called. Had the caller felt those were sufficient then	 * they could have (would have?) simply used what was cached	 * after revalidating. In this case, there's a good chance the	 * caller is looking for the current time stamps and/or size. Something	 * pretty volatile anyway.	 */	err = 0;					/* compiler cookie */	if (pno) {		char	*path;		struct filesys *fs;		time_t	t;		path = _sysio_pb_path(pno->p_base, '/');		if (!path)			return -ENOMEM;		fs = pno->p_mount->mnt_fs;		t = _SYSIO_LOCAL_TIME();		err = native_stat(path, ino, t + FS2NFS(fs)->nfs_atimo, stat);		free(path);	} else if ((nino = I2NI(ino))->ni_fd >= 0)		/*		 * Don't have access to the fs record anymore. Just		 * refresh but keep the current timeout.		 */		err = native_stat(NULL, ino, nino->ni_attrtim, stat);	else {		/*		 * Dev inodes don't open in this driver. We won't have		 * a file descriptor with which to do the deed then. Satisfy		 * the request from the cached copy of the attributes.		 */		(void )memcpy(stat,			      &ino->i_stbuf,			      sizeof(struct intnl_stat));		err = 0;	}		return err;}#ifdef SYSIO_SYS_utimestatic int_ut(const char *path, time_t actime, time_t modtime){	struct utimbuf ut;	ut.actime = actime;	ut.modtime = modtime;	return syscall(SYSIO_SYS_utime, path, &ut);}#elsestatic int_ut(const char *path, time_t actime, time_t modtime){	struct timeval tv[2];	tv[0].tv_sec = actime;	tv[0].tv_usec = 0;	tv[1].tv_sec = modtime;	tv[1].tv_usec = 0;	return syscall(SYSIO_SYS_utimes, path, &tv);}#endifstatic intnative_inop_setattr(struct pnode *pno,		    struct inode *ino,		    unsigned mask,		    struct intnl_stat *stat){	char	*path;	struct native_inode *nino;	int	fd;	int	err;	path = NULL;	nino = ino ? I2NI(ino) : NULL;	fd = -1;	if (nino)		fd = nino->ni_fd;	if (fd < 0 || mask & (SETATTR_MTIME|SETATTR_ATIME)) {		if (!pno)			return -EEXIST;		path = _sysio_pb_path(pno->p_base, '/');		if (!path)			return -ENOMEM;	}	/*	 * Get current status for undo.	 */	err = native_stat(path, ino, 0, NULL);	if (err)		goto out;	if (mask & SETATTR_MODE) {		mode_t	mode;		/*		 * Alter permissions attribute.		 */		mode = stat->st_mode & 07777;		err =		    fd < 0		      ? syscall(SYSIO_SYS_chmod, path, mode)		      : syscall(SYSIO_SYS_fchmod, fd, mode);		if (err)			err = -errno;	}	if (err)		mask &= ~SETATTR_MODE;	else if (mask & (SETATTR_MTIME|SETATTR_ATIME)) {		time_t	actime, modtime;		/*		 * Alter access and/or modify time attributes.		 */		actime  = ino->i_stbuf.st_atime;		modtime  = ino->i_stbuf.st_mtime;		if (mask & SETATTR_ATIME)			actime = stat->st_atime;		if (mask & SETATTR_MTIME)			modtime = stat->st_mtime;		if (_ut(path, actime, modtime) != 0)			return -errno;	}	if (err)		mask &= ~(SETATTR_MTIME|SETATTR_ATIME);	else if (mask & (SETATTR_UID|SETATTR_GID)) {		/*		 * Alter owner and/or group identifiers.		 */		err =		    fd < 0		      ? syscall(SYSIO_SYS_chown,				path,				mask & SETATTR_UID				  ? stat->st_uid				  : (uid_t )-1,				mask & SETATTR_GID				  ? stat->st_gid				  : (gid_t )-1)		      : syscall(SYSIO_SYS_fchown,				fd,				mask & SETATTR_UID				  ? stat->st_uid				  : (uid_t )-1,				mask & SETATTR_GID				  ? stat->st_gid				  : (gid_t )-1);		if (err)			err = -errno;	}	if (err)		mask &= ~(SETATTR_UID|SETATTR_GID);	else if (mask & SETATTR_LEN) {		/*		 * Do the truncate last. It can't be undone.		 */		 err = fd < 0			   ? syscall(SYSIO_SYS_truncate, path, stat->st_size)			   : syscall(SYSIO_SYS_ftruncate, fd, stat->st_size);		if (err)			err = -errno;	}	if (!err)		goto out;	/*	 * Undo after error. Some or all of this might not work... We	 * can but try.	 */	if (mask & (SETATTR_UID|SETATTR_GID)) {		 (void )(fd < 0			   ? syscall(SYSIO_SYS_chown,				     path,				     mask & SETATTR_UID				       ? ino->i_stbuf.st_uid				       : (uid_t )-1,				     mask & SETATTR_GID				       ? ino->i_stbuf.st_gid				       : (gid_t )-1)			   : syscall(SYSIO_SYS_fchown,				     fd,				     mask & SETATTR_UID				       ? ino->i_stbuf.st_uid				       : (uid_t )-1,				     mask & SETATTR_GID				       ? ino->i_stbuf.st_gid				       : (gid_t )-1));	}	if (mask & (SETATTR_MTIME|SETATTR_ATIME))		(void )_ut(path, ino->i_stbuf.st_atime, ino->i_stbuf.st_mtime);	if (mask & SETATTR_MODE) {		fd < 0		  ? syscall(SYSIO_SYS_chmod, path, ino->i_stbuf.st_mode & 07777)		  : syscall(SYSIO_SYS_fchmod, ino->i_stbuf.st_mode & 07777);	}out:	/*	 * We must refresh the cached attributes.	 */	if (!err && native_stat(path, ino, _SYSIO_LOCAL_TIME(), NULL) != 0)		abort();	if (path)		free(path);	return err;}static intnative_pos(int fd, _SYSIO_OFF_T *offset, int whence){	_SYSIO_OFF_T off;	assert(fd >= 0);	assert(*offset >= 0);	off = *offset;#if defined(_LARGEFILE64_SOURCE) && defined(SYSIO_SYS__llseek)	{		int	err;		err =		    syscall(SYSIO_SYS__llseek,			    (unsigned int)fd,			    (unsigned int)(off >> 32),			    (unsigned int)off,			    &off,			    whence);		if (err == -1)			return -errno;	}#else	off =	    syscall(SYSIO_SYS_lseek,		    fd,		    off,		    whence);	if (off == -1)		return -errno;#endif	*offset = off;	return 0;}static ssize_tnative_ifilldirentries(struct native_inode *nino,		       _SYSIO_OFF_T *posp,		       char *buf,		       size_t nbytes){	int	err;	ssize_t	cc;#if defined(SYSIO_SYS_getdirentries)	_SYSIO_OFF_T	waste=*posp;#endif	if (*posp < 0)		return -EINVAL;	/*	 * Stream-oriented access requires that we reposition prior to the	 * fill call.	 */	assert(nino->ni_seekok);	if (*posp != nino->ni_fpos || nino->ni_resetfpos) {		nino->ni_fpos = *posp;		err = native_pos(nino->ni_fd, &nino->ni_fpos, SEEK_SET);		if (err) {			nino->ni_resetfpos = 1;			return err;		}		nino->ni_resetfpos = 0;	}	cc =#if defined(SYSIO_SYS_getdirentries)	    syscall(SYSIO_SYS_getdirentries,		    nino->ni_fd,		    buf,		    nbytes,		    &waste);#elif defined(SYSIO_SYS_getdents64)	    syscall(SYSIO_SYS_getdents64, nino->ni_fd, buf, nbytes);#elif defined(SYSIO_SYS_getdents)	    syscall(SYSIO_SYS_getdents, nino->ni_fd, buf, nbytes);#endif	if (cc < 0)		return -errno;	/*	 * Stream-oriented access requires that we discover where we are	 * after the call.	 */	if ((err = native_pos(nino->ni_fd, &nino->ni_fpos, SEEK_CUR)) != 0) {		/*		 * Leave the position at the old I suppose.		 */		nino->ni_resetfpos = 1;		return err;	}	*posp = nino->ni_fpos;	return cc;}static ssize_tnative_filldirentries(struct inode *ino,		      _SYSIO_OFF_T *posp,		      char *buf,		      size_t nbytes){	struct native_inode *nino = I2NI(ino);#if DIR_CVT_64	char	*bp;	size_t	count;	struct linux_dirent *ldp;	struct dirent64 *d64p;	size_t	namlen;	size_t	reclen;#else#define bp buf#define count nbytes#endif	ssize_t	cc;	assert(nino->ni_fd >= 0);#if DIR_CVT_64	count = nbytes;	while (!(bp = malloc(count))) {		count /= 2;		if (count < sizeof(struct dirent))			return -ENOMEM;	}#endif	cc = native_ifilldirentries(nino, posp, bp, count);	if (cc < 0) {#if DIR_CVT_64		free(bp);#endif		return cc;	}#if DIR_CVT_64	ldp = (struct linux_dirent *)bp;	d64p = (struct dirent64 *)buf;	while (cc) {		namlen = strlen(ldp->ld_name);		reclen = sizeof(*d64p) - sizeof(d64p->d_name) + namlen;		if (nbytes <= reclen)			break;		d64p->d_ino = ldp->ld_ino;		d64p->d_off = nino->ni_fpos = ldp->ld_off;		d64p->d_reclen = 		    (((reclen + sizeof(long))) / sizeof(long)) * sizeof(long);		if (nbytes < d64p->d_reclen)			d64p->d_reclen = reclen + 1;		d64p->d_type = DT_UNKNOWN;		/* you lose -- sorry. */		(void )memcpy(d64p->d_name, ldp->ld_name, namlen);		/*		 * Zero pad the rest.		 */		for (cp = d64p->d_name + namlen, n = d64p->d_reclen - reclen;		     n;		     n--)			*cp++ = 0;		cc -= ldp->ld_reclen;		ldp = (struct linux_dirent *)((char *)ldp + ldp->ld_reclen);		nbytes -= d64p->d_reclen;		d64p = (struct dirent64 *)((char *)d64p + d64p->d_reclen);	}	free(bp);	cc =	    (d64p == (struct dirent64 *)buf && cc)	      ? -EINVAL	      : (char *)d64p - buf;#else#undef bp#undef count#endif	return cc;}static intnative_inop_mkdir(struct pnode *pno, mode_t mode){	char	*path;	int	err;	path = _sysio_pb_path(pno->p_base, '/');	if (!path)		return -ENOMEM;	err = syscall(SYSIO_SYS_mkdir, path, mode);	if (err != 0)		err = -errno;	free(path);	return err;}static intnative_inop_rmdir(struct pnode *pno){	char	*path;	int	err;	path = _sysio_pb_path(pno->p_base, '/');	if (!path)		return -ENOMEM;	err = syscall(SYSIO_SYS_rmdir, path);	if (err != 0)		err = -errno;	free(path);	return err;}static intnative_inop_symlink(struct pnode *pno, const char *data){	char	*path;	int	err;	path = _sysio_pb_path(pno->p_base, '/');	if (!path)		return -ENOMEM;	err = syscall(SYSIO_SYS_symlink, data, path);	if (err != 0)		err = -errno;	free(path);	return err;}static intnative_inop_readlink(struct pnode *pno, char *buf, size_t bufsiz){	char	*path;	int	i;	path = _sysio_pb_path(pno->p_base, '/');	if (!path)		return -ENOMEM;	i = syscall(SYSIO_SYS_readlink, path, buf, bufsiz);	if (i < 0)		i = -errno;	free(path);	return i;}static int native_inop_open(struct pnode *pno, int flags, mode_t mode){	struct native_inode *nino;	char	*path;	int	fd;	path = _sysio_pb_path(pno->p_base, '/');	if (!path)		return -ENOMEM;	/*	 * Whether the file is already open, or not, makes no difference.	 * Want to always give the host OS a chance to authorize in case	 * something has changed underneath us.	 */	if (flags & O_WRONLY) {		/*		 * Promote write-only attempt to RW.		 */		flags &= ~O_WRONLY;		flags |= O_RDWR;	}#ifdef O_LARGEFILE	flags |= O_LARGEFILE;#endif	fd = syscall(SYSIO_SYS_open, path, flags, mode);	if (!pno->p_base->pb_ino && fd >= 0) {		struct filesys *fs;		int	err;		/*		 * Success but we need to return an i-node.		 */		fs = pno->p_mount->mnt_fs;		err =		    native_ibind(fs,				 path,				 _SYSIO_LOCAL_TIME() + FS2NFS(fs)->nfs_atimo,				 &pno->p_base->pb_ino);		if (err) {			(void )syscall(SYSIO_SYS_close, fd);			if (err == -EEXIST)				abort();

⌨️ 快捷键说明

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