diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 323 |
1 files changed, 218 insertions, 105 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 0c381686171e..64f87194d390 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "delegation.h" | 46 | #include "delegation.h" |
47 | #include "iostat.h" | 47 | #include "iostat.h" |
48 | #include "internal.h" | 48 | #include "internal.h" |
49 | #include "fscache.h" | ||
49 | 50 | ||
50 | #define NFSDBG_FACILITY NFSDBG_VFS | 51 | #define NFSDBG_FACILITY NFSDBG_VFS |
51 | 52 | ||
@@ -66,6 +67,18 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
66 | } | 67 | } |
67 | 68 | ||
68 | /** | 69 | /** |
70 | * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks | ||
71 | * @word: long word containing the bit lock | ||
72 | */ | ||
73 | int nfs_wait_bit_killable(void *word) | ||
74 | { | ||
75 | if (fatal_signal_pending(current)) | ||
76 | return -ERESTARTSYS; | ||
77 | schedule(); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /** | ||
69 | * nfs_compat_user_ino64 - returns the user-visible inode number | 82 | * nfs_compat_user_ino64 - returns the user-visible inode number |
70 | * @fileid: 64-bit fileid | 83 | * @fileid: 64-bit fileid |
71 | * | 84 | * |
@@ -109,6 +122,7 @@ void nfs_clear_inode(struct inode *inode) | |||
109 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); | 122 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); |
110 | nfs_zap_acl_cache(inode); | 123 | nfs_zap_acl_cache(inode); |
111 | nfs_access_zap_cache(inode); | 124 | nfs_access_zap_cache(inode); |
125 | nfs_fscache_release_inode_cookie(inode); | ||
112 | } | 126 | } |
113 | 127 | ||
114 | /** | 128 | /** |
@@ -249,13 +263,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
249 | struct inode *inode = ERR_PTR(-ENOENT); | 263 | struct inode *inode = ERR_PTR(-ENOENT); |
250 | unsigned long hash; | 264 | unsigned long hash; |
251 | 265 | ||
252 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 266 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) |
253 | goto out_no_inode; | 267 | goto out_no_inode; |
254 | 268 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) | |
255 | if (!fattr->nlink) { | ||
256 | printk("NFS: Buggy server - nlink == 0!\n"); | ||
257 | goto out_no_inode; | 269 | goto out_no_inode; |
258 | } | ||
259 | 270 | ||
260 | hash = nfs_fattr_to_ino_t(fattr); | 271 | hash = nfs_fattr_to_ino_t(fattr); |
261 | 272 | ||
@@ -291,7 +302,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
291 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 302 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
292 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 303 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
293 | /* Deal with crossing mountpoints */ | 304 | /* Deal with crossing mountpoints */ |
294 | if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | 305 | if ((fattr->valid & NFS_ATTR_FATTR_FSID) |
306 | && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | ||
295 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 307 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
296 | inode->i_op = &nfs_referral_inode_operations; | 308 | inode->i_op = &nfs_referral_inode_operations; |
297 | else | 309 | else |
@@ -304,30 +316,49 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
304 | else | 316 | else |
305 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 317 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
306 | 318 | ||
319 | memset(&inode->i_atime, 0, sizeof(inode->i_atime)); | ||
320 | memset(&inode->i_mtime, 0, sizeof(inode->i_mtime)); | ||
321 | memset(&inode->i_ctime, 0, sizeof(inode->i_ctime)); | ||
322 | nfsi->change_attr = 0; | ||
323 | inode->i_size = 0; | ||
324 | inode->i_nlink = 0; | ||
325 | inode->i_uid = -2; | ||
326 | inode->i_gid = -2; | ||
327 | inode->i_blocks = 0; | ||
328 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
329 | |||
307 | nfsi->read_cache_jiffies = fattr->time_start; | 330 | nfsi->read_cache_jiffies = fattr->time_start; |
308 | nfsi->attr_gencount = fattr->gencount; | 331 | nfsi->attr_gencount = fattr->gencount; |
309 | inode->i_atime = fattr->atime; | 332 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
310 | inode->i_mtime = fattr->mtime; | 333 | inode->i_atime = fattr->atime; |
311 | inode->i_ctime = fattr->ctime; | 334 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) |
312 | if (fattr->valid & NFS_ATTR_FATTR_V4) | 335 | inode->i_mtime = fattr->mtime; |
336 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) | ||
337 | inode->i_ctime = fattr->ctime; | ||
338 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | ||
313 | nfsi->change_attr = fattr->change_attr; | 339 | nfsi->change_attr = fattr->change_attr; |
314 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 340 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
315 | inode->i_nlink = fattr->nlink; | 341 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
316 | inode->i_uid = fattr->uid; | 342 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) |
317 | inode->i_gid = fattr->gid; | 343 | inode->i_nlink = fattr->nlink; |
318 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 344 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) |
345 | inode->i_uid = fattr->uid; | ||
346 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) | ||
347 | inode->i_gid = fattr->gid; | ||
348 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
349 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
350 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { | ||
319 | /* | 351 | /* |
320 | * report the blocks in 512byte units | 352 | * report the blocks in 512byte units |
321 | */ | 353 | */ |
322 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 354 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
323 | } else { | ||
324 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
325 | } | 355 | } |
326 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 356 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
327 | nfsi->attrtimeo_timestamp = now; | 357 | nfsi->attrtimeo_timestamp = now; |
328 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
329 | nfsi->access_cache = RB_ROOT; | 358 | nfsi->access_cache = RB_ROOT; |
330 | 359 | ||
360 | nfs_fscache_init_inode_cookie(inode); | ||
361 | |||
331 | unlock_new_inode(inode); | 362 | unlock_new_inode(inode); |
332 | } else | 363 | } else |
333 | nfs_refresh_inode(inode, fattr); | 364 | nfs_refresh_inode(inode, fattr); |
@@ -514,6 +545,32 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
514 | return err; | 545 | return err; |
515 | } | 546 | } |
516 | 547 | ||
548 | /** | ||
549 | * nfs_close_context - Common close_context() routine NFSv2/v3 | ||
550 | * @ctx: pointer to context | ||
551 | * @is_sync: is this a synchronous close | ||
552 | * | ||
553 | * always ensure that the attributes are up to date if we're mounted | ||
554 | * with close-to-open semantics | ||
555 | */ | ||
556 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync) | ||
557 | { | ||
558 | struct inode *inode; | ||
559 | struct nfs_server *server; | ||
560 | |||
561 | if (!(ctx->mode & FMODE_WRITE)) | ||
562 | return; | ||
563 | if (!is_sync) | ||
564 | return; | ||
565 | inode = ctx->path.dentry->d_inode; | ||
566 | if (!list_empty(&NFS_I(inode)->open_files)) | ||
567 | return; | ||
568 | server = NFS_SERVER(inode); | ||
569 | if (server->flags & NFS_MOUNT_NOCTO) | ||
570 | return; | ||
571 | nfs_revalidate_inode(server, inode); | ||
572 | } | ||
573 | |||
517 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) | 574 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) |
518 | { | 575 | { |
519 | struct nfs_open_context *ctx; | 576 | struct nfs_open_context *ctx; |
@@ -540,24 +597,15 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | |||
540 | return ctx; | 597 | return ctx; |
541 | } | 598 | } |
542 | 599 | ||
543 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) | 600 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) |
544 | { | 601 | { |
545 | struct inode *inode; | 602 | struct inode *inode = ctx->path.dentry->d_inode; |
546 | |||
547 | if (ctx == NULL) | ||
548 | return; | ||
549 | 603 | ||
550 | inode = ctx->path.dentry->d_inode; | ||
551 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 604 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) |
552 | return; | 605 | return; |
553 | list_del(&ctx->list); | 606 | list_del(&ctx->list); |
554 | spin_unlock(&inode->i_lock); | 607 | spin_unlock(&inode->i_lock); |
555 | if (ctx->state != NULL) { | 608 | NFS_PROTO(inode)->close_context(ctx, is_sync); |
556 | if (wait) | ||
557 | nfs4_close_sync(&ctx->path, ctx->state, ctx->mode); | ||
558 | else | ||
559 | nfs4_close_state(&ctx->path, ctx->state, ctx->mode); | ||
560 | } | ||
561 | if (ctx->cred != NULL) | 609 | if (ctx->cred != NULL) |
562 | put_rpccred(ctx->cred); | 610 | put_rpccred(ctx->cred); |
563 | path_put(&ctx->path); | 611 | path_put(&ctx->path); |
@@ -642,6 +690,7 @@ int nfs_open(struct inode *inode, struct file *filp) | |||
642 | ctx->mode = filp->f_mode; | 690 | ctx->mode = filp->f_mode; |
643 | nfs_file_set_open_context(filp, ctx); | 691 | nfs_file_set_open_context(filp, ctx); |
644 | put_nfs_open_context(ctx); | 692 | put_nfs_open_context(ctx); |
693 | nfs_fscache_set_inode_cookie(inode, filp); | ||
645 | return 0; | 694 | return 0; |
646 | } | 695 | } |
647 | 696 | ||
@@ -670,9 +719,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
670 | if (NFS_STALE(inode)) | 719 | if (NFS_STALE(inode)) |
671 | goto out; | 720 | goto out; |
672 | 721 | ||
673 | if (NFS_STALE(inode)) | ||
674 | goto out; | ||
675 | |||
676 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 722 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
677 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 723 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
678 | if (status != 0) { | 724 | if (status != 0) { |
@@ -745,6 +791,7 @@ static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_spa | |||
745 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 791 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
746 | spin_unlock(&inode->i_lock); | 792 | spin_unlock(&inode->i_lock); |
747 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 793 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); |
794 | nfs_fscache_reset_inode_cookie(inode); | ||
748 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 795 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
749 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 796 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
750 | return 0; | 797 | return 0; |
@@ -815,25 +862,31 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
815 | { | 862 | { |
816 | struct nfs_inode *nfsi = NFS_I(inode); | 863 | struct nfs_inode *nfsi = NFS_I(inode); |
817 | 864 | ||
818 | if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 && | 865 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) |
819 | nfsi->change_attr == fattr->pre_change_attr) { | 866 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
867 | && nfsi->change_attr == fattr->pre_change_attr) { | ||
820 | nfsi->change_attr = fattr->change_attr; | 868 | nfsi->change_attr = fattr->change_attr; |
821 | if (S_ISDIR(inode->i_mode)) | 869 | if (S_ISDIR(inode->i_mode)) |
822 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 870 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
823 | } | 871 | } |
824 | /* If we have atomic WCC data, we may update some attributes */ | 872 | /* If we have atomic WCC data, we may update some attributes */ |
825 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 873 | if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) |
826 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | 874 | && (fattr->valid & NFS_ATTR_FATTR_CTIME) |
875 | && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | ||
827 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 876 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
828 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 877 | |
878 | if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) | ||
879 | && (fattr->valid & NFS_ATTR_FATTR_MTIME) | ||
880 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | ||
829 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 881 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
830 | if (S_ISDIR(inode->i_mode)) | 882 | if (S_ISDIR(inode->i_mode)) |
831 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 883 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
832 | } | ||
833 | if (i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) && | ||
834 | nfsi->npages == 0) | ||
835 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
836 | } | 884 | } |
885 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | ||
886 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) | ||
887 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) | ||
888 | && nfsi->npages == 0) | ||
889 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
837 | } | 890 | } |
838 | 891 | ||
839 | /** | 892 | /** |
@@ -853,35 +906,39 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
853 | 906 | ||
854 | 907 | ||
855 | /* Has the inode gone and changed behind our back? */ | 908 | /* Has the inode gone and changed behind our back? */ |
856 | if (nfsi->fileid != fattr->fileid | 909 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
857 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 910 | return -EIO; |
911 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | ||
858 | return -EIO; | 912 | return -EIO; |
859 | } | ||
860 | 913 | ||
861 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 914 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
862 | nfsi->change_attr != fattr->change_attr) | 915 | nfsi->change_attr != fattr->change_attr) |
863 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 916 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
864 | 917 | ||
865 | /* Verify a few of the more important attributes */ | 918 | /* Verify a few of the more important attributes */ |
866 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) | 919 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) |
867 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 920 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
868 | 921 | ||
869 | cur_size = i_size_read(inode); | 922 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
870 | new_isize = nfs_size_to_loff_t(fattr->size); | 923 | cur_size = i_size_read(inode); |
871 | if (cur_size != new_isize && nfsi->npages == 0) | 924 | new_isize = nfs_size_to_loff_t(fattr->size); |
872 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 925 | if (cur_size != new_isize && nfsi->npages == 0) |
926 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | ||
927 | } | ||
873 | 928 | ||
874 | /* Have any file permissions changed? */ | 929 | /* Have any file permissions changed? */ |
875 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 930 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) |
876 | || inode->i_uid != fattr->uid | 931 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
877 | || inode->i_gid != fattr->gid) | 932 | if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && inode->i_uid != fattr->uid) |
933 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | ||
934 | if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && inode->i_gid != fattr->gid) | ||
878 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 935 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
879 | 936 | ||
880 | /* Has the link count changed? */ | 937 | /* Has the link count changed? */ |
881 | if (inode->i_nlink != fattr->nlink) | 938 | if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink) |
882 | invalid |= NFS_INO_INVALID_ATTR; | 939 | invalid |= NFS_INO_INVALID_ATTR; |
883 | 940 | ||
884 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 941 | if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime)) |
885 | invalid |= NFS_INO_INVALID_ATIME; | 942 | invalid |= NFS_INO_INVALID_ATIME; |
886 | 943 | ||
887 | if (invalid != 0) | 944 | if (invalid != 0) |
@@ -893,11 +950,15 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
893 | 950 | ||
894 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 951 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
895 | { | 952 | { |
953 | if (!(fattr->valid & NFS_ATTR_FATTR_CTIME)) | ||
954 | return 0; | ||
896 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 955 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
897 | } | 956 | } |
898 | 957 | ||
899 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 958 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
900 | { | 959 | { |
960 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
961 | return 0; | ||
901 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | 962 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); |
902 | } | 963 | } |
903 | 964 | ||
@@ -975,6 +1036,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
975 | spin_lock(&inode->i_lock); | 1036 | spin_lock(&inode->i_lock); |
976 | status = nfs_refresh_inode_locked(inode, fattr); | 1037 | status = nfs_refresh_inode_locked(inode, fattr); |
977 | spin_unlock(&inode->i_lock); | 1038 | spin_unlock(&inode->i_lock); |
1039 | |||
978 | return status; | 1040 | return status; |
979 | } | 1041 | } |
980 | 1042 | ||
@@ -1033,20 +1095,31 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1033 | /* Don't do a WCC update if these attributes are already stale */ | 1095 | /* Don't do a WCC update if these attributes are already stale */ |
1034 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1096 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
1035 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1097 | !nfs_inode_attrs_need_update(inode, fattr)) { |
1036 | fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC); | 1098 | fattr->valid &= ~(NFS_ATTR_FATTR_PRECHANGE |
1099 | | NFS_ATTR_FATTR_PRESIZE | ||
1100 | | NFS_ATTR_FATTR_PREMTIME | ||
1101 | | NFS_ATTR_FATTR_PRECTIME); | ||
1037 | goto out_noforce; | 1102 | goto out_noforce; |
1038 | } | 1103 | } |
1039 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1104 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
1040 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | 1105 | (fattr->valid & NFS_ATTR_FATTR_PRECHANGE) == 0) { |
1041 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1106 | fattr->pre_change_attr = NFS_I(inode)->change_attr; |
1042 | fattr->valid |= NFS_ATTR_WCC_V4; | 1107 | fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; |
1043 | } | 1108 | } |
1044 | if ((fattr->valid & NFS_ATTR_FATTR) != 0 && | 1109 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 && |
1045 | (fattr->valid & NFS_ATTR_WCC) == 0) { | 1110 | (fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) { |
1046 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); | 1111 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); |
1112 | fattr->valid |= NFS_ATTR_FATTR_PRECTIME; | ||
1113 | } | ||
1114 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 && | ||
1115 | (fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) { | ||
1047 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); | 1116 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); |
1117 | fattr->valid |= NFS_ATTR_FATTR_PREMTIME; | ||
1118 | } | ||
1119 | if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 && | ||
1120 | (fattr->valid & NFS_ATTR_FATTR_PRESIZE) == 0) { | ||
1048 | fattr->pre_size = i_size_read(inode); | 1121 | fattr->pre_size = i_size_read(inode); |
1049 | fattr->valid |= NFS_ATTR_WCC; | 1122 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE; |
1050 | } | 1123 | } |
1051 | out_noforce: | 1124 | out_noforce: |
1052 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1125 | status = nfs_post_op_update_inode_locked(inode, fattr); |
@@ -1078,18 +1151,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1078 | __func__, inode->i_sb->s_id, inode->i_ino, | 1151 | __func__, inode->i_sb->s_id, inode->i_ino, |
1079 | atomic_read(&inode->i_count), fattr->valid); | 1152 | atomic_read(&inode->i_count), fattr->valid); |
1080 | 1153 | ||
1081 | if (nfsi->fileid != fattr->fileid) | 1154 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
1082 | goto out_fileid; | 1155 | goto out_fileid; |
1083 | 1156 | ||
1084 | /* | 1157 | /* |
1085 | * Make sure the inode's type hasn't changed. | 1158 | * Make sure the inode's type hasn't changed. |
1086 | */ | 1159 | */ |
1087 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1160 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
1088 | goto out_changed; | 1161 | goto out_changed; |
1089 | 1162 | ||
1090 | server = NFS_SERVER(inode); | 1163 | server = NFS_SERVER(inode); |
1091 | /* Update the fsid? */ | 1164 | /* Update the fsid? */ |
1092 | if (S_ISDIR(inode->i_mode) && | 1165 | if (S_ISDIR(inode->i_mode) && (fattr->valid & NFS_ATTR_FATTR_FSID) && |
1093 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && | 1166 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
1094 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | 1167 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) |
1095 | server->fsid = fattr->fsid; | 1168 | server->fsid = fattr->fsid; |
@@ -1099,14 +1172,27 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1099 | */ | 1172 | */ |
1100 | nfsi->read_cache_jiffies = fattr->time_start; | 1173 | nfsi->read_cache_jiffies = fattr->time_start; |
1101 | 1174 | ||
1102 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ATIME | 1175 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) || (fattr->valid & (NFS_ATTR_FATTR_MTIME|NFS_ATTR_FATTR_CTIME))) |
1103 | | NFS_INO_REVAL_PAGECACHE); | 1176 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR |
1177 | | NFS_INO_INVALID_ATIME | ||
1178 | | NFS_INO_REVAL_PAGECACHE); | ||
1104 | 1179 | ||
1105 | /* Do atomic weak cache consistency updates */ | 1180 | /* Do atomic weak cache consistency updates */ |
1106 | nfs_wcc_update_inode(inode, fattr); | 1181 | nfs_wcc_update_inode(inode, fattr); |
1107 | 1182 | ||
1108 | /* More cache consistency checks */ | 1183 | /* More cache consistency checks */ |
1109 | if (!(fattr->valid & NFS_ATTR_FATTR_V4)) { | 1184 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { |
1185 | if (nfsi->change_attr != fattr->change_attr) { | ||
1186 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1187 | inode->i_sb->s_id, inode->i_ino); | ||
1188 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1189 | if (S_ISDIR(inode->i_mode)) | ||
1190 | nfs_force_lookup_revalidate(inode); | ||
1191 | nfsi->change_attr = fattr->change_attr; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) { | ||
1110 | /* NFSv2/v3: Check if the mtime agrees */ | 1196 | /* NFSv2/v3: Check if the mtime agrees */ |
1111 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1197 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1112 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1198 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
@@ -1114,59 +1200,80 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1114 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1200 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1115 | if (S_ISDIR(inode->i_mode)) | 1201 | if (S_ISDIR(inode->i_mode)) |
1116 | nfs_force_lookup_revalidate(inode); | 1202 | nfs_force_lookup_revalidate(inode); |
1203 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | ||
1117 | } | 1204 | } |
1205 | } | ||
1206 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) { | ||
1118 | /* If ctime has changed we should definitely clear access+acl caches */ | 1207 | /* If ctime has changed we should definitely clear access+acl caches */ |
1119 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1208 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1120 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1209 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1121 | } else if (nfsi->change_attr != fattr->change_attr) { | 1210 | /* and probably clear data for a directory too as utimes can cause |
1122 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1211 | * havoc with our cache. |
1123 | inode->i_sb->s_id, inode->i_ino); | 1212 | */ |
1124 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1213 | if (S_ISDIR(inode->i_mode)) { |
1125 | if (S_ISDIR(inode->i_mode)) | 1214 | invalid |= NFS_INO_INVALID_DATA; |
1126 | nfs_force_lookup_revalidate(inode); | 1215 | nfs_force_lookup_revalidate(inode); |
1216 | } | ||
1217 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | ||
1218 | } | ||
1127 | } | 1219 | } |
1128 | 1220 | ||
1129 | /* Check if our cached file size is stale */ | 1221 | /* Check if our cached file size is stale */ |
1130 | new_isize = nfs_size_to_loff_t(fattr->size); | 1222 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1131 | cur_isize = i_size_read(inode); | 1223 | new_isize = nfs_size_to_loff_t(fattr->size); |
1132 | if (new_isize != cur_isize) { | 1224 | cur_isize = i_size_read(inode); |
1133 | /* Do we perhaps have any outstanding writes, or has | 1225 | if (new_isize != cur_isize) { |
1134 | * the file grown beyond our last write? */ | 1226 | /* Do we perhaps have any outstanding writes, or has |
1135 | if (nfsi->npages == 0 || new_isize > cur_isize) { | 1227 | * the file grown beyond our last write? */ |
1136 | i_size_write(inode, new_isize); | 1228 | if (nfsi->npages == 0 || new_isize > cur_isize) { |
1137 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1229 | i_size_write(inode, new_isize); |
1230 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
1231 | } | ||
1232 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1233 | inode->i_sb->s_id, inode->i_ino); | ||
1138 | } | 1234 | } |
1139 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1140 | inode->i_sb->s_id, inode->i_ino); | ||
1141 | } | 1235 | } |
1142 | 1236 | ||
1143 | 1237 | ||
1144 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1238 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
1145 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1239 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1146 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | ||
1147 | nfsi->change_attr = fattr->change_attr; | ||
1148 | |||
1149 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || | ||
1150 | inode->i_uid != fattr->uid || | ||
1151 | inode->i_gid != fattr->gid) | ||
1152 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1153 | 1240 | ||
1154 | if (inode->i_nlink != fattr->nlink) | 1241 | if (fattr->valid & NFS_ATTR_FATTR_MODE) { |
1155 | invalid |= NFS_INO_INVALID_ATTR; | 1242 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) { |
1243 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1244 | inode->i_mode = fattr->mode; | ||
1245 | } | ||
1246 | } | ||
1247 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) { | ||
1248 | if (inode->i_uid != fattr->uid) { | ||
1249 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1250 | inode->i_uid = fattr->uid; | ||
1251 | } | ||
1252 | } | ||
1253 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) { | ||
1254 | if (inode->i_gid != fattr->gid) { | ||
1255 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1256 | inode->i_gid = fattr->gid; | ||
1257 | } | ||
1258 | } | ||
1156 | 1259 | ||
1157 | inode->i_mode = fattr->mode; | 1260 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) { |
1158 | inode->i_nlink = fattr->nlink; | 1261 | if (inode->i_nlink != fattr->nlink) { |
1159 | inode->i_uid = fattr->uid; | 1262 | invalid |= NFS_INO_INVALID_ATTR; |
1160 | inode->i_gid = fattr->gid; | 1263 | if (S_ISDIR(inode->i_mode)) |
1264 | invalid |= NFS_INO_INVALID_DATA; | ||
1265 | inode->i_nlink = fattr->nlink; | ||
1266 | } | ||
1267 | } | ||
1161 | 1268 | ||
1162 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 1269 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { |
1163 | /* | 1270 | /* |
1164 | * report the blocks in 512byte units | 1271 | * report the blocks in 512byte units |
1165 | */ | 1272 | */ |
1166 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 1273 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
1167 | } else { | ||
1168 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1169 | } | 1274 | } |
1275 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
1276 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1170 | 1277 | ||
1171 | /* Update attrtimeo value if we're out of the unstable period */ | 1278 | /* Update attrtimeo value if we're out of the unstable period */ |
1172 | if (invalid & NFS_INO_INVALID_ATTR) { | 1279 | if (invalid & NFS_INO_INVALID_ATTR) { |
@@ -1274,7 +1381,6 @@ static void init_once(void *foo) | |||
1274 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | 1381 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); |
1275 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | 1382 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); |
1276 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 1383 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
1277 | nfsi->ncommit = 0; | ||
1278 | nfsi->npages = 0; | 1384 | nfsi->npages = 0; |
1279 | atomic_set(&nfsi->silly_count, 1); | 1385 | atomic_set(&nfsi->silly_count, 1); |
1280 | INIT_HLIST_HEAD(&nfsi->silly_list); | 1386 | INIT_HLIST_HEAD(&nfsi->silly_list); |
@@ -1337,6 +1443,10 @@ static int __init init_nfs_fs(void) | |||
1337 | { | 1443 | { |
1338 | int err; | 1444 | int err; |
1339 | 1445 | ||
1446 | err = nfs_fscache_register(); | ||
1447 | if (err < 0) | ||
1448 | goto out7; | ||
1449 | |||
1340 | err = nfsiod_start(); | 1450 | err = nfsiod_start(); |
1341 | if (err) | 1451 | if (err) |
1342 | goto out6; | 1452 | goto out6; |
@@ -1389,6 +1499,8 @@ out4: | |||
1389 | out5: | 1499 | out5: |
1390 | nfsiod_stop(); | 1500 | nfsiod_stop(); |
1391 | out6: | 1501 | out6: |
1502 | nfs_fscache_unregister(); | ||
1503 | out7: | ||
1392 | return err; | 1504 | return err; |
1393 | } | 1505 | } |
1394 | 1506 | ||
@@ -1399,6 +1511,7 @@ static void __exit exit_nfs_fs(void) | |||
1399 | nfs_destroy_readpagecache(); | 1511 | nfs_destroy_readpagecache(); |
1400 | nfs_destroy_inodecache(); | 1512 | nfs_destroy_inodecache(); |
1401 | nfs_destroy_nfspagecache(); | 1513 | nfs_destroy_nfspagecache(); |
1514 | nfs_fscache_unregister(); | ||
1402 | #ifdef CONFIG_PROC_FS | 1515 | #ifdef CONFIG_PROC_FS |
1403 | rpc_proc_unregister("nfs"); | 1516 | rpc_proc_unregister("nfs"); |
1404 | #endif | 1517 | #endif |