Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d0def49 authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1a384eaa
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1087,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
+20 −10
Original line number Diff line number Diff line
@@ -48,9 +48,18 @@ static const char *nfs_get_link(struct dentry *dentry,
	struct page *page;
	void *err;

	if (!dentry)
	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;
@@ -58,6 +67,7 @@ static const char *nfs_get_link(struct dentry *dentry,
					(filler_t *)nfs_symlink_filler, inode);
		if (IS_ERR(page))
			return ERR_CAST(page);
	}
	*cookie = page;
	return page_address(page);
}
+1 −0
Original line number Diff line number Diff line
@@ -359,6 +359,7 @@ extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
extern int nfs_revalidate_mapping_rcu(struct inode *inode);
extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping);
extern int nfs_setattr(struct dentry *, struct iattr *);
extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *);