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

📄 xfs_dir2_leaf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			for (lowstale = index - 1;			     lowstale >= 0 &&				be32_to_cpu(leaf->ents[lowstale].address) !=				XFS_DIR2_NULL_DATAPTR;			     lowstale--)				continue;			/*			 * Find the next stale entry at or after the insertion			 * point, if any.   Stop if we go so far that the			 * lowstale entry would be better.			 */			for (highstale = index;			     highstale < be16_to_cpu(leaf->hdr.count) &&				be32_to_cpu(leaf->ents[highstale].address) !=				XFS_DIR2_NULL_DATAPTR &&				(lowstale < 0 ||				 index - lowstale - 1 >= highstale - index);			     highstale++)				continue;		}		/*		 * If the low one is better, use it.		 */		if (lowstale >= 0 &&		    (highstale == be16_to_cpu(leaf->hdr.count) ||		     index - lowstale - 1 < highstale - index)) {			ASSERT(index - lowstale - 1 >= 0);			ASSERT(be32_to_cpu(leaf->ents[lowstale].address) ==			       XFS_DIR2_NULL_DATAPTR);			/*			 * Copy entries up to cover the stale entry			 * and make room for the new entry.			 */			if (index - lowstale - 1 > 0)				memmove(&leaf->ents[lowstale],					&leaf->ents[lowstale + 1],					(index - lowstale - 1) * sizeof(*lep));			lep = &leaf->ents[index - 1];			lfloglow = MIN(lowstale, lfloglow);			lfloghigh = MAX(index - 1, lfloghigh);		}		/*		 * The high one is better, so use that one.		 */		else {			ASSERT(highstale - index >= 0);			ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==			       XFS_DIR2_NULL_DATAPTR);			/*			 * Copy entries down to cover the stale entry			 * and make room for the new entry.			 */			if (highstale - index > 0)				memmove(&leaf->ents[index + 1],					&leaf->ents[index],					(highstale - index) * sizeof(*lep));			lep = &leaf->ents[index];			lfloglow = MIN(index, lfloglow);			lfloghigh = MAX(highstale, lfloghigh);		}		be16_add(&leaf->hdr.stale, -1);	}	/*	 * Fill in the new leaf entry.	 */	lep->hashval = cpu_to_be32(args->hashval);	lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, use_block,				be16_to_cpu(*tagp)));	/*	 * Log the leaf fields and give up the buffers.	 */	xfs_dir2_leaf_log_header(tp, lbp);	xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh);	xfs_dir2_leaf_check(dp, lbp);	xfs_da_buf_done(lbp);	xfs_dir2_data_check(dp, dbp);	xfs_da_buf_done(dbp);	return 0;}#ifdef DEBUG/* * Check the internal consistency of a leaf1 block. * Pop an assert if something is wrong. */voidxfs_dir2_leaf_check(	xfs_inode_t		*dp,		/* incore directory inode */	xfs_dabuf_t		*bp)		/* leaf's buffer */{	int			i;		/* leaf index */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail pointer */	xfs_mount_t		*mp;		/* filesystem mount point */	int			stale;		/* count of stale leaves */	leaf = bp->data;	mp = dp->i_mount;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);	/*	 * This value is not restrictive enough.	 * Should factor in the size of the bests table as well.	 * We can deduce a value for that from di_size.	 */	ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));	ltp = xfs_dir2_leaf_tail_p(mp, leaf);	/*	 * Leaves and bests don't overlap.	 */	ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <=	       (char *)xfs_dir2_leaf_bests_p(ltp));	/*	 * Check hash value order, count stale entries.	 */	for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {		if (i + 1 < be16_to_cpu(leaf->hdr.count))			ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=			       be32_to_cpu(leaf->ents[i + 1].hashval));		if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR)			stale++;	}	ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);}#endif	/* DEBUG *//* * Compact out any stale entries in the leaf. * Log the header and changed leaf entries, if any. */voidxfs_dir2_leaf_compact(	xfs_da_args_t	*args,		/* operation arguments */	xfs_dabuf_t	*bp)		/* leaf buffer */{	int		from;		/* source leaf index */	xfs_dir2_leaf_t	*leaf;		/* leaf structure */	int		loglow;		/* first leaf entry to log */	int		to;		/* target leaf index */	leaf = bp->data;	if (!leaf->hdr.stale) {		return;	}	/*	 * Compress out the stale entries in place.	 */	for (from = to = 0, loglow = -1; from < be16_to_cpu(leaf->hdr.count); from++) {		if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)			continue;		/*		 * Only actually copy the entries that are different.		 */		if (from > to) {			if (loglow == -1)				loglow = to;			leaf->ents[to] = leaf->ents[from];		}		to++;	}	/*	 * Update and log the header, log the leaf entries.	 */	ASSERT(be16_to_cpu(leaf->hdr.stale) == from - to);	be16_add(&leaf->hdr.count, -(be16_to_cpu(leaf->hdr.stale)));	leaf->hdr.stale = 0;	xfs_dir2_leaf_log_header(args->trans, bp);	if (loglow != -1)		xfs_dir2_leaf_log_ents(args->trans, bp, loglow, to - 1);}/* * Compact the leaf entries, removing stale ones. * Leave one stale entry behind - the one closest to our * insertion index - and the caller will shift that one to our insertion * point later. * Return new insertion index, where the remaining stale entry is, * and leaf logging indices. */voidxfs_dir2_leaf_compact_x1(	xfs_dabuf_t	*bp,		/* leaf buffer */	int		*indexp,	/* insertion index */	int		*lowstalep,	/* out: stale entry before us */	int		*highstalep,	/* out: stale entry after us */	int		*lowlogp,	/* out: low log index */	int		*highlogp)	/* out: high log index */{	int		from;		/* source copy index */	int		highstale;	/* stale entry at/after index */	int		index;		/* insertion index */	int		keepstale;	/* source index of kept stale */	xfs_dir2_leaf_t	*leaf;		/* leaf structure */	int		lowstale;	/* stale entry before index */	int		newindex=0;	/* new insertion index */	int		to;		/* destination copy index */	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.stale) > 1);	index = *indexp;	/*	 * Find the first stale entry before our index, if any.	 */	for (lowstale = index - 1;	     lowstale >= 0 &&		be32_to_cpu(leaf->ents[lowstale].address) != XFS_DIR2_NULL_DATAPTR;	     lowstale--)		continue;	/*	 * Find the first stale entry at or after our index, if any.	 * Stop if the answer would be worse than lowstale.	 */	for (highstale = index;	     highstale < be16_to_cpu(leaf->hdr.count) &&		be32_to_cpu(leaf->ents[highstale].address) != XFS_DIR2_NULL_DATAPTR &&		(lowstale < 0 || index - lowstale > highstale - index);	     highstale++)		continue;	/*	 * Pick the better of lowstale and highstale.	 */	if (lowstale >= 0 &&	    (highstale == be16_to_cpu(leaf->hdr.count) ||	     index - lowstale <= highstale - index))		keepstale = lowstale;	else		keepstale = highstale;	/*	 * Copy the entries in place, removing all the stale entries	 * except keepstale.	 */	for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {		/*		 * Notice the new value of index.		 */		if (index == from)			newindex = to;		if (from != keepstale &&		    be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR) {			if (from == to)				*lowlogp = to;			continue;		}		/*		 * Record the new keepstale value for the insertion.		 */		if (from == keepstale)			lowstale = highstale = to;		/*		 * Copy only the entries that have moved.		 */		if (from > to)			leaf->ents[to] = leaf->ents[from];		to++;	}	ASSERT(from > to);	/*	 * If the insertion point was past the last entry,	 * set the new insertion point accordingly.	 */	if (index == from)		newindex = to;	*indexp = newindex;	/*	 * Adjust the leaf header values.	 */	be16_add(&leaf->hdr.count, -(from - to));	leaf->hdr.stale = cpu_to_be16(1);	/*	 * Remember the low/high stale value only in the "right"	 * direction.	 */	if (lowstale >= newindex)		lowstale = -1;	else		highstale = be16_to_cpu(leaf->hdr.count);	*highlogp = be16_to_cpu(leaf->hdr.count) - 1;	*lowstalep = lowstale;	*highstalep = highstale;}/* * Getdents (readdir) for leaf and node directories. * This reads the data blocks only, so is the same for both forms. */int						/* error */xfs_dir2_leaf_getdents(	xfs_inode_t		*dp,		/* incore directory inode */	void			*dirent,	size_t			bufsize,	xfs_off_t		*offset,	filldir_t		filldir){	xfs_dabuf_t		*bp;		/* data block buffer */	int			byteoff;	/* offset in current block */	xfs_dir2_db_t		curdb;		/* db for current block */	xfs_dir2_off_t		curoff;		/* current overall offset */	xfs_dir2_data_t		*data;		/* data block structure */	xfs_dir2_data_entry_t	*dep;		/* data entry */	xfs_dir2_data_unused_t	*dup;		/* unused entry */	int			error = 0;	/* error return value */	int			i;		/* temporary loop index */	int			j;		/* temporary loop index */	int			length;		/* temporary length value */	xfs_bmbt_irec_t		*map;		/* map vector for blocks */	xfs_extlen_t		map_blocks;	/* number of fsbs in map */	xfs_dablk_t		map_off;	/* last mapped file offset */	int			map_size;	/* total entries in *map */	int			map_valid;	/* valid entries in *map */	xfs_mount_t		*mp;		/* filesystem mount point */	xfs_dir2_off_t		newoff;		/* new curoff after new blk */	int			nmap;		/* mappings to ask xfs_bmapi */	char			*ptr = NULL;	/* pointer to current data */	int			ra_current;	/* number of read-ahead blks */	int			ra_index;	/* *map index for read-ahead */	int			ra_offset;	/* map entry offset for ra */	int			ra_want;	/* readahead count wanted */	xfs_ino_t		ino;	/*	 * If the offset is at or past the largest allowed value,	 * give up right away.	 */	if (*offset >= XFS_DIR2_MAX_DATAPTR)		return 0;	mp = dp->i_mount;	/*	 * Set up to bmap a number of blocks based on the caller's	 * buffer size, the directory block size, and the filesystem	 * block size.	 */	map_size = howmany(bufsize + mp->m_dirblksize, mp->m_sb.sb_blocksize);	map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP);	map_valid = ra_index = ra_offset = ra_current = map_blocks = 0;	bp = NULL;	/*	 * Inside the loop we keep the main offset value as a byte offset	 * in the directory file.	 */	curoff = xfs_dir2_dataptr_to_byte(mp, *offset);	/*	 * Force this conversion through db so we truncate the offset	 * down to get the start of the data block.	 */	map_off = xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, curoff));	/*	 * Loop over directory entries until we reach the end offset.	 * Get more blocks and readahead as necessary.	 */	while (curoff < XFS_DIR2_LEAF_OFFSET) {		/*		 * If we have no buffer, or we're off the end of the		 * current buffer, need to get another one.		 */		if (!bp || ptr >= (char *)bp->data + mp->m_dirblksize) {			/*			 * If we have a buffer, we need to release it and			 * take it out of the mapping.			 */			if (bp) {				xfs_da_brelse(NULL, bp);				bp = NULL;				map_blocks -= mp->m_dirblkfsbs;				/*				 * Loop to get rid of the extents for the				 * directory block.				 */				for (i = mp->m_dirblkfsbs; i > 0; ) {					j = MIN((int)map->br_blockcount, i);					map->br_blockcount -= j;					map->br_startblock += j;					map->br_startoff += j;					/*					 * If mapping is done, pitch it from					 * the table.					 */					if (!map->br_blockcount && --map_valid)						memmove(&map[0], &map[1],							sizeof(map[0]) *							map_valid);					i -= j;				}			}			/*			 * Recalculate the readahead blocks wanted.			 */			ra_want = howmany(bufsize + mp->m_dirblksize,					  mp->m_sb.sb_blocksize) - 1;			/*			 * If we don't have as many as we want, and we haven't			 * run out of data blocks, get some more mappings.			 */			if (1 + ra_want > map_blocks &&			    map_off <			    xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) {				/*				 * Get more bmaps, fill in after the ones				 * we already have in the table.				 */				nmap = map_size - map_valid;				error = xfs_bmapi(NULL, dp,					map_off,					xfs_dir2_byte_to_da(mp,						XFS_DIR2_LEAF_OFFSET) - map_off,					XFS_BMAPI_METADATA, NULL, 0,					&map[map_valid], &nmap, NULL, NULL);				/*				 * Don't know if we should ignore this or				 * try to return an error.				 * The trouble with returning errors				 * is that readdir will just stop without				 * actually passing the error through.				 */				if (error)					break;	/* XXX */				/*				 * If we got all the mappings we asked for,				 * set the final map offset based on the				 * last bmap value received.				 * Otherwise, we've reached the end.				 */				if (nmap == map_size - map_valid)					map_off =					map[map_valid + nmap - 1].br_startoff +					map[map_valid + nmap - 1].br_blockcount;				else					map_off =						xfs_dir2_byte_to_da(mp,							XFS_DIR2_LEAF_OFFSET);				/*				 * Look for holes in the mapping, and				 * eliminate them.  Count up the valid blocks.				 */				for (i = map_valid; i < map_valid + nmap; ) {					if (map[i].br_startblock ==					    HOLESTARTBLOCK) {						nmap--;						length = map_valid + nmap - i;						if (length)							memmove(&map[i],								&map[i + 1],								sizeof(map[i]) *								length);					} else {						map_blocks +=							map[i].br_blockcount;						i++;					}				}				map_valid += nmap;			}			/*			 * No valid mappings, so no more data blocks.			 */			if (!map_valid) {				curoff = xfs_dir2_da_to_byte(mp, map_off);				break;			}			/*			 * Read the directory block starting at the first			 * mapping.

⌨️ 快捷键说明

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