Commit 6b255391 authored by Al Viro's avatar Al Viro
Browse files

replace ->follow_link() with new method that could stay in RCU mode



new method: ->get_link(); replacement of ->follow_link().  The differences
are:
	* inode and dentry are passed separately
	* might be called both in RCU and non-RCU mode;
the former is indicated by passing it a NULL dentry.
	* when called that way it isn't allowed to block
and should return ERR_PTR(-ECHILD) if it needs to be called
in non-RCU mode.

It's a flagday change - the old method is gone, all in-tree instances
converted.  Conversion isn't hard; said that, so far very few instances
do not immediately bail out when called in RCU mode.  That'll change
in the next commits.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 21fc61c7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ prototypes:
	int (*rename2) (struct inode *, struct dentry *,
			struct inode *, struct dentry *, unsigned int);
	int (*readlink) (struct dentry *, char __user *,int);
	const char *(*follow_link) (struct dentry *, void **);
	const char *(*get_link) (struct dentry *, struct inode *, void **);
	void (*put_link) (struct inode *, void *);
	void (*truncate) (struct inode *);
	int (*permission) (struct inode *, int, unsigned int);
@@ -83,7 +83,7 @@ rmdir: yes (both) (see below)
rename:		yes (all)	(see below)
rename2:	yes (all)	(see below)
readlink:	no
follow_link:	no
get_link:	no
put_link:	no
setattr:	yes
permission:	no (may not block if called in rcu-walk mode)
+6 −0
Original line number Diff line number Diff line
@@ -509,3 +509,9 @@ in your dentry operations instead.
	any symlink that might use page_follow_link_light/page_put_link() must
	have inode_nohighmem(inode) called before anything might start playing with
	its pagecache.
--
[mandatory]
	->follow_link() is replaced with ->get_link(); same API, except that
		* ->get_link() gets inode as a separate argument
		* ->get_link() may be called in RCU mode - in that case NULL
		  dentry is passed
+5 −3
Original line number Diff line number Diff line
@@ -118,12 +118,14 @@ failed:
	return rc;
}

static const char *ll_follow_link(struct dentry *dentry, void **cookie)
static const char *ll_get_link(struct dentry *dentry,
			       struct inode *inode, void **cookie)
{
	struct inode *inode = d_inode(dentry);
	struct ptlrpc_request *request = NULL;
	int rc;
	char *symname = NULL;
	if (!dentry)
		return ERR_PTR(-ECHILD);

	CDEBUG(D_VFSTRACE, "VFS Op\n");
	ll_inode_size_lock(inode);
@@ -149,7 +151,7 @@ static void ll_put_link(struct inode *unused, void *cookie)
struct inode_operations ll_fast_symlink_inode_operations = {
	.readlink	= generic_readlink,
	.setattr	= ll_setattr,
	.follow_link	= ll_follow_link,
	.get_link	= ll_get_link,
	.put_link	= ll_put_link,
	.getattr	= ll_getattr,
	.permission	= ll_inode_permission,
+12 −5
Original line number Diff line number Diff line
@@ -1223,18 +1223,25 @@ ino_t v9fs_qid2ino(struct p9_qid *qid)
}

/**
 * v9fs_vfs_follow_link - follow a symlink path
 * v9fs_vfs_get_link - follow a symlink path
 * @dentry: dentry for symlink
 * @inode: inode for symlink
 * @cookie: place to pass the data to put_link()
 */

static const char *v9fs_vfs_follow_link(struct dentry *dentry, void **cookie)
static const char *v9fs_vfs_get_link(struct dentry *dentry,
				     struct inode *inode, void **cookie)
{
	struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry);
	struct p9_fid *fid = v9fs_fid_lookup(dentry);
	struct v9fs_session_info *v9ses;
	struct p9_fid *fid;
	struct p9_wstat *st;
	char *res;

	if (!dentry)
		return ERR_PTR(-ECHILD);

	v9ses = v9fs_dentry2v9ses(dentry);
	fid = v9fs_fid_lookup(dentry);
	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);

	if (IS_ERR(fid))
@@ -1452,7 +1459,7 @@ static const struct inode_operations v9fs_file_inode_operations = {

static const struct inode_operations v9fs_symlink_inode_operations = {
	.readlink = generic_readlink,
	.follow_link = v9fs_vfs_follow_link,
	.get_link = v9fs_vfs_get_link,
	.put_link = kfree_put_link,
	.getattr = v9fs_vfs_getattr,
	.setattr = v9fs_vfs_setattr,
+10 −4
Original line number Diff line number Diff line
@@ -899,20 +899,26 @@ error:
}

/**
 * v9fs_vfs_follow_link_dotl - follow a symlink path
 * v9fs_vfs_get_link_dotl - follow a symlink path
 * @dentry: dentry for symlink
 * @inode: inode for symlink
 * @cookie: place to pass the data to put_link()
 */

static const char *
v9fs_vfs_follow_link_dotl(struct dentry *dentry, void **cookie)
v9fs_vfs_get_link_dotl(struct dentry *dentry,
		       struct inode *inode, void **cookie)
{
	struct p9_fid *fid = v9fs_fid_lookup(dentry);
	struct p9_fid *fid;
	char *target;
	int retval;

	if (!dentry)
		return ERR_PTR(-ECHILD);

	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);

	fid = v9fs_fid_lookup(dentry);
	if (IS_ERR(fid))
		return ERR_CAST(fid);
	retval = p9_client_readlink(fid, &target);
@@ -984,7 +990,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {

const struct inode_operations v9fs_symlink_inode_operations_dotl = {
	.readlink = generic_readlink,
	.follow_link = v9fs_vfs_follow_link_dotl,
	.get_link = v9fs_vfs_get_link_dotl,
	.put_link = kfree_put_link,
	.getattr = v9fs_vfs_getattr_dotl,
	.setattr = v9fs_vfs_setattr_dotl,
Loading