diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 86 |
1 files changed, 61 insertions, 25 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 05bf3c0dc751..e756075637b0 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "internal.h" | 36 | #include "internal.h" |
37 | #include "iostat.h" | 37 | #include "iostat.h" |
38 | #include "fscache.h" | 38 | #include "fscache.h" |
39 | #include "pnfs.h" | ||
39 | 40 | ||
40 | #define NFSDBG_FACILITY NFSDBG_FILE | 41 | #define NFSDBG_FACILITY NFSDBG_FILE |
41 | 42 | ||
@@ -386,6 +387,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
386 | file->f_path.dentry->d_name.name, | 387 | file->f_path.dentry->d_name.name, |
387 | mapping->host->i_ino, len, (long long) pos); | 388 | mapping->host->i_ino, len, (long long) pos); |
388 | 389 | ||
390 | pnfs_update_layout(mapping->host, | ||
391 | nfs_file_open_context(file), | ||
392 | IOMODE_RW); | ||
393 | |||
389 | start: | 394 | start: |
390 | /* | 395 | /* |
391 | * Prevent starvation issues if someone is doing a consistency | 396 | * Prevent starvation issues if someone is doing a consistency |
@@ -551,7 +556,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
551 | struct file *filp = vma->vm_file; | 556 | struct file *filp = vma->vm_file; |
552 | struct dentry *dentry = filp->f_path.dentry; | 557 | struct dentry *dentry = filp->f_path.dentry; |
553 | unsigned pagelen; | 558 | unsigned pagelen; |
554 | int ret = -EINVAL; | 559 | int ret = VM_FAULT_NOPAGE; |
555 | struct address_space *mapping; | 560 | struct address_space *mapping; |
556 | 561 | ||
557 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", | 562 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", |
@@ -567,21 +572,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
567 | if (mapping != dentry->d_inode->i_mapping) | 572 | if (mapping != dentry->d_inode->i_mapping) |
568 | goto out_unlock; | 573 | goto out_unlock; |
569 | 574 | ||
570 | ret = 0; | ||
571 | pagelen = nfs_page_length(page); | 575 | pagelen = nfs_page_length(page); |
572 | if (pagelen == 0) | 576 | if (pagelen == 0) |
573 | goto out_unlock; | 577 | goto out_unlock; |
574 | 578 | ||
575 | ret = nfs_flush_incompatible(filp, page); | 579 | ret = VM_FAULT_LOCKED; |
576 | if (ret != 0) | 580 | if (nfs_flush_incompatible(filp, page) == 0 && |
577 | goto out_unlock; | 581 | nfs_updatepage(filp, page, 0, pagelen) == 0) |
582 | goto out; | ||
578 | 583 | ||
579 | ret = nfs_updatepage(filp, page, 0, pagelen); | 584 | ret = VM_FAULT_SIGBUS; |
580 | out_unlock: | 585 | out_unlock: |
581 | if (!ret) | ||
582 | return VM_FAULT_LOCKED; | ||
583 | unlock_page(page); | 586 | unlock_page(page); |
584 | return VM_FAULT_SIGBUS; | 587 | out: |
588 | return ret; | ||
585 | } | 589 | } |
586 | 590 | ||
587 | static const struct vm_operations_struct nfs_file_vm_ops = { | 591 | static const struct vm_operations_struct nfs_file_vm_ops = { |
@@ -684,7 +688,8 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
684 | return ret; | 688 | return ret; |
685 | } | 689 | } |
686 | 690 | ||
687 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 691 | static int |
692 | do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
688 | { | 693 | { |
689 | struct inode *inode = filp->f_mapping->host; | 694 | struct inode *inode = filp->f_mapping->host; |
690 | int status = 0; | 695 | int status = 0; |
@@ -699,7 +704,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
699 | if (nfs_have_delegation(inode, FMODE_READ)) | 704 | if (nfs_have_delegation(inode, FMODE_READ)) |
700 | goto out_noconflict; | 705 | goto out_noconflict; |
701 | 706 | ||
702 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | 707 | if (is_local) |
703 | goto out_noconflict; | 708 | goto out_noconflict; |
704 | 709 | ||
705 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 710 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
@@ -726,7 +731,8 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
726 | return res; | 731 | return res; |
727 | } | 732 | } |
728 | 733 | ||
729 | static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | 734 | static int |
735 | do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
730 | { | 736 | { |
731 | struct inode *inode = filp->f_mapping->host; | 737 | struct inode *inode = filp->f_mapping->host; |
732 | int status; | 738 | int status; |
@@ -741,15 +747,24 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | |||
741 | * If we're signalled while cleaning up locks on process exit, we | 747 | * If we're signalled while cleaning up locks on process exit, we |
742 | * still need to complete the unlock. | 748 | * still need to complete the unlock. |
743 | */ | 749 | */ |
744 | /* Use local locking if mounted with "-onolock" */ | 750 | /* |
745 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 751 | * Use local locking if mounted with "-onolock" or with appropriate |
752 | * "-olocal_lock=" | ||
753 | */ | ||
754 | if (!is_local) | ||
746 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 755 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
747 | else | 756 | else |
748 | status = do_vfs_lock(filp, fl); | 757 | status = do_vfs_lock(filp, fl); |
749 | return status; | 758 | return status; |
750 | } | 759 | } |
751 | 760 | ||
752 | static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | 761 | static int |
762 | is_time_granular(struct timespec *ts) { | ||
763 | return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000)); | ||
764 | } | ||
765 | |||
766 | static int | ||
767 | do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
753 | { | 768 | { |
754 | struct inode *inode = filp->f_mapping->host; | 769 | struct inode *inode = filp->f_mapping->host; |
755 | int status; | 770 | int status; |
@@ -762,20 +777,31 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
762 | if (status != 0) | 777 | if (status != 0) |
763 | goto out; | 778 | goto out; |
764 | 779 | ||
765 | /* Use local locking if mounted with "-onolock" */ | 780 | /* |
766 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 781 | * Use local locking if mounted with "-onolock" or with appropriate |
782 | * "-olocal_lock=" | ||
783 | */ | ||
784 | if (!is_local) | ||
767 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 785 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
768 | else | 786 | else |
769 | status = do_vfs_lock(filp, fl); | 787 | status = do_vfs_lock(filp, fl); |
770 | if (status < 0) | 788 | if (status < 0) |
771 | goto out; | 789 | goto out; |
790 | |||
772 | /* | 791 | /* |
773 | * Make sure we clear the cache whenever we try to get the lock. | 792 | * Revalidate the cache if the server has time stamps granular |
793 | * enough to detect subsecond changes. Otherwise, clear the | ||
794 | * cache to prevent missing any changes. | ||
795 | * | ||
774 | * This makes locking act as a cache coherency point. | 796 | * This makes locking act as a cache coherency point. |
775 | */ | 797 | */ |
776 | nfs_sync_mapping(filp->f_mapping); | 798 | nfs_sync_mapping(filp->f_mapping); |
777 | if (!nfs_have_delegation(inode, FMODE_READ)) | 799 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
778 | nfs_zap_caches(inode); | 800 | if (is_time_granular(&NFS_SERVER(inode)->time_delta)) |
801 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
802 | else | ||
803 | nfs_zap_caches(inode); | ||
804 | } | ||
779 | out: | 805 | out: |
780 | return status; | 806 | return status; |
781 | } | 807 | } |
@@ -787,6 +813,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
787 | { | 813 | { |
788 | struct inode *inode = filp->f_mapping->host; | 814 | struct inode *inode = filp->f_mapping->host; |
789 | int ret = -ENOLCK; | 815 | int ret = -ENOLCK; |
816 | int is_local = 0; | ||
790 | 817 | ||
791 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", | 818 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", |
792 | filp->f_path.dentry->d_parent->d_name.name, | 819 | filp->f_path.dentry->d_parent->d_name.name, |
@@ -800,6 +827,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
800 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | 827 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
801 | goto out_err; | 828 | goto out_err; |
802 | 829 | ||
830 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL) | ||
831 | is_local = 1; | ||
832 | |||
803 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { | 833 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { |
804 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); | 834 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); |
805 | if (ret < 0) | 835 | if (ret < 0) |
@@ -807,11 +837,11 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
807 | } | 837 | } |
808 | 838 | ||
809 | if (IS_GETLK(cmd)) | 839 | if (IS_GETLK(cmd)) |
810 | ret = do_getlk(filp, cmd, fl); | 840 | ret = do_getlk(filp, cmd, fl, is_local); |
811 | else if (fl->fl_type == F_UNLCK) | 841 | else if (fl->fl_type == F_UNLCK) |
812 | ret = do_unlk(filp, cmd, fl); | 842 | ret = do_unlk(filp, cmd, fl, is_local); |
813 | else | 843 | else |
814 | ret = do_setlk(filp, cmd, fl); | 844 | ret = do_setlk(filp, cmd, fl, is_local); |
815 | out_err: | 845 | out_err: |
816 | return ret; | 846 | return ret; |
817 | } | 847 | } |
@@ -821,6 +851,9 @@ out_err: | |||
821 | */ | 851 | */ |
822 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | 852 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) |
823 | { | 853 | { |
854 | struct inode *inode = filp->f_mapping->host; | ||
855 | int is_local = 0; | ||
856 | |||
824 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", | 857 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", |
825 | filp->f_path.dentry->d_parent->d_name.name, | 858 | filp->f_path.dentry->d_parent->d_name.name, |
826 | filp->f_path.dentry->d_name.name, | 859 | filp->f_path.dentry->d_name.name, |
@@ -829,14 +862,17 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
829 | if (!(fl->fl_flags & FL_FLOCK)) | 862 | if (!(fl->fl_flags & FL_FLOCK)) |
830 | return -ENOLCK; | 863 | return -ENOLCK; |
831 | 864 | ||
865 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK) | ||
866 | is_local = 1; | ||
867 | |||
832 | /* We're simulating flock() locks using posix locks on the server */ | 868 | /* We're simulating flock() locks using posix locks on the server */ |
833 | fl->fl_owner = (fl_owner_t)filp; | 869 | fl->fl_owner = (fl_owner_t)filp; |
834 | fl->fl_start = 0; | 870 | fl->fl_start = 0; |
835 | fl->fl_end = OFFSET_MAX; | 871 | fl->fl_end = OFFSET_MAX; |
836 | 872 | ||
837 | if (fl->fl_type == F_UNLCK) | 873 | if (fl->fl_type == F_UNLCK) |
838 | return do_unlk(filp, cmd, fl); | 874 | return do_unlk(filp, cmd, fl, is_local); |
839 | return do_setlk(filp, cmd, fl); | 875 | return do_setlk(filp, cmd, fl, is_local); |
840 | } | 876 | } |
841 | 877 | ||
842 | /* | 878 | /* |