summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-11-17 21:14:24 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-12-08 22:41:55 -0500
commit0d0def49d05ae988936268b0e57d19aeef8c3ad2 (patch)
tree471fbf67f67815197aea2540650ee73d754b40ac
parent1a384eaac265b57961c9696d9177f82eb84319e9 (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.c21
-rw-r--r--fs/nfs/symlink.c30
-rw-r--r--include/linux/nfs_fs.h1
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
1090int 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);
1107out:
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);
359extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode); 359extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode);
360extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); 360extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
361extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); 361extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
362extern int nfs_revalidate_mapping_rcu(struct inode *inode);
362extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping); 363extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping);
363extern int nfs_setattr(struct dentry *, struct iattr *); 364extern int nfs_setattr(struct dentry *, struct iattr *);
364extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *); 365extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *);