diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-01 13:58:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-01 13:58:42 -0400 |
commit | 4fe70410d9a219dabb47328effccae7e7f2a6e26 (patch) | |
tree | 7f36d6cd27333fa28447f06ce37a6fecceb42955 /fs/nfs/inode.c | |
parent | 395d73413c5656c6d7706ae91dcb441f9b7e3074 (diff) | |
parent | cc85906110e26fe8537c3bdbc08a74ae8110030b (diff) |
Merge branch 'for-linus' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'for-linus' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (58 commits)
SUNRPC: Ensure IPV6_V6ONLY is set on the socket before binding to a port
NSM: Fix unaligned accesses in nsm_init_private()
NFS: Simplify logic to compare socket addresses in client.c
NFS: Start PF_INET6 callback listener only if IPv6 support is available
lockd: Start PF_INET6 listener only if IPv6 support is available
SUNRPC: Remove CONFIG_SUNRPC_REGISTER_V4
SUNRPC: rpcb_register() should handle errors silently
SUNRPC: Simplify kernel RPC service registration
SUNRPC: Simplify svc_unregister()
SUNRPC: Allow callers to pass rpcb_v4_register a NULL address
SUNRPC: rpcbind actually interprets r_owner string
SUNRPC: Clean up address type casts in rpcb_v4_register()
SUNRPC: Don't return EPROTONOSUPPORT in svc_register()'s helpers
SUNRPC: Use IPv4 loopback for registering AF_INET6 kernel RPC services
SUNRPC: Set IPV6ONLY flag on PF_INET6 RPC listener sockets
NFS: Revert creation of IPv6 listeners for lockd and NFSv4 callbacks
SUNRPC: Remove @family argument from svc_create() and svc_create_pooled()
SUNRPC: Change svc_create_xprt() to take a @family argument
SUNRPC: svc_setup_socket() gets protocol family from socket
SUNRPC: Pass a family argument to svc_register()
...
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 309 |
1 files changed, 204 insertions, 105 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 0c381686171e..a834d1d850b7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -66,6 +66,18 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks | ||
70 | * @word: long word containing the bit lock | ||
71 | */ | ||
72 | int nfs_wait_bit_killable(void *word) | ||
73 | { | ||
74 | if (fatal_signal_pending(current)) | ||
75 | return -ERESTARTSYS; | ||
76 | schedule(); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | /** | ||
69 | * nfs_compat_user_ino64 - returns the user-visible inode number | 81 | * nfs_compat_user_ino64 - returns the user-visible inode number |
70 | * @fileid: 64-bit fileid | 82 | * @fileid: 64-bit fileid |
71 | * | 83 | * |
@@ -249,13 +261,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
249 | struct inode *inode = ERR_PTR(-ENOENT); | 261 | struct inode *inode = ERR_PTR(-ENOENT); |
250 | unsigned long hash; | 262 | unsigned long hash; |
251 | 263 | ||
252 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 264 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) |
253 | goto out_no_inode; | 265 | goto out_no_inode; |
254 | 266 | 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; | 267 | goto out_no_inode; |
258 | } | ||
259 | 268 | ||
260 | hash = nfs_fattr_to_ino_t(fattr); | 269 | hash = nfs_fattr_to_ino_t(fattr); |
261 | 270 | ||
@@ -291,7 +300,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
291 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 300 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
292 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 301 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
293 | /* Deal with crossing mountpoints */ | 302 | /* Deal with crossing mountpoints */ |
294 | if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | 303 | if ((fattr->valid & NFS_ATTR_FATTR_FSID) |
304 | && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | ||
295 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 305 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
296 | inode->i_op = &nfs_referral_inode_operations; | 306 | inode->i_op = &nfs_referral_inode_operations; |
297 | else | 307 | else |
@@ -304,28 +314,45 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
304 | else | 314 | else |
305 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 315 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
306 | 316 | ||
317 | memset(&inode->i_atime, 0, sizeof(inode->i_atime)); | ||
318 | memset(&inode->i_mtime, 0, sizeof(inode->i_mtime)); | ||
319 | memset(&inode->i_ctime, 0, sizeof(inode->i_ctime)); | ||
320 | nfsi->change_attr = 0; | ||
321 | inode->i_size = 0; | ||
322 | inode->i_nlink = 0; | ||
323 | inode->i_uid = -2; | ||
324 | inode->i_gid = -2; | ||
325 | inode->i_blocks = 0; | ||
326 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
327 | |||
307 | nfsi->read_cache_jiffies = fattr->time_start; | 328 | nfsi->read_cache_jiffies = fattr->time_start; |
308 | nfsi->attr_gencount = fattr->gencount; | 329 | nfsi->attr_gencount = fattr->gencount; |
309 | inode->i_atime = fattr->atime; | 330 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
310 | inode->i_mtime = fattr->mtime; | 331 | inode->i_atime = fattr->atime; |
311 | inode->i_ctime = fattr->ctime; | 332 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) |
312 | if (fattr->valid & NFS_ATTR_FATTR_V4) | 333 | inode->i_mtime = fattr->mtime; |
334 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) | ||
335 | inode->i_ctime = fattr->ctime; | ||
336 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | ||
313 | nfsi->change_attr = fattr->change_attr; | 337 | nfsi->change_attr = fattr->change_attr; |
314 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 338 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
315 | inode->i_nlink = fattr->nlink; | 339 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
316 | inode->i_uid = fattr->uid; | 340 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) |
317 | inode->i_gid = fattr->gid; | 341 | inode->i_nlink = fattr->nlink; |
318 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 342 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) |
343 | inode->i_uid = fattr->uid; | ||
344 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) | ||
345 | inode->i_gid = fattr->gid; | ||
346 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
347 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
348 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { | ||
319 | /* | 349 | /* |
320 | * report the blocks in 512byte units | 350 | * report the blocks in 512byte units |
321 | */ | 351 | */ |
322 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 352 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
323 | } else { | ||
324 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
325 | } | 353 | } |
326 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 354 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
327 | nfsi->attrtimeo_timestamp = now; | 355 | nfsi->attrtimeo_timestamp = now; |
328 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
329 | nfsi->access_cache = RB_ROOT; | 356 | nfsi->access_cache = RB_ROOT; |
330 | 357 | ||
331 | unlock_new_inode(inode); | 358 | unlock_new_inode(inode); |
@@ -514,6 +541,32 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
514 | return err; | 541 | return err; |
515 | } | 542 | } |
516 | 543 | ||
544 | /** | ||
545 | * nfs_close_context - Common close_context() routine NFSv2/v3 | ||
546 | * @ctx: pointer to context | ||
547 | * @is_sync: is this a synchronous close | ||
548 | * | ||
549 | * always ensure that the attributes are up to date if we're mounted | ||
550 | * with close-to-open semantics | ||
551 | */ | ||
552 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync) | ||
553 | { | ||
554 | struct inode *inode; | ||
555 | struct nfs_server *server; | ||
556 | |||
557 | if (!(ctx->mode & FMODE_WRITE)) | ||
558 | return; | ||
559 | if (!is_sync) | ||
560 | return; | ||
561 | inode = ctx->path.dentry->d_inode; | ||
562 | if (!list_empty(&NFS_I(inode)->open_files)) | ||
563 | return; | ||
564 | server = NFS_SERVER(inode); | ||
565 | if (server->flags & NFS_MOUNT_NOCTO) | ||
566 | return; | ||
567 | nfs_revalidate_inode(server, inode); | ||
568 | } | ||
569 | |||
517 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) | 570 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) |
518 | { | 571 | { |
519 | struct nfs_open_context *ctx; | 572 | struct nfs_open_context *ctx; |
@@ -540,24 +593,15 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | |||
540 | return ctx; | 593 | return ctx; |
541 | } | 594 | } |
542 | 595 | ||
543 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) | 596 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) |
544 | { | 597 | { |
545 | struct inode *inode; | 598 | struct inode *inode = ctx->path.dentry->d_inode; |
546 | |||
547 | if (ctx == NULL) | ||
548 | return; | ||
549 | 599 | ||
550 | inode = ctx->path.dentry->d_inode; | ||
551 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 600 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) |
552 | return; | 601 | return; |
553 | list_del(&ctx->list); | 602 | list_del(&ctx->list); |
554 | spin_unlock(&inode->i_lock); | 603 | spin_unlock(&inode->i_lock); |
555 | if (ctx->state != NULL) { | 604 | 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) | 605 | if (ctx->cred != NULL) |
562 | put_rpccred(ctx->cred); | 606 | put_rpccred(ctx->cred); |
563 | path_put(&ctx->path); | 607 | path_put(&ctx->path); |
@@ -670,9 +714,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
670 | if (NFS_STALE(inode)) | 714 | if (NFS_STALE(inode)) |
671 | goto out; | 715 | goto out; |
672 | 716 | ||
673 | if (NFS_STALE(inode)) | ||
674 | goto out; | ||
675 | |||
676 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 717 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
677 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 718 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
678 | if (status != 0) { | 719 | if (status != 0) { |
@@ -815,25 +856,31 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
815 | { | 856 | { |
816 | struct nfs_inode *nfsi = NFS_I(inode); | 857 | struct nfs_inode *nfsi = NFS_I(inode); |
817 | 858 | ||
818 | if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 && | 859 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) |
819 | nfsi->change_attr == fattr->pre_change_attr) { | 860 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
861 | && nfsi->change_attr == fattr->pre_change_attr) { | ||
820 | nfsi->change_attr = fattr->change_attr; | 862 | nfsi->change_attr = fattr->change_attr; |
821 | if (S_ISDIR(inode->i_mode)) | 863 | if (S_ISDIR(inode->i_mode)) |
822 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 864 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
823 | } | 865 | } |
824 | /* If we have atomic WCC data, we may update some attributes */ | 866 | /* If we have atomic WCC data, we may update some attributes */ |
825 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 867 | if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) |
826 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | 868 | && (fattr->valid & NFS_ATTR_FATTR_CTIME) |
869 | && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | ||
827 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 870 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
828 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 871 | |
872 | if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) | ||
873 | && (fattr->valid & NFS_ATTR_FATTR_MTIME) | ||
874 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | ||
829 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 875 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
830 | if (S_ISDIR(inode->i_mode)) | 876 | if (S_ISDIR(inode->i_mode)) |
831 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 877 | 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 | } | 878 | } |
879 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | ||
880 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) | ||
881 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) | ||
882 | && nfsi->npages == 0) | ||
883 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
837 | } | 884 | } |
838 | 885 | ||
839 | /** | 886 | /** |
@@ -853,35 +900,39 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
853 | 900 | ||
854 | 901 | ||
855 | /* Has the inode gone and changed behind our back? */ | 902 | /* Has the inode gone and changed behind our back? */ |
856 | if (nfsi->fileid != fattr->fileid | 903 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
857 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 904 | return -EIO; |
905 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | ||
858 | return -EIO; | 906 | return -EIO; |
859 | } | ||
860 | 907 | ||
861 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 908 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
862 | nfsi->change_attr != fattr->change_attr) | 909 | nfsi->change_attr != fattr->change_attr) |
863 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 910 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
864 | 911 | ||
865 | /* Verify a few of the more important attributes */ | 912 | /* Verify a few of the more important attributes */ |
866 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) | 913 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) |
867 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 914 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
868 | 915 | ||
869 | cur_size = i_size_read(inode); | 916 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
870 | new_isize = nfs_size_to_loff_t(fattr->size); | 917 | cur_size = i_size_read(inode); |
871 | if (cur_size != new_isize && nfsi->npages == 0) | 918 | new_isize = nfs_size_to_loff_t(fattr->size); |
872 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 919 | if (cur_size != new_isize && nfsi->npages == 0) |
920 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | ||
921 | } | ||
873 | 922 | ||
874 | /* Have any file permissions changed? */ | 923 | /* Have any file permissions changed? */ |
875 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 924 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) |
876 | || inode->i_uid != fattr->uid | 925 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
877 | || inode->i_gid != fattr->gid) | 926 | if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && inode->i_uid != fattr->uid) |
927 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | ||
928 | 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; | 929 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
879 | 930 | ||
880 | /* Has the link count changed? */ | 931 | /* Has the link count changed? */ |
881 | if (inode->i_nlink != fattr->nlink) | 932 | if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink) |
882 | invalid |= NFS_INO_INVALID_ATTR; | 933 | invalid |= NFS_INO_INVALID_ATTR; |
883 | 934 | ||
884 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 935 | if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime)) |
885 | invalid |= NFS_INO_INVALID_ATIME; | 936 | invalid |= NFS_INO_INVALID_ATIME; |
886 | 937 | ||
887 | if (invalid != 0) | 938 | if (invalid != 0) |
@@ -893,11 +944,15 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
893 | 944 | ||
894 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 945 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
895 | { | 946 | { |
947 | if (!(fattr->valid & NFS_ATTR_FATTR_CTIME)) | ||
948 | return 0; | ||
896 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 949 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
897 | } | 950 | } |
898 | 951 | ||
899 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 952 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
900 | { | 953 | { |
954 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
955 | return 0; | ||
901 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | 956 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); |
902 | } | 957 | } |
903 | 958 | ||
@@ -1033,20 +1088,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 */ | 1088 | /* Don't do a WCC update if these attributes are already stale */ |
1034 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1089 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
1035 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1090 | !nfs_inode_attrs_need_update(inode, fattr)) { |
1036 | fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC); | 1091 | fattr->valid &= ~(NFS_ATTR_FATTR_PRECHANGE |
1092 | | NFS_ATTR_FATTR_PRESIZE | ||
1093 | | NFS_ATTR_FATTR_PREMTIME | ||
1094 | | NFS_ATTR_FATTR_PRECTIME); | ||
1037 | goto out_noforce; | 1095 | goto out_noforce; |
1038 | } | 1096 | } |
1039 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1097 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
1040 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | 1098 | (fattr->valid & NFS_ATTR_FATTR_PRECHANGE) == 0) { |
1041 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1099 | fattr->pre_change_attr = NFS_I(inode)->change_attr; |
1042 | fattr->valid |= NFS_ATTR_WCC_V4; | 1100 | fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; |
1043 | } | 1101 | } |
1044 | if ((fattr->valid & NFS_ATTR_FATTR) != 0 && | 1102 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 && |
1045 | (fattr->valid & NFS_ATTR_WCC) == 0) { | 1103 | (fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) { |
1046 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); | 1104 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); |
1105 | fattr->valid |= NFS_ATTR_FATTR_PRECTIME; | ||
1106 | } | ||
1107 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 && | ||
1108 | (fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) { | ||
1047 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); | 1109 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); |
1110 | fattr->valid |= NFS_ATTR_FATTR_PREMTIME; | ||
1111 | } | ||
1112 | if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 && | ||
1113 | (fattr->valid & NFS_ATTR_FATTR_PRESIZE) == 0) { | ||
1048 | fattr->pre_size = i_size_read(inode); | 1114 | fattr->pre_size = i_size_read(inode); |
1049 | fattr->valid |= NFS_ATTR_WCC; | 1115 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE; |
1050 | } | 1116 | } |
1051 | out_noforce: | 1117 | out_noforce: |
1052 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1118 | status = nfs_post_op_update_inode_locked(inode, fattr); |
@@ -1078,18 +1144,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1078 | __func__, inode->i_sb->s_id, inode->i_ino, | 1144 | __func__, inode->i_sb->s_id, inode->i_ino, |
1079 | atomic_read(&inode->i_count), fattr->valid); | 1145 | atomic_read(&inode->i_count), fattr->valid); |
1080 | 1146 | ||
1081 | if (nfsi->fileid != fattr->fileid) | 1147 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
1082 | goto out_fileid; | 1148 | goto out_fileid; |
1083 | 1149 | ||
1084 | /* | 1150 | /* |
1085 | * Make sure the inode's type hasn't changed. | 1151 | * Make sure the inode's type hasn't changed. |
1086 | */ | 1152 | */ |
1087 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1153 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
1088 | goto out_changed; | 1154 | goto out_changed; |
1089 | 1155 | ||
1090 | server = NFS_SERVER(inode); | 1156 | server = NFS_SERVER(inode); |
1091 | /* Update the fsid? */ | 1157 | /* Update the fsid? */ |
1092 | if (S_ISDIR(inode->i_mode) && | 1158 | if (S_ISDIR(inode->i_mode) && (fattr->valid & NFS_ATTR_FATTR_FSID) && |
1093 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && | 1159 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
1094 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | 1160 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) |
1095 | server->fsid = fattr->fsid; | 1161 | server->fsid = fattr->fsid; |
@@ -1099,14 +1165,27 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1099 | */ | 1165 | */ |
1100 | nfsi->read_cache_jiffies = fattr->time_start; | 1166 | nfsi->read_cache_jiffies = fattr->time_start; |
1101 | 1167 | ||
1102 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ATIME | 1168 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) || (fattr->valid & (NFS_ATTR_FATTR_MTIME|NFS_ATTR_FATTR_CTIME))) |
1103 | | NFS_INO_REVAL_PAGECACHE); | 1169 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR |
1170 | | NFS_INO_INVALID_ATIME | ||
1171 | | NFS_INO_REVAL_PAGECACHE); | ||
1104 | 1172 | ||
1105 | /* Do atomic weak cache consistency updates */ | 1173 | /* Do atomic weak cache consistency updates */ |
1106 | nfs_wcc_update_inode(inode, fattr); | 1174 | nfs_wcc_update_inode(inode, fattr); |
1107 | 1175 | ||
1108 | /* More cache consistency checks */ | 1176 | /* More cache consistency checks */ |
1109 | if (!(fattr->valid & NFS_ATTR_FATTR_V4)) { | 1177 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { |
1178 | if (nfsi->change_attr != fattr->change_attr) { | ||
1179 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1180 | inode->i_sb->s_id, inode->i_ino); | ||
1181 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1182 | if (S_ISDIR(inode->i_mode)) | ||
1183 | nfs_force_lookup_revalidate(inode); | ||
1184 | nfsi->change_attr = fattr->change_attr; | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) { | ||
1110 | /* NFSv2/v3: Check if the mtime agrees */ | 1189 | /* NFSv2/v3: Check if the mtime agrees */ |
1111 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1190 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1112 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1191 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
@@ -1114,59 +1193,80 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1114 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1193 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1115 | if (S_ISDIR(inode->i_mode)) | 1194 | if (S_ISDIR(inode->i_mode)) |
1116 | nfs_force_lookup_revalidate(inode); | 1195 | nfs_force_lookup_revalidate(inode); |
1196 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | ||
1117 | } | 1197 | } |
1198 | } | ||
1199 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) { | ||
1118 | /* If ctime has changed we should definitely clear access+acl caches */ | 1200 | /* If ctime has changed we should definitely clear access+acl caches */ |
1119 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1201 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1120 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1202 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1121 | } else if (nfsi->change_attr != fattr->change_attr) { | 1203 | /* 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", | 1204 | * havoc with our cache. |
1123 | inode->i_sb->s_id, inode->i_ino); | 1205 | */ |
1124 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1206 | if (S_ISDIR(inode->i_mode)) { |
1125 | if (S_ISDIR(inode->i_mode)) | 1207 | invalid |= NFS_INO_INVALID_DATA; |
1126 | nfs_force_lookup_revalidate(inode); | 1208 | nfs_force_lookup_revalidate(inode); |
1209 | } | ||
1210 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | ||
1211 | } | ||
1127 | } | 1212 | } |
1128 | 1213 | ||
1129 | /* Check if our cached file size is stale */ | 1214 | /* Check if our cached file size is stale */ |
1130 | new_isize = nfs_size_to_loff_t(fattr->size); | 1215 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1131 | cur_isize = i_size_read(inode); | 1216 | new_isize = nfs_size_to_loff_t(fattr->size); |
1132 | if (new_isize != cur_isize) { | 1217 | cur_isize = i_size_read(inode); |
1133 | /* Do we perhaps have any outstanding writes, or has | 1218 | if (new_isize != cur_isize) { |
1134 | * the file grown beyond our last write? */ | 1219 | /* Do we perhaps have any outstanding writes, or has |
1135 | if (nfsi->npages == 0 || new_isize > cur_isize) { | 1220 | * the file grown beyond our last write? */ |
1136 | i_size_write(inode, new_isize); | 1221 | if (nfsi->npages == 0 || new_isize > cur_isize) { |
1137 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1222 | i_size_write(inode, new_isize); |
1223 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
1224 | } | ||
1225 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1226 | inode->i_sb->s_id, inode->i_ino); | ||
1138 | } | 1227 | } |
1139 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1140 | inode->i_sb->s_id, inode->i_ino); | ||
1141 | } | 1228 | } |
1142 | 1229 | ||
1143 | 1230 | ||
1144 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1231 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
1145 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1232 | 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 | 1233 | ||
1154 | if (inode->i_nlink != fattr->nlink) | 1234 | if (fattr->valid & NFS_ATTR_FATTR_MODE) { |
1155 | invalid |= NFS_INO_INVALID_ATTR; | 1235 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) { |
1236 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1237 | inode->i_mode = fattr->mode; | ||
1238 | } | ||
1239 | } | ||
1240 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) { | ||
1241 | if (inode->i_uid != fattr->uid) { | ||
1242 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1243 | inode->i_uid = fattr->uid; | ||
1244 | } | ||
1245 | } | ||
1246 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) { | ||
1247 | if (inode->i_gid != fattr->gid) { | ||
1248 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1249 | inode->i_gid = fattr->gid; | ||
1250 | } | ||
1251 | } | ||
1156 | 1252 | ||
1157 | inode->i_mode = fattr->mode; | 1253 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) { |
1158 | inode->i_nlink = fattr->nlink; | 1254 | if (inode->i_nlink != fattr->nlink) { |
1159 | inode->i_uid = fattr->uid; | 1255 | invalid |= NFS_INO_INVALID_ATTR; |
1160 | inode->i_gid = fattr->gid; | 1256 | if (S_ISDIR(inode->i_mode)) |
1257 | invalid |= NFS_INO_INVALID_DATA; | ||
1258 | inode->i_nlink = fattr->nlink; | ||
1259 | } | ||
1260 | } | ||
1161 | 1261 | ||
1162 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 1262 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { |
1163 | /* | 1263 | /* |
1164 | * report the blocks in 512byte units | 1264 | * report the blocks in 512byte units |
1165 | */ | 1265 | */ |
1166 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 1266 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
1167 | } else { | ||
1168 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1169 | } | 1267 | } |
1268 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
1269 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1170 | 1270 | ||
1171 | /* Update attrtimeo value if we're out of the unstable period */ | 1271 | /* Update attrtimeo value if we're out of the unstable period */ |
1172 | if (invalid & NFS_INO_INVALID_ATTR) { | 1272 | if (invalid & NFS_INO_INVALID_ATTR) { |
@@ -1274,7 +1374,6 @@ static void init_once(void *foo) | |||
1274 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | 1374 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); |
1275 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | 1375 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); |
1276 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 1376 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
1277 | nfsi->ncommit = 0; | ||
1278 | nfsi->npages = 0; | 1377 | nfsi->npages = 0; |
1279 | atomic_set(&nfsi->silly_count, 1); | 1378 | atomic_set(&nfsi->silly_count, 1); |
1280 | INIT_HLIST_HEAD(&nfsi->silly_list); | 1379 | INIT_HLIST_HEAD(&nfsi->silly_list); |