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 /fs/nfs/symlink.c | |
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>
Diffstat (limited to 'fs/nfs/symlink.c')
-rw-r--r-- | fs/nfs/symlink.c | 30 |
1 files changed, 20 insertions, 10 deletions
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, struct page *page; void *err; - if (!dentry) - return ERR_PTR(-ECHILD); - - err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); - if (err) - return err; - page = read_cache_page(&inode->i_data, 0, - (filler_t *)nfs_symlink_filler, inode); - if (IS_ERR(page)) - return ERR_CAST(page); + if (!dentry) { + err = ERR_PTR(nfs_revalidate_mapping_rcu(inode)); + if (err) + return err; + page = find_get_page(inode->i_mapping, 0); + if (!page) + return ERR_PTR(-ECHILD); + if (!PageUptodate(page)) { + put_page(page); + return ERR_PTR(-ECHILD); + } + } else { + err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); + if (err) + return err; + page = read_cache_page(&inode->i_data, 0, + (filler_t *)nfs_symlink_filler, inode); + if (IS_ERR(page)) + return ERR_CAST(page); + } *cookie = page; return page_address(page); } |