mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
rpc_mkpipe_dentry(): saner calling conventions
Instead of returning a dentry or ERR_PTR(-E...), return 0 and store dentry into pipe->dentry on success and return -E... on failure. Callers are happier that way... NOTE: dummy rpc_pipe is getting ->dentry set; we never access that, since we 1) never call rpc_unlink() for it (dentry is taken out by ->kill_sb()) 2) never call rpc_queue_upcall() for it (writing to that sucker fails; no downcalls are ever submitted, so no replies are going to arrive) IOW, having that ->dentry set (and left dangling) is harmless, if ugly; cleaner solution will take more massage. Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
bccea4ed06
commit
19a6314a99
6 changed files with 45 additions and 79 deletions
|
@ -141,17 +141,18 @@ static const struct rpc_pipe_ops bl_upcall_ops = {
|
||||||
.destroy_msg = bl_pipe_destroy_msg,
|
.destroy_msg = bl_pipe_destroy_msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dentry *nfs4blocklayout_register_sb(struct super_block *sb,
|
static int nfs4blocklayout_register_sb(struct super_block *sb,
|
||||||
struct rpc_pipe *pipe)
|
struct rpc_pipe *pipe)
|
||||||
{
|
{
|
||||||
struct dentry *dir, *dentry;
|
struct dentry *dir;
|
||||||
|
int err;
|
||||||
|
|
||||||
dir = rpc_d_lookup_sb(sb, NFS_PIPE_DIRNAME);
|
dir = rpc_d_lookup_sb(sb, NFS_PIPE_DIRNAME);
|
||||||
if (dir == NULL)
|
if (dir == NULL)
|
||||||
return ERR_PTR(-ENOENT);
|
return -ENOENT;
|
||||||
dentry = rpc_mkpipe_dentry(dir, "blocklayout", NULL, pipe);
|
err = rpc_mkpipe_dentry(dir, "blocklayout", NULL, pipe);
|
||||||
dput(dir);
|
dput(dir);
|
||||||
return dentry;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
|
static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
|
||||||
|
@ -160,7 +161,6 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
|
||||||
struct super_block *sb = ptr;
|
struct super_block *sb = ptr;
|
||||||
struct net *net = sb->s_fs_info;
|
struct net *net = sb->s_fs_info;
|
||||||
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
||||||
struct dentry *dentry;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!try_module_get(THIS_MODULE))
|
if (!try_module_get(THIS_MODULE))
|
||||||
|
@ -173,12 +173,7 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case RPC_PIPEFS_MOUNT:
|
case RPC_PIPEFS_MOUNT:
|
||||||
dentry = nfs4blocklayout_register_sb(sb, nn->bl_device_pipe);
|
ret = nfs4blocklayout_register_sb(sb, nn->bl_device_pipe);
|
||||||
if (IS_ERR(dentry)) {
|
|
||||||
ret = PTR_ERR(dentry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nn->bl_device_pipe->dentry = dentry;
|
|
||||||
break;
|
break;
|
||||||
case RPC_PIPEFS_UMOUNT:
|
case RPC_PIPEFS_UMOUNT:
|
||||||
rpc_unlink(nn->bl_device_pipe);
|
rpc_unlink(nn->bl_device_pipe);
|
||||||
|
@ -195,18 +190,17 @@ static struct notifier_block nfs4blocklayout_block = {
|
||||||
.notifier_call = rpc_pipefs_event,
|
.notifier_call = rpc_pipefs_event,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dentry *nfs4blocklayout_register_net(struct net *net,
|
static int nfs4blocklayout_register_net(struct net *net, struct rpc_pipe *pipe)
|
||||||
struct rpc_pipe *pipe)
|
|
||||||
{
|
{
|
||||||
struct super_block *pipefs_sb;
|
struct super_block *pipefs_sb;
|
||||||
struct dentry *dentry;
|
int ret;
|
||||||
|
|
||||||
pipefs_sb = rpc_get_sb_net(net);
|
pipefs_sb = rpc_get_sb_net(net);
|
||||||
if (!pipefs_sb)
|
if (!pipefs_sb)
|
||||||
return NULL;
|
return 0;
|
||||||
dentry = nfs4blocklayout_register_sb(pipefs_sb, pipe);
|
ret = nfs4blocklayout_register_sb(pipefs_sb, pipe);
|
||||||
rpc_put_sb_net(net);
|
rpc_put_sb_net(net);
|
||||||
return dentry;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs4blocklayout_unregister_net(struct net *net,
|
static void nfs4blocklayout_unregister_net(struct net *net,
|
||||||
|
@ -224,20 +218,17 @@ static void nfs4blocklayout_unregister_net(struct net *net,
|
||||||
static int nfs4blocklayout_net_init(struct net *net)
|
static int nfs4blocklayout_net_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
||||||
struct dentry *dentry;
|
int err;
|
||||||
|
|
||||||
mutex_init(&nn->bl_mutex);
|
mutex_init(&nn->bl_mutex);
|
||||||
init_waitqueue_head(&nn->bl_wq);
|
init_waitqueue_head(&nn->bl_wq);
|
||||||
nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0);
|
nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0);
|
||||||
if (IS_ERR(nn->bl_device_pipe))
|
if (IS_ERR(nn->bl_device_pipe))
|
||||||
return PTR_ERR(nn->bl_device_pipe);
|
return PTR_ERR(nn->bl_device_pipe);
|
||||||
dentry = nfs4blocklayout_register_net(net, nn->bl_device_pipe);
|
err = nfs4blocklayout_register_net(net, nn->bl_device_pipe);
|
||||||
if (IS_ERR(dentry)) {
|
if (unlikely(err))
|
||||||
rpc_destroy_pipe_data(nn->bl_device_pipe);
|
rpc_destroy_pipe_data(nn->bl_device_pipe);
|
||||||
return PTR_ERR(dentry);
|
return err;
|
||||||
}
|
|
||||||
nn->bl_device_pipe->dentry = dentry;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs4blocklayout_net_exit(struct net *net)
|
static void nfs4blocklayout_net_exit(struct net *net)
|
||||||
|
|
|
@ -432,14 +432,8 @@ static int nfs_idmap_pipe_create(struct dentry *dir,
|
||||||
struct rpc_pipe_dir_object *pdo)
|
struct rpc_pipe_dir_object *pdo)
|
||||||
{
|
{
|
||||||
struct idmap *idmap = pdo->pdo_data;
|
struct idmap *idmap = pdo->pdo_data;
|
||||||
struct rpc_pipe *pipe = idmap->idmap_pipe;
|
|
||||||
struct dentry *dentry;
|
|
||||||
|
|
||||||
dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
|
return rpc_mkpipe_dentry(dir, "idmap", idmap, idmap->idmap_pipe);
|
||||||
if (IS_ERR(dentry))
|
|
||||||
return PTR_ERR(dentry);
|
|
||||||
pipe->dentry = dentry;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
|
static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
|
||||||
|
|
|
@ -950,31 +950,32 @@ static const struct rpc_pipe_ops cld_upcall_ops = {
|
||||||
.destroy_msg = cld_pipe_destroy_msg,
|
.destroy_msg = cld_pipe_destroy_msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dentry *
|
static int
|
||||||
nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
|
nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
|
||||||
{
|
{
|
||||||
struct dentry *dir, *dentry;
|
struct dentry *dir;
|
||||||
|
int err;
|
||||||
|
|
||||||
dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
|
dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
|
||||||
if (dir == NULL)
|
if (dir == NULL)
|
||||||
return ERR_PTR(-ENOENT);
|
return -ENOENT;
|
||||||
dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
|
err = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
|
||||||
dput(dir);
|
dput(dir);
|
||||||
return dentry;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *
|
static int
|
||||||
nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
|
nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
|
||||||
{
|
{
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct dentry *dentry;
|
int err;
|
||||||
|
|
||||||
sb = rpc_get_sb_net(net);
|
sb = rpc_get_sb_net(net);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return NULL;
|
return 0;
|
||||||
dentry = nfsd4_cld_register_sb(sb, pipe);
|
err = nfsd4_cld_register_sb(sb, pipe);
|
||||||
rpc_put_sb_net(net);
|
rpc_put_sb_net(net);
|
||||||
return dentry;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -994,7 +995,6 @@ static int
|
||||||
__nfsd4_init_cld_pipe(struct net *net)
|
__nfsd4_init_cld_pipe(struct net *net)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct dentry *dentry;
|
|
||||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
struct cld_net *cn;
|
struct cld_net *cn;
|
||||||
|
|
||||||
|
@ -1015,13 +1015,10 @@ __nfsd4_init_cld_pipe(struct net *net)
|
||||||
spin_lock_init(&cn->cn_lock);
|
spin_lock_init(&cn->cn_lock);
|
||||||
INIT_LIST_HEAD(&cn->cn_list);
|
INIT_LIST_HEAD(&cn->cn_list);
|
||||||
|
|
||||||
dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
|
ret = nfsd4_cld_register_net(net, cn->cn_pipe);
|
||||||
if (IS_ERR(dentry)) {
|
if (unlikely(ret))
|
||||||
ret = PTR_ERR(dentry);
|
|
||||||
goto err_destroy_data;
|
goto err_destroy_data;
|
||||||
}
|
|
||||||
|
|
||||||
cn->cn_pipe->dentry = dentry;
|
|
||||||
#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
|
#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
|
||||||
cn->cn_has_legacy = false;
|
cn->cn_has_legacy = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2114,7 +2111,6 @@ rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
|
||||||
struct net *net = sb->s_fs_info;
|
struct net *net = sb->s_fs_info;
|
||||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
struct cld_net *cn = nn->cld_net;
|
struct cld_net *cn = nn->cld_net;
|
||||||
struct dentry *dentry;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!try_module_get(THIS_MODULE))
|
if (!try_module_get(THIS_MODULE))
|
||||||
|
@ -2127,12 +2123,7 @@ rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case RPC_PIPEFS_MOUNT:
|
case RPC_PIPEFS_MOUNT:
|
||||||
dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
|
ret = nfsd4_cld_register_sb(sb, cn->cn_pipe);
|
||||||
if (IS_ERR(dentry)) {
|
|
||||||
ret = PTR_ERR(dentry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cn->cn_pipe->dentry = dentry;
|
|
||||||
break;
|
break;
|
||||||
case RPC_PIPEFS_UMOUNT:
|
case RPC_PIPEFS_UMOUNT:
|
||||||
rpc_unlink(cn->cn_pipe);
|
rpc_unlink(cn->cn_pipe);
|
||||||
|
|
|
@ -127,7 +127,7 @@ extern void rpc_remove_cache_dir(struct dentry *);
|
||||||
|
|
||||||
struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags);
|
struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags);
|
||||||
void rpc_destroy_pipe_data(struct rpc_pipe *pipe);
|
void rpc_destroy_pipe_data(struct rpc_pipe *pipe);
|
||||||
extern struct dentry *rpc_mkpipe_dentry(struct dentry *, const char *, void *,
|
extern int rpc_mkpipe_dentry(struct dentry *, const char *, void *,
|
||||||
struct rpc_pipe *);
|
struct rpc_pipe *);
|
||||||
extern void rpc_unlink(struct rpc_pipe *);
|
extern void rpc_unlink(struct rpc_pipe *);
|
||||||
extern int register_rpc_pipefs(void);
|
extern int register_rpc_pipefs(void);
|
||||||
|
|
|
@ -895,13 +895,8 @@ static int gss_pipe_dentry_create(struct dentry *dir,
|
||||||
struct rpc_pipe_dir_object *pdo)
|
struct rpc_pipe_dir_object *pdo)
|
||||||
{
|
{
|
||||||
struct gss_pipe *p = pdo->pdo_data;
|
struct gss_pipe *p = pdo->pdo_data;
|
||||||
struct dentry *dentry;
|
|
||||||
|
|
||||||
dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe);
|
return rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe);
|
||||||
if (IS_ERR(dentry))
|
|
||||||
return PTR_ERR(dentry);
|
|
||||||
p->pipe->dentry = dentry;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = {
|
static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = {
|
||||||
|
|
|
@ -702,7 +702,7 @@ out_err:
|
||||||
* The @private argument passed here will be available to all these methods
|
* The @private argument passed here will be available to all these methods
|
||||||
* from the file pointer, via RPC_I(file_inode(file))->private.
|
* from the file pointer, via RPC_I(file_inode(file))->private.
|
||||||
*/
|
*/
|
||||||
struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
|
int rpc_mkpipe_dentry(struct dentry *parent, const char *name,
|
||||||
void *private, struct rpc_pipe *pipe)
|
void *private, struct rpc_pipe *pipe)
|
||||||
{
|
{
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
|
@ -717,21 +717,19 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
|
||||||
|
|
||||||
inode_lock_nested(dir, I_MUTEX_PARENT);
|
inode_lock_nested(dir, I_MUTEX_PARENT);
|
||||||
dentry = __rpc_lookup_create_exclusive(parent, name);
|
dentry = __rpc_lookup_create_exclusive(parent, name);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry)) {
|
||||||
goto out;
|
inode_unlock(dir);
|
||||||
|
return PTR_ERR(dentry);
|
||||||
|
}
|
||||||
err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
|
err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
|
||||||
private, pipe);
|
private, pipe);
|
||||||
if (err)
|
if (unlikely(err))
|
||||||
goto out_err;
|
pr_warn("%s() failed to create pipe %pd/%s (errno = %d)\n",
|
||||||
out:
|
__func__, parent, name, err);
|
||||||
|
else
|
||||||
|
pipe->dentry = dentry;
|
||||||
inode_unlock(dir);
|
inode_unlock(dir);
|
||||||
return dentry;
|
return err;
|
||||||
out_err:
|
|
||||||
dentry = ERR_PTR(err);
|
|
||||||
printk(KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)\n",
|
|
||||||
__FILE__, __func__, parent, name,
|
|
||||||
err);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
|
EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
|
||||||
|
|
||||||
|
@ -1185,7 +1183,6 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct dentry *gssd_dentry;
|
struct dentry *gssd_dentry;
|
||||||
struct dentry *clnt_dentry = NULL;
|
struct dentry *clnt_dentry = NULL;
|
||||||
struct dentry *pipe_dentry = NULL;
|
|
||||||
|
|
||||||
/* We should never get this far if "gssd" doesn't exist */
|
/* We should never get this far if "gssd" doesn't exist */
|
||||||
gssd_dentry = try_lookup_noperm(&QSTR(files[RPCAUTH_gssd].name), root);
|
gssd_dentry = try_lookup_noperm(&QSTR(files[RPCAUTH_gssd].name), root);
|
||||||
|
@ -1209,10 +1206,8 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
|
||||||
dput(clnt_dentry);
|
dput(clnt_dentry);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
|
ret = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
|
||||||
dput(clnt_dentry);
|
dput(clnt_dentry);
|
||||||
if (IS_ERR(pipe_dentry))
|
|
||||||
ret = PTR_ERR(pipe_dentry);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue