diff options
author | Souptick Joarder <jrdr.linux@gmail.com> | 2018-06-07 20:04:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-07 20:34:33 -0400 |
commit | ab77dab46210bb630e06c6803c5d84074bacd351 (patch) | |
tree | 1b0c7f6899d1438d11fa3fab5353318539aafd96 /fs/dax.c | |
parent | 3036bc45364f98515a2c446d7fac2c34dcfbeff4 (diff) |
fs/dax.c: use new return type vm_fault_t
Use new return type vm_fault_t for fault handler. For now, this is just
documenting that the function returns a VM_FAULT value rather than an
errno. Once all instances are converted, vm_fault_t will become a
distinct type.
commit 1c8f422059ae ("mm: change return type to vm_fault_t")
There was an existing bug inside dax_load_hole() if vm_insert_mixed had
failed to allocate a page table, we'd return VM_FAULT_NOPAGE instead of
VM_FAULT_OOM. With new vmf_insert_mixed() this issue is addressed.
vm_insert_mixed_mkwrite has inefficiency when it returns an error value,
driver has to convert it to vm_fault_t type. With new
vmf_insert_mixed_mkwrite() this limitation will be addressed.
Link: http://lkml.kernel.org/r/20180510181121.GA15239@jordon-HP-15-Notebook-PC
Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Matthew Wilcox <mawilcox@microsoft.com>
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/dax.c')
-rw-r--r-- | fs/dax.c | 78 |
1 files changed, 37 insertions, 41 deletions
@@ -905,12 +905,12 @@ out: | |||
905 | * If this page is ever written to we will re-fault and change the mapping to | 905 | * If this page is ever written to we will re-fault and change the mapping to |
906 | * point to real DAX storage instead. | 906 | * point to real DAX storage instead. |
907 | */ | 907 | */ |
908 | static int dax_load_hole(struct address_space *mapping, void *entry, | 908 | static vm_fault_t dax_load_hole(struct address_space *mapping, void *entry, |
909 | struct vm_fault *vmf) | 909 | struct vm_fault *vmf) |
910 | { | 910 | { |
911 | struct inode *inode = mapping->host; | 911 | struct inode *inode = mapping->host; |
912 | unsigned long vaddr = vmf->address; | 912 | unsigned long vaddr = vmf->address; |
913 | int ret = VM_FAULT_NOPAGE; | 913 | vm_fault_t ret = VM_FAULT_NOPAGE; |
914 | struct page *zero_page; | 914 | struct page *zero_page; |
915 | void *entry2; | 915 | void *entry2; |
916 | pfn_t pfn; | 916 | pfn_t pfn; |
@@ -929,7 +929,7 @@ static int dax_load_hole(struct address_space *mapping, void *entry, | |||
929 | goto out; | 929 | goto out; |
930 | } | 930 | } |
931 | 931 | ||
932 | vm_insert_mixed(vmf->vma, vaddr, pfn); | 932 | ret = vmf_insert_mixed(vmf->vma, vaddr, pfn); |
933 | out: | 933 | out: |
934 | trace_dax_load_hole(inode, vmf, ret); | 934 | trace_dax_load_hole(inode, vmf, ret); |
935 | return ret; | 935 | return ret; |
@@ -1112,7 +1112,7 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
1112 | } | 1112 | } |
1113 | EXPORT_SYMBOL_GPL(dax_iomap_rw); | 1113 | EXPORT_SYMBOL_GPL(dax_iomap_rw); |
1114 | 1114 | ||
1115 | static int dax_fault_return(int error) | 1115 | static vm_fault_t dax_fault_return(int error) |
1116 | { | 1116 | { |
1117 | if (error == 0) | 1117 | if (error == 0) |
1118 | return VM_FAULT_NOPAGE; | 1118 | return VM_FAULT_NOPAGE; |
@@ -1132,7 +1132,7 @@ static bool dax_fault_is_synchronous(unsigned long flags, | |||
1132 | && (iomap->flags & IOMAP_F_DIRTY); | 1132 | && (iomap->flags & IOMAP_F_DIRTY); |
1133 | } | 1133 | } |
1134 | 1134 | ||
1135 | static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | 1135 | static vm_fault_t dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, |
1136 | int *iomap_errp, const struct iomap_ops *ops) | 1136 | int *iomap_errp, const struct iomap_ops *ops) |
1137 | { | 1137 | { |
1138 | struct vm_area_struct *vma = vmf->vma; | 1138 | struct vm_area_struct *vma = vmf->vma; |
@@ -1145,18 +1145,18 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1145 | int error, major = 0; | 1145 | int error, major = 0; |
1146 | bool write = vmf->flags & FAULT_FLAG_WRITE; | 1146 | bool write = vmf->flags & FAULT_FLAG_WRITE; |
1147 | bool sync; | 1147 | bool sync; |
1148 | int vmf_ret = 0; | 1148 | vm_fault_t ret = 0; |
1149 | void *entry; | 1149 | void *entry; |
1150 | pfn_t pfn; | 1150 | pfn_t pfn; |
1151 | 1151 | ||
1152 | trace_dax_pte_fault(inode, vmf, vmf_ret); | 1152 | trace_dax_pte_fault(inode, vmf, ret); |
1153 | /* | 1153 | /* |
1154 | * Check whether offset isn't beyond end of file now. Caller is supposed | 1154 | * Check whether offset isn't beyond end of file now. Caller is supposed |
1155 | * to hold locks serializing us with truncate / punch hole so this is | 1155 | * to hold locks serializing us with truncate / punch hole so this is |
1156 | * a reliable test. | 1156 | * a reliable test. |
1157 | */ | 1157 | */ |
1158 | if (pos >= i_size_read(inode)) { | 1158 | if (pos >= i_size_read(inode)) { |
1159 | vmf_ret = VM_FAULT_SIGBUS; | 1159 | ret = VM_FAULT_SIGBUS; |
1160 | goto out; | 1160 | goto out; |
1161 | } | 1161 | } |
1162 | 1162 | ||
@@ -1165,7 +1165,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1165 | 1165 | ||
1166 | entry = grab_mapping_entry(mapping, vmf->pgoff, 0); | 1166 | entry = grab_mapping_entry(mapping, vmf->pgoff, 0); |
1167 | if (IS_ERR(entry)) { | 1167 | if (IS_ERR(entry)) { |
1168 | vmf_ret = dax_fault_return(PTR_ERR(entry)); | 1168 | ret = dax_fault_return(PTR_ERR(entry)); |
1169 | goto out; | 1169 | goto out; |
1170 | } | 1170 | } |
1171 | 1171 | ||
@@ -1176,7 +1176,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1176 | * retried. | 1176 | * retried. |
1177 | */ | 1177 | */ |
1178 | if (pmd_trans_huge(*vmf->pmd) || pmd_devmap(*vmf->pmd)) { | 1178 | if (pmd_trans_huge(*vmf->pmd) || pmd_devmap(*vmf->pmd)) { |
1179 | vmf_ret = VM_FAULT_NOPAGE; | 1179 | ret = VM_FAULT_NOPAGE; |
1180 | goto unlock_entry; | 1180 | goto unlock_entry; |
1181 | } | 1181 | } |
1182 | 1182 | ||
@@ -1189,7 +1189,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1189 | if (iomap_errp) | 1189 | if (iomap_errp) |
1190 | *iomap_errp = error; | 1190 | *iomap_errp = error; |
1191 | if (error) { | 1191 | if (error) { |
1192 | vmf_ret = dax_fault_return(error); | 1192 | ret = dax_fault_return(error); |
1193 | goto unlock_entry; | 1193 | goto unlock_entry; |
1194 | } | 1194 | } |
1195 | if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) { | 1195 | if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) { |
@@ -1219,9 +1219,9 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1219 | goto error_finish_iomap; | 1219 | goto error_finish_iomap; |
1220 | 1220 | ||
1221 | __SetPageUptodate(vmf->cow_page); | 1221 | __SetPageUptodate(vmf->cow_page); |
1222 | vmf_ret = finish_fault(vmf); | 1222 | ret = finish_fault(vmf); |
1223 | if (!vmf_ret) | 1223 | if (!ret) |
1224 | vmf_ret = VM_FAULT_DONE_COW; | 1224 | ret = VM_FAULT_DONE_COW; |
1225 | goto finish_iomap; | 1225 | goto finish_iomap; |
1226 | } | 1226 | } |
1227 | 1227 | ||
@@ -1257,23 +1257,20 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1257 | goto error_finish_iomap; | 1257 | goto error_finish_iomap; |
1258 | } | 1258 | } |
1259 | *pfnp = pfn; | 1259 | *pfnp = pfn; |
1260 | vmf_ret = VM_FAULT_NEEDDSYNC | major; | 1260 | ret = VM_FAULT_NEEDDSYNC | major; |
1261 | goto finish_iomap; | 1261 | goto finish_iomap; |
1262 | } | 1262 | } |
1263 | trace_dax_insert_mapping(inode, vmf, entry); | 1263 | trace_dax_insert_mapping(inode, vmf, entry); |
1264 | if (write) | 1264 | if (write) |
1265 | error = vm_insert_mixed_mkwrite(vma, vaddr, pfn); | 1265 | ret = vmf_insert_mixed_mkwrite(vma, vaddr, pfn); |
1266 | else | 1266 | else |
1267 | error = vm_insert_mixed(vma, vaddr, pfn); | 1267 | ret = vmf_insert_mixed(vma, vaddr, pfn); |
1268 | 1268 | ||
1269 | /* -EBUSY is fine, somebody else faulted on the same PTE */ | 1269 | goto finish_iomap; |
1270 | if (error == -EBUSY) | ||
1271 | error = 0; | ||
1272 | break; | ||
1273 | case IOMAP_UNWRITTEN: | 1270 | case IOMAP_UNWRITTEN: |
1274 | case IOMAP_HOLE: | 1271 | case IOMAP_HOLE: |
1275 | if (!write) { | 1272 | if (!write) { |
1276 | vmf_ret = dax_load_hole(mapping, entry, vmf); | 1273 | ret = dax_load_hole(mapping, entry, vmf); |
1277 | goto finish_iomap; | 1274 | goto finish_iomap; |
1278 | } | 1275 | } |
1279 | /*FALLTHRU*/ | 1276 | /*FALLTHRU*/ |
@@ -1284,12 +1281,12 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1284 | } | 1281 | } |
1285 | 1282 | ||
1286 | error_finish_iomap: | 1283 | error_finish_iomap: |
1287 | vmf_ret = dax_fault_return(error) | major; | 1284 | ret = dax_fault_return(error); |
1288 | finish_iomap: | 1285 | finish_iomap: |
1289 | if (ops->iomap_end) { | 1286 | if (ops->iomap_end) { |
1290 | int copied = PAGE_SIZE; | 1287 | int copied = PAGE_SIZE; |
1291 | 1288 | ||
1292 | if (vmf_ret & VM_FAULT_ERROR) | 1289 | if (ret & VM_FAULT_ERROR) |
1293 | copied = 0; | 1290 | copied = 0; |
1294 | /* | 1291 | /* |
1295 | * The fault is done by now and there's no way back (other | 1292 | * The fault is done by now and there's no way back (other |
@@ -1302,12 +1299,12 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1302 | unlock_entry: | 1299 | unlock_entry: |
1303 | put_locked_mapping_entry(mapping, vmf->pgoff); | 1300 | put_locked_mapping_entry(mapping, vmf->pgoff); |
1304 | out: | 1301 | out: |
1305 | trace_dax_pte_fault_done(inode, vmf, vmf_ret); | 1302 | trace_dax_pte_fault_done(inode, vmf, ret); |
1306 | return vmf_ret; | 1303 | return ret | major; |
1307 | } | 1304 | } |
1308 | 1305 | ||
1309 | #ifdef CONFIG_FS_DAX_PMD | 1306 | #ifdef CONFIG_FS_DAX_PMD |
1310 | static int dax_pmd_load_hole(struct vm_fault *vmf, struct iomap *iomap, | 1307 | static vm_fault_t dax_pmd_load_hole(struct vm_fault *vmf, struct iomap *iomap, |
1311 | void *entry) | 1308 | void *entry) |
1312 | { | 1309 | { |
1313 | struct address_space *mapping = vmf->vma->vm_file->f_mapping; | 1310 | struct address_space *mapping = vmf->vma->vm_file->f_mapping; |
@@ -1348,7 +1345,7 @@ fallback: | |||
1348 | return VM_FAULT_FALLBACK; | 1345 | return VM_FAULT_FALLBACK; |
1349 | } | 1346 | } |
1350 | 1347 | ||
1351 | static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, | 1348 | static vm_fault_t dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, |
1352 | const struct iomap_ops *ops) | 1349 | const struct iomap_ops *ops) |
1353 | { | 1350 | { |
1354 | struct vm_area_struct *vma = vmf->vma; | 1351 | struct vm_area_struct *vma = vmf->vma; |
@@ -1358,7 +1355,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1358 | bool sync; | 1355 | bool sync; |
1359 | unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT; | 1356 | unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT; |
1360 | struct inode *inode = mapping->host; | 1357 | struct inode *inode = mapping->host; |
1361 | int result = VM_FAULT_FALLBACK; | 1358 | vm_fault_t result = VM_FAULT_FALLBACK; |
1362 | struct iomap iomap = { 0 }; | 1359 | struct iomap iomap = { 0 }; |
1363 | pgoff_t max_pgoff, pgoff; | 1360 | pgoff_t max_pgoff, pgoff; |
1364 | void *entry; | 1361 | void *entry; |
@@ -1509,7 +1506,7 @@ out: | |||
1509 | return result; | 1506 | return result; |
1510 | } | 1507 | } |
1511 | #else | 1508 | #else |
1512 | static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, | 1509 | static vm_fault_t dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, |
1513 | const struct iomap_ops *ops) | 1510 | const struct iomap_ops *ops) |
1514 | { | 1511 | { |
1515 | return VM_FAULT_FALLBACK; | 1512 | return VM_FAULT_FALLBACK; |
@@ -1529,7 +1526,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, | |||
1529 | * has done all the necessary locking for page fault to proceed | 1526 | * has done all the necessary locking for page fault to proceed |
1530 | * successfully. | 1527 | * successfully. |
1531 | */ | 1528 | */ |
1532 | int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, | 1529 | vm_fault_t dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, |
1533 | pfn_t *pfnp, int *iomap_errp, const struct iomap_ops *ops) | 1530 | pfn_t *pfnp, int *iomap_errp, const struct iomap_ops *ops) |
1534 | { | 1531 | { |
1535 | switch (pe_size) { | 1532 | switch (pe_size) { |
@@ -1553,14 +1550,14 @@ EXPORT_SYMBOL_GPL(dax_iomap_fault); | |||
1553 | * DAX file. It takes care of marking corresponding radix tree entry as dirty | 1550 | * DAX file. It takes care of marking corresponding radix tree entry as dirty |
1554 | * as well. | 1551 | * as well. |
1555 | */ | 1552 | */ |
1556 | static int dax_insert_pfn_mkwrite(struct vm_fault *vmf, | 1553 | static vm_fault_t dax_insert_pfn_mkwrite(struct vm_fault *vmf, |
1557 | enum page_entry_size pe_size, | 1554 | enum page_entry_size pe_size, |
1558 | pfn_t pfn) | 1555 | pfn_t pfn) |
1559 | { | 1556 | { |
1560 | struct address_space *mapping = vmf->vma->vm_file->f_mapping; | 1557 | struct address_space *mapping = vmf->vma->vm_file->f_mapping; |
1561 | void *entry, **slot; | 1558 | void *entry, **slot; |
1562 | pgoff_t index = vmf->pgoff; | 1559 | pgoff_t index = vmf->pgoff; |
1563 | int vmf_ret, error; | 1560 | vm_fault_t ret; |
1564 | 1561 | ||
1565 | xa_lock_irq(&mapping->i_pages); | 1562 | xa_lock_irq(&mapping->i_pages); |
1566 | entry = get_unlocked_mapping_entry(mapping, index, &slot); | 1563 | entry = get_unlocked_mapping_entry(mapping, index, &slot); |
@@ -1579,21 +1576,20 @@ static int dax_insert_pfn_mkwrite(struct vm_fault *vmf, | |||
1579 | xa_unlock_irq(&mapping->i_pages); | 1576 | xa_unlock_irq(&mapping->i_pages); |
1580 | switch (pe_size) { | 1577 | switch (pe_size) { |
1581 | case PE_SIZE_PTE: | 1578 | case PE_SIZE_PTE: |
1582 | error = vm_insert_mixed_mkwrite(vmf->vma, vmf->address, pfn); | 1579 | ret = vmf_insert_mixed_mkwrite(vmf->vma, vmf->address, pfn); |
1583 | vmf_ret = dax_fault_return(error); | ||
1584 | break; | 1580 | break; |
1585 | #ifdef CONFIG_FS_DAX_PMD | 1581 | #ifdef CONFIG_FS_DAX_PMD |
1586 | case PE_SIZE_PMD: | 1582 | case PE_SIZE_PMD: |
1587 | vmf_ret = vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, | 1583 | ret = vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, |
1588 | pfn, true); | 1584 | pfn, true); |
1589 | break; | 1585 | break; |
1590 | #endif | 1586 | #endif |
1591 | default: | 1587 | default: |
1592 | vmf_ret = VM_FAULT_FALLBACK; | 1588 | ret = VM_FAULT_FALLBACK; |
1593 | } | 1589 | } |
1594 | put_locked_mapping_entry(mapping, index); | 1590 | put_locked_mapping_entry(mapping, index); |
1595 | trace_dax_insert_pfn_mkwrite(mapping->host, vmf, vmf_ret); | 1591 | trace_dax_insert_pfn_mkwrite(mapping->host, vmf, ret); |
1596 | return vmf_ret; | 1592 | return ret; |
1597 | } | 1593 | } |
1598 | 1594 | ||
1599 | /** | 1595 | /** |
@@ -1606,8 +1602,8 @@ static int dax_insert_pfn_mkwrite(struct vm_fault *vmf, | |||
1606 | * stored persistently on the media and handles inserting of appropriate page | 1602 | * stored persistently on the media and handles inserting of appropriate page |
1607 | * table entry. | 1603 | * table entry. |
1608 | */ | 1604 | */ |
1609 | int dax_finish_sync_fault(struct vm_fault *vmf, enum page_entry_size pe_size, | 1605 | vm_fault_t dax_finish_sync_fault(struct vm_fault *vmf, |
1610 | pfn_t pfn) | 1606 | enum page_entry_size pe_size, pfn_t pfn) |
1611 | { | 1607 | { |
1612 | int err; | 1608 | int err; |
1613 | loff_t start = ((loff_t)vmf->pgoff) << PAGE_SHIFT; | 1609 | loff_t start = ((loff_t)vmf->pgoff) << PAGE_SHIFT; |