aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dax.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2017-11-01 11:36:42 -0400
committerDan Williams <dan.j.williams@intel.com>2017-11-03 09:26:25 -0400
commitcaa51d26f85c248f1c4f43a870ad3ef84bf9eb8f (patch)
tree1949315570cf10dc95ebf1dde715cc1abaf81a2f /fs/dax.c
parentb6fb293f2497a9841d94f6b57bd2bb2cd222da43 (diff)
dax, iomap: Add support for synchronous faults
Add a flag to iomap interface informing the caller that inode needs fdstasync(2) for returned extent to become persistent and use it in DAX fault code so that we don't map such extents into page tables immediately. Instead we propagate the information that fdatasync(2) is necessary from dax_iomap_fault() with a new VM_FAULT_NEEDDSYNC flag. Filesystem fault handler is then responsible for calling fdatasync(2) and inserting pfn into page tables. Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'fs/dax.c')
-rw-r--r--fs/dax.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/fs/dax.c b/fs/dax.c
index efc210ff6665..bb9ff907738c 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1091,6 +1091,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp,
1091 unsigned flags = IOMAP_FAULT; 1091 unsigned flags = IOMAP_FAULT;
1092 int error, major = 0; 1092 int error, major = 0;
1093 bool write = vmf->flags & FAULT_FLAG_WRITE; 1093 bool write = vmf->flags & FAULT_FLAG_WRITE;
1094 bool sync;
1094 int vmf_ret = 0; 1095 int vmf_ret = 0;
1095 void *entry; 1096 void *entry;
1096 pfn_t pfn; 1097 pfn_t pfn;
@@ -1169,6 +1170,8 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp,
1169 goto finish_iomap; 1170 goto finish_iomap;
1170 } 1171 }
1171 1172
1173 sync = (vma->vm_flags & VM_SYNC) && (iomap.flags & IOMAP_F_DIRTY);
1174
1172 switch (iomap.type) { 1175 switch (iomap.type) {
1173 case IOMAP_MAPPED: 1176 case IOMAP_MAPPED:
1174 if (iomap.flags & IOMAP_F_NEW) { 1177 if (iomap.flags & IOMAP_F_NEW) {
@@ -1182,12 +1185,27 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp,
1182 1185
1183 entry = dax_insert_mapping_entry(mapping, vmf, entry, 1186 entry = dax_insert_mapping_entry(mapping, vmf, entry,
1184 dax_iomap_sector(&iomap, pos), 1187 dax_iomap_sector(&iomap, pos),
1185 0, write); 1188 0, write && !sync);
1186 if (IS_ERR(entry)) { 1189 if (IS_ERR(entry)) {
1187 error = PTR_ERR(entry); 1190 error = PTR_ERR(entry);
1188 goto error_finish_iomap; 1191 goto error_finish_iomap;
1189 } 1192 }
1190 1193
1194 /*
1195 * If we are doing synchronous page fault and inode needs fsync,
1196 * we can insert PTE into page tables only after that happens.
1197 * Skip insertion for now and return the pfn so that caller can
1198 * insert it after fsync is done.
1199 */
1200 if (sync) {
1201 if (WARN_ON_ONCE(!pfnp)) {
1202 error = -EIO;
1203 goto error_finish_iomap;
1204 }
1205 *pfnp = pfn;
1206 vmf_ret = VM_FAULT_NEEDDSYNC | major;
1207 goto finish_iomap;
1208 }
1191 trace_dax_insert_mapping(inode, vmf, entry); 1209 trace_dax_insert_mapping(inode, vmf, entry);
1192 if (write) 1210 if (write)
1193 error = vm_insert_mixed_mkwrite(vma, vaddr, pfn); 1211 error = vm_insert_mixed_mkwrite(vma, vaddr, pfn);
@@ -1287,6 +1305,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp,
1287 struct address_space *mapping = vma->vm_file->f_mapping; 1305 struct address_space *mapping = vma->vm_file->f_mapping;
1288 unsigned long pmd_addr = vmf->address & PMD_MASK; 1306 unsigned long pmd_addr = vmf->address & PMD_MASK;
1289 bool write = vmf->flags & FAULT_FLAG_WRITE; 1307 bool write = vmf->flags & FAULT_FLAG_WRITE;
1308 bool sync;
1290 unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT; 1309 unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT;
1291 struct inode *inode = mapping->host; 1310 struct inode *inode = mapping->host;
1292 int result = VM_FAULT_FALLBACK; 1311 int result = VM_FAULT_FALLBACK;
@@ -1371,6 +1390,8 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp,
1371 if (iomap.offset + iomap.length < pos + PMD_SIZE) 1390 if (iomap.offset + iomap.length < pos + PMD_SIZE)
1372 goto finish_iomap; 1391 goto finish_iomap;
1373 1392
1393 sync = (vma->vm_flags & VM_SYNC) && (iomap.flags & IOMAP_F_DIRTY);
1394
1374 switch (iomap.type) { 1395 switch (iomap.type) {
1375 case IOMAP_MAPPED: 1396 case IOMAP_MAPPED:
1376 error = dax_iomap_pfn(&iomap, pos, PMD_SIZE, &pfn); 1397 error = dax_iomap_pfn(&iomap, pos, PMD_SIZE, &pfn);
@@ -1379,10 +1400,24 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp,
1379 1400
1380 entry = dax_insert_mapping_entry(mapping, vmf, entry, 1401 entry = dax_insert_mapping_entry(mapping, vmf, entry,
1381 dax_iomap_sector(&iomap, pos), 1402 dax_iomap_sector(&iomap, pos),
1382 RADIX_DAX_PMD, write); 1403 RADIX_DAX_PMD, write && !sync);
1383 if (IS_ERR(entry)) 1404 if (IS_ERR(entry))
1384 goto finish_iomap; 1405 goto finish_iomap;
1385 1406
1407 /*
1408 * If we are doing synchronous page fault and inode needs fsync,
1409 * we can insert PMD into page tables only after that happens.
1410 * Skip insertion for now and return the pfn so that caller can
1411 * insert it after fsync is done.
1412 */
1413 if (sync) {
1414 if (WARN_ON_ONCE(!pfnp))
1415 goto finish_iomap;
1416 *pfnp = pfn;
1417 result = VM_FAULT_NEEDDSYNC;
1418 goto finish_iomap;
1419 }
1420
1386 trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, entry); 1421 trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, entry);
1387 result = vmf_insert_pfn_pmd(vma, vmf->address, vmf->pmd, pfn, 1422 result = vmf_insert_pfn_pmd(vma, vmf->address, vmf->pmd, pfn,
1388 write); 1423 write);