diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 183 |
1 files changed, 109 insertions, 74 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 52daefa2f521..b9195c02a863 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -305,8 +305,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
305 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 305 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
306 | 306 | ||
307 | nfsi->read_cache_jiffies = fattr->time_start; | 307 | nfsi->read_cache_jiffies = fattr->time_start; |
308 | nfsi->last_updated = now; | 308 | nfsi->attr_gencount = fattr->gencount; |
309 | nfsi->cache_change_attribute = now; | ||
310 | inode->i_atime = fattr->atime; | 309 | inode->i_atime = fattr->atime; |
311 | inode->i_mtime = fattr->mtime; | 310 | inode->i_mtime = fattr->mtime; |
312 | inode->i_ctime = fattr->ctime; | 311 | inode->i_ctime = fattr->ctime; |
@@ -453,6 +452,7 @@ out_big: | |||
453 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | 452 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) |
454 | { | 453 | { |
455 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 454 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
455 | spin_lock(&inode->i_lock); | ||
456 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 456 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
457 | int mode = attr->ia_mode & S_IALLUGO; | 457 | int mode = attr->ia_mode & S_IALLUGO; |
458 | mode |= inode->i_mode & ~S_IALLUGO; | 458 | mode |= inode->i_mode & ~S_IALLUGO; |
@@ -462,7 +462,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
462 | inode->i_uid = attr->ia_uid; | 462 | inode->i_uid = attr->ia_uid; |
463 | if ((attr->ia_valid & ATTR_GID) != 0) | 463 | if ((attr->ia_valid & ATTR_GID) != 0) |
464 | inode->i_gid = attr->ia_gid; | 464 | inode->i_gid = attr->ia_gid; |
465 | spin_lock(&inode->i_lock); | ||
466 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 465 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
467 | spin_unlock(&inode->i_lock); | 466 | spin_unlock(&inode->i_lock); |
468 | } | 467 | } |
@@ -472,37 +471,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
472 | } | 471 | } |
473 | } | 472 | } |
474 | 473 | ||
475 | static int nfs_wait_schedule(void *word) | ||
476 | { | ||
477 | if (signal_pending(current)) | ||
478 | return -ERESTARTSYS; | ||
479 | schedule(); | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | /* | ||
484 | * Wait for the inode to get unlocked. | ||
485 | */ | ||
486 | static int nfs_wait_on_inode(struct inode *inode) | ||
487 | { | ||
488 | struct nfs_inode *nfsi = NFS_I(inode); | ||
489 | int error; | ||
490 | |||
491 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, | ||
492 | nfs_wait_schedule, TASK_KILLABLE); | ||
493 | |||
494 | return error; | ||
495 | } | ||
496 | |||
497 | static void nfs_wake_up_inode(struct inode *inode) | ||
498 | { | ||
499 | struct nfs_inode *nfsi = NFS_I(inode); | ||
500 | |||
501 | clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); | ||
502 | smp_mb__after_clear_bit(); | ||
503 | wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); | ||
504 | } | ||
505 | |||
506 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 474 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
507 | { | 475 | { |
508 | struct inode *inode = dentry->d_inode; | 476 | struct inode *inode = dentry->d_inode; |
@@ -697,20 +665,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
697 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 665 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
698 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 666 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
699 | 667 | ||
700 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | ||
701 | if (is_bad_inode(inode)) | 668 | if (is_bad_inode(inode)) |
702 | goto out_nowait; | 669 | goto out; |
703 | if (NFS_STALE(inode)) | 670 | if (NFS_STALE(inode)) |
704 | goto out_nowait; | ||
705 | |||
706 | status = nfs_wait_on_inode(inode); | ||
707 | if (status < 0) | ||
708 | goto out; | 671 | goto out; |
709 | 672 | ||
710 | status = -ESTALE; | ||
711 | if (NFS_STALE(inode)) | 673 | if (NFS_STALE(inode)) |
712 | goto out; | 674 | goto out; |
713 | 675 | ||
676 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | ||
714 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 677 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
715 | if (status != 0) { | 678 | if (status != 0) { |
716 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 679 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
@@ -724,16 +687,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
724 | goto out; | 687 | goto out; |
725 | } | 688 | } |
726 | 689 | ||
727 | spin_lock(&inode->i_lock); | 690 | status = nfs_refresh_inode(inode, &fattr); |
728 | status = nfs_update_inode(inode, &fattr); | ||
729 | if (status) { | 691 | if (status) { |
730 | spin_unlock(&inode->i_lock); | ||
731 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 692 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
732 | inode->i_sb->s_id, | 693 | inode->i_sb->s_id, |
733 | (long long)NFS_FILEID(inode), status); | 694 | (long long)NFS_FILEID(inode), status); |
734 | goto out; | 695 | goto out; |
735 | } | 696 | } |
736 | spin_unlock(&inode->i_lock); | ||
737 | 697 | ||
738 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) | 698 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
739 | nfs_zap_acl_cache(inode); | 699 | nfs_zap_acl_cache(inode); |
@@ -743,9 +703,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
743 | (long long)NFS_FILEID(inode)); | 703 | (long long)NFS_FILEID(inode)); |
744 | 704 | ||
745 | out: | 705 | out: |
746 | nfs_wake_up_inode(inode); | ||
747 | |||
748 | out_nowait: | ||
749 | return status; | 706 | return status; |
750 | } | 707 | } |
751 | 708 | ||
@@ -908,9 +865,6 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
908 | return -EIO; | 865 | return -EIO; |
909 | } | 866 | } |
910 | 867 | ||
911 | /* Do atomic weak cache consistency updates */ | ||
912 | nfs_wcc_update_inode(inode, fattr); | ||
913 | |||
914 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 868 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
915 | nfsi->change_attr != fattr->change_attr) | 869 | nfsi->change_attr != fattr->change_attr) |
916 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 870 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
@@ -939,15 +893,81 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
939 | 893 | ||
940 | if (invalid != 0) | 894 | if (invalid != 0) |
941 | nfsi->cache_validity |= invalid; | 895 | nfsi->cache_validity |= invalid; |
942 | else | ||
943 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | ||
944 | | NFS_INO_INVALID_ATIME | ||
945 | | NFS_INO_REVAL_PAGECACHE); | ||
946 | 896 | ||
947 | nfsi->read_cache_jiffies = fattr->time_start; | 897 | nfsi->read_cache_jiffies = fattr->time_start; |
948 | return 0; | 898 | return 0; |
949 | } | 899 | } |
950 | 900 | ||
901 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
902 | { | ||
903 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | ||
904 | } | ||
905 | |||
906 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
907 | { | ||
908 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | ||
909 | } | ||
910 | |||
911 | static unsigned long nfs_attr_generation_counter; | ||
912 | |||
913 | static unsigned long nfs_read_attr_generation_counter(void) | ||
914 | { | ||
915 | smp_rmb(); | ||
916 | return nfs_attr_generation_counter; | ||
917 | } | ||
918 | |||
919 | unsigned long nfs_inc_attr_generation_counter(void) | ||
920 | { | ||
921 | unsigned long ret; | ||
922 | smp_rmb(); | ||
923 | ret = ++nfs_attr_generation_counter; | ||
924 | smp_wmb(); | ||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | void nfs_fattr_init(struct nfs_fattr *fattr) | ||
929 | { | ||
930 | fattr->valid = 0; | ||
931 | fattr->time_start = jiffies; | ||
932 | fattr->gencount = nfs_inc_attr_generation_counter(); | ||
933 | } | ||
934 | |||
935 | /** | ||
936 | * nfs_inode_attrs_need_update - check if the inode attributes need updating | ||
937 | * @inode - pointer to inode | ||
938 | * @fattr - attributes | ||
939 | * | ||
940 | * Attempt to divine whether or not an RPC call reply carrying stale | ||
941 | * attributes got scheduled after another call carrying updated ones. | ||
942 | * | ||
943 | * To do so, the function first assumes that a more recent ctime means | ||
944 | * that the attributes in fattr are newer, however it also attempt to | ||
945 | * catch the case where ctime either didn't change, or went backwards | ||
946 | * (if someone reset the clock on the server) by looking at whether | ||
947 | * or not this RPC call was started after the inode was last updated. | ||
948 | * Note also the check for wraparound of 'attr_gencount' | ||
949 | * | ||
950 | * The function returns 'true' if it thinks the attributes in 'fattr' are | ||
951 | * more recent than the ones cached in the inode. | ||
952 | * | ||
953 | */ | ||
954 | static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
955 | { | ||
956 | const struct nfs_inode *nfsi = NFS_I(inode); | ||
957 | |||
958 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || | ||
959 | nfs_ctime_need_update(inode, fattr) || | ||
960 | nfs_size_need_update(inode, fattr) || | ||
961 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | ||
962 | } | ||
963 | |||
964 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | ||
965 | { | ||
966 | if (nfs_inode_attrs_need_update(inode, fattr)) | ||
967 | return nfs_update_inode(inode, fattr); | ||
968 | return nfs_check_inode_attributes(inode, fattr); | ||
969 | } | ||
970 | |||
951 | /** | 971 | /** |
952 | * nfs_refresh_inode - try to update the inode attribute cache | 972 | * nfs_refresh_inode - try to update the inode attribute cache |
953 | * @inode - pointer to inode | 973 | * @inode - pointer to inode |
@@ -960,21 +980,28 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
960 | */ | 980 | */ |
961 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | 981 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) |
962 | { | 982 | { |
963 | struct nfs_inode *nfsi = NFS_I(inode); | ||
964 | int status; | 983 | int status; |
965 | 984 | ||
966 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 985 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
967 | return 0; | 986 | return 0; |
968 | spin_lock(&inode->i_lock); | 987 | spin_lock(&inode->i_lock); |
969 | if (time_after(fattr->time_start, nfsi->last_updated)) | 988 | status = nfs_refresh_inode_locked(inode, fattr); |
970 | status = nfs_update_inode(inode, fattr); | ||
971 | else | ||
972 | status = nfs_check_inode_attributes(inode, fattr); | ||
973 | |||
974 | spin_unlock(&inode->i_lock); | 989 | spin_unlock(&inode->i_lock); |
975 | return status; | 990 | return status; |
976 | } | 991 | } |
977 | 992 | ||
993 | static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | ||
994 | { | ||
995 | struct nfs_inode *nfsi = NFS_I(inode); | ||
996 | |||
997 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | ||
998 | if (S_ISDIR(inode->i_mode)) | ||
999 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
1000 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | ||
1001 | return 0; | ||
1002 | return nfs_refresh_inode_locked(inode, fattr); | ||
1003 | } | ||
1004 | |||
978 | /** | 1005 | /** |
979 | * nfs_post_op_update_inode - try to update the inode attribute cache | 1006 | * nfs_post_op_update_inode - try to update the inode attribute cache |
980 | * @inode - pointer to inode | 1007 | * @inode - pointer to inode |
@@ -991,14 +1018,12 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
991 | */ | 1018 | */ |
992 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1019 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
993 | { | 1020 | { |
994 | struct nfs_inode *nfsi = NFS_I(inode); | 1021 | int status; |
995 | 1022 | ||
996 | spin_lock(&inode->i_lock); | 1023 | spin_lock(&inode->i_lock); |
997 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 1024 | status = nfs_post_op_update_inode_locked(inode, fattr); |
998 | if (S_ISDIR(inode->i_mode)) | ||
999 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
1000 | spin_unlock(&inode->i_lock); | 1025 | spin_unlock(&inode->i_lock); |
1001 | return nfs_refresh_inode(inode, fattr); | 1026 | return status; |
1002 | } | 1027 | } |
1003 | 1028 | ||
1004 | /** | 1029 | /** |
@@ -1014,6 +1039,15 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1014 | */ | 1039 | */ |
1015 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1040 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) |
1016 | { | 1041 | { |
1042 | int status; | ||
1043 | |||
1044 | spin_lock(&inode->i_lock); | ||
1045 | /* Don't do a WCC update if these attributes are already stale */ | ||
1046 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | ||
1047 | !nfs_inode_attrs_need_update(inode, fattr)) { | ||
1048 | fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC); | ||
1049 | goto out_noforce; | ||
1050 | } | ||
1017 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1051 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
1018 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | 1052 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { |
1019 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1053 | fattr->pre_change_attr = NFS_I(inode)->change_attr; |
@@ -1026,7 +1060,10 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1026 | fattr->pre_size = i_size_read(inode); | 1060 | fattr->pre_size = i_size_read(inode); |
1027 | fattr->valid |= NFS_ATTR_WCC; | 1061 | fattr->valid |= NFS_ATTR_WCC; |
1028 | } | 1062 | } |
1029 | return nfs_post_op_update_inode(inode, fattr); | 1063 | out_noforce: |
1064 | status = nfs_post_op_update_inode_locked(inode, fattr); | ||
1065 | spin_unlock(&inode->i_lock); | ||
1066 | return status; | ||
1030 | } | 1067 | } |
1031 | 1068 | ||
1032 | /* | 1069 | /* |
@@ -1092,7 +1129,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1092 | } | 1129 | } |
1093 | /* If ctime has changed we should definitely clear access+acl caches */ | 1130 | /* If ctime has changed we should definitely clear access+acl caches */ |
1094 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1131 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) |
1095 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1132 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1096 | } else if (nfsi->change_attr != fattr->change_attr) { | 1133 | } else if (nfsi->change_attr != fattr->change_attr) { |
1097 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1134 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
1098 | inode->i_sb->s_id, inode->i_ino); | 1135 | inode->i_sb->s_id, inode->i_ino); |
@@ -1126,6 +1163,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1126 | inode->i_gid != fattr->gid) | 1163 | inode->i_gid != fattr->gid) |
1127 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1164 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1128 | 1165 | ||
1166 | if (inode->i_nlink != fattr->nlink) | ||
1167 | invalid |= NFS_INO_INVALID_ATTR; | ||
1168 | |||
1129 | inode->i_mode = fattr->mode; | 1169 | inode->i_mode = fattr->mode; |
1130 | inode->i_nlink = fattr->nlink; | 1170 | inode->i_nlink = fattr->nlink; |
1131 | inode->i_uid = fattr->uid; | 1171 | inode->i_uid = fattr->uid; |
@@ -1145,18 +1185,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1145 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1185 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1146 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1186 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1147 | nfsi->attrtimeo_timestamp = now; | 1187 | nfsi->attrtimeo_timestamp = now; |
1148 | nfsi->last_updated = now; | 1188 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
1149 | } else { | 1189 | } else { |
1150 | if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { | 1190 | if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
1151 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1191 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
1152 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1192 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
1153 | nfsi->attrtimeo_timestamp = now; | 1193 | nfsi->attrtimeo_timestamp = now; |
1154 | } | 1194 | } |
1155 | /* | ||
1156 | * Avoid jiffy wraparound issues with nfsi->last_updated | ||
1157 | */ | ||
1158 | if (!time_in_range(nfsi->last_updated, nfsi->read_cache_jiffies, now)) | ||
1159 | nfsi->last_updated = nfsi->read_cache_jiffies; | ||
1160 | } | 1195 | } |
1161 | invalid &= ~NFS_INO_INVALID_ATTR; | 1196 | invalid &= ~NFS_INO_INVALID_ATTR; |
1162 | /* Don't invalidate the data if we were to blame */ | 1197 | /* Don't invalidate the data if we were to blame */ |