diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_dir2_block.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_dir2_block.c | 131 | 
1 files changed, 61 insertions, 70 deletions
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c index 49e4bc39e7bb..d6ced59b9567 100644 --- a/fs/xfs/libxfs/xfs_dir2_block.c +++ b/fs/xfs/libxfs/xfs_dir2_block.c @@ -123,7 +123,7 @@ xfs_dir3_block_read(  	struct xfs_mount	*mp = dp->i_mount;  	int			err; -	err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp, +	err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, 0, bpp,  				XFS_DATA_FORK, &xfs_dir3_block_buf_ops);  	if (!err && tp && *bpp)  		xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF); @@ -172,7 +172,7 @@ xfs_dir2_block_need_space(  	struct xfs_dir2_data_unused	*enddup = NULL;  	*compact = 0; -	bf = dp->d_ops->data_bestfree_p(hdr); +	bf = xfs_dir2_data_bestfree_p(dp->i_mount, hdr);  	/*  	 * If there are stale entries we'll use one for the leaf. @@ -311,7 +311,7 @@ xfs_dir2_block_compact(  	 * This needs to happen before the next call to use_free.  	 */  	if (needscan) -		xfs_dir2_data_freescan(args->dp, hdr, needlog); +		xfs_dir2_data_freescan(args->dp->i_mount, hdr, needlog);  }  /* @@ -355,7 +355,7 @@ xfs_dir2_block_addname(  	if (error)  		return error; -	len = dp->d_ops->data_entsize(args->namelen); +	len = xfs_dir2_data_entsize(dp->i_mount, args->namelen);  	/*  	 * Set up pointers to parts of the block. @@ -458,7 +458,7 @@ xfs_dir2_block_addname(  		 * This needs to happen before the next call to use_free.  		 */  		if (needscan) { -			xfs_dir2_data_freescan(dp, hdr, &needlog); +			xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);  			needscan = 0;  		}  		/* @@ -541,14 +541,14 @@ xfs_dir2_block_addname(  	dep->inumber = cpu_to_be64(args->inumber);  	dep->namelen = args->namelen;  	memcpy(dep->name, args->name, args->namelen); -	dp->d_ops->data_put_ftype(dep, args->filetype); -	tagp = dp->d_ops->data_entry_tag_p(dep); +	xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype); +	tagp = xfs_dir2_data_entry_tag_p(dp->i_mount, dep);  	*tagp = cpu_to_be16((char *)dep - (char *)hdr);  	/*  	 * Clean up the bestfree array and log the header, tail, and entry.  	 */  	if (needscan) -		xfs_dir2_data_freescan(dp, hdr, &needlog); +		xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);  	if (needlog)  		xfs_dir2_data_log_header(args, bp);  	xfs_dir2_block_log_tail(tp, bp); @@ -633,7 +633,7 @@ xfs_dir2_block_lookup(  	 * Fill in inode number, CI name if appropriate, release the block.  	 */  	args->inumber = be64_to_cpu(dep->inumber); -	args->filetype = dp->d_ops->data_get_ftype(dep); +	args->filetype = xfs_dir2_data_get_ftype(dp->i_mount, dep);  	error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);  	xfs_trans_brelse(args->trans, bp);  	return error; @@ -660,13 +660,11 @@ xfs_dir2_block_lookup_int(  	int			high;		/* binary search high index */  	int			low;		/* binary search low index */  	int			mid;		/* binary search current idx */ -	xfs_mount_t		*mp;		/* filesystem mount point */  	xfs_trans_t		*tp;		/* transaction pointer */  	enum xfs_dacmp		cmp;		/* comparison result */  	dp = args->dp;  	tp = args->trans; -	mp = dp->i_mount;  	error = xfs_dir3_block_read(tp, dp, &bp);  	if (error) @@ -718,7 +716,7 @@ xfs_dir2_block_lookup_int(  		 * and buffer. If it's the first case-insensitive match, store  		 * the index and buffer and continue looking for an exact match.  		 */ -		cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); +		cmp = xfs_dir2_compname(args, dep->name, dep->namelen);  		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {  			args->cmpresult = cmp;  			*bpp = bp; @@ -791,7 +789,8 @@ xfs_dir2_block_removename(  	needlog = needscan = 0;  	xfs_dir2_data_make_free(args, bp,  		(xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), -		dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); +		xfs_dir2_data_entsize(dp->i_mount, dep->namelen), &needlog, +		&needscan);  	/*  	 * Fix up the block tail.  	 */ @@ -806,7 +805,7 @@ xfs_dir2_block_removename(  	 * Fix up bestfree, log the header if necessary.  	 */  	if (needscan) -		xfs_dir2_data_freescan(dp, hdr, &needlog); +		xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);  	if (needlog)  		xfs_dir2_data_log_header(args, bp);  	xfs_dir3_data_check(dp, bp); @@ -864,7 +863,7 @@ xfs_dir2_block_replace(  	 * Change the inode number to the new value.  	 */  	dep->inumber = cpu_to_be64(args->inumber); -	dp->d_ops->data_put_ftype(dep, args->filetype); +	xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype);  	xfs_dir2_data_log_entry(args, bp, dep);  	xfs_dir3_data_check(dp, bp);  	return 0; @@ -914,7 +913,6 @@ xfs_dir2_leaf_to_block(  	__be16			*tagp;		/* end of entry (tag) */  	int			to;		/* block/leaf to index */  	xfs_trans_t		*tp;		/* transaction pointer */ -	struct xfs_dir2_leaf_entry *ents;  	struct xfs_dir3_icleaf_hdr leafhdr;  	trace_xfs_dir2_leaf_to_block(args); @@ -923,8 +921,7 @@ xfs_dir2_leaf_to_block(  	tp = args->trans;  	mp = dp->i_mount;  	leaf = lbp->b_addr; -	dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); -	ents = dp->d_ops->leaf_ents_p(leaf); +	xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);  	ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);  	ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || @@ -938,7 +935,7 @@ xfs_dir2_leaf_to_block(  	while (dp->i_d.di_size > args->geo->blksize) {  		int hdrsz; -		hdrsz = dp->d_ops->data_entry_offset; +		hdrsz = args->geo->data_entry_offset;  		bestsp = xfs_dir2_leaf_bests_p(ltp);  		if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==  					    args->geo->blksize - hdrsz) { @@ -953,7 +950,7 @@ xfs_dir2_leaf_to_block(  	 * Read the data block if we don't already have it, give up if it fails.  	 */  	if (!dbp) { -		error = xfs_dir3_data_read(tp, dp, args->geo->datablk, -1, &dbp); +		error = xfs_dir3_data_read(tp, dp, args->geo->datablk, 0, &dbp);  		if (error)  			return error;  	} @@ -1004,9 +1001,10 @@ xfs_dir2_leaf_to_block(  	 */  	lep = xfs_dir2_block_leaf_p(btp);  	for (from = to = 0; from < leafhdr.count; from++) { -		if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) +		if (leafhdr.ents[from].address == +		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))  			continue; -		lep[to++] = ents[from]; +		lep[to++] = leafhdr.ents[from];  	}  	ASSERT(to == be32_to_cpu(btp->count));  	xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1); @@ -1014,7 +1012,7 @@ xfs_dir2_leaf_to_block(  	 * Scan the bestfree if we need it and log the data block header.  	 */  	if (needscan) -		xfs_dir2_data_freescan(dp, hdr, &needlog); +		xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);  	if (needlog)  		xfs_dir2_data_log_header(args, dbp);  	/* @@ -1039,47 +1037,38 @@ xfs_dir2_leaf_to_block(   */  int						/* error */  xfs_dir2_sf_to_block( -	xfs_da_args_t		*args)		/* operation arguments */ +	struct xfs_da_args	*args)  { +	struct xfs_trans	*tp = args->trans; +	struct xfs_inode	*dp = args->dp; +	struct xfs_mount	*mp = dp->i_mount; +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK); +	struct xfs_da_geometry	*geo = args->geo;  	xfs_dir2_db_t		blkno;		/* dir-relative block # (0) */  	xfs_dir2_data_hdr_t	*hdr;		/* block header */  	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */  	struct xfs_buf		*bp;		/* block buffer */  	xfs_dir2_block_tail_t	*btp;		/* block tail pointer */  	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */ -	xfs_inode_t		*dp;		/* incore directory inode */  	int			dummy;		/* trash */  	xfs_dir2_data_unused_t	*dup;		/* unused entry pointer */  	int			endoffset;	/* end of data objects */  	int			error;		/* error return value */  	int			i;		/* index */ -	xfs_mount_t		*mp;		/* filesystem mount point */  	int			needlog;	/* need to log block header */  	int			needscan;	/* need to scan block freespc */  	int			newoffset;	/* offset from current entry */ -	int			offset;		/* target block offset */ +	unsigned int		offset = geo->data_entry_offset;  	xfs_dir2_sf_entry_t	*sfep;		/* sf entry pointer */  	xfs_dir2_sf_hdr_t	*oldsfp;	/* old shortform header  */  	xfs_dir2_sf_hdr_t	*sfp;		/* shortform header  */  	__be16			*tagp;		/* end of data entry */ -	xfs_trans_t		*tp;		/* transaction pointer */  	struct xfs_name		name; -	struct xfs_ifork	*ifp;  	trace_xfs_dir2_sf_to_block(args); -	dp = args->dp; -	tp = args->trans; -	mp = dp->i_mount; -	ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK);  	ASSERT(ifp->if_flags & XFS_IFINLINE); -	/* -	 * Bomb out if the shortform directory is way too short. -	 */ -	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { -		ASSERT(XFS_FORCED_SHUTDOWN(mp)); -		return -EIO; -	} +	ASSERT(dp->i_d.di_size >= offsetof(struct xfs_dir2_sf_hdr, parent));  	oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data; @@ -1123,7 +1112,7 @@ xfs_dir2_sf_to_block(  	 * The whole thing is initialized to free by the init routine.  	 * Say we're using the leaf and tail area.  	 */ -	dup = dp->d_ops->data_unused_p(hdr); +	dup = bp->b_addr + offset;  	needlog = needscan = 0;  	error = xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,  			i, &needlog, &needscan); @@ -1146,35 +1135,37 @@ xfs_dir2_sf_to_block(  			be16_to_cpu(dup->length), &needlog, &needscan);  	if (error)  		goto out_free; +  	/*  	 * Create entry for .  	 */ -	dep = dp->d_ops->data_dot_entry_p(hdr); +	dep = bp->b_addr + offset;  	dep->inumber = cpu_to_be64(dp->i_ino);  	dep->namelen = 1;  	dep->name[0] = '.'; -	dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); -	tagp = dp->d_ops->data_entry_tag_p(dep); -	*tagp = cpu_to_be16((char *)dep - (char *)hdr); +	xfs_dir2_data_put_ftype(mp, dep, XFS_DIR3_FT_DIR); +	tagp = xfs_dir2_data_entry_tag_p(mp, dep); +	*tagp = cpu_to_be16(offset);  	xfs_dir2_data_log_entry(args, bp, dep);  	blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); -	blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( -				(char *)dep - (char *)hdr)); +	blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(offset)); +	offset += xfs_dir2_data_entsize(mp, dep->namelen); +  	/*  	 * Create entry for ..  	 */ -	dep = dp->d_ops->data_dotdot_entry_p(hdr); -	dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp)); +	dep = bp->b_addr + offset; +	dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));  	dep->namelen = 2;  	dep->name[0] = dep->name[1] = '.'; -	dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); -	tagp = dp->d_ops->data_entry_tag_p(dep); -	*tagp = cpu_to_be16((char *)dep - (char *)hdr); +	xfs_dir2_data_put_ftype(mp, dep, XFS_DIR3_FT_DIR); +	tagp = xfs_dir2_data_entry_tag_p(mp, dep); +	*tagp = cpu_to_be16(offset);  	xfs_dir2_data_log_entry(args, bp, dep);  	blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); -	blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( -				(char *)dep - (char *)hdr)); -	offset = dp->d_ops->data_first_offset; +	blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(offset)); +	offset += xfs_dir2_data_entsize(mp, dep->namelen); +  	/*  	 * Loop over existing entries, stuff them in.  	 */ @@ -1183,6 +1174,7 @@ xfs_dir2_sf_to_block(  		sfep = NULL;  	else  		sfep = xfs_dir2_sf_firstentry(sfp); +  	/*  	 * Need to preserve the existing offset values in the sf directory.  	 * Insert holes (unused entries) where necessary. @@ -1199,40 +1191,39 @@ xfs_dir2_sf_to_block(  		 * There should be a hole here, make one.  		 */  		if (offset < newoffset) { -			dup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); +			dup = bp->b_addr + offset;  			dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);  			dup->length = cpu_to_be16(newoffset - offset); -			*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16( -				((char *)dup - (char *)hdr)); +			*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(offset);  			xfs_dir2_data_log_unused(args, bp, dup);  			xfs_dir2_data_freeinsert(hdr, -						 dp->d_ops->data_bestfree_p(hdr), -						 dup, &dummy); +					xfs_dir2_data_bestfree_p(mp, hdr), +					dup, &dummy);  			offset += be16_to_cpu(dup->length);  			continue;  		}  		/*  		 * Copy a real entry.  		 */ -		dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); -		dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep)); +		dep = bp->b_addr + newoffset; +		dep->inumber = cpu_to_be64(xfs_dir2_sf_get_ino(mp, sfp, sfep));  		dep->namelen = sfep->namelen; -		dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep)); +		xfs_dir2_data_put_ftype(mp, dep, +				xfs_dir2_sf_get_ftype(mp, sfep));  		memcpy(dep->name, sfep->name, dep->namelen); -		tagp = dp->d_ops->data_entry_tag_p(dep); -		*tagp = cpu_to_be16((char *)dep - (char *)hdr); +		tagp = xfs_dir2_data_entry_tag_p(mp, dep); +		*tagp = cpu_to_be16(newoffset);  		xfs_dir2_data_log_entry(args, bp, dep);  		name.name = sfep->name;  		name.len = sfep->namelen; -		blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> -							hashname(&name)); -		blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( -						 (char *)dep - (char *)hdr)); +		blp[2 + i].hashval = cpu_to_be32(xfs_dir2_hashname(mp, &name)); +		blp[2 + i].address = +			cpu_to_be32(xfs_dir2_byte_to_dataptr(newoffset));  		offset = (int)((char *)(tagp + 1) - (char *)hdr);  		if (++i == sfp->count)  			sfep = NULL;  		else -			sfep = dp->d_ops->sf_nextentry(sfp, sfep); +			sfep = xfs_dir2_sf_nextentry(mp, sfp, sfep);  	}  	/* Done with the temporary buffer */  	kmem_free(sfp);  |