diff options
-rw-r--r-- | fs/xfs/xfs_aops.c | 50 | ||||
-rw-r--r-- | fs/xfs/xfs_aops.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 6 |
3 files changed, 49 insertions, 9 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 50ab2879b9da..e747d6ad5d18 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -1250,13 +1250,28 @@ xfs_vm_releasepage( | |||
1250 | * the DIO. There is only going to be one reference to the ioend and its life | 1250 | * the DIO. There is only going to be one reference to the ioend and its life |
1251 | * cycle is constrained by the DIO completion code. hence we don't need | 1251 | * cycle is constrained by the DIO completion code. hence we don't need |
1252 | * reference counting here. | 1252 | * reference counting here. |
1253 | * | ||
1254 | * Note that for DIO, an IO to the highest supported file block offset (i.e. | ||
1255 | * 2^63 - 1FSB bytes) will result in the offset + count overflowing a signed 64 | ||
1256 | * bit variable. Hence if we see this overflow, we have to assume that the IO is | ||
1257 | * extending the file size. We won't know for sure until IO completion is run | ||
1258 | * and the actual max write offset is communicated to the IO completion | ||
1259 | * routine. | ||
1260 | * | ||
1261 | * For DAX page faults, we are preparing to never see unwritten extents here, | ||
1262 | * nor should we ever extend the inode size. Hence we will soon have nothing to | ||
1263 | * do here for this case, ensuring we don't have to provide an IO completion | ||
1264 | * callback to free an ioend that we don't actually need for a fault into the | ||
1265 | * page at offset (2^63 - 1FSB) bytes. | ||
1253 | */ | 1266 | */ |
1267 | |||
1254 | static void | 1268 | static void |
1255 | xfs_map_direct( | 1269 | xfs_map_direct( |
1256 | struct inode *inode, | 1270 | struct inode *inode, |
1257 | struct buffer_head *bh_result, | 1271 | struct buffer_head *bh_result, |
1258 | struct xfs_bmbt_irec *imap, | 1272 | struct xfs_bmbt_irec *imap, |
1259 | xfs_off_t offset) | 1273 | xfs_off_t offset, |
1274 | bool dax_fault) | ||
1260 | { | 1275 | { |
1261 | struct xfs_ioend *ioend; | 1276 | struct xfs_ioend *ioend; |
1262 | xfs_off_t size = bh_result->b_size; | 1277 | xfs_off_t size = bh_result->b_size; |
@@ -1269,6 +1284,16 @@ xfs_map_direct( | |||
1269 | 1284 | ||
1270 | trace_xfs_gbmap_direct(XFS_I(inode), offset, size, type, imap); | 1285 | trace_xfs_gbmap_direct(XFS_I(inode), offset, size, type, imap); |
1271 | 1286 | ||
1287 | /* XXX: preparation for removing unwritten extents in DAX */ | ||
1288 | #if 0 | ||
1289 | if (dax_fault) { | ||
1290 | ASSERT(type == XFS_IO_OVERWRITE); | ||
1291 | trace_xfs_gbmap_direct_none(XFS_I(inode), offset, size, type, | ||
1292 | imap); | ||
1293 | return; | ||
1294 | } | ||
1295 | #endif | ||
1296 | |||
1272 | if (bh_result->b_private) { | 1297 | if (bh_result->b_private) { |
1273 | ioend = bh_result->b_private; | 1298 | ioend = bh_result->b_private; |
1274 | ASSERT(ioend->io_size > 0); | 1299 | ASSERT(ioend->io_size > 0); |
@@ -1283,7 +1308,8 @@ xfs_map_direct( | |||
1283 | ioend->io_size, ioend->io_type, | 1308 | ioend->io_size, ioend->io_type, |
1284 | imap); | 1309 | imap); |
1285 | } else if (type == XFS_IO_UNWRITTEN || | 1310 | } else if (type == XFS_IO_UNWRITTEN || |
1286 | offset + size > i_size_read(inode)) { | 1311 | offset + size > i_size_read(inode) || |
1312 | offset + size < 0) { | ||
1287 | ioend = xfs_alloc_ioend(inode, type); | 1313 | ioend = xfs_alloc_ioend(inode, type); |
1288 | ioend->io_offset = offset; | 1314 | ioend->io_offset = offset; |
1289 | ioend->io_size = size; | 1315 | ioend->io_size = size; |
@@ -1345,7 +1371,8 @@ __xfs_get_blocks( | |||
1345 | sector_t iblock, | 1371 | sector_t iblock, |
1346 | struct buffer_head *bh_result, | 1372 | struct buffer_head *bh_result, |
1347 | int create, | 1373 | int create, |
1348 | bool direct) | 1374 | bool direct, |
1375 | bool dax_fault) | ||
1349 | { | 1376 | { |
1350 | struct xfs_inode *ip = XFS_I(inode); | 1377 | struct xfs_inode *ip = XFS_I(inode); |
1351 | struct xfs_mount *mp = ip->i_mount; | 1378 | struct xfs_mount *mp = ip->i_mount; |
@@ -1458,7 +1485,8 @@ __xfs_get_blocks( | |||
1458 | set_buffer_unwritten(bh_result); | 1485 | set_buffer_unwritten(bh_result); |
1459 | /* direct IO needs special help */ | 1486 | /* direct IO needs special help */ |
1460 | if (create && direct) | 1487 | if (create && direct) |
1461 | xfs_map_direct(inode, bh_result, &imap, offset); | 1488 | xfs_map_direct(inode, bh_result, &imap, offset, |
1489 | dax_fault); | ||
1462 | } | 1490 | } |
1463 | 1491 | ||
1464 | /* | 1492 | /* |
@@ -1505,7 +1533,7 @@ xfs_get_blocks( | |||
1505 | struct buffer_head *bh_result, | 1533 | struct buffer_head *bh_result, |
1506 | int create) | 1534 | int create) |
1507 | { | 1535 | { |
1508 | return __xfs_get_blocks(inode, iblock, bh_result, create, false); | 1536 | return __xfs_get_blocks(inode, iblock, bh_result, create, false, false); |
1509 | } | 1537 | } |
1510 | 1538 | ||
1511 | int | 1539 | int |
@@ -1515,7 +1543,17 @@ xfs_get_blocks_direct( | |||
1515 | struct buffer_head *bh_result, | 1543 | struct buffer_head *bh_result, |
1516 | int create) | 1544 | int create) |
1517 | { | 1545 | { |
1518 | return __xfs_get_blocks(inode, iblock, bh_result, create, true); | 1546 | return __xfs_get_blocks(inode, iblock, bh_result, create, true, false); |
1547 | } | ||
1548 | |||
1549 | int | ||
1550 | xfs_get_blocks_dax_fault( | ||
1551 | struct inode *inode, | ||
1552 | sector_t iblock, | ||
1553 | struct buffer_head *bh_result, | ||
1554 | int create) | ||
1555 | { | ||
1556 | return __xfs_get_blocks(inode, iblock, bh_result, create, true, true); | ||
1519 | } | 1557 | } |
1520 | 1558 | ||
1521 | static void | 1559 | static void |
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 86afd1ac7895..d39ba25ccc98 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h | |||
@@ -58,6 +58,8 @@ int xfs_get_blocks(struct inode *inode, sector_t offset, | |||
58 | struct buffer_head *map_bh, int create); | 58 | struct buffer_head *map_bh, int create); |
59 | int xfs_get_blocks_direct(struct inode *inode, sector_t offset, | 59 | int xfs_get_blocks_direct(struct inode *inode, sector_t offset, |
60 | struct buffer_head *map_bh, int create); | 60 | struct buffer_head *map_bh, int create); |
61 | int xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset, | ||
62 | struct buffer_head *map_bh, int create); | ||
61 | void xfs_end_io_dax_write(struct buffer_head *bh, int uptodate); | 63 | void xfs_end_io_dax_write(struct buffer_head *bh, int uptodate); |
62 | 64 | ||
63 | extern void xfs_count_page_state(struct page *, int *, int *); | 65 | extern void xfs_count_page_state(struct page *, int *, int *); |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index e78feb400e22..27abe1c92184 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -1503,7 +1503,7 @@ xfs_filemap_page_mkwrite( | |||
1503 | xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); | 1503 | xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); |
1504 | 1504 | ||
1505 | if (IS_DAX(inode)) { | 1505 | if (IS_DAX(inode)) { |
1506 | ret = __dax_mkwrite(vma, vmf, xfs_get_blocks_direct, | 1506 | ret = __dax_mkwrite(vma, vmf, xfs_get_blocks_dax_fault, |
1507 | xfs_end_io_dax_write); | 1507 | xfs_end_io_dax_write); |
1508 | } else { | 1508 | } else { |
1509 | ret = __block_page_mkwrite(vma, vmf, xfs_get_blocks); | 1509 | ret = __block_page_mkwrite(vma, vmf, xfs_get_blocks); |
@@ -1538,7 +1538,7 @@ xfs_filemap_fault( | |||
1538 | * changes to xfs_get_blocks_direct() to map unwritten extent | 1538 | * changes to xfs_get_blocks_direct() to map unwritten extent |
1539 | * ioend for conversion on read-only mappings. | 1539 | * ioend for conversion on read-only mappings. |
1540 | */ | 1540 | */ |
1541 | ret = __dax_fault(vma, vmf, xfs_get_blocks_direct, NULL); | 1541 | ret = __dax_fault(vma, vmf, xfs_get_blocks_dax_fault, NULL); |
1542 | } else | 1542 | } else |
1543 | ret = filemap_fault(vma, vmf); | 1543 | ret = filemap_fault(vma, vmf); |
1544 | xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); | 1544 | xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); |
@@ -1565,7 +1565,7 @@ xfs_filemap_pmd_fault( | |||
1565 | sb_start_pagefault(inode->i_sb); | 1565 | sb_start_pagefault(inode->i_sb); |
1566 | file_update_time(vma->vm_file); | 1566 | file_update_time(vma->vm_file); |
1567 | xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); | 1567 | xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); |
1568 | ret = __dax_pmd_fault(vma, addr, pmd, flags, xfs_get_blocks_direct, | 1568 | ret = __dax_pmd_fault(vma, addr, pmd, flags, xfs_get_blocks_dax_fault, |
1569 | xfs_end_io_dax_write); | 1569 | xfs_end_io_dax_write); |
1570 | xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); | 1570 | xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); |
1571 | sb_end_pagefault(inode->i_sb); | 1571 | sb_end_pagefault(inode->i_sb); |