aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_aops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_aops.c')
-rw-r--r--fs/xfs/xfs_aops.c55
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
454static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) 443static 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
1430STATIC ssize_t 1412STATIC 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 }