Print this page
11083 support NFS server in zone
Portions contributed by: Dan Kruchinin <dan.kruchinin@nexenta.com>
Portions contributed by: Stepan Zastupov <stepan.zastupov@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Portions contributed by: Mike Zeller <mike@mikezeller.net>
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Portions contributed by: Vitaliy Gusev <gusev.vitaliy@gmail.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Change-Id: I22f289d357503f9b48a0bc2482cc4328a6d43d16
*** 20,32 ****
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/systm.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include <nfs/nfs4_kprot.h>
#include <nfs/nfs4.h>
--- 20,35 ----
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+ /*
+ * Copyright 2018 Nexenta Systems, Inc.
+ */
+
#include <sys/systm.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include <nfs/nfs4_kprot.h>
#include <nfs/nfs4.h>
*** 46,59 ****
#include <inet/ip.h>
#include <inet/ip6.h>
#define MAX_READ_DELEGATIONS 5
- krwlock_t rfs4_deleg_policy_lock;
- srv_deleg_policy_t rfs4_deleg_policy = SRV_NEVER_DELEGATE;
static int rfs4_deleg_wlp = 5;
- kmutex_t rfs4_deleg_lock;
static int rfs4_deleg_disabled;
static int rfs4_max_setup_cb_tries = 5;
#ifdef DEBUG
--- 49,59 ----
*** 136,165 ****
/*
* Update the delegation policy with the
* value of "new_policy"
*/
void
! rfs4_set_deleg_policy(srv_deleg_policy_t new_policy)
{
! rw_enter(&rfs4_deleg_policy_lock, RW_WRITER);
! rfs4_deleg_policy = new_policy;
! rw_exit(&rfs4_deleg_policy_lock);
}
void
! rfs4_hold_deleg_policy(void)
{
! rw_enter(&rfs4_deleg_policy_lock, RW_READER);
}
void
! rfs4_rele_deleg_policy(void)
{
! rw_exit(&rfs4_deleg_policy_lock);
}
/*
* This free function is to be used when the client struct is being
* released and nothing at all is needed of the callback info any
* longer.
*/
--- 136,172 ----
/*
* Update the delegation policy with the
* value of "new_policy"
*/
void
! rfs4_set_deleg_policy(nfs4_srv_t *nsrv4, srv_deleg_policy_t new_policy)
{
! rw_enter(&nsrv4->deleg_policy_lock, RW_WRITER);
! nsrv4->nfs4_deleg_policy = new_policy;
! rw_exit(&nsrv4->deleg_policy_lock);
}
void
! rfs4_hold_deleg_policy(nfs4_srv_t *nsrv4)
{
! rw_enter(&nsrv4->deleg_policy_lock, RW_READER);
}
void
! rfs4_rele_deleg_policy(nfs4_srv_t *nsrv4)
{
! rw_exit(&nsrv4->deleg_policy_lock);
}
+ srv_deleg_policy_t
+ nfs4_get_deleg_policy()
+ {
+ nfs4_srv_t *nsrv4 = nfs4_get_srv();
+ return (nsrv4->nfs4_deleg_policy);
+ }
+
/*
* This free function is to be used when the client struct is being
* released and nothing at all is needed of the callback info any
* longer.
*/
*** 208,218 ****
mutex_enter(cbp->cb_lock);
/* If another thread is doing CB_NULL RPC then return */
if (cbp->cb_nullcaller == TRUE) {
mutex_exit(cbp->cb_lock);
rfs4_client_rele(cp);
! return;
}
/* Mark the cbinfo as having a thread in the NULL callback */
cbp->cb_nullcaller = TRUE;
--- 215,225 ----
mutex_enter(cbp->cb_lock);
/* If another thread is doing CB_NULL RPC then return */
if (cbp->cb_nullcaller == TRUE) {
mutex_exit(cbp->cb_lock);
rfs4_client_rele(cp);
! zthread_exit();
}
/* Mark the cbinfo as having a thread in the NULL callback */
cbp->cb_nullcaller = TRUE;
*** 276,286 ****
if (cbp->cb_state != CB_NONE) {
cv_broadcast(cbp->cb_cv); /* let the others know */
cbp->cb_nullcaller = FALSE;
mutex_exit(cbp->cb_lock);
rfs4_client_rele(cp);
! return;
}
/* mark rfs4_client_t as CALLBACK NULL in progress */
cbp->cb_state = CB_INPROG;
mutex_exit(cbp->cb_lock);
--- 283,293 ----
if (cbp->cb_state != CB_NONE) {
cv_broadcast(cbp->cb_cv); /* let the others know */
cbp->cb_nullcaller = FALSE;
mutex_exit(cbp->cb_lock);
rfs4_client_rele(cp);
! zthread_exit();
}
/* mark rfs4_client_t as CALLBACK NULL in progress */
cbp->cb_state = CB_INPROG;
mutex_exit(cbp->cb_lock);
*** 318,329 ****
cbp->cb_timefailed = gethrestime_sec(); /* observability */
cv_broadcast(cbp->cb_cv); /* start up the other threads */
cbp->cb_nullcaller = FALSE;
mutex_exit(cbp->cb_lock);
-
rfs4_client_rele(cp);
}
/*
* Given a client struct, inspect the callback info to see if the
* callback path is up and available.
--- 325,336 ----
cbp->cb_timefailed = gethrestime_sec(); /* observability */
cv_broadcast(cbp->cb_cv); /* start up the other threads */
cbp->cb_nullcaller = FALSE;
mutex_exit(cbp->cb_lock);
rfs4_client_rele(cp);
+ zthread_exit();
}
/*
* Given a client struct, inspect the callback info to see if the
* callback path is up and available.
*** 685,695 ****
cp->rc_cbinfo.cb_newer.cb_confirmed = TRUE;
rfs4_dbe_hold(cp->rc_dbe); /* hold the client struct for thread */
! (void) thread_create(NULL, 0, rfs4_do_cb_null, cp, 0, &p0, TS_RUN,
minclsyspri);
}
static void
rfs4args_cb_recall_free(nfs_cb_argop4 *argop)
--- 692,702 ----
cp->rc_cbinfo.cb_newer.cb_confirmed = TRUE;
rfs4_dbe_hold(cp->rc_dbe); /* hold the client struct for thread */
! (void) zthread_create(NULL, 0, rfs4_do_cb_null, cp, 0,
minclsyspri);
}
static void
rfs4args_cb_recall_free(nfs_cb_argop4 *argop)
*** 946,957 ****
mutex_enter(&cpr_lock);
CALLB_CPR_EXIT(&cpr_info);
mutex_destroy(&cpr_lock);
rfs4_deleg_state_rele(dsp); /* release the hold for this thread */
-
kmem_free(arg, sizeof (struct recall_arg));
}
struct master_recall_args {
rfs4_file_t *fp;
void (*recall)(rfs4_deleg_state_t *, bool_t);
--- 953,964 ----
mutex_enter(&cpr_lock);
CALLB_CPR_EXIT(&cpr_info);
mutex_destroy(&cpr_lock);
rfs4_deleg_state_rele(dsp); /* release the hold for this thread */
kmem_free(arg, sizeof (struct recall_arg));
+ zthread_exit();
}
struct master_recall_args {
rfs4_file_t *fp;
void (*recall)(rfs4_deleg_state_t *, bool_t);
*** 975,985 ****
if (fp->rf_dinfo.rd_recall_count != 0) {
mutex_exit(fp->rf_dinfo.rd_recall_lock);
rfs4_dbe_rele_nolock(fp->rf_dbe);
rfs4_dbe_unlock(fp->rf_dbe);
kmem_free(map, sizeof (struct master_recall_args));
! return;
}
mutex_exit(fp->rf_dinfo.rd_recall_lock);
mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
--- 982,992 ----
if (fp->rf_dinfo.rd_recall_count != 0) {
mutex_exit(fp->rf_dinfo.rd_recall_lock);
rfs4_dbe_rele_nolock(fp->rf_dbe);
rfs4_dbe_unlock(fp->rf_dbe);
kmem_free(map, sizeof (struct master_recall_args));
! zthread_exit();
}
mutex_exit(fp->rf_dinfo.rd_recall_lock);
mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
*** 1008,1018 ****
arg->trunc = map->trunc;
arg->dsp = dsp;
recall_count++;
! (void) thread_create(NULL, 0, do_recall, arg, 0, &p0, TS_RUN,
minclsyspri);
}
rfs4_dbe_unlock(fp->rf_dbe);
--- 1015,1025 ----
arg->trunc = map->trunc;
arg->dsp = dsp;
recall_count++;
! (void) zthread_create(NULL, 0, do_recall, arg, 0,
minclsyspri);
}
rfs4_dbe_unlock(fp->rf_dbe);
*** 1033,1042 ****
--- 1040,1050 ----
rfs4_file_rele(fp);
kmem_free(map, sizeof (struct master_recall_args));
mutex_enter(&cpr_lock);
CALLB_CPR_EXIT(&cpr_info);
mutex_destroy(&cpr_lock);
+ zthread_exit();
}
static void
rfs4_recall_file(rfs4_file_t *fp,
void (*recall)(rfs4_deleg_state_t *, bool_t trunc),
*** 1068,1078 ****
args = kmem_alloc(sizeof (struct master_recall_args), KM_SLEEP);
args->fp = fp;
args->recall = recall;
args->trunc = trunc;
! (void) thread_create(NULL, 0, do_recall_file, args, 0, &p0, TS_RUN,
minclsyspri);
}
void
rfs4_recall_deleg(rfs4_file_t *fp, bool_t trunc, rfs4_client_t *cp)
--- 1076,1086 ----
args = kmem_alloc(sizeof (struct master_recall_args), KM_SLEEP);
args->fp = fp;
args->recall = recall;
args->trunc = trunc;
! (void) zthread_create(NULL, 0, do_recall_file, args, 0,
minclsyspri);
}
void
rfs4_recall_deleg(rfs4_file_t *fp, bool_t trunc, rfs4_client_t *cp)
*** 1204,1219 ****
/*
* Given the desired delegation type and the "history" of the file
* determine the actual delegation type to return.
*/
static open_delegation_type4
! rfs4_delegation_policy(open_delegation_type4 dtype,
rfs4_dinfo_t *dinfo, clientid4 cid)
{
time_t elapsed;
! if (rfs4_deleg_policy != SRV_NORMAL_DELEGATE)
return (OPEN_DELEGATE_NONE);
/*
* Has this file/delegation ever been recalled? If not then
* no further checks for a delegation race need to be done.
--- 1212,1227 ----
/*
* Given the desired delegation type and the "history" of the file
* determine the actual delegation type to return.
*/
static open_delegation_type4
! rfs4_delegation_policy(nfs4_srv_t *nsrv4, open_delegation_type4 dtype,
rfs4_dinfo_t *dinfo, clientid4 cid)
{
time_t elapsed;
! if (nsrv4->nfs4_deleg_policy != SRV_NORMAL_DELEGATE)
return (OPEN_DELEGATE_NONE);
/*
* Has this file/delegation ever been recalled? If not then
* no further checks for a delegation race need to be done.
*** 1252,1276 ****
* The state and associate file entry must be locked
*/
rfs4_deleg_state_t *
rfs4_grant_delegation(delegreq_t dreq, rfs4_state_t *sp, int *recall)
{
rfs4_file_t *fp = sp->rs_finfo;
open_delegation_type4 dtype;
int no_delegation;
ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
ASSERT(rfs4_dbe_islocked(fp->rf_dbe));
/* Is the server even providing delegations? */
! if (rfs4_deleg_policy == SRV_NEVER_DELEGATE || dreq == DELEG_NONE)
return (NULL);
/* Check to see if delegations have been temporarily disabled */
! mutex_enter(&rfs4_deleg_lock);
no_delegation = rfs4_deleg_disabled;
! mutex_exit(&rfs4_deleg_lock);
if (no_delegation)
return (NULL);
/* Don't grant a delegation if a deletion is impending. */
--- 1260,1289 ----
* The state and associate file entry must be locked
*/
rfs4_deleg_state_t *
rfs4_grant_delegation(delegreq_t dreq, rfs4_state_t *sp, int *recall)
{
+ nfs4_srv_t *nsrv4;
rfs4_file_t *fp = sp->rs_finfo;
open_delegation_type4 dtype;
int no_delegation;
ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
ASSERT(rfs4_dbe_islocked(fp->rf_dbe));
+ nsrv4 = nfs4_get_srv();
+
/* Is the server even providing delegations? */
! if (nsrv4->nfs4_deleg_policy == SRV_NEVER_DELEGATE ||
! dreq == DELEG_NONE) {
return (NULL);
+ }
/* Check to see if delegations have been temporarily disabled */
! mutex_enter(&nsrv4->deleg_lock);
no_delegation = rfs4_deleg_disabled;
! mutex_exit(&nsrv4->deleg_lock);
if (no_delegation)
return (NULL);
/* Don't grant a delegation if a deletion is impending. */
*** 1347,1357 ****
/*
* Based on policy and the history of the file get the
* actual delegation.
*/
! dtype = rfs4_delegation_policy(dtype, &fp->rf_dinfo,
sp->rs_owner->ro_client->rc_clientid);
if (dtype == OPEN_DELEGATE_NONE)
return (NULL);
break;
--- 1360,1370 ----
/*
* Based on policy and the history of the file get the
* actual delegation.
*/
! dtype = rfs4_delegation_policy(nsrv4, dtype, &fp->rf_dinfo,
sp->rs_owner->ro_client->rc_clientid);
if (dtype == OPEN_DELEGATE_NONE)
return (NULL);
break;
*** 1436,1447 ****
rfs4_check_delegated_byfp(int mode, rfs4_file_t *fp,
bool_t trunc, bool_t do_delay, bool_t is_rm, clientid4 *cp)
{
rfs4_deleg_state_t *dsp;
/* Is delegation enabled? */
! if (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
return (FALSE);
/* do we have a delegation on this file? */
rfs4_dbe_lock(fp->rf_dbe);
if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
--- 1449,1462 ----
rfs4_check_delegated_byfp(int mode, rfs4_file_t *fp,
bool_t trunc, bool_t do_delay, bool_t is_rm, clientid4 *cp)
{
rfs4_deleg_state_t *dsp;
+ nfs4_srv_t *nsrv4 = nfs4_get_srv();
+
/* Is delegation enabled? */
! if (nsrv4->nfs4_deleg_policy == SRV_NEVER_DELEGATE)
return (FALSE);
/* do we have a delegation on this file? */
rfs4_dbe_lock(fp->rf_dbe);
if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
*** 1502,1529 ****
* drop the request and in the case of v3 JUKEBOX should be returned.
*/
bool_t
rfs4_check_delegated(int mode, vnode_t *vp, bool_t trunc)
{
rfs4_file_t *fp;
bool_t create = FALSE;
bool_t rc = FALSE;
! rfs4_hold_deleg_policy();
/* Is delegation enabled? */
! if (rfs4_deleg_policy != SRV_NEVER_DELEGATE) {
fp = rfs4_findfile(vp, NULL, &create);
if (fp != NULL) {
if (rfs4_check_delegated_byfp(mode, fp, trunc,
TRUE, FALSE, NULL)) {
rc = TRUE;
}
rfs4_file_rele(fp);
}
}
! rfs4_rele_deleg_policy();
return (rc);
}
/*
* Release a hold on the hold_grant counter which
--- 1517,1546 ----
* drop the request and in the case of v3 JUKEBOX should be returned.
*/
bool_t
rfs4_check_delegated(int mode, vnode_t *vp, bool_t trunc)
{
+ nfs4_srv_t *nsrv4;
rfs4_file_t *fp;
bool_t create = FALSE;
bool_t rc = FALSE;
! nsrv4 = nfs4_get_srv();
! rfs4_hold_deleg_policy(nsrv4);
/* Is delegation enabled? */
! if (nsrv4->nfs4_deleg_policy != SRV_NEVER_DELEGATE) {
fp = rfs4_findfile(vp, NULL, &create);
if (fp != NULL) {
if (rfs4_check_delegated_byfp(mode, fp, trunc,
TRUE, FALSE, NULL)) {
rc = TRUE;
}
rfs4_file_rele(fp);
}
}
! rfs4_rele_deleg_policy(nsrv4);
return (rc);
}
/*
* Release a hold on the hold_grant counter which
*** 1531,1541 ****
* or a rename is in progress.
*/
void
rfs4_clear_dont_grant(rfs4_file_t *fp)
{
! if (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
return;
rfs4_dbe_lock(fp->rf_dbe);
ASSERT(fp->rf_dinfo.rd_hold_grant > 0);
fp->rf_dinfo.rd_hold_grant--;
fp->rf_dinfo.rd_time_rm_delayed = 0;
--- 1548,1560 ----
* or a rename is in progress.
*/
void
rfs4_clear_dont_grant(rfs4_file_t *fp)
{
! nfs4_srv_t *nsrv4 = nfs4_get_srv();
!
! if (nsrv4->nfs4_deleg_policy == SRV_NEVER_DELEGATE)
return;
rfs4_dbe_lock(fp->rf_dbe);
ASSERT(fp->rf_dinfo.rd_hold_grant > 0);
fp->rf_dinfo.rd_hold_grant--;
fp->rf_dinfo.rd_time_rm_delayed = 0;
*** 1867,1888 ****
}
void
rfs4_disable_delegation(void)
{
! mutex_enter(&rfs4_deleg_lock);
rfs4_deleg_disabled++;
! mutex_exit(&rfs4_deleg_lock);
}
void
rfs4_enable_delegation(void)
{
! mutex_enter(&rfs4_deleg_lock);
ASSERT(rfs4_deleg_disabled > 0);
rfs4_deleg_disabled--;
! mutex_exit(&rfs4_deleg_lock);
}
void
rfs4_mon_hold(void *arg)
{
--- 1886,1913 ----
}
void
rfs4_disable_delegation(void)
{
! nfs4_srv_t *nsrv4;
!
! nsrv4 = nfs4_get_srv();
! mutex_enter(&nsrv4->deleg_lock);
rfs4_deleg_disabled++;
! mutex_exit(&nsrv4->deleg_lock);
}
void
rfs4_enable_delegation(void)
{
! nfs4_srv_t *nsrv4;
!
! nsrv4 = nfs4_get_srv();
! mutex_enter(&nsrv4->deleg_lock);
ASSERT(rfs4_deleg_disabled > 0);
rfs4_deleg_disabled--;
! mutex_exit(&nsrv4->deleg_lock);
}
void
rfs4_mon_hold(void *arg)
{