diff options
Diffstat (limited to 'fs/xfs/xfs_aops.c')
-rw-r--r-- | fs/xfs/xfs_aops.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 596ec71da00e..e51e581454e9 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -28,9 +28,9 @@ | |||
28 | #include "xfs_alloc.h" | 28 | #include "xfs_alloc.h" |
29 | #include "xfs_error.h" | 29 | #include "xfs_error.h" |
30 | #include "xfs_iomap.h" | 30 | #include "xfs_iomap.h" |
31 | #include "xfs_vnodeops.h" | ||
32 | #include "xfs_trace.h" | 31 | #include "xfs_trace.h" |
33 | #include "xfs_bmap.h" | 32 | #include "xfs_bmap.h" |
33 | #include "xfs_bmap_util.h" | ||
34 | #include <linux/aio.h> | 34 | #include <linux/aio.h> |
35 | #include <linux/gfp.h> | 35 | #include <linux/gfp.h> |
36 | #include <linux/mpage.h> | 36 | #include <linux/mpage.h> |
@@ -86,14 +86,6 @@ xfs_destroy_ioend( | |||
86 | bh->b_end_io(bh, !ioend->io_error); | 86 | bh->b_end_io(bh, !ioend->io_error); |
87 | } | 87 | } |
88 | 88 | ||
89 | if (ioend->io_iocb) { | ||
90 | inode_dio_done(ioend->io_inode); | ||
91 | if (ioend->io_isasync) { | ||
92 | aio_complete(ioend->io_iocb, ioend->io_error ? | ||
93 | ioend->io_error : ioend->io_result, 0); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | mempool_free(ioend, xfs_ioend_pool); | 89 | mempool_free(ioend, xfs_ioend_pool); |
98 | } | 90 | } |
99 | 91 | ||
@@ -116,7 +108,7 @@ xfs_setfilesize_trans_alloc( | |||
116 | 108 | ||
117 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); | 109 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); |
118 | 110 | ||
119 | error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); | 111 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); |
120 | if (error) { | 112 | if (error) { |
121 | xfs_trans_cancel(tp, 0); | 113 | xfs_trans_cancel(tp, 0); |
122 | return error; | 114 | return error; |
@@ -281,7 +273,6 @@ xfs_alloc_ioend( | |||
281 | * all the I/O from calling the completion routine too early. | 273 | * all the I/O from calling the completion routine too early. |
282 | */ | 274 | */ |
283 | atomic_set(&ioend->io_remaining, 1); | 275 | atomic_set(&ioend->io_remaining, 1); |
284 | ioend->io_isasync = 0; | ||
285 | ioend->io_isdirect = 0; | 276 | ioend->io_isdirect = 0; |
286 | ioend->io_error = 0; | 277 | ioend->io_error = 0; |
287 | ioend->io_list = NULL; | 278 | ioend->io_list = NULL; |
@@ -291,8 +282,6 @@ xfs_alloc_ioend( | |||
291 | ioend->io_buffer_tail = NULL; | 282 | ioend->io_buffer_tail = NULL; |
292 | ioend->io_offset = 0; | 283 | ioend->io_offset = 0; |
293 | ioend->io_size = 0; | 284 | ioend->io_size = 0; |
294 | ioend->io_iocb = NULL; | ||
295 | ioend->io_result = 0; | ||
296 | ioend->io_append_trans = NULL; | 285 | ioend->io_append_trans = NULL; |
297 | 286 | ||
298 | INIT_WORK(&ioend->io_work, xfs_end_io); | 287 | INIT_WORK(&ioend->io_work, xfs_end_io); |
@@ -451,7 +440,7 @@ xfs_start_page_writeback( | |||
451 | end_page_writeback(page); | 440 | end_page_writeback(page); |
452 | } | 441 | } |
453 | 442 | ||
454 | static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) | 443 | static inline int xfs_bio_add_buffer(struct bio *bio, struct buffer_head *bh) |
455 | { | 444 | { |
456 | return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); | 445 | return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); |
457 | } | 446 | } |
@@ -525,7 +514,7 @@ xfs_submit_ioend( | |||
525 | goto retry; | 514 | goto retry; |
526 | } | 515 | } |
527 | 516 | ||
528 | if (bio_add_buffer(bio, bh) != bh->b_size) { | 517 | if (xfs_bio_add_buffer(bio, bh) != bh->b_size) { |
529 | xfs_submit_ioend_bio(wbc, ioend, bio); | 518 | xfs_submit_ioend_bio(wbc, ioend, bio); |
530 | goto retry; | 519 | goto retry; |
531 | } | 520 | } |
@@ -1292,8 +1281,10 @@ __xfs_get_blocks( | |||
1292 | if (create || !ISUNWRITTEN(&imap)) | 1281 | if (create || !ISUNWRITTEN(&imap)) |
1293 | xfs_map_buffer(inode, bh_result, &imap, offset); | 1282 | xfs_map_buffer(inode, bh_result, &imap, offset); |
1294 | if (create && ISUNWRITTEN(&imap)) { | 1283 | if (create && ISUNWRITTEN(&imap)) { |
1295 | if (direct) | 1284 | if (direct) { |
1296 | bh_result->b_private = inode; | 1285 | bh_result->b_private = inode; |
1286 | set_buffer_defer_completion(bh_result); | ||
1287 | } | ||
1297 | set_buffer_unwritten(bh_result); | 1288 | set_buffer_unwritten(bh_result); |
1298 | } | 1289 | } |
1299 | } | 1290 | } |
@@ -1390,9 +1381,7 @@ xfs_end_io_direct_write( | |||
1390 | struct kiocb *iocb, | 1381 | struct kiocb *iocb, |
1391 | loff_t offset, | 1382 | loff_t offset, |
1392 | ssize_t size, | 1383 | ssize_t size, |
1393 | void *private, | 1384 | void *private) |
1394 | int ret, | ||
1395 | bool is_async) | ||
1396 | { | 1385 | { |
1397 | struct xfs_ioend *ioend = iocb->private; | 1386 | struct xfs_ioend *ioend = iocb->private; |
1398 | 1387 | ||
@@ -1414,17 +1403,10 @@ xfs_end_io_direct_write( | |||
1414 | 1403 | ||
1415 | ioend->io_offset = offset; | 1404 | ioend->io_offset = offset; |
1416 | ioend->io_size = size; | 1405 | ioend->io_size = size; |
1417 | ioend->io_iocb = iocb; | ||
1418 | ioend->io_result = ret; | ||
1419 | if (private && size > 0) | 1406 | if (private && size > 0) |
1420 | ioend->io_type = XFS_IO_UNWRITTEN; | 1407 | ioend->io_type = XFS_IO_UNWRITTEN; |
1421 | 1408 | ||
1422 | if (is_async) { | 1409 | xfs_finish_ioend_sync(ioend); |
1423 | ioend->io_isasync = 1; | ||
1424 | xfs_finish_ioend(ioend); | ||
1425 | } else { | ||
1426 | xfs_finish_ioend_sync(ioend); | ||
1427 | } | ||
1428 | } | 1410 | } |
1429 | 1411 | ||
1430 | STATIC ssize_t | 1412 | STATIC ssize_t |
@@ -1516,13 +1498,26 @@ xfs_vm_write_failed( | |||
1516 | loff_t pos, | 1498 | loff_t pos, |
1517 | unsigned len) | 1499 | unsigned len) |
1518 | { | 1500 | { |
1519 | loff_t block_offset = pos & PAGE_MASK; | 1501 | loff_t block_offset; |
1520 | loff_t block_start; | 1502 | loff_t block_start; |
1521 | loff_t block_end; | 1503 | loff_t block_end; |
1522 | loff_t from = pos & (PAGE_CACHE_SIZE - 1); | 1504 | loff_t from = pos & (PAGE_CACHE_SIZE - 1); |
1523 | loff_t to = from + len; | 1505 | loff_t to = from + len; |
1524 | struct buffer_head *bh, *head; | 1506 | struct buffer_head *bh, *head; |
1525 | 1507 | ||
1508 | /* | ||
1509 | * The request pos offset might be 32 or 64 bit, this is all fine | ||
1510 | * on 64-bit platform. However, for 64-bit pos request on 32-bit | ||
1511 | * platform, the high 32-bit will be masked off if we evaluate the | ||
1512 | * block_offset via (pos & PAGE_MASK) because the PAGE_MASK is | ||
1513 | * 0xfffff000 as an unsigned long, hence the result is incorrect | ||
1514 | * which could cause the following ASSERT failed in most cases. | ||
1515 | * In order to avoid this, we can evaluate the block_offset of the | ||
1516 | * start of the page by using shifts rather than masks the mismatch | ||
1517 | * problem. | ||
1518 | */ | ||
1519 | block_offset = (pos >> PAGE_CACHE_SHIFT) << PAGE_CACHE_SHIFT; | ||
1520 | |||
1526 | ASSERT(block_offset + from == pos); | 1521 | ASSERT(block_offset + from == pos); |
1527 | 1522 | ||
1528 | head = page_buffers(page); | 1523 | head = page_buffers(page); |
@@ -1587,7 +1582,7 @@ xfs_vm_write_begin( | |||
1587 | unlock_page(page); | 1582 | unlock_page(page); |
1588 | 1583 | ||
1589 | if (pos + len > i_size_read(inode)) | 1584 | if (pos + len > i_size_read(inode)) |
1590 | truncate_pagecache(inode, pos + len, i_size_read(inode)); | 1585 | truncate_pagecache(inode, i_size_read(inode)); |
1591 | 1586 | ||
1592 | page_cache_release(page); | 1587 | page_cache_release(page); |
1593 | page = NULL; | 1588 | page = NULL; |
@@ -1623,7 +1618,7 @@ xfs_vm_write_end( | |||
1623 | loff_t to = pos + len; | 1618 | loff_t to = pos + len; |
1624 | 1619 | ||
1625 | if (to > isize) { | 1620 | if (to > isize) { |
1626 | truncate_pagecache(inode, to, isize); | 1621 | truncate_pagecache(inode, isize); |
1627 | xfs_vm_kill_delalloc_range(inode, isize, to); | 1622 | xfs_vm_kill_delalloc_range(inode, isize, to); |
1628 | } | 1623 | } |
1629 | } | 1624 | } |