// SPDX-License-Identifier: GPL-2.0-only /* * linux/fs/lockd/svc.c * * This is the central lockd service. * * FIXME: Separate the lockd NFS server functionality from the lockd NFS * client functionality. Oh why didn't Sun create two separate * services in the first place? * * Authors: Olaf Kirch (okir@monad.swb.de) * * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
/* * These can be set at insmod time (useful for NFS as root filesystem), * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
*/ staticunsignedlong nlm_grace_period; unsignedlong nlm_timeout = LOCKD_DFLT_TIMEO; staticint nlm_udpport, nlm_tcpport;
/* * This is the lockd kernel thread
*/ staticint
lockd(void *vrqstp)
{ struct svc_rqst *rqstp = vrqstp; struct net *net = &init_net; struct lockd_net *ln = net_generic(net, lockd_net_id);
svc_thread_init_status(rqstp, 0);
/* try_to_freeze() is called from svc_recv() */
set_freezable();
dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
/* * The main request loop. We don't terminate until the last * NFS mount or NFS daemon has gone away.
*/ while (!svc_thread_should_stop(rqstp)) {
nlmsvc_retry_blocked(rqstp);
svc_recv(rqstp);
} if (nlmsvc_ops)
nlmsvc_invalidate_all();
nlm_shutdown_hosts();
cancel_delayed_work_sync(&ln->grace_period_end);
locks_end_grace(&ln->lockd_manager);
/* * Ensure there are active UDP and TCP listeners for lockd. * * Even if we have only TCP NFS mounts and/or TCP NFSDs, some * local services (such as rpc.statd) still require UDP, and * some NFS servers do not yet support NLM over TCP. * * Returns zero if all listeners are available; otherwise a * negative errno value is returned.
*/ staticint make_socks(struct svc_serv *serv, struct net *net, conststruct cred *cred)
{ staticint warned; int err;
staticint lockd_get(void)
{ struct svc_serv *serv; int error;
if (nlmsvc_serv) {
nlmsvc_users++; return 0;
}
/* * Sanity check: if there's no pid, * we should be the first user ...
*/ if (nlmsvc_users)
printk(KERN_WARNING "lockd_up: no pid, %d users??\n", nlmsvc_users);
serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, lockd); if (!serv) {
printk(KERN_WARNING "lockd_up: create service failed\n"); return -ENOMEM;
}
/* * Decrement the user count and bring down lockd if we're the last.
*/ void
lockd_down(struct net *net)
{
mutex_lock(&nlmsvc_mutex);
lockd_down_net(nlmsvc_serv, net);
lockd_put();
mutex_unlock(&nlmsvc_mutex);
}
EXPORT_SYMBOL_GPL(lockd_down);
#ifdef CONFIG_SYSCTL
/* * Sysctl parameters (same as module parameters, different interface).
*/
WARN_ONCE(!list_empty(&ln->lockd_manager.list), "net %x %s: lockd_manager.list is not empty\n",
net->ns.inum, __func__);
WARN_ONCE(!list_empty(&ln->nsm_handles), "net %x %s: nsm_handles list is not empty\n",
net->ns.inum, __func__);
WARN_ONCE(delayed_work_pending(&ln->grace_period_end), "net %x %s: grace_period_end was not cancelled\n",
net->ns.inum, __func__);
}
#define NLM_NRVERS ARRAY_SIZE(nlmsvc_version) staticstruct svc_program nlmsvc_program = {
.pg_prog = NLM_PROGRAM, /* program number */
.pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
.pg_vers = nlmsvc_version, /* version table */
.pg_name = "lockd", /* service name */
.pg_class = "nfsd", /* share authentication with nfsd */
.pg_authenticate = &lockd_authenticate, /* export authentication */
.pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
};
/** * lockd_nl_server_set_doit - set the lockd server parameters via netlink * @skb: reply buffer * @info: netlink metadata and command arguments * * This updates the per-net values. When updating the values in the init_net * namespace, also update the "legacy" global values. * * Return 0 on success or a negative errno.
*/ int lockd_nl_server_set_doit(struct sk_buff *skb, struct genl_info *info)
{ struct net *net = genl_info_net(info); struct lockd_net *ln = net_generic(net, lockd_net_id); conststruct nlattr *attr;
if (GENL_REQ_ATTR_CHECK(info, LOCKD_A_SERVER_GRACETIME)) return -EINVAL;
if (info->attrs[LOCKD_A_SERVER_GRACETIME] ||
info->attrs[LOCKD_A_SERVER_TCP_PORT] ||
info->attrs[LOCKD_A_SERVER_UDP_PORT]) {
attr = info->attrs[LOCKD_A_SERVER_GRACETIME]; if (attr) {
u32 gracetime = nla_get_u32(attr);
if (gracetime > nlm_grace_period_max) return -EINVAL;
ln->gracetime = gracetime;
if (net == &init_net)
nlm_grace_period = gracetime;
}
attr = info->attrs[LOCKD_A_SERVER_TCP_PORT]; if (attr) {
ln->tcp_port = nla_get_u16(attr); if (net == &init_net)
nlm_tcpport = ln->tcp_port;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.