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

📄 xfs_itable.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				irbp->ir_startino = gino;				irbp->ir_freecount = gcnt;				irbp->ir_free = gfree;				irbp++;				agino = gino + XFS_INODES_PER_CHUNK;				icount = XFS_INODES_PER_CHUNK - gcnt;			} else {				/*				 * If any of those tests failed, bump the				 * inode number (just in case).				 */				agino++;				icount = 0;			}			/*			 * In any case, increment to the next record.			 */			if (!error)				error = xfs_inobt_increment(cur, 0, &tmp);		} else {			/*			 * Start of ag.  Lookup the first inode chunk.			 */			error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &tmp);			icount = 0;		}		/*		 * Loop through inode btree records in this ag,		 * until we run out of inodes or space in the buffer.		 */		while (irbp < irbufend && icount < ubcount) {			/*			 * Loop as long as we're unable to read the			 * inode btree.			 */			while (error) {				agino += XFS_INODES_PER_CHUNK;				if (XFS_AGINO_TO_AGBNO(mp, agino) >=						be32_to_cpu(agi->agi_length))					break;				error = xfs_inobt_lookup_ge(cur, agino, 0, 0,							    &tmp);				cond_resched();			}			/*			 * If ran off the end of the ag either with an error,			 * or the normal way, set end and stop collecting.			 */			if (error ||			    (error = xfs_inobt_get_rec(cur, &gino, &gcnt,				    &gfree, &i)) ||			    i == 0) {				end_of_ag = 1;				break;			}			/*			 * If this chunk has any allocated inodes, save it.			 * Also start read-ahead now for this chunk.			 */			if (gcnt < XFS_INODES_PER_CHUNK) {				/*				 * Loop over all clusters in the next chunk.				 * Do a readahead if there are any allocated				 * inodes in that cluster.				 */				for (agbno = XFS_AGINO_TO_AGBNO(mp, gino),				     chunkidx = 0;				     chunkidx < XFS_INODES_PER_CHUNK;				     chunkidx += nicluster,				     agbno += nbcluster) {					if (XFS_INOBT_MASKN(chunkidx,							    nicluster) & ~gfree)						xfs_btree_reada_bufs(mp, agno,							agbno, nbcluster);				}				irbp->ir_startino = gino;				irbp->ir_freecount = gcnt;				irbp->ir_free = gfree;				irbp++;				icount += XFS_INODES_PER_CHUNK - gcnt;			}			/*			 * Set agino to after this chunk and bump the cursor.			 */			agino = gino + XFS_INODES_PER_CHUNK;			error = xfs_inobt_increment(cur, 0, &tmp);			cond_resched();		}		/*		 * Drop the btree buffers and the agi buffer.		 * We can't hold any of the locks these represent		 * when calling iget.		 */		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);		xfs_buf_relse(agbp);		/*		 * Now format all the good inodes into the user's buffer.		 */		irbufend = irbp;		for (irbp = irbuf;		     irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) {			/*			 * Now process this chunk of inodes.			 */			for (agino = irbp->ir_startino, chunkidx = clustidx = 0;			     XFS_BULKSTAT_UBLEFT(ubleft) &&				irbp->ir_freecount < XFS_INODES_PER_CHUNK;			     chunkidx++, clustidx++, agino++) {				ASSERT(chunkidx < XFS_INODES_PER_CHUNK);				/*				 * Recompute agbno if this is the				 * first inode of the cluster.				 *				 * Careful with clustidx.   There can be				 * multple clusters per chunk, a single				 * cluster per chunk or a cluster that has				 * inodes represented from several different				 * chunks (if blocksize is large).				 *				 * Because of this, the starting clustidx is				 * initialized to zero in this loop but must				 * later be reset after reading in the cluster				 * buffer.				 */				if ((chunkidx & (nicluster - 1)) == 0) {					agbno = XFS_AGINO_TO_AGBNO(mp,							irbp->ir_startino) +						((chunkidx & nimask) >>						 mp->m_sb.sb_inopblog);					if (flags & (BULKSTAT_FG_QUICK |						     BULKSTAT_FG_INLINE)) {						ino = XFS_AGINO_TO_INO(mp, agno,								       agino);						bno = XFS_AGB_TO_DADDR(mp, agno,								       agbno);						/*						 * Get the inode cluster buffer						 */						ASSERT(xfs_inode_zone != NULL);						ip = kmem_zone_zalloc(xfs_inode_zone,								      KM_SLEEP);						ip->i_ino = ino;						ip->i_mount = mp;						spin_lock_init(&ip->i_flags_lock);						if (bp)							xfs_buf_relse(bp);						error = xfs_itobp(mp, NULL, ip,								&dip, &bp, bno,								XFS_IMAP_BULKSTAT);						if (!error)							clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;						kmem_zone_free(xfs_inode_zone, ip);						if (XFS_TEST_ERROR(error != 0,								   mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,								   XFS_RANDOM_BULKSTAT_READ_CHUNK)) {							bp = NULL;							ubleft = 0;							rval = error;							break;						}					}				}				ino = XFS_AGINO_TO_INO(mp, agno, agino);				bno = XFS_AGB_TO_DADDR(mp, agno, agbno);				/*				 * Skip if this inode is free.				 */				if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {					lastino = ino;					continue;				}				/*				 * Count used inodes as free so we can tell				 * when the chunk is used up.				 */				irbp->ir_freecount++;				if (!xfs_bulkstat_use_dinode(mp, flags, bp,							     clustidx, &dip)) {					lastino = ino;					continue;				}				/*				 * If we need to do an iget, cannot hold bp.				 * Drop it, until starting the next cluster.				 */				if ((flags & BULKSTAT_FG_INLINE) && !dip) {					if (bp)						xfs_buf_relse(bp);					bp = NULL;				}				/*				 * Get the inode and fill in a single buffer.				 * BULKSTAT_FG_QUICK uses dip to fill it in.				 * BULKSTAT_FG_IGET uses igets.				 * BULKSTAT_FG_INLINE uses dip if we have an				 * inline attr fork, else igets.				 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.				 * This is also used to count inodes/blks, etc				 * in xfs_qm_quotacheck.				 */				ubused = statstruct_size;				error = formatter(mp, ino, ubufp,						ubleft, private_data,						bno, &ubused, dip, &fmterror);				if (fmterror == BULKSTAT_RV_NOTHING) {					if (error && error != ENOENT &&						error != EINVAL) {						ubleft = 0;						rval = error;						break;					}					lastino = ino;					continue;				}				if (fmterror == BULKSTAT_RV_GIVEUP) {					ubleft = 0;					ASSERT(error);					rval = error;					break;				}				if (ubufp)					ubufp += ubused;				ubleft -= ubused;				ubelem++;				lastino = ino;			}			cond_resched();		}		if (bp)			xfs_buf_relse(bp);		/*		 * Set up for the next loop iteration.		 */		if (XFS_BULKSTAT_UBLEFT(ubleft)) {			if (end_of_ag) {				agno++;				agino = 0;			} else				agino = XFS_INO_TO_AGINO(mp, lastino);		} else			break;	}	/*	 * Done, we're either out of filesystem or space to put the data.	 */	kmem_free(irbuf, irbsize);	*ubcountp = ubelem;	/*	 * Found some inodes, return them now and return the error next time.	 */	if (ubelem)		rval = 0;	if (agno >= mp->m_sb.sb_agcount) {		/*		 * If we ran out of filesystem, mark lastino as off		 * the end of the filesystem, so the next call		 * will return immediately.		 */		*lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0);		*done = 1;	} else		*lastinop = (xfs_ino_t)lastino;	return rval;}/* * Return stat information in bulk (by-inode) for the filesystem. * Special case for non-sequential one inode bulkstat. */int					/* error status */xfs_bulkstat_single(	xfs_mount_t		*mp,	/* mount point for filesystem */	xfs_ino_t		*lastinop, /* inode to return */	char			__user *buffer, /* buffer with inode stats */	int			*done)	/* 1 if there are more stats to get */{	int			count;	/* count value for bulkstat call */	int			error;	/* return value */	xfs_ino_t		ino;	/* filesystem inode number */	int			res;	/* result from bs1 */	/*	 * note that requesting valid inode numbers which are not allocated	 * to inodes will most likely cause xfs_itobp to generate warning	 * messages about bad magic numbers. This is ok. The fact that	 * the inode isn't actually an inode is handled by the	 * error check below. Done this way to make the usual case faster	 * at the expense of the error case.	 */	ino = (xfs_ino_t)*lastinop;	error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),				 NULL, 0, NULL, NULL, &res);	if (error) {		/*		 * Special case way failed, do it the "long" way		 * to see if that works.		 */		(*lastinop)--;		count = 1;		if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,				NULL, sizeof(xfs_bstat_t), buffer,				BULKSTAT_FG_IGET, done))			return error;		if (count == 0 || (xfs_ino_t)*lastinop != ino)			return error == EFSCORRUPTED ?				XFS_ERROR(EINVAL) : error;		else			return 0;	}	*done = 0;	return 0;}intxfs_inumbers_fmt(	void			__user *ubuffer, /* buffer to write to */	const xfs_inogrp_t	*buffer,	/* buffer to read from */	long			count,		/* # of elements to read */	long			*written)	/* # of bytes written */{	if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer)))		return -EFAULT;	*written = count * sizeof(*buffer);	return 0;}/* * Return inode number table for the filesystem. */int					/* error status */xfs_inumbers(	xfs_mount_t	*mp,		/* mount point for filesystem */	xfs_ino_t	*lastino,	/* last inode returned */	int		*count,		/* size of buffer/count returned */	void		__user *ubuffer,/* buffer with inode descriptions */	inumbers_fmt_pf	formatter){	xfs_buf_t	*agbp;	xfs_agino_t	agino;	xfs_agnumber_t	agno;	int		bcount;	xfs_inogrp_t	*buffer;	int		bufidx;	xfs_btree_cur_t	*cur;	int		error;	__int32_t	gcnt;	xfs_inofree_t	gfree;	xfs_agino_t	gino;	int		i;	xfs_ino_t	ino;	int		left;	int		tmp;	ino = (xfs_ino_t)*lastino;	agno = XFS_INO_TO_AGNO(mp, ino);	agino = XFS_INO_TO_AGINO(mp, ino);	left = *count;	*count = 0;	bcount = MIN(left, (int)(NBPP / sizeof(*buffer)));	buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);	error = bufidx = 0;	cur = NULL;	agbp = NULL;	while (left > 0 && agno < mp->m_sb.sb_agcount) {		if (agbp == NULL) {			down_read(&mp->m_peraglock);			error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);			up_read(&mp->m_peraglock);			if (error) {				/*				 * If we can't read the AGI of this ag,				 * then just skip to the next one.				 */				ASSERT(cur == NULL);				agbp = NULL;				agno++;				agino = 0;				continue;			}			cur = xfs_btree_init_cursor(mp, NULL, agbp, agno,				XFS_BTNUM_INO, (xfs_inode_t *)0, 0);			error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp);			if (error) {				xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);				cur = NULL;				xfs_buf_relse(agbp);				agbp = NULL;				/*				 * Move up the last inode in the current				 * chunk.  The lookup_ge will always get				 * us the first inode in the next chunk.				 */				agino += XFS_INODES_PER_CHUNK - 1;				continue;			}		}		if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree,			&i)) ||		    i == 0) {			xfs_buf_relse(agbp);			agbp = NULL;			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);			cur = NULL;			agno++;			agino = 0;			continue;		}		agino = gino + XFS_INODES_PER_CHUNK - 1;		buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, gino);		buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - gcnt;		buffer[bufidx].xi_allocmask = ~gfree;		bufidx++;		left--;		if (bufidx == bcount) {			long written;			if (formatter(ubuffer, buffer, bufidx, &written)) {				error = XFS_ERROR(EFAULT);				break;			}			ubuffer += written;			*count += bufidx;			bufidx = 0;		}		if (left) {			error = xfs_inobt_increment(cur, 0, &tmp);			if (error) {				xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);				cur = NULL;				xfs_buf_relse(agbp);				agbp = NULL;				/*				 * The agino value has already been bumped.				 * Just try to skip up to it.				 */				agino += XFS_INODES_PER_CHUNK;				continue;			}		}	}	if (!error) {		if (bufidx) {			long written;			if (formatter(ubuffer, buffer, bufidx, &written))				error = XFS_ERROR(EFAULT);			else				*count += bufidx;		}		*lastino = XFS_AGINO_TO_INO(mp, agno, agino);	}	kmem_free(buffer, bcount * sizeof(*buffer));	if (cur)		xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR :					   XFS_BTREE_NOERROR));	if (agbp)		xfs_buf_relse(agbp);	return error;}

⌨️ 快捷键说明

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