Merge branch 'work.symlinks' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs RCU symlink updates from Al Viro: "Replacement of ->follow_link/->put_link, allowing to stay in RCU mode even if the symlink is not an embedded one. No changes since the mailbomb on Jan 1" * 'work.symlinks' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: switch ->get_link() to delayed_call, kill ->put_link() kill free_page_put_link() teach nfs_get_link() to work in RCU mode teach proc_self_get_link()/proc_thread_self_get_link() to work in RCU mode teach shmem_get_link() to work in RCU mode teach page_get_link() to work in RCU mode replace ->follow_link() with new method that could stay in RCU mode don't put symlink bodies in pagecache into highmem namei: page_getlink() and page_follow_link_light() are the same thing ufs: get rid of ->setattr() for symlinks udf: don't duplicate page_symlink_inode_operations logfs: don't duplicate page_symlink_inode_operations switch befs long symlinks to page_symlink_operations
This commit is contained in:
@@ -408,9 +408,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
|
||||
inode->i_fop = NULL;
|
||||
inode->i_flags |= S_AUTOMOUNT;
|
||||
}
|
||||
} else if (S_ISLNK(inode->i_mode))
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
inode->i_op = &nfs_symlink_inode_operations;
|
||||
else
|
||||
inode_nohighmem(inode);
|
||||
} else
|
||||
init_special_inode(inode, inode->i_mode, fattr->rdev);
|
||||
|
||||
memset(&inode->i_atime, 0, sizeof(inode->i_atime));
|
||||
@@ -1086,6 +1087,27 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode)
|
||||
|| NFS_STALE(inode);
|
||||
}
|
||||
|
||||
int nfs_revalidate_mapping_rcu(struct inode *inode)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
unsigned long *bitlock = &nfsi->flags;
|
||||
int ret = 0;
|
||||
|
||||
if (IS_SWAPFILE(inode))
|
||||
goto out;
|
||||
if (nfs_mapping_need_revalidate_inode(inode)) {
|
||||
ret = -ECHILD;
|
||||
goto out;
|
||||
}
|
||||
spin_lock(&inode->i_lock);
|
||||
if (test_bit(NFS_INO_INVALIDATING, bitlock) ||
|
||||
(nfsi->cache_validity & NFS_INO_INVALID_DATA))
|
||||
ret = -ECHILD;
|
||||
spin_unlock(&inode->i_lock);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* __nfs_revalidate_mapping - Revalidate the pagecache
|
||||
* @inode - pointer to host inode
|
||||
|
@@ -42,21 +42,35 @@ error:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const char *nfs_follow_link(struct dentry *dentry, void **cookie)
|
||||
static const char *nfs_get_link(struct dentry *dentry,
|
||||
struct inode *inode,
|
||||
struct delayed_call *done)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct page *page;
|
||||
void *err;
|
||||
|
||||
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 kmap(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);
|
||||
}
|
||||
set_delayed_call(done, page_put_link, page);
|
||||
return page_address(page);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -64,8 +78,7 @@ static const char *nfs_follow_link(struct dentry *dentry, void **cookie)
|
||||
*/
|
||||
const struct inode_operations nfs_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.follow_link = nfs_follow_link,
|
||||
.put_link = page_put_link,
|
||||
.get_link = nfs_get_link,
|
||||
.getattr = nfs_getattr,
|
||||
.setattr = nfs_setattr,
|
||||
};
|
||||
|
Reference in New Issue
Block a user