diff options
Diffstat (limited to 'fs/xfs/xfs_dir2.c')
| -rw-r--r-- | fs/xfs/xfs_dir2.c | 136 | 
1 files changed, 86 insertions, 50 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index fda46253966a..79670cda48ae 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -85,38 +85,74 @@ static struct xfs_nameops xfs_ascii_ci_nameops = {  	.compname	= xfs_ascii_ci_compname,  }; -void -xfs_dir_mount( -	xfs_mount_t	*mp) +int +xfs_da_mount( +	struct xfs_mount	*mp)  { -	int	nodehdr_size; +	struct xfs_da_geometry	*dageo; +	int			nodehdr_size; -	ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); +	ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);  	ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=  	       XFS_MAX_BLOCKSIZE);  	mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);  	mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); -	mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); -	mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog; -	mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); -	mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); -	mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); -  	nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; -	mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / +	mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), +				    KM_SLEEP | KM_MAYFAIL); +	mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), +				     KM_SLEEP | KM_MAYFAIL); +	if (!mp->m_dir_geo || !mp->m_attr_geo) { +		kmem_free(mp->m_dir_geo); +		kmem_free(mp->m_attr_geo); +		return ENOMEM; +	} + +	/* set up directory geometry */ +	dageo = mp->m_dir_geo; +	dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog; +	dageo->fsblog = mp->m_sb.sb_blocklog; +	dageo->blksize = 1 << dageo->blklog; +	dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog; + +	/* +	 * Now we've set up the block conversion variables, we can calculate the +	 * segment block constants using the geometry structure. +	 */ +	dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET); +	dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET); +	dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET); +	dageo->node_ents = (dageo->blksize - nodehdr_size) /  				(uint)sizeof(xfs_da_node_entry_t); -	mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / +	dageo->magicpct = (dageo->blksize * 37) / 100; + +	/* set up attribute geometry - single fsb only */ +	dageo = mp->m_attr_geo; +	dageo->blklog = mp->m_sb.sb_blocklog; +	dageo->fsblog = mp->m_sb.sb_blocklog; +	dageo->blksize = 1 << dageo->blklog; +	dageo->fsbcount = 1; +	dageo->node_ents = (dageo->blksize - nodehdr_size) /  				(uint)sizeof(xfs_da_node_entry_t); +	dageo->magicpct = (dageo->blksize * 37) / 100; -	mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;  	if (xfs_sb_version_hasasciici(&mp->m_sb))  		mp->m_dirnameops = &xfs_ascii_ci_nameops;  	else  		mp->m_dirnameops = &xfs_default_nameops; +	return 0; +} + +void +xfs_da_unmount( +	struct xfs_mount	*mp) +{ +	kmem_free(mp->m_dir_geo); +	kmem_free(mp->m_attr_geo);  }  /* @@ -192,6 +228,7 @@ xfs_dir_init(  	if (!args)  		return ENOMEM; +	args->geo = dp->i_mount->m_dir_geo;  	args->dp = dp;  	args->trans = tp;  	error = xfs_dir2_sf_create(args, pdp->i_ino); @@ -226,6 +263,7 @@ xfs_dir_createname(  	if (!args)  		return ENOMEM; +	args->geo = dp->i_mount->m_dir_geo;  	args->name = name->name;  	args->namelen = name->len;  	args->filetype = name->type; @@ -244,7 +282,7 @@ xfs_dir_createname(  		goto out_free;  	} -	rval = xfs_dir2_isblock(tp, dp, &v); +	rval = xfs_dir2_isblock(args, &v);  	if (rval)  		goto out_free;  	if (v) { @@ -252,7 +290,7 @@ xfs_dir_createname(  		goto out_free;  	} -	rval = xfs_dir2_isleaf(tp, dp, &v); +	rval = xfs_dir2_isleaf(args, &v);  	if (rval)  		goto out_free;  	if (v) @@ -320,6 +358,7 @@ xfs_dir_lookup(  	 * annotations into the reclaim path for the ilock.  	 */  	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); +	args->geo = dp->i_mount->m_dir_geo;  	args->name = name->name;  	args->namelen = name->len;  	args->filetype = name->type; @@ -336,7 +375,7 @@ xfs_dir_lookup(  		goto out_check_rval;  	} -	rval = xfs_dir2_isblock(tp, dp, &v); +	rval = xfs_dir2_isblock(args, &v);  	if (rval)  		goto out_free;  	if (v) { @@ -344,7 +383,7 @@ xfs_dir_lookup(  		goto out_check_rval;  	} -	rval = xfs_dir2_isleaf(tp, dp, &v); +	rval = xfs_dir2_isleaf(args, &v);  	if (rval)  		goto out_free;  	if (v) @@ -391,6 +430,7 @@ xfs_dir_removename(  	if (!args)  		return ENOMEM; +	args->geo = dp->i_mount->m_dir_geo;  	args->name = name->name;  	args->namelen = name->len;  	args->filetype = name->type; @@ -408,7 +448,7 @@ xfs_dir_removename(  		goto out_free;  	} -	rval = xfs_dir2_isblock(tp, dp, &v); +	rval = xfs_dir2_isblock(args, &v);  	if (rval)  		goto out_free;  	if (v) { @@ -416,7 +456,7 @@ xfs_dir_removename(  		goto out_free;  	} -	rval = xfs_dir2_isleaf(tp, dp, &v); +	rval = xfs_dir2_isleaf(args, &v);  	if (rval)  		goto out_free;  	if (v) @@ -455,6 +495,7 @@ xfs_dir_replace(  	if (!args)  		return ENOMEM; +	args->geo = dp->i_mount->m_dir_geo;  	args->name = name->name;  	args->namelen = name->len;  	args->filetype = name->type; @@ -472,7 +513,7 @@ xfs_dir_replace(  		goto out_free;  	} -	rval = xfs_dir2_isblock(tp, dp, &v); +	rval = xfs_dir2_isblock(args, &v);  	if (rval)  		goto out_free;  	if (v) { @@ -480,7 +521,7 @@ xfs_dir_replace(  		goto out_free;  	} -	rval = xfs_dir2_isleaf(tp, dp, &v); +	rval = xfs_dir2_isleaf(args, &v);  	if (rval)  		goto out_free;  	if (v) @@ -516,6 +557,7 @@ xfs_dir_canenter(  	if (!args)  		return ENOMEM; +	args->geo = dp->i_mount->m_dir_geo;  	args->name = name->name;  	args->namelen = name->len;  	args->filetype = name->type; @@ -531,7 +573,7 @@ xfs_dir_canenter(  		goto out_free;  	} -	rval = xfs_dir2_isblock(tp, dp, &v); +	rval = xfs_dir2_isblock(args, &v);  	if (rval)  		goto out_free;  	if (v) { @@ -539,7 +581,7 @@ xfs_dir_canenter(  		goto out_free;  	} -	rval = xfs_dir2_isleaf(tp, dp, &v); +	rval = xfs_dir2_isleaf(args, &v);  	if (rval)  		goto out_free;  	if (v) @@ -579,13 +621,13 @@ xfs_dir2_grow_inode(  	 * Set lowest possible block in the space requested.  	 */  	bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); -	count = mp->m_dirblkfsbs; +	count = args->geo->fsbcount;  	error = xfs_da_grow_inode_int(args, &bno, count);  	if (error)  		return error; -	*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); +	*dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);  	/*  	 * Update file's size if this is the data space and it grew. @@ -607,19 +649,16 @@ xfs_dir2_grow_inode(   */  int  xfs_dir2_isblock( -	xfs_trans_t	*tp, -	xfs_inode_t	*dp, -	int		*vp)		/* out: 1 is block, 0 is not block */ +	struct xfs_da_args	*args, +	int			*vp)	/* out: 1 is block, 0 is not block */  { -	xfs_fileoff_t	last;		/* last file offset */ -	xfs_mount_t	*mp; -	int		rval; +	xfs_fileoff_t		last;	/* last file offset */ +	int			rval; -	mp = dp->i_mount; -	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) +	if ((rval = xfs_bmap_last_offset(args->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); +	rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; +	ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize);  	*vp = rval;  	return 0;  } @@ -629,18 +668,15 @@ xfs_dir2_isblock(   */  int  xfs_dir2_isleaf( -	xfs_trans_t	*tp, -	xfs_inode_t	*dp, -	int		*vp)		/* out: 1 is leaf, 0 is not leaf */ +	struct xfs_da_args	*args, +	int			*vp)	/* out: 1 is block, 0 is not block */  { -	xfs_fileoff_t	last;		/* last file offset */ -	xfs_mount_t	*mp; -	int		rval; +	xfs_fileoff_t		last;	/* last file offset */ +	int			rval; -	mp = dp->i_mount; -	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) +	if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))  		return rval; -	*vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); +	*vp = last == args->geo->leafblk + args->geo->fsbcount;  	return 0;  } @@ -668,11 +704,11 @@ xfs_dir2_shrink_inode(  	dp = args->dp;  	mp = dp->i_mount;  	tp = args->trans; -	da = xfs_dir2_db_to_da(mp, db); +	da = xfs_dir2_db_to_da(args->geo, db);  	/*  	 * Unmap the fsblock(s).  	 */ -	if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, +	if ((error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount,  			XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,  			&done))) {  		/* @@ -699,12 +735,12 @@ xfs_dir2_shrink_inode(  	/*  	 * If it's not a data block, we're done.  	 */ -	if (db >= XFS_DIR2_LEAF_FIRSTDB(mp)) +	if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))  		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)) +	if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))  		return 0;  	bno = da;  	if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { @@ -713,7 +749,7 @@ xfs_dir2_shrink_inode(  		 */  		return error;  	} -	if (db == mp->m_dirdatablk) +	if (db == args->geo->datablk)  		ASSERT(bno == 0);  	else  		ASSERT(bno > 0);  |