|
15 | 15 | #include <linux/sunrpc/addr.h> |
16 | 16 | #include <linux/sunrpc/gss_api.h> |
17 | 17 | #include <linux/sunrpc/rpc_pipe_fs.h> |
| 18 | +#include <linux/sunrpc/svc.h> |
18 | 19 | #include <linux/module.h> |
19 | 20 | #include <linux/fsnotify.h> |
20 | 21 |
|
@@ -1653,6 +1654,148 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb) |
1653 | 1654 | return 0; |
1654 | 1655 | } |
1655 | 1656 |
|
| 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 | + |
1656 | 1799 | /** |
1657 | 1800 | * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace |
1658 | 1801 | * @net: a freshly-created network namespace |
|
0 commit comments