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

📄 xfs_dir2_leaf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			 */			curdb = xfs_dir2_da_to_db(mp, map->br_startoff);			error = xfs_da_read_buf(NULL, dp, map->br_startoff,				map->br_blockcount >= mp->m_dirblkfsbs ?				    XFS_FSB_TO_DADDR(mp, map->br_startblock) :				    -1,				&bp, XFS_DATA_FORK);			/*			 * Should just skip over the data block instead			 * of giving up.			 */			if (error)				break;	/* XXX */			/*			 * Adjust the current amount of read-ahead: we just			 * read a block that was previously ra.			 */			if (ra_current)				ra_current -= mp->m_dirblkfsbs;			/*			 * Do we need more readahead?			 */			for (ra_index = ra_offset = i = 0;			     ra_want > ra_current && i < map_blocks;			     i += mp->m_dirblkfsbs) {				ASSERT(ra_index < map_valid);				/*				 * Read-ahead a contiguous directory block.				 */				if (i > ra_current &&				    map[ra_index].br_blockcount >=				    mp->m_dirblkfsbs) {					xfs_baread(mp->m_ddev_targp,						XFS_FSB_TO_DADDR(mp,						   map[ra_index].br_startblock +						   ra_offset),						(int)BTOBB(mp->m_dirblksize));					ra_current = i;				}				/*				 * Read-ahead a non-contiguous directory block.				 * This doesn't use our mapping, but this				 * is a very rare case.				 */				else if (i > ra_current) {					(void)xfs_da_reada_buf(NULL, dp,						map[ra_index].br_startoff +						ra_offset, XFS_DATA_FORK);					ra_current = i;				}				/*				 * Advance offset through the mapping table.				 */				for (j = 0; j < mp->m_dirblkfsbs; j++) {					/*					 * The rest of this extent but not					 * more than a dir block.					 */					length = MIN(mp->m_dirblkfsbs,						(int)(map[ra_index].br_blockcount -						ra_offset));					j += length;					ra_offset += length;					/*					 * Advance to the next mapping if					 * this one is used up.					 */					if (ra_offset ==					    map[ra_index].br_blockcount) {						ra_offset = 0;						ra_index++;					}				}			}			/*			 * Having done a read, we need to set a new offset.			 */			newoff = xfs_dir2_db_off_to_byte(mp, curdb, 0);			/*			 * Start of the current block.			 */			if (curoff < newoff)				curoff = newoff;			/*			 * Make sure we're in the right block.			 */			else if (curoff > newoff)				ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==				       curdb);			data = bp->data;			xfs_dir2_data_check(dp, bp);			/*			 * Find our position in the block.			 */			ptr = (char *)&data->u;			byteoff = xfs_dir2_byte_to_off(mp, curoff);			/*			 * Skip past the header.			 */			if (byteoff == 0)				curoff += (uint)sizeof(data->hdr);			/*			 * Skip past entries until we reach our offset.			 */			else {				while ((char *)ptr - (char *)data < byteoff) {					dup = (xfs_dir2_data_unused_t *)ptr;					if (be16_to_cpu(dup->freetag)						  == XFS_DIR2_DATA_FREE_TAG) {						length = be16_to_cpu(dup->length);						ptr += length;						continue;					}					dep = (xfs_dir2_data_entry_t *)ptr;					length =					   xfs_dir2_data_entsize(dep->namelen);					ptr += length;				}				/*				 * Now set our real offset.				 */				curoff =					xfs_dir2_db_off_to_byte(mp,					    xfs_dir2_byte_to_db(mp, curoff),					    (char *)ptr - (char *)data);				if (ptr >= (char *)data + mp->m_dirblksize) {					continue;				}			}		}		/*		 * We have a pointer to an entry.		 * Is it a live one?		 */		dup = (xfs_dir2_data_unused_t *)ptr;		/*		 * No, it's unused, skip over it.		 */		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {			length = be16_to_cpu(dup->length);			ptr += length;			curoff += length;			continue;		}		/*		 * Copy the entry into the putargs, and try formatting it.		 */		dep = (xfs_dir2_data_entry_t *)ptr;		length = xfs_dir2_data_entsize(dep->namelen);		ino = be64_to_cpu(dep->inumber);#if XFS_BIG_INUMS		ino += mp->m_inoadd;#endif		/*		 * Won't fit.  Return to caller.		 */		if (filldir(dirent, dep->name, dep->namelen,			    xfs_dir2_byte_to_dataptr(mp, curoff),			    ino, DT_UNKNOWN))			break;		/*		 * Advance to next entry in the block.		 */		ptr += length;		curoff += length;		bufsize -= length;	}	/*	 * All done.  Set output offset value to current offset.	 */	if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))		*offset = XFS_DIR2_MAX_DATAPTR;	else		*offset = xfs_dir2_byte_to_dataptr(mp, curoff);	kmem_free(map, map_size * sizeof(*map));	if (bp)		xfs_da_brelse(NULL, bp);	return error;}/* * Initialize a new leaf block, leaf1 or leafn magic accepted. */intxfs_dir2_leaf_init(	xfs_da_args_t		*args,		/* operation arguments */	xfs_dir2_db_t		bno,		/* directory block number */	xfs_dabuf_t		**bpp,		/* out: leaf buffer */	int			magic)		/* magic number for block */{	xfs_dabuf_t		*bp;		/* leaf buffer */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return code */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */	xfs_mount_t		*mp;		/* filesystem mount point */	xfs_trans_t		*tp;		/* transaction pointer */	dp = args->dp;	ASSERT(dp != NULL);	tp = args->trans;	mp = dp->i_mount;	ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) &&	       bno < XFS_DIR2_FREE_FIRSTDB(mp));	/*	 * Get the buffer for the block.	 */	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,		XFS_DATA_FORK);	if (error) {		return error;	}	ASSERT(bp != NULL);	leaf = bp->data;	/*	 * Initialize the header.	 */	leaf->hdr.info.magic = cpu_to_be16(magic);	leaf->hdr.info.forw = 0;	leaf->hdr.info.back = 0;	leaf->hdr.count = 0;	leaf->hdr.stale = 0;	xfs_dir2_leaf_log_header(tp, bp);	/*	 * If it's a leaf-format directory initialize the tail.	 * In this case our caller has the real bests table to copy into	 * the block.	 */	if (magic == XFS_DIR2_LEAF1_MAGIC) {		ltp = xfs_dir2_leaf_tail_p(mp, leaf);		ltp->bestcount = 0;		xfs_dir2_leaf_log_tail(tp, bp);	}	*bpp = bp;	return 0;}/* * Log the bests entries indicated from a leaf1 block. */static voidxfs_dir2_leaf_log_bests(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp,		/* leaf buffer */	int			first,		/* first entry to log */	int			last)		/* last entry to log */{	__be16			*firstb;	/* pointer to first entry */	__be16			*lastb;		/* pointer to last entry */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);	ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf);	firstb = xfs_dir2_leaf_bests_p(ltp) + first;	lastb = xfs_dir2_leaf_bests_p(ltp) + last;	xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),		(uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));}/* * Log the leaf entries indicated from a leaf1 or leafn block. */voidxfs_dir2_leaf_log_ents(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp,		/* leaf buffer */	int			first,		/* first entry to log */	int			last)		/* last entry to log */{	xfs_dir2_leaf_entry_t	*firstlep;	/* pointer to first entry */	xfs_dir2_leaf_entry_t	*lastlep;	/* pointer to last entry */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||	       be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);	firstlep = &leaf->ents[first];	lastlep = &leaf->ents[last];	xfs_da_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf),		(uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1));}/* * Log the header of the leaf1 or leafn block. */voidxfs_dir2_leaf_log_header(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp)		/* leaf buffer */{	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||	       be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);	xfs_da_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf),		(uint)(sizeof(leaf->hdr) - 1));}/* * Log the tail of the leaf1 block. */STATIC voidxfs_dir2_leaf_log_tail(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp)		/* leaf buffer */{	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */	xfs_mount_t		*mp;		/* filesystem mount point */	mp = tp->t_mountp;	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);	ltp = xfs_dir2_leaf_tail_p(mp, leaf);	xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),		(uint)(mp->m_dirblksize - 1));}/* * Look up the entry referred to by args in the leaf format directory. * Most of the work is done by the xfs_dir2_leaf_lookup_int routine which * is also used by the node-format code. */intxfs_dir2_leaf_lookup(	xfs_da_args_t		*args)		/* operation arguments */{	xfs_dabuf_t		*dbp;		/* data block buffer */	xfs_dir2_data_entry_t	*dep;		/* data block entry */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return code */	int			index;		/* found entry index */	xfs_dabuf_t		*lbp;		/* leaf buffer */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */	xfs_trans_t		*tp;		/* transaction pointer */	xfs_dir2_trace_args("leaf_lookup", args);	/*	 * Look up name in the leaf block, returning both buffers and index.	 */	if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) {		return error;	}	tp = args->trans;	dp = args->dp;	xfs_dir2_leaf_check(dp, lbp);	leaf = lbp->data;	/*	 * Get to the leaf entry and contained data entry address.	 */	lep = &leaf->ents[index];	/*	 * Point to the data entry.	 */	dep = (xfs_dir2_data_entry_t *)	      ((char *)dbp->data +	       xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));	/*	 * Return the found inode number.	 */	args->inumber = be64_to_cpu(dep->inumber);	xfs_da_brelse(tp, dbp);	xfs_da_brelse(tp, lbp);	return XFS_ERROR(EEXIST);}/* * Look up name/hash in the leaf block. * Fill in indexp with the found index, and dbpp with the data buffer. * If not found dbpp will be NULL, and ENOENT comes back. * lbpp will always be filled in with the leaf buffer unless there's an error. */static int					/* error */xfs_dir2_leaf_lookup_int(	xfs_da_args_t		*args,		/* operation arguments */	xfs_dabuf_t		**lbpp,		/* out: leaf buffer */	int			*indexp,	/* out: index in leaf block */	xfs_dabuf_t		**dbpp)		/* out: data buffer */{	xfs_dir2_db_t		curdb;		/* current data block number */	xfs_dabuf_t		*dbp;		/* data buffer */	xfs_dir2_data_entry_t	*dep;		/* data entry */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return code */	int			index;		/* index in leaf block */	xfs_dabuf_t		*lbp;		/* leaf buffer */	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_mount_t		*mp;		/* filesystem mount point */	xfs_dir2_db_t		newdb;		/* new data block number */	xfs_trans_t		*tp;		/* transaction pointer */	dp = args->dp;	tp = args->trans;	mp = dp->i_mount;	/*	 * Read the leaf block into the buffer.	 */	if ((error =	    xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,		    XFS_DATA_FORK))) {		return error;	}	*lbpp = lbp;	leaf = lbp->data;	xfs_dir2_leaf_check(dp, lbp);	/*	 * Look for the first leaf entry with our hash value.	 */	index = xfs_dir2_leaf_search_hash(args, lbp);	/*	 * Loop over all the entries with the right hash value	 * looking to match the name.	 */	for (lep = &leaf->ents[index], dbp = NULL, curdb = -1;	     index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval;	     lep++, index++) {		/*		 * Skip over stale leaf entries.		 */		if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)			continue;		/*		 * Get the new data block number.		 */		newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));		/*		 * If it's not the same as the old data block number,		 * need to pitch the old one and read the new one.		 */		if (newdb != curdb) {			if (dbp)				xfs_da_brelse(tp, dbp);			if ((error =			    xfs_da_read_buf(tp, dp,				    xfs_dir2_db_to_da(mp, newdb), -1, &dbp,				    XFS_DATA_FORK))) {				xfs_da_brelse(tp, lbp);				return error;			}			xfs_dir2_data_check(dp, dbp);			curdb = newdb;		}		/*		 * Point to the data entry.		 */		dep = (xfs_dir2_data_entry_t *)		      ((char *)dbp->data +		       xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));		/*		 * If it matches then return it.		 */		if (dep->namelen == args->namelen &&

⌨️ 快捷键说明

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