diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 273 |
1 files changed, 142 insertions, 131 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 71a49c3acabd..035c769b715e 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -49,6 +49,11 @@ | |||
49 | 49 | ||
50 | #define NFSDBG_FACILITY NFSDBG_VFS | 50 | #define NFSDBG_FACILITY NFSDBG_VFS |
51 | 51 | ||
52 | #define NFS_64_BIT_INODE_NUMBERS_ENABLED 1 | ||
53 | |||
54 | /* Default is to see 64-bit inode numbers */ | ||
55 | static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED; | ||
56 | |||
52 | static void nfs_invalidate_inode(struct inode *); | 57 | static void nfs_invalidate_inode(struct inode *); |
53 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); | 58 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); |
54 | 59 | ||
@@ -62,6 +67,25 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
62 | return nfs_fileid_to_ino_t(fattr->fileid); | 67 | return nfs_fileid_to_ino_t(fattr->fileid); |
63 | } | 68 | } |
64 | 69 | ||
70 | /** | ||
71 | * nfs_compat_user_ino64 - returns the user-visible inode number | ||
72 | * @fileid: 64-bit fileid | ||
73 | * | ||
74 | * This function returns a 32-bit inode number if the boot parameter | ||
75 | * nfs.enable_ino64 is zero. | ||
76 | */ | ||
77 | u64 nfs_compat_user_ino64(u64 fileid) | ||
78 | { | ||
79 | int ino; | ||
80 | |||
81 | if (enable_ino64) | ||
82 | return fileid; | ||
83 | ino = fileid; | ||
84 | if (sizeof(ino) < sizeof(fileid)) | ||
85 | ino ^= fileid >> (sizeof(fileid)-sizeof(ino)) * 8; | ||
86 | return ino; | ||
87 | } | ||
88 | |||
65 | int nfs_write_inode(struct inode *inode, int sync) | 89 | int nfs_write_inode(struct inode *inode, int sync) |
66 | { | 90 | { |
67 | int ret; | 91 | int ret; |
@@ -85,7 +109,6 @@ void nfs_clear_inode(struct inode *inode) | |||
85 | */ | 109 | */ |
86 | BUG_ON(nfs_have_writebacks(inode)); | 110 | BUG_ON(nfs_have_writebacks(inode)); |
87 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); | 111 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); |
88 | BUG_ON(atomic_read(&NFS_I(inode)->data_updates) != 0); | ||
89 | nfs_zap_acl_cache(inode); | 112 | nfs_zap_acl_cache(inode); |
90 | nfs_access_zap_cache(inode); | 113 | nfs_access_zap_cache(inode); |
91 | } | 114 | } |
@@ -118,8 +141,8 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
118 | 141 | ||
119 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 142 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
120 | 143 | ||
121 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 144 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
122 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 145 | nfsi->attrtimeo_timestamp = jiffies; |
123 | 146 | ||
124 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); | 147 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); |
125 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) | 148 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) |
@@ -156,6 +179,13 @@ static void nfs_zap_acl_cache(struct inode *inode) | |||
156 | spin_unlock(&inode->i_lock); | 179 | spin_unlock(&inode->i_lock); |
157 | } | 180 | } |
158 | 181 | ||
182 | void nfs_invalidate_atime(struct inode *inode) | ||
183 | { | ||
184 | spin_lock(&inode->i_lock); | ||
185 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
186 | spin_unlock(&inode->i_lock); | ||
187 | } | ||
188 | |||
159 | /* | 189 | /* |
160 | * Invalidate, but do not unhash, the inode. | 190 | * Invalidate, but do not unhash, the inode. |
161 | * NB: must be called with inode->i_lock held! | 191 | * NB: must be called with inode->i_lock held! |
@@ -338,7 +368,6 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
338 | return 0; | 368 | return 0; |
339 | 369 | ||
340 | lock_kernel(); | 370 | lock_kernel(); |
341 | nfs_begin_data_update(inode); | ||
342 | /* Write all dirty data */ | 371 | /* Write all dirty data */ |
343 | if (S_ISREG(inode->i_mode)) { | 372 | if (S_ISREG(inode->i_mode)) { |
344 | filemap_write_and_wait(inode->i_mapping); | 373 | filemap_write_and_wait(inode->i_mapping); |
@@ -352,7 +381,6 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
352 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 381 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); |
353 | if (error == 0) | 382 | if (error == 0) |
354 | nfs_refresh_inode(inode, &fattr); | 383 | nfs_refresh_inode(inode, &fattr); |
355 | nfs_end_data_update(inode); | ||
356 | unlock_kernel(); | 384 | unlock_kernel(); |
357 | return error; | 385 | return error; |
358 | } | 386 | } |
@@ -431,7 +459,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
431 | 459 | ||
432 | /* Flush out writes to the server in order to update c/mtime */ | 460 | /* Flush out writes to the server in order to update c/mtime */ |
433 | if (S_ISREG(inode->i_mode)) | 461 | if (S_ISREG(inode->i_mode)) |
434 | nfs_sync_mapping_range(inode->i_mapping, 0, 0, FLUSH_NOCOMMIT); | 462 | nfs_wb_nocommit(inode); |
435 | 463 | ||
436 | /* | 464 | /* |
437 | * We may force a getattr if the user cares about atime. | 465 | * We may force a getattr if the user cares about atime. |
@@ -450,8 +478,10 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
450 | err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 478 | err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
451 | else | 479 | else |
452 | err = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 480 | err = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
453 | if (!err) | 481 | if (!err) { |
454 | generic_fillattr(inode, stat); | 482 | generic_fillattr(inode, stat); |
483 | stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); | ||
484 | } | ||
455 | return err; | 485 | return err; |
456 | } | 486 | } |
457 | 487 | ||
@@ -536,7 +566,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
536 | static void nfs_file_clear_open_context(struct file *filp) | 566 | static void nfs_file_clear_open_context(struct file *filp) |
537 | { | 567 | { |
538 | struct inode *inode = filp->f_path.dentry->d_inode; | 568 | struct inode *inode = filp->f_path.dentry->d_inode; |
539 | struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data; | 569 | struct nfs_open_context *ctx = nfs_file_open_context(filp); |
540 | 570 | ||
541 | if (ctx) { | 571 | if (ctx) { |
542 | filp->private_data = NULL; | 572 | filp->private_data = NULL; |
@@ -598,16 +628,10 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
598 | status = nfs_wait_on_inode(inode); | 628 | status = nfs_wait_on_inode(inode); |
599 | if (status < 0) | 629 | if (status < 0) |
600 | goto out; | 630 | goto out; |
601 | if (NFS_STALE(inode)) { | 631 | |
602 | status = -ESTALE; | 632 | status = -ESTALE; |
603 | /* Do we trust the cached ESTALE? */ | 633 | if (NFS_STALE(inode)) |
604 | if (NFS_ATTRTIMEO(inode) != 0) { | 634 | goto out; |
605 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME)) { | ||
606 | /* no */ | ||
607 | } else | ||
608 | goto out; | ||
609 | } | ||
610 | } | ||
611 | 635 | ||
612 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 636 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
613 | if (status != 0) { | 637 | if (status != 0) { |
@@ -654,7 +678,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
654 | 678 | ||
655 | if (nfs_have_delegation(inode, FMODE_READ)) | 679 | if (nfs_have_delegation(inode, FMODE_READ)) |
656 | return 0; | 680 | return 0; |
657 | return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo); | 681 | return !time_in_range(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); |
658 | } | 682 | } |
659 | 683 | ||
660 | /** | 684 | /** |
@@ -683,11 +707,8 @@ static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_spa | |||
683 | } | 707 | } |
684 | spin_lock(&inode->i_lock); | 708 | spin_lock(&inode->i_lock); |
685 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 709 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
686 | if (S_ISDIR(inode->i_mode)) { | 710 | if (S_ISDIR(inode->i_mode)) |
687 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 711 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
688 | /* This ensures we revalidate child dentries */ | ||
689 | nfsi->cache_change_attribute = jiffies; | ||
690 | } | ||
691 | spin_unlock(&inode->i_lock); | 712 | spin_unlock(&inode->i_lock); |
692 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 713 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); |
693 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 714 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
@@ -756,56 +777,27 @@ out: | |||
756 | return ret; | 777 | return ret; |
757 | } | 778 | } |
758 | 779 | ||
759 | /** | ||
760 | * nfs_begin_data_update | ||
761 | * @inode - pointer to inode | ||
762 | * Declare that a set of operations will update file data on the server | ||
763 | */ | ||
764 | void nfs_begin_data_update(struct inode *inode) | ||
765 | { | ||
766 | atomic_inc(&NFS_I(inode)->data_updates); | ||
767 | } | ||
768 | |||
769 | /** | ||
770 | * nfs_end_data_update | ||
771 | * @inode - pointer to inode | ||
772 | * Declare end of the operations that will update file data | ||
773 | * This will mark the inode as immediately needing revalidation | ||
774 | * of its attribute cache. | ||
775 | */ | ||
776 | void nfs_end_data_update(struct inode *inode) | ||
777 | { | ||
778 | struct nfs_inode *nfsi = NFS_I(inode); | ||
779 | |||
780 | /* Directories: invalidate page cache */ | ||
781 | if (S_ISDIR(inode->i_mode)) { | ||
782 | spin_lock(&inode->i_lock); | ||
783 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
784 | spin_unlock(&inode->i_lock); | ||
785 | } | ||
786 | nfsi->cache_change_attribute = jiffies; | ||
787 | atomic_dec(&nfsi->data_updates); | ||
788 | } | ||
789 | |||
790 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 780 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
791 | { | 781 | { |
792 | struct nfs_inode *nfsi = NFS_I(inode); | 782 | struct nfs_inode *nfsi = NFS_I(inode); |
793 | unsigned long now = jiffies; | ||
794 | 783 | ||
784 | if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 && | ||
785 | nfsi->change_attr == fattr->pre_change_attr) { | ||
786 | nfsi->change_attr = fattr->change_attr; | ||
787 | if (S_ISDIR(inode->i_mode)) | ||
788 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
789 | } | ||
795 | /* If we have atomic WCC data, we may update some attributes */ | 790 | /* If we have atomic WCC data, we may update some attributes */ |
796 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 791 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { |
797 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { | 792 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) |
798 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 793 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
799 | nfsi->cache_change_attribute = now; | ||
800 | } | ||
801 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 794 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
802 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 795 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
803 | nfsi->cache_change_attribute = now; | 796 | if (S_ISDIR(inode->i_mode)) |
797 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
804 | } | 798 | } |
805 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { | 799 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) |
806 | inode->i_size = fattr->size; | 800 | inode->i_size = fattr->size; |
807 | nfsi->cache_change_attribute = now; | ||
808 | } | ||
809 | } | 801 | } |
810 | } | 802 | } |
811 | 803 | ||
@@ -822,7 +814,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
822 | { | 814 | { |
823 | struct nfs_inode *nfsi = NFS_I(inode); | 815 | struct nfs_inode *nfsi = NFS_I(inode); |
824 | loff_t cur_size, new_isize; | 816 | loff_t cur_size, new_isize; |
825 | int data_unstable; | 817 | unsigned long invalid = 0; |
826 | 818 | ||
827 | 819 | ||
828 | /* Has the inode gone and changed behind our back? */ | 820 | /* Has the inode gone and changed behind our back? */ |
@@ -831,37 +823,41 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
831 | return -EIO; | 823 | return -EIO; |
832 | } | 824 | } |
833 | 825 | ||
834 | /* Are we in the process of updating data on the server? */ | ||
835 | data_unstable = nfs_caches_unstable(inode); | ||
836 | |||
837 | /* Do atomic weak cache consistency updates */ | 826 | /* Do atomic weak cache consistency updates */ |
838 | nfs_wcc_update_inode(inode, fattr); | 827 | nfs_wcc_update_inode(inode, fattr); |
839 | 828 | ||
840 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 829 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
841 | nfsi->change_attr != fattr->change_attr) | 830 | nfsi->change_attr != fattr->change_attr) |
842 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 831 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
843 | 832 | ||
844 | /* Verify a few of the more important attributes */ | 833 | /* Verify a few of the more important attributes */ |
845 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) | 834 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) |
846 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 835 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
847 | 836 | ||
848 | cur_size = i_size_read(inode); | 837 | cur_size = i_size_read(inode); |
849 | new_isize = nfs_size_to_loff_t(fattr->size); | 838 | new_isize = nfs_size_to_loff_t(fattr->size); |
850 | if (cur_size != new_isize && nfsi->npages == 0) | 839 | if (cur_size != new_isize && nfsi->npages == 0) |
851 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 840 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
852 | 841 | ||
853 | /* Have any file permissions changed? */ | 842 | /* Have any file permissions changed? */ |
854 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 843 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) |
855 | || inode->i_uid != fattr->uid | 844 | || inode->i_uid != fattr->uid |
856 | || inode->i_gid != fattr->gid) | 845 | || inode->i_gid != fattr->gid) |
857 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 846 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
858 | 847 | ||
859 | /* Has the link count changed? */ | 848 | /* Has the link count changed? */ |
860 | if (inode->i_nlink != fattr->nlink) | 849 | if (inode->i_nlink != fattr->nlink) |
861 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 850 | invalid |= NFS_INO_INVALID_ATTR; |
862 | 851 | ||
863 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 852 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
864 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; | 853 | invalid |= NFS_INO_INVALID_ATIME; |
854 | |||
855 | if (invalid != 0) | ||
856 | nfsi->cache_validity |= invalid; | ||
857 | else | ||
858 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | ||
859 | | NFS_INO_INVALID_ATIME | ||
860 | | NFS_INO_REVAL_PAGECACHE); | ||
865 | 861 | ||
866 | nfsi->read_cache_jiffies = fattr->time_start; | 862 | nfsi->read_cache_jiffies = fattr->time_start; |
867 | return 0; | 863 | return 0; |
@@ -911,17 +907,41 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
911 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 907 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
912 | { | 908 | { |
913 | struct nfs_inode *nfsi = NFS_I(inode); | 909 | struct nfs_inode *nfsi = NFS_I(inode); |
914 | int status = 0; | ||
915 | 910 | ||
916 | spin_lock(&inode->i_lock); | 911 | spin_lock(&inode->i_lock); |
917 | if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) { | 912 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
918 | nfsi->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 913 | if (S_ISDIR(inode->i_mode)) |
919 | goto out; | 914 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
920 | } | ||
921 | status = nfs_update_inode(inode, fattr); | ||
922 | out: | ||
923 | spin_unlock(&inode->i_lock); | 915 | spin_unlock(&inode->i_lock); |
924 | return status; | 916 | return nfs_refresh_inode(inode, fattr); |
917 | } | ||
918 | |||
919 | /** | ||
920 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | ||
921 | * @inode - pointer to inode | ||
922 | * @fattr - updated attributes | ||
923 | * | ||
924 | * After an operation that has changed the inode metadata, mark the | ||
925 | * attribute cache as being invalid, then try to update it. Fake up | ||
926 | * weak cache consistency data, if none exist. | ||
927 | * | ||
928 | * This function is mainly designed to be used by the ->write_done() functions. | ||
929 | */ | ||
930 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | ||
931 | { | ||
932 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | ||
933 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | ||
934 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | ||
935 | fattr->valid |= NFS_ATTR_WCC_V4; | ||
936 | } | ||
937 | if ((fattr->valid & NFS_ATTR_FATTR) != 0 && | ||
938 | (fattr->valid & NFS_ATTR_WCC) == 0) { | ||
939 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); | ||
940 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); | ||
941 | fattr->pre_size = inode->i_size; | ||
942 | fattr->valid |= NFS_ATTR_WCC; | ||
943 | } | ||
944 | return nfs_post_op_update_inode(inode, fattr); | ||
925 | } | 945 | } |
926 | 946 | ||
927 | /* | 947 | /* |
@@ -941,9 +961,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
941 | struct nfs_server *server; | 961 | struct nfs_server *server; |
942 | struct nfs_inode *nfsi = NFS_I(inode); | 962 | struct nfs_inode *nfsi = NFS_I(inode); |
943 | loff_t cur_isize, new_isize; | 963 | loff_t cur_isize, new_isize; |
944 | unsigned int invalid = 0; | 964 | unsigned long invalid = 0; |
945 | unsigned long now = jiffies; | 965 | unsigned long now = jiffies; |
946 | int data_stable; | ||
947 | 966 | ||
948 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 967 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
949 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, | 968 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, |
@@ -968,57 +987,51 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
968 | * Update the read time so we don't revalidate too often. | 987 | * Update the read time so we don't revalidate too often. |
969 | */ | 988 | */ |
970 | nfsi->read_cache_jiffies = fattr->time_start; | 989 | nfsi->read_cache_jiffies = fattr->time_start; |
971 | nfsi->last_updated = now; | ||
972 | 990 | ||
973 | /* Fix a wraparound issue with nfsi->cache_change_attribute */ | 991 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ATIME |
974 | if (time_before(now, nfsi->cache_change_attribute)) | 992 | | NFS_INO_REVAL_PAGECACHE); |
975 | nfsi->cache_change_attribute = now - 600*HZ; | ||
976 | |||
977 | /* Are we racing with known updates of the metadata on the server? */ | ||
978 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); | ||
979 | if (data_stable) | ||
980 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATIME); | ||
981 | 993 | ||
982 | /* Do atomic weak cache consistency updates */ | 994 | /* Do atomic weak cache consistency updates */ |
983 | nfs_wcc_update_inode(inode, fattr); | 995 | nfs_wcc_update_inode(inode, fattr); |
984 | 996 | ||
997 | /* More cache consistency checks */ | ||
998 | if (!(fattr->valid & NFS_ATTR_FATTR_V4)) { | ||
999 | /* NFSv2/v3: Check if the mtime agrees */ | ||
1000 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | ||
1001 | dprintk("NFS: mtime change on server for file %s/%ld\n", | ||
1002 | inode->i_sb->s_id, inode->i_ino); | ||
1003 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
1004 | nfsi->cache_change_attribute = now; | ||
1005 | } | ||
1006 | /* If ctime has changed we should definitely clear access+acl caches */ | ||
1007 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | ||
1008 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1009 | } else if (nfsi->change_attr != fattr->change_attr) { | ||
1010 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1011 | inode->i_sb->s_id, inode->i_ino); | ||
1012 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1013 | nfsi->cache_change_attribute = now; | ||
1014 | } | ||
1015 | |||
985 | /* Check if our cached file size is stale */ | 1016 | /* Check if our cached file size is stale */ |
986 | new_isize = nfs_size_to_loff_t(fattr->size); | 1017 | new_isize = nfs_size_to_loff_t(fattr->size); |
987 | cur_isize = i_size_read(inode); | 1018 | cur_isize = i_size_read(inode); |
988 | if (new_isize != cur_isize) { | 1019 | if (new_isize != cur_isize) { |
989 | /* Do we perhaps have any outstanding writes? */ | 1020 | /* Do we perhaps have any outstanding writes, or has |
990 | if (nfsi->npages == 0) { | 1021 | * the file grown beyond our last write? */ |
991 | /* No, but did we race with nfs_end_data_update()? */ | 1022 | if (nfsi->npages == 0 || new_isize > cur_isize) { |
992 | if (data_stable) { | ||
993 | inode->i_size = new_isize; | ||
994 | invalid |= NFS_INO_INVALID_DATA; | ||
995 | } | ||
996 | invalid |= NFS_INO_INVALID_ATTR; | ||
997 | } else if (new_isize > cur_isize) { | ||
998 | inode->i_size = new_isize; | 1023 | inode->i_size = new_isize; |
999 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1024 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1000 | } | 1025 | } |
1001 | nfsi->cache_change_attribute = now; | ||
1002 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1026 | dprintk("NFS: isize change on server for file %s/%ld\n", |
1003 | inode->i_sb->s_id, inode->i_ino); | 1027 | inode->i_sb->s_id, inode->i_ino); |
1004 | } | 1028 | } |
1005 | 1029 | ||
1006 | /* Check if the mtime agrees */ | ||
1007 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | ||
1008 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | ||
1009 | dprintk("NFS: mtime change on server for file %s/%ld\n", | ||
1010 | inode->i_sb->s_id, inode->i_ino); | ||
1011 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
1012 | nfsi->cache_change_attribute = now; | ||
1013 | } | ||
1014 | 1030 | ||
1015 | /* If ctime has changed we should definitely clear access+acl caches */ | 1031 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
1016 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1032 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
1017 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1018 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | ||
1019 | nfsi->cache_change_attribute = now; | ||
1020 | } | ||
1021 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1033 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1034 | nfsi->change_attr = fattr->change_attr; | ||
1022 | 1035 | ||
1023 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || | 1036 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || |
1024 | inode->i_uid != fattr->uid || | 1037 | inode->i_uid != fattr->uid || |
@@ -1039,31 +1052,29 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1039 | inode->i_blocks = fattr->du.nfs2.blocks; | 1052 | inode->i_blocks = fattr->du.nfs2.blocks; |
1040 | } | 1053 | } |
1041 | 1054 | ||
1042 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | ||
1043 | nfsi->change_attr != fattr->change_attr) { | ||
1044 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1045 | inode->i_sb->s_id, inode->i_ino); | ||
1046 | nfsi->change_attr = fattr->change_attr; | ||
1047 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1048 | nfsi->cache_change_attribute = now; | ||
1049 | } | ||
1050 | |||
1051 | /* Update attrtimeo value if we're out of the unstable period */ | 1055 | /* Update attrtimeo value if we're out of the unstable period */ |
1052 | if (invalid & NFS_INO_INVALID_ATTR) { | 1056 | if (invalid & NFS_INO_INVALID_ATTR) { |
1053 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1057 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1054 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1058 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1055 | nfsi->attrtimeo_timestamp = now; | 1059 | nfsi->attrtimeo_timestamp = now; |
1056 | } else if (time_after(now, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1060 | nfsi->last_updated = now; |
1057 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1061 | } else { |
1058 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1062 | if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
1059 | nfsi->attrtimeo_timestamp = now; | 1063 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
1064 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | ||
1065 | nfsi->attrtimeo_timestamp = now; | ||
1066 | } | ||
1067 | /* | ||
1068 | * Avoid jiffy wraparound issues with nfsi->last_updated | ||
1069 | */ | ||
1070 | if (!time_in_range(nfsi->last_updated, nfsi->read_cache_jiffies, now)) | ||
1071 | nfsi->last_updated = nfsi->read_cache_jiffies; | ||
1060 | } | 1072 | } |
1073 | invalid &= ~NFS_INO_INVALID_ATTR; | ||
1061 | /* Don't invalidate the data if we were to blame */ | 1074 | /* Don't invalidate the data if we were to blame */ |
1062 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1075 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1063 | || S_ISLNK(inode->i_mode))) | 1076 | || S_ISLNK(inode->i_mode))) |
1064 | invalid &= ~NFS_INO_INVALID_DATA; | 1077 | invalid &= ~NFS_INO_INVALID_DATA; |
1065 | if (data_stable) | ||
1066 | invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
1067 | if (!nfs_have_delegation(inode, FMODE_READ) || | 1078 | if (!nfs_have_delegation(inode, FMODE_READ) || |
1068 | (nfsi->cache_validity & NFS_INO_REVAL_FORCED)) | 1079 | (nfsi->cache_validity & NFS_INO_REVAL_FORCED)) |
1069 | nfsi->cache_validity |= invalid; | 1080 | nfsi->cache_validity |= invalid; |
@@ -1152,7 +1163,6 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag | |||
1152 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | 1163 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); |
1153 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | 1164 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); |
1154 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 1165 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
1155 | atomic_set(&nfsi->data_updates, 0); | ||
1156 | nfsi->ncommit = 0; | 1166 | nfsi->ncommit = 0; |
1157 | nfsi->npages = 0; | 1167 | nfsi->npages = 0; |
1158 | nfs4_init_once(nfsi); | 1168 | nfs4_init_once(nfsi); |
@@ -1249,6 +1259,7 @@ static void __exit exit_nfs_fs(void) | |||
1249 | /* Not quite true; I just maintain it */ | 1259 | /* Not quite true; I just maintain it */ |
1250 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); | 1260 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); |
1251 | MODULE_LICENSE("GPL"); | 1261 | MODULE_LICENSE("GPL"); |
1262 | module_param(enable_ino64, bool, 0644); | ||
1252 | 1263 | ||
1253 | module_init(init_nfs_fs) | 1264 | module_init(init_nfs_fs) |
1254 | module_exit(exit_nfs_fs) | 1265 | module_exit(exit_nfs_fs) |