Ensure we call unmap_mapping_range() and sync dirty pages to disk before doing an NFS direct write. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Unified · Split
| @@ -678,15 +678,9 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t · 677 unmodified lines | ||
| 678 | 678 | if (!count) |
| 679 | 679 | goto out; |
| 680 | 680 | |
| 681 | − if (mapping->nrpages) { | |
| 682 | − retval = filemap_fdatawrite(mapping); | |
| 683 | − if (retval == 0) | |
| 684 | − retval = nfs_wb_all(inode); | |
| 685 | − if (retval == 0) | |
| 686 | − retval = filemap_fdatawait(mapping); | |
| 687 | − if (retval) | |
| 688 | − goto out; | |
| 689 | − } | |
| 681 | + retval = nfs_sync_mapping(mapping); | |
| 682 | + if (retval) | |
| 683 | + goto out; | |
| 690 | 684 | |
| 691 | 685 | retval = nfs_direct_read(inode, ctx, &iov, pos, 1); |
| 692 | 686 | if (retval > 0) |
| @@ -764,15 +758,9 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, · 71 unmodified lines | ||
| 764 | 758 | if (!count) |
| 765 | 759 | goto out; |
| 766 | 760 | |
| 767 | − if (mapping->nrpages) { | |
| 768 | − retval = filemap_fdatawrite(mapping); | |
| 769 | − if (retval == 0) | |
| 770 | − retval = nfs_wb_all(inode); | |
| 771 | − if (retval == 0) | |
| 772 | − retval = filemap_fdatawait(mapping); | |
| 773 | − if (retval) | |
| 774 | − goto out; | |
| 775 | − } | |
| 761 | + retval = nfs_sync_mapping(mapping); | |
| 762 | + if (retval) | |
| 763 | + goto out; | |
| 776 | 764 | |
| 777 | 765 | retval = nfs_direct_write(inode, ctx, &iov, pos, 1); |
| 778 | 766 | if (mapping->nrpages) |
| @@ -433,11 +433,7 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) · 432 unmodified lines | ||
| 433 | 433 | * Flush all pending writes before doing anything |
| 434 | 434 | * with locks.. |
| 435 | 435 | */ |
| 436 | − filemap_fdatawrite(filp->f_mapping); | |
| 437 | − down(&inode->i_sem); | |
| 438 | − nfs_wb_all(inode); | |
| 439 | − up(&inode->i_sem); | |
| 440 | − filemap_fdatawait(filp->f_mapping); | |
| 436 | + nfs_sync_mapping(filp->f_mapping); | |
| 441 | 437 | |
| 442 | 438 | /* NOTE: special case |
| 443 | 439 | * If we're signalled while cleaning up locks on process exit, we |
| @@ -465,15 +461,8 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) · 21 unmodified lines | ||
| 465 | 461 | * Flush all pending writes before doing anything |
| 466 | 462 | * with locks.. |
| 467 | 463 | */ |
| 468 | − status = filemap_fdatawrite(filp->f_mapping); | |
| 469 | − if (status == 0) { | |
| 470 | − down(&inode->i_sem); | |
| 471 | − status = nfs_wb_all(inode); | |
| 472 | − up(&inode->i_sem); | |
| 473 | − if (status == 0) | |
| 474 | − status = filemap_fdatawait(filp->f_mapping); | |
| 475 | − } | |
| 476 | − if (status < 0) | |
| 464 | + status = nfs_sync_mapping(filp->f_mapping); | |
| 465 | + if (status != 0) | |
| 477 | 466 | goto out; |
| 478 | 467 | |
| 479 | 468 | lock_kernel(); |
| @@ -497,11 +486,7 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) · 17 unmodified lines | ||
| 497 | 486 | * Make sure we clear the cache whenever we try to get the lock. |
| 498 | 487 | * This makes locking act as a cache coherency point. |
| 499 | 488 | */ |
| 500 | − filemap_fdatawrite(filp->f_mapping); | |
| 501 | − down(&inode->i_sem); | |
| 502 | − nfs_wb_all(inode); /* we may have slept */ | |
| 503 | − up(&inode->i_sem); | |
| 504 | − filemap_fdatawait(filp->f_mapping); | |
| 489 | + nfs_sync_mapping(filp->f_mapping); | |
| 505 | 490 | nfs_zap_caches(inode); |
| 506 | 491 | out: |
| 507 | 492 | rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset); |
| @@ -640,6 +640,27 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) · 639 unmodified lines | ||
| 640 | 640 | return 0; |
| 641 | 641 | } |
| 642 | 642 | |
| 643 | +/** | |
| 644 | + * nfs_sync_mapping - helper to flush all mmapped dirty data to disk | |
| 645 | + */ | |
| 646 | +int nfs_sync_mapping(struct address_space *mapping) | |
| 647 | +{ | |
| 648 | + int ret; | |
| 649 | + | |
| 650 | + if (mapping->nrpages == 0) | |
| 651 | + return 0; | |
| 652 | + unmap_mapping_range(mapping, 0, 0, 0); | |
| 653 | + ret = filemap_fdatawrite(mapping); | |
| 654 | + if (ret != 0) | |
| 655 | + goto out; | |
| 656 | + ret = filemap_fdatawait(mapping); | |
| 657 | + if (ret != 0) | |
| 658 | + goto out; | |
| 659 | + ret = nfs_wb_all(mapping->host); | |
| 660 | +out: | |
| 661 | + return ret; | |
| 662 | +} | |
| 663 | + | |
| 643 | 664 | /* |
| 644 | 665 | * Invalidate the local caches |
| 645 | 666 | */ |
| @@ -1179,11 +1200,8 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) · 533 unmodified lines | ||
| 1179 | 1200 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1180 | 1201 | |
| 1181 | 1202 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
| 1182 | − if (S_ISREG(inode->i_mode)) { | |
| 1183 | − if (filemap_fdatawrite(mapping) == 0) | |
| 1184 | − filemap_fdatawait(mapping); | |
| 1185 | − nfs_wb_all(inode); | |
| 1186 | − } | |
| 1203 | + if (S_ISREG(inode->i_mode)) | |
| 1204 | + nfs_sync_mapping(mapping); | |
| 1187 | 1205 | invalidate_inode_pages2(mapping); |
| 1188 | 1206 | |
| 1189 | 1207 | spin_lock(&inode->i_lock); |
| @@ -291,6 +291,7 @@ static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long · 290 unmodified lines | ||
| 291 | 291 | /* |
| 292 | 292 | * linux/fs/nfs/inode.c |
| 293 | 293 | */ |
| 294 | +extern int nfs_sync_mapping(struct address_space *mapping); | |
| 294 | 295 | extern void nfs_zap_caches(struct inode *); |
| 295 | 296 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, |
| 296 | 297 | struct nfs_fattr *); |