/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy is of the CDDL is also available via the Internet
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
* NFS Lock Manager, server-side and common.
*
* This file contains all the external entry points of klmmod.
* Basically, this is the "glue" to the BSD nlm code.
*/
#include <rpcsvc/nlm_prot.h>
#include "nlm_impl.h"
&mod_miscops, "lock mgr common module"
};
};
/*
* Cluster node ID. Zero unless we're part of a cluster.
* Set by lm_set_nlmid_flk. Pass to lm_set_nlm_status.
* We're not yet doing "clustered" NLM stuff.
*/
int lm_global_nlmid = 0;
/*
* Call-back hook for clusters: Set lock manager status.
* If this hook is set, call this instead of the ususal
* flk_set_lockmgr_status(FLK_LOCKMGR_UP / DOWN);
*/
/*
* Call-back hook for clusters: Delete all locks held by sysid.
* Call from code that drops all client locks (for which we're
* the server) i.e. after the SM tells us a client has crashed.
*/
/*
*/
/* ARGSUSED */
void *
{
struct nlm_globals *g;
g = kmem_zalloc(sizeof (*g), KM_SLEEP);
sizeof (struct nlm_host),
64, mod_hash_null_valdtor);
TAILQ_INIT(&g->nlm_idle_hosts);
TAILQ_INIT(&g->nlm_slocks);
g->lockd_pid = 0;
g->run_status = NLM_ST_DOWN;
return (g);
}
/* ARGSUSED */
void
{
struct nlm_globals *g = data;
avl_destroy(&g->nlm_hosts_tree);
mutex_destroy(&g->lock);
cv_destroy(&g->nlm_gc_sched_cv);
cv_destroy(&g->nlm_gc_finish_cv);
mutex_destroy(&g->clean_lock);
kmem_free(g, sizeof (*g));
}
/*
* ****************************************************************
* module init, fini, info
*/
int
_init()
{
int retval;
nlm_init();
if (retval == 0)
return (0);
/*
* mod_install failed! undo above, reverse order
*/
(void) zone_key_delete(flock_zone_key);
(void) zone_key_delete(nlm_zone_key);
rw_destroy(&lm_lck);
return (retval);
}
int
_fini()
{
/* Don't unload. */
return (EBUSY);
}
int
{
}
/*
* ****************************************************************
* Stubs listed in modstubs.s
*/
/*
* klm system calls. Start service on some endpoint.
* Called by nfssys() LM_SVC, from lockd.
*/
int
{
const char *netid;
struct nlm_globals *g;
int err = 0;
/* Get our "globals" */
/*
* Check version of lockd calling.
*/
NLM_ERR("lm_svc: Version mismatch "
"(given 0x%x, expected 0x%x)\n",
return (EINVAL);
}
/*
* Build knetconfig, checking arg values.
* Also come up with the "netid" string.
*/
case LM_TCP:
break;
case LM_UDP:
break;
default:
NLM_ERR("nlm_build_knetconfig: Unknown "
return (EINVAL);
}
case LM_INET:
break;
case LM_INET6:
break;
case LM_LOOPBACK:
/* Override what we set above. */
break;
default:
NLM_ERR("nlm_build_knetconfig: Unknown "
return (EINVAL);
}
if (!netid)
return (EINVAL);
/*
* Setup service on the passed transport.
* NB: must releasef(fp) after this.
*/
return (EBADF);
mutex_enter(&g->lock);
/*
* Don't try to start while still shutting down,
* or lots of things will fail...
*/
if (g->run_status == NLM_ST_STOPPING) {
goto out;
}
/*
* There is no separate "initialize" sub-call for nfssys,
* and we want to do some one-time work when the first
* binding comes in from lockd.
*/
if (g->run_status == NLM_ST_DOWN) {
g->run_status = NLM_ST_STARTING;
/* Save the options. */
/* See nfs_sys.c (not yet per-zone) */
if (INGLOBALZONE(curproc)) {
}
mutex_exit(&g->lock);
mutex_enter(&g->lock);
} else {
/*
* If KLM is not started and the very first endpoint lockd
* tries to add is not a loopback device, report an error.
*/
if (g->run_status != NLM_ST_UP) {
err = ENOTACTIVE;
goto out;
}
/* Check if caller has the same PID lockd does */
goto out;
}
}
out:
mutex_exit(&g->lock);
return (err);
}
/*
* klm system calls. Kill the lock manager.
* Called by nfssys() KILL_LOCKMGR,
* liblm:lm_shutdown() <- unused?
*/
int
lm_shutdown(void)
{
struct nlm_globals *g;
proc_t *p;
/* Get our "globals" */
mutex_enter(&g->lock);
if (g->run_status != NLM_ST_UP) {
mutex_exit(&g->lock);
return (EBUSY);
}
g->run_status = NLM_ST_STOPPING;
mutex_exit(&g->lock);
nlm_svc_stopping(g);
if (p != NULL)
return (0);
}
/*
* Cleanup remote locks on FS un-export.
*
* NOTE: called from nfs_export.c:unexport()
* right before the share is going to
* be unexported.
*/
void
{
}
/*
* See:cpr_suspend, cpr_resume
*
* Before suspend, get current state from "statd" on
* all remote systems for which we have locks.
*
* After resume, check with those systems again,
* and either reclaim locks, or do SIGLOST.
*/
void
lm_cprsuspend(void)
{
}
void
lm_cprresume(void)
{
}
/*
* Add the nlm_id bits to the sysid (by ref).
*/
void
{
if (lm_global_nlmid != 0)
}
/*
* It seems that closed source klmmod used
* this function to release knetconfig stored
* in mntinfo structure (see mntinfo's mi_klmconfig
* field).
* We store knetconfigs differently, thus we don't
* need this function.
*/
void
{
}
/*
* Called by NFS4 delegation code to check if there are any
*
* NOTE: called from NFSv4 code
* (see nfs4_srv_deleg.c:rfs4_bgrant_delegation())
*/
int
{
return (nlm_vp_active(vp));
}
/*
* Find or create a "sysid" for given knc+addr.
* name is optional. Sets nc_changed if the
* found knc_proto is different from passed.
* Increments the reference count.
*
* Called internally, and in nfs4_find_sysid()
*/
struct lm_sysid *
{
struct nlm_globals *g;
const char *netid;
return (NULL);
return (NULL);
}
/*
* Release a reference on a "sysid".
*/
void
{
struct nlm_globals *g;
}
/*
* LM_SYSID and LM_SYSID_MAX).
*
* Used by NFSv4 rfs4_op_lockt and smbsrv/smb_fsop_frlock,
* both to represent non-local locks outside of klm.
*
* NOTE: called from NFSv4 and SMBFS to allocate unique
* sysid.
*/
lm_alloc_sysidt(void)
{
return (nlm_sysid_alloc());
}
void
{
}
/* Access private member lms->sysid */
{
}
/*
* Called by nfs_frlock to check lock constraints.
* Return non-zero if the lock request is "safe", i.e.
* the range is not mapped, not MANDLOCK, etc.
*
* determine whether it's safe to add new lock.
*/
int
{
}
/*
* Called by nfs_lockcompletion to check whether it's "safe"
* to map the file (and cache it's data). Walks the list of
* file locks looking for any that are not "whole file".
*
* NOTE: called from nfs_client.c:nfs_lockcompletion()
*/
int
{
return (nlm_safemap(vp));
}
/*
* Called by nfs_map() for the MANDLOCK case.
* Return non-zero if the file has any locks with a
* blocked request (sleep).
*
* order to determine whether it's safe to add new
* mapping.
*/
int
{
return (nlm_has_sleep(vp));
}
/*
* ****************************************************************
* Stuff needed by klmops?
*/