Skip to content

Commit

Permalink
lockd: get rid of reference-counted NSM RPC clients
Browse files Browse the repository at this point in the history
Currently we have reference-counted per-net NSM RPC client
which created on the first monitor request and destroyed
after the last unmonitor request. It's needed because
RPC client need to know 'utsname()->nodename', but utsname()
might be NULL when nsm_unmonitor() called.

So instead of holding the rpc client we could just save nodename
in struct nlm_host and pass it to the rpc_create().
Thus ther is no need in keeping rpc client until last
unmonitor request. We could create separate RPC clients
for each monitor/unmonitor requests.

Signed-off-by: Andrey Ryabinin <[email protected]>
Signed-off-by: J. Bruce Fields <[email protected]>
  • Loading branch information
aryabinin authored and J. Bruce Fields committed Oct 23, 2015
1 parent 226453d commit 0d0f4aa
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 78 deletions.
1 change: 1 addition & 0 deletions fs/lockd/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
host->h_nsmhandle = nsm;
host->h_addrbuf = nsm->sm_addrbuf;
host->net = ni->net;
strlcpy(host->nodename, utsname()->nodename, sizeof(host->nodename));

out:
return host;
Expand Down
89 changes: 15 additions & 74 deletions fs/lockd/mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct nsm_args {
u32 proc;

char *mon_name;
char *nodename;
const char *nodename;
};

struct nsm_res {
Expand Down Expand Up @@ -86,69 +86,18 @@ static struct rpc_clnt *nsm_create(struct net *net, const char *nodename)
return rpc_create(&args);
}

static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
struct rpc_clnt *clnt)
{
spin_lock(&ln->nsm_clnt_lock);
if (ln->nsm_users == 0) {
if (clnt == NULL)
goto out;
ln->nsm_clnt = clnt;
}
clnt = ln->nsm_clnt;
ln->nsm_users++;
out:
spin_unlock(&ln->nsm_clnt_lock);
return clnt;
}

static struct rpc_clnt *nsm_client_get(struct net *net, const char *nodename)
{
struct rpc_clnt *clnt, *new;
struct lockd_net *ln = net_generic(net, lockd_net_id);

clnt = nsm_client_set(ln, NULL);
if (clnt != NULL)
goto out;

clnt = new = nsm_create(net, nodename);
if (IS_ERR(clnt))
goto out;

clnt = nsm_client_set(ln, new);
if (clnt != new)
rpc_shutdown_client(new);
out:
return clnt;
}

static void nsm_client_put(struct net *net)
{
struct lockd_net *ln = net_generic(net, lockd_net_id);
struct rpc_clnt *clnt = NULL;

spin_lock(&ln->nsm_clnt_lock);
ln->nsm_users--;
if (ln->nsm_users == 0) {
clnt = ln->nsm_clnt;
ln->nsm_clnt = NULL;
}
spin_unlock(&ln->nsm_clnt_lock);
if (clnt != NULL)
rpc_shutdown_client(clnt);
}

static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
struct rpc_clnt *clnt)
const struct nlm_host *host)
{
int status;
struct rpc_clnt *clnt;
struct nsm_args args = {
.priv = &nsm->sm_priv,
.prog = NLM_PROGRAM,
.vers = 3,
.proc = NLMPROC_NSM_NOTIFY,
.mon_name = nsm->sm_mon_name,
.nodename = clnt->cl_nodename,
.nodename = host->nodename,
};
struct rpc_message msg = {
.rpc_argp = &args,
Expand All @@ -157,6 +106,13 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,

memset(res, 0, sizeof(*res));

clnt = nsm_create(host->net, host->nodename);
if (IS_ERR(clnt)) {
dprintk("lockd: failed to create NSM upcall transport, "
"status=%ld, net=%p\n", PTR_ERR(clnt), host->net);
return PTR_ERR(clnt);
}

msg.rpc_proc = &clnt->cl_procinfo[proc];
status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
if (status == -ECONNREFUSED) {
Expand All @@ -170,6 +126,8 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
status);
else
status = 0;

rpc_shutdown_client(clnt);
return status;
}

Expand All @@ -189,32 +147,19 @@ int nsm_monitor(const struct nlm_host *host)
struct nsm_handle *nsm = host->h_nsmhandle;
struct nsm_res res;
int status;
struct rpc_clnt *clnt;
const char *nodename = NULL;

dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);

if (nsm->sm_monitored)
return 0;

if (host->h_rpcclnt)
nodename = host->h_rpcclnt->cl_nodename;

/*
* Choose whether to record the caller_name or IP address of
* this peer in the local rpc.statd's database.
*/
nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;

clnt = nsm_client_get(host->net, nodename);
if (IS_ERR(clnt)) {
status = PTR_ERR(clnt);
dprintk("lockd: failed to create NSM upcall transport, "
"status=%d, net=%p\n", status, host->net);
return status;
}

status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host);
if (unlikely(res.status != 0))
status = -EIO;
if (unlikely(status < 0)) {
Expand Down Expand Up @@ -246,20 +191,16 @@ void nsm_unmonitor(const struct nlm_host *host)

if (atomic_read(&nsm->sm_count) == 1
&& nsm->sm_monitored && !nsm->sm_sticky) {
struct lockd_net *ln = net_generic(host->net, lockd_net_id);

dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);

status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host);
if (res.status != 0)
status = -EIO;
if (status < 0)
printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
nsm->sm_name);
else
nsm->sm_monitored = 0;

nsm_client_put(host->net);
}
}

Expand Down
3 changes: 0 additions & 3 deletions fs/lockd/netns.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ struct lockd_net {
struct delayed_work grace_period_end;
struct lock_manager lockd_manager;

spinlock_t nsm_clnt_lock;
unsigned int nsm_users;
struct rpc_clnt *nsm_clnt;
struct list_head nsm_handles;
};

Expand Down
1 change: 0 additions & 1 deletion fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,6 @@ static int lockd_init_net(struct net *net)
INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
INIT_LIST_HEAD(&ln->lockd_manager.list);
ln->lockd_manager.block_opens = false;
spin_lock_init(&ln->nsm_clnt_lock);
INIT_LIST_HEAD(&ln->nsm_handles);
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions include/linux/lockd/lockd.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct nlm_host {
struct nsm_handle *h_nsmhandle; /* NSM status handle */
char *h_addrbuf; /* address eyecatcher */
struct net *net; /* host net */
char nodename[UNX_MAXNODENAME + 1];
};

/*
Expand Down

0 comments on commit 0d0f4aa

Please sign in to comment.