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

📄 fs_incore.c

📁 非常经典的一个分布式系统
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (((l == LONG_MIN || l == LONG_MAX) &&		     errno == ERANGE) ||		    (long )gid != l)			return -EINVAL;		if (*cp != '\0')			return -EINVAL;	}	err = 0;	dev = _sysio_dev_alloc();	mnt = NULL;	rootpb = NULL;	rooti = NULL;	fs = NULL;	icino = NULL;	icfs = NULL;	/*	 * Create new FS.	 */	icfs = malloc(sizeof(struct incore_filesys));	if (!icfs) {		err = -ENOMEM;		goto error;	}	(void )memset(icfs, 0, sizeof(struct incore_filesys));	LIST_INIT(&icfs->icfs_icinodes);	/*	 * Create root i-node.	 */	(void )memset(&stat, 0, sizeof(stat));	stat.st_dev = dev;	inum = incore_inum_alloc();#ifdef HAVE__ST_INO	stat.__st_ino = inum; #endif	stat.st_mode = S_IFDIR | (mode & 07777);	stat.st_nlink = 2;	stat.st_uid = uid;	stat.st_gid = gid;	stat.st_size = 0;	stat.st_blksize = INCORE_BLKSIZE;	stat.st_blocks = 0;	stat.st_ctime = stat.st_mtime = stat.st_atime = 0;	stat.st_ino = inum;	icino = incore_directory_new(icfs, NULL, &stat);	if (!icino)		return -ENOSPC;	icino->ici_st.st_atime = icino->ici_st.st_mtime;	fs =	    _sysio_fs_new(&incore_fs_ops,			  (flags & MOUNT_F_RO) ? FS_F_RO : 0,			  icfs);	if (!fs) {		err = -ENOMEM;		goto error;	}	/*	 * Create root for system.	 *	 * Persistent across remounts because we ask for immunity.	 */	rooti =	    _sysio_i_new(fs,			 &icino->ici_fileid,			 &icino->ici_st,			 1,			 &_sysio_incore_dir_ops,			 icino);	if (!rooti) {		err = -ENOMEM;		goto error;	}	rootpb = _sysio_pb_new(&noname, NULL, rooti);	if (!rootpb) {		err = -ENOMEM;		goto error;	}	/*	 * Have path-node specified by the given source argument. Let the	 * system finish the job, now.	 */	mnt = NULL;	err =	    _sysio_do_mount(fs,			    rootpb,			    flags,			    tocover,			    &mnt);	if (err)		goto error;	*mntp = mnt;	goto out;error:	if (mnt && _sysio_do_unmount(mnt) != 0)			abort();	if (rootpb) {		_sysio_pb_gone(rootpb);		rooti = NULL;	}	if (rooti)		I_RELE(rooti);	if (fs) {		FS_RELE(fs);		goto out;	}	if (icino) {		incore_i_destroy(icino);		goto out;	}	if (icfs) {		free(icfs);		goto out;	}out:	return err;}static void_sysio_incore_fsop_gone(struct filesys *fs){	struct incore_filesys *icfs;	struct incore_inode *icino, *oicino;	icfs = FS2ICFS(fs);	/*	 * Free up i-node resource associated with this file system.	 */	icino = icfs->icfs_icinodes.lh_first;	while (icino) {		oicino = icino;		icino = icino->ici_link.le_next;		incore_i_destroy(oicino);	}	/*	 * Free the FS record.	 */	free(icfs);}/* * A directory search engine. Various functions are carried out by * supplying appropriate callback functions. * * The two arguments, entry and hole, are called, if not null, for each * directory entry and hole, respectively. */static void *incore_directory_probe(void *data,		       size_t siz,		       _SYSIO_OFF_T origin#ifndef _DIRENT_HAVE_D_OFF				__IS_UNUSED#endif		       ,		       probe_ty entry,		       probe_ty hole,		       void *arg){	struct intnl_dirent *de;	void	*p;	size_t	n;	de = data;	for (;;) {#ifdef _DIRENT_HAVE_D_OFF		assert(de->d_off);#else		assert(de->d_reclen);#endif		if (entry && (p = (*entry)(de, de->d_reclen, arg)))			return p;		n =#ifdef _DIRENT_HAVE_D_OFF		    de->d_off - origin;#else		    ((void *)de - data) + de->d_reclen;#endif		if (hole) {			p = (*hole)((void *)de, de->d_reclen, arg);			if (p)				return p;		}		if (n >= siz)			break;		de = (struct intnl_dirent *)((char *)data + n);	}	return NULL;}static struct intnl_dirent *incore_directory_match(struct intnl_dirent *de,		       size_t reclen,		       struct lookup_data *ld){	size_t	len;#if defined(BSD) || defined(REDSTORM)	if (IFTODT(de->d_type) == DT_WHT)		return NULL;#endif#ifdef _DIRENT_HAVE_D_NAMLEN	len = de->d_namlen;#else	{		const char *cp, *end;		cp = de->d_name;		end = (const char *)de + reclen;		while (cp < end && *cp != '\0')			cp++;		len = cp - de->d_name;	}#endif	if (ld->name->len == len &&	    strncmp(de->d_name, ld->name->name, ld->name->len) == 0)		return de;	ld->de = de;	return NULL;}static int_sysio_incore_dirop_lookup(struct pnode *pno,			   struct inode **inop,			   struct intent *intnt __IS_UNUSED,			   const char *path __IS_UNUSED){	struct inode *ino;	struct intnl_dirent *de;	struct incore_inode *icino;	struct lookup_data lookup_data;	struct file_identifier fileid;#ifdef notdef	struct inode_ops *ops;#endif	/*	 * Revalidate?	 */	if (*inop) {		icino = I2IC(*inop);		assert(icino);		(*inop)->i_stbuf = icino->ici_st;		return 0;	}	ino = pno->p_parent->p_base->pb_ino;	icino = I2IC(ino);	INCORE_LD_INIT(&lookup_data,		       ULONG_MAX,		       &pno->p_base->pb_name);	de =	    incore_directory_probe(icino->ici_data,				   icino->ici_st.st_size,				   0,				   (probe_ty )incore_directory_match,				   NULL,				   &lookup_data);	if (!de)		return -ENOENT;	fileid.fid_data = &de->d_ino;	fileid.fid_len = sizeof(de->d_ino);	ino =	    _sysio_i_find(ino->i_fs, &fileid);#ifdef notdef	if (ino)		goto out;	icino->ici_fileid.fid_data = &icino->ici_st.st_ino;	icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino);	ops = NULL;	switch (icino->ici_st.st_mode & S_IFMT) {	case S_IFDIR:		ops = &_sysio_incore_dir_ops;		break;	case S_IFREG:		ops = &_sysio_incore_file_ops;		break;	default:		break;	}	if (!ops)		abort();	ino =	    _sysio_i_new(ino->i_fs,			 &icino->ici_fileid,			 &icino->ici_st			 1,			 ops,			 icino);#endif	if (!ino)		return -ENOMEM;#ifdef notdefout:#endif	*inop = ino;	return 0;}static int_sysio_incore_inop_getattr(struct pnode *pno,			   struct inode *ino,			   struct intnl_stat *stbuf){	struct incore_inode *icino;	if (!ino)		ino = pno->p_base->pb_ino;	icino = I2IC(ino);	*stbuf = icino->ici_st;	return 0;}static int_sysio_incore_inop_setattr(struct pnode *pno,			   struct inode *ino,			   unsigned mask,			   struct intnl_stat *stbuf){	struct incore_inode *icino;	int	err;	if (!ino)		ino = pno->p_base->pb_ino;	if (!ino)		return -EBADF;	icino = I2IC(ino);	err = 0;	if (mask & SETATTR_LEN) {		err = incore_trunc(icino, stbuf->st_size, 1);		if (err)			goto out;		mask &= ~SETATTR_LEN;	}	if (mask & SETATTR_MODE) {		icino->ici_st.st_mode =		    (icino->ici_st.st_mode & S_IFMT) | (stbuf->st_mode & 07777);	}	if (mask & SETATTR_MTIME)		icino->ici_st.st_mtime = stbuf->st_mtime;	if (mask & SETATTR_ATIME)		icino->ici_st.st_atime = stbuf->st_atime;	if (mask & SETATTR_UID)		icino->ici_st.st_uid = stbuf->st_uid;	if (mask & SETATTR_GID)		icino->ici_st.st_gid = stbuf->st_gid;	icino->ici_st.st_ctime = time(NULL);	ino->i_stbuf = icino->ici_st;out:	return err;}static void *incore_directory_position(struct intnl_dirent *de,			  size_t reclen __IS_UNUSED,			  void *p){	return (void *)de >= p ? de : NULL;}struct copy_info {	void	*data;	size_t	nbytes;	unsigned count;};/* * Eumeration callback. * * Note: * Whiteout entries are never returned. */static void *incore_directory_enumerate(struct intnl_dirent *de,			   size_t reclen,			   struct copy_info *cinfo) {#ifdef DT_WHT	if (de->d_type == DT_WHT) {		/*		 * Keep going  but skip the copy.		 */		return NULL;	}#endif	cinfo->count++;	if (reclen > cinfo->nbytes)		return de;	(void *)memcpy(cinfo->data, de, reclen);	cinfo->data = (char *)cinfo->data + reclen;	cinfo->nbytes -= reclen;	return NULL;}static ssize_t_sysio_incore_dirop_filldirentries(struct inode *ino,				   _SYSIO_OFF_T *posp,				   char *buf,				   size_t nbytes){	struct incore_inode *icino = I2IC(ino);	off_t	off;	struct intnl_dirent *de;	struct copy_info copy_info;	if (*posp >= icino->ici_st.st_size)		return 0;	de =	    incore_directory_probe(icino->ici_data,				   icino->ici_st.st_size,				   *posp,				   (probe_ty )incore_directory_position,				   NULL,				   (char *)icino->ici_data + *posp);	if (!de) {		/*		 * Past EOF.		 */		return 0;	}	copy_info.data = buf;	copy_info.nbytes = nbytes;	copy_info.count = 0;	off = (char *)de - (char *)icino->ici_data;	de =	    incore_directory_probe(de,				   icino->ici_st.st_size - off,				   off,				   (probe_ty )incore_directory_enumerate,				   NULL,				   &copy_info);	icino->ici_st.st_atime = time(NULL);	if (nbytes == copy_info.nbytes && copy_info.count)		return -EINVAL;	nbytes -= copy_info.nbytes;#if 0	if (!nbytes)		return -EOVERFLOW;#endif	*posp += nbytes;	return (ssize_t )nbytes;}static struct intnl_dirent *incore_directory_best_fit(void *data, size_t len, struct lookup_data *ld){	if (!ld->hole.len || len < ld->hole.len) {		ld->hole.p = data;		ld->hole.len = len;	}	return NULL;}static intincore_directory_insert(struct incore_inode *parent,			struct qstr *name,			ino_t inum,			unsigned char type){	size_t	reclen;	struct lookup_data lookup_data;	struct intnl_dirent *de;	size_t	xt;	size_t	n;	size_t	r;	reclen = INCORE_D_RECLEN(name->len);	INCORE_LD_INIT(&lookup_data, reclen, name);	de =	    incore_directory_probe(parent->ici_data,				   parent->ici_st.st_size,				   0,				   (probe_ty )incore_directory_match,				   (probe_ty )incore_directory_best_fit,				   &lookup_data);	if (de)		return -EEXIST;	de = lookup_data.de;	xt = (char *)lookup_data.de - (char *)parent->ici_data;	n =#ifdef _DIRENT_HAVE_D_OFF	    de->d_off;#else	    xt + de->d_reclen;#endif	r =#ifdef _DIRENT_HAVE_D_OFF	    de->d_reclen;#else	    INCORE_D_RECLEN(de->d_namlen);#endif	if (!parent->ici_st.st_size ||	    xt + r + reclen > (size_t )parent->ici_st.st_size) {		int	err;		err = incore_trunc(parent, xt + r + reclen, 1);		if (err)			return err;		de = (struct intnl_dirent *)((char *)parent->ici_data + xt);		n = parent->ici_st.st_size;	}#ifdef _DIRENT_HAVE_D_OFF	de->d_off = xt + r;				/* trim */#else	de->d_reclen = r;#endif	de = (struct intnl_dirent *)((char *)de + r);				/* reposition */	xt += r;#ifndef _DIRENT_HAVE_D_OFF	/*	 * Will we split this hole or use all of it?	 */	if (lookup_data.hole.len - reclen &&	    lookup_data.hole.len - reclen <= INCORE_D_RECLEN(1))		reclen = lookup_data.hole.len;#endif	/*	 * Insert new.	 */	de->d_ino = inum;#ifdef _DIRENT_HAVE_D_OFF	de->d_off = n;#endif	de->d_reclen = reclen;	de->d_type = type;	(void )memcpy(de->d_name, name->name, name->len);#ifdef _DIRENT_HAVE_D_NAMLEN	de->d_namlen = name->len;#endif#ifndef _DIRENT_HAVE_D_OFF	xt += reclen;	if (n - xt) {		/*		 * White-out remaining part of the hole.		 */		(void *)de += reclen;		de->d_ino = 0;		de->d_reclen = n - xt;		de->d_type = DT_WHT;		de->d_namlen = 0;	}#endif	/*	 * Update attributes to reflect the new entry.	 */	parent->ici_st.st_nlink++;	assert(parent->ici_st.st_nlink);	parent->ici_st.st_atime = parent->ici_st.st_mtime = time(NULL);

⌨️ 快捷键说明

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