diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/file.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 05bf3c0dc751..2f093ed16980 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 | ||
@@ -300,7 +301,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
300 | * disk, but it retrieves and clears ctx->error after synching, despite | 301 | * disk, but it retrieves and clears ctx->error after synching, despite |
301 | * the two being set at the same time in nfs_context_set_write_error(). | 302 | * the two being set at the same time in nfs_context_set_write_error(). |
302 | * This is because the former is used to notify the _next_ call to | 303 | * This is because the former is used to notify the _next_ call to |
303 | * nfs_file_write() that a write error occured, and hence cause it to | 304 | * nfs_file_write() that a write error occurred, and hence cause it to |
304 | * fall back to doing a synchronous write. | 305 | * fall back to doing a synchronous write. |
305 | */ | 306 | */ |
306 | static int | 307 | static int |
@@ -325,6 +326,9 @@ nfs_file_fsync(struct file *file, int datasync) | |||
325 | ret = xchg(&ctx->error, 0); | 326 | ret = xchg(&ctx->error, 0); |
326 | if (!ret && status < 0) | 327 | if (!ret && status < 0) |
327 | ret = status; | 328 | ret = status; |
329 | if (!ret && !datasync) | ||
330 | /* application has asked for meta-data sync */ | ||
331 | ret = pnfs_layoutcommit_inode(inode, true); | ||
328 | return ret; | 332 | return ret; |
329 | } | 333 | } |
330 | 334 | ||
@@ -551,7 +555,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
551 | struct file *filp = vma->vm_file; | 555 | struct file *filp = vma->vm_file; |
552 | struct dentry *dentry = filp->f_path.dentry; | 556 | struct dentry *dentry = filp->f_path.dentry; |
553 | unsigned pagelen; | 557 | unsigned pagelen; |
554 | int ret = -EINVAL; | 558 | int ret = VM_FAULT_NOPAGE; |
555 | struct address_space *mapping; | 559 | struct address_space *mapping; |
556 | 560 | ||
557 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", | 561 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", |
@@ -567,21 +571,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
567 | if (mapping != dentry->d_inode->i_mapping) | 571 | if (mapping != dentry->d_inode->i_mapping) |
568 | goto out_unlock; | 572 | goto out_unlock; |
569 | 573 | ||
570 | ret = 0; | ||
571 | pagelen = nfs_page_length(page); | 574 | pagelen = nfs_page_length(page); |
572 | if (pagelen == 0) | 575 | if (pagelen == 0) |
573 | goto out_unlock; | 576 | goto out_unlock; |
574 | 577 | ||
575 | ret = nfs_flush_incompatible(filp, page); | 578 | ret = VM_FAULT_LOCKED; |
576 | if (ret != 0) | 579 | if (nfs_flush_incompatible(filp, page) == 0 && |
577 | goto out_unlock; | 580 | nfs_updatepage(filp, page, 0, pagelen) == 0) |
581 | goto out; | ||
578 | 582 | ||
579 | ret = nfs_updatepage(filp, page, 0, pagelen); | 583 | ret = VM_FAULT_SIGBUS; |
580 | out_unlock: | 584 | out_unlock: |
581 | if (!ret) | ||
582 | return VM_FAULT_LOCKED; | ||
583 | unlock_page(page); | 585 | unlock_page(page); |
584 | return VM_FAULT_SIGBUS; | 586 | out: |
587 | return ret; | ||
585 | } | 588 | } |
586 | 589 | ||
587 | static const struct vm_operations_struct nfs_file_vm_ops = { | 590 | static const struct vm_operations_struct nfs_file_vm_ops = { |
@@ -684,10 +687,12 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
684 | return ret; | 687 | return ret; |
685 | } | 688 | } |
686 | 689 | ||
687 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 690 | static int |
691 | do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
688 | { | 692 | { |
689 | struct inode *inode = filp->f_mapping->host; | 693 | struct inode *inode = filp->f_mapping->host; |
690 | int status = 0; | 694 | int status = 0; |
695 | unsigned int saved_type = fl->fl_type; | ||
691 | 696 | ||
692 | /* Try local locking first */ | 697 | /* Try local locking first */ |
693 | posix_test_lock(filp, fl); | 698 | posix_test_lock(filp, fl); |
@@ -695,11 +700,12 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
695 | /* found a conflict */ | 700 | /* found a conflict */ |
696 | goto out; | 701 | goto out; |
697 | } | 702 | } |
703 | fl->fl_type = saved_type; | ||
698 | 704 | ||
699 | if (nfs_have_delegation(inode, FMODE_READ)) | 705 | if (nfs_have_delegation(inode, FMODE_READ)) |
700 | goto out_noconflict; | 706 | goto out_noconflict; |
701 | 707 | ||
702 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | 708 | if (is_local) |
703 | goto out_noconflict; | 709 | goto out_noconflict; |
704 | 710 | ||
705 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 711 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
@@ -726,7 +732,8 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
726 | return res; | 732 | return res; |
727 | } | 733 | } |
728 | 734 | ||
729 | static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | 735 | static int |
736 | do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
730 | { | 737 | { |
731 | struct inode *inode = filp->f_mapping->host; | 738 | struct inode *inode = filp->f_mapping->host; |
732 | int status; | 739 | int status; |
@@ -741,15 +748,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 | 748 | * If we're signalled while cleaning up locks on process exit, we |
742 | * still need to complete the unlock. | 749 | * still need to complete the unlock. |
743 | */ | 750 | */ |
744 | /* Use local locking if mounted with "-onolock" */ | 751 | /* |
745 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 752 | * Use local locking if mounted with "-onolock" or with appropriate |
753 | * "-olocal_lock=" | ||
754 | */ | ||
755 | if (!is_local) | ||
746 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 756 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
747 | else | 757 | else |
748 | status = do_vfs_lock(filp, fl); | 758 | status = do_vfs_lock(filp, fl); |
749 | return status; | 759 | return status; |
750 | } | 760 | } |
751 | 761 | ||
752 | static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | 762 | static int |
763 | is_time_granular(struct timespec *ts) { | ||
764 | return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000)); | ||
765 | } | ||
766 | |||
767 | static int | ||
768 | do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | ||
753 | { | 769 | { |
754 | struct inode *inode = filp->f_mapping->host; | 770 | struct inode *inode = filp->f_mapping->host; |
755 | int status; | 771 | int status; |
@@ -762,20 +778,31 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
762 | if (status != 0) | 778 | if (status != 0) |
763 | goto out; | 779 | goto out; |
764 | 780 | ||
765 | /* Use local locking if mounted with "-onolock" */ | 781 | /* |
766 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 782 | * Use local locking if mounted with "-onolock" or with appropriate |
783 | * "-olocal_lock=" | ||
784 | */ | ||
785 | if (!is_local) | ||
767 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 786 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
768 | else | 787 | else |
769 | status = do_vfs_lock(filp, fl); | 788 | status = do_vfs_lock(filp, fl); |
770 | if (status < 0) | 789 | if (status < 0) |
771 | goto out; | 790 | goto out; |
791 | |||
772 | /* | 792 | /* |
773 | * Make sure we clear the cache whenever we try to get the lock. | 793 | * Revalidate the cache if the server has time stamps granular |
794 | * enough to detect subsecond changes. Otherwise, clear the | ||
795 | * cache to prevent missing any changes. | ||
796 | * | ||
774 | * This makes locking act as a cache coherency point. | 797 | * This makes locking act as a cache coherency point. |
775 | */ | 798 | */ |
776 | nfs_sync_mapping(filp->f_mapping); | 799 | nfs_sync_mapping(filp->f_mapping); |
777 | if (!nfs_have_delegation(inode, FMODE_READ)) | 800 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
778 | nfs_zap_caches(inode); | 801 | if (is_time_granular(&NFS_SERVER(inode)->time_delta)) |
802 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
803 | else | ||
804 | nfs_zap_caches(inode); | ||
805 | } | ||
779 | out: | 806 | out: |
780 | return status; | 807 | return status; |
781 | } | 808 | } |
@@ -787,6 +814,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
787 | { | 814 | { |
788 | struct inode *inode = filp->f_mapping->host; | 815 | struct inode *inode = filp->f_mapping->host; |
789 | int ret = -ENOLCK; | 816 | int ret = -ENOLCK; |
817 | int is_local = 0; | ||
790 | 818 | ||
791 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", | 819 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", |
792 | filp->f_path.dentry->d_parent->d_name.name, | 820 | filp->f_path.dentry->d_parent->d_name.name, |
@@ -800,6 +828,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
800 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | 828 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
801 | goto out_err; | 829 | goto out_err; |
802 | 830 | ||
831 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL) | ||
832 | is_local = 1; | ||
833 | |||
803 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { | 834 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { |
804 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); | 835 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); |
805 | if (ret < 0) | 836 | if (ret < 0) |
@@ -807,11 +838,11 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
807 | } | 838 | } |
808 | 839 | ||
809 | if (IS_GETLK(cmd)) | 840 | if (IS_GETLK(cmd)) |
810 | ret = do_getlk(filp, cmd, fl); | 841 | ret = do_getlk(filp, cmd, fl, is_local); |
811 | else if (fl->fl_type == F_UNLCK) | 842 | else if (fl->fl_type == F_UNLCK) |
812 | ret = do_unlk(filp, cmd, fl); | 843 | ret = do_unlk(filp, cmd, fl, is_local); |
813 | else | 844 | else |
814 | ret = do_setlk(filp, cmd, fl); | 845 | ret = do_setlk(filp, cmd, fl, is_local); |
815 | out_err: | 846 | out_err: |
816 | return ret; | 847 | return ret; |
817 | } | 848 | } |
@@ -821,6 +852,9 @@ out_err: | |||
821 | */ | 852 | */ |
822 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | 853 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) |
823 | { | 854 | { |
855 | struct inode *inode = filp->f_mapping->host; | ||
856 | int is_local = 0; | ||
857 | |||
824 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", | 858 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", |
825 | filp->f_path.dentry->d_parent->d_name.name, | 859 | filp->f_path.dentry->d_parent->d_name.name, |
826 | filp->f_path.dentry->d_name.name, | 860 | filp->f_path.dentry->d_name.name, |
@@ -829,14 +863,17 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
829 | if (!(fl->fl_flags & FL_FLOCK)) | 863 | if (!(fl->fl_flags & FL_FLOCK)) |
830 | return -ENOLCK; | 864 | return -ENOLCK; |
831 | 865 | ||
866 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK) | ||
867 | is_local = 1; | ||
868 | |||
832 | /* We're simulating flock() locks using posix locks on the server */ | 869 | /* We're simulating flock() locks using posix locks on the server */ |
833 | fl->fl_owner = (fl_owner_t)filp; | 870 | fl->fl_owner = (fl_owner_t)filp; |
834 | fl->fl_start = 0; | 871 | fl->fl_start = 0; |
835 | fl->fl_end = OFFSET_MAX; | 872 | fl->fl_end = OFFSET_MAX; |
836 | 873 | ||
837 | if (fl->fl_type == F_UNLCK) | 874 | if (fl->fl_type == F_UNLCK) |
838 | return do_unlk(filp, cmd, fl); | 875 | return do_unlk(filp, cmd, fl, is_local); |
839 | return do_setlk(filp, cmd, fl); | 876 | return do_setlk(filp, cmd, fl, is_local); |
840 | } | 877 | } |
841 | 878 | ||
842 | /* | 879 | /* |
@@ -848,6 +885,5 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) | |||
848 | dprintk("NFS: setlease(%s/%s, arg=%ld)\n", | 885 | dprintk("NFS: setlease(%s/%s, arg=%ld)\n", |
849 | file->f_path.dentry->d_parent->d_name.name, | 886 | file->f_path.dentry->d_parent->d_name.name, |
850 | file->f_path.dentry->d_name.name, arg); | 887 | file->f_path.dentry->d_name.name, arg); |
851 | |||
852 | return -EINVAL; | 888 | return -EINVAL; |
853 | } | 889 | } |