diff options
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r-- | drivers/block/loop.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 96c664af8d0..a452b13620a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -213,7 +213,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, | |||
213 | struct address_space_operations *aops = mapping->a_ops; | 213 | struct address_space_operations *aops = mapping->a_ops; |
214 | pgoff_t index; | 214 | pgoff_t index; |
215 | unsigned offset, bv_offs; | 215 | unsigned offset, bv_offs; |
216 | int len, ret = 0; | 216 | int len, ret; |
217 | 217 | ||
218 | down(&mapping->host->i_sem); | 218 | down(&mapping->host->i_sem); |
219 | index = pos >> PAGE_CACHE_SHIFT; | 219 | index = pos >> PAGE_CACHE_SHIFT; |
@@ -232,9 +232,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, | |||
232 | page = grab_cache_page(mapping, index); | 232 | page = grab_cache_page(mapping, index); |
233 | if (unlikely(!page)) | 233 | if (unlikely(!page)) |
234 | goto fail; | 234 | goto fail; |
235 | if (unlikely(aops->prepare_write(file, page, offset, | 235 | ret = aops->prepare_write(file, page, offset, |
236 | offset + size))) | 236 | offset + size); |
237 | if (unlikely(ret)) { | ||
238 | if (ret == AOP_TRUNCATED_PAGE) { | ||
239 | page_cache_release(page); | ||
240 | continue; | ||
241 | } | ||
237 | goto unlock; | 242 | goto unlock; |
243 | } | ||
238 | transfer_result = lo_do_transfer(lo, WRITE, page, offset, | 244 | transfer_result = lo_do_transfer(lo, WRITE, page, offset, |
239 | bvec->bv_page, bv_offs, size, IV); | 245 | bvec->bv_page, bv_offs, size, IV); |
240 | if (unlikely(transfer_result)) { | 246 | if (unlikely(transfer_result)) { |
@@ -251,9 +257,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, | |||
251 | kunmap_atomic(kaddr, KM_USER0); | 257 | kunmap_atomic(kaddr, KM_USER0); |
252 | } | 258 | } |
253 | flush_dcache_page(page); | 259 | flush_dcache_page(page); |
254 | if (unlikely(aops->commit_write(file, page, offset, | 260 | ret = aops->commit_write(file, page, offset, |
255 | offset + size))) | 261 | offset + size); |
262 | if (unlikely(ret)) { | ||
263 | if (ret == AOP_TRUNCATED_PAGE) { | ||
264 | page_cache_release(page); | ||
265 | continue; | ||
266 | } | ||
256 | goto unlock; | 267 | goto unlock; |
268 | } | ||
257 | if (unlikely(transfer_result)) | 269 | if (unlikely(transfer_result)) |
258 | goto unlock; | 270 | goto unlock; |
259 | bv_offs += size; | 271 | bv_offs += size; |
@@ -264,6 +276,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, | |||
264 | unlock_page(page); | 276 | unlock_page(page); |
265 | page_cache_release(page); | 277 | page_cache_release(page); |
266 | } | 278 | } |
279 | ret = 0; | ||
267 | out: | 280 | out: |
268 | up(&mapping->host->i_sem); | 281 | up(&mapping->host->i_sem); |
269 | return ret; | 282 | return ret; |