nfsd: allow passing in array of thread counts via netlink

Now that nfsd_svc can handle an array of thread counts, fix up the
netlink threads interface to construct one from the netlink call
and pass it through so we can start a pooled server the same way we
would start a normal one.

Note that any unspecified values in the array are considered zeroes,
so it's possible to shut down a pooled server by passing in a short
array that has only zeros, or even an empty array.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by Jeff Layton and committed by Chuck Lever 7f5c330b b4d8f228

+31 -13
+20 -12
fs/nfsd/nfsctl.c
··· 1645 1645 */ 1646 1646 int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info) 1647 1647 { 1648 - int nthreads = 0, count = 0, nrpools, ret = -EOPNOTSUPP, rem; 1648 + int *nthreads, count = 0, nrpools, i, ret = -EOPNOTSUPP, rem; 1649 1649 struct net *net = genl_info_net(info); 1650 1650 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1651 1651 const struct nlattr *attr; ··· 1662 1662 1663 1663 mutex_lock(&nfsd_mutex); 1664 1664 1665 - nrpools = nfsd_nrpools(net); 1666 - if (nrpools && count > nrpools) 1667 - count = nrpools; 1668 - 1669 - /* XXX: make this handle non-global pool-modes */ 1670 - if (count > 1) 1665 + nrpools = max(count, nfsd_nrpools(net)); 1666 + nthreads = kcalloc(nrpools, sizeof(int), GFP_KERNEL); 1667 + if (!nthreads) { 1668 + ret = -ENOMEM; 1671 1669 goto out_unlock; 1670 + } 1672 1671 1673 - nthreads = nla_get_u32(info->attrs[NFSD_A_SERVER_THREADS]); 1672 + i = 0; 1673 + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1674 + if (nla_type(attr) == NFSD_A_SERVER_THREADS) { 1675 + nthreads[i++] = nla_get_u32(attr); 1676 + if (i >= nrpools) 1677 + break; 1678 + } 1679 + } 1680 + 1674 1681 if (info->attrs[NFSD_A_SERVER_GRACETIME] || 1675 1682 info->attrs[NFSD_A_SERVER_LEASETIME] || 1676 1683 info->attrs[NFSD_A_SERVER_SCOPE]) { ··· 1711 1704 scope = nla_data(attr); 1712 1705 } 1713 1706 1714 - ret = nfsd_svc(1, &nthreads, net, get_current_cred(), scope); 1715 - 1707 + ret = nfsd_svc(nrpools, nthreads, net, get_current_cred(), scope); 1708 + if (ret > 0) 1709 + ret = 0; 1716 1710 out_unlock: 1717 1711 mutex_unlock(&nfsd_mutex); 1718 - 1719 - return ret == nthreads ? 0 : ret; 1712 + kfree(nthreads); 1713 + return ret; 1720 1714 } 1721 1715 1722 1716 /**
+11 -1
fs/nfsd/nfssvc.c
··· 769 769 &nn->nfsd_serv->sv_pools[i], 770 770 nthreads[i]); 771 771 if (err) 772 - break; 772 + goto out; 773 773 } 774 + 775 + /* Anything undefined in array is considered to be 0 */ 776 + for (i = n; i < nn->nfsd_serv->sv_nrpools; ++i) { 777 + err = svc_set_num_threads(nn->nfsd_serv, 778 + &nn->nfsd_serv->sv_pools[i], 779 + 0); 780 + if (err) 781 + goto out; 782 + } 783 + out: 774 784 return err; 775 785 } 776 786