Skip to content

Commit 924f4fb

Browse files
LorenzoBianconichucklever
authored andcommitted
NFSD: convert write_threads to netlink command
Introduce write_threads netlink command similar to the one available through the procfs. Tested-by: Jeff Layton <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Co-developed-by: Jeff Layton <[email protected]> Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 9077d59 commit 924f4fb

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed

Documentation/netlink/specs/nfsd.yaml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ attribute-sets:
6262
name: compound-ops
6363
type: u32
6464
multi-attr: true
65+
-
66+
name: server
67+
attributes:
68+
-
69+
name: threads
70+
type: u32
71+
multi-attr: true
72+
-
73+
name: gracetime
74+
type: u32
75+
-
76+
name: leasetime
77+
type: u32
78+
-
79+
name: scope
80+
type: string
6581

6682
operations:
6783
list:
@@ -87,3 +103,26 @@ operations:
87103
- sport
88104
- dport
89105
- compound-ops
106+
-
107+
name: threads-set
108+
doc: set the number of running threads
109+
attribute-set: server
110+
flags: [ admin-perm ]
111+
do:
112+
request:
113+
attributes:
114+
- threads
115+
- gracetime
116+
- leasetime
117+
- scope
118+
-
119+
name: threads-get
120+
doc: get the number of running threads
121+
attribute-set: server
122+
do:
123+
reply:
124+
attributes:
125+
- threads
126+
- gracetime
127+
- leasetime
128+
- scope

fs/nfsd/netlink.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010

1111
#include <uapi/linux/nfsd_netlink.h>
1212

13+
/* NFSD_CMD_THREADS_SET - do */
14+
static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_SCOPE + 1] = {
15+
[NFSD_A_SERVER_THREADS] = { .type = NLA_U32, },
16+
[NFSD_A_SERVER_GRACETIME] = { .type = NLA_U32, },
17+
[NFSD_A_SERVER_LEASETIME] = { .type = NLA_U32, },
18+
[NFSD_A_SERVER_SCOPE] = { .type = NLA_NUL_STRING, },
19+
};
20+
1321
/* Ops table for nfsd */
1422
static const struct genl_split_ops nfsd_nl_ops[] = {
1523
{
@@ -19,6 +27,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
1927
.done = nfsd_nl_rpc_status_get_done,
2028
.flags = GENL_CMD_CAP_DUMP,
2129
},
30+
{
31+
.cmd = NFSD_CMD_THREADS_SET,
32+
.doit = nfsd_nl_threads_set_doit,
33+
.policy = nfsd_threads_set_nl_policy,
34+
.maxattr = NFSD_A_SERVER_SCOPE,
35+
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
36+
},
37+
{
38+
.cmd = NFSD_CMD_THREADS_GET,
39+
.doit = nfsd_nl_threads_get_doit,
40+
.flags = GENL_CMD_CAP_DO,
41+
},
2242
};
2343

2444
struct genl_family nfsd_nl_family __ro_after_init = {

fs/nfsd/netlink.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb);
1616

1717
int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb,
1818
struct netlink_callback *cb);
19+
int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info);
20+
int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info);
1921

2022
extern struct genl_family nfsd_nl_family;
2123

fs/nfsd/nfsctl.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/sunrpc/addr.h>
1616
#include <linux/sunrpc/gss_api.h>
1717
#include <linux/sunrpc/rpc_pipe_fs.h>
18+
#include <linux/sunrpc/svc.h>
1819
#include <linux/module.h>
1920
#include <linux/fsnotify.h>
2021

@@ -1653,6 +1654,148 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb)
16531654
return 0;
16541655
}
16551656

1657+
/**
1658+
* nfsd_nl_threads_set_doit - set the number of running threads
1659+
* @skb: reply buffer
1660+
* @info: netlink metadata and command arguments
1661+
*
1662+
* Return 0 on success or a negative errno.
1663+
*/
1664+
int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
1665+
{
1666+
int nthreads = 0, count = 0, nrpools, ret = -EOPNOTSUPP, rem;
1667+
struct net *net = genl_info_net(info);
1668+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1669+
const struct nlattr *attr;
1670+
const char *scope = NULL;
1671+
1672+
if (GENL_REQ_ATTR_CHECK(info, NFSD_A_SERVER_THREADS))
1673+
return -EINVAL;
1674+
1675+
/* count number of SERVER_THREADS values */
1676+
nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
1677+
if (nla_type(attr) == NFSD_A_SERVER_THREADS)
1678+
count++;
1679+
}
1680+
1681+
mutex_lock(&nfsd_mutex);
1682+
1683+
nrpools = nfsd_nrpools(net);
1684+
if (nrpools && count > nrpools)
1685+
count = nrpools;
1686+
1687+
/* XXX: make this handle non-global pool-modes */
1688+
if (count > 1)
1689+
goto out_unlock;
1690+
1691+
nthreads = nla_get_u32(info->attrs[NFSD_A_SERVER_THREADS]);
1692+
if (info->attrs[NFSD_A_SERVER_GRACETIME] ||
1693+
info->attrs[NFSD_A_SERVER_LEASETIME] ||
1694+
info->attrs[NFSD_A_SERVER_SCOPE]) {
1695+
ret = -EBUSY;
1696+
if (nn->nfsd_serv && nn->nfsd_serv->sv_nrthreads)
1697+
goto out_unlock;
1698+
1699+
ret = -EINVAL;
1700+
attr = info->attrs[NFSD_A_SERVER_GRACETIME];
1701+
if (attr) {
1702+
u32 gracetime = nla_get_u32(attr);
1703+
1704+
if (gracetime < 10 || gracetime > 3600)
1705+
goto out_unlock;
1706+
1707+
nn->nfsd4_grace = gracetime;
1708+
}
1709+
1710+
attr = info->attrs[NFSD_A_SERVER_LEASETIME];
1711+
if (attr) {
1712+
u32 leasetime = nla_get_u32(attr);
1713+
1714+
if (leasetime < 10 || leasetime > 3600)
1715+
goto out_unlock;
1716+
1717+
nn->nfsd4_lease = leasetime;
1718+
}
1719+
1720+
attr = info->attrs[NFSD_A_SERVER_SCOPE];
1721+
if (attr)
1722+
scope = nla_data(attr);
1723+
}
1724+
1725+
ret = nfsd_svc(nthreads, net, get_current_cred(), scope);
1726+
1727+
out_unlock:
1728+
mutex_unlock(&nfsd_mutex);
1729+
1730+
return ret == nthreads ? 0 : ret;
1731+
}
1732+
1733+
/**
1734+
* nfsd_nl_threads_get_doit - get the number of running threads
1735+
* @skb: reply buffer
1736+
* @info: netlink metadata and command arguments
1737+
*
1738+
* Return 0 on success or a negative errno.
1739+
*/
1740+
int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info)
1741+
{
1742+
struct net *net = genl_info_net(info);
1743+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1744+
void *hdr;
1745+
int err;
1746+
1747+
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1748+
if (!skb)
1749+
return -ENOMEM;
1750+
1751+
hdr = genlmsg_iput(skb, info);
1752+
if (!hdr) {
1753+
err = -EMSGSIZE;
1754+
goto err_free_msg;
1755+
}
1756+
1757+
mutex_lock(&nfsd_mutex);
1758+
1759+
err = nla_put_u32(skb, NFSD_A_SERVER_GRACETIME,
1760+
nn->nfsd4_grace) ||
1761+
nla_put_u32(skb, NFSD_A_SERVER_LEASETIME,
1762+
nn->nfsd4_lease) ||
1763+
nla_put_string(skb, NFSD_A_SERVER_SCOPE,
1764+
nn->nfsd_name);
1765+
if (err)
1766+
goto err_unlock;
1767+
1768+
if (nn->nfsd_serv) {
1769+
int i;
1770+
1771+
for (i = 0; i < nfsd_nrpools(net); ++i) {
1772+
struct svc_pool *sp = &nn->nfsd_serv->sv_pools[i];
1773+
1774+
err = nla_put_u32(skb, NFSD_A_SERVER_THREADS,
1775+
atomic_read(&sp->sp_nrthreads));
1776+
if (err)
1777+
goto err_unlock;
1778+
}
1779+
} else {
1780+
err = nla_put_u32(skb, NFSD_A_SERVER_THREADS, 0);
1781+
if (err)
1782+
goto err_unlock;
1783+
}
1784+
1785+
mutex_unlock(&nfsd_mutex);
1786+
1787+
genlmsg_end(skb, hdr);
1788+
1789+
return genlmsg_reply(skb, info);
1790+
1791+
err_unlock:
1792+
mutex_unlock(&nfsd_mutex);
1793+
err_free_msg:
1794+
nlmsg_free(skb);
1795+
1796+
return err;
1797+
}
1798+
16561799
/**
16571800
* nfsd_net_init - Prepare the nfsd_net portion of a new net namespace
16581801
* @net: a freshly-created network namespace

include/uapi/linux/nfsd_netlink.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,20 @@ enum {
2929
NFSD_A_RPC_STATUS_MAX = (__NFSD_A_RPC_STATUS_MAX - 1)
3030
};
3131

32+
enum {
33+
NFSD_A_SERVER_THREADS = 1,
34+
NFSD_A_SERVER_GRACETIME,
35+
NFSD_A_SERVER_LEASETIME,
36+
NFSD_A_SERVER_SCOPE,
37+
38+
__NFSD_A_SERVER_MAX,
39+
NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1)
40+
};
41+
3242
enum {
3343
NFSD_CMD_RPC_STATUS_GET = 1,
44+
NFSD_CMD_THREADS_SET,
45+
NFSD_CMD_THREADS_GET,
3446

3547
__NFSD_CMD_MAX,
3648
NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)

0 commit comments

Comments
 (0)