aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_aops.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 596ec71da00e..79670869d436 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1516,13 +1516,26 @@ xfs_vm_write_failed(
1516 loff_t pos, 1516 loff_t pos,
1517 unsigned len) 1517 unsigned len)
1518{ 1518{
1519 loff_t block_offset = pos & PAGE_MASK; 1519 loff_t block_offset;
1520 loff_t block_start; 1520 loff_t block_start;
1521 loff_t block_end; 1521 loff_t block_end;
1522 loff_t from = pos & (PAGE_CACHE_SIZE - 1); 1522 loff_t from = pos & (PAGE_CACHE_SIZE - 1);
1523 loff_t to = from + len; 1523 loff_t to = from + len;
1524 struct buffer_head *bh, *head; 1524 struct buffer_head *bh, *head;
1525 1525
1526 /*
1527 * The request pos offset might be 32 or 64 bit, this is all fine
1528 * on 64-bit platform. However, for 64-bit pos request on 32-bit
1529 * platform, the high 32-bit will be masked off if we evaluate the
1530 * block_offset via (pos & PAGE_MASK) because the PAGE_MASK is
1531 * 0xfffff000 as an unsigned long, hence the result is incorrect
1532 * which could cause the following ASSERT failed in most cases.
1533 * In order to avoid this, we can evaluate the block_offset of the
1534 * start of the page by using shifts rather than masks the mismatch
1535 * problem.
1536 */
1537 block_offset = (pos >> PAGE_CACHE_SHIFT) << PAGE_CACHE_SHIFT;
1538
1526 ASSERT(block_offset + from == pos); 1539 ASSERT(block_offset + from == pos);
1527 1540
1528 head = page_buffers(page); 1541 head = page_buffers(page);