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

📄 xfs_dir2.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	int		v;		/* type-checking value */	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))		return rval;	args.name = name;	args.namelen = namelen;	args.hashval = xfs_da_hashname(name, namelen);	args.inumber = inum;	args.dp = dp;	args.firstblock = first;	args.flist = flist;	args.total = total;	args.whichfork = XFS_DATA_FORK;	args.trans = tp;	args.justcheck = args.addname = args.oknoent = 0;	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)		rval = xfs_dir2_sf_replace(&args);	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))		return rval;	else if (v)		rval = xfs_dir2_block_replace(&args);	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))		return rval;	else if (v)		rval = xfs_dir2_leaf_replace(&args);	else		rval = xfs_dir2_node_replace(&args);	return rval;}/* * See if this entry can be added to the directory without allocating space. */intxfs_dir_canenter(	xfs_trans_t	*tp,	xfs_inode_t	*dp,	char		*name,		/* name of entry to add */	int		namelen){	xfs_da_args_t	args;	int		rval;	int		v;		/* type-checking value */	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);	args.name = name;	args.namelen = namelen;	args.hashval = xfs_da_hashname(name, namelen);	args.inumber = 0;	args.dp = dp;	args.firstblock = NULL;	args.flist = NULL;	args.total = 0;	args.whichfork = XFS_DATA_FORK;	args.trans = tp;	args.justcheck = args.addname = args.oknoent = 1;	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)		rval = xfs_dir2_sf_addname(&args);	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))		return rval;	else if (v)		rval = xfs_dir2_block_addname(&args);	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))		return rval;	else if (v)		rval = xfs_dir2_leaf_addname(&args);	else		rval = xfs_dir2_node_addname(&args);	return rval;}/* * Utility routines. *//* * Add a block to the directory. * This routine is for data and free blocks, not leaf/node blocks * which are handled by xfs_da_grow_inode. */intxfs_dir2_grow_inode(	xfs_da_args_t	*args,	int		space,		/* v2 dir's space XFS_DIR2_xxx_SPACE */	xfs_dir2_db_t	*dbp)		/* out: block number added */{	xfs_fileoff_t	bno;		/* directory offset of new block */	int		count;		/* count of filesystem blocks */	xfs_inode_t	*dp;		/* incore directory inode */	int		error;	int		got;		/* blocks actually mapped */	int		i;	xfs_bmbt_irec_t	map;		/* single structure for bmap */	int		mapi;		/* mapping index */	xfs_bmbt_irec_t	*mapp;		/* bmap mapping structure(s) */	xfs_mount_t	*mp;	int		nmap;		/* number of bmap entries */	xfs_trans_t	*tp;	xfs_dir2_trace_args_s("grow_inode", args, space);	dp = args->dp;	tp = args->trans;	mp = dp->i_mount;	/*	 * Set lowest possible block in the space requested.	 */	bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);	count = mp->m_dirblkfsbs;	/*	 * Find the first hole for our block.	 */	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))		return error;	nmap = 1;	ASSERT(args->firstblock != NULL);	/*	 * Try mapping the new block contiguously (one extent).	 */	if ((error = xfs_bmapi(tp, dp, bno, count,			XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,			args->firstblock, args->total, &map, &nmap,			args->flist, NULL)))		return error;	ASSERT(nmap <= 1);	if (nmap == 1) {		mapp = &map;		mapi = 1;	}	/*	 * Didn't work and this is a multiple-fsb directory block.	 * Try again with contiguous flag turned on.	 */	else if (nmap == 0 && count > 1) {		xfs_fileoff_t	b;	/* current file offset */		/*		 * Space for maximum number of mappings.		 */		mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);		/*		 * Iterate until we get to the end of our block.		 */		for (b = bno, mapi = 0; b < bno + count; ) {			int	c;	/* current fsb count */			/*			 * Can't map more than MAX_NMAP at once.			 */			nmap = MIN(XFS_BMAP_MAX_NMAP, count);			c = (int)(bno + count - b);			if ((error = xfs_bmapi(tp, dp, b, c,					XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,					args->firstblock, args->total,					&mapp[mapi], &nmap, args->flist,					NULL))) {				kmem_free(mapp, sizeof(*mapp) * count);				return error;			}			if (nmap < 1)				break;			/*			 * Add this bunch into our table, go to the next offset.			 */			mapi += nmap;			b = mapp[mapi - 1].br_startoff +			    mapp[mapi - 1].br_blockcount;		}	}	/*	 * Didn't work.	 */	else {		mapi = 0;		mapp = NULL;	}	/*	 * See how many fsb's we got.	 */	for (i = 0, got = 0; i < mapi; i++)		got += mapp[i].br_blockcount;	/*	 * Didn't get enough fsb's, or the first/last block's are wrong.	 */	if (got != count || mapp[0].br_startoff != bno ||	    mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=	    bno + count) {		if (mapp != &map)			kmem_free(mapp, sizeof(*mapp) * count);		return XFS_ERROR(ENOSPC);	}	/*	 * Done with the temporary mapping table.	 */	if (mapp != &map)		kmem_free(mapp, sizeof(*mapp) * count);	*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);	/*	 * Update file's size if this is the data space and it grew.	 */	if (space == XFS_DIR2_DATA_SPACE) {		xfs_fsize_t	size;		/* directory file (data) size */		size = XFS_FSB_TO_B(mp, bno + count);		if (size > dp->i_d.di_size) {			dp->i_d.di_size = size;			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);		}	}	return 0;}/* * See if the directory is a single-block form directory. */intxfs_dir2_isblock(	xfs_trans_t	*tp,	xfs_inode_t	*dp,	int		*vp)		/* out: 1 is block, 0 is not block */{	xfs_fileoff_t	last;		/* last file offset */	xfs_mount_t	*mp;	int		rval;	mp = dp->i_mount;	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))		return rval;	rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;	ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);	*vp = rval;	return 0;}/* * See if the directory is a single-leaf form directory. */intxfs_dir2_isleaf(	xfs_trans_t	*tp,	xfs_inode_t	*dp,	int		*vp)		/* out: 1 is leaf, 0 is not leaf */{	xfs_fileoff_t	last;		/* last file offset */	xfs_mount_t	*mp;	int		rval;	mp = dp->i_mount;	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))		return rval;	*vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);	return 0;}/* * Remove the given block from the directory. * This routine is used for data and free blocks, leaf/node are done * by xfs_da_shrink_inode. */intxfs_dir2_shrink_inode(	xfs_da_args_t	*args,	xfs_dir2_db_t	db,	xfs_dabuf_t	*bp){	xfs_fileoff_t	bno;		/* directory file offset */	xfs_dablk_t	da;		/* directory file offset */	int		done;		/* bunmap is finished */	xfs_inode_t	*dp;	int		error;	xfs_mount_t	*mp;	xfs_trans_t	*tp;	xfs_dir2_trace_args_db("shrink_inode", args, db, bp);	dp = args->dp;	mp = dp->i_mount;	tp = args->trans;	da = xfs_dir2_db_to_da(mp, db);	/*	 * Unmap the fsblock(s).	 */	if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,			XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,			NULL, &done))) {		/*		 * ENOSPC actually can happen if we're in a removename with		 * no space reservation, and the resulting block removal		 * would cause a bmap btree split or conversion from extents		 * to btree.  This can only happen for un-fragmented		 * directory blocks, since you need to be punching out		 * the middle of an extent.		 * In this case we need to leave the block in the file,		 * and not binval it.		 * So the block has to be in a consistent empty state		 * and appropriately logged.		 * We don't free up the buffer, the caller can tell it		 * hasn't happened since it got an error back.		 */		return error;	}	ASSERT(done);	/*	 * Invalidate the buffer from the transaction.	 */	xfs_da_binval(tp, bp);	/*	 * If it's not a data block, we're done.	 */	if (db >= XFS_DIR2_LEAF_FIRSTDB(mp))		return 0;	/*	 * If the block isn't the last one in the directory, we're done.	 */	if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0))		return 0;	bno = da;	if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {		/*		 * This can't really happen unless there's kernel corruption.		 */		return error;	}	if (db == mp->m_dirdatablk)		ASSERT(bno == 0);	else		ASSERT(bno > 0);	/*	 * Set the size to the new last block.	 */	dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);	return 0;}

⌨️ 快捷键说明

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