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

Commit 54281548 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Fix a 'Busy inodes' error in rpc_pipefs

parent a9a80178
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ struct rpc_clnt {
	int			cl_nodelen;	/* nodename length */
	char 			cl_nodename[UNX_MAXNODENAME];
	char			cl_pathname[30];/* Path in rpc_pipe_fs */
	struct vfsmount *	cl_vfsmnt;
	struct dentry *		cl_dentry;	/* inode */
	struct rpc_clnt *	cl_parent;	/* Points to parent of clones */
	struct rpc_rtt		cl_rtt_default;
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
extern int rpc_rmdir(char *);
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
extern int rpc_unlink(char *);
extern struct vfsmount *rpc_get_mount(void);
extern void rpc_put_mount(void);

#endif
#endif
+20 −4
Original line number Diff line number Diff line
@@ -70,8 +70,15 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
	static uint32_t clntid;
	int error;

	clnt->cl_vfsmnt = ERR_PTR(-ENOENT);
	clnt->cl_dentry = ERR_PTR(-ENOENT);
	if (dir_name == NULL)
		return 0;

	clnt->cl_vfsmnt = rpc_get_mount();
	if (IS_ERR(clnt->cl_vfsmnt))
		return PTR_ERR(clnt->cl_vfsmnt);

	for (;;) {
		snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
				"%s/clnt%x", dir_name,
@@ -84,6 +91,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
		if (error != -EEXIST) {
			printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
					clnt->cl_pathname, error);
			rpc_put_mount();
			return error;
		}
	}
@@ -175,7 +183,11 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
	return clnt;

out_no_auth:
	if (!IS_ERR(clnt->cl_dentry)) {
		rpc_rmdir(clnt->cl_pathname);
		dput(clnt->cl_dentry);
		rpc_put_mount();
	}
out_no_path:
	if (clnt->cl_server != clnt->cl_inline_name)
		kfree(clnt->cl_server);
@@ -240,13 +252,15 @@ rpc_clone_client(struct rpc_clnt *clnt)
	new->cl_autobind = 0;
	new->cl_oneshot = 0;
	new->cl_dead = 0;
	if (!IS_ERR(new->cl_dentry)) {
		dget(new->cl_dentry);
		rpc_get_mount();
	}
	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
	if (new->cl_auth)
		atomic_inc(&new->cl_auth->au_count);
	new->cl_pmap		= &new->cl_pmap_default;
	new->cl_metrics         = rpc_alloc_iostats(clnt);
	rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
	return new;
out_no_clnt:
	printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
@@ -318,8 +332,10 @@ rpc_destroy_client(struct rpc_clnt *clnt)
out_free:
	rpc_free_iostats(clnt->cl_metrics);
	clnt->cl_metrics = NULL;
	if (clnt->cl_dentry)
	if (!IS_ERR(clnt->cl_dentry)) {
		dput(clnt->cl_dentry);
		rpc_put_mount();
	}
	kfree(clnt);
	return 0;
}
+12 −10
Original line number Diff line number Diff line
@@ -435,14 +435,17 @@ static struct rpc_filelist authfiles[] = {
	},
};

static int
rpc_get_mount(void)
struct vfsmount *rpc_get_mount(void)
{
	return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
	int err;

	err = simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
	if (err != 0)
		return ERR_PTR(err);
	return rpc_mount;
}

static void
rpc_put_mount(void)
void rpc_put_mount(void)
{
	simple_release_fs(&rpc_mount, &rpc_mount_count);
}
@@ -452,12 +455,13 @@ rpc_lookup_parent(char *path, struct nameidata *nd)
{
	if (path[0] == '\0')
		return -ENOENT;
	if (rpc_get_mount()) {
	nd->mnt = rpc_get_mount();
	if (IS_ERR(nd->mnt)) {
		printk(KERN_WARNING "%s: %s failed to mount "
			       "pseudofilesystem \n", __FILE__, __FUNCTION__);
		return -ENODEV;
		return PTR_ERR(nd->mnt);
	}
	nd->mnt = mntget(rpc_mount);
	mntget(nd->mnt);
	nd->dentry = dget(rpc_mount->mnt_root);
	nd->last_type = LAST_ROOT;
	nd->flags = LOOKUP_PARENT;
@@ -594,7 +598,6 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
	d_instantiate(dentry, inode);
	dir->i_nlink++;
	inode_dir_notify(dir, DN_CREATE);
	rpc_get_mount();
	return 0;
out_err:
	printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
@@ -615,7 +618,6 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
	if (!error) {
		inode_dir_notify(dir, DN_DELETE);
		d_drop(dentry);
		rpc_put_mount();
	}
	return 0;
}