diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 16:48:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 16:48:29 -0400 |
commit | 74eb94b218d087798a52c0b4f1379b635287a4b8 (patch) | |
tree | 4e467c3014c2b1169f6f71d88cf5d1598f3ce28e /fs/nfs/file.c | |
parent | 7b6181e06841f5ad15c4ff708b967b4db65a64de (diff) | |
parent | 9a84d38031c258a17bb39beed1e500eadee67407 (diff) |
Merge branch 'nfs-for-2.6.37' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'nfs-for-2.6.37' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (67 commits)
SUNRPC: Cleanup duplicate assignment in rpcauth_refreshcred
nfs: fix unchecked value
Ask for time_delta during fsinfo probe
Revalidate caches on lock
SUNRPC: After calling xprt_release(), we must restart from call_reserve
NFSv4: Fix up the 'dircount' hint in encode_readdir
NFSv4: Clean up nfs4_decode_dirent
NFSv4: nfs4_decode_dirent must clear entry->fattr->valid
NFSv4: Fix a regression in decode_getfattr
NFSv4: Fix up decode_attr_filehandle() to handle the case of empty fh pointer
NFS: Ensure we check all allocation return values in new readdir code
NFS: Readdir plus in v4
NFS: introduce generic decode_getattr function
NFS: check xdr_decode for errors
NFS: nfs_readdir_filler catch all errors
NFS: readdir with vmapped pages
NFS: remove page size checking code
NFS: decode_dirent should use an xdr_stream
SUNRPC: Add a helper function xdr_inline_peek
NFS: remove readdir plus limit
...
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 81 |
1 files changed, 56 insertions, 25 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 05bf3c0dc751..e18c31e08a28 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -551,7 +551,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
551 | struct file *filp = vma->vm_file; | 551 | struct file *filp = vma->vm_file; |
552 | struct dentry *dentry = filp->f_path.dentry; | 552 | struct dentry *dentry = filp->f_path.dentry; |
553 | unsigned pagelen; | 553 | unsigned pagelen; |
554 | int ret = -EINVAL; | 554 | int ret = VM_FAULT_NOPAGE; |
555 | struct address_space *mapping; | 555 | struct address_space *mapping; |
556 | 556 | ||
557 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", | 557 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", |
@@ -567,21 +567,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
567 | if (mapping != dentry->d_inode->i_mapping) | 567 | if (mapping != dentry->d_inode->i_mapping) |
568 | goto out_unlock; | 568 | goto out_unlock; |
569 | 569 | ||
570 | ret = 0; | ||
571 | pagelen = nfs_page_length(page); | 570 | pagelen = nfs_page_length(page); |
572 | if (pagelen == 0) | 571 | if (pagelen == 0) |
573 | goto out_unlock; | 572 | goto out_unlock; |
574 | 573 | ||
575 | ret = nfs_flush_incompatible(filp, page); | 574 | ret = VM_FAULT_LOCKED; |
576 | if (ret != 0) | 575 | if (nfs_flush_incompatible(filp, page) == 0 && |
577 | goto out_unlock; | 576 | nfs_updatepage(filp, page, 0, pagelen) == 0) |
577 | goto out; | ||
578 | 578 | ||
579 | ret = nfs_updatepage(filp, page, 0, pagelen); | 579 | ret = VM_FAULT_SIGBUS; |
580 | out_unlock: | 580 | out_unlock: |
581 | if (!ret) | ||
582 | return VM_FAULT_LOCKED; | ||
583 | unlock_page(page); | 581 | unlock_page(page); |
584 | return VM_FAULT_SIGBUS; | 582 | out: |
583 | return ret; | ||
585 | } | 584 | } |
586 | 585 | ||
587 | static const struct vm_operations_struct nfs_file_vm_ops = { | 586 | static const struct vm_operations_struct nfs_file_vm_ops = { |
@@ -684,7 +683,8 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
684 | return ret; | 683 | return ret; |
685 | } | 684 | } |
686 | 685 | ||
687 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 686 | static int |
687 | do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
688 | { | 688 | { |
689 | struct inode *inode = filp->f_mapping->host; | 689 | struct inode *inode = filp->f_mapping->host; |
690 | int status = 0; | 690 | int status = 0; |
@@ -699,7 +699,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
699 | if (nfs_have_delegation(inode, FMODE_READ)) | 699 | if (nfs_have_delegation(inode, FMODE_READ)) |
700 | goto out_noconflict; | 700 | goto out_noconflict; |
701 | 701 | ||
702 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | 702 | if (is_local) |
703 | goto out_noconflict; | 703 | goto out_noconflict; |
704 | 704 | ||
705 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 705 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
@@ -726,7 +726,8 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
726 | return res; | 726 | return res; |
727 | } | 727 | } |
728 | 728 | ||
729 | static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | 729 | static int |
730 | do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
730 | { | 731 | { |
731 | struct inode *inode = filp->f_mapping->host; | 732 | struct inode *inode = filp->f_mapping->host; |
732 | int status; | 733 | int status; |
@@ -741,15 +742,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 | 742 | * If we're signalled while cleaning up locks on process exit, we |
742 | * still need to complete the unlock. | 743 | * still need to complete the unlock. |
743 | */ | 744 | */ |
744 | /* Use local locking if mounted with "-onolock" */ | 745 | /* |
745 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 746 | * Use local locking if mounted with "-onolock" or with appropriate |
747 | * "-olocal_lock=" | ||
748 | */ | ||
749 | if (!is_local) | ||
746 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 750 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
747 | else | 751 | else |
748 | status = do_vfs_lock(filp, fl); | 752 | status = do_vfs_lock(filp, fl); |
749 | return status; | 753 | return status; |
750 | } | 754 | } |
751 | 755 | ||
752 | static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | 756 | static int |
757 | is_time_granular(struct timespec *ts) { | ||
758 | return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000)); | ||
759 | } | ||
760 | |||
761 | static int | ||
762 | do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
753 | { | 763 | { |
754 | struct inode *inode = filp->f_mapping->host; | 764 | struct inode *inode = filp->f_mapping->host; |
755 | int status; | 765 | int status; |
@@ -762,20 +772,31 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
762 | if (status != 0) | 772 | if (status != 0) |
763 | goto out; | 773 | goto out; |
764 | 774 | ||
765 | /* Use local locking if mounted with "-onolock" */ | 775 | /* |
766 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 776 | * Use local locking if mounted with "-onolock" or with appropriate |
777 | * "-olocal_lock=" | ||
778 | */ | ||
779 | if (!is_local) | ||
767 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 780 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
768 | else | 781 | else |
769 | status = do_vfs_lock(filp, fl); | 782 | status = do_vfs_lock(filp, fl); |
770 | if (status < 0) | 783 | if (status < 0) |
771 | goto out; | 784 | goto out; |
785 | |||
772 | /* | 786 | /* |
773 | * Make sure we clear the cache whenever we try to get the lock. | 787 | * Revalidate the cache if the server has time stamps granular |
788 | * enough to detect subsecond changes. Otherwise, clear the | ||
789 | * cache to prevent missing any changes. | ||
790 | * | ||
774 | * This makes locking act as a cache coherency point. | 791 | * This makes locking act as a cache coherency point. |
775 | */ | 792 | */ |
776 | nfs_sync_mapping(filp->f_mapping); | 793 | nfs_sync_mapping(filp->f_mapping); |
777 | if (!nfs_have_delegation(inode, FMODE_READ)) | 794 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
778 | nfs_zap_caches(inode); | 795 | if (is_time_granular(&NFS_SERVER(inode)->time_delta)) |
796 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
797 | else | ||
798 | nfs_zap_caches(inode); | ||
799 | } | ||
779 | out: | 800 | out: |
780 | return status; | 801 | return status; |
781 | } | 802 | } |
@@ -787,6 +808,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
787 | { | 808 | { |
788 | struct inode *inode = filp->f_mapping->host; | 809 | struct inode *inode = filp->f_mapping->host; |
789 | int ret = -ENOLCK; | 810 | int ret = -ENOLCK; |
811 | int is_local = 0; | ||
790 | 812 | ||
791 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", | 813 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", |
792 | filp->f_path.dentry->d_parent->d_name.name, | 814 | filp->f_path.dentry->d_parent->d_name.name, |
@@ -800,6 +822,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
800 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | 822 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
801 | goto out_err; | 823 | goto out_err; |
802 | 824 | ||
825 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL) | ||
826 | is_local = 1; | ||
827 | |||
803 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { | 828 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { |
804 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); | 829 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); |
805 | if (ret < 0) | 830 | if (ret < 0) |
@@ -807,11 +832,11 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
807 | } | 832 | } |
808 | 833 | ||
809 | if (IS_GETLK(cmd)) | 834 | if (IS_GETLK(cmd)) |
810 | ret = do_getlk(filp, cmd, fl); | 835 | ret = do_getlk(filp, cmd, fl, is_local); |
811 | else if (fl->fl_type == F_UNLCK) | 836 | else if (fl->fl_type == F_UNLCK) |
812 | ret = do_unlk(filp, cmd, fl); | 837 | ret = do_unlk(filp, cmd, fl, is_local); |
813 | else | 838 | else |
814 | ret = do_setlk(filp, cmd, fl); | 839 | ret = do_setlk(filp, cmd, fl, is_local); |
815 | out_err: | 840 | out_err: |
816 | return ret; | 841 | return ret; |
817 | } | 842 | } |
@@ -821,6 +846,9 @@ out_err: | |||
821 | */ | 846 | */ |
822 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | 847 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) |
823 | { | 848 | { |
849 | struct inode *inode = filp->f_mapping->host; | ||
850 | int is_local = 0; | ||
851 | |||
824 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", | 852 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", |
825 | filp->f_path.dentry->d_parent->d_name.name, | 853 | filp->f_path.dentry->d_parent->d_name.name, |
826 | filp->f_path.dentry->d_name.name, | 854 | filp->f_path.dentry->d_name.name, |
@@ -829,14 +857,17 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
829 | if (!(fl->fl_flags & FL_FLOCK)) | 857 | if (!(fl->fl_flags & FL_FLOCK)) |
830 | return -ENOLCK; | 858 | return -ENOLCK; |
831 | 859 | ||
860 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK) | ||
861 | is_local = 1; | ||
862 | |||
832 | /* We're simulating flock() locks using posix locks on the server */ | 863 | /* We're simulating flock() locks using posix locks on the server */ |
833 | fl->fl_owner = (fl_owner_t)filp; | 864 | fl->fl_owner = (fl_owner_t)filp; |
834 | fl->fl_start = 0; | 865 | fl->fl_start = 0; |
835 | fl->fl_end = OFFSET_MAX; | 866 | fl->fl_end = OFFSET_MAX; |
836 | 867 | ||
837 | if (fl->fl_type == F_UNLCK) | 868 | if (fl->fl_type == F_UNLCK) |
838 | return do_unlk(filp, cmd, fl); | 869 | return do_unlk(filp, cmd, fl, is_local); |
839 | return do_setlk(filp, cmd, fl); | 870 | return do_setlk(filp, cmd, fl, is_local); |
840 | } | 871 | } |
841 | 872 | ||
842 | /* | 873 | /* |