diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_inode_fork.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.c | 26 | 
1 files changed, 23 insertions, 3 deletions
| diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 25c1e078aef6..9653e964eda4 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -33,6 +33,8 @@  #include "xfs_trace.h"  #include "xfs_attr_sf.h"  #include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_dir2_priv.h"  kmem_zone_t *xfs_ifork_zone; @@ -320,6 +322,7 @@ xfs_iformat_local(  	int		whichfork,  	int		size)  { +	int		error;  	/*  	 * If the size is unreasonable, then something @@ -336,6 +339,14 @@ xfs_iformat_local(  		return -EFSCORRUPTED;  	} +	if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) { +		error = xfs_dir2_sf_verify(ip->i_mount, +				(struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip), +				size); +		if (error) +			return error; +	} +  	xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);  	return 0;  } @@ -856,7 +867,7 @@ xfs_iextents_copy(   * In these cases, the format always takes precedence, because the   * format indicates the current state of the fork.   */ -void +int  xfs_iflush_fork(  	xfs_inode_t		*ip,  	xfs_dinode_t		*dip, @@ -866,6 +877,7 @@ xfs_iflush_fork(  	char			*cp;  	xfs_ifork_t		*ifp;  	xfs_mount_t		*mp; +	int			error;  	static const short	brootflag[2] =  		{ XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };  	static const short	dataflag[2] = @@ -874,7 +886,7 @@ xfs_iflush_fork(  		{ XFS_ILOG_DEXT, XFS_ILOG_AEXT };  	if (!iip) -		return; +		return 0;  	ifp = XFS_IFORK_PTR(ip, whichfork);  	/*  	 * This can happen if we gave up in iformat in an error path, @@ -882,12 +894,19 @@ xfs_iflush_fork(  	 */  	if (!ifp) {  		ASSERT(whichfork == XFS_ATTR_FORK); -		return; +		return 0;  	}  	cp = XFS_DFORK_PTR(dip, whichfork);  	mp = ip->i_mount;  	switch (XFS_IFORK_FORMAT(ip, whichfork)) {  	case XFS_DINODE_FMT_LOCAL: +		if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) { +			error = xfs_dir2_sf_verify(mp, +					(struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data, +					ifp->if_bytes); +			if (error) +				return error; +		}  		if ((iip->ili_fields & dataflag[whichfork]) &&  		    (ifp->if_bytes > 0)) {  			ASSERT(ifp->if_u1.if_data != NULL); @@ -940,6 +959,7 @@ xfs_iflush_fork(  		ASSERT(0);  		break;  	} +	return 0;  }  /* |