diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
| -rw-r--r-- | fs/btrfs/extent_io.c | 36 | 
1 files changed, 26 insertions, 10 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 1f87c4d0e7a..be1bf627a14 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2285,16 +2285,22 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  				clean_io_failure(start, page);  		}  		if (!uptodate) { -			u64 failed_mirror; -			failed_mirror = (u64)bio->bi_bdev; -			if (tree->ops && tree->ops->readpage_io_failed_hook) -				ret = tree->ops->readpage_io_failed_hook( -						bio, page, start, end, -						failed_mirror, state); -			else -				ret = bio_readpage_error(bio, page, start, end, -							 failed_mirror, NULL); +			int failed_mirror; +			failed_mirror = (int)(unsigned long)bio->bi_bdev; +			/* +			 * The generic bio_readpage_error handles errors the +			 * following way: If possible, new read requests are +			 * created and submitted and will end up in +			 * end_bio_extent_readpage as well (if we're lucky, not +			 * in the !uptodate case). In that case it returns 0 and +			 * we just go on with the next page in our bio. If it +			 * can't handle the error it will return -EIO and we +			 * remain responsible for that page. +			 */ +			ret = bio_readpage_error(bio, page, start, end, +							failed_mirror, NULL);  			if (ret == 0) { +error_handled:  				uptodate =  					test_bit(BIO_UPTODATE, &bio->bi_flags);  				if (err) @@ -2302,6 +2308,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  				uncache_state(&cached);  				continue;  			} +			if (tree->ops && tree->ops->readpage_io_failed_hook) { +				ret = tree->ops->readpage_io_failed_hook( +							bio, page, start, end, +							failed_mirror, state); +				if (ret == 0) +					goto error_handled; +			}  		}  		if (uptodate) { @@ -3366,6 +3379,9 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  		return -ENOMEM;  	path->leave_spinning = 1; +	start = ALIGN(start, BTRFS_I(inode)->root->sectorsize); +	len = ALIGN(len, BTRFS_I(inode)->root->sectorsize); +  	/*  	 * lookup the last file extent.  We're not using i_size here  	 * because there might be preallocation past i_size @@ -3413,7 +3429,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  	lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,  			 &cached_state, GFP_NOFS); -	em = get_extent_skip_holes(inode, off, last_for_get_extent, +	em = get_extent_skip_holes(inode, start, last_for_get_extent,  				   get_extent);  	if (!em)  		goto out;  |