diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-11-17 21:14:24 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-12-08 22:41:55 -0500 |
commit | 0d0def49d05ae988936268b0e57d19aeef8c3ad2 (patch) | |
tree | 471fbf67f67815197aea2540650ee73d754b40ac | |
parent | 1a384eaac265b57961c9696d9177f82eb84319e9 (diff) |
teach nfs_get_link() to work in RCU mode
based upon the corresponding patch from Neil's March patchset,
again with kmap-related horrors removed.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/nfs/inode.c | 21 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 30 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 |
3 files changed, 42 insertions, 10 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index ae9aa0b8155c..aa828e8b6e04 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1087,6 +1087,27 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) | |||
1087 | || NFS_STALE(inode); | 1087 | || NFS_STALE(inode); |
1088 | } | 1088 | } |
1089 | 1089 | ||
1090 | int nfs_revalidate_mapping_rcu(struct inode *inode) | ||
1091 | { | ||
1092 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1093 | unsigned long *bitlock = &nfsi->flags; | ||
1094 | int ret = 0; | ||
1095 | |||
1096 | if (IS_SWAPFILE(inode)) | ||
1097 | goto out; | ||
1098 | if (nfs_mapping_need_revalidate_inode(inode)) { | ||
1099 | ret = -ECHILD; | ||
1100 | goto out; | ||
1101 | } | ||
1102 | spin_lock(&inode->i_lock); | ||
1103 | if (test_bit(NFS_INO_INVALIDATING, bitlock) || | ||
1104 | (nfsi->cache_validity & NFS_INO_INVALID_DATA)) | ||
1105 | ret = -ECHILD; | ||
1106 | spin_unlock(&inode->i_lock); | ||
1107 | out: | ||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1090 | /** | 1111 | /** |
1091 | * __nfs_revalidate_mapping - Revalidate the pagecache | 1112 | * __nfs_revalidate_mapping - Revalidate the pagecache |
1092 | * @inode - pointer to host inode | 1113 | * @inode - pointer to host inode |
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 8ade8a812607..95c69af7e4d0 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c | |||
@@ -48,16 +48,26 @@ static const char *nfs_get_link(struct dentry *dentry, | |||
48 | struct page *page; | 48 | struct page *page; |
49 | void *err; | 49 | void *err; |
50 | 50 | ||
51 | if (!dentry) | 51 | if (!dentry) { |
52 | return ERR_PTR(-ECHILD); | 52 | err = ERR_PTR(nfs_revalidate_mapping_rcu(inode)); |
53 | 53 | if (err) | |
54 | err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); | 54 | return err; |
55 | if (err) | 55 | page = find_get_page(inode->i_mapping, 0); |
56 | return err; | 56 | if (!page) |
57 | page = read_cache_page(&inode->i_data, 0, | 57 | return ERR_PTR(-ECHILD); |
58 | (filler_t *)nfs_symlink_filler, inode); | 58 | if (!PageUptodate(page)) { |
59 | if (IS_ERR(page)) | 59 | put_page(page); |
60 | return ERR_CAST(page); | 60 | return ERR_PTR(-ECHILD); |
61 | } | ||
62 | } else { | ||
63 | err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); | ||
64 | if (err) | ||
65 | return err; | ||
66 | page = read_cache_page(&inode->i_data, 0, | ||
67 | (filler_t *)nfs_symlink_filler, inode); | ||
68 | if (IS_ERR(page)) | ||
69 | return ERR_CAST(page); | ||
70 | } | ||
61 | *cookie = page; | 71 | *cookie = page; |
62 | return page_address(page); | 72 | return page_address(page); |
63 | } | 73 | } |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index c0e961474a52..37a3d2981352 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -359,6 +359,7 @@ extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); | |||
359 | extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode); | 359 | extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode); |
360 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | 360 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); |
361 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | 361 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |
362 | extern int nfs_revalidate_mapping_rcu(struct inode *inode); | ||
362 | extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping); | 363 | extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping); |
363 | extern int nfs_setattr(struct dentry *, struct iattr *); | 364 | extern int nfs_setattr(struct dentry *, struct iattr *); |
364 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *); | 365 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *); |