aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 16:48:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 16:48:29 -0400
commit74eb94b218d087798a52c0b4f1379b635287a4b8 (patch)
tree4e467c3014c2b1169f6f71d88cf5d1598f3ce28e /fs/nfs/file.c
parent7b6181e06841f5ad15c4ff708b967b4db65a64de (diff)
parent9a84d38031c258a17bb39beed1e500eadee67407 (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.c81
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;
580out_unlock: 580out_unlock:
581 if (!ret)
582 return VM_FAULT_LOCKED;
583 unlock_page(page); 581 unlock_page(page);
584 return VM_FAULT_SIGBUS; 582out:
583 return ret;
585} 584}
586 585
587static const struct vm_operations_struct nfs_file_vm_ops = { 586static 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
687static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) 686static int
687do_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
729static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) 729static int
730do_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
752static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) 756static int
757is_time_granular(struct timespec *ts) {
758 return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000));
759}
760
761static int
762do_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 }
779out: 800out:
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);
815out_err: 840out_err:
816 return ret; 841 return ret;
817} 842}
@@ -821,6 +846,9 @@ out_err:
821 */ 846 */
822static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) 847static 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/*