diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/dir.c | 4 | ||||
-rw-r--r-- | fs/nfs/inode.c | 69 |
2 files changed, 45 insertions, 28 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 5732e13cd0da..27cf5577f239 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -182,7 +182,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
182 | /* We requested READDIRPLUS, but the server doesn't grok it */ | 182 | /* We requested READDIRPLUS, but the server doesn't grok it */ |
183 | if (error == -ENOTSUPP && desc->plus) { | 183 | if (error == -ENOTSUPP && desc->plus) { |
184 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; | 184 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; |
185 | NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; | 185 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
186 | desc->plus = 0; | 186 | desc->plus = 0; |
187 | goto again; | 187 | goto again; |
188 | } | 188 | } |
@@ -545,7 +545,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
545 | break; | 545 | break; |
546 | } | 546 | } |
547 | if (res == -ETOOSMALL && desc->plus) { | 547 | if (res == -ETOOSMALL && desc->plus) { |
548 | NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; | 548 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
549 | nfs_zap_caches(inode); | 549 | nfs_zap_caches(inode); |
550 | desc->plus = 0; | 550 | desc->plus = 0; |
551 | desc->entry->eof = 0; | 551 | desc->entry->eof = 0; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 622184553516..ee27578277f3 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -739,7 +739,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
739 | inode->i_fop = &nfs_dir_operations; | 739 | inode->i_fop = &nfs_dir_operations; |
740 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) | 740 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) |
741 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 741 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
742 | NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS; | 742 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
743 | } else if (S_ISLNK(inode->i_mode)) | 743 | } else if (S_ISLNK(inode->i_mode)) |
744 | inode->i_op = &nfs_symlink_inode_operations; | 744 | inode->i_op = &nfs_symlink_inode_operations; |
745 | else | 745 | else |
@@ -849,26 +849,43 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
849 | } | 849 | } |
850 | } | 850 | } |
851 | 851 | ||
852 | static int nfs_wait_schedule(void *word) | ||
853 | { | ||
854 | if (signal_pending(current)) | ||
855 | return -ERESTARTSYS; | ||
856 | schedule(); | ||
857 | return 0; | ||
858 | } | ||
859 | |||
852 | /* | 860 | /* |
853 | * Wait for the inode to get unlocked. | 861 | * Wait for the inode to get unlocked. |
854 | * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING). | ||
855 | */ | 862 | */ |
856 | static int | 863 | static int nfs_wait_on_inode(struct inode *inode) |
857 | nfs_wait_on_inode(struct inode *inode, int flag) | ||
858 | { | 864 | { |
859 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | 865 | struct rpc_clnt *clnt = NFS_CLIENT(inode); |
860 | struct nfs_inode *nfsi = NFS_I(inode); | 866 | struct nfs_inode *nfsi = NFS_I(inode); |
861 | 867 | sigset_t oldmask; | |
862 | int error; | 868 | int error; |
863 | if (!(NFS_FLAGS(inode) & flag)) | 869 | |
864 | return 0; | ||
865 | atomic_inc(&inode->i_count); | 870 | atomic_inc(&inode->i_count); |
866 | error = nfs_wait_event(clnt, nfsi->nfs_i_wait, | 871 | rpc_clnt_sigmask(clnt, &oldmask); |
867 | !(NFS_FLAGS(inode) & flag)); | 872 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, |
873 | nfs_wait_schedule, TASK_INTERRUPTIBLE); | ||
874 | rpc_clnt_sigunmask(clnt, &oldmask); | ||
868 | iput(inode); | 875 | iput(inode); |
876 | |||
869 | return error; | 877 | return error; |
870 | } | 878 | } |
871 | 879 | ||
880 | static void nfs_wake_up_inode(struct inode *inode) | ||
881 | { | ||
882 | struct nfs_inode *nfsi = NFS_I(inode); | ||
883 | |||
884 | clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); | ||
885 | smp_mb__after_clear_bit(); | ||
886 | wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); | ||
887 | } | ||
888 | |||
872 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 889 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
873 | { | 890 | { |
874 | struct inode *inode = dentry->d_inode; | 891 | struct inode *inode = dentry->d_inode; |
@@ -1029,18 +1046,19 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1029 | if (NFS_STALE(inode)) | 1046 | if (NFS_STALE(inode)) |
1030 | goto out_nowait; | 1047 | goto out_nowait; |
1031 | 1048 | ||
1032 | while (NFS_REVALIDATING(inode)) { | 1049 | status = nfs_wait_on_inode(inode); |
1033 | status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING); | 1050 | if (status < 0) |
1034 | if (status < 0) | 1051 | goto out; |
1035 | goto out_nowait; | 1052 | if (NFS_STALE(inode)) { |
1036 | if (NFS_ATTRTIMEO(inode) == 0) | 1053 | status = -ESTALE; |
1037 | continue; | 1054 | /* Do we trust the cached ESTALE? */ |
1038 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) | 1055 | if (NFS_ATTRTIMEO(inode) != 0) { |
1039 | continue; | 1056 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) { |
1040 | status = NFS_STALE(inode) ? -ESTALE : 0; | 1057 | /* no */ |
1041 | goto out_nowait; | 1058 | } else |
1059 | goto out; | ||
1060 | } | ||
1042 | } | 1061 | } |
1043 | NFS_FLAGS(inode) |= NFS_INO_REVALIDATING; | ||
1044 | 1062 | ||
1045 | /* Protect against RPC races by saving the change attribute */ | 1063 | /* Protect against RPC races by saving the change attribute */ |
1046 | verifier = nfs_save_change_attribute(inode); | 1064 | verifier = nfs_save_change_attribute(inode); |
@@ -1052,7 +1070,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1052 | if (status == -ESTALE) { | 1070 | if (status == -ESTALE) { |
1053 | nfs_zap_caches(inode); | 1071 | nfs_zap_caches(inode); |
1054 | if (!S_ISDIR(inode->i_mode)) | 1072 | if (!S_ISDIR(inode->i_mode)) |
1055 | NFS_FLAGS(inode) |= NFS_INO_STALE; | 1073 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
1056 | } | 1074 | } |
1057 | goto out; | 1075 | goto out; |
1058 | } | 1076 | } |
@@ -1083,9 +1101,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1083 | inode->i_sb->s_id, | 1101 | inode->i_sb->s_id, |
1084 | (long long)NFS_FILEID(inode)); | 1102 | (long long)NFS_FILEID(inode)); |
1085 | 1103 | ||
1086 | out: | 1104 | out: |
1087 | NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING; | 1105 | nfs_wake_up_inode(inode); |
1088 | wake_up(&nfsi->nfs_i_wait); | 1106 | |
1089 | out_nowait: | 1107 | out_nowait: |
1090 | unlock_kernel(); | 1108 | unlock_kernel(); |
1091 | return status; | 1109 | return status; |
@@ -1404,7 +1422,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1404 | */ | 1422 | */ |
1405 | nfs_invalidate_inode(inode); | 1423 | nfs_invalidate_inode(inode); |
1406 | out_err: | 1424 | out_err: |
1407 | NFS_FLAGS(inode) |= NFS_INO_STALE; | 1425 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
1408 | return -ESTALE; | 1426 | return -ESTALE; |
1409 | } | 1427 | } |
1410 | 1428 | ||
@@ -1996,7 +2014,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |||
1996 | nfsi->ndirty = 0; | 2014 | nfsi->ndirty = 0; |
1997 | nfsi->ncommit = 0; | 2015 | nfsi->ncommit = 0; |
1998 | nfsi->npages = 0; | 2016 | nfsi->npages = 0; |
1999 | init_waitqueue_head(&nfsi->nfs_i_wait); | ||
2000 | nfs4_init_once(nfsi); | 2017 | nfs4_init_once(nfsi); |
2001 | } | 2018 | } |
2002 | } | 2019 | } |