Print this page
NEX-15279 support NFS server in zone
NEX-15520 online NFS shares cause zoneadm halt to hang in nfs_export_zone_fini
Portions contributed by: Dan Kruchinin dan.kruchinin@nexenta.com
Portions contributed by: Stepan Zastupov stepan.zastupov@gmail.com
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
4487 snoop can only work with 2GB files
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
Reviewed by: Sebastien Roy <sebastien.roy@delphix.com>
Approved by: Garrett D'Amore <garrett@damore.org>
3105 Kernel inet_pton() implementation returns result in host byte order
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Robert Mustacchi <rm@joyent.com>

*** 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 = zone_getspecific(rfs4_zone_key, curzone); + 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,1287 ---- * 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 = zone_getspecific(rfs4_zone_key, curzone); + /* 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; --- 1358,1368 ---- /* * 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) { --- 1447,1460 ---- 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 = zone_getspecific(rfs4_zone_key, curzone); + /* 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 --- 1515,1544 ---- * 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 = zone_getspecific(rfs4_zone_key, curzone); ! 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; --- 1546,1558 ---- * or a rename is in progress. */ void rfs4_clear_dont_grant(rfs4_file_t *fp) { ! nfs4_srv_t *nsrv4 = zone_getspecific(rfs4_zone_key, curzone); ! ! 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) { --- 1884,1911 ---- } void rfs4_disable_delegation(void) { ! nfs4_srv_t *nsrv4; ! ! nsrv4 = zone_getspecific(rfs4_zone_key, curzone); ! mutex_enter(&nsrv4->deleg_lock); rfs4_deleg_disabled++; ! mutex_exit(&nsrv4->deleg_lock); } void rfs4_enable_delegation(void) { ! nfs4_srv_t *nsrv4; ! ! nsrv4 = zone_getspecific(rfs4_zone_key, curzone); ! mutex_enter(&nsrv4->deleg_lock); ASSERT(rfs4_deleg_disabled > 0); rfs4_deleg_disabled--; ! mutex_exit(&nsrv4->deleg_lock); } void rfs4_mon_hold(void *arg) {