|
28 | 28 | #include <linux/mm.h> |
29 | 29 | #include <linux/pagemap.h> |
30 | 30 | #include <linux/gfp.h> |
| 31 | +#include <linux/rmap.h> |
31 | 32 | #include <linux/swap.h> |
32 | 33 | #include <linux/compaction.h> |
33 | 34 |
|
@@ -280,6 +281,37 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
280 | 281 | } |
281 | 282 | EXPORT_SYMBOL_GPL(nfs_file_fsync); |
282 | 283 |
|
| 284 | +void nfs_truncate_last_folio(struct address_space *mapping, loff_t from, |
| 285 | + loff_t to) |
| 286 | +{ |
| 287 | + struct folio *folio; |
| 288 | + |
| 289 | + if (from >= to) |
| 290 | + return; |
| 291 | + |
| 292 | + folio = filemap_lock_folio(mapping, from >> PAGE_SHIFT); |
| 293 | + if (IS_ERR(folio)) |
| 294 | + return; |
| 295 | + |
| 296 | + if (folio_mkclean(folio)) |
| 297 | + folio_mark_dirty(folio); |
| 298 | + |
| 299 | + if (folio_test_uptodate(folio)) { |
| 300 | + loff_t fpos = folio_pos(folio); |
| 301 | + size_t offset = from - fpos; |
| 302 | + size_t end = folio_size(folio); |
| 303 | + |
| 304 | + if (to - fpos < end) |
| 305 | + end = to - fpos; |
| 306 | + folio_zero_segment(folio, offset, end); |
| 307 | + trace_nfs_size_truncate_folio(mapping->host, to); |
| 308 | + } |
| 309 | + |
| 310 | + folio_unlock(folio); |
| 311 | + folio_put(folio); |
| 312 | +} |
| 313 | +EXPORT_SYMBOL_GPL(nfs_truncate_last_folio); |
| 314 | + |
283 | 315 | /* |
284 | 316 | * Decide whether a read/modify/write cycle may be more efficient |
285 | 317 | * then a modify/write/read cycle when writing to a page in the |
@@ -356,6 +388,7 @@ static int nfs_write_begin(const struct kiocb *iocb, |
356 | 388 |
|
357 | 389 | dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n", |
358 | 390 | file, mapping->host->i_ino, len, (long long) pos); |
| 391 | + nfs_truncate_last_folio(mapping, i_size_read(mapping->host), pos); |
359 | 392 |
|
360 | 393 | fgp |= fgf_set_order(len); |
361 | 394 | start: |
@@ -442,10 +475,11 @@ static void nfs_invalidate_folio(struct folio *folio, size_t offset, |
442 | 475 | dfprintk(PAGECACHE, "NFS: invalidate_folio(%lu, %zu, %zu)\n", |
443 | 476 | folio->index, offset, length); |
444 | 477 |
|
445 | | - if (offset != 0 || length < folio_size(folio)) |
446 | | - return; |
447 | 478 | /* Cancel any unstarted writes on this page */ |
448 | | - nfs_wb_folio_cancel(inode, folio); |
| 479 | + if (offset != 0 || length < folio_size(folio)) |
| 480 | + nfs_wb_folio(inode, folio); |
| 481 | + else |
| 482 | + nfs_wb_folio_cancel(inode, folio); |
449 | 483 | folio_wait_private_2(folio); /* [DEPRECATED] */ |
450 | 484 | trace_nfs_invalidate_folio(inode, folio_pos(folio) + offset, length); |
451 | 485 | } |
|
0 commit comments