diff options
| author | Olof Johansson <olof@lixom.net> | 2011-12-15 22:02:34 -0800 | 
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2011-12-15 22:02:34 -0800 | 
| commit | 02735a29d8ce882ec698803f064e17888874780c (patch) | |
| tree | 6a4afa3bc8b6d4334df24910a56f77adf126b0c7 /fs/btrfs/extent_io.c | |
| parent | 8d685b7f4d9c9882442bf1b492558d5f17b694fa (diff) | |
| parent | 3d911ad22e8405c1a333a6812e405cb1a5ae9829 (diff) | |
| download | olio-linux-3.10-02735a29d8ce882ec698803f064e17888874780c.tar.xz olio-linux-3.10-02735a29d8ce882ec698803f064e17888874780c.zip  | |
Merge branch 'at91/defconfig' into next/cleanup
Diffstat (limited to 'fs/btrfs/extent_io.c')
| -rw-r--r-- | fs/btrfs/extent_io.c | 51 | 
1 files changed, 36 insertions, 15 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 9472d3de5e5..49f3c9dc09f 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -935,8 +935,10 @@ again:  	node = tree_search(tree, start);  	if (!node) {  		prealloc = alloc_extent_state_atomic(prealloc); -		if (!prealloc) -			return -ENOMEM; +		if (!prealloc) { +			err = -ENOMEM; +			goto out; +		}  		err = insert_state(tree, prealloc, start, end, &bits);  		prealloc = NULL;  		BUG_ON(err == -EEXIST); @@ -992,8 +994,10 @@ hit_next:  	 */  	if (state->start < start) {  		prealloc = alloc_extent_state_atomic(prealloc); -		if (!prealloc) -			return -ENOMEM; +		if (!prealloc) { +			err = -ENOMEM; +			goto out; +		}  		err = split_state(tree, state, prealloc, start);  		BUG_ON(err == -EEXIST);  		prealloc = NULL; @@ -1024,8 +1028,10 @@ hit_next:  			this_end = last_start - 1;  		prealloc = alloc_extent_state_atomic(prealloc); -		if (!prealloc) -			return -ENOMEM; +		if (!prealloc) { +			err = -ENOMEM; +			goto out; +		}  		/*  		 * Avoid to free 'prealloc' if it can be merged with @@ -1051,8 +1057,10 @@ hit_next:  	 */  	if (state->start <= end && state->end > end) {  		prealloc = alloc_extent_state_atomic(prealloc); -		if (!prealloc) -			return -ENOMEM; +		if (!prealloc) { +			err = -ENOMEM; +			goto out; +		}  		err = split_state(tree, state, prealloc, end + 1);  		BUG_ON(err == -EEXIST); @@ -2287,14 +2295,20 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  		if (!uptodate) {  			int failed_mirror;  			failed_mirror = (int)(unsigned long)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); +			/* +			 * 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 +2316,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) {  |