diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_readdir.c')
| -rw-r--r-- | fs/xfs/xfs_dir2_readdir.c | 15 | 
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index ad9396e516f6..20b7a5c6eb2f 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -394,6 +394,7 @@ xfs_dir2_leaf_readbuf(  	/*  	 * Do we need more readahead? +	 * Each loop tries to process 1 full dir blk; last may be partial.  	 */  	blk_start_plug(&plug);  	for (mip->ra_index = mip->ra_offset = i = 0; @@ -404,7 +405,8 @@ xfs_dir2_leaf_readbuf(  		 * Read-ahead a contiguous directory block.  		 */  		if (i > mip->ra_current && -		    map[mip->ra_index].br_blockcount >= geo->fsbcount) { +		    (map[mip->ra_index].br_blockcount - mip->ra_offset) >= +		    geo->fsbcount) {  			xfs_dir3_data_readahead(dp,  				map[mip->ra_index].br_startoff + mip->ra_offset,  				XFS_FSB_TO_DADDR(dp->i_mount, @@ -425,14 +427,19 @@ xfs_dir2_leaf_readbuf(  		}  		/* -		 * Advance offset through the mapping table. +		 * Advance offset through the mapping table, processing a full +		 * dir block even if it is fragmented into several extents. +		 * But stop if we have consumed all valid mappings, even if +		 * it's not yet a full directory block.  		 */ -		for (j = 0; j < geo->fsbcount; j += length ) { +		for (j = 0; +		     j < geo->fsbcount && mip->ra_index < mip->map_valid; +		     j += length ) {  			/*  			 * The rest of this extent but not more than a dir  			 * block.  			 */ -			length = min_t(int, geo->fsbcount, +			length = min_t(int, geo->fsbcount - j,  					map[mip->ra_index].br_blockcount -  							mip->ra_offset);  			mip->ra_offset += length;  |