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,13 +20,16 @@
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
+/*
+ * 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,14 +49,11 @@
#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
@@ -136,30 +136,37 @@
/*
* Update the delegation policy with the
* value of "new_policy"
*/
void
-rfs4_set_deleg_policy(srv_deleg_policy_t new_policy)
+rfs4_set_deleg_policy(nfs4_srv_t *nsrv4, 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);
+ 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(void)
+rfs4_hold_deleg_policy(nfs4_srv_t *nsrv4)
{
- rw_enter(&rfs4_deleg_policy_lock, RW_READER);
+ rw_enter(&nsrv4->deleg_policy_lock, RW_READER);
}
void
-rfs4_rele_deleg_policy(void)
+rfs4_rele_deleg_policy(nfs4_srv_t *nsrv4)
{
- rw_exit(&rfs4_deleg_policy_lock);
+ 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,11 +215,11 @@
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;
+ zthread_exit();
}
/* Mark the cbinfo as having a thread in the NULL callback */
cbp->cb_nullcaller = TRUE;
@@ -276,11 +283,11 @@
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;
+ zthread_exit();
}
/* mark rfs4_client_t as CALLBACK NULL in progress */
cbp->cb_state = CB_INPROG;
mutex_exit(cbp->cb_lock);
@@ -318,12 +325,12 @@
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,11 +692,11 @@
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,
+ (void) zthread_create(NULL, 0, rfs4_do_cb_null, cp, 0,
minclsyspri);
}
static void
rfs4args_cb_recall_free(nfs_cb_argop4 *argop)
@@ -946,12 +953,12 @@
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,11 +982,11 @@
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;
+ zthread_exit();
}
mutex_exit(fp->rf_dinfo.rd_recall_lock);
mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -1008,11 +1015,11 @@
arg->trunc = map->trunc;
arg->dsp = dsp;
recall_count++;
- (void) thread_create(NULL, 0, do_recall, arg, 0, &p0, TS_RUN,
+ (void) zthread_create(NULL, 0, do_recall, arg, 0,
minclsyspri);
}
rfs4_dbe_unlock(fp->rf_dbe);
@@ -1033,10 +1040,11 @@
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,11 +1076,11 @@
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,
+ (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,16 +1212,16 @@
/*
* 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_delegation_policy(nfs4_srv_t *nsrv4, open_delegation_type4 dtype,
rfs4_dinfo_t *dinfo, clientid4 cid)
{
time_t elapsed;
- if (rfs4_deleg_policy != SRV_NORMAL_DELEGATE)
+ 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,25 +1260,30 @@
* 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 (rfs4_deleg_policy == SRV_NEVER_DELEGATE || dreq == DELEG_NONE)
+ if (nsrv4->nfs4_deleg_policy == SRV_NEVER_DELEGATE ||
+ dreq == DELEG_NONE) {
return (NULL);
+ }
/* Check to see if delegations have been temporarily disabled */
- mutex_enter(&rfs4_deleg_lock);
+ mutex_enter(&nsrv4->deleg_lock);
no_delegation = rfs4_deleg_disabled;
- mutex_exit(&rfs4_deleg_lock);
+ mutex_exit(&nsrv4->deleg_lock);
if (no_delegation)
return (NULL);
/* Don't grant a delegation if a deletion is impending. */
@@ -1347,11 +1360,11 @@
/*
* Based on policy and the history of the file get the
* actual delegation.
*/
- dtype = rfs4_delegation_policy(dtype, &fp->rf_dinfo,
+ 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,12 +1449,14 @@
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 (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
+ 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,28 +1517,30 @@
* 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;
- rfs4_hold_deleg_policy();
+ nsrv4 = nfs4_get_srv();
+ rfs4_hold_deleg_policy(nsrv4);
/* Is delegation enabled? */
- if (rfs4_deleg_policy != SRV_NEVER_DELEGATE) {
+ 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();
+ rfs4_rele_deleg_policy(nsrv4);
return (rc);
}
/*
* Release a hold on the hold_grant counter which
@@ -1531,11 +1548,13 @@
* or a rename is in progress.
*/
void
rfs4_clear_dont_grant(rfs4_file_t *fp)
{
- if (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
+ 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,22 +1886,28 @@
}
void
rfs4_disable_delegation(void)
{
- mutex_enter(&rfs4_deleg_lock);
+ nfs4_srv_t *nsrv4;
+
+ nsrv4 = nfs4_get_srv();
+ mutex_enter(&nsrv4->deleg_lock);
rfs4_deleg_disabled++;
- mutex_exit(&rfs4_deleg_lock);
+ mutex_exit(&nsrv4->deleg_lock);
}
void
rfs4_enable_delegation(void)
{
- mutex_enter(&rfs4_deleg_lock);
+ nfs4_srv_t *nsrv4;
+
+ nsrv4 = nfs4_get_srv();
+ mutex_enter(&nsrv4->deleg_lock);
ASSERT(rfs4_deleg_disabled > 0);
rfs4_deleg_disabled--;
- mutex_exit(&rfs4_deleg_lock);
+ mutex_exit(&nsrv4->deleg_lock);
}
void
rfs4_mon_hold(void *arg)
{