diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 141 |
1 files changed, 82 insertions, 59 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f036153d9f50..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 | ||
@@ -203,37 +204,11 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
203 | } | 204 | } |
204 | 205 | ||
205 | /* | 206 | /* |
206 | * Helper for nfs_file_flush() and nfs_file_fsync() | ||
207 | * | ||
208 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
209 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
210 | * the two being set at the same time in nfs_context_set_write_error(). | ||
211 | * This is because the former is used to notify the _next_ call to | ||
212 | * nfs_file_write() that a write error occured, and hence cause it to | ||
213 | * fall back to doing a synchronous write. | ||
214 | */ | ||
215 | static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | ||
216 | { | ||
217 | int have_error, status; | ||
218 | int ret = 0; | ||
219 | |||
220 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
221 | status = nfs_wb_all(inode); | ||
222 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
223 | if (have_error) | ||
224 | ret = xchg(&ctx->error, 0); | ||
225 | if (!ret) | ||
226 | ret = status; | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Flush all dirty pages, and check for write errors. | 207 | * Flush all dirty pages, and check for write errors. |
232 | */ | 208 | */ |
233 | static int | 209 | static int |
234 | nfs_file_flush(struct file *file, fl_owner_t id) | 210 | nfs_file_flush(struct file *file, fl_owner_t id) |
235 | { | 211 | { |
236 | struct nfs_open_context *ctx = nfs_file_open_context(file); | ||
237 | struct dentry *dentry = file->f_path.dentry; | 212 | struct dentry *dentry = file->f_path.dentry; |
238 | struct inode *inode = dentry->d_inode; | 213 | struct inode *inode = dentry->d_inode; |
239 | 214 | ||
@@ -246,7 +221,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
246 | return 0; | 221 | return 0; |
247 | 222 | ||
248 | /* Flush writes to the server and return any errors */ | 223 | /* Flush writes to the server and return any errors */ |
249 | return nfs_do_fsync(ctx, inode); | 224 | return vfs_fsync(file, 0); |
250 | } | 225 | } |
251 | 226 | ||
252 | static ssize_t | 227 | static ssize_t |
@@ -321,6 +296,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
321 | * Flush any dirty pages for this process, and check for write errors. | 296 | * Flush any dirty pages for this process, and check for write errors. |
322 | * The return status from this call provides a reliable indication of | 297 | * The return status from this call provides a reliable indication of |
323 | * whether any write errors occurred for this process. | 298 | * whether any write errors occurred for this process. |
299 | * | ||
300 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
301 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
302 | * the two being set at the same time in nfs_context_set_write_error(). | ||
303 | * This is because the former is used to notify the _next_ call to | ||
304 | * nfs_file_write() that a write error occured, and hence cause it to | ||
305 | * fall back to doing a synchronous write. | ||
324 | */ | 306 | */ |
325 | static int | 307 | static int |
326 | nfs_file_fsync(struct file *file, int datasync) | 308 | nfs_file_fsync(struct file *file, int datasync) |
@@ -328,13 +310,23 @@ nfs_file_fsync(struct file *file, int datasync) | |||
328 | struct dentry *dentry = file->f_path.dentry; | 310 | struct dentry *dentry = file->f_path.dentry; |
329 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 311 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
330 | struct inode *inode = dentry->d_inode; | 312 | struct inode *inode = dentry->d_inode; |
313 | int have_error, status; | ||
314 | int ret = 0; | ||
315 | |||
331 | 316 | ||
332 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", | 317 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", |
333 | dentry->d_parent->d_name.name, dentry->d_name.name, | 318 | dentry->d_parent->d_name.name, dentry->d_name.name, |
334 | datasync); | 319 | datasync); |
335 | 320 | ||
336 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 321 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
337 | return nfs_do_fsync(ctx, inode); | 322 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
323 | status = nfs_commit_inode(inode, FLUSH_SYNC); | ||
324 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
325 | if (have_error) | ||
326 | ret = xchg(&ctx->error, 0); | ||
327 | if (!ret && status < 0) | ||
328 | ret = status; | ||
329 | return ret; | ||
338 | } | 330 | } |
339 | 331 | ||
340 | /* | 332 | /* |
@@ -395,6 +387,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
395 | file->f_path.dentry->d_name.name, | 387 | file->f_path.dentry->d_name.name, |
396 | mapping->host->i_ino, len, (long long) pos); | 388 | mapping->host->i_ino, len, (long long) pos); |
397 | 389 | ||
390 | pnfs_update_layout(mapping->host, | ||
391 | nfs_file_open_context(file), | ||
392 | IOMODE_RW); | ||
393 | |||
398 | start: | 394 | start: |
399 | /* | 395 | /* |
400 | * Prevent starvation issues if someone is doing a consistency | 396 | * Prevent starvation issues if someone is doing a consistency |
@@ -560,7 +556,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
560 | struct file *filp = vma->vm_file; | 556 | struct file *filp = vma->vm_file; |
561 | struct dentry *dentry = filp->f_path.dentry; | 557 | struct dentry *dentry = filp->f_path.dentry; |
562 | unsigned pagelen; | 558 | unsigned pagelen; |
563 | int ret = -EINVAL; | 559 | int ret = VM_FAULT_NOPAGE; |
564 | struct address_space *mapping; | 560 | struct address_space *mapping; |
565 | 561 | ||
566 | 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", |
@@ -576,21 +572,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
576 | if (mapping != dentry->d_inode->i_mapping) | 572 | if (mapping != dentry->d_inode->i_mapping) |
577 | goto out_unlock; | 573 | goto out_unlock; |
578 | 574 | ||
579 | ret = 0; | ||
580 | pagelen = nfs_page_length(page); | 575 | pagelen = nfs_page_length(page); |
581 | if (pagelen == 0) | 576 | if (pagelen == 0) |
582 | goto out_unlock; | 577 | goto out_unlock; |
583 | 578 | ||
584 | ret = nfs_flush_incompatible(filp, page); | 579 | ret = VM_FAULT_LOCKED; |
585 | if (ret != 0) | 580 | if (nfs_flush_incompatible(filp, page) == 0 && |
586 | goto out_unlock; | 581 | nfs_updatepage(filp, page, 0, pagelen) == 0) |
582 | goto out; | ||
587 | 583 | ||
588 | ret = nfs_updatepage(filp, page, 0, pagelen); | 584 | ret = VM_FAULT_SIGBUS; |
589 | out_unlock: | 585 | out_unlock: |
590 | if (!ret) | ||
591 | return VM_FAULT_LOCKED; | ||
592 | unlock_page(page); | 586 | unlock_page(page); |
593 | return VM_FAULT_SIGBUS; | 587 | out: |
588 | return ret; | ||
594 | } | 589 | } |
595 | 590 | ||
596 | static const struct vm_operations_struct nfs_file_vm_ops = { | 591 | static const struct vm_operations_struct nfs_file_vm_ops = { |
@@ -648,7 +643,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
648 | 643 | ||
649 | /* Return error values for O_DSYNC and IS_SYNC() */ | 644 | /* Return error values for O_DSYNC and IS_SYNC() */ |
650 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { | 645 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
651 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); | 646 | int err = vfs_fsync(iocb->ki_filp, 0); |
652 | if (err < 0) | 647 | if (err < 0) |
653 | result = err; | 648 | result = err; |
654 | } | 649 | } |
@@ -684,7 +679,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
684 | written = ret; | 679 | written = ret; |
685 | 680 | ||
686 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | 681 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { |
687 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | 682 | int err = vfs_fsync(filp, 0); |
688 | if (err < 0) | 683 | if (err < 0) |
689 | ret = err; | 684 | ret = err; |
690 | } | 685 | } |
@@ -693,7 +688,8 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
693 | return ret; | 688 | return ret; |
694 | } | 689 | } |
695 | 690 | ||
696 | 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) | ||
697 | { | 693 | { |
698 | struct inode *inode = filp->f_mapping->host; | 694 | struct inode *inode = filp->f_mapping->host; |
699 | int status = 0; | 695 | int status = 0; |
@@ -708,7 +704,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
708 | if (nfs_have_delegation(inode, FMODE_READ)) | 704 | if (nfs_have_delegation(inode, FMODE_READ)) |
709 | goto out_noconflict; | 705 | goto out_noconflict; |
710 | 706 | ||
711 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | 707 | if (is_local) |
712 | goto out_noconflict; | 708 | goto out_noconflict; |
713 | 709 | ||
714 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 710 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
@@ -732,14 +728,11 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
732 | default: | 728 | default: |
733 | BUG(); | 729 | BUG(); |
734 | } | 730 | } |
735 | if (res < 0) | ||
736 | dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" | ||
737 | " - error %d!\n", | ||
738 | __func__, res); | ||
739 | return res; | 731 | return res; |
740 | } | 732 | } |
741 | 733 | ||
742 | 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) | ||
743 | { | 736 | { |
744 | struct inode *inode = filp->f_mapping->host; | 737 | struct inode *inode = filp->f_mapping->host; |
745 | int status; | 738 | int status; |
@@ -754,15 +747,24 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | |||
754 | * 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 |
755 | * still need to complete the unlock. | 748 | * still need to complete the unlock. |
756 | */ | 749 | */ |
757 | /* Use local locking if mounted with "-onolock" */ | 750 | /* |
758 | 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) | ||
759 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 755 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
760 | else | 756 | else |
761 | status = do_vfs_lock(filp, fl); | 757 | status = do_vfs_lock(filp, fl); |
762 | return status; | 758 | return status; |
763 | } | 759 | } |
764 | 760 | ||
765 | 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) | ||
766 | { | 768 | { |
767 | struct inode *inode = filp->f_mapping->host; | 769 | struct inode *inode = filp->f_mapping->host; |
768 | int status; | 770 | int status; |
@@ -775,20 +777,31 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
775 | if (status != 0) | 777 | if (status != 0) |
776 | goto out; | 778 | goto out; |
777 | 779 | ||
778 | /* Use local locking if mounted with "-onolock" */ | 780 | /* |
779 | 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) | ||
780 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 785 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
781 | else | 786 | else |
782 | status = do_vfs_lock(filp, fl); | 787 | status = do_vfs_lock(filp, fl); |
783 | if (status < 0) | 788 | if (status < 0) |
784 | goto out; | 789 | goto out; |
790 | |||
785 | /* | 791 | /* |
786 | * 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 | * | ||
787 | * This makes locking act as a cache coherency point. | 796 | * This makes locking act as a cache coherency point. |
788 | */ | 797 | */ |
789 | nfs_sync_mapping(filp->f_mapping); | 798 | nfs_sync_mapping(filp->f_mapping); |
790 | if (!nfs_have_delegation(inode, FMODE_READ)) | 799 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
791 | 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 | } | ||
792 | out: | 805 | out: |
793 | return status; | 806 | return status; |
794 | } | 807 | } |
@@ -800,6 +813,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
800 | { | 813 | { |
801 | struct inode *inode = filp->f_mapping->host; | 814 | struct inode *inode = filp->f_mapping->host; |
802 | int ret = -ENOLCK; | 815 | int ret = -ENOLCK; |
816 | int is_local = 0; | ||
803 | 817 | ||
804 | 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", |
805 | filp->f_path.dentry->d_parent->d_name.name, | 819 | filp->f_path.dentry->d_parent->d_name.name, |
@@ -813,6 +827,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
813 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | 827 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
814 | goto out_err; | 828 | goto out_err; |
815 | 829 | ||
830 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL) | ||
831 | is_local = 1; | ||
832 | |||
816 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { | 833 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { |
817 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); | 834 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); |
818 | if (ret < 0) | 835 | if (ret < 0) |
@@ -820,11 +837,11 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
820 | } | 837 | } |
821 | 838 | ||
822 | if (IS_GETLK(cmd)) | 839 | if (IS_GETLK(cmd)) |
823 | ret = do_getlk(filp, cmd, fl); | 840 | ret = do_getlk(filp, cmd, fl, is_local); |
824 | else if (fl->fl_type == F_UNLCK) | 841 | else if (fl->fl_type == F_UNLCK) |
825 | ret = do_unlk(filp, cmd, fl); | 842 | ret = do_unlk(filp, cmd, fl, is_local); |
826 | else | 843 | else |
827 | ret = do_setlk(filp, cmd, fl); | 844 | ret = do_setlk(filp, cmd, fl, is_local); |
828 | out_err: | 845 | out_err: |
829 | return ret; | 846 | return ret; |
830 | } | 847 | } |
@@ -834,6 +851,9 @@ out_err: | |||
834 | */ | 851 | */ |
835 | 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) |
836 | { | 853 | { |
854 | struct inode *inode = filp->f_mapping->host; | ||
855 | int is_local = 0; | ||
856 | |||
837 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", | 857 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", |
838 | filp->f_path.dentry->d_parent->d_name.name, | 858 | filp->f_path.dentry->d_parent->d_name.name, |
839 | filp->f_path.dentry->d_name.name, | 859 | filp->f_path.dentry->d_name.name, |
@@ -842,14 +862,17 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
842 | if (!(fl->fl_flags & FL_FLOCK)) | 862 | if (!(fl->fl_flags & FL_FLOCK)) |
843 | return -ENOLCK; | 863 | return -ENOLCK; |
844 | 864 | ||
865 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK) | ||
866 | is_local = 1; | ||
867 | |||
845 | /* We're simulating flock() locks using posix locks on the server */ | 868 | /* We're simulating flock() locks using posix locks on the server */ |
846 | fl->fl_owner = (fl_owner_t)filp; | 869 | fl->fl_owner = (fl_owner_t)filp; |
847 | fl->fl_start = 0; | 870 | fl->fl_start = 0; |
848 | fl->fl_end = OFFSET_MAX; | 871 | fl->fl_end = OFFSET_MAX; |
849 | 872 | ||
850 | if (fl->fl_type == F_UNLCK) | 873 | if (fl->fl_type == F_UNLCK) |
851 | return do_unlk(filp, cmd, fl); | 874 | return do_unlk(filp, cmd, fl, is_local); |
852 | return do_setlk(filp, cmd, fl); | 875 | return do_setlk(filp, cmd, fl, is_local); |
853 | } | 876 | } |
854 | 877 | ||
855 | /* | 878 | /* |