17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5cee86682Scalum * Common Development and Distribution License (the "License").
6cee86682Scalum * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
210dfe541eSEvan Layton
227c478bd9Sstevel@tonic-gate /*
23eec118a1SMarcel Telka * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240dfe541eSEvan Layton */
250dfe541eSEvan Layton
260dfe541eSEvan Layton /*
270dfe541eSEvan Layton * Copyright 2018 Nexenta Systems, Inc.
280dfe541eSEvan Layton * Copyright 2019 Nexenta by DDN, Inc.
29*f44e1126SVitaliy Gusev * Copyright 2020 RackTop Systems, Inc.
30967a528aSDan McDonald * Copyright 2023 MNX Cloud, Inc.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include <sys/systm.h>
347c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
367c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
377c478bd9Sstevel@tonic-gate #include <sys/clconf.h>
387c478bd9Sstevel@tonic-gate #include <sys/cladm.h>
397c478bd9Sstevel@tonic-gate #include <sys/flock.h>
407c478bd9Sstevel@tonic-gate #include <nfs/export.h>
417c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
427c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h>
437c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h>
447c478bd9Sstevel@tonic-gate #include <nfs/lm.h>
457c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
46ed57cab9Srg #include <sys/sdt.h>
47cee86682Scalum #include <sys/nvpair.h>
487c478bd9Sstevel@tonic-gate
49da6c28aaSamw extern u_longlong_t nfs4_srv_caller_id;
507c478bd9Sstevel@tonic-gate
511b300de9Sjwahlig extern uint_t nfs4_srv_vkey;
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate stateid4 special0 = {
547c478bd9Sstevel@tonic-gate 0,
557c478bd9Sstevel@tonic-gate { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate stateid4 special1 = {
597c478bd9Sstevel@tonic-gate 0xffffffff,
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate (char)0xff, (char)0xff, (char)0xff, (char)0xff,
627c478bd9Sstevel@tonic-gate (char)0xff, (char)0xff, (char)0xff, (char)0xff,
637c478bd9Sstevel@tonic-gate (char)0xff, (char)0xff, (char)0xff, (char)0xff
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate };
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #define ISSPECIAL(id) (stateid4_cmp(id, &special0) || \
697c478bd9Sstevel@tonic-gate stateid4_cmp(id, &special1))
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate /* For embedding the cluster nodeid into our clientid */
727c478bd9Sstevel@tonic-gate #define CLUSTER_NODEID_SHIFT 24
737c478bd9Sstevel@tonic-gate #define CLUSTER_MAX_NODEID 255
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate #ifdef DEBUG
767c478bd9Sstevel@tonic-gate int rfs4_debug;
777c478bd9Sstevel@tonic-gate #endif
787c478bd9Sstevel@tonic-gate
79aab20b47SToomas Soome rfs4_db_mem_cache_t rfs4_db_mem_cache_table[RFS4_DB_MEM_CACHE_NUM];
807c478bd9Sstevel@tonic-gate static uint32_t rfs4_database_debug = 0x00;
817c478bd9Sstevel@tonic-gate
820dfe541eSEvan Layton /* CSTYLED */
830dfe541eSEvan Layton static void rfs4_ss_clid_write(nfs4_srv_t *nsrv4, rfs4_client_t *cp, char *leaf);
84cee86682Scalum static void rfs4_ss_clid_write_one(rfs4_client_t *cp, char *dir, char *leaf);
85cee86682Scalum static void rfs4_dss_clear_oldstate(rfs4_servinst_t *sip);
86cee86682Scalum static void rfs4_ss_chkclid_sip(rfs4_client_t *cp, rfs4_servinst_t *sip);
87cee86682Scalum
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate * Couple of simple init/destroy functions for a general waiter
907c478bd9Sstevel@tonic-gate */
917c478bd9Sstevel@tonic-gate void
rfs4_sw_init(rfs4_state_wait_t * swp)927c478bd9Sstevel@tonic-gate rfs4_sw_init(rfs4_state_wait_t *swp)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate mutex_init(swp->sw_cv_lock, NULL, MUTEX_DEFAULT, NULL);
957c478bd9Sstevel@tonic-gate cv_init(swp->sw_cv, NULL, CV_DEFAULT, NULL);
967c478bd9Sstevel@tonic-gate swp->sw_active = FALSE;
977c478bd9Sstevel@tonic-gate swp->sw_wait_count = 0;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate void
rfs4_sw_destroy(rfs4_state_wait_t * swp)1017c478bd9Sstevel@tonic-gate rfs4_sw_destroy(rfs4_state_wait_t *swp)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate mutex_destroy(swp->sw_cv_lock);
1047c478bd9Sstevel@tonic-gate cv_destroy(swp->sw_cv);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate void
rfs4_sw_enter(rfs4_state_wait_t * swp)1087c478bd9Sstevel@tonic-gate rfs4_sw_enter(rfs4_state_wait_t *swp)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate mutex_enter(swp->sw_cv_lock);
1117c478bd9Sstevel@tonic-gate while (swp->sw_active) {
1127c478bd9Sstevel@tonic-gate swp->sw_wait_count++;
1137c478bd9Sstevel@tonic-gate cv_wait(swp->sw_cv, swp->sw_cv_lock);
1147c478bd9Sstevel@tonic-gate swp->sw_wait_count--;
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate ASSERT(swp->sw_active == FALSE);
1177c478bd9Sstevel@tonic-gate swp->sw_active = TRUE;
1187c478bd9Sstevel@tonic-gate mutex_exit(swp->sw_cv_lock);
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate void
rfs4_sw_exit(rfs4_state_wait_t * swp)1227c478bd9Sstevel@tonic-gate rfs4_sw_exit(rfs4_state_wait_t *swp)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate mutex_enter(swp->sw_cv_lock);
1257c478bd9Sstevel@tonic-gate ASSERT(swp->sw_active == TRUE);
1267c478bd9Sstevel@tonic-gate swp->sw_active = FALSE;
1277c478bd9Sstevel@tonic-gate if (swp->sw_wait_count != 0)
1287c478bd9Sstevel@tonic-gate cv_broadcast(swp->sw_cv);
1297c478bd9Sstevel@tonic-gate mutex_exit(swp->sw_cv_lock);
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate static void
deep_lock_copy(LOCK4res * dres,LOCK4res * sres)1337c478bd9Sstevel@tonic-gate deep_lock_copy(LOCK4res *dres, LOCK4res *sres)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate lock_owner4 *slo = &sres->LOCK4res_u.denied.owner;
1367c478bd9Sstevel@tonic-gate lock_owner4 *dlo = &dres->LOCK4res_u.denied.owner;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (sres->status == NFS4ERR_DENIED) {
1397c478bd9Sstevel@tonic-gate dlo->owner_val = kmem_alloc(slo->owner_len, KM_SLEEP);
1407c478bd9Sstevel@tonic-gate bcopy(slo->owner_val, dlo->owner_val, slo->owner_len);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1440dfe541eSEvan Layton /*
1450dfe541eSEvan Layton * CPR callback id -- not related to v4 callbacks
1460dfe541eSEvan Layton */
1470dfe541eSEvan Layton static callb_id_t cpr_id = 0;
1480dfe541eSEvan Layton
1497c478bd9Sstevel@tonic-gate static void
deep_lock_free(LOCK4res * res)1507c478bd9Sstevel@tonic-gate deep_lock_free(LOCK4res *res)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate lock_owner4 *lo = &res->LOCK4res_u.denied.owner;
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate if (res->status == NFS4ERR_DENIED)
1557c478bd9Sstevel@tonic-gate kmem_free(lo->owner_val, lo->owner_len);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate static void
deep_open_copy(OPEN4res * dres,OPEN4res * sres)1597c478bd9Sstevel@tonic-gate deep_open_copy(OPEN4res *dres, OPEN4res *sres)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate nfsace4 *sacep, *dacep;
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (sres->status != NFS4_OK) {
1647c478bd9Sstevel@tonic-gate return;
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate dres->attrset = sres->attrset;
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate switch (sres->delegation.delegation_type) {
1707c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_NONE:
1717c478bd9Sstevel@tonic-gate return;
1727c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_READ:
1737c478bd9Sstevel@tonic-gate sacep = &sres->delegation.open_delegation4_u.read.permissions;
1747c478bd9Sstevel@tonic-gate dacep = &dres->delegation.open_delegation4_u.read.permissions;
1757c478bd9Sstevel@tonic-gate break;
1767c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_WRITE:
1777c478bd9Sstevel@tonic-gate sacep = &sres->delegation.open_delegation4_u.write.permissions;
1787c478bd9Sstevel@tonic-gate dacep = &dres->delegation.open_delegation4_u.write.permissions;
1797c478bd9Sstevel@tonic-gate break;
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate dacep->who.utf8string_val =
182ed57cab9Srg kmem_alloc(sacep->who.utf8string_len, KM_SLEEP);
1837c478bd9Sstevel@tonic-gate bcopy(sacep->who.utf8string_val, dacep->who.utf8string_val,
1847c478bd9Sstevel@tonic-gate sacep->who.utf8string_len);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate static void
deep_open_free(OPEN4res * res)1887c478bd9Sstevel@tonic-gate deep_open_free(OPEN4res *res)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate nfsace4 *acep;
1917c478bd9Sstevel@tonic-gate if (res->status != NFS4_OK)
1927c478bd9Sstevel@tonic-gate return;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate switch (res->delegation.delegation_type) {
1957c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_NONE:
1967c478bd9Sstevel@tonic-gate return;
1977c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_READ:
1987c478bd9Sstevel@tonic-gate acep = &res->delegation.open_delegation4_u.read.permissions;
1997c478bd9Sstevel@tonic-gate break;
2007c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_WRITE:
2017c478bd9Sstevel@tonic-gate acep = &res->delegation.open_delegation4_u.write.permissions;
2027c478bd9Sstevel@tonic-gate break;
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate if (acep->who.utf8string_val) {
2067c478bd9Sstevel@tonic-gate kmem_free(acep->who.utf8string_val, acep->who.utf8string_len);
2077c478bd9Sstevel@tonic-gate acep->who.utf8string_val = NULL;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate void
rfs4_free_reply(nfs_resop4 * rp)2127c478bd9Sstevel@tonic-gate rfs4_free_reply(nfs_resop4 *rp)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate switch (rp->resop) {
2157c478bd9Sstevel@tonic-gate case OP_LOCK:
2167c478bd9Sstevel@tonic-gate deep_lock_free(&rp->nfs_resop4_u.oplock);
2177c478bd9Sstevel@tonic-gate break;
2187c478bd9Sstevel@tonic-gate case OP_OPEN:
2197c478bd9Sstevel@tonic-gate deep_open_free(&rp->nfs_resop4_u.opopen);
2207c478bd9Sstevel@tonic-gate default:
2217c478bd9Sstevel@tonic-gate break;
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate void
rfs4_copy_reply(nfs_resop4 * dst,nfs_resop4 * src)2267c478bd9Sstevel@tonic-gate rfs4_copy_reply(nfs_resop4 *dst, nfs_resop4 *src)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate *dst = *src;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate /* Handle responses that need deep copy */
2317c478bd9Sstevel@tonic-gate switch (src->resop) {
2327c478bd9Sstevel@tonic-gate case OP_LOCK:
2337c478bd9Sstevel@tonic-gate deep_lock_copy(&dst->nfs_resop4_u.oplock,
234ed57cab9Srg &src->nfs_resop4_u.oplock);
2357c478bd9Sstevel@tonic-gate break;
2367c478bd9Sstevel@tonic-gate case OP_OPEN:
2377c478bd9Sstevel@tonic-gate deep_open_copy(&dst->nfs_resop4_u.opopen,
238ed57cab9Srg &src->nfs_resop4_u.opopen);
2397c478bd9Sstevel@tonic-gate break;
2407c478bd9Sstevel@tonic-gate default:
2417c478bd9Sstevel@tonic-gate break;
2427c478bd9Sstevel@tonic-gate };
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * This is the implementation of the underlying state engine. The
2477c478bd9Sstevel@tonic-gate * public interface to this engine is described by
2487c478bd9Sstevel@tonic-gate * nfs4_state.h. Callers to the engine should hold no state engine
2497c478bd9Sstevel@tonic-gate * locks when they call in to it. If the protocol needs to lock data
2507c478bd9Sstevel@tonic-gate * structures it should do so after acquiring all references to them
2517c478bd9Sstevel@tonic-gate * first and then follow the following lock order:
2527c478bd9Sstevel@tonic-gate *
2537c478bd9Sstevel@tonic-gate * client > openowner > state > lo_state > lockowner > file.
2547c478bd9Sstevel@tonic-gate *
2557c478bd9Sstevel@tonic-gate * Internally we only allow a thread to hold one hash bucket lock at a
2567c478bd9Sstevel@tonic-gate * time and the lock is higher in the lock order (must be acquired
2577c478bd9Sstevel@tonic-gate * first) than the data structure that is on that hash list.
2587c478bd9Sstevel@tonic-gate *
2597c478bd9Sstevel@tonic-gate * If a new reference was acquired by the caller, that reference needs
2607c478bd9Sstevel@tonic-gate * to be released after releasing all acquired locks with the
2617c478bd9Sstevel@tonic-gate * corresponding rfs4_*_rele routine.
2627c478bd9Sstevel@tonic-gate */
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate /*
2657c478bd9Sstevel@tonic-gate * This code is some what prototypical for now. Its purpose currently is to
2667c478bd9Sstevel@tonic-gate * implement the interfaces sufficiently to finish the higher protocol
2677c478bd9Sstevel@tonic-gate * elements. This will be replaced by a dynamically resizeable tables
2687c478bd9Sstevel@tonic-gate * backed by kmem_cache allocator. However synchronization is handled
2697c478bd9Sstevel@tonic-gate * correctly (I hope) and will not change by much. The mutexes for
2707c478bd9Sstevel@tonic-gate * the hash buckets that can be used to create new instances of data
2717c478bd9Sstevel@tonic-gate * structures might be good candidates to evolve into reader writer
2727c478bd9Sstevel@tonic-gate * locks. If it has to do a creation, it would be holding the
2737c478bd9Sstevel@tonic-gate * mutex across a kmem_alloc with KM_SLEEP specified.
2747c478bd9Sstevel@tonic-gate */
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate #ifdef DEBUG
2777c478bd9Sstevel@tonic-gate #define TABSIZE 17
2787c478bd9Sstevel@tonic-gate #else
2797c478bd9Sstevel@tonic-gate #define TABSIZE 2047
2807c478bd9Sstevel@tonic-gate #endif
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate #define ADDRHASH(key) ((unsigned long)(key) >> 3)
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate #define MAXTABSZ 1024*1024
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /* The values below are rfs4_lease_time units */
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate #ifdef DEBUG
2897c478bd9Sstevel@tonic-gate #define CLIENT_CACHE_TIME 1
2907c478bd9Sstevel@tonic-gate #define OPENOWNER_CACHE_TIME 1
2917c478bd9Sstevel@tonic-gate #define STATE_CACHE_TIME 1
2927c478bd9Sstevel@tonic-gate #define LO_STATE_CACHE_TIME 1
2937c478bd9Sstevel@tonic-gate #define LOCKOWNER_CACHE_TIME 1
2947c478bd9Sstevel@tonic-gate #define FILE_CACHE_TIME 3
2957c478bd9Sstevel@tonic-gate #define DELEG_STATE_CACHE_TIME 1
2967c478bd9Sstevel@tonic-gate #else
2977c478bd9Sstevel@tonic-gate #define CLIENT_CACHE_TIME 10
2987c478bd9Sstevel@tonic-gate #define OPENOWNER_CACHE_TIME 5
2997c478bd9Sstevel@tonic-gate #define STATE_CACHE_TIME 1
3007c478bd9Sstevel@tonic-gate #define LO_STATE_CACHE_TIME 1
3017c478bd9Sstevel@tonic-gate #define LOCKOWNER_CACHE_TIME 3
3027c478bd9Sstevel@tonic-gate #define FILE_CACHE_TIME 40
3037c478bd9Sstevel@tonic-gate #define DELEG_STATE_CACHE_TIME 1
3047c478bd9Sstevel@tonic-gate #endif
3057c478bd9Sstevel@tonic-gate
3060dfe541eSEvan Layton /*
3070dfe541eSEvan Layton * NFSv4 server state databases
3080dfe541eSEvan Layton *
3090dfe541eSEvan Layton * Initilized when the module is loaded and used by NFSv4 state tables.
3100dfe541eSEvan Layton * These kmem_cache databases are global, the tables that make use of these
3110dfe541eSEvan Layton * are per zone.
3120dfe541eSEvan Layton */
3130dfe541eSEvan Layton kmem_cache_t *rfs4_client_mem_cache;
3140dfe541eSEvan Layton kmem_cache_t *rfs4_clntIP_mem_cache;
3150dfe541eSEvan Layton kmem_cache_t *rfs4_openown_mem_cache;
3160dfe541eSEvan Layton kmem_cache_t *rfs4_openstID_mem_cache;
3170dfe541eSEvan Layton kmem_cache_t *rfs4_lockstID_mem_cache;
3180dfe541eSEvan Layton kmem_cache_t *rfs4_lockown_mem_cache;
3190dfe541eSEvan Layton kmem_cache_t *rfs4_file_mem_cache;
3200dfe541eSEvan Layton kmem_cache_t *rfs4_delegstID_mem_cache;
321*f44e1126SVitaliy Gusev kmem_cache_t *rfs4_session_mem_cache;
3227c478bd9Sstevel@tonic-gate
3230dfe541eSEvan Layton /*
3240dfe541eSEvan Layton * NFSv4 state table functions
3250dfe541eSEvan Layton */
3267c478bd9Sstevel@tonic-gate static bool_t rfs4_client_create(rfs4_entry_t, void *);
327cee86682Scalum static void rfs4_dss_remove_cpleaf(rfs4_client_t *);
328cee86682Scalum static void rfs4_dss_remove_leaf(rfs4_servinst_t *, char *, char *);
3297c478bd9Sstevel@tonic-gate static void rfs4_client_destroy(rfs4_entry_t);
3307c478bd9Sstevel@tonic-gate static bool_t rfs4_client_expiry(rfs4_entry_t);
3317c478bd9Sstevel@tonic-gate static uint32_t clientid_hash(void *);
3327c478bd9Sstevel@tonic-gate static bool_t clientid_compare(rfs4_entry_t, void *);
3337c478bd9Sstevel@tonic-gate static void *clientid_mkkey(rfs4_entry_t);
3347c478bd9Sstevel@tonic-gate static uint32_t nfsclnt_hash(void *);
3357c478bd9Sstevel@tonic-gate static bool_t nfsclnt_compare(rfs4_entry_t, void *);
3367c478bd9Sstevel@tonic-gate static void *nfsclnt_mkkey(rfs4_entry_t);
3372f172c55SRobert Thurlow static bool_t rfs4_clntip_expiry(rfs4_entry_t);
3382f172c55SRobert Thurlow static void rfs4_clntip_destroy(rfs4_entry_t);
3392f172c55SRobert Thurlow static bool_t rfs4_clntip_create(rfs4_entry_t, void *);
3402f172c55SRobert Thurlow static uint32_t clntip_hash(void *);
3412f172c55SRobert Thurlow static bool_t clntip_compare(rfs4_entry_t, void *);
3422f172c55SRobert Thurlow static void *clntip_mkkey(rfs4_entry_t);
3437c478bd9Sstevel@tonic-gate static bool_t rfs4_openowner_create(rfs4_entry_t, void *);
3447c478bd9Sstevel@tonic-gate static void rfs4_openowner_destroy(rfs4_entry_t);
3457c478bd9Sstevel@tonic-gate static bool_t rfs4_openowner_expiry(rfs4_entry_t);
3467c478bd9Sstevel@tonic-gate static uint32_t openowner_hash(void *);
3477c478bd9Sstevel@tonic-gate static bool_t openowner_compare(rfs4_entry_t, void *);
3487c478bd9Sstevel@tonic-gate static void *openowner_mkkey(rfs4_entry_t);
3497c478bd9Sstevel@tonic-gate static bool_t rfs4_state_create(rfs4_entry_t, void *);
3507c478bd9Sstevel@tonic-gate static void rfs4_state_destroy(rfs4_entry_t);
3517c478bd9Sstevel@tonic-gate static bool_t rfs4_state_expiry(rfs4_entry_t);
3527c478bd9Sstevel@tonic-gate static uint32_t state_hash(void *);
3537c478bd9Sstevel@tonic-gate static bool_t state_compare(rfs4_entry_t, void *);
3547c478bd9Sstevel@tonic-gate static void *state_mkkey(rfs4_entry_t);
3557c478bd9Sstevel@tonic-gate static uint32_t state_owner_file_hash(void *);
3567c478bd9Sstevel@tonic-gate static bool_t state_owner_file_compare(rfs4_entry_t, void *);
3577c478bd9Sstevel@tonic-gate static void *state_owner_file_mkkey(rfs4_entry_t);
3587c478bd9Sstevel@tonic-gate static uint32_t state_file_hash(void *);
3597c478bd9Sstevel@tonic-gate static bool_t state_file_compare(rfs4_entry_t, void *);
3607c478bd9Sstevel@tonic-gate static void *state_file_mkkey(rfs4_entry_t);
3617c478bd9Sstevel@tonic-gate static bool_t rfs4_lo_state_create(rfs4_entry_t, void *);
3627c478bd9Sstevel@tonic-gate static void rfs4_lo_state_destroy(rfs4_entry_t);
3637c478bd9Sstevel@tonic-gate static bool_t rfs4_lo_state_expiry(rfs4_entry_t);
3647c478bd9Sstevel@tonic-gate static uint32_t lo_state_hash(void *);
3657c478bd9Sstevel@tonic-gate static bool_t lo_state_compare(rfs4_entry_t, void *);
3667c478bd9Sstevel@tonic-gate static void *lo_state_mkkey(rfs4_entry_t);
3677c478bd9Sstevel@tonic-gate static uint32_t lo_state_lo_hash(void *);
3687c478bd9Sstevel@tonic-gate static bool_t lo_state_lo_compare(rfs4_entry_t, void *);
3697c478bd9Sstevel@tonic-gate static void *lo_state_lo_mkkey(rfs4_entry_t);
3707c478bd9Sstevel@tonic-gate static bool_t rfs4_lockowner_create(rfs4_entry_t, void *);
3717c478bd9Sstevel@tonic-gate static void rfs4_lockowner_destroy(rfs4_entry_t);
3727c478bd9Sstevel@tonic-gate static bool_t rfs4_lockowner_expiry(rfs4_entry_t);
3737c478bd9Sstevel@tonic-gate static uint32_t lockowner_hash(void *);
3747c478bd9Sstevel@tonic-gate static bool_t lockowner_compare(rfs4_entry_t, void *);
3757c478bd9Sstevel@tonic-gate static void *lockowner_mkkey(rfs4_entry_t);
3767c478bd9Sstevel@tonic-gate static uint32_t pid_hash(void *);
3777c478bd9Sstevel@tonic-gate static bool_t pid_compare(rfs4_entry_t, void *);
3787c478bd9Sstevel@tonic-gate static void *pid_mkkey(rfs4_entry_t);
3797c478bd9Sstevel@tonic-gate static bool_t rfs4_file_create(rfs4_entry_t, void *);
3807c478bd9Sstevel@tonic-gate static void rfs4_file_destroy(rfs4_entry_t);
3817c478bd9Sstevel@tonic-gate static uint32_t file_hash(void *);
3827c478bd9Sstevel@tonic-gate static bool_t file_compare(rfs4_entry_t, void *);
3837c478bd9Sstevel@tonic-gate static void *file_mkkey(rfs4_entry_t);
3847c478bd9Sstevel@tonic-gate static bool_t rfs4_deleg_state_create(rfs4_entry_t, void *);
3857c478bd9Sstevel@tonic-gate static void rfs4_deleg_state_destroy(rfs4_entry_t);
3867c478bd9Sstevel@tonic-gate static bool_t rfs4_deleg_state_expiry(rfs4_entry_t);
3877c478bd9Sstevel@tonic-gate static uint32_t deleg_hash(void *);
3887c478bd9Sstevel@tonic-gate static bool_t deleg_compare(rfs4_entry_t, void *);
3897c478bd9Sstevel@tonic-gate static void *deleg_mkkey(rfs4_entry_t);
3907c478bd9Sstevel@tonic-gate static uint32_t deleg_state_hash(void *);
3917c478bd9Sstevel@tonic-gate static bool_t deleg_state_compare(rfs4_entry_t, void *);
3927c478bd9Sstevel@tonic-gate static void *deleg_state_mkkey(rfs4_entry_t);
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate static void rfs4_state_rele_nounlock(rfs4_state_t *);
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate static int rfs4_ss_enabled = 0;
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate void
rfs4_ss_pnfree(rfs4_ss_pn_t * ss_pn)3997c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(rfs4_ss_pn_t *ss_pn)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate kmem_free(ss_pn, sizeof (rfs4_ss_pn_t));
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate static rfs4_ss_pn_t *
rfs4_ss_pnalloc(char * dir,char * leaf)4057c478bd9Sstevel@tonic-gate rfs4_ss_pnalloc(char *dir, char *leaf)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate rfs4_ss_pn_t *ss_pn;
4080dfe541eSEvan Layton int dir_len, leaf_len;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate * validate we have a resonable path
4127c478bd9Sstevel@tonic-gate * (account for the '/' and trailing null)
4137c478bd9Sstevel@tonic-gate */
4147c478bd9Sstevel@tonic-gate if ((dir_len = strlen(dir)) > MAXPATHLEN ||
415ed57cab9Srg (leaf_len = strlen(leaf)) > MAXNAMELEN ||
416ed57cab9Srg (dir_len + leaf_len + 2) > MAXPATHLEN) {
4177c478bd9Sstevel@tonic-gate return (NULL);
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate ss_pn = kmem_alloc(sizeof (rfs4_ss_pn_t), KM_SLEEP);
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate (void) snprintf(ss_pn->pn, MAXPATHLEN, "%s/%s", dir, leaf);
4237c478bd9Sstevel@tonic-gate /* Handy pointer to just the leaf name */
4247c478bd9Sstevel@tonic-gate ss_pn->leaf = ss_pn->pn + dir_len + 1;
4257c478bd9Sstevel@tonic-gate return (ss_pn);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate * Move the "leaf" filename from "sdir" directory
4317c478bd9Sstevel@tonic-gate * to the "ddir" directory. Return the pathname of
4327c478bd9Sstevel@tonic-gate * the destination unless the rename fails in which
4337c478bd9Sstevel@tonic-gate * case we need to return the source pathname.
4347c478bd9Sstevel@tonic-gate */
4357c478bd9Sstevel@tonic-gate static rfs4_ss_pn_t *
rfs4_ss_movestate(char * sdir,char * ddir,char * leaf)4367c478bd9Sstevel@tonic-gate rfs4_ss_movestate(char *sdir, char *ddir, char *leaf)
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate rfs4_ss_pn_t *src, *dst;
4397c478bd9Sstevel@tonic-gate
440cee86682Scalum if ((src = rfs4_ss_pnalloc(sdir, leaf)) == NULL)
4417c478bd9Sstevel@tonic-gate return (NULL);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate if ((dst = rfs4_ss_pnalloc(ddir, leaf)) == NULL) {
4447c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(src);
4457c478bd9Sstevel@tonic-gate return (NULL);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate * If the rename fails we shall return the src
4507c478bd9Sstevel@tonic-gate * pathname and free the dst. Otherwise we need
4517c478bd9Sstevel@tonic-gate * to free the src and return the dst pathanme.
4527c478bd9Sstevel@tonic-gate */
4537c478bd9Sstevel@tonic-gate if (vn_rename(src->pn, dst->pn, UIO_SYSSPACE)) {
4547c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(dst);
4557c478bd9Sstevel@tonic-gate return (src);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(src);
4587c478bd9Sstevel@tonic-gate return (dst);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate static rfs4_oldstate_t *
rfs4_ss_getstate(vnode_t * dvp,rfs4_ss_pn_t * ss_pn)4637c478bd9Sstevel@tonic-gate rfs4_ss_getstate(vnode_t *dvp, rfs4_ss_pn_t *ss_pn)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate struct uio uio;
4667c478bd9Sstevel@tonic-gate struct iovec iov[3];
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate rfs4_oldstate_t *cl_ss = NULL;
4697c478bd9Sstevel@tonic-gate vnode_t *vp;
4707c478bd9Sstevel@tonic-gate vattr_t va;
4717c478bd9Sstevel@tonic-gate uint_t id_len;
4727c478bd9Sstevel@tonic-gate int err, kill_file, file_vers;
4737c478bd9Sstevel@tonic-gate
474cee86682Scalum if (ss_pn == NULL)
4757c478bd9Sstevel@tonic-gate return (NULL);
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate /*
4787c478bd9Sstevel@tonic-gate * open the state file.
4797c478bd9Sstevel@tonic-gate */
4807c478bd9Sstevel@tonic-gate if (vn_open(ss_pn->pn, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0) != 0) {
4817c478bd9Sstevel@tonic-gate return (NULL);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
485da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
4867c478bd9Sstevel@tonic-gate VN_RELE(vp);
4877c478bd9Sstevel@tonic-gate return (NULL);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate
490da6c28aaSamw err = VOP_ACCESS(vp, VREAD, 0, CRED(), NULL);
4917c478bd9Sstevel@tonic-gate if (err) {
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate * We don't have read access? better get the heck out.
4947c478bd9Sstevel@tonic-gate */
495da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
4967c478bd9Sstevel@tonic-gate VN_RELE(vp);
4977c478bd9Sstevel@tonic-gate return (NULL);
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
5017c478bd9Sstevel@tonic-gate /*
5027c478bd9Sstevel@tonic-gate * get the file size to do some basic validation
5037c478bd9Sstevel@tonic-gate */
5047c478bd9Sstevel@tonic-gate va.va_mask = AT_SIZE;
505da6c28aaSamw err = VOP_GETATTR(vp, &va, 0, CRED(), NULL);
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate kill_file = (va.va_size == 0 || va.va_size <
508ed57cab9Srg (NFS4_VERIFIER_SIZE + sizeof (uint_t)+1));
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate if (err || kill_file) {
5117c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
512da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5137c478bd9Sstevel@tonic-gate VN_RELE(vp);
5147c478bd9Sstevel@tonic-gate if (kill_file) {
515da6c28aaSamw (void) VOP_REMOVE(dvp, ss_pn->leaf, CRED(), NULL, 0);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate return (NULL);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate cl_ss = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate /*
5237c478bd9Sstevel@tonic-gate * build iovecs to read in the file_version, verifier and id_len
5247c478bd9Sstevel@tonic-gate */
5257c478bd9Sstevel@tonic-gate iov[0].iov_base = (caddr_t)&file_vers;
5267c478bd9Sstevel@tonic-gate iov[0].iov_len = sizeof (int);
527cee86682Scalum iov[1].iov_base = (caddr_t)&cl_ss->cl_id4.verifier;
5287c478bd9Sstevel@tonic-gate iov[1].iov_len = NFS4_VERIFIER_SIZE;
5297c478bd9Sstevel@tonic-gate iov[2].iov_base = (caddr_t)&id_len;
5307c478bd9Sstevel@tonic-gate iov[2].iov_len = sizeof (uint_t);
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate uio.uio_iov = iov;
5337c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 3;
5347c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
5357c478bd9Sstevel@tonic-gate uio.uio_loffset = 0;
5367c478bd9Sstevel@tonic-gate uio.uio_resid = sizeof (int) + NFS4_VERIFIER_SIZE + sizeof (uint_t);
5377c478bd9Sstevel@tonic-gate
538bd3561fbSToomas Soome err = VOP_READ(vp, &uio, FREAD, CRED(), NULL);
539bd3561fbSToomas Soome if (err != 0) {
5407c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
541da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5427c478bd9Sstevel@tonic-gate VN_RELE(vp);
5437c478bd9Sstevel@tonic-gate kmem_free(cl_ss, sizeof (rfs4_oldstate_t));
5447c478bd9Sstevel@tonic-gate return (NULL);
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate /*
5487c478bd9Sstevel@tonic-gate * if the file_version doesn't match or if the
5497c478bd9Sstevel@tonic-gate * id_len is zero or the combination of the verifier,
5507c478bd9Sstevel@tonic-gate * id_len and id_val is bigger than the file we have
5517c478bd9Sstevel@tonic-gate * a problem. If so ditch the file.
5527c478bd9Sstevel@tonic-gate */
5537c478bd9Sstevel@tonic-gate kill_file = (file_vers != NFS4_SS_VERSION || id_len == 0 ||
5547c478bd9Sstevel@tonic-gate (id_len + NFS4_VERIFIER_SIZE + sizeof (uint_t)) > va.va_size);
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate if (err || kill_file) {
5577c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
558da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5597c478bd9Sstevel@tonic-gate VN_RELE(vp);
5607c478bd9Sstevel@tonic-gate kmem_free(cl_ss, sizeof (rfs4_oldstate_t));
5617c478bd9Sstevel@tonic-gate if (kill_file) {
562da6c28aaSamw (void) VOP_REMOVE(dvp, ss_pn->leaf, CRED(), NULL, 0);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate return (NULL);
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate /*
5687c478bd9Sstevel@tonic-gate * now get the client id value
5697c478bd9Sstevel@tonic-gate */
5707c478bd9Sstevel@tonic-gate cl_ss->cl_id4.id_val = kmem_alloc(id_len, KM_SLEEP);
5717c478bd9Sstevel@tonic-gate iov[0].iov_base = cl_ss->cl_id4.id_val;
5727c478bd9Sstevel@tonic-gate iov[0].iov_len = id_len;
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate uio.uio_iov = iov;
5757c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
5767c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
5777c478bd9Sstevel@tonic-gate uio.uio_resid = cl_ss->cl_id4.id_len = id_len;
5787c478bd9Sstevel@tonic-gate
579bd3561fbSToomas Soome err = VOP_READ(vp, &uio, FREAD, CRED(), NULL);
580bd3561fbSToomas Soome if (err != 0) {
5817c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
582da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5837c478bd9Sstevel@tonic-gate VN_RELE(vp);
5847c478bd9Sstevel@tonic-gate kmem_free(cl_ss->cl_id4.id_val, id_len);
5857c478bd9Sstevel@tonic-gate kmem_free(cl_ss, sizeof (rfs4_oldstate_t));
5867c478bd9Sstevel@tonic-gate return (NULL);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
590da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5917c478bd9Sstevel@tonic-gate VN_RELE(vp);
5927c478bd9Sstevel@tonic-gate return (cl_ss);
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate #ifdef nextdp
5967c478bd9Sstevel@tonic-gate #undef nextdp
5977c478bd9Sstevel@tonic-gate #endif
5987c478bd9Sstevel@tonic-gate #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
5997c478bd9Sstevel@tonic-gate
600*f44e1126SVitaliy Gusev /*
601*f44e1126SVitaliy Gusev * Check whether list already contains the client
602*f44e1126SVitaliy Gusev * This protects against counting the same client twice.
603*f44e1126SVitaliy Gusev */
604*f44e1126SVitaliy Gusev static bool_t
rfs4_ss_has_client(rfs4_oldstate_t * head,nfs_client_id4 * client)605*f44e1126SVitaliy Gusev rfs4_ss_has_client(rfs4_oldstate_t *head, nfs_client_id4 *client)
606*f44e1126SVitaliy Gusev {
607*f44e1126SVitaliy Gusev rfs4_oldstate_t *p;
608*f44e1126SVitaliy Gusev
609*f44e1126SVitaliy Gusev for (p = head->next; p != head; p = p->next) {
610*f44e1126SVitaliy Gusev nfs_client_id4 *m = &p->cl_id4;
611*f44e1126SVitaliy Gusev
612*f44e1126SVitaliy Gusev if (m->id_len != client->id_len)
613*f44e1126SVitaliy Gusev continue;
614*f44e1126SVitaliy Gusev
615*f44e1126SVitaliy Gusev if (bcmp(m->id_val, client->id_val, client->id_len) == 0)
616*f44e1126SVitaliy Gusev continue;
617*f44e1126SVitaliy Gusev
618*f44e1126SVitaliy Gusev /* client ids match */
619*f44e1126SVitaliy Gusev return (TRUE);
620*f44e1126SVitaliy Gusev }
621*f44e1126SVitaliy Gusev
622*f44e1126SVitaliy Gusev return (FALSE);
623*f44e1126SVitaliy Gusev }
624*f44e1126SVitaliy Gusev
6257c478bd9Sstevel@tonic-gate /*
626cee86682Scalum * Add entries from statedir to supplied oldstate list.
627cee86682Scalum * Optionally, move all entries from statedir -> destdir.
6287c478bd9Sstevel@tonic-gate */
629*f44e1126SVitaliy Gusev static void
rfs4_ss_oldstate(rfs4_oldstate_t * oldstate,char * statedir,char * destdir)630cee86682Scalum rfs4_ss_oldstate(rfs4_oldstate_t *oldstate, char *statedir, char *destdir)
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate rfs4_ss_pn_t *ss_pn;
6337c478bd9Sstevel@tonic-gate rfs4_oldstate_t *cl_ss = NULL;
6347c478bd9Sstevel@tonic-gate char *dirt = NULL;
6357c478bd9Sstevel@tonic-gate int err, dir_eof = 0, size = 0;
6367c478bd9Sstevel@tonic-gate vnode_t *dvp;
6377c478bd9Sstevel@tonic-gate struct iovec iov;
6387c478bd9Sstevel@tonic-gate struct uio uio;
6397c478bd9Sstevel@tonic-gate struct dirent64 *dep;
6407c478bd9Sstevel@tonic-gate offset_t dirchunk_offset = 0;
641*f44e1126SVitaliy Gusev unsigned int nclients = 0;
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate * open the state directory
6457c478bd9Sstevel@tonic-gate */
646cee86682Scalum if (vn_open(statedir, UIO_SYSSPACE, FREAD, 0, &dvp, 0, 0))
6477c478bd9Sstevel@tonic-gate return;
6487c478bd9Sstevel@tonic-gate
649da6c28aaSamw if (dvp->v_type != VDIR || VOP_ACCESS(dvp, VREAD, 0, CRED(), NULL))
6507c478bd9Sstevel@tonic-gate goto out;
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate dirt = kmem_alloc(RFS4_SS_DIRSIZE, KM_SLEEP);
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate /*
6557c478bd9Sstevel@tonic-gate * Get and process the directory entries
6567c478bd9Sstevel@tonic-gate */
6577c478bd9Sstevel@tonic-gate while (!dir_eof) {
6587c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(dvp, V_WRITELOCK_FALSE, NULL);
6597c478bd9Sstevel@tonic-gate iov.iov_base = dirt;
6607c478bd9Sstevel@tonic-gate iov.iov_len = RFS4_SS_DIRSIZE;
6617c478bd9Sstevel@tonic-gate uio.uio_iov = &iov;
6627c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
6637c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
6647c478bd9Sstevel@tonic-gate uio.uio_loffset = dirchunk_offset;
6657c478bd9Sstevel@tonic-gate uio.uio_resid = RFS4_SS_DIRSIZE;
6667c478bd9Sstevel@tonic-gate
667da6c28aaSamw err = VOP_READDIR(dvp, &uio, CRED(), &dir_eof, NULL, 0);
6687c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(dvp, V_WRITELOCK_FALSE, NULL);
669cee86682Scalum if (err)
6707c478bd9Sstevel@tonic-gate goto out;
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate size = RFS4_SS_DIRSIZE - uio.uio_resid;
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate /*
6757c478bd9Sstevel@tonic-gate * Process all the directory entries in this
6767c478bd9Sstevel@tonic-gate * readdir chunk
6777c478bd9Sstevel@tonic-gate */
6787c478bd9Sstevel@tonic-gate for (dep = (struct dirent64 *)dirt; size > 0;
679ed57cab9Srg dep = nextdp(dep)) {
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate size -= dep->d_reclen;
6827c478bd9Sstevel@tonic-gate dirchunk_offset = dep->d_off;
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate * Skip '.' and '..'
6867c478bd9Sstevel@tonic-gate */
687cee86682Scalum if (NFS_IS_DOTNAME(dep->d_name))
6887c478bd9Sstevel@tonic-gate continue;
6897c478bd9Sstevel@tonic-gate
690cee86682Scalum ss_pn = rfs4_ss_pnalloc(statedir, dep->d_name);
691cee86682Scalum if (ss_pn == NULL)
6927c478bd9Sstevel@tonic-gate continue;
6937c478bd9Sstevel@tonic-gate
694bd3561fbSToomas Soome cl_ss = rfs4_ss_getstate(dvp, ss_pn);
695bd3561fbSToomas Soome if (cl_ss != NULL) {
696cee86682Scalum if (destdir != NULL) {
6977c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(ss_pn);
6987c478bd9Sstevel@tonic-gate cl_ss->ss_pn = rfs4_ss_movestate(
699ed57cab9Srg statedir, destdir, dep->d_name);
7007c478bd9Sstevel@tonic-gate } else {
7017c478bd9Sstevel@tonic-gate cl_ss->ss_pn = ss_pn;
7027c478bd9Sstevel@tonic-gate }
703*f44e1126SVitaliy Gusev
704*f44e1126SVitaliy Gusev if (!rfs4_ss_has_client(oldstate,
705*f44e1126SVitaliy Gusev &cl_ss->cl_id4))
706*f44e1126SVitaliy Gusev nclients++;
707*f44e1126SVitaliy Gusev
708cee86682Scalum insque(cl_ss, oldstate);
7097c478bd9Sstevel@tonic-gate } else {
7107c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(ss_pn);
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate
715cee86682Scalum out:
716da6c28aaSamw (void) VOP_CLOSE(dvp, FREAD, 1, (offset_t)0, CRED(), NULL);
7177c478bd9Sstevel@tonic-gate VN_RELE(dvp);
7187c478bd9Sstevel@tonic-gate if (dirt)
7197c478bd9Sstevel@tonic-gate kmem_free((caddr_t)dirt, RFS4_SS_DIRSIZE);
720*f44e1126SVitaliy Gusev
721*f44e1126SVitaliy Gusev if (nclients > 0) {
722*f44e1126SVitaliy Gusev nfs4_srv_t *nsrv4 = nfs4_get_srv();
723*f44e1126SVitaliy Gusev
724*f44e1126SVitaliy Gusev atomic_add_32(&(nsrv4->nfs4_cur_servinst->nreclaim), nclients);
725*f44e1126SVitaliy Gusev }
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate
728cee86682Scalum static void
rfs4_ss_init(nfs4_srv_t * nsrv4)7290dfe541eSEvan Layton rfs4_ss_init(nfs4_srv_t *nsrv4)
7307c478bd9Sstevel@tonic-gate {
731cee86682Scalum int npaths = 1;
732cee86682Scalum char *default_dss_path = NFS4_DSS_VAR_DIR;
7337c478bd9Sstevel@tonic-gate
734cee86682Scalum /* read the default stable storage state */
7350dfe541eSEvan Layton rfs4_dss_readstate(nsrv4, npaths, &default_dss_path);
736cee86682Scalum
737cee86682Scalum rfs4_ss_enabled = 1;
738cee86682Scalum }
739cee86682Scalum
740cee86682Scalum static void
rfs4_ss_fini(nfs4_srv_t * nsrv4)7410dfe541eSEvan Layton rfs4_ss_fini(nfs4_srv_t *nsrv4)
742cee86682Scalum {
743cee86682Scalum rfs4_servinst_t *sip;
744cee86682Scalum
7450dfe541eSEvan Layton mutex_enter(&nsrv4->servinst_lock);
7460dfe541eSEvan Layton sip = nsrv4->nfs4_cur_servinst;
747cee86682Scalum while (sip != NULL) {
748cee86682Scalum rfs4_dss_clear_oldstate(sip);
749cee86682Scalum sip = sip->next;
7507c478bd9Sstevel@tonic-gate }
7510dfe541eSEvan Layton mutex_exit(&nsrv4->servinst_lock);
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /*
755cee86682Scalum * Remove all oldstate files referenced by this servinst.
7567c478bd9Sstevel@tonic-gate */
7577c478bd9Sstevel@tonic-gate static void
rfs4_dss_clear_oldstate(rfs4_servinst_t * sip)758cee86682Scalum rfs4_dss_clear_oldstate(rfs4_servinst_t *sip)
7597c478bd9Sstevel@tonic-gate {
760cee86682Scalum rfs4_oldstate_t *os_head, *osp;
761cee86682Scalum
762cee86682Scalum rw_enter(&sip->oldstate_lock, RW_WRITER);
763cee86682Scalum os_head = sip->oldstate;
7647c478bd9Sstevel@tonic-gate
765eec118a1SMarcel Telka if (os_head == NULL) {
766eec118a1SMarcel Telka rw_exit(&sip->oldstate_lock);
7677c478bd9Sstevel@tonic-gate return;
768eec118a1SMarcel Telka }
7697c478bd9Sstevel@tonic-gate
770cee86682Scalum /* skip dummy entry */
771cee86682Scalum osp = os_head->next;
772cee86682Scalum while (osp != os_head) {
773cee86682Scalum char *leaf = osp->ss_pn->leaf;
774cee86682Scalum rfs4_oldstate_t *os_next;
7757c478bd9Sstevel@tonic-gate
776cee86682Scalum rfs4_dss_remove_leaf(sip, NFS4_DSS_OLDSTATE_LEAF, leaf);
7777c478bd9Sstevel@tonic-gate
778cee86682Scalum if (osp->cl_id4.id_val)
779cee86682Scalum kmem_free(osp->cl_id4.id_val, osp->cl_id4.id_len);
780eec118a1SMarcel Telka rfs4_ss_pnfree(osp->ss_pn);
7817c478bd9Sstevel@tonic-gate
782cee86682Scalum os_next = osp->next;
783cee86682Scalum remque(osp);
784cee86682Scalum kmem_free(osp, sizeof (rfs4_oldstate_t));
785cee86682Scalum osp = os_next;
786cee86682Scalum }
787cee86682Scalum
788cee86682Scalum rw_exit(&sip->oldstate_lock);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate
791cee86682Scalum /*
792cee86682Scalum * Form the state and oldstate paths, and read in the stable storage files.
793cee86682Scalum */
794cee86682Scalum void
rfs4_dss_readstate(nfs4_srv_t * nsrv4,int npaths,char ** paths)7950dfe541eSEvan Layton rfs4_dss_readstate(nfs4_srv_t *nsrv4, int npaths, char **paths)
7967c478bd9Sstevel@tonic-gate {
797cee86682Scalum int i;
798cee86682Scalum char *state, *oldstate;
7997c478bd9Sstevel@tonic-gate
800cee86682Scalum state = kmem_alloc(MAXPATHLEN, KM_SLEEP);
801cee86682Scalum oldstate = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8027c478bd9Sstevel@tonic-gate
803cee86682Scalum for (i = 0; i < npaths; i++) {
804cee86682Scalum char *path = paths[i];
8057c478bd9Sstevel@tonic-gate
806cee86682Scalum (void) sprintf(state, "%s/%s", path, NFS4_DSS_STATE_LEAF);
807cee86682Scalum (void) sprintf(oldstate, "%s/%s", path, NFS4_DSS_OLDSTATE_LEAF);
8087c478bd9Sstevel@tonic-gate
809cee86682Scalum /*
810cee86682Scalum * Populate the current server instance's oldstate list.
811cee86682Scalum *
812cee86682Scalum * 1. Read stable storage data from old state directory,
813cee86682Scalum * leaving its contents alone.
814cee86682Scalum *
815cee86682Scalum * 2. Read stable storage data from state directory,
816cee86682Scalum * and move the latter's contents to old state
817cee86682Scalum * directory.
818cee86682Scalum */
819*f44e1126SVitaliy Gusev rfs4_ss_oldstate(nsrv4->nfs4_cur_servinst->oldstate,
820*f44e1126SVitaliy Gusev oldstate, NULL);
821*f44e1126SVitaliy Gusev rfs4_ss_oldstate(nsrv4->nfs4_cur_servinst->oldstate,
822*f44e1126SVitaliy Gusev state, oldstate);
8237c478bd9Sstevel@tonic-gate }
824cee86682Scalum
825cee86682Scalum kmem_free(state, MAXPATHLEN);
826cee86682Scalum kmem_free(oldstate, MAXPATHLEN);
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate /*
8317c478bd9Sstevel@tonic-gate * Check if we are still in grace and if the client can be
8327c478bd9Sstevel@tonic-gate * granted permission to perform reclaims.
8337c478bd9Sstevel@tonic-gate */
8347c478bd9Sstevel@tonic-gate void
rfs4_ss_chkclid(nfs4_srv_t * nsrv4,rfs4_client_t * cp)8350dfe541eSEvan Layton rfs4_ss_chkclid(nfs4_srv_t *nsrv4, rfs4_client_t *cp)
8367c478bd9Sstevel@tonic-gate {
837cee86682Scalum rfs4_servinst_t *sip;
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate /*
840cee86682Scalum * It should be sufficient to check the oldstate data for just
841cee86682Scalum * this client's instance. However, since our per-instance
842cee86682Scalum * client grouping is solely temporal, HA-NFSv4 RG failover
843cee86682Scalum * might result in clients of the same RG being partitioned into
844cee86682Scalum * separate instances.
845cee86682Scalum *
846cee86682Scalum * Until the client grouping is improved, we must check the
847cee86682Scalum * oldstate data for all instances with an active grace period.
848cee86682Scalum *
849cee86682Scalum * This also serves as the mechanism to remove stale oldstate data.
850cee86682Scalum * The first time we check an instance after its grace period has
851cee86682Scalum * expired, the oldstate data should be cleared.
852cee86682Scalum *
853cee86682Scalum * Start at the current instance, and walk the list backwards
854cee86682Scalum * to the first.
8557c478bd9Sstevel@tonic-gate */
8560dfe541eSEvan Layton mutex_enter(&nsrv4->servinst_lock);
8570dfe541eSEvan Layton for (sip = nsrv4->nfs4_cur_servinst; sip != NULL; sip = sip->prev) {
858cee86682Scalum rfs4_ss_chkclid_sip(cp, sip);
8597c478bd9Sstevel@tonic-gate
860cee86682Scalum /* if the above check found this client, we're done */
861d216dff5SRobert Mastors if (cp->rc_can_reclaim)
862cee86682Scalum break;
863cee86682Scalum }
8640dfe541eSEvan Layton mutex_exit(&nsrv4->servinst_lock);
865cee86682Scalum }
8667c478bd9Sstevel@tonic-gate
867cee86682Scalum static void
rfs4_ss_chkclid_sip(rfs4_client_t * cp,rfs4_servinst_t * sip)868cee86682Scalum rfs4_ss_chkclid_sip(rfs4_client_t *cp, rfs4_servinst_t *sip)
869cee86682Scalum {
870cee86682Scalum rfs4_oldstate_t *osp, *os_head;
8717c478bd9Sstevel@tonic-gate
872cee86682Scalum /* short circuit everything if this server instance has no oldstate */
873cee86682Scalum rw_enter(&sip->oldstate_lock, RW_READER);
874cee86682Scalum os_head = sip->oldstate;
875cee86682Scalum rw_exit(&sip->oldstate_lock);
876cee86682Scalum if (os_head == NULL)
8777c478bd9Sstevel@tonic-gate return;
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate /*
880cee86682Scalum * If this server instance is no longer in a grace period then
881cee86682Scalum * the client won't be able to reclaim. No further need for this
882cee86682Scalum * instance's oldstate data, so it can be cleared.
8837c478bd9Sstevel@tonic-gate */
884cee86682Scalum if (!rfs4_servinst_in_grace(sip))
885cee86682Scalum return;
8867c478bd9Sstevel@tonic-gate
887cee86682Scalum /* this instance is still in grace; search for the clientid */
8887c478bd9Sstevel@tonic-gate
889cee86682Scalum rw_enter(&sip->oldstate_lock, RW_READER);
890cee86682Scalum
891cee86682Scalum os_head = sip->oldstate;
892cee86682Scalum /* skip dummy entry */
893cee86682Scalum osp = os_head->next;
8947c478bd9Sstevel@tonic-gate while (osp != os_head) {
895d216dff5SRobert Mastors if (osp->cl_id4.id_len == cp->rc_nfs_client.id_len) {
896d216dff5SRobert Mastors if (bcmp(osp->cl_id4.id_val, cp->rc_nfs_client.id_val,
897ed57cab9Srg osp->cl_id4.id_len) == 0) {
898d216dff5SRobert Mastors cp->rc_can_reclaim = 1;
8997c478bd9Sstevel@tonic-gate break;
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate osp = osp->next;
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate
905cee86682Scalum rw_exit(&sip->oldstate_lock);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate
9087c478bd9Sstevel@tonic-gate /*
909cee86682Scalum * Place client information into stable storage: 1/3.
910cee86682Scalum * First, generate the leaf filename, from the client's IP address and
911cee86682Scalum * the server-generated short-hand clientid.
9127c478bd9Sstevel@tonic-gate */
9137c478bd9Sstevel@tonic-gate void
rfs4_ss_clid(nfs4_srv_t * nsrv4,rfs4_client_t * cp)9140dfe541eSEvan Layton rfs4_ss_clid(nfs4_srv_t *nsrv4, rfs4_client_t *cp)
9157c478bd9Sstevel@tonic-gate {
9167c478bd9Sstevel@tonic-gate const char *kinet_ntop6(uchar_t *, char *, size_t);
9177c478bd9Sstevel@tonic-gate char leaf[MAXNAMELEN], buf[INET6_ADDRSTRLEN];
9187c478bd9Sstevel@tonic-gate struct sockaddr *ca;
9197c478bd9Sstevel@tonic-gate uchar_t *b;
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate if (rfs4_ss_enabled == 0) {
9227c478bd9Sstevel@tonic-gate return;
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate buf[0] = 0;
9267c478bd9Sstevel@tonic-gate
9272f172c55SRobert Thurlow ca = (struct sockaddr *)&cp->rc_addr;
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate /*
9307c478bd9Sstevel@tonic-gate * Convert the caller's IP address to a dotted string
9317c478bd9Sstevel@tonic-gate */
9327c478bd9Sstevel@tonic-gate if (ca->sa_family == AF_INET) {
9337c478bd9Sstevel@tonic-gate b = (uchar_t *)&((struct sockaddr_in *)ca)->sin_addr;
9347c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%03d.%03d.%03d.%03d", b[0] & 0xFF,
935ed57cab9Srg b[1] & 0xFF, b[2] & 0xFF, b[3] & 0xFF);
9367c478bd9Sstevel@tonic-gate } else if (ca->sa_family == AF_INET6) {
9377c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6;
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)ca;
9407c478bd9Sstevel@tonic-gate (void) kinet_ntop6((uchar_t *)&sin6->sin6_addr,
941ed57cab9Srg buf, INET6_ADDRSTRLEN);
9427c478bd9Sstevel@tonic-gate }
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate (void) snprintf(leaf, MAXNAMELEN, "%s-%llx", buf,
945d216dff5SRobert Mastors (longlong_t)cp->rc_clientid);
9460dfe541eSEvan Layton rfs4_ss_clid_write(nsrv4, cp, leaf);
947cee86682Scalum }
9487c478bd9Sstevel@tonic-gate
949cee86682Scalum /*
950cee86682Scalum * Place client information into stable storage: 2/3.
951cee86682Scalum * DSS: distributed stable storage: the file may need to be written to
952cee86682Scalum * multiple directories.
953cee86682Scalum */
954cee86682Scalum static void
rfs4_ss_clid_write(nfs4_srv_t * nsrv4,rfs4_client_t * cp,char * leaf)9550dfe541eSEvan Layton rfs4_ss_clid_write(nfs4_srv_t *nsrv4, rfs4_client_t *cp, char *leaf)
956cee86682Scalum {
957cee86682Scalum rfs4_servinst_t *sip;
958cee86682Scalum
959cee86682Scalum /*
960cee86682Scalum * It should be sufficient to write the leaf file to (all) DSS paths
961cee86682Scalum * associated with just this client's instance. However, since our
962cee86682Scalum * per-instance client grouping is solely temporal, HA-NFSv4 RG
963cee86682Scalum * failover might result in us losing DSS data.
964cee86682Scalum *
965cee86682Scalum * Until the client grouping is improved, we must write the DSS data
966cee86682Scalum * to all instances' paths. Start at the current instance, and
967cee86682Scalum * walk the list backwards to the first.
968cee86682Scalum */
9690dfe541eSEvan Layton mutex_enter(&nsrv4->servinst_lock);
9700dfe541eSEvan Layton for (sip = nsrv4->nfs4_cur_servinst; sip != NULL; sip = sip->prev) {
971cee86682Scalum int i, npaths = sip->dss_npaths;
972cee86682Scalum
973cee86682Scalum /* write the leaf file to all DSS paths */
974cee86682Scalum for (i = 0; i < npaths; i++) {
975cee86682Scalum rfs4_dss_path_t *dss_path = sip->dss_paths[i];
976cee86682Scalum
977cee86682Scalum /* HA-NFSv4 path might have been failed-away from us */
978cee86682Scalum if (dss_path == NULL)
979cee86682Scalum continue;
980cee86682Scalum
981cee86682Scalum rfs4_ss_clid_write_one(cp, dss_path->path, leaf);
982cee86682Scalum }
9837c478bd9Sstevel@tonic-gate }
9840dfe541eSEvan Layton mutex_exit(&nsrv4->servinst_lock);
985cee86682Scalum }
986cee86682Scalum
987cee86682Scalum /*
988cee86682Scalum * Place client information into stable storage: 3/3.
989cee86682Scalum * Write the stable storage data to the requested file.
990cee86682Scalum */
991cee86682Scalum static void
rfs4_ss_clid_write_one(rfs4_client_t * cp,char * dss_path,char * leaf)992cee86682Scalum rfs4_ss_clid_write_one(rfs4_client_t *cp, char *dss_path, char *leaf)
993cee86682Scalum {
994cee86682Scalum int ioflag;
995cee86682Scalum int file_vers = NFS4_SS_VERSION;
99697669b90Scalum size_t dirlen;
997cee86682Scalum struct uio uio;
998cee86682Scalum struct iovec iov[4];
999cee86682Scalum char *dir;
1000cee86682Scalum rfs4_ss_pn_t *ss_pn;
1001cee86682Scalum vnode_t *vp;
1002d216dff5SRobert Mastors nfs_client_id4 *cl_id4 = &(cp->rc_nfs_client);
1003cee86682Scalum
1004cee86682Scalum /* allow 2 extra bytes for '/' & NUL */
100597669b90Scalum dirlen = strlen(dss_path) + strlen(NFS4_DSS_STATE_LEAF) + 2;
100697669b90Scalum dir = kmem_alloc(dirlen, KM_SLEEP);
1007cee86682Scalum (void) sprintf(dir, "%s/%s", dss_path, NFS4_DSS_STATE_LEAF);
1008cee86682Scalum
100997669b90Scalum ss_pn = rfs4_ss_pnalloc(dir, leaf);
101097669b90Scalum /* rfs4_ss_pnalloc takes its own copy */
101197669b90Scalum kmem_free(dir, dirlen);
101297669b90Scalum if (ss_pn == NULL)
1013cee86682Scalum return;
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate if (vn_open(ss_pn->pn, UIO_SYSSPACE, FCREAT|FWRITE, 0600, &vp,
1016ed57cab9Srg CRCREAT, 0)) {
10177c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(ss_pn);
10187c478bd9Sstevel@tonic-gate return;
10197c478bd9Sstevel@tonic-gate }
10207c478bd9Sstevel@tonic-gate
1021cee86682Scalum /*
1022cee86682Scalum * We need to record leaf - i.e. the filename - so that we know
1023cee86682Scalum * what to remove, in the future. However, the dir part of cp->ss_pn
1024cee86682Scalum * should never be referenced directly, since it's potentially only
1025cee86682Scalum * one of several paths with this leaf in it.
1026cee86682Scalum */
1027d216dff5SRobert Mastors if (cp->rc_ss_pn != NULL) {
1028d216dff5SRobert Mastors if (strcmp(cp->rc_ss_pn->leaf, leaf) == 0) {
1029cee86682Scalum /* we've already recorded *this* leaf */
1030cee86682Scalum rfs4_ss_pnfree(ss_pn);
1031cee86682Scalum } else {
1032cee86682Scalum /* replace with this leaf */
1033d216dff5SRobert Mastors rfs4_ss_pnfree(cp->rc_ss_pn);
1034d216dff5SRobert Mastors cp->rc_ss_pn = ss_pn;
1035cee86682Scalum }
1036cee86682Scalum } else {
1037d216dff5SRobert Mastors cp->rc_ss_pn = ss_pn;
1038cee86682Scalum }
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate * Build a scatter list that points to the nfs_client_id4
10427c478bd9Sstevel@tonic-gate */
10437c478bd9Sstevel@tonic-gate iov[0].iov_base = (caddr_t)&file_vers;
10447c478bd9Sstevel@tonic-gate iov[0].iov_len = sizeof (int);
1045cee86682Scalum iov[1].iov_base = (caddr_t)&(cl_id4->verifier);
10467c478bd9Sstevel@tonic-gate iov[1].iov_len = NFS4_VERIFIER_SIZE;
10477c478bd9Sstevel@tonic-gate iov[2].iov_base = (caddr_t)&(cl_id4->id_len);
10487c478bd9Sstevel@tonic-gate iov[2].iov_len = sizeof (uint_t);
10497c478bd9Sstevel@tonic-gate iov[3].iov_base = (caddr_t)cl_id4->id_val;
10507c478bd9Sstevel@tonic-gate iov[3].iov_len = cl_id4->id_len;
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate uio.uio_iov = iov;
10537c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 4;
10547c478bd9Sstevel@tonic-gate uio.uio_loffset = 0;
10557c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
10567c478bd9Sstevel@tonic-gate uio.uio_llimit = (rlim64_t)MAXOFFSET_T;
10577c478bd9Sstevel@tonic-gate uio.uio_resid = cl_id4->id_len + sizeof (int) +
1058ed57cab9Srg NFS4_VERIFIER_SIZE + sizeof (uint_t);
10597c478bd9Sstevel@tonic-gate
10607c478bd9Sstevel@tonic-gate ioflag = uio.uio_fmode = (FWRITE|FSYNC);
10617c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_DEFAULT;
10627c478bd9Sstevel@tonic-gate
10637c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
10647c478bd9Sstevel@tonic-gate /* write the full client id to the file. */
10657c478bd9Sstevel@tonic-gate (void) VOP_WRITE(vp, &uio, ioflag, CRED(), NULL);
10667c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
10677c478bd9Sstevel@tonic-gate
1068da6c28aaSamw (void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED(), NULL);
10697c478bd9Sstevel@tonic-gate VN_RELE(vp);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate
1072cee86682Scalum /*
1073cee86682Scalum * DSS: distributed stable storage.
1074cee86682Scalum * Unpack the list of paths passed by nfsd.
1075cee86682Scalum * Use nvlist_alloc(9F) to manage the data.
1076cee86682Scalum * The caller is responsible for allocating and freeing the buffer.
1077cee86682Scalum */
1078cee86682Scalum int
rfs4_dss_setpaths(char * buf,size_t buflen)1079cee86682Scalum rfs4_dss_setpaths(char *buf, size_t buflen)
1080cee86682Scalum {
1081cee86682Scalum int error;
1082cee86682Scalum
1083cee86682Scalum /*
1084cee86682Scalum * If this is a "warm start", i.e. we previously had DSS paths,
1085cee86682Scalum * preserve the old paths.
1086cee86682Scalum */
1087cee86682Scalum if (rfs4_dss_paths != NULL) {
1088cee86682Scalum /*
1089cee86682Scalum * Before we lose the ptr, destroy the nvlist and pathnames
1090cee86682Scalum * array from the warm start before this one.
1091cee86682Scalum */
1092aab83bb8SJosef 'Jeff' Sipek nvlist_free(rfs4_dss_oldpaths);
1093cee86682Scalum rfs4_dss_oldpaths = rfs4_dss_paths;
1094cee86682Scalum }
1095cee86682Scalum
1096cee86682Scalum /* unpack the buffer into a searchable nvlist */
1097cee86682Scalum error = nvlist_unpack(buf, buflen, &rfs4_dss_paths, KM_SLEEP);
1098cee86682Scalum if (error)
1099cee86682Scalum return (error);
1100cee86682Scalum
1101cee86682Scalum /*
1102cee86682Scalum * Search the nvlist for the pathnames nvpair (which is the only nvpair
1103cee86682Scalum * in the list, and record its location.
1104cee86682Scalum */
1105cee86682Scalum error = nvlist_lookup_string_array(rfs4_dss_paths, NFS4_DSS_NVPAIR_NAME,
1106cee86682Scalum &rfs4_dss_newpaths, &rfs4_dss_numnewpaths);
1107cee86682Scalum return (error);
1108cee86682Scalum }
1109cee86682Scalum
11107c478bd9Sstevel@tonic-gate /*
11117c478bd9Sstevel@tonic-gate * Ultimately the nfssys() call NFS4_CLR_STATE endsup here
11127c478bd9Sstevel@tonic-gate * to find and mark the client for forced expire.
11137c478bd9Sstevel@tonic-gate */
11147c478bd9Sstevel@tonic-gate static void
rfs4_client_scrub(rfs4_entry_t ent,void * arg)11157c478bd9Sstevel@tonic-gate rfs4_client_scrub(rfs4_entry_t ent, void *arg)
11167c478bd9Sstevel@tonic-gate {
11177c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)ent;
11187c478bd9Sstevel@tonic-gate struct nfs4clrst_args *clr = arg;
11197c478bd9Sstevel@tonic-gate struct sockaddr_in6 *ent_sin6;
11207c478bd9Sstevel@tonic-gate struct in6_addr clr_in6;
11217c478bd9Sstevel@tonic-gate struct sockaddr_in *ent_sin;
11227c478bd9Sstevel@tonic-gate struct in_addr clr_in;
11237c478bd9Sstevel@tonic-gate
1124d216dff5SRobert Mastors if (clr->addr_type != cp->rc_addr.ss_family) {
11257c478bd9Sstevel@tonic-gate return;
11267c478bd9Sstevel@tonic-gate }
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate switch (clr->addr_type) {
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate case AF_INET6:
11317c478bd9Sstevel@tonic-gate /* copyin the address from user space */
11327c478bd9Sstevel@tonic-gate if (copyin(clr->ap, &clr_in6, sizeof (clr_in6))) {
11337c478bd9Sstevel@tonic-gate break;
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
1136d216dff5SRobert Mastors ent_sin6 = (struct sockaddr_in6 *)&cp->rc_addr;
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate /*
11397c478bd9Sstevel@tonic-gate * now compare, and if equivalent mark entry
11407c478bd9Sstevel@tonic-gate * for forced expiration
11417c478bd9Sstevel@tonic-gate */
11427c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&ent_sin6->sin6_addr, &clr_in6)) {
1143d216dff5SRobert Mastors cp->rc_forced_expire = 1;
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate break;
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate case AF_INET:
11487c478bd9Sstevel@tonic-gate /* copyin the address from user space */
11497c478bd9Sstevel@tonic-gate if (copyin(clr->ap, &clr_in, sizeof (clr_in))) {
11507c478bd9Sstevel@tonic-gate break;
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate
1153d216dff5SRobert Mastors ent_sin = (struct sockaddr_in *)&cp->rc_addr;
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate /*
11567c478bd9Sstevel@tonic-gate * now compare, and if equivalent mark entry
11577c478bd9Sstevel@tonic-gate * for forced expiration
11587c478bd9Sstevel@tonic-gate */
11597c478bd9Sstevel@tonic-gate if (ent_sin->sin_addr.s_addr == clr_in.s_addr) {
1160d216dff5SRobert Mastors cp->rc_forced_expire = 1;
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate break;
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate default:
11657c478bd9Sstevel@tonic-gate /* force this assert to fail */
11667c478bd9Sstevel@tonic-gate ASSERT(clr->addr_type != clr->addr_type);
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate }
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate /*
11717c478bd9Sstevel@tonic-gate * This is called from nfssys() in order to clear server state
11727c478bd9Sstevel@tonic-gate * for the specified client IP Address.
11737c478bd9Sstevel@tonic-gate */
1174967a528aSDan McDonald int
rfs4_clear_client_state(struct nfs4clrst_args * clr)11757c478bd9Sstevel@tonic-gate rfs4_clear_client_state(struct nfs4clrst_args *clr)
11767c478bd9Sstevel@tonic-gate {
1177967a528aSDan McDonald nfs4_srv_t *nsrv4 = nfs4_get_srv();
1178967a528aSDan McDonald int rc;
1179967a528aSDan McDonald
1180967a528aSDan McDonald /* Once nfssrv is loaded, every zone should have one of these. */
1181967a528aSDan McDonald VERIFY(nsrv4 != NULL);
1182967a528aSDan McDonald
1183967a528aSDan McDonald mutex_enter(&nsrv4->state_lock);
1184967a528aSDan McDonald /*
1185967a528aSDan McDonald * But only after NFS service is running is the nfs4_server_state
1186967a528aSDan McDonald * around. It's dirty (and needs the state_lock held), but all of the
1187967a528aSDan McDonald * databases live deep in the nfs4_server_state, so it's the only thing
1188967a528aSDan McDonald * to legitimately check prior to using anything. The pointers
1189967a528aSDan McDonald * themselves may be stale.
1190967a528aSDan McDonald */
1191967a528aSDan McDonald if (nsrv4->nfs4_server_state != NULL) {
1192967a528aSDan McDonald VERIFY(nsrv4->rfs4_client_tab != NULL);
1193967a528aSDan McDonald rfs4_dbe_walk(nsrv4->rfs4_client_tab, rfs4_client_scrub, clr);
1194967a528aSDan McDonald rc = 0;
1195967a528aSDan McDonald } else {
1196967a528aSDan McDonald rc = ENXIO;
1197967a528aSDan McDonald }
1198967a528aSDan McDonald mutex_exit(&nsrv4->state_lock);
1199967a528aSDan McDonald return (rc);
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate /*
12037c478bd9Sstevel@tonic-gate * Used to initialize the NFSv4 server's state or database. All of
12040dfe541eSEvan Layton * the tables are created and timers are set.
12057c478bd9Sstevel@tonic-gate */
12067c478bd9Sstevel@tonic-gate void
rfs4_state_g_init(void)1207*f44e1126SVitaliy Gusev rfs4_state_g_init(void)
12087c478bd9Sstevel@tonic-gate {
12097c478bd9Sstevel@tonic-gate extern boolean_t rfs4_cpr_callb(void *, int);
12100dfe541eSEvan Layton /*
12110dfe541eSEvan Layton * Add a CPR callback so that we can update client
12120dfe541eSEvan Layton * access times to extend the lease after a suspend
12130dfe541eSEvan Layton * and resume (using the same class as rpcmod/connmgr)
12140dfe541eSEvan Layton */
12150dfe541eSEvan Layton cpr_id = callb_add(rfs4_cpr_callb, 0, CB_CL_CPR_RPC, "rfs4");
12167c478bd9Sstevel@tonic-gate
12170dfe541eSEvan Layton /*
12180dfe541eSEvan Layton * NFSv4 server state databases
12190dfe541eSEvan Layton *
12200dfe541eSEvan Layton * Initialized when the module is loaded and used by NFSv4 state
12210dfe541eSEvan Layton * tables. These kmem_cache free pools are used globally, the NFSv4
12220dfe541eSEvan Layton * state tables which make use of these kmem_cache free pools are per
12230dfe541eSEvan Layton * zone.
12240dfe541eSEvan Layton *
12250dfe541eSEvan Layton * initialize the global kmem_cache free pools which will be used by
12260dfe541eSEvan Layton * the NFSv4 state tables.
12270dfe541eSEvan Layton */
1228*f44e1126SVitaliy Gusev rfs4_client_mem_cache = nfs4_init_mem_cache("Client_entry_cache",
1229*f44e1126SVitaliy Gusev 2, sizeof (rfs4_client_t), 0);
1230*f44e1126SVitaliy Gusev rfs4_clntIP_mem_cache = nfs4_init_mem_cache("ClntIP_entry_cache",
1231*f44e1126SVitaliy Gusev 1, sizeof (rfs4_clntip_t), 1);
1232*f44e1126SVitaliy Gusev rfs4_openown_mem_cache = nfs4_init_mem_cache("OpenOwner_entry_cache",
1233*f44e1126SVitaliy Gusev 1, sizeof (rfs4_openowner_t), 2);
1234*f44e1126SVitaliy Gusev rfs4_openstID_mem_cache = nfs4_init_mem_cache("OpenStateID_entry_cache",
1235*f44e1126SVitaliy Gusev 3, sizeof (rfs4_state_t), 3);
1236*f44e1126SVitaliy Gusev rfs4_lockstID_mem_cache = nfs4_init_mem_cache("LockStateID_entry_cache",
1237*f44e1126SVitaliy Gusev 3, sizeof (rfs4_lo_state_t), 4);
1238*f44e1126SVitaliy Gusev rfs4_lockown_mem_cache = nfs4_init_mem_cache("Lockowner_entry_cache",
1239*f44e1126SVitaliy Gusev 2, sizeof (rfs4_lockowner_t), 5);
1240*f44e1126SVitaliy Gusev rfs4_file_mem_cache = nfs4_init_mem_cache("File_entry_cache",
1241*f44e1126SVitaliy Gusev 1, sizeof (rfs4_file_t), 6);
1242*f44e1126SVitaliy Gusev rfs4_delegstID_mem_cache =
1243*f44e1126SVitaliy Gusev nfs4_init_mem_cache("DelegStateID_entry_cache", 2,
1244*f44e1126SVitaliy Gusev sizeof (rfs4_deleg_state_t), 7);
1245*f44e1126SVitaliy Gusev rfs4_session_mem_cache = nfs4_init_mem_cache("Session_entry_cache",
1246*f44e1126SVitaliy Gusev 1, sizeof (rfs4_session_t), 8);
12470dfe541eSEvan Layton }
12480dfe541eSEvan Layton
12490dfe541eSEvan Layton
12500dfe541eSEvan Layton /*
12510dfe541eSEvan Layton * Used at server shutdown to cleanup all of the NFSv4 server's structures
12520dfe541eSEvan Layton * and other state.
12530dfe541eSEvan Layton */
12540dfe541eSEvan Layton void
rfs4_state_g_fini(void)1255*f44e1126SVitaliy Gusev rfs4_state_g_fini(void)
12560dfe541eSEvan Layton {
12570dfe541eSEvan Layton int i;
12587c478bd9Sstevel@tonic-gate /*
12590dfe541eSEvan Layton * Cleanup the CPR callback.
12607c478bd9Sstevel@tonic-gate */
12610dfe541eSEvan Layton if (cpr_id)
12620dfe541eSEvan Layton (void) callb_delete(cpr_id);
12630dfe541eSEvan Layton
12640dfe541eSEvan Layton /* free the NFSv4 state databases */
12650dfe541eSEvan Layton for (i = 0; i < RFS4_DB_MEM_CACHE_NUM; i++) {
12660dfe541eSEvan Layton kmem_cache_destroy(rfs4_db_mem_cache_table[i].r_db_mem_cache);
12670dfe541eSEvan Layton rfs4_db_mem_cache_table[i].r_db_mem_cache = NULL;
12687c478bd9Sstevel@tonic-gate }
12697c478bd9Sstevel@tonic-gate
12700dfe541eSEvan Layton rfs4_client_mem_cache = NULL;
12710dfe541eSEvan Layton rfs4_clntIP_mem_cache = NULL;
12720dfe541eSEvan Layton rfs4_openown_mem_cache = NULL;
12730dfe541eSEvan Layton rfs4_openstID_mem_cache = NULL;
12740dfe541eSEvan Layton rfs4_lockstID_mem_cache = NULL;
12750dfe541eSEvan Layton rfs4_lockown_mem_cache = NULL;
12760dfe541eSEvan Layton rfs4_file_mem_cache = NULL;
12770dfe541eSEvan Layton rfs4_delegstID_mem_cache = NULL;
1278*f44e1126SVitaliy Gusev rfs4_session_mem_cache = NULL;
12790dfe541eSEvan Layton
12800dfe541eSEvan Layton /* DSS: distributed stable storage */
12810dfe541eSEvan Layton nvlist_free(rfs4_dss_oldpaths);
12820dfe541eSEvan Layton nvlist_free(rfs4_dss_paths);
12830dfe541eSEvan Layton rfs4_dss_paths = rfs4_dss_oldpaths = NULL;
12840dfe541eSEvan Layton }
12850dfe541eSEvan Layton
12860dfe541eSEvan Layton /*
12870dfe541eSEvan Layton * Used to initialize the per zone NFSv4 server's state
12880dfe541eSEvan Layton */
12890dfe541eSEvan Layton void
rfs4_state_zone_init(nfs4_srv_t * nsrv4)12900dfe541eSEvan Layton rfs4_state_zone_init(nfs4_srv_t *nsrv4)
12910dfe541eSEvan Layton {
12920dfe541eSEvan Layton time_t start_time;
12930dfe541eSEvan Layton int start_grace;
12940dfe541eSEvan Layton char *dss_path = NFS4_DSS_VAR_DIR;
12950dfe541eSEvan Layton
12960dfe541eSEvan Layton /* DSS: distributed stable storage: initialise served paths list */
12970dfe541eSEvan Layton nsrv4->dss_pathlist = NULL;
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate /*
13007c478bd9Sstevel@tonic-gate * Set the boot time. If the server
13017c478bd9Sstevel@tonic-gate * has been restarted quickly and has had the opportunity to
13027c478bd9Sstevel@tonic-gate * service clients, then the start_time needs to be bumped
13037c478bd9Sstevel@tonic-gate * regardless. A small window but it exists...
13047c478bd9Sstevel@tonic-gate */
130525a1318cSMarcel Telka start_time = gethrestime_sec();
13060dfe541eSEvan Layton if (nsrv4->rfs4_start_time < start_time)
13070dfe541eSEvan Layton nsrv4->rfs4_start_time = start_time;
13087c478bd9Sstevel@tonic-gate else
13090dfe541eSEvan Layton nsrv4->rfs4_start_time++;
1310cee86682Scalum
13117c478bd9Sstevel@tonic-gate /*
13127c478bd9Sstevel@tonic-gate * Create the first server instance, or a new one if the server has
13137c478bd9Sstevel@tonic-gate * been restarted; see above comments on rfs4_start_time. Don't
13147c478bd9Sstevel@tonic-gate * start its grace period; that will be done later, to maximise the
13157c478bd9Sstevel@tonic-gate * clients' recovery window.
13167c478bd9Sstevel@tonic-gate */
13177c478bd9Sstevel@tonic-gate start_grace = 0;
13180dfe541eSEvan Layton if (curzone == global_zone && rfs4_dss_numnewpaths > 0) {
13190dfe541eSEvan Layton int i;
13200dfe541eSEvan Layton char **dss_allpaths = NULL;
13210dfe541eSEvan Layton dss_allpaths = kmem_alloc(sizeof (char *) *
13220dfe541eSEvan Layton (rfs4_dss_numnewpaths + 1), KM_SLEEP);
13230dfe541eSEvan Layton /*
13240dfe541eSEvan Layton * Add the default path into the list of paths for saving
13250dfe541eSEvan Layton * state informantion.
13260dfe541eSEvan Layton */
13270dfe541eSEvan Layton dss_allpaths[0] = dss_path;
13280dfe541eSEvan Layton for (i = 0; i < rfs4_dss_numnewpaths; i++) {
13290dfe541eSEvan Layton dss_allpaths[i + 1] = rfs4_dss_newpaths[i];
13300dfe541eSEvan Layton }
13310dfe541eSEvan Layton rfs4_servinst_create(nsrv4, start_grace,
13320dfe541eSEvan Layton (rfs4_dss_numnewpaths + 1), dss_allpaths);
13330dfe541eSEvan Layton kmem_free(dss_allpaths,
13340dfe541eSEvan Layton (sizeof (char *) * (rfs4_dss_numnewpaths + 1)));
13350dfe541eSEvan Layton } else {
13360dfe541eSEvan Layton rfs4_servinst_create(nsrv4, start_grace, 1, &dss_path);
13370dfe541eSEvan Layton }
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate /* reset the "first NFSv4 request" status */
13400dfe541eSEvan Layton nsrv4->seen_first_compound = 0;
13410dfe541eSEvan Layton
13420dfe541eSEvan Layton mutex_enter(&nsrv4->state_lock);
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate /*
13450dfe541eSEvan Layton * If the server state database has already been initialized,
13460dfe541eSEvan Layton * skip it
13477c478bd9Sstevel@tonic-gate */
13480dfe541eSEvan Layton if (nsrv4->nfs4_server_state != NULL) {
13490dfe541eSEvan Layton mutex_exit(&nsrv4->state_lock);
13500dfe541eSEvan Layton return;
13510dfe541eSEvan Layton }
13520dfe541eSEvan Layton
13530dfe541eSEvan Layton rw_init(&nsrv4->rfs4_findclient_lock, NULL, RW_DEFAULT, NULL);
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate /* set the various cache timers for table creation */
13560dfe541eSEvan Layton if (nsrv4->rfs4_client_cache_time == 0)
13570dfe541eSEvan Layton nsrv4->rfs4_client_cache_time = CLIENT_CACHE_TIME;
13580dfe541eSEvan Layton if (nsrv4->rfs4_openowner_cache_time == 0)
13590dfe541eSEvan Layton nsrv4->rfs4_openowner_cache_time = OPENOWNER_CACHE_TIME;
13600dfe541eSEvan Layton if (nsrv4->rfs4_state_cache_time == 0)
13610dfe541eSEvan Layton nsrv4->rfs4_state_cache_time = STATE_CACHE_TIME;
13620dfe541eSEvan Layton if (nsrv4->rfs4_lo_state_cache_time == 0)
13630dfe541eSEvan Layton nsrv4->rfs4_lo_state_cache_time = LO_STATE_CACHE_TIME;
13640dfe541eSEvan Layton if (nsrv4->rfs4_lockowner_cache_time == 0)
13650dfe541eSEvan Layton nsrv4->rfs4_lockowner_cache_time = LOCKOWNER_CACHE_TIME;
13660dfe541eSEvan Layton if (nsrv4->rfs4_file_cache_time == 0)
13670dfe541eSEvan Layton nsrv4->rfs4_file_cache_time = FILE_CACHE_TIME;
13680dfe541eSEvan Layton if (nsrv4->rfs4_deleg_state_cache_time == 0)
13690dfe541eSEvan Layton nsrv4->rfs4_deleg_state_cache_time = DELEG_STATE_CACHE_TIME;
13707c478bd9Sstevel@tonic-gate
13717c478bd9Sstevel@tonic-gate /* Create the overall database to hold all server state */
13720dfe541eSEvan Layton nsrv4->nfs4_server_state = rfs4_database_create(rfs4_database_debug);
13737c478bd9Sstevel@tonic-gate
13747c478bd9Sstevel@tonic-gate /* Now create the individual tables */
13750dfe541eSEvan Layton nsrv4->rfs4_client_cache_time *= rfs4_lease_time;
13760dfe541eSEvan Layton nsrv4->rfs4_client_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1377ed57cab9Srg "Client",
13780dfe541eSEvan Layton nsrv4->rfs4_client_cache_time,
1379ed57cab9Srg 2,
1380ed57cab9Srg rfs4_client_create,
1381ed57cab9Srg rfs4_client_destroy,
1382ed57cab9Srg rfs4_client_expiry,
1383ed57cab9Srg sizeof (rfs4_client_t),
1384ed57cab9Srg TABSIZE,
1385ed57cab9Srg MAXTABSZ/8, 100);
13860dfe541eSEvan Layton nsrv4->rfs4_nfsclnt_idx = rfs4_index_create(nsrv4->rfs4_client_tab,
1387ed57cab9Srg "nfs_client_id4", nfsclnt_hash,
1388ed57cab9Srg nfsclnt_compare, nfsclnt_mkkey,
1389ed57cab9Srg TRUE);
13900dfe541eSEvan Layton nsrv4->rfs4_clientid_idx = rfs4_index_create(nsrv4->rfs4_client_tab,
1391ed57cab9Srg "client_id", clientid_hash,
1392ed57cab9Srg clientid_compare, clientid_mkkey,
1393ed57cab9Srg FALSE);
13947c478bd9Sstevel@tonic-gate
13950dfe541eSEvan Layton nsrv4->rfs4_clntip_cache_time = 86400 * 365; /* about a year */
13960dfe541eSEvan Layton nsrv4->rfs4_clntip_tab = rfs4_table_create(nsrv4->nfs4_server_state,
13972f172c55SRobert Thurlow "ClntIP",
13980dfe541eSEvan Layton nsrv4->rfs4_clntip_cache_time,
13992f172c55SRobert Thurlow 1,
14002f172c55SRobert Thurlow rfs4_clntip_create,
14012f172c55SRobert Thurlow rfs4_clntip_destroy,
14022f172c55SRobert Thurlow rfs4_clntip_expiry,
14032f172c55SRobert Thurlow sizeof (rfs4_clntip_t),
14042f172c55SRobert Thurlow TABSIZE,
14052f172c55SRobert Thurlow MAXTABSZ, 100);
14060dfe541eSEvan Layton nsrv4->rfs4_clntip_idx = rfs4_index_create(nsrv4->rfs4_clntip_tab,
14072f172c55SRobert Thurlow "client_ip", clntip_hash,
14082f172c55SRobert Thurlow clntip_compare, clntip_mkkey,
14092f172c55SRobert Thurlow TRUE);
14102f172c55SRobert Thurlow
14110dfe541eSEvan Layton nsrv4->rfs4_openowner_cache_time *= rfs4_lease_time;
14120dfe541eSEvan Layton nsrv4->rfs4_openowner_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1413ed57cab9Srg "OpenOwner",
14140dfe541eSEvan Layton nsrv4->rfs4_openowner_cache_time,
1415ed57cab9Srg 1,
1416ed57cab9Srg rfs4_openowner_create,
1417ed57cab9Srg rfs4_openowner_destroy,
1418ed57cab9Srg rfs4_openowner_expiry,
1419ed57cab9Srg sizeof (rfs4_openowner_t),
1420ed57cab9Srg TABSIZE,
1421ed57cab9Srg MAXTABSZ, 100);
14220dfe541eSEvan Layton nsrv4->rfs4_openowner_idx = rfs4_index_create(nsrv4->rfs4_openowner_tab,
1423ed57cab9Srg "open_owner4", openowner_hash,
1424ed57cab9Srg openowner_compare,
1425ed57cab9Srg openowner_mkkey, TRUE);
14267c478bd9Sstevel@tonic-gate
14270dfe541eSEvan Layton nsrv4->rfs4_state_cache_time *= rfs4_lease_time;
14280dfe541eSEvan Layton nsrv4->rfs4_state_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1429ed57cab9Srg "OpenStateID",
14300dfe541eSEvan Layton nsrv4->rfs4_state_cache_time,
1431ed57cab9Srg 3,
1432ed57cab9Srg rfs4_state_create,
1433ed57cab9Srg rfs4_state_destroy,
1434ed57cab9Srg rfs4_state_expiry,
1435ed57cab9Srg sizeof (rfs4_state_t),
1436ed57cab9Srg TABSIZE,
1437ed57cab9Srg MAXTABSZ, 100);
1438ed57cab9Srg
14390dfe541eSEvan Layton /* CSTYLED */
14400dfe541eSEvan Layton nsrv4->rfs4_state_owner_file_idx = rfs4_index_create(nsrv4->rfs4_state_tab,
1441ed57cab9Srg "Openowner-File",
1442ed57cab9Srg state_owner_file_hash,
1443ed57cab9Srg state_owner_file_compare,
1444ed57cab9Srg state_owner_file_mkkey, TRUE);
1445ed57cab9Srg
14460dfe541eSEvan Layton nsrv4->rfs4_state_idx = rfs4_index_create(nsrv4->rfs4_state_tab,
1447ed57cab9Srg "State-id", state_hash,
1448ed57cab9Srg state_compare, state_mkkey, FALSE);
1449ed57cab9Srg
14500dfe541eSEvan Layton nsrv4->rfs4_state_file_idx = rfs4_index_create(nsrv4->rfs4_state_tab,
1451ed57cab9Srg "File", state_file_hash,
1452ed57cab9Srg state_file_compare, state_file_mkkey,
1453ed57cab9Srg FALSE);
14547c478bd9Sstevel@tonic-gate
14550dfe541eSEvan Layton nsrv4->rfs4_lo_state_cache_time *= rfs4_lease_time;
14560dfe541eSEvan Layton nsrv4->rfs4_lo_state_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1457ed57cab9Srg "LockStateID",
14580dfe541eSEvan Layton nsrv4->rfs4_lo_state_cache_time,
1459ed57cab9Srg 2,
1460ed57cab9Srg rfs4_lo_state_create,
1461ed57cab9Srg rfs4_lo_state_destroy,
1462ed57cab9Srg rfs4_lo_state_expiry,
1463ed57cab9Srg sizeof (rfs4_lo_state_t),
1464ed57cab9Srg TABSIZE,
1465ed57cab9Srg MAXTABSZ, 100);
1466ed57cab9Srg
14670dfe541eSEvan Layton /* CSTYLED */
14680dfe541eSEvan Layton nsrv4->rfs4_lo_state_owner_idx = rfs4_index_create(nsrv4->rfs4_lo_state_tab,
1469ed57cab9Srg "lockownerxstate",
1470ed57cab9Srg lo_state_lo_hash,
1471ed57cab9Srg lo_state_lo_compare,
1472ed57cab9Srg lo_state_lo_mkkey, TRUE);
1473ed57cab9Srg
14740dfe541eSEvan Layton nsrv4->rfs4_lo_state_idx = rfs4_index_create(nsrv4->rfs4_lo_state_tab,
1475ed57cab9Srg "State-id",
1476ed57cab9Srg lo_state_hash, lo_state_compare,
1477ed57cab9Srg lo_state_mkkey, FALSE);
14787c478bd9Sstevel@tonic-gate
14790dfe541eSEvan Layton nsrv4->rfs4_lockowner_cache_time *= rfs4_lease_time;
1480ed57cab9Srg
14810dfe541eSEvan Layton nsrv4->rfs4_lockowner_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1482ed57cab9Srg "Lockowner",
14830dfe541eSEvan Layton nsrv4->rfs4_lockowner_cache_time,
1484ed57cab9Srg 2,
1485ed57cab9Srg rfs4_lockowner_create,
1486ed57cab9Srg rfs4_lockowner_destroy,
1487ed57cab9Srg rfs4_lockowner_expiry,
1488ed57cab9Srg sizeof (rfs4_lockowner_t),
1489ed57cab9Srg TABSIZE,
1490ed57cab9Srg MAXTABSZ, 100);
1491ed57cab9Srg
14920dfe541eSEvan Layton nsrv4->rfs4_lockowner_idx = rfs4_index_create(nsrv4->rfs4_lockowner_tab,
1493ed57cab9Srg "lock_owner4", lockowner_hash,
1494ed57cab9Srg lockowner_compare,
1495ed57cab9Srg lockowner_mkkey, TRUE);
1496ed57cab9Srg
14970dfe541eSEvan Layton /* CSTYLED */
14980dfe541eSEvan Layton nsrv4->rfs4_lockowner_pid_idx = rfs4_index_create(nsrv4->rfs4_lockowner_tab,
1499ed57cab9Srg "pid", pid_hash,
1500ed57cab9Srg pid_compare, pid_mkkey,
1501ed57cab9Srg FALSE);
15027c478bd9Sstevel@tonic-gate
15030dfe541eSEvan Layton nsrv4->rfs4_file_cache_time *= rfs4_lease_time;
15040dfe541eSEvan Layton nsrv4->rfs4_file_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1505ed57cab9Srg "File",
15060dfe541eSEvan Layton nsrv4->rfs4_file_cache_time,
1507ed57cab9Srg 1,
1508ed57cab9Srg rfs4_file_create,
1509ed57cab9Srg rfs4_file_destroy,
1510ed57cab9Srg NULL,
1511ed57cab9Srg sizeof (rfs4_file_t),
1512ed57cab9Srg TABSIZE,
1513ed57cab9Srg MAXTABSZ, -1);
1514ed57cab9Srg
15150dfe541eSEvan Layton nsrv4->rfs4_file_idx = rfs4_index_create(nsrv4->rfs4_file_tab,
1516ed57cab9Srg "Filehandle", file_hash,
1517ed57cab9Srg file_compare, file_mkkey, TRUE);
15187c478bd9Sstevel@tonic-gate
15190dfe541eSEvan Layton nsrv4->rfs4_deleg_state_cache_time *= rfs4_lease_time;
15200dfe541eSEvan Layton /* CSTYLED */
15210dfe541eSEvan Layton nsrv4->rfs4_deleg_state_tab = rfs4_table_create(nsrv4->nfs4_server_state,
1522ed57cab9Srg "DelegStateID",
15230dfe541eSEvan Layton nsrv4->rfs4_deleg_state_cache_time,
1524ed57cab9Srg 2,
1525ed57cab9Srg rfs4_deleg_state_create,
1526ed57cab9Srg rfs4_deleg_state_destroy,
1527ed57cab9Srg rfs4_deleg_state_expiry,
1528ed57cab9Srg sizeof (rfs4_deleg_state_t),
1529ed57cab9Srg TABSIZE,
1530ed57cab9Srg MAXTABSZ, 100);
15310dfe541eSEvan Layton nsrv4->rfs4_deleg_idx = rfs4_index_create(nsrv4->rfs4_deleg_state_tab,
1532ed57cab9Srg "DelegByFileClient",
1533ed57cab9Srg deleg_hash,
1534ed57cab9Srg deleg_compare,
1535ed57cab9Srg deleg_mkkey, TRUE);
1536ed57cab9Srg
15370dfe541eSEvan Layton /* CSTYLED */
15380dfe541eSEvan Layton nsrv4->rfs4_deleg_state_idx = rfs4_index_create(nsrv4->rfs4_deleg_state_tab,
1539ed57cab9Srg "DelegState",
1540ed57cab9Srg deleg_state_hash,
1541ed57cab9Srg deleg_state_compare,
1542ed57cab9Srg deleg_state_mkkey, FALSE);
15437c478bd9Sstevel@tonic-gate
1544*f44e1126SVitaliy Gusev rfs4x_state_init_locked(nsrv4);
1545*f44e1126SVitaliy Gusev
15460dfe541eSEvan Layton mutex_exit(&nsrv4->state_lock);
15470dfe541eSEvan Layton
15487c478bd9Sstevel@tonic-gate /*
15497c478bd9Sstevel@tonic-gate * Init the stable storage.
15507c478bd9Sstevel@tonic-gate */
15510dfe541eSEvan Layton rfs4_ss_init(nsrv4);
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate /*
15550dfe541eSEvan Layton * Used at server shutdown to cleanup all of NFSv4 server's zone structures
15560dfe541eSEvan Layton * and state.
15577c478bd9Sstevel@tonic-gate */
15587c478bd9Sstevel@tonic-gate void
rfs4_state_zone_fini(void)1559*f44e1126SVitaliy Gusev rfs4_state_zone_fini(void)
15607c478bd9Sstevel@tonic-gate {
15617c478bd9Sstevel@tonic-gate rfs4_database_t *dbp;
15620dfe541eSEvan Layton nfs4_srv_t *nsrv4;
15630dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
15640dfe541eSEvan Layton
15650dfe541eSEvan Layton rfs4_set_deleg_policy(nsrv4, SRV_NEVER_DELEGATE);
15660dfe541eSEvan Layton
15670dfe541eSEvan Layton /*
15680dfe541eSEvan Layton * Clean up any dangling stable storage structures BEFORE calling
15690dfe541eSEvan Layton * rfs4_servinst_destroy_all() so there are no dangling structures
15700dfe541eSEvan Layton * (i.e. the srvinsts are all cleared of danglers BEFORE they get
15710dfe541eSEvan Layton * freed).
15720dfe541eSEvan Layton */
15730dfe541eSEvan Layton rfs4_ss_fini(nsrv4);
15747c478bd9Sstevel@tonic-gate
15750dfe541eSEvan Layton mutex_enter(&nsrv4->state_lock);
15767c478bd9Sstevel@tonic-gate
15770dfe541eSEvan Layton if (nsrv4->nfs4_server_state == NULL) {
15780dfe541eSEvan Layton mutex_exit(&nsrv4->state_lock);
15797c478bd9Sstevel@tonic-gate return;
15807c478bd9Sstevel@tonic-gate }
15817c478bd9Sstevel@tonic-gate
1582*f44e1126SVitaliy Gusev rfs4x_state_fini(nsrv4);
1583*f44e1126SVitaliy Gusev
15840dfe541eSEvan Layton /* destroy server instances and current instance ptr */
15850dfe541eSEvan Layton rfs4_servinst_destroy_all(nsrv4);
15867c478bd9Sstevel@tonic-gate
15870dfe541eSEvan Layton /* reset the "first NFSv4 request" status */
15880dfe541eSEvan Layton nsrv4->seen_first_compound = 0;
15897c478bd9Sstevel@tonic-gate
15900dfe541eSEvan Layton dbp = nsrv4->nfs4_server_state;
15910dfe541eSEvan Layton nsrv4->nfs4_server_state = NULL;
15927c478bd9Sstevel@tonic-gate
15930dfe541eSEvan Layton rw_destroy(&nsrv4->rfs4_findclient_lock);
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate /* First stop all of the reaper threads in the database */
15967c478bd9Sstevel@tonic-gate rfs4_database_shutdown(dbp);
15970dfe541eSEvan Layton
15980dfe541eSEvan Layton /*
15990dfe541eSEvan Layton * WARNING: There may be consumers of the rfs4 database still
16000dfe541eSEvan Layton * active as we destroy these. IF that's the case, consider putting
16010dfe541eSEvan Layton * some of their _zone_fini()-like functions into the zsd key as
16020dfe541eSEvan Layton * ~~SHUTDOWN~~ functions instead of ~~DESTROY~~ functions. We can
16030dfe541eSEvan Layton * maintain some ordering guarantees better that way.
16040dfe541eSEvan Layton */
16050dfe541eSEvan Layton /* Now destroy/release the database tables */
16067c478bd9Sstevel@tonic-gate rfs4_database_destroy(dbp);
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate /* Reset the cache timers for next time */
16090dfe541eSEvan Layton nsrv4->rfs4_client_cache_time = 0;
16100dfe541eSEvan Layton nsrv4->rfs4_openowner_cache_time = 0;
16110dfe541eSEvan Layton nsrv4->rfs4_state_cache_time = 0;
16120dfe541eSEvan Layton nsrv4->rfs4_lo_state_cache_time = 0;
16130dfe541eSEvan Layton nsrv4->rfs4_lockowner_cache_time = 0;
16140dfe541eSEvan Layton nsrv4->rfs4_file_cache_time = 0;
16150dfe541eSEvan Layton nsrv4->rfs4_deleg_state_cache_time = 0;
1616cee86682Scalum
16170dfe541eSEvan Layton mutex_exit(&nsrv4->state_lock);
16187c478bd9Sstevel@tonic-gate }
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate typedef union {
16217c478bd9Sstevel@tonic-gate struct {
16227c478bd9Sstevel@tonic-gate uint32_t start_time;
16237c478bd9Sstevel@tonic-gate uint32_t c_id;
16247c478bd9Sstevel@tonic-gate } impl_id;
16257c478bd9Sstevel@tonic-gate clientid4 id4;
16267c478bd9Sstevel@tonic-gate } cid;
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gate static int foreign_stateid(stateid_t *id);
16297c478bd9Sstevel@tonic-gate static int foreign_clientid(cid *cidp);
16307c478bd9Sstevel@tonic-gate static void embed_nodeid(cid *cidp);
16317c478bd9Sstevel@tonic-gate
16327c478bd9Sstevel@tonic-gate typedef union {
16337c478bd9Sstevel@tonic-gate struct {
16347c478bd9Sstevel@tonic-gate uint32_t c_id;
16357c478bd9Sstevel@tonic-gate uint32_t gen_num;
16367c478bd9Sstevel@tonic-gate } cv_impl;
16377c478bd9Sstevel@tonic-gate verifier4 confirm_verf;
16387c478bd9Sstevel@tonic-gate } scid_confirm_verf;
16397c478bd9Sstevel@tonic-gate
16407c478bd9Sstevel@tonic-gate static uint32_t
clientid_hash(void * key)16417c478bd9Sstevel@tonic-gate clientid_hash(void *key)
16427c478bd9Sstevel@tonic-gate {
16437c478bd9Sstevel@tonic-gate cid *idp = key;
16447c478bd9Sstevel@tonic-gate
16457c478bd9Sstevel@tonic-gate return (idp->impl_id.c_id);
16467c478bd9Sstevel@tonic-gate }
16477c478bd9Sstevel@tonic-gate
16487c478bd9Sstevel@tonic-gate static bool_t
clientid_compare(rfs4_entry_t entry,void * key)16497c478bd9Sstevel@tonic-gate clientid_compare(rfs4_entry_t entry, void *key)
16507c478bd9Sstevel@tonic-gate {
1651d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry;
16527c478bd9Sstevel@tonic-gate clientid4 *idp = key;
16537c478bd9Sstevel@tonic-gate
1654d216dff5SRobert Mastors return (*idp == cp->rc_clientid);
16557c478bd9Sstevel@tonic-gate }
16567c478bd9Sstevel@tonic-gate
16577c478bd9Sstevel@tonic-gate static void *
clientid_mkkey(rfs4_entry_t entry)16587c478bd9Sstevel@tonic-gate clientid_mkkey(rfs4_entry_t entry)
16597c478bd9Sstevel@tonic-gate {
1660d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry;
16617c478bd9Sstevel@tonic-gate
1662d216dff5SRobert Mastors return (&cp->rc_clientid);
16637c478bd9Sstevel@tonic-gate }
16647c478bd9Sstevel@tonic-gate
16657c478bd9Sstevel@tonic-gate static uint32_t
nfsclnt_hash(void * key)16667c478bd9Sstevel@tonic-gate nfsclnt_hash(void *key)
16677c478bd9Sstevel@tonic-gate {
16687c478bd9Sstevel@tonic-gate nfs_client_id4 *client = key;
16697c478bd9Sstevel@tonic-gate int i;
16707c478bd9Sstevel@tonic-gate uint32_t hash = 0;
16717c478bd9Sstevel@tonic-gate
16727c478bd9Sstevel@tonic-gate for (i = 0; i < client->id_len; i++) {
16737c478bd9Sstevel@tonic-gate hash <<= 1;
16747c478bd9Sstevel@tonic-gate hash += (uint_t)client->id_val[i];
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate return (hash);
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate
16807c478bd9Sstevel@tonic-gate static bool_t
nfsclnt_compare(rfs4_entry_t entry,void * key)16817c478bd9Sstevel@tonic-gate nfsclnt_compare(rfs4_entry_t entry, void *key)
16827c478bd9Sstevel@tonic-gate {
1683d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry;
16847c478bd9Sstevel@tonic-gate nfs_client_id4 *nfs_client = key;
16857c478bd9Sstevel@tonic-gate
1686d216dff5SRobert Mastors if (cp->rc_nfs_client.id_len != nfs_client->id_len)
16877c478bd9Sstevel@tonic-gate return (FALSE);
16887c478bd9Sstevel@tonic-gate
1689d216dff5SRobert Mastors return (bcmp(cp->rc_nfs_client.id_val, nfs_client->id_val,
1690ed57cab9Srg nfs_client->id_len) == 0);
16917c478bd9Sstevel@tonic-gate }
16927c478bd9Sstevel@tonic-gate
16937c478bd9Sstevel@tonic-gate static void *
nfsclnt_mkkey(rfs4_entry_t entry)16947c478bd9Sstevel@tonic-gate nfsclnt_mkkey(rfs4_entry_t entry)
16957c478bd9Sstevel@tonic-gate {
1696d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry;
16977c478bd9Sstevel@tonic-gate
1698d216dff5SRobert Mastors return (&cp->rc_nfs_client);
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate static bool_t
rfs4_client_expiry(rfs4_entry_t u_entry)17027c478bd9Sstevel@tonic-gate rfs4_client_expiry(rfs4_entry_t u_entry)
17037c478bd9Sstevel@tonic-gate {
17047c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)u_entry;
17057c478bd9Sstevel@tonic-gate bool_t cp_expired;
17067c478bd9Sstevel@tonic-gate
1707fbd8dcf9SGerald Thornbrugh if (rfs4_dbe_is_invalid(cp->rc_dbe)) {
1708fbd8dcf9SGerald Thornbrugh cp->rc_ss_remove = 1;
17097c478bd9Sstevel@tonic-gate return (TRUE);
1710fbd8dcf9SGerald Thornbrugh }
17117c478bd9Sstevel@tonic-gate /*
17127c478bd9Sstevel@tonic-gate * If the sysadmin has used clear_locks for this
17137c478bd9Sstevel@tonic-gate * entry then forced_expire will be set and we
17147c478bd9Sstevel@tonic-gate * want this entry to be reaped. Or the entry
17157c478bd9Sstevel@tonic-gate * has exceeded its lease period.
17167c478bd9Sstevel@tonic-gate */
1717d216dff5SRobert Mastors cp_expired = (cp->rc_forced_expire ||
1718d216dff5SRobert Mastors (gethrestime_sec() - cp->rc_last_access
1719ed57cab9Srg > rfs4_lease_time));
1720cee86682Scalum
1721d216dff5SRobert Mastors if (!cp->rc_ss_remove && cp_expired)
1722d216dff5SRobert Mastors cp->rc_ss_remove = 1;
17237c478bd9Sstevel@tonic-gate return (cp_expired);
17247c478bd9Sstevel@tonic-gate }
17257c478bd9Sstevel@tonic-gate
1726cee86682Scalum /*
1727cee86682Scalum * Remove the leaf file from all distributed stable storage paths.
1728cee86682Scalum */
1729cee86682Scalum static void
rfs4_dss_remove_cpleaf(rfs4_client_t * cp)1730cee86682Scalum rfs4_dss_remove_cpleaf(rfs4_client_t *cp)
1731cee86682Scalum {
17320dfe541eSEvan Layton nfs4_srv_t *nsrv4;
1733fbd8dcf9SGerald Thornbrugh rfs4_servinst_t *sip;
1734d216dff5SRobert Mastors char *leaf = cp->rc_ss_pn->leaf;
1735cee86682Scalum
1736fbd8dcf9SGerald Thornbrugh /*
1737fbd8dcf9SGerald Thornbrugh * since the state files are written to all DSS
1738fbd8dcf9SGerald Thornbrugh * paths we must remove this leaf file instance
1739fbd8dcf9SGerald Thornbrugh * from all server instances.
1740fbd8dcf9SGerald Thornbrugh */
1741fbd8dcf9SGerald Thornbrugh
17420dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
17430dfe541eSEvan Layton mutex_enter(&nsrv4->servinst_lock);
17440dfe541eSEvan Layton for (sip = nsrv4->nfs4_cur_servinst; sip != NULL; sip = sip->prev) {
1745fbd8dcf9SGerald Thornbrugh /* remove the leaf file associated with this server instance */
1746fbd8dcf9SGerald Thornbrugh rfs4_dss_remove_leaf(sip, NFS4_DSS_STATE_LEAF, leaf);
1747fbd8dcf9SGerald Thornbrugh }
17480dfe541eSEvan Layton mutex_exit(&nsrv4->servinst_lock);
1749cee86682Scalum }
1750cee86682Scalum
1751cee86682Scalum static void
rfs4_dss_remove_leaf(rfs4_servinst_t * sip,char * dir_leaf,char * leaf)1752cee86682Scalum rfs4_dss_remove_leaf(rfs4_servinst_t *sip, char *dir_leaf, char *leaf)
1753cee86682Scalum {
1754cee86682Scalum int i, npaths = sip->dss_npaths;
1755cee86682Scalum
1756cee86682Scalum for (i = 0; i < npaths; i++) {
1757cee86682Scalum rfs4_dss_path_t *dss_path = sip->dss_paths[i];
1758cee86682Scalum char *path, *dir;
1759cee86682Scalum size_t pathlen;
1760cee86682Scalum
1761cee86682Scalum /* the HA-NFSv4 path might have been failed-over away from us */
1762cee86682Scalum if (dss_path == NULL)
1763cee86682Scalum continue;
1764cee86682Scalum
1765cee86682Scalum dir = dss_path->path;
1766cee86682Scalum
1767cee86682Scalum /* allow 3 extra bytes for two '/' & a NUL */
1768cee86682Scalum pathlen = strlen(dir) + strlen(dir_leaf) + strlen(leaf) + 3;
1769cee86682Scalum path = kmem_alloc(pathlen, KM_SLEEP);
1770cee86682Scalum (void) sprintf(path, "%s/%s/%s", dir, dir_leaf, leaf);
1771cee86682Scalum
1772cee86682Scalum (void) vn_remove(path, UIO_SYSSPACE, RMFILE);
1773cee86682Scalum
1774cee86682Scalum kmem_free(path, pathlen);
1775cee86682Scalum }
1776cee86682Scalum }
1777cee86682Scalum
17787c478bd9Sstevel@tonic-gate static void
rfs4_client_destroy(rfs4_entry_t u_entry)17797c478bd9Sstevel@tonic-gate rfs4_client_destroy(rfs4_entry_t u_entry)
17807c478bd9Sstevel@tonic-gate {
17817c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)u_entry;
17827c478bd9Sstevel@tonic-gate
1783d216dff5SRobert Mastors mutex_destroy(cp->rc_cbinfo.cb_lock);
1784d216dff5SRobert Mastors cv_destroy(cp->rc_cbinfo.cb_cv);
1785d216dff5SRobert Mastors cv_destroy(cp->rc_cbinfo.cb_cv_nullcaller);
1786d216dff5SRobert Mastors list_destroy(&cp->rc_openownerlist);
17877c478bd9Sstevel@tonic-gate
1788*f44e1126SVitaliy Gusev list_destroy(&cp->rc_sessions);
1789*f44e1126SVitaliy Gusev
17907c478bd9Sstevel@tonic-gate /* free callback info */
1791d216dff5SRobert Mastors rfs4_cbinfo_free(&cp->rc_cbinfo);
17927c478bd9Sstevel@tonic-gate
1793d216dff5SRobert Mastors if (cp->rc_cp_confirmed)
1794d216dff5SRobert Mastors rfs4_client_rele(cp->rc_cp_confirmed);
17957c478bd9Sstevel@tonic-gate
1796d216dff5SRobert Mastors if (cp->rc_ss_pn) {
1797cee86682Scalum /* check if the stable storage files need to be removed */
1798d216dff5SRobert Mastors if (cp->rc_ss_remove)
1799cee86682Scalum rfs4_dss_remove_cpleaf(cp);
1800d216dff5SRobert Mastors rfs4_ss_pnfree(cp->rc_ss_pn);
18017c478bd9Sstevel@tonic-gate }
18027c478bd9Sstevel@tonic-gate
18037c478bd9Sstevel@tonic-gate /* Free the client supplied client id */
1804d216dff5SRobert Mastors kmem_free(cp->rc_nfs_client.id_val, cp->rc_nfs_client.id_len);
18057c478bd9Sstevel@tonic-gate
1806d216dff5SRobert Mastors if (cp->rc_sysidt != LM_NOSYSID)
1807d216dff5SRobert Mastors lm_free_sysidt(cp->rc_sysidt);
1808*f44e1126SVitaliy Gusev
1809*f44e1126SVitaliy Gusev rfs4_free_cred_set(&cp->rc_cr_set);
18107c478bd9Sstevel@tonic-gate }
18117c478bd9Sstevel@tonic-gate
18127c478bd9Sstevel@tonic-gate static bool_t
rfs4_client_create(rfs4_entry_t u_entry,void * arg)18137c478bd9Sstevel@tonic-gate rfs4_client_create(rfs4_entry_t u_entry, void *arg)
18147c478bd9Sstevel@tonic-gate {
18157c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)u_entry;
18167c478bd9Sstevel@tonic-gate nfs_client_id4 *client = (nfs_client_id4 *)arg;
18172f172c55SRobert Thurlow struct sockaddr *ca;
18187c478bd9Sstevel@tonic-gate cid *cidp;
18197c478bd9Sstevel@tonic-gate scid_confirm_verf *scvp;
18200dfe541eSEvan Layton nfs4_srv_t *nsrv4;
18210dfe541eSEvan Layton
18220dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate /* Get a clientid to give to the client */
1825d216dff5SRobert Mastors cidp = (cid *)&cp->rc_clientid;
18260dfe541eSEvan Layton cidp->impl_id.start_time = nsrv4->rfs4_start_time;
1827d216dff5SRobert Mastors cidp->impl_id.c_id = (uint32_t)rfs4_dbe_getid(cp->rc_dbe);
18287c478bd9Sstevel@tonic-gate
18297c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, embed our nodeid */
18307c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED)
18317c478bd9Sstevel@tonic-gate embed_nodeid(cidp);
18327c478bd9Sstevel@tonic-gate
18337c478bd9Sstevel@tonic-gate /* Allocate and copy client's client id value */
1834d216dff5SRobert Mastors cp->rc_nfs_client.id_val = kmem_alloc(client->id_len, KM_SLEEP);
1835d216dff5SRobert Mastors cp->rc_nfs_client.id_len = client->id_len;
1836d216dff5SRobert Mastors bcopy(client->id_val, cp->rc_nfs_client.id_val, client->id_len);
1837d216dff5SRobert Mastors cp->rc_nfs_client.verifier = client->verifier;
18387c478bd9Sstevel@tonic-gate
18392f172c55SRobert Thurlow /* Copy client's IP address */
18402f172c55SRobert Thurlow ca = client->cl_addr;
18412f172c55SRobert Thurlow if (ca->sa_family == AF_INET)
18422f172c55SRobert Thurlow bcopy(ca, &cp->rc_addr, sizeof (struct sockaddr_in));
18432f172c55SRobert Thurlow else if (ca->sa_family == AF_INET6)
18442f172c55SRobert Thurlow bcopy(ca, &cp->rc_addr, sizeof (struct sockaddr_in6));
18452f172c55SRobert Thurlow cp->rc_nfs_client.cl_addr = (struct sockaddr *)&cp->rc_addr;
18462f172c55SRobert Thurlow
18477c478bd9Sstevel@tonic-gate /* Init the value for the SETCLIENTID_CONFIRM verifier */
1848d216dff5SRobert Mastors scvp = (scid_confirm_verf *)&cp->rc_confirm_verf;
18497c478bd9Sstevel@tonic-gate scvp->cv_impl.c_id = cidp->impl_id.c_id;
18507c478bd9Sstevel@tonic-gate scvp->cv_impl.gen_num = 0;
18517c478bd9Sstevel@tonic-gate
18527c478bd9Sstevel@tonic-gate /* An F_UNLKSYS has been done for this client */
1853d216dff5SRobert Mastors cp->rc_unlksys_completed = FALSE;
18547c478bd9Sstevel@tonic-gate
18557c478bd9Sstevel@tonic-gate /* We need the client to ack us */
1856d216dff5SRobert Mastors cp->rc_need_confirm = TRUE;
1857d216dff5SRobert Mastors cp->rc_cp_confirmed = NULL;
1858*f44e1126SVitaliy Gusev cp->rc_destroying = FALSE;
18597c478bd9Sstevel@tonic-gate
18607c478bd9Sstevel@tonic-gate /* TRUE all the time until the callback path actually fails */
1861d216dff5SRobert Mastors cp->rc_cbinfo.cb_notified_of_cb_path_down = TRUE;
18627c478bd9Sstevel@tonic-gate
18637c478bd9Sstevel@tonic-gate /* Initialize the access time to now */
1864d216dff5SRobert Mastors cp->rc_last_access = gethrestime_sec();
18657c478bd9Sstevel@tonic-gate
1866*f44e1126SVitaliy Gusev bzero(&cp->rc_cr_set, sizeof (cred_set_t));
18677c478bd9Sstevel@tonic-gate
1868d216dff5SRobert Mastors cp->rc_sysidt = LM_NOSYSID;
18697c478bd9Sstevel@tonic-gate
1870d216dff5SRobert Mastors list_create(&cp->rc_openownerlist, sizeof (rfs4_openowner_t),
1871d216dff5SRobert Mastors offsetof(rfs4_openowner_t, ro_node));
18727c478bd9Sstevel@tonic-gate
1873*f44e1126SVitaliy Gusev list_create(&cp->rc_sessions, sizeof (rfs4_session_t),
1874*f44e1126SVitaliy Gusev offsetof(rfs4_session_t, sn_node));
1875*f44e1126SVitaliy Gusev
18767c478bd9Sstevel@tonic-gate /* set up the callback control structure */
1877d216dff5SRobert Mastors cp->rc_cbinfo.cb_state = CB_UNINIT;
1878d216dff5SRobert Mastors mutex_init(cp->rc_cbinfo.cb_lock, NULL, MUTEX_DEFAULT, NULL);
1879d216dff5SRobert Mastors cv_init(cp->rc_cbinfo.cb_cv, NULL, CV_DEFAULT, NULL);
1880d216dff5SRobert Mastors cv_init(cp->rc_cbinfo.cb_cv_nullcaller, NULL, CV_DEFAULT, NULL);
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate /*
18837c478bd9Sstevel@tonic-gate * Associate the client_t with the current server instance.
18847c478bd9Sstevel@tonic-gate * The hold is solely to satisfy the calling requirement of
18857c478bd9Sstevel@tonic-gate * rfs4_servinst_assign(). In this case it's not strictly necessary.
18867c478bd9Sstevel@tonic-gate */
1887d216dff5SRobert Mastors rfs4_dbe_hold(cp->rc_dbe);
18880dfe541eSEvan Layton rfs4_servinst_assign(nsrv4, cp, nsrv4->nfs4_cur_servinst);
1889d216dff5SRobert Mastors rfs4_dbe_rele(cp->rc_dbe);
18907c478bd9Sstevel@tonic-gate
1891*f44e1126SVitaliy Gusev /*
1892*f44e1126SVitaliy Gusev * NFSv4.1: See rfc8881, Section 18.36.4, eir_sequenceid
1893*f44e1126SVitaliy Gusev * "Before the server replies to that EXCHANGE_ID
1894*f44e1126SVitaliy Gusev * operation, it initializes the client ID slot to be equal to
1895*f44e1126SVitaliy Gusev * eir_sequenceid - 1 (accounting for underflow), and records a
1896*f44e1126SVitaliy Gusev * contrived CREATE_SESSION result with a "cached" result of
1897*f44e1126SVitaliy Gusev * NFS4ERR_SEQ_MISORDERED."
1898*f44e1126SVitaliy Gusev */
1899*f44e1126SVitaliy Gusev cp->rc_contrived.xi_sid = 1;
1900*f44e1126SVitaliy Gusev cp->rc_contrived.cs_status = NFS4ERR_SEQ_MISORDERED;
1901*f44e1126SVitaliy Gusev
19027c478bd9Sstevel@tonic-gate return (TRUE);
19037c478bd9Sstevel@tonic-gate }
19047c478bd9Sstevel@tonic-gate
19057c478bd9Sstevel@tonic-gate /*
19067c478bd9Sstevel@tonic-gate * Caller wants to generate/update the setclientid_confirm verifier
19077c478bd9Sstevel@tonic-gate * associated with a client. This is done during the SETCLIENTID
19087c478bd9Sstevel@tonic-gate * processing.
19097c478bd9Sstevel@tonic-gate */
19107c478bd9Sstevel@tonic-gate void
rfs4_client_scv_next(rfs4_client_t * cp)19117c478bd9Sstevel@tonic-gate rfs4_client_scv_next(rfs4_client_t *cp)
19127c478bd9Sstevel@tonic-gate {
19137c478bd9Sstevel@tonic-gate scid_confirm_verf *scvp;
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gate /* Init the value for the SETCLIENTID_CONFIRM verifier */
1916d216dff5SRobert Mastors scvp = (scid_confirm_verf *)&cp->rc_confirm_verf;
19177c478bd9Sstevel@tonic-gate scvp->cv_impl.gen_num++;
19187c478bd9Sstevel@tonic-gate }
19197c478bd9Sstevel@tonic-gate
19207c478bd9Sstevel@tonic-gate void
rfs4_client_rele(rfs4_client_t * cp)19217c478bd9Sstevel@tonic-gate rfs4_client_rele(rfs4_client_t *cp)
19227c478bd9Sstevel@tonic-gate {
1923d216dff5SRobert Mastors rfs4_dbe_rele(cp->rc_dbe);
19247c478bd9Sstevel@tonic-gate }
19257c478bd9Sstevel@tonic-gate
19267c478bd9Sstevel@tonic-gate rfs4_client_t *
rfs4_findclient(nfs_client_id4 * client,bool_t * create,rfs4_client_t * oldcp)19277c478bd9Sstevel@tonic-gate rfs4_findclient(nfs_client_id4 *client, bool_t *create, rfs4_client_t *oldcp)
19287c478bd9Sstevel@tonic-gate {
19297c478bd9Sstevel@tonic-gate rfs4_client_t *cp;
19300dfe541eSEvan Layton nfs4_srv_t *nsrv4;
19310dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate
19347c478bd9Sstevel@tonic-gate if (oldcp) {
19350dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_WRITER);
1936d216dff5SRobert Mastors rfs4_dbe_hide(oldcp->rc_dbe);
19377c478bd9Sstevel@tonic-gate } else {
19380dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_READER);
19397c478bd9Sstevel@tonic-gate }
19407c478bd9Sstevel@tonic-gate
19410dfe541eSEvan Layton cp = (rfs4_client_t *)rfs4_dbsearch(nsrv4->rfs4_nfsclnt_idx, client,
1942ed57cab9Srg create, (void *)client, RFS4_DBS_VALID);
19437c478bd9Sstevel@tonic-gate
19447c478bd9Sstevel@tonic-gate if (oldcp)
1945d216dff5SRobert Mastors rfs4_dbe_unhide(oldcp->rc_dbe);
19467c478bd9Sstevel@tonic-gate
19470dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
19487c478bd9Sstevel@tonic-gate
19497c478bd9Sstevel@tonic-gate return (cp);
19507c478bd9Sstevel@tonic-gate }
19517c478bd9Sstevel@tonic-gate
19527c478bd9Sstevel@tonic-gate rfs4_client_t *
rfs4_findclient_by_id(clientid4 clientid,bool_t find_unconfirmed)19537c478bd9Sstevel@tonic-gate rfs4_findclient_by_id(clientid4 clientid, bool_t find_unconfirmed)
19547c478bd9Sstevel@tonic-gate {
19557c478bd9Sstevel@tonic-gate rfs4_client_t *cp;
19567c478bd9Sstevel@tonic-gate bool_t create = FALSE;
19577c478bd9Sstevel@tonic-gate cid *cidp = (cid *)&clientid;
19580dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
19597c478bd9Sstevel@tonic-gate
19607c478bd9Sstevel@tonic-gate /* If we're a cluster and the nodeid isn't right, short-circuit */
19617c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED && foreign_clientid(cidp))
19627c478bd9Sstevel@tonic-gate return (NULL);
19637c478bd9Sstevel@tonic-gate
19640dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_READER);
19657c478bd9Sstevel@tonic-gate
19660dfe541eSEvan Layton cp = (rfs4_client_t *)rfs4_dbsearch(nsrv4->rfs4_clientid_idx, &clientid,
1967ed57cab9Srg &create, NULL, RFS4_DBS_VALID);
19687c478bd9Sstevel@tonic-gate
19690dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
19707c478bd9Sstevel@tonic-gate
1971d216dff5SRobert Mastors if (cp && cp->rc_need_confirm && find_unconfirmed == FALSE) {
19727c478bd9Sstevel@tonic-gate rfs4_client_rele(cp);
19737c478bd9Sstevel@tonic-gate return (NULL);
19747c478bd9Sstevel@tonic-gate } else {
19757c478bd9Sstevel@tonic-gate return (cp);
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate }
19787c478bd9Sstevel@tonic-gate
19792f172c55SRobert Thurlow static uint32_t
clntip_hash(void * key)19802f172c55SRobert Thurlow clntip_hash(void *key)
19812f172c55SRobert Thurlow {
19822f172c55SRobert Thurlow struct sockaddr *addr = key;
19832f172c55SRobert Thurlow int i, len = 0;
19842f172c55SRobert Thurlow uint32_t hash = 0;
1985fab83d6aSRobert Thurlow char *ptr;
1986fab83d6aSRobert Thurlow
1987fab83d6aSRobert Thurlow if (addr->sa_family == AF_INET) {
1988fab83d6aSRobert Thurlow struct sockaddr_in *a = (struct sockaddr_in *)addr;
1989fab83d6aSRobert Thurlow len = sizeof (struct in_addr);
1990fab83d6aSRobert Thurlow ptr = (char *)&a->sin_addr;
1991fab83d6aSRobert Thurlow } else if (addr->sa_family == AF_INET6) {
1992fab83d6aSRobert Thurlow struct sockaddr_in6 *a = (struct sockaddr_in6 *)addr;
1993fab83d6aSRobert Thurlow len = sizeof (struct in6_addr);
1994fab83d6aSRobert Thurlow ptr = (char *)&a->sin6_addr;
1995fab83d6aSRobert Thurlow } else
1996fab83d6aSRobert Thurlow return (0);
19972f172c55SRobert Thurlow
19982f172c55SRobert Thurlow for (i = 0; i < len; i++) {
19992f172c55SRobert Thurlow hash <<= 1;
2000fab83d6aSRobert Thurlow hash += (uint_t)ptr[i];
20012f172c55SRobert Thurlow }
20022f172c55SRobert Thurlow return (hash);
20032f172c55SRobert Thurlow }
20042f172c55SRobert Thurlow
20052f172c55SRobert Thurlow static bool_t
clntip_compare(rfs4_entry_t entry,void * key)20062f172c55SRobert Thurlow clntip_compare(rfs4_entry_t entry, void *key)
20072f172c55SRobert Thurlow {
20082f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)entry;
20092f172c55SRobert Thurlow struct sockaddr *addr = key;
20102f172c55SRobert Thurlow int len = 0;
2011fab83d6aSRobert Thurlow char *p1, *p2;
2012fab83d6aSRobert Thurlow
2013fab83d6aSRobert Thurlow if (addr->sa_family == AF_INET) {
2014fab83d6aSRobert Thurlow struct sockaddr_in *a1 = (struct sockaddr_in *)&cp->ri_addr;
2015fab83d6aSRobert Thurlow struct sockaddr_in *a2 = (struct sockaddr_in *)addr;
2016fab83d6aSRobert Thurlow len = sizeof (struct in_addr);
2017fab83d6aSRobert Thurlow p1 = (char *)&a1->sin_addr;
2018fab83d6aSRobert Thurlow p2 = (char *)&a2->sin_addr;
2019fab83d6aSRobert Thurlow } else if (addr->sa_family == AF_INET6) {
2020fab83d6aSRobert Thurlow struct sockaddr_in6 *a1 = (struct sockaddr_in6 *)&cp->ri_addr;
2021fab83d6aSRobert Thurlow struct sockaddr_in6 *a2 = (struct sockaddr_in6 *)addr;
2022fab83d6aSRobert Thurlow len = sizeof (struct in6_addr);
2023fab83d6aSRobert Thurlow p1 = (char *)&a1->sin6_addr;
2024fab83d6aSRobert Thurlow p2 = (char *)&a2->sin6_addr;
2025fab83d6aSRobert Thurlow } else
20262f172c55SRobert Thurlow return (0);
20272f172c55SRobert Thurlow
2028fab83d6aSRobert Thurlow return (bcmp(p1, p2, len) == 0);
20292f172c55SRobert Thurlow }
20302f172c55SRobert Thurlow
20312f172c55SRobert Thurlow static void *
clntip_mkkey(rfs4_entry_t entry)20322f172c55SRobert Thurlow clntip_mkkey(rfs4_entry_t entry)
20332f172c55SRobert Thurlow {
20342f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)entry;
20352f172c55SRobert Thurlow
20362f172c55SRobert Thurlow return (&cp->ri_addr);
20372f172c55SRobert Thurlow }
20382f172c55SRobert Thurlow
20392f172c55SRobert Thurlow static bool_t
rfs4_clntip_expiry(rfs4_entry_t u_entry)20402f172c55SRobert Thurlow rfs4_clntip_expiry(rfs4_entry_t u_entry)
20412f172c55SRobert Thurlow {
20422f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)u_entry;
20432f172c55SRobert Thurlow
20442f172c55SRobert Thurlow if (rfs4_dbe_is_invalid(cp->ri_dbe))
20452f172c55SRobert Thurlow return (TRUE);
20462f172c55SRobert Thurlow return (FALSE);
20472f172c55SRobert Thurlow }
20482f172c55SRobert Thurlow
20492f172c55SRobert Thurlow /* ARGSUSED */
20502f172c55SRobert Thurlow static void
rfs4_clntip_destroy(rfs4_entry_t u_entry)20512f172c55SRobert Thurlow rfs4_clntip_destroy(rfs4_entry_t u_entry)
20522f172c55SRobert Thurlow {
20532f172c55SRobert Thurlow }
20542f172c55SRobert Thurlow
20552f172c55SRobert Thurlow static bool_t
rfs4_clntip_create(rfs4_entry_t u_entry,void * arg)20562f172c55SRobert Thurlow rfs4_clntip_create(rfs4_entry_t u_entry, void *arg)
20572f172c55SRobert Thurlow {
20582f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)u_entry;
20592f172c55SRobert Thurlow struct sockaddr *ca = (struct sockaddr *)arg;
20602f172c55SRobert Thurlow
20612f172c55SRobert Thurlow /* Copy client's IP address */
20622f172c55SRobert Thurlow if (ca->sa_family == AF_INET)
20632f172c55SRobert Thurlow bcopy(ca, &cp->ri_addr, sizeof (struct sockaddr_in));
20642f172c55SRobert Thurlow else if (ca->sa_family == AF_INET6)
20652f172c55SRobert Thurlow bcopy(ca, &cp->ri_addr, sizeof (struct sockaddr_in6));
20662f172c55SRobert Thurlow else
20672f172c55SRobert Thurlow return (FALSE);
20682f172c55SRobert Thurlow cp->ri_no_referrals = 1;
20692f172c55SRobert Thurlow
20702f172c55SRobert Thurlow return (TRUE);
20712f172c55SRobert Thurlow }
20722f172c55SRobert Thurlow
20732f172c55SRobert Thurlow rfs4_clntip_t *
rfs4_find_clntip(struct sockaddr * addr,bool_t * create)20742f172c55SRobert Thurlow rfs4_find_clntip(struct sockaddr *addr, bool_t *create)
20752f172c55SRobert Thurlow {
20762f172c55SRobert Thurlow rfs4_clntip_t *cp;
20770dfe541eSEvan Layton nfs4_srv_t *nsrv4;
20782f172c55SRobert Thurlow
20790dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
20802f172c55SRobert Thurlow
20810dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_READER);
20820dfe541eSEvan Layton
20830dfe541eSEvan Layton cp = (rfs4_clntip_t *)rfs4_dbsearch(nsrv4->rfs4_clntip_idx, addr,
20842f172c55SRobert Thurlow create, addr, RFS4_DBS_VALID);
20852f172c55SRobert Thurlow
20860dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
20872f172c55SRobert Thurlow
20882f172c55SRobert Thurlow return (cp);
20892f172c55SRobert Thurlow }
20902f172c55SRobert Thurlow
20912f172c55SRobert Thurlow void
rfs4_invalidate_clntip(struct sockaddr * addr)20922f172c55SRobert Thurlow rfs4_invalidate_clntip(struct sockaddr *addr)
20932f172c55SRobert Thurlow {
20942f172c55SRobert Thurlow rfs4_clntip_t *cp;
20952f172c55SRobert Thurlow bool_t create = FALSE;
20960dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
20972f172c55SRobert Thurlow
20980dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_READER);
20992f172c55SRobert Thurlow
21000dfe541eSEvan Layton cp = (rfs4_clntip_t *)rfs4_dbsearch(nsrv4->rfs4_clntip_idx, addr,
21012f172c55SRobert Thurlow &create, NULL, RFS4_DBS_VALID);
21022f172c55SRobert Thurlow if (cp == NULL) {
21030dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
21042f172c55SRobert Thurlow return;
21052f172c55SRobert Thurlow }
21062f172c55SRobert Thurlow rfs4_dbe_invalidate(cp->ri_dbe);
21072f172c55SRobert Thurlow rfs4_dbe_rele(cp->ri_dbe);
21082f172c55SRobert Thurlow
21090dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
21102f172c55SRobert Thurlow }
21112f172c55SRobert Thurlow
21127c478bd9Sstevel@tonic-gate bool_t
rfs4_lease_expired(rfs4_client_t * cp)21137c478bd9Sstevel@tonic-gate rfs4_lease_expired(rfs4_client_t *cp)
21147c478bd9Sstevel@tonic-gate {
21157c478bd9Sstevel@tonic-gate bool_t rc;
21167c478bd9Sstevel@tonic-gate
2117d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe);
21187c478bd9Sstevel@tonic-gate
21197c478bd9Sstevel@tonic-gate /*
21207c478bd9Sstevel@tonic-gate * If the admin has executed clear_locks for this
21217c478bd9Sstevel@tonic-gate * client id, force expire will be set, so no need
21227c478bd9Sstevel@tonic-gate * to calculate anything because it's "outa here".
21237c478bd9Sstevel@tonic-gate */
2124d216dff5SRobert Mastors if (cp->rc_forced_expire) {
21257c478bd9Sstevel@tonic-gate rc = TRUE;
21267c478bd9Sstevel@tonic-gate } else {
2127d216dff5SRobert Mastors rc = (gethrestime_sec() - cp->rc_last_access > rfs4_lease_time);
21287c478bd9Sstevel@tonic-gate }
21297c478bd9Sstevel@tonic-gate
21307c478bd9Sstevel@tonic-gate /*
21317c478bd9Sstevel@tonic-gate * If the lease has expired we will also want
21327c478bd9Sstevel@tonic-gate * to remove any stable storage state data. So
21337c478bd9Sstevel@tonic-gate * mark the client id accordingly.
21347c478bd9Sstevel@tonic-gate */
2135d216dff5SRobert Mastors if (!cp->rc_ss_remove)
2136d216dff5SRobert Mastors cp->rc_ss_remove = (rc == TRUE);
21377c478bd9Sstevel@tonic-gate
2138d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe);
21397c478bd9Sstevel@tonic-gate
21407c478bd9Sstevel@tonic-gate return (rc);
21417c478bd9Sstevel@tonic-gate }
21427c478bd9Sstevel@tonic-gate
21437c478bd9Sstevel@tonic-gate void
rfs4_update_lease(rfs4_client_t * cp)21447c478bd9Sstevel@tonic-gate rfs4_update_lease(rfs4_client_t *cp)
21457c478bd9Sstevel@tonic-gate {
2146d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe);
2147d216dff5SRobert Mastors if (!cp->rc_forced_expire)
2148d216dff5SRobert Mastors cp->rc_last_access = gethrestime_sec();
2149d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe);
21507c478bd9Sstevel@tonic-gate }
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate static bool_t
EQOPENOWNER(open_owner4 * a,open_owner4 * b)21547c478bd9Sstevel@tonic-gate EQOPENOWNER(open_owner4 *a, open_owner4 *b)
21557c478bd9Sstevel@tonic-gate {
21567c478bd9Sstevel@tonic-gate bool_t rc;
21577c478bd9Sstevel@tonic-gate
21587c478bd9Sstevel@tonic-gate if (a->clientid != b->clientid)
21597c478bd9Sstevel@tonic-gate return (FALSE);
21607c478bd9Sstevel@tonic-gate
21617c478bd9Sstevel@tonic-gate if (a->owner_len != b->owner_len)
21627c478bd9Sstevel@tonic-gate return (FALSE);
21637c478bd9Sstevel@tonic-gate
21647c478bd9Sstevel@tonic-gate rc = (bcmp(a->owner_val, b->owner_val, a->owner_len) == 0);
21657c478bd9Sstevel@tonic-gate
21667c478bd9Sstevel@tonic-gate return (rc);
21677c478bd9Sstevel@tonic-gate }
21687c478bd9Sstevel@tonic-gate
21697c478bd9Sstevel@tonic-gate static uint_t
openowner_hash(void * key)21707c478bd9Sstevel@tonic-gate openowner_hash(void *key)
21717c478bd9Sstevel@tonic-gate {
21727c478bd9Sstevel@tonic-gate int i;
21737c478bd9Sstevel@tonic-gate open_owner4 *openowner = key;
21747c478bd9Sstevel@tonic-gate uint_t hash = 0;
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate for (i = 0; i < openowner->owner_len; i++) {
21777c478bd9Sstevel@tonic-gate hash <<= 4;
21787c478bd9Sstevel@tonic-gate hash += (uint_t)openowner->owner_val[i];
21797c478bd9Sstevel@tonic-gate }
21807c478bd9Sstevel@tonic-gate hash += (uint_t)openowner->clientid;
21817c478bd9Sstevel@tonic-gate hash |= (openowner->clientid >> 32);
21827c478bd9Sstevel@tonic-gate
21837c478bd9Sstevel@tonic-gate return (hash);
21847c478bd9Sstevel@tonic-gate }
21857c478bd9Sstevel@tonic-gate
21867c478bd9Sstevel@tonic-gate static bool_t
openowner_compare(rfs4_entry_t u_entry,void * key)21877c478bd9Sstevel@tonic-gate openowner_compare(rfs4_entry_t u_entry, void *key)
21887c478bd9Sstevel@tonic-gate {
2189d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry;
21907c478bd9Sstevel@tonic-gate open_owner4 *arg = key;
21917c478bd9Sstevel@tonic-gate
2192d216dff5SRobert Mastors return (EQOPENOWNER(&oo->ro_owner, arg));
21937c478bd9Sstevel@tonic-gate }
21947c478bd9Sstevel@tonic-gate
21957c478bd9Sstevel@tonic-gate void *
openowner_mkkey(rfs4_entry_t u_entry)21967c478bd9Sstevel@tonic-gate openowner_mkkey(rfs4_entry_t u_entry)
21977c478bd9Sstevel@tonic-gate {
2198d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry;
21997c478bd9Sstevel@tonic-gate
2200d216dff5SRobert Mastors return (&oo->ro_owner);
22017c478bd9Sstevel@tonic-gate }
22027c478bd9Sstevel@tonic-gate
2203afb25078SVitaliy Gusev /* ARGSUSED */
22047c478bd9Sstevel@tonic-gate static bool_t
rfs4_openowner_expiry(rfs4_entry_t u_entry)22057c478bd9Sstevel@tonic-gate rfs4_openowner_expiry(rfs4_entry_t u_entry)
22067c478bd9Sstevel@tonic-gate {
2207afb25078SVitaliy Gusev /* openstateid held us and did all needed delay */
2208afb25078SVitaliy Gusev return (TRUE);
22097c478bd9Sstevel@tonic-gate }
22107c478bd9Sstevel@tonic-gate
22117c478bd9Sstevel@tonic-gate static void
rfs4_openowner_destroy(rfs4_entry_t u_entry)22127c478bd9Sstevel@tonic-gate rfs4_openowner_destroy(rfs4_entry_t u_entry)
22137c478bd9Sstevel@tonic-gate {
2214d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry;
22157c478bd9Sstevel@tonic-gate
22167c478bd9Sstevel@tonic-gate /* Remove open owner from client's lists of open owners */
2217d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_client->rc_dbe);
2218d216dff5SRobert Mastors list_remove(&oo->ro_client->rc_openownerlist, oo);
2219d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_client->rc_dbe);
22207c478bd9Sstevel@tonic-gate
22217c478bd9Sstevel@tonic-gate /* One less reference to the client */
2222d216dff5SRobert Mastors rfs4_client_rele(oo->ro_client);
2223d216dff5SRobert Mastors oo->ro_client = NULL;
22247c478bd9Sstevel@tonic-gate
22257c478bd9Sstevel@tonic-gate /* Free the last reply for this lock owner */
2226d216dff5SRobert Mastors rfs4_free_reply(&oo->ro_reply);
22277c478bd9Sstevel@tonic-gate
2228d216dff5SRobert Mastors if (oo->ro_reply_fh.nfs_fh4_val) {
2229d216dff5SRobert Mastors kmem_free(oo->ro_reply_fh.nfs_fh4_val,
2230d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len);
2231d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = NULL;
2232d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len = 0;
22337c478bd9Sstevel@tonic-gate }
22347c478bd9Sstevel@tonic-gate
2235d216dff5SRobert Mastors rfs4_sw_destroy(&oo->ro_sw);
2236d216dff5SRobert Mastors list_destroy(&oo->ro_statelist);
2237d216dff5SRobert Mastors
22387c478bd9Sstevel@tonic-gate /* Free the lock owner id */
2239d216dff5SRobert Mastors kmem_free(oo->ro_owner.owner_val, oo->ro_owner.owner_len);
22407c478bd9Sstevel@tonic-gate }
22417c478bd9Sstevel@tonic-gate
22427c478bd9Sstevel@tonic-gate void
rfs4_openowner_rele(rfs4_openowner_t * oo)2243d216dff5SRobert Mastors rfs4_openowner_rele(rfs4_openowner_t *oo)
22447c478bd9Sstevel@tonic-gate {
2245d216dff5SRobert Mastors rfs4_dbe_rele(oo->ro_dbe);
22467c478bd9Sstevel@tonic-gate }
22477c478bd9Sstevel@tonic-gate
22487c478bd9Sstevel@tonic-gate static bool_t
rfs4_openowner_create(rfs4_entry_t u_entry,void * arg)22497c478bd9Sstevel@tonic-gate rfs4_openowner_create(rfs4_entry_t u_entry, void *arg)
22507c478bd9Sstevel@tonic-gate {
2251d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry;
22527c478bd9Sstevel@tonic-gate rfs4_openowner_t *argp = (rfs4_openowner_t *)arg;
2253d216dff5SRobert Mastors open_owner4 *openowner = &argp->ro_owner;
2254d216dff5SRobert Mastors seqid4 seqid = argp->ro_open_seqid;
22557c478bd9Sstevel@tonic-gate rfs4_client_t *cp;
22567c478bd9Sstevel@tonic-gate bool_t create = FALSE;
22570dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
22587c478bd9Sstevel@tonic-gate
22590dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_READER);
22607c478bd9Sstevel@tonic-gate
22610dfe541eSEvan Layton cp = (rfs4_client_t *)rfs4_dbsearch(nsrv4->rfs4_clientid_idx,
2262ed57cab9Srg &openowner->clientid,
2263ed57cab9Srg &create, NULL, RFS4_DBS_VALID);
22647c478bd9Sstevel@tonic-gate
22650dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
22667c478bd9Sstevel@tonic-gate
22677c478bd9Sstevel@tonic-gate if (cp == NULL)
22687c478bd9Sstevel@tonic-gate return (FALSE);
22697c478bd9Sstevel@tonic-gate
2270d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len = 0;
2271d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = NULL;
22727c478bd9Sstevel@tonic-gate
2273d216dff5SRobert Mastors oo->ro_owner.clientid = openowner->clientid;
2274d216dff5SRobert Mastors oo->ro_owner.owner_val =
2275ed57cab9Srg kmem_alloc(openowner->owner_len, KM_SLEEP);
2276ed57cab9Srg
22777c478bd9Sstevel@tonic-gate bcopy(openowner->owner_val,
2278d216dff5SRobert Mastors oo->ro_owner.owner_val, openowner->owner_len);
22797c478bd9Sstevel@tonic-gate
2280d216dff5SRobert Mastors oo->ro_owner.owner_len = openowner->owner_len;
22817c478bd9Sstevel@tonic-gate
2282d216dff5SRobert Mastors oo->ro_need_confirm = TRUE;
22837c478bd9Sstevel@tonic-gate
2284d216dff5SRobert Mastors rfs4_sw_init(&oo->ro_sw);
22857c478bd9Sstevel@tonic-gate
2286d216dff5SRobert Mastors oo->ro_open_seqid = seqid;
2287d216dff5SRobert Mastors bzero(&oo->ro_reply, sizeof (nfs_resop4));
2288d216dff5SRobert Mastors oo->ro_client = cp;
22897c478bd9Sstevel@tonic-gate
2290d216dff5SRobert Mastors list_create(&oo->ro_statelist, sizeof (rfs4_state_t),
2291d216dff5SRobert Mastors offsetof(rfs4_state_t, rs_node));
22927c478bd9Sstevel@tonic-gate
2293d216dff5SRobert Mastors /* Insert openowner into client's open owner list */
2294d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe);
2295d216dff5SRobert Mastors list_insert_tail(&cp->rc_openownerlist, oo);
2296d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe);
22977c478bd9Sstevel@tonic-gate
22987c478bd9Sstevel@tonic-gate return (TRUE);
22997c478bd9Sstevel@tonic-gate }
23007c478bd9Sstevel@tonic-gate
23017c478bd9Sstevel@tonic-gate rfs4_openowner_t *
rfs4_findopenowner(open_owner4 * openowner,bool_t * create,seqid4 seqid)23027c478bd9Sstevel@tonic-gate rfs4_findopenowner(open_owner4 *openowner, bool_t *create, seqid4 seqid)
23037c478bd9Sstevel@tonic-gate {
2304d216dff5SRobert Mastors rfs4_openowner_t *oo;
23057c478bd9Sstevel@tonic-gate rfs4_openowner_t arg;
23060dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
23077c478bd9Sstevel@tonic-gate
2308d216dff5SRobert Mastors arg.ro_owner = *openowner;
2309d216dff5SRobert Mastors arg.ro_open_seqid = seqid;
23100dfe541eSEvan Layton /* CSTYLED */
23110dfe541eSEvan Layton oo = (rfs4_openowner_t *)rfs4_dbsearch(nsrv4->rfs4_openowner_idx, openowner,
2312ed57cab9Srg create, &arg, RFS4_DBS_VALID);
23137c478bd9Sstevel@tonic-gate
2314d216dff5SRobert Mastors return (oo);
23157c478bd9Sstevel@tonic-gate }
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate void
rfs4_update_open_sequence(rfs4_openowner_t * oo)2318d216dff5SRobert Mastors rfs4_update_open_sequence(rfs4_openowner_t *oo)
23197c478bd9Sstevel@tonic-gate {
23207c478bd9Sstevel@tonic-gate
2321d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe);
23227c478bd9Sstevel@tonic-gate
2323d216dff5SRobert Mastors oo->ro_open_seqid++;
23247c478bd9Sstevel@tonic-gate
2325d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe);
23267c478bd9Sstevel@tonic-gate }
23277c478bd9Sstevel@tonic-gate
23287c478bd9Sstevel@tonic-gate void
rfs4_update_open_resp(rfs4_openowner_t * oo,nfs_resop4 * resp,nfs_fh4 * fh)2329d216dff5SRobert Mastors rfs4_update_open_resp(rfs4_openowner_t *oo, nfs_resop4 *resp, nfs_fh4 *fh)
23307c478bd9Sstevel@tonic-gate {
23317c478bd9Sstevel@tonic-gate
2332d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe);
23337c478bd9Sstevel@tonic-gate
2334d216dff5SRobert Mastors rfs4_free_reply(&oo->ro_reply);
23357c478bd9Sstevel@tonic-gate
2336d216dff5SRobert Mastors rfs4_copy_reply(&oo->ro_reply, resp);
23377c478bd9Sstevel@tonic-gate
23387c478bd9Sstevel@tonic-gate /* Save the filehandle if provided and free if not used */
23397c478bd9Sstevel@tonic-gate if (resp->nfs_resop4_u.opopen.status == NFS4_OK &&
23407c478bd9Sstevel@tonic-gate fh && fh->nfs_fh4_len) {
2341d216dff5SRobert Mastors if (oo->ro_reply_fh.nfs_fh4_val == NULL)
2342d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val =
2343ed57cab9Srg kmem_alloc(fh->nfs_fh4_len, KM_SLEEP);
2344d216dff5SRobert Mastors nfs_fh4_copy(fh, &oo->ro_reply_fh);
23457c478bd9Sstevel@tonic-gate } else {
2346d216dff5SRobert Mastors if (oo->ro_reply_fh.nfs_fh4_val) {
2347d216dff5SRobert Mastors kmem_free(oo->ro_reply_fh.nfs_fh4_val,
2348d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len);
2349d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = NULL;
2350d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len = 0;
23517c478bd9Sstevel@tonic-gate }
23527c478bd9Sstevel@tonic-gate }
23537c478bd9Sstevel@tonic-gate
2354d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe);
23557c478bd9Sstevel@tonic-gate }
23567c478bd9Sstevel@tonic-gate
23577c478bd9Sstevel@tonic-gate static bool_t
lockowner_compare(rfs4_entry_t u_entry,void * key)23587c478bd9Sstevel@tonic-gate lockowner_compare(rfs4_entry_t u_entry, void *key)
23597c478bd9Sstevel@tonic-gate {
23607c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry;
23617c478bd9Sstevel@tonic-gate lock_owner4 *b = (lock_owner4 *)key;
23627c478bd9Sstevel@tonic-gate
2363d216dff5SRobert Mastors if (lo->rl_owner.clientid != b->clientid)
23647c478bd9Sstevel@tonic-gate return (FALSE);
23657c478bd9Sstevel@tonic-gate
2366d216dff5SRobert Mastors if (lo->rl_owner.owner_len != b->owner_len)
23677c478bd9Sstevel@tonic-gate return (FALSE);
23687c478bd9Sstevel@tonic-gate
2369d216dff5SRobert Mastors return (bcmp(lo->rl_owner.owner_val, b->owner_val,
2370d216dff5SRobert Mastors lo->rl_owner.owner_len) == 0);
23717c478bd9Sstevel@tonic-gate }
23727c478bd9Sstevel@tonic-gate
23737c478bd9Sstevel@tonic-gate void *
lockowner_mkkey(rfs4_entry_t u_entry)23747c478bd9Sstevel@tonic-gate lockowner_mkkey(rfs4_entry_t u_entry)
23757c478bd9Sstevel@tonic-gate {
23767c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry;
23777c478bd9Sstevel@tonic-gate
2378d216dff5SRobert Mastors return (&lo->rl_owner);
23797c478bd9Sstevel@tonic-gate }
23807c478bd9Sstevel@tonic-gate
23817c478bd9Sstevel@tonic-gate static uint32_t
lockowner_hash(void * key)23827c478bd9Sstevel@tonic-gate lockowner_hash(void *key)
23837c478bd9Sstevel@tonic-gate {
23847c478bd9Sstevel@tonic-gate int i;
23857c478bd9Sstevel@tonic-gate lock_owner4 *lockowner = key;
23867c478bd9Sstevel@tonic-gate uint_t hash = 0;
23877c478bd9Sstevel@tonic-gate
23887c478bd9Sstevel@tonic-gate for (i = 0; i < lockowner->owner_len; i++) {
23897c478bd9Sstevel@tonic-gate hash <<= 4;
23907c478bd9Sstevel@tonic-gate hash += (uint_t)lockowner->owner_val[i];
23917c478bd9Sstevel@tonic-gate }
23927c478bd9Sstevel@tonic-gate hash += (uint_t)lockowner->clientid;
23937c478bd9Sstevel@tonic-gate hash |= (lockowner->clientid >> 32);
23947c478bd9Sstevel@tonic-gate
23957c478bd9Sstevel@tonic-gate return (hash);
23967c478bd9Sstevel@tonic-gate }
23977c478bd9Sstevel@tonic-gate
23987c478bd9Sstevel@tonic-gate static uint32_t
pid_hash(void * key)23997c478bd9Sstevel@tonic-gate pid_hash(void *key)
24007c478bd9Sstevel@tonic-gate {
24017c478bd9Sstevel@tonic-gate return ((uint32_t)(uintptr_t)key);
24027c478bd9Sstevel@tonic-gate }
24037c478bd9Sstevel@tonic-gate
24047c478bd9Sstevel@tonic-gate static void *
pid_mkkey(rfs4_entry_t u_entry)24057c478bd9Sstevel@tonic-gate pid_mkkey(rfs4_entry_t u_entry)
24067c478bd9Sstevel@tonic-gate {
24077c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry;
24087c478bd9Sstevel@tonic-gate
2409d216dff5SRobert Mastors return ((void *)(uintptr_t)lo->rl_pid);
24107c478bd9Sstevel@tonic-gate }
24117c478bd9Sstevel@tonic-gate
24127c478bd9Sstevel@tonic-gate static bool_t
pid_compare(rfs4_entry_t u_entry,void * key)24137c478bd9Sstevel@tonic-gate pid_compare(rfs4_entry_t u_entry, void *key)
24147c478bd9Sstevel@tonic-gate {
24157c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry;
24167c478bd9Sstevel@tonic-gate
2417d216dff5SRobert Mastors return (lo->rl_pid == (pid_t)(uintptr_t)key);
24187c478bd9Sstevel@tonic-gate }
24197c478bd9Sstevel@tonic-gate
24207c478bd9Sstevel@tonic-gate static void
rfs4_lockowner_destroy(rfs4_entry_t u_entry)24217c478bd9Sstevel@tonic-gate rfs4_lockowner_destroy(rfs4_entry_t u_entry)
24227c478bd9Sstevel@tonic-gate {
24237c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry;
24247c478bd9Sstevel@tonic-gate
24257c478bd9Sstevel@tonic-gate /* Free the lock owner id */
2426d216dff5SRobert Mastors kmem_free(lo->rl_owner.owner_val, lo->rl_owner.owner_len);
2427d216dff5SRobert Mastors rfs4_client_rele(lo->rl_client);
24287c478bd9Sstevel@tonic-gate }
24297c478bd9Sstevel@tonic-gate
24307c478bd9Sstevel@tonic-gate void
rfs4_lockowner_rele(rfs4_lockowner_t * lo)24317c478bd9Sstevel@tonic-gate rfs4_lockowner_rele(rfs4_lockowner_t *lo)
24327c478bd9Sstevel@tonic-gate {
2433d216dff5SRobert Mastors rfs4_dbe_rele(lo->rl_dbe);
24347c478bd9Sstevel@tonic-gate }
24357c478bd9Sstevel@tonic-gate
24367c478bd9Sstevel@tonic-gate /* ARGSUSED */
24377c478bd9Sstevel@tonic-gate static bool_t
rfs4_lockowner_expiry(rfs4_entry_t u_entry)24387c478bd9Sstevel@tonic-gate rfs4_lockowner_expiry(rfs4_entry_t u_entry)
24397c478bd9Sstevel@tonic-gate {
24407c478bd9Sstevel@tonic-gate /*
24417c478bd9Sstevel@tonic-gate * Since expiry is called with no other references on
24427c478bd9Sstevel@tonic-gate * this struct, go ahead and have it removed.
24437c478bd9Sstevel@tonic-gate */
24447c478bd9Sstevel@tonic-gate return (TRUE);
24457c478bd9Sstevel@tonic-gate }
24467c478bd9Sstevel@tonic-gate
24477c478bd9Sstevel@tonic-gate static bool_t
rfs4_lockowner_create(rfs4_entry_t u_entry,void * arg)24487c478bd9Sstevel@tonic-gate rfs4_lockowner_create(rfs4_entry_t u_entry, void *arg)
24497c478bd9Sstevel@tonic-gate {
24507c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry;
24517c478bd9Sstevel@tonic-gate lock_owner4 *lockowner = (lock_owner4 *)arg;
24527c478bd9Sstevel@tonic-gate rfs4_client_t *cp;
24537c478bd9Sstevel@tonic-gate bool_t create = FALSE;
24540dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
24557c478bd9Sstevel@tonic-gate
24560dfe541eSEvan Layton rw_enter(&nsrv4->rfs4_findclient_lock, RW_READER);
24577c478bd9Sstevel@tonic-gate
24580dfe541eSEvan Layton cp = (rfs4_client_t *)rfs4_dbsearch(nsrv4->rfs4_clientid_idx,
2459ed57cab9Srg &lockowner->clientid,
2460ed57cab9Srg &create, NULL, RFS4_DBS_VALID);
24617c478bd9Sstevel@tonic-gate
24620dfe541eSEvan Layton rw_exit(&nsrv4->rfs4_findclient_lock);
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate if (cp == NULL)
24657c478bd9Sstevel@tonic-gate return (FALSE);
24667c478bd9Sstevel@tonic-gate
24677c478bd9Sstevel@tonic-gate /* Reference client */
2468d216dff5SRobert Mastors lo->rl_client = cp;
2469d216dff5SRobert Mastors lo->rl_owner.clientid = lockowner->clientid;
2470d216dff5SRobert Mastors lo->rl_owner.owner_val = kmem_alloc(lockowner->owner_len, KM_SLEEP);
2471d216dff5SRobert Mastors bcopy(lockowner->owner_val, lo->rl_owner.owner_val,
2472d216dff5SRobert Mastors lockowner->owner_len);
2473d216dff5SRobert Mastors lo->rl_owner.owner_len = lockowner->owner_len;
2474d216dff5SRobert Mastors lo->rl_pid = rfs4_dbe_getid(lo->rl_dbe);
24757c478bd9Sstevel@tonic-gate
24767c478bd9Sstevel@tonic-gate return (TRUE);
24777c478bd9Sstevel@tonic-gate }
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate rfs4_lockowner_t *
rfs4_findlockowner(lock_owner4 * lockowner,bool_t * create)24807c478bd9Sstevel@tonic-gate rfs4_findlockowner(lock_owner4 *lockowner, bool_t *create)
24817c478bd9Sstevel@tonic-gate {
24827c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo;
24830dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
24847c478bd9Sstevel@tonic-gate
24850dfe541eSEvan Layton /* CSTYLED */
24860dfe541eSEvan Layton lo = (rfs4_lockowner_t *)rfs4_dbsearch(nsrv4->rfs4_lockowner_idx, lockowner,
2487ed57cab9Srg create, lockowner, RFS4_DBS_VALID);
24887c478bd9Sstevel@tonic-gate
24897c478bd9Sstevel@tonic-gate return (lo);
24907c478bd9Sstevel@tonic-gate }
24917c478bd9Sstevel@tonic-gate
24927c478bd9Sstevel@tonic-gate rfs4_lockowner_t *
rfs4_findlockowner_by_pid(pid_t pid)24937c478bd9Sstevel@tonic-gate rfs4_findlockowner_by_pid(pid_t pid)
24947c478bd9Sstevel@tonic-gate {
24957c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo;
24967c478bd9Sstevel@tonic-gate bool_t create = FALSE;
24970dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
24987c478bd9Sstevel@tonic-gate
24990dfe541eSEvan Layton lo = (rfs4_lockowner_t *)rfs4_dbsearch(nsrv4->rfs4_lockowner_pid_idx,
2500ed57cab9Srg (void *)(uintptr_t)pid, &create, NULL, RFS4_DBS_VALID);
25017c478bd9Sstevel@tonic-gate
25027c478bd9Sstevel@tonic-gate return (lo);
25037c478bd9Sstevel@tonic-gate }
25047c478bd9Sstevel@tonic-gate
25057c478bd9Sstevel@tonic-gate
25067c478bd9Sstevel@tonic-gate static uint32_t
file_hash(void * key)25077c478bd9Sstevel@tonic-gate file_hash(void *key)
25087c478bd9Sstevel@tonic-gate {
25097c478bd9Sstevel@tonic-gate return (ADDRHASH(key));
25107c478bd9Sstevel@tonic-gate }
25117c478bd9Sstevel@tonic-gate
25127c478bd9Sstevel@tonic-gate static void *
file_mkkey(rfs4_entry_t u_entry)25137c478bd9Sstevel@tonic-gate file_mkkey(rfs4_entry_t u_entry)
25147c478bd9Sstevel@tonic-gate {
25157c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry;
25167c478bd9Sstevel@tonic-gate
2517d216dff5SRobert Mastors return (fp->rf_vp);
25187c478bd9Sstevel@tonic-gate }
25197c478bd9Sstevel@tonic-gate
25207c478bd9Sstevel@tonic-gate static bool_t
file_compare(rfs4_entry_t u_entry,void * key)25217c478bd9Sstevel@tonic-gate file_compare(rfs4_entry_t u_entry, void *key)
25227c478bd9Sstevel@tonic-gate {
25237c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry;
25247c478bd9Sstevel@tonic-gate
2525d216dff5SRobert Mastors return (fp->rf_vp == (vnode_t *)key);
25267c478bd9Sstevel@tonic-gate }
25277c478bd9Sstevel@tonic-gate
25287c478bd9Sstevel@tonic-gate static void
rfs4_file_destroy(rfs4_entry_t u_entry)25297c478bd9Sstevel@tonic-gate rfs4_file_destroy(rfs4_entry_t u_entry)
25307c478bd9Sstevel@tonic-gate {
25317c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry;
25327c478bd9Sstevel@tonic-gate
2533d216dff5SRobert Mastors list_destroy(&fp->rf_delegstatelist);
2534d216dff5SRobert Mastors
2535d216dff5SRobert Mastors if (fp->rf_filehandle.nfs_fh4_val)
2536d216dff5SRobert Mastors kmem_free(fp->rf_filehandle.nfs_fh4_val,
2537d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_len);
2538d216dff5SRobert Mastors cv_destroy(fp->rf_dinfo.rd_recall_cv);
2539d216dff5SRobert Mastors if (fp->rf_vp) {
2540d216dff5SRobert Mastors vnode_t *vp = fp->rf_vp;
25411b300de9Sjwahlig
2542d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock);
25431b300de9Sjwahlig (void) vsd_set(vp, nfs4_srv_vkey, NULL);
2544d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
25451b300de9Sjwahlig VN_RELE(vp);
2546d216dff5SRobert Mastors fp->rf_vp = NULL;
25477c478bd9Sstevel@tonic-gate }
2548d216dff5SRobert Mastors rw_destroy(&fp->rf_file_rwlock);
25497c478bd9Sstevel@tonic-gate }
25507c478bd9Sstevel@tonic-gate
25517c478bd9Sstevel@tonic-gate /*
25527c478bd9Sstevel@tonic-gate * Used to unlock the underlying dbe struct only
25537c478bd9Sstevel@tonic-gate */
25547c478bd9Sstevel@tonic-gate void
rfs4_file_rele(rfs4_file_t * fp)25557c478bd9Sstevel@tonic-gate rfs4_file_rele(rfs4_file_t *fp)
25567c478bd9Sstevel@tonic-gate {
2557d216dff5SRobert Mastors rfs4_dbe_rele(fp->rf_dbe);
25587c478bd9Sstevel@tonic-gate }
25597c478bd9Sstevel@tonic-gate
25607c478bd9Sstevel@tonic-gate typedef struct {
25617c478bd9Sstevel@tonic-gate vnode_t *vp;
25627c478bd9Sstevel@tonic-gate nfs_fh4 *fh;
25637c478bd9Sstevel@tonic-gate } rfs4_fcreate_arg;
25647c478bd9Sstevel@tonic-gate
25657c478bd9Sstevel@tonic-gate static bool_t
rfs4_file_create(rfs4_entry_t u_entry,void * arg)25667c478bd9Sstevel@tonic-gate rfs4_file_create(rfs4_entry_t u_entry, void *arg)
25677c478bd9Sstevel@tonic-gate {
25687c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry;
25697c478bd9Sstevel@tonic-gate rfs4_fcreate_arg *ap = (rfs4_fcreate_arg *)arg;
25707c478bd9Sstevel@tonic-gate vnode_t *vp = ap->vp;
25717c478bd9Sstevel@tonic-gate nfs_fh4 *fh = ap->fh;
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate VN_HOLD(vp);
25747c478bd9Sstevel@tonic-gate
2575d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_len = 0;
2576d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_val = NULL;
25777c478bd9Sstevel@tonic-gate ASSERT(fh && fh->nfs_fh4_len);
25787c478bd9Sstevel@tonic-gate if (fh && fh->nfs_fh4_len) {
2579d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_val =
2580ed57cab9Srg kmem_alloc(fh->nfs_fh4_len, KM_SLEEP);
2581d216dff5SRobert Mastors nfs_fh4_copy(fh, &fp->rf_filehandle);
25827c478bd9Sstevel@tonic-gate }
2583d216dff5SRobert Mastors fp->rf_vp = vp;
25847c478bd9Sstevel@tonic-gate
2585d216dff5SRobert Mastors list_create(&fp->rf_delegstatelist, sizeof (rfs4_deleg_state_t),
2586d216dff5SRobert Mastors offsetof(rfs4_deleg_state_t, rds_node));
25877c478bd9Sstevel@tonic-gate
2588d216dff5SRobert Mastors fp->rf_share_deny = fp->rf_share_access = fp->rf_access_read = 0;
2589d216dff5SRobert Mastors fp->rf_access_write = fp->rf_deny_read = fp->rf_deny_write = 0;
25907c478bd9Sstevel@tonic-gate
2591d216dff5SRobert Mastors mutex_init(fp->rf_dinfo.rd_recall_lock, NULL, MUTEX_DEFAULT, NULL);
2592d216dff5SRobert Mastors cv_init(fp->rf_dinfo.rd_recall_cv, NULL, CV_DEFAULT, NULL);
25937c478bd9Sstevel@tonic-gate
2594d216dff5SRobert Mastors fp->rf_dinfo.rd_dtype = OPEN_DELEGATE_NONE;
25957c478bd9Sstevel@tonic-gate
2596d216dff5SRobert Mastors rw_init(&fp->rf_file_rwlock, NULL, RW_DEFAULT, NULL);
25977c478bd9Sstevel@tonic-gate
2598d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock);
2599d216dff5SRobert Mastors VERIFY(vsd_set(vp, nfs4_srv_vkey, (void *)fp) == 0);
2600d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
26011b300de9Sjwahlig
26027c478bd9Sstevel@tonic-gate return (TRUE);
26037c478bd9Sstevel@tonic-gate }
26047c478bd9Sstevel@tonic-gate
26057c478bd9Sstevel@tonic-gate rfs4_file_t *
rfs4_findfile(vnode_t * vp,nfs_fh4 * fh,bool_t * create)26067c478bd9Sstevel@tonic-gate rfs4_findfile(vnode_t *vp, nfs_fh4 *fh, bool_t *create)
26077c478bd9Sstevel@tonic-gate {
26087c478bd9Sstevel@tonic-gate rfs4_file_t *fp;
26097c478bd9Sstevel@tonic-gate rfs4_fcreate_arg arg;
26100dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
26117c478bd9Sstevel@tonic-gate
26127c478bd9Sstevel@tonic-gate arg.vp = vp;
26137c478bd9Sstevel@tonic-gate arg.fh = fh;
26147c478bd9Sstevel@tonic-gate
26151b300de9Sjwahlig if (*create == TRUE)
26160dfe541eSEvan Layton /* CSTYLED */
26170dfe541eSEvan Layton fp = (rfs4_file_t *)rfs4_dbsearch(nsrv4->rfs4_file_idx, vp, create,
26181b300de9Sjwahlig &arg, RFS4_DBS_VALID);
26191b300de9Sjwahlig else {
2620d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock);
26211b300de9Sjwahlig fp = (rfs4_file_t *)vsd_get(vp, nfs4_srv_vkey);
26221b300de9Sjwahlig if (fp) {
2623d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe);
2624d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(fp->rf_dbe) ||
2625d216dff5SRobert Mastors (rfs4_dbe_refcnt(fp->rf_dbe) == 0)) {
2626d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
26271b300de9Sjwahlig fp = NULL;
26281b300de9Sjwahlig } else {
2629d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe);
2630d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
26311b300de9Sjwahlig }
26321b300de9Sjwahlig }
2633d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
26341b300de9Sjwahlig }
26357c478bd9Sstevel@tonic-gate return (fp);
26367c478bd9Sstevel@tonic-gate }
26377c478bd9Sstevel@tonic-gate
26387c478bd9Sstevel@tonic-gate /*
26397c478bd9Sstevel@tonic-gate * Find a file in the db and once it is located, take the rw lock.
26407c478bd9Sstevel@tonic-gate * Need to check the vnode pointer and if it does not exist (it was
26417c478bd9Sstevel@tonic-gate * removed between the db location and check) redo the find. This
26427c478bd9Sstevel@tonic-gate * assumes that a file struct that has a NULL vnode pointer is marked
26437c478bd9Sstevel@tonic-gate * at 'invalid' and will not be found in the db the second time
26447c478bd9Sstevel@tonic-gate * around.
26457c478bd9Sstevel@tonic-gate */
26467c478bd9Sstevel@tonic-gate rfs4_file_t *
rfs4_findfile_withlock(vnode_t * vp,nfs_fh4 * fh,bool_t * create)26477c478bd9Sstevel@tonic-gate rfs4_findfile_withlock(vnode_t *vp, nfs_fh4 *fh, bool_t *create)
26487c478bd9Sstevel@tonic-gate {
26497c478bd9Sstevel@tonic-gate rfs4_file_t *fp;
26507c478bd9Sstevel@tonic-gate rfs4_fcreate_arg arg;
26517c478bd9Sstevel@tonic-gate bool_t screate = *create;
26520dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
26537c478bd9Sstevel@tonic-gate
26541b300de9Sjwahlig if (screate == FALSE) {
2655d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock);
26561b300de9Sjwahlig fp = (rfs4_file_t *)vsd_get(vp, nfs4_srv_vkey);
26571b300de9Sjwahlig if (fp) {
2658d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe);
2659d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(fp->rf_dbe) ||
2660d216dff5SRobert Mastors (rfs4_dbe_refcnt(fp->rf_dbe) == 0)) {
2661d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
2662d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
26631b300de9Sjwahlig fp = NULL;
26641b300de9Sjwahlig } else {
2665d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe);
2666d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
2667d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
2668d216dff5SRobert Mastors rw_enter(&fp->rf_file_rwlock, RW_WRITER);
2669d216dff5SRobert Mastors if (fp->rf_vp == NULL) {
2670d216dff5SRobert Mastors rw_exit(&fp->rf_file_rwlock);
2671a08f57bcSJames Wahlig rfs4_file_rele(fp);
2672a08f57bcSJames Wahlig fp = NULL;
2673a08f57bcSJames Wahlig }
26741b300de9Sjwahlig }
2675d216dff5SRobert Mastors } else {
2676d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
26771b300de9Sjwahlig }
26781b300de9Sjwahlig } else {
26797c478bd9Sstevel@tonic-gate retry:
26801b300de9Sjwahlig arg.vp = vp;
26811b300de9Sjwahlig arg.fh = fh;
26821b300de9Sjwahlig
26830dfe541eSEvan Layton fp = (rfs4_file_t *)rfs4_dbsearch(nsrv4->rfs4_file_idx, vp,
26840dfe541eSEvan Layton create, &arg, RFS4_DBS_VALID);
26851b300de9Sjwahlig if (fp != NULL) {
2686d216dff5SRobert Mastors rw_enter(&fp->rf_file_rwlock, RW_WRITER);
2687d216dff5SRobert Mastors if (fp->rf_vp == NULL) {
2688d216dff5SRobert Mastors rw_exit(&fp->rf_file_rwlock);
26891b300de9Sjwahlig rfs4_file_rele(fp);
26901b300de9Sjwahlig *create = screate;
26911b300de9Sjwahlig goto retry;
26921b300de9Sjwahlig }
26937c478bd9Sstevel@tonic-gate }
26947c478bd9Sstevel@tonic-gate }
26957c478bd9Sstevel@tonic-gate
26967c478bd9Sstevel@tonic-gate return (fp);
26977c478bd9Sstevel@tonic-gate }
26987c478bd9Sstevel@tonic-gate
26997c478bd9Sstevel@tonic-gate static uint32_t
lo_state_hash(void * key)27007c478bd9Sstevel@tonic-gate lo_state_hash(void *key)
27017c478bd9Sstevel@tonic-gate {
27027c478bd9Sstevel@tonic-gate stateid_t *id = key;
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate return (id->bits.ident+id->bits.pid);
27057c478bd9Sstevel@tonic-gate }
27067c478bd9Sstevel@tonic-gate
27077c478bd9Sstevel@tonic-gate static bool_t
lo_state_compare(rfs4_entry_t u_entry,void * key)27087c478bd9Sstevel@tonic-gate lo_state_compare(rfs4_entry_t u_entry, void *key)
27097c478bd9Sstevel@tonic-gate {
2710d216dff5SRobert Mastors rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
27117c478bd9Sstevel@tonic-gate stateid_t *id = key;
27127c478bd9Sstevel@tonic-gate bool_t rc;
27137c478bd9Sstevel@tonic-gate
2714d216dff5SRobert Mastors rc = (lsp->rls_lockid.bits.boottime == id->bits.boottime &&
2715d216dff5SRobert Mastors lsp->rls_lockid.bits.type == id->bits.type &&
2716d216dff5SRobert Mastors lsp->rls_lockid.bits.ident == id->bits.ident &&
2717d216dff5SRobert Mastors lsp->rls_lockid.bits.pid == id->bits.pid);
27187c478bd9Sstevel@tonic-gate
27197c478bd9Sstevel@tonic-gate return (rc);
27207c478bd9Sstevel@tonic-gate }
27217c478bd9Sstevel@tonic-gate
27227c478bd9Sstevel@tonic-gate static void *
lo_state_mkkey(rfs4_entry_t u_entry)27237c478bd9Sstevel@tonic-gate lo_state_mkkey(rfs4_entry_t u_entry)
27247c478bd9Sstevel@tonic-gate {
27257c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
27267c478bd9Sstevel@tonic-gate
2727d216dff5SRobert Mastors return (&lsp->rls_lockid);
27287c478bd9Sstevel@tonic-gate }
27297c478bd9Sstevel@tonic-gate
27307c478bd9Sstevel@tonic-gate static bool_t
rfs4_lo_state_expiry(rfs4_entry_t u_entry)27317c478bd9Sstevel@tonic-gate rfs4_lo_state_expiry(rfs4_entry_t u_entry)
27327c478bd9Sstevel@tonic-gate {
27337c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
27347c478bd9Sstevel@tonic-gate
2735d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(lsp->rls_dbe))
27367c478bd9Sstevel@tonic-gate return (TRUE);
2737d216dff5SRobert Mastors if (lsp->rls_state->rs_closed)
27387c478bd9Sstevel@tonic-gate return (TRUE);
2739d216dff5SRobert Mastors return ((gethrestime_sec() -
2740d216dff5SRobert Mastors lsp->rls_state->rs_owner->ro_client->rc_last_access
2741ed57cab9Srg > rfs4_lease_time));
27427c478bd9Sstevel@tonic-gate }
27437c478bd9Sstevel@tonic-gate
27447c478bd9Sstevel@tonic-gate static void
rfs4_lo_state_destroy(rfs4_entry_t u_entry)27457c478bd9Sstevel@tonic-gate rfs4_lo_state_destroy(rfs4_entry_t u_entry)
27467c478bd9Sstevel@tonic-gate {
27477c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
27487c478bd9Sstevel@tonic-gate
2749d216dff5SRobert Mastors rfs4_dbe_lock(lsp->rls_state->rs_dbe);
2750d216dff5SRobert Mastors list_remove(&lsp->rls_state->rs_lostatelist, lsp);
2751d216dff5SRobert Mastors rfs4_dbe_unlock(lsp->rls_state->rs_dbe);
2752d216dff5SRobert Mastors
2753d216dff5SRobert Mastors rfs4_sw_destroy(&lsp->rls_sw);
27547c478bd9Sstevel@tonic-gate
27557c478bd9Sstevel@tonic-gate /* Make sure to release the file locks */
2756d216dff5SRobert Mastors if (lsp->rls_locks_cleaned == FALSE) {
2757d216dff5SRobert Mastors lsp->rls_locks_cleaned = TRUE;
2758d216dff5SRobert Mastors if (lsp->rls_locker->rl_client->rc_sysidt != LM_NOSYSID) {
27597c478bd9Sstevel@tonic-gate /* Is the PxFS kernel module loaded? */
27607c478bd9Sstevel@tonic-gate if (lm_remove_file_locks != NULL) {
27617c478bd9Sstevel@tonic-gate int new_sysid;
27627c478bd9Sstevel@tonic-gate
27637c478bd9Sstevel@tonic-gate /* Encode the cluster nodeid in new sysid */
2764d216dff5SRobert Mastors new_sysid =
2765d216dff5SRobert Mastors lsp->rls_locker->rl_client->rc_sysidt;
27667c478bd9Sstevel@tonic-gate lm_set_nlmid_flk(&new_sysid);
27677c478bd9Sstevel@tonic-gate
27687c478bd9Sstevel@tonic-gate /*
27697c478bd9Sstevel@tonic-gate * This PxFS routine removes file locks for a
27707c478bd9Sstevel@tonic-gate * client over all nodes of a cluster.
27717c478bd9Sstevel@tonic-gate */
2772ed57cab9Srg DTRACE_PROBE1(nfss_i_clust_rm_lck,
2773ed57cab9Srg int, new_sysid);
27747c478bd9Sstevel@tonic-gate (*lm_remove_file_locks)(new_sysid);
27757c478bd9Sstevel@tonic-gate } else {
2776d216dff5SRobert Mastors (void) cleanlocks(
2777d216dff5SRobert Mastors lsp->rls_state->rs_finfo->rf_vp,
2778d216dff5SRobert Mastors lsp->rls_locker->rl_pid,
2779d216dff5SRobert Mastors lsp->rls_locker->rl_client->rc_sysidt);
27807c478bd9Sstevel@tonic-gate }
27817c478bd9Sstevel@tonic-gate }
27827c478bd9Sstevel@tonic-gate }
27837c478bd9Sstevel@tonic-gate
27847c478bd9Sstevel@tonic-gate /* Free the last reply for this state */
2785d216dff5SRobert Mastors rfs4_free_reply(&lsp->rls_reply);
27867c478bd9Sstevel@tonic-gate
2787d216dff5SRobert Mastors rfs4_lockowner_rele(lsp->rls_locker);
2788d216dff5SRobert Mastors lsp->rls_locker = NULL;
27897c478bd9Sstevel@tonic-gate
2790d216dff5SRobert Mastors rfs4_state_rele_nounlock(lsp->rls_state);
2791d216dff5SRobert Mastors lsp->rls_state = NULL;
27927c478bd9Sstevel@tonic-gate }
27937c478bd9Sstevel@tonic-gate
27947c478bd9Sstevel@tonic-gate static bool_t
rfs4_lo_state_create(rfs4_entry_t u_entry,void * arg)27957c478bd9Sstevel@tonic-gate rfs4_lo_state_create(rfs4_entry_t u_entry, void *arg)
27967c478bd9Sstevel@tonic-gate {
27977c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
27987c478bd9Sstevel@tonic-gate rfs4_lo_state_t *argp = (rfs4_lo_state_t *)arg;
2799d216dff5SRobert Mastors rfs4_lockowner_t *lo = argp->rls_locker;
2800d216dff5SRobert Mastors rfs4_state_t *sp = argp->rls_state;
28017c478bd9Sstevel@tonic-gate
2802d216dff5SRobert Mastors lsp->rls_state = sp;
28037c478bd9Sstevel@tonic-gate
2804d216dff5SRobert Mastors lsp->rls_lockid = sp->rs_stateid;
2805d216dff5SRobert Mastors lsp->rls_lockid.bits.type = LOCKID;
2806d216dff5SRobert Mastors lsp->rls_lockid.bits.chgseq = 0;
2807d216dff5SRobert Mastors lsp->rls_lockid.bits.pid = lo->rl_pid;
28087c478bd9Sstevel@tonic-gate
2809d216dff5SRobert Mastors lsp->rls_locks_cleaned = FALSE;
2810d216dff5SRobert Mastors lsp->rls_lock_completed = FALSE;
28117c478bd9Sstevel@tonic-gate
2812d216dff5SRobert Mastors rfs4_sw_init(&lsp->rls_sw);
28137c478bd9Sstevel@tonic-gate
28147c478bd9Sstevel@tonic-gate /* Attached the supplied lock owner */
2815d216dff5SRobert Mastors rfs4_dbe_hold(lo->rl_dbe);
2816d216dff5SRobert Mastors lsp->rls_locker = lo;
28177c478bd9Sstevel@tonic-gate
2818d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe);
2819d216dff5SRobert Mastors list_insert_tail(&sp->rs_lostatelist, lsp);
2820d216dff5SRobert Mastors rfs4_dbe_hold(sp->rs_dbe);
2821d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe);
28227c478bd9Sstevel@tonic-gate
28237c478bd9Sstevel@tonic-gate return (TRUE);
28247c478bd9Sstevel@tonic-gate }
28257c478bd9Sstevel@tonic-gate
28267c478bd9Sstevel@tonic-gate void
rfs4_lo_state_rele(rfs4_lo_state_t * lsp,bool_t unlock_fp)28277c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(rfs4_lo_state_t *lsp, bool_t unlock_fp)
28287c478bd9Sstevel@tonic-gate {
28297c478bd9Sstevel@tonic-gate if (unlock_fp == TRUE)
2830d216dff5SRobert Mastors rw_exit(&lsp->rls_state->rs_finfo->rf_file_rwlock);
2831d216dff5SRobert Mastors rfs4_dbe_rele(lsp->rls_dbe);
28327c478bd9Sstevel@tonic-gate }
28337c478bd9Sstevel@tonic-gate
28347c478bd9Sstevel@tonic-gate static rfs4_lo_state_t *
rfs4_findlo_state(stateid_t * id,bool_t lock_fp)28357c478bd9Sstevel@tonic-gate rfs4_findlo_state(stateid_t *id, bool_t lock_fp)
28367c478bd9Sstevel@tonic-gate {
28377c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp;
28387c478bd9Sstevel@tonic-gate bool_t create = FALSE;
28390dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
28407c478bd9Sstevel@tonic-gate
28410dfe541eSEvan Layton lsp = (rfs4_lo_state_t *)rfs4_dbsearch(nsrv4->rfs4_lo_state_idx, id,
2842ed57cab9Srg &create, NULL, RFS4_DBS_VALID);
28437c478bd9Sstevel@tonic-gate if (lock_fp == TRUE && lsp != NULL)
2844d216dff5SRobert Mastors rw_enter(&lsp->rls_state->rs_finfo->rf_file_rwlock, RW_READER);
28457c478bd9Sstevel@tonic-gate
28467c478bd9Sstevel@tonic-gate return (lsp);
28477c478bd9Sstevel@tonic-gate }
28487c478bd9Sstevel@tonic-gate
28497c478bd9Sstevel@tonic-gate
28507c478bd9Sstevel@tonic-gate static uint32_t
lo_state_lo_hash(void * key)28517c478bd9Sstevel@tonic-gate lo_state_lo_hash(void *key)
28527c478bd9Sstevel@tonic-gate {
2853d216dff5SRobert Mastors rfs4_lo_state_t *lsp = key;
28547c478bd9Sstevel@tonic-gate
2855d216dff5SRobert Mastors return (ADDRHASH(lsp->rls_locker) ^ ADDRHASH(lsp->rls_state));
28567c478bd9Sstevel@tonic-gate }
28577c478bd9Sstevel@tonic-gate
28587c478bd9Sstevel@tonic-gate static bool_t
lo_state_lo_compare(rfs4_entry_t u_entry,void * key)28597c478bd9Sstevel@tonic-gate lo_state_lo_compare(rfs4_entry_t u_entry, void *key)
28607c478bd9Sstevel@tonic-gate {
2861d216dff5SRobert Mastors rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
28627c478bd9Sstevel@tonic-gate rfs4_lo_state_t *keyp = key;
28637c478bd9Sstevel@tonic-gate
2864d216dff5SRobert Mastors return (keyp->rls_locker == lsp->rls_locker &&
2865d216dff5SRobert Mastors keyp->rls_state == lsp->rls_state);
28667c478bd9Sstevel@tonic-gate }
28677c478bd9Sstevel@tonic-gate
28687c478bd9Sstevel@tonic-gate static void *
lo_state_lo_mkkey(rfs4_entry_t u_entry)28697c478bd9Sstevel@tonic-gate lo_state_lo_mkkey(rfs4_entry_t u_entry)
28707c478bd9Sstevel@tonic-gate {
28717c478bd9Sstevel@tonic-gate return (u_entry);
28727c478bd9Sstevel@tonic-gate }
28737c478bd9Sstevel@tonic-gate
28747c478bd9Sstevel@tonic-gate rfs4_lo_state_t *
rfs4_findlo_state_by_owner(rfs4_lockowner_t * lo,rfs4_state_t * sp,bool_t * create)2875d216dff5SRobert Mastors rfs4_findlo_state_by_owner(rfs4_lockowner_t *lo, rfs4_state_t *sp,
2876d216dff5SRobert Mastors bool_t *create)
28777c478bd9Sstevel@tonic-gate {
28787c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp;
28797c478bd9Sstevel@tonic-gate rfs4_lo_state_t arg;
28800dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
28817c478bd9Sstevel@tonic-gate
2882d216dff5SRobert Mastors arg.rls_locker = lo;
2883d216dff5SRobert Mastors arg.rls_state = sp;
28847c478bd9Sstevel@tonic-gate
28850dfe541eSEvan Layton lsp = (rfs4_lo_state_t *)rfs4_dbsearch(nsrv4->rfs4_lo_state_owner_idx,
28860dfe541eSEvan Layton &arg, create, &arg, RFS4_DBS_VALID);
28877c478bd9Sstevel@tonic-gate
28887c478bd9Sstevel@tonic-gate return (lsp);
28897c478bd9Sstevel@tonic-gate }
28907c478bd9Sstevel@tonic-gate
28917c478bd9Sstevel@tonic-gate static stateid_t
get_stateid(id_t eid)28927c478bd9Sstevel@tonic-gate get_stateid(id_t eid)
28937c478bd9Sstevel@tonic-gate {
28947c478bd9Sstevel@tonic-gate stateid_t id;
28950dfe541eSEvan Layton nfs4_srv_t *nsrv4;
28960dfe541eSEvan Layton
28970dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
28987c478bd9Sstevel@tonic-gate
28990dfe541eSEvan Layton id.bits.boottime = nsrv4->rfs4_start_time;
29007c478bd9Sstevel@tonic-gate id.bits.ident = eid;
29017c478bd9Sstevel@tonic-gate id.bits.chgseq = 0;
29027c478bd9Sstevel@tonic-gate id.bits.type = 0;
29037c478bd9Sstevel@tonic-gate id.bits.pid = 0;
29047c478bd9Sstevel@tonic-gate
29057c478bd9Sstevel@tonic-gate /*
29067c478bd9Sstevel@tonic-gate * If we are booted as a cluster node, embed our nodeid.
29077c478bd9Sstevel@tonic-gate * We've already done sanity checks in rfs4_client_create() so no
29087c478bd9Sstevel@tonic-gate * need to repeat them here.
29097c478bd9Sstevel@tonic-gate */
29107c478bd9Sstevel@tonic-gate id.bits.clnodeid = (cluster_bootflags & CLUSTER_BOOTED) ?
29117c478bd9Sstevel@tonic-gate clconf_get_nodeid() : 0;
29127c478bd9Sstevel@tonic-gate
29137c478bd9Sstevel@tonic-gate return (id);
29147c478bd9Sstevel@tonic-gate }
29157c478bd9Sstevel@tonic-gate
29167c478bd9Sstevel@tonic-gate /*
29177c478bd9Sstevel@tonic-gate * For use only when booted as a cluster node.
29187c478bd9Sstevel@tonic-gate * Returns TRUE if the embedded nodeid indicates that this stateid was
29197c478bd9Sstevel@tonic-gate * generated on another node.
29207c478bd9Sstevel@tonic-gate */
29217c478bd9Sstevel@tonic-gate static int
foreign_stateid(stateid_t * id)29227c478bd9Sstevel@tonic-gate foreign_stateid(stateid_t *id)
29237c478bd9Sstevel@tonic-gate {
29247c478bd9Sstevel@tonic-gate ASSERT(cluster_bootflags & CLUSTER_BOOTED);
29257c478bd9Sstevel@tonic-gate return (id->bits.clnodeid != (uint32_t)clconf_get_nodeid());
29267c478bd9Sstevel@tonic-gate }
29277c478bd9Sstevel@tonic-gate
29287c478bd9Sstevel@tonic-gate /*
29297c478bd9Sstevel@tonic-gate * For use only when booted as a cluster node.
29307c478bd9Sstevel@tonic-gate * Returns TRUE if the embedded nodeid indicates that this clientid was
29317c478bd9Sstevel@tonic-gate * generated on another node.
29327c478bd9Sstevel@tonic-gate */
29337c478bd9Sstevel@tonic-gate static int
foreign_clientid(cid * cidp)29347c478bd9Sstevel@tonic-gate foreign_clientid(cid *cidp)
29357c478bd9Sstevel@tonic-gate {
29367c478bd9Sstevel@tonic-gate ASSERT(cluster_bootflags & CLUSTER_BOOTED);
29377c478bd9Sstevel@tonic-gate return (cidp->impl_id.c_id >> CLUSTER_NODEID_SHIFT !=
29387c478bd9Sstevel@tonic-gate (uint32_t)clconf_get_nodeid());
29397c478bd9Sstevel@tonic-gate }
29407c478bd9Sstevel@tonic-gate
29417c478bd9Sstevel@tonic-gate /*
29427c478bd9Sstevel@tonic-gate * For use only when booted as a cluster node.
29437c478bd9Sstevel@tonic-gate * Embed our cluster nodeid into the clientid.
29447c478bd9Sstevel@tonic-gate */
29457c478bd9Sstevel@tonic-gate static void
embed_nodeid(cid * cidp)29467c478bd9Sstevel@tonic-gate embed_nodeid(cid *cidp)
29477c478bd9Sstevel@tonic-gate {
29487c478bd9Sstevel@tonic-gate int clnodeid;
29497c478bd9Sstevel@tonic-gate /*
29507c478bd9Sstevel@tonic-gate * Currently, our state tables are small enough that their
29517c478bd9Sstevel@tonic-gate * ids will leave enough bits free for the nodeid. If the
29527c478bd9Sstevel@tonic-gate * tables become larger, we mustn't overwrite the id.
29537c478bd9Sstevel@tonic-gate * Equally, we only have room for so many bits of nodeid, so
29547c478bd9Sstevel@tonic-gate * must check that too.
29557c478bd9Sstevel@tonic-gate */
29567c478bd9Sstevel@tonic-gate ASSERT(cluster_bootflags & CLUSTER_BOOTED);
29577c478bd9Sstevel@tonic-gate ASSERT(cidp->impl_id.c_id >> CLUSTER_NODEID_SHIFT == 0);
29587c478bd9Sstevel@tonic-gate clnodeid = clconf_get_nodeid();
29597c478bd9Sstevel@tonic-gate ASSERT(clnodeid <= CLUSTER_MAX_NODEID);
29607c478bd9Sstevel@tonic-gate ASSERT(clnodeid != NODEID_UNKNOWN);
29617c478bd9Sstevel@tonic-gate cidp->impl_id.c_id |= (clnodeid << CLUSTER_NODEID_SHIFT);
29627c478bd9Sstevel@tonic-gate }
29637c478bd9Sstevel@tonic-gate
29647c478bd9Sstevel@tonic-gate static uint32_t
state_hash(void * key)29657c478bd9Sstevel@tonic-gate state_hash(void *key)
29667c478bd9Sstevel@tonic-gate {
29677c478bd9Sstevel@tonic-gate stateid_t *ip = (stateid_t *)key;
29687c478bd9Sstevel@tonic-gate
29697c478bd9Sstevel@tonic-gate return (ip->bits.ident);
29707c478bd9Sstevel@tonic-gate }
29717c478bd9Sstevel@tonic-gate
29727c478bd9Sstevel@tonic-gate static bool_t
state_compare(rfs4_entry_t u_entry,void * key)29737c478bd9Sstevel@tonic-gate state_compare(rfs4_entry_t u_entry, void *key)
29747c478bd9Sstevel@tonic-gate {
29757c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
29767c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)key;
29777c478bd9Sstevel@tonic-gate bool_t rc;
29787c478bd9Sstevel@tonic-gate
2979d216dff5SRobert Mastors rc = (sp->rs_stateid.bits.boottime == id->bits.boottime &&
2980d216dff5SRobert Mastors sp->rs_stateid.bits.ident == id->bits.ident);
29817c478bd9Sstevel@tonic-gate
29827c478bd9Sstevel@tonic-gate return (rc);
29837c478bd9Sstevel@tonic-gate }
29847c478bd9Sstevel@tonic-gate
29857c478bd9Sstevel@tonic-gate static void *
state_mkkey(rfs4_entry_t u_entry)29867c478bd9Sstevel@tonic-gate state_mkkey(rfs4_entry_t u_entry)
29877c478bd9Sstevel@tonic-gate {
29887c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
29897c478bd9Sstevel@tonic-gate
2990d216dff5SRobert Mastors return (&sp->rs_stateid);
29917c478bd9Sstevel@tonic-gate }
29927c478bd9Sstevel@tonic-gate
29937c478bd9Sstevel@tonic-gate static void
rfs4_state_destroy(rfs4_entry_t u_entry)29947c478bd9Sstevel@tonic-gate rfs4_state_destroy(rfs4_entry_t u_entry)
29957c478bd9Sstevel@tonic-gate {
29967c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
29977c478bd9Sstevel@tonic-gate
2998d216dff5SRobert Mastors /* remove from openowner list */
2999d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_owner->ro_dbe);
3000d216dff5SRobert Mastors list_remove(&sp->rs_owner->ro_statelist, sp);
3001d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_owner->ro_dbe);
3002d216dff5SRobert Mastors
3003d216dff5SRobert Mastors list_destroy(&sp->rs_lostatelist);
30047c478bd9Sstevel@tonic-gate
30057c478bd9Sstevel@tonic-gate /* release any share locks for this stateid if it's still open */
3006d216dff5SRobert Mastors if (!sp->rs_closed) {
3007d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe);
3008d216dff5SRobert Mastors (void) rfs4_unshare(sp);
3009d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe);
3010d216dff5SRobert Mastors }
30117c478bd9Sstevel@tonic-gate
30127c478bd9Sstevel@tonic-gate /* Were done with the file */
3013d216dff5SRobert Mastors rfs4_file_rele(sp->rs_finfo);
3014d216dff5SRobert Mastors sp->rs_finfo = NULL;
30157c478bd9Sstevel@tonic-gate
30167c478bd9Sstevel@tonic-gate /* And now with the openowner */
3017d216dff5SRobert Mastors rfs4_openowner_rele(sp->rs_owner);
3018d216dff5SRobert Mastors sp->rs_owner = NULL;
30197c478bd9Sstevel@tonic-gate }
30207c478bd9Sstevel@tonic-gate
30217c478bd9Sstevel@tonic-gate static void
rfs4_state_rele_nounlock(rfs4_state_t * sp)30227c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(rfs4_state_t *sp)
30237c478bd9Sstevel@tonic-gate {
3024d216dff5SRobert Mastors rfs4_dbe_rele(sp->rs_dbe);
30257c478bd9Sstevel@tonic-gate }
30267c478bd9Sstevel@tonic-gate
30277c478bd9Sstevel@tonic-gate void
rfs4_state_rele(rfs4_state_t * sp)30287c478bd9Sstevel@tonic-gate rfs4_state_rele(rfs4_state_t *sp)
30297c478bd9Sstevel@tonic-gate {
3030d216dff5SRobert Mastors rw_exit(&sp->rs_finfo->rf_file_rwlock);
3031d216dff5SRobert Mastors rfs4_dbe_rele(sp->rs_dbe);
30327c478bd9Sstevel@tonic-gate }
30337c478bd9Sstevel@tonic-gate
30347c478bd9Sstevel@tonic-gate static uint32_t
deleg_hash(void * key)30357c478bd9Sstevel@tonic-gate deleg_hash(void *key)
30367c478bd9Sstevel@tonic-gate {
30377c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)key;
30387c478bd9Sstevel@tonic-gate
3039d216dff5SRobert Mastors return (ADDRHASH(dsp->rds_client) ^ ADDRHASH(dsp->rds_finfo));
30407c478bd9Sstevel@tonic-gate }
30417c478bd9Sstevel@tonic-gate
30427c478bd9Sstevel@tonic-gate static bool_t
deleg_compare(rfs4_entry_t u_entry,void * key)30437c478bd9Sstevel@tonic-gate deleg_compare(rfs4_entry_t u_entry, void *key)
30447c478bd9Sstevel@tonic-gate {
30457c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
30467c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *kdsp = (rfs4_deleg_state_t *)key;
30477c478bd9Sstevel@tonic-gate
3048d216dff5SRobert Mastors return (dsp->rds_client == kdsp->rds_client &&
3049d216dff5SRobert Mastors dsp->rds_finfo == kdsp->rds_finfo);
30507c478bd9Sstevel@tonic-gate }
30517c478bd9Sstevel@tonic-gate
30527c478bd9Sstevel@tonic-gate static void *
deleg_mkkey(rfs4_entry_t u_entry)30537c478bd9Sstevel@tonic-gate deleg_mkkey(rfs4_entry_t u_entry)
30547c478bd9Sstevel@tonic-gate {
30557c478bd9Sstevel@tonic-gate return (u_entry);
30567c478bd9Sstevel@tonic-gate }
30577c478bd9Sstevel@tonic-gate
30587c478bd9Sstevel@tonic-gate static uint32_t
deleg_state_hash(void * key)30597c478bd9Sstevel@tonic-gate deleg_state_hash(void *key)
30607c478bd9Sstevel@tonic-gate {
30617c478bd9Sstevel@tonic-gate stateid_t *ip = (stateid_t *)key;
30627c478bd9Sstevel@tonic-gate
30637c478bd9Sstevel@tonic-gate return (ip->bits.ident);
30647c478bd9Sstevel@tonic-gate }
30657c478bd9Sstevel@tonic-gate
30667c478bd9Sstevel@tonic-gate static bool_t
deleg_state_compare(rfs4_entry_t u_entry,void * key)30677c478bd9Sstevel@tonic-gate deleg_state_compare(rfs4_entry_t u_entry, void *key)
30687c478bd9Sstevel@tonic-gate {
30697c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
30707c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)key;
30717c478bd9Sstevel@tonic-gate bool_t rc;
30727c478bd9Sstevel@tonic-gate
30737c478bd9Sstevel@tonic-gate if (id->bits.type != DELEGID)
30747c478bd9Sstevel@tonic-gate return (FALSE);
30757c478bd9Sstevel@tonic-gate
3076d216dff5SRobert Mastors rc = (dsp->rds_delegid.bits.boottime == id->bits.boottime &&
3077d216dff5SRobert Mastors dsp->rds_delegid.bits.ident == id->bits.ident);
30787c478bd9Sstevel@tonic-gate
30797c478bd9Sstevel@tonic-gate return (rc);
30807c478bd9Sstevel@tonic-gate }
30817c478bd9Sstevel@tonic-gate
30827c478bd9Sstevel@tonic-gate static void *
deleg_state_mkkey(rfs4_entry_t u_entry)30837c478bd9Sstevel@tonic-gate deleg_state_mkkey(rfs4_entry_t u_entry)
30847c478bd9Sstevel@tonic-gate {
30857c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
30867c478bd9Sstevel@tonic-gate
3087d216dff5SRobert Mastors return (&dsp->rds_delegid);
30887c478bd9Sstevel@tonic-gate }
30897c478bd9Sstevel@tonic-gate
30907c478bd9Sstevel@tonic-gate static bool_t
rfs4_deleg_state_expiry(rfs4_entry_t u_entry)30917c478bd9Sstevel@tonic-gate rfs4_deleg_state_expiry(rfs4_entry_t u_entry)
30927c478bd9Sstevel@tonic-gate {
30937c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
30947c478bd9Sstevel@tonic-gate
3095d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(dsp->rds_dbe))
30967c478bd9Sstevel@tonic-gate return (TRUE);
30977c478bd9Sstevel@tonic-gate
3098eec118a1SMarcel Telka if (dsp->rds_dtype == OPEN_DELEGATE_NONE)
3099eec118a1SMarcel Telka return (TRUE);
3100eec118a1SMarcel Telka
3101d216dff5SRobert Mastors if ((gethrestime_sec() - dsp->rds_client->rc_last_access
3102ed57cab9Srg > rfs4_lease_time)) {
3103d216dff5SRobert Mastors rfs4_dbe_invalidate(dsp->rds_dbe);
3104ed57cab9Srg return (TRUE);
3105ed57cab9Srg }
3106ed57cab9Srg
3107ed57cab9Srg return (FALSE);
31087c478bd9Sstevel@tonic-gate }
31097c478bd9Sstevel@tonic-gate
31107c478bd9Sstevel@tonic-gate static bool_t
rfs4_deleg_state_create(rfs4_entry_t u_entry,void * argp)31117c478bd9Sstevel@tonic-gate rfs4_deleg_state_create(rfs4_entry_t u_entry, void *argp)
31127c478bd9Sstevel@tonic-gate {
31137c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
3114d216dff5SRobert Mastors rfs4_file_t *fp = ((rfs4_deleg_state_t *)argp)->rds_finfo;
3115d216dff5SRobert Mastors rfs4_client_t *cp = ((rfs4_deleg_state_t *)argp)->rds_client;
31167c478bd9Sstevel@tonic-gate
3117d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe);
3118d216dff5SRobert Mastors rfs4_dbe_hold(cp->rc_dbe);
31197c478bd9Sstevel@tonic-gate
3120d216dff5SRobert Mastors dsp->rds_delegid = get_stateid(rfs4_dbe_getid(dsp->rds_dbe));
3121d216dff5SRobert Mastors dsp->rds_delegid.bits.type = DELEGID;
3122d216dff5SRobert Mastors dsp->rds_finfo = fp;
3123d216dff5SRobert Mastors dsp->rds_client = cp;
3124d216dff5SRobert Mastors dsp->rds_dtype = OPEN_DELEGATE_NONE;
31257c478bd9Sstevel@tonic-gate
3126d216dff5SRobert Mastors dsp->rds_time_granted = gethrestime_sec(); /* observability */
3127d216dff5SRobert Mastors dsp->rds_time_revoked = 0;
31287c478bd9Sstevel@tonic-gate
3129d216dff5SRobert Mastors list_link_init(&dsp->rds_node);
31307c478bd9Sstevel@tonic-gate
31317c478bd9Sstevel@tonic-gate return (TRUE);
31327c478bd9Sstevel@tonic-gate }
31337c478bd9Sstevel@tonic-gate
31347c478bd9Sstevel@tonic-gate static void
rfs4_deleg_state_destroy(rfs4_entry_t u_entry)31357c478bd9Sstevel@tonic-gate rfs4_deleg_state_destroy(rfs4_entry_t u_entry)
31367c478bd9Sstevel@tonic-gate {
31377c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
31387c478bd9Sstevel@tonic-gate
3139d216dff5SRobert Mastors /* return delegation if necessary */
3140d216dff5SRobert Mastors rfs4_return_deleg(dsp, FALSE);
31417c478bd9Sstevel@tonic-gate
31427c478bd9Sstevel@tonic-gate /* Were done with the file */
3143d216dff5SRobert Mastors rfs4_file_rele(dsp->rds_finfo);
3144d216dff5SRobert Mastors dsp->rds_finfo = NULL;
31457c478bd9Sstevel@tonic-gate
31467c478bd9Sstevel@tonic-gate /* And now with the openowner */
3147d216dff5SRobert Mastors rfs4_client_rele(dsp->rds_client);
3148d216dff5SRobert Mastors dsp->rds_client = NULL;
31497c478bd9Sstevel@tonic-gate }
31507c478bd9Sstevel@tonic-gate
31517c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *
rfs4_finddeleg(rfs4_state_t * sp,bool_t * create)31527c478bd9Sstevel@tonic-gate rfs4_finddeleg(rfs4_state_t *sp, bool_t *create)
31537c478bd9Sstevel@tonic-gate {
31547c478bd9Sstevel@tonic-gate rfs4_deleg_state_t ds, *dsp;
31550dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
31567c478bd9Sstevel@tonic-gate
3157d216dff5SRobert Mastors ds.rds_client = sp->rs_owner->ro_client;
3158d216dff5SRobert Mastors ds.rds_finfo = sp->rs_finfo;
31597c478bd9Sstevel@tonic-gate
31600dfe541eSEvan Layton dsp = (rfs4_deleg_state_t *)rfs4_dbsearch(nsrv4->rfs4_deleg_idx, &ds,
3161ed57cab9Srg create, &ds, RFS4_DBS_VALID);
31627c478bd9Sstevel@tonic-gate
31637c478bd9Sstevel@tonic-gate return (dsp);
31647c478bd9Sstevel@tonic-gate }
31657c478bd9Sstevel@tonic-gate
31667c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *
rfs4_finddelegstate(stateid_t * id)31677c478bd9Sstevel@tonic-gate rfs4_finddelegstate(stateid_t *id)
31687c478bd9Sstevel@tonic-gate {
31697c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp;
31707c478bd9Sstevel@tonic-gate bool_t create = FALSE;
31710dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
31727c478bd9Sstevel@tonic-gate
31730dfe541eSEvan Layton dsp = (rfs4_deleg_state_t *)rfs4_dbsearch(nsrv4->rfs4_deleg_state_idx,
31740dfe541eSEvan Layton id, &create, NULL, RFS4_DBS_VALID);
31757c478bd9Sstevel@tonic-gate
31767c478bd9Sstevel@tonic-gate return (dsp);
31777c478bd9Sstevel@tonic-gate }
31787c478bd9Sstevel@tonic-gate
31797c478bd9Sstevel@tonic-gate void
rfs4_deleg_state_rele(rfs4_deleg_state_t * dsp)31807c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(rfs4_deleg_state_t *dsp)
31817c478bd9Sstevel@tonic-gate {
3182d216dff5SRobert Mastors rfs4_dbe_rele(dsp->rds_dbe);
31837c478bd9Sstevel@tonic-gate }
31847c478bd9Sstevel@tonic-gate
31857c478bd9Sstevel@tonic-gate void
rfs4_update_lock_sequence(rfs4_lo_state_t * lsp)31867c478bd9Sstevel@tonic-gate rfs4_update_lock_sequence(rfs4_lo_state_t *lsp)
31877c478bd9Sstevel@tonic-gate {
31887c478bd9Sstevel@tonic-gate
3189d216dff5SRobert Mastors rfs4_dbe_lock(lsp->rls_dbe);
31907c478bd9Sstevel@tonic-gate
31917c478bd9Sstevel@tonic-gate /*
31927c478bd9Sstevel@tonic-gate * If we are skipping sequence id checking, this means that
31937c478bd9Sstevel@tonic-gate * this is the first lock request and therefore the sequence
31947c478bd9Sstevel@tonic-gate * id does not need to be updated. This only happens on the
31957c478bd9Sstevel@tonic-gate * first lock request for a lockowner
31967c478bd9Sstevel@tonic-gate */
3197d216dff5SRobert Mastors if (!lsp->rls_skip_seqid_check)
3198d216dff5SRobert Mastors lsp->rls_seqid++;
31997c478bd9Sstevel@tonic-gate
3200d216dff5SRobert Mastors rfs4_dbe_unlock(lsp->rls_dbe);
32017c478bd9Sstevel@tonic-gate }
32027c478bd9Sstevel@tonic-gate
32037c478bd9Sstevel@tonic-gate void
rfs4_update_lock_resp(rfs4_lo_state_t * lsp,nfs_resop4 * resp)32047c478bd9Sstevel@tonic-gate rfs4_update_lock_resp(rfs4_lo_state_t *lsp, nfs_resop4 *resp)
32057c478bd9Sstevel@tonic-gate {
32067c478bd9Sstevel@tonic-gate
3207d216dff5SRobert Mastors rfs4_dbe_lock(lsp->rls_dbe);
32087c478bd9Sstevel@tonic-gate
3209d216dff5SRobert Mastors rfs4_free_reply(&lsp->rls_reply);
32107c478bd9Sstevel@tonic-gate
3211d216dff5SRobert Mastors rfs4_copy_reply(&lsp->rls_reply, resp);
32127c478bd9Sstevel@tonic-gate
3213d216dff5SRobert Mastors rfs4_dbe_unlock(lsp->rls_dbe);
32147c478bd9Sstevel@tonic-gate }
32157c478bd9Sstevel@tonic-gate
32167c478bd9Sstevel@tonic-gate void
rfs4_free_opens(rfs4_openowner_t * oo,bool_t invalidate,bool_t close_of_client)3217d216dff5SRobert Mastors rfs4_free_opens(rfs4_openowner_t *oo, bool_t invalidate,
3218d216dff5SRobert Mastors bool_t close_of_client)
32197c478bd9Sstevel@tonic-gate {
32207c478bd9Sstevel@tonic-gate rfs4_state_t *sp;
32217c478bd9Sstevel@tonic-gate
3222d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe);
32237c478bd9Sstevel@tonic-gate
3224d216dff5SRobert Mastors for (sp = list_head(&oo->ro_statelist); sp != NULL;
3225d216dff5SRobert Mastors sp = list_next(&oo->ro_statelist, sp)) {
32267c478bd9Sstevel@tonic-gate rfs4_state_close(sp, FALSE, close_of_client, CRED());
32277c478bd9Sstevel@tonic-gate if (invalidate == TRUE)
3228d216dff5SRobert Mastors rfs4_dbe_invalidate(sp->rs_dbe);
32297c478bd9Sstevel@tonic-gate }
32307c478bd9Sstevel@tonic-gate
3231d216dff5SRobert Mastors rfs4_dbe_invalidate(oo->ro_dbe);
3232d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe);
32337c478bd9Sstevel@tonic-gate }
32347c478bd9Sstevel@tonic-gate
32357c478bd9Sstevel@tonic-gate static uint32_t
state_owner_file_hash(void * key)32367c478bd9Sstevel@tonic-gate state_owner_file_hash(void *key)
32377c478bd9Sstevel@tonic-gate {
32387c478bd9Sstevel@tonic-gate rfs4_state_t *sp = key;
32397c478bd9Sstevel@tonic-gate
3240d216dff5SRobert Mastors return (ADDRHASH(sp->rs_owner) ^ ADDRHASH(sp->rs_finfo));
32417c478bd9Sstevel@tonic-gate }
32427c478bd9Sstevel@tonic-gate
32437c478bd9Sstevel@tonic-gate static bool_t
state_owner_file_compare(rfs4_entry_t u_entry,void * key)32447c478bd9Sstevel@tonic-gate state_owner_file_compare(rfs4_entry_t u_entry, void *key)
32457c478bd9Sstevel@tonic-gate {
32467c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
32477c478bd9Sstevel@tonic-gate rfs4_state_t *arg = key;
32487c478bd9Sstevel@tonic-gate
3249d216dff5SRobert Mastors if (sp->rs_closed == TRUE)
32507c478bd9Sstevel@tonic-gate return (FALSE);
32517c478bd9Sstevel@tonic-gate
3252d216dff5SRobert Mastors return (arg->rs_owner == sp->rs_owner && arg->rs_finfo == sp->rs_finfo);
32537c478bd9Sstevel@tonic-gate }
32547c478bd9Sstevel@tonic-gate
32557c478bd9Sstevel@tonic-gate static void *
state_owner_file_mkkey(rfs4_entry_t u_entry)32567c478bd9Sstevel@tonic-gate state_owner_file_mkkey(rfs4_entry_t u_entry)
32577c478bd9Sstevel@tonic-gate {
32587c478bd9Sstevel@tonic-gate return (u_entry);
32597c478bd9Sstevel@tonic-gate }
32607c478bd9Sstevel@tonic-gate
32617c478bd9Sstevel@tonic-gate static uint32_t
state_file_hash(void * key)32627c478bd9Sstevel@tonic-gate state_file_hash(void *key)
32637c478bd9Sstevel@tonic-gate {
32647c478bd9Sstevel@tonic-gate return (ADDRHASH(key));
32657c478bd9Sstevel@tonic-gate }
32667c478bd9Sstevel@tonic-gate
32677c478bd9Sstevel@tonic-gate static bool_t
state_file_compare(rfs4_entry_t u_entry,void * key)32687c478bd9Sstevel@tonic-gate state_file_compare(rfs4_entry_t u_entry, void *key)
32697c478bd9Sstevel@tonic-gate {
32707c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
32717c478bd9Sstevel@tonic-gate rfs4_file_t *fp = key;
32727c478bd9Sstevel@tonic-gate
3273d216dff5SRobert Mastors if (sp->rs_closed == TRUE)
32747c478bd9Sstevel@tonic-gate return (FALSE);
32757c478bd9Sstevel@tonic-gate
3276d216dff5SRobert Mastors return (fp == sp->rs_finfo);
32777c478bd9Sstevel@tonic-gate }
32787c478bd9Sstevel@tonic-gate
32797c478bd9Sstevel@tonic-gate static void *
state_file_mkkey(rfs4_entry_t u_entry)32807c478bd9Sstevel@tonic-gate state_file_mkkey(rfs4_entry_t u_entry)
32817c478bd9Sstevel@tonic-gate {
32827c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
32837c478bd9Sstevel@tonic-gate
3284d216dff5SRobert Mastors return (sp->rs_finfo);
32857c478bd9Sstevel@tonic-gate }
32867c478bd9Sstevel@tonic-gate
32877c478bd9Sstevel@tonic-gate rfs4_state_t *
rfs4_findstate_by_owner_file(rfs4_openowner_t * oo,rfs4_file_t * fp,bool_t * create)3288d216dff5SRobert Mastors rfs4_findstate_by_owner_file(rfs4_openowner_t *oo, rfs4_file_t *fp,
32890dfe541eSEvan Layton bool_t *create)
32907c478bd9Sstevel@tonic-gate {
32917c478bd9Sstevel@tonic-gate rfs4_state_t *sp;
32927c478bd9Sstevel@tonic-gate rfs4_state_t key;
32930dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
32947c478bd9Sstevel@tonic-gate
3295d216dff5SRobert Mastors key.rs_owner = oo;
3296d216dff5SRobert Mastors key.rs_finfo = fp;
32977c478bd9Sstevel@tonic-gate
32980dfe541eSEvan Layton sp = (rfs4_state_t *)rfs4_dbsearch(nsrv4->rfs4_state_owner_file_idx,
32990dfe541eSEvan Layton &key, create, &key, RFS4_DBS_VALID);
33007c478bd9Sstevel@tonic-gate
33017c478bd9Sstevel@tonic-gate return (sp);
33027c478bd9Sstevel@tonic-gate }
33037c478bd9Sstevel@tonic-gate
33047c478bd9Sstevel@tonic-gate /* This returns ANY state struct that refers to this file */
33057c478bd9Sstevel@tonic-gate static rfs4_state_t *
rfs4_findstate_by_file(rfs4_file_t * fp)33067c478bd9Sstevel@tonic-gate rfs4_findstate_by_file(rfs4_file_t *fp)
33077c478bd9Sstevel@tonic-gate {
33087c478bd9Sstevel@tonic-gate bool_t create = FALSE;
33090dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
33107c478bd9Sstevel@tonic-gate
33110dfe541eSEvan Layton return ((rfs4_state_t *)rfs4_dbsearch(nsrv4->rfs4_state_file_idx, fp,
3312ed57cab9Srg &create, fp, RFS4_DBS_VALID));
33137c478bd9Sstevel@tonic-gate }
33147c478bd9Sstevel@tonic-gate
33157c478bd9Sstevel@tonic-gate static bool_t
rfs4_state_expiry(rfs4_entry_t u_entry)33167c478bd9Sstevel@tonic-gate rfs4_state_expiry(rfs4_entry_t u_entry)
33177c478bd9Sstevel@tonic-gate {
33187c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
33197c478bd9Sstevel@tonic-gate
3320d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(sp->rs_dbe))
33217c478bd9Sstevel@tonic-gate return (TRUE);
33227c478bd9Sstevel@tonic-gate
3323d216dff5SRobert Mastors if (sp->rs_closed == TRUE &&
3324d216dff5SRobert Mastors ((gethrestime_sec() - rfs4_dbe_get_timerele(sp->rs_dbe))
3325ed57cab9Srg > rfs4_lease_time))
33267c478bd9Sstevel@tonic-gate return (TRUE);
33277c478bd9Sstevel@tonic-gate
3328d216dff5SRobert Mastors return ((gethrestime_sec() - sp->rs_owner->ro_client->rc_last_access
3329ed57cab9Srg > rfs4_lease_time));
33307c478bd9Sstevel@tonic-gate }
33317c478bd9Sstevel@tonic-gate
33327c478bd9Sstevel@tonic-gate static bool_t
rfs4_state_create(rfs4_entry_t u_entry,void * argp)33337c478bd9Sstevel@tonic-gate rfs4_state_create(rfs4_entry_t u_entry, void *argp)
33347c478bd9Sstevel@tonic-gate {
33357c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
3336d216dff5SRobert Mastors rfs4_file_t *fp = ((rfs4_state_t *)argp)->rs_finfo;
3337d216dff5SRobert Mastors rfs4_openowner_t *oo = ((rfs4_state_t *)argp)->rs_owner;
33387c478bd9Sstevel@tonic-gate
3339d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe);
3340d216dff5SRobert Mastors rfs4_dbe_hold(oo->ro_dbe);
3341d216dff5SRobert Mastors sp->rs_stateid = get_stateid(rfs4_dbe_getid(sp->rs_dbe));
3342d216dff5SRobert Mastors sp->rs_stateid.bits.type = OPENID;
3343d216dff5SRobert Mastors sp->rs_owner = oo;
3344d216dff5SRobert Mastors sp->rs_finfo = fp;
33457c478bd9Sstevel@tonic-gate
3346d216dff5SRobert Mastors list_create(&sp->rs_lostatelist, sizeof (rfs4_lo_state_t),
3347d216dff5SRobert Mastors offsetof(rfs4_lo_state_t, rls_node));
33487c478bd9Sstevel@tonic-gate
3349d216dff5SRobert Mastors /* Insert state on per open owner's list */
3350d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe);
3351d216dff5SRobert Mastors list_insert_tail(&oo->ro_statelist, sp);
3352d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe);
33537c478bd9Sstevel@tonic-gate
33547c478bd9Sstevel@tonic-gate return (TRUE);
33557c478bd9Sstevel@tonic-gate }
33567c478bd9Sstevel@tonic-gate
33577c478bd9Sstevel@tonic-gate static rfs4_state_t *
rfs4_findstate(stateid_t * id,rfs4_dbsearch_type_t find_invalid,bool_t lock_fp)3358d216dff5SRobert Mastors rfs4_findstate(stateid_t *id, rfs4_dbsearch_type_t find_invalid, bool_t lock_fp)
33597c478bd9Sstevel@tonic-gate {
33607c478bd9Sstevel@tonic-gate rfs4_state_t *sp;
33617c478bd9Sstevel@tonic-gate bool_t create = FALSE;
33620dfe541eSEvan Layton nfs4_srv_t *nsrv4 = nfs4_get_srv();
33637c478bd9Sstevel@tonic-gate
33640dfe541eSEvan Layton sp = (rfs4_state_t *)rfs4_dbsearch(nsrv4->rfs4_state_idx, id,
3365ed57cab9Srg &create, NULL, find_invalid);
33667c478bd9Sstevel@tonic-gate if (lock_fp == TRUE && sp != NULL)
3367d216dff5SRobert Mastors rw_enter(&sp->rs_finfo->rf_file_rwlock, RW_READER);
33687c478bd9Sstevel@tonic-gate
33697c478bd9Sstevel@tonic-gate return (sp);
33707c478bd9Sstevel@tonic-gate }
33717c478bd9Sstevel@tonic-gate
33727c478bd9Sstevel@tonic-gate void
rfs4_state_close(rfs4_state_t * sp,bool_t lock_held,bool_t close_of_client,cred_t * cr)3373d216dff5SRobert Mastors rfs4_state_close(rfs4_state_t *sp, bool_t lock_held, bool_t close_of_client,
3374d216dff5SRobert Mastors cred_t *cr)
33757c478bd9Sstevel@tonic-gate {
33767c478bd9Sstevel@tonic-gate /* Remove the associated lo_state owners */
33777c478bd9Sstevel@tonic-gate if (!lock_held)
3378d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe);
33797c478bd9Sstevel@tonic-gate
3380c420ca07Smaheshvs /*
3381c420ca07Smaheshvs * If refcnt == 0, the dbe is about to be destroyed.
3382c420ca07Smaheshvs * lock state will be released by the reaper thread.
3383c420ca07Smaheshvs */
3384c420ca07Smaheshvs
3385d216dff5SRobert Mastors if (rfs4_dbe_refcnt(sp->rs_dbe) > 0) {
3386d216dff5SRobert Mastors if (sp->rs_closed == FALSE) {
3387c420ca07Smaheshvs rfs4_release_share_lock_state(sp, cr, close_of_client);
3388d216dff5SRobert Mastors sp->rs_closed = TRUE;
3389c420ca07Smaheshvs }
33907c478bd9Sstevel@tonic-gate }
3391c420ca07Smaheshvs
33927c478bd9Sstevel@tonic-gate if (!lock_held)
3393d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe);
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate
33967c478bd9Sstevel@tonic-gate /*
33977c478bd9Sstevel@tonic-gate * Remove all state associated with the given client.
33987c478bd9Sstevel@tonic-gate */
33997c478bd9Sstevel@tonic-gate void
rfs4_client_state_remove(rfs4_client_t * cp)34007c478bd9Sstevel@tonic-gate rfs4_client_state_remove(rfs4_client_t *cp)
34017c478bd9Sstevel@tonic-gate {
3402d216dff5SRobert Mastors rfs4_openowner_t *oo;
34037c478bd9Sstevel@tonic-gate
3404d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe);
34057c478bd9Sstevel@tonic-gate
3406d216dff5SRobert Mastors for (oo = list_head(&cp->rc_openownerlist); oo != NULL;
3407d216dff5SRobert Mastors oo = list_next(&cp->rc_openownerlist, oo)) {
3408d216dff5SRobert Mastors rfs4_free_opens(oo, TRUE, TRUE);
34097c478bd9Sstevel@tonic-gate }
34107c478bd9Sstevel@tonic-gate
3411d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe);
34127c478bd9Sstevel@tonic-gate }
34137c478bd9Sstevel@tonic-gate
34147c478bd9Sstevel@tonic-gate void
rfs4_client_close(rfs4_client_t * cp)34157c478bd9Sstevel@tonic-gate rfs4_client_close(rfs4_client_t *cp)
34167c478bd9Sstevel@tonic-gate {
34177c478bd9Sstevel@tonic-gate /* Mark client as going away. */
3418d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe);
3419d216dff5SRobert Mastors rfs4_dbe_invalidate(cp->rc_dbe);
3420d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe);
34217c478bd9Sstevel@tonic-gate
34227c478bd9Sstevel@tonic-gate rfs4_client_state_remove(cp);
3423*f44e1126SVitaliy Gusev rfs4x_client_session_remove(cp);
34247c478bd9Sstevel@tonic-gate
34257c478bd9Sstevel@tonic-gate /* Release the client */
34267c478bd9Sstevel@tonic-gate rfs4_client_rele(cp);
34277c478bd9Sstevel@tonic-gate }
34287c478bd9Sstevel@tonic-gate
34297c478bd9Sstevel@tonic-gate nfsstat4
rfs4_check_clientid(clientid4 * cp,int setclid_confirm)34307c478bd9Sstevel@tonic-gate rfs4_check_clientid(clientid4 *cp, int setclid_confirm)
34317c478bd9Sstevel@tonic-gate {
34327c478bd9Sstevel@tonic-gate cid *cidp = (cid *) cp;
34330dfe541eSEvan Layton nfs4_srv_t *nsrv4;
34340dfe541eSEvan Layton
34350dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
34367c478bd9Sstevel@tonic-gate
34377c478bd9Sstevel@tonic-gate /*
34387c478bd9Sstevel@tonic-gate * If we are booted as a cluster node, check the embedded nodeid.
34397c478bd9Sstevel@tonic-gate * If it indicates that this clientid was generated on another node,
34407c478bd9Sstevel@tonic-gate * inform the client accordingly.
34417c478bd9Sstevel@tonic-gate */
34427c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED && foreign_clientid(cidp))
34437c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_CLIENTID);
34447c478bd9Sstevel@tonic-gate
34457c478bd9Sstevel@tonic-gate /*
34467c478bd9Sstevel@tonic-gate * If the server start time matches the time provided
34477c478bd9Sstevel@tonic-gate * by the client (via the clientid) and this is NOT a
34487c478bd9Sstevel@tonic-gate * setclientid_confirm then return EXPIRED.
34497c478bd9Sstevel@tonic-gate */
34500dfe541eSEvan Layton if (!setclid_confirm &&
34510dfe541eSEvan Layton cidp->impl_id.start_time == nsrv4->rfs4_start_time)
34527c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED);
34537c478bd9Sstevel@tonic-gate
34547c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_CLIENTID);
34557c478bd9Sstevel@tonic-gate }
34567c478bd9Sstevel@tonic-gate
34577c478bd9Sstevel@tonic-gate /*
34587c478bd9Sstevel@tonic-gate * This is used when a stateid has not been found amongst the
34597c478bd9Sstevel@tonic-gate * current server's state. Check the stateid to see if it
34607c478bd9Sstevel@tonic-gate * was from this server instantiation or not.
34617c478bd9Sstevel@tonic-gate */
34627c478bd9Sstevel@tonic-gate static nfsstat4
what_stateid_error(stateid_t * id,stateid_type_t type)34637c478bd9Sstevel@tonic-gate what_stateid_error(stateid_t *id, stateid_type_t type)
34647c478bd9Sstevel@tonic-gate {
34650dfe541eSEvan Layton nfs4_srv_t *nsrv4;
34660dfe541eSEvan Layton
34670dfe541eSEvan Layton nsrv4 = nfs4_get_srv();
34680dfe541eSEvan Layton
34697c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */
34707c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id))
34717c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID);
34727c478bd9Sstevel@tonic-gate
34737c478bd9Sstevel@tonic-gate /* If types don't match then no use checking further */
34747c478bd9Sstevel@tonic-gate if (type != id->bits.type)
34757c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
34767c478bd9Sstevel@tonic-gate
347725a1318cSMarcel Telka /* From a different server instantiation, return STALE */
34780dfe541eSEvan Layton if (id->bits.boottime != nsrv4->rfs4_start_time)
34797c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID);
34807c478bd9Sstevel@tonic-gate
34817c478bd9Sstevel@tonic-gate /*
34827c478bd9Sstevel@tonic-gate * From this server but the state is most likely beyond lease
34837c478bd9Sstevel@tonic-gate * timeout: return NFS4ERR_EXPIRED. However, there is the
34847c478bd9Sstevel@tonic-gate * case of a delegation stateid. For delegations, there is a
34857c478bd9Sstevel@tonic-gate * case where the state can be removed without the client's
34867c478bd9Sstevel@tonic-gate * knowledge/consent: revocation. In the case of delegation
34877c478bd9Sstevel@tonic-gate * revocation, the delegation state will be removed and will
34887c478bd9Sstevel@tonic-gate * not be found. If the client does something like a
34897c478bd9Sstevel@tonic-gate * DELEGRETURN or even a READ/WRITE with a delegatoin stateid
34907c478bd9Sstevel@tonic-gate * that has been revoked, the server should return BAD_STATEID
34917c478bd9Sstevel@tonic-gate * instead of the more common EXPIRED error.
34927c478bd9Sstevel@tonic-gate */
34930dfe541eSEvan Layton if (id->bits.boottime == nsrv4->rfs4_start_time) {
34947c478bd9Sstevel@tonic-gate if (type == DELEGID)
34957c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
34967c478bd9Sstevel@tonic-gate else
34977c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED);
34987c478bd9Sstevel@tonic-gate }
34997c478bd9Sstevel@tonic-gate
35007c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
35017c478bd9Sstevel@tonic-gate }
35027c478bd9Sstevel@tonic-gate
35037c478bd9Sstevel@tonic-gate /*
35047c478bd9Sstevel@tonic-gate * Used later on to find the various state structs. When called from
35057c478bd9Sstevel@tonic-gate * rfs4_check_stateid()->rfs4_get_all_state(), no file struct lock is
35067c478bd9Sstevel@tonic-gate * taken (it is not needed) and helps on the read/write path with
35077c478bd9Sstevel@tonic-gate * respect to performance.
35087c478bd9Sstevel@tonic-gate */
35097c478bd9Sstevel@tonic-gate static nfsstat4
rfs4_get_state_lockit(stateid4 * stateid,rfs4_state_t ** spp,rfs4_dbsearch_type_t find_invalid,bool_t lock_fp)35107c478bd9Sstevel@tonic-gate rfs4_get_state_lockit(stateid4 *stateid, rfs4_state_t **spp,
3511d216dff5SRobert Mastors rfs4_dbsearch_type_t find_invalid, bool_t lock_fp)
35127c478bd9Sstevel@tonic-gate {
35137c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid;
35147c478bd9Sstevel@tonic-gate rfs4_state_t *sp;
35157c478bd9Sstevel@tonic-gate
35167c478bd9Sstevel@tonic-gate *spp = NULL;
35177c478bd9Sstevel@tonic-gate
35187c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */
35197c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id))
35207c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID);
35217c478bd9Sstevel@tonic-gate
35227c478bd9Sstevel@tonic-gate sp = rfs4_findstate(id, find_invalid, lock_fp);
35237c478bd9Sstevel@tonic-gate if (sp == NULL) {
35247c478bd9Sstevel@tonic-gate return (what_stateid_error(id, OPENID));
35257c478bd9Sstevel@tonic-gate }
35267c478bd9Sstevel@tonic-gate
3527d216dff5SRobert Mastors if (rfs4_lease_expired(sp->rs_owner->ro_client)) {
35287c478bd9Sstevel@tonic-gate if (lock_fp == TRUE)
35297c478bd9Sstevel@tonic-gate rfs4_state_rele(sp);
35307c478bd9Sstevel@tonic-gate else
35317c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
35327c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED);
35337c478bd9Sstevel@tonic-gate }
35347c478bd9Sstevel@tonic-gate
35357c478bd9Sstevel@tonic-gate *spp = sp;
35367c478bd9Sstevel@tonic-gate
35377c478bd9Sstevel@tonic-gate return (NFS4_OK);
35387c478bd9Sstevel@tonic-gate }
35397c478bd9Sstevel@tonic-gate
35407c478bd9Sstevel@tonic-gate nfsstat4
rfs4_get_state(stateid4 * stateid,rfs4_state_t ** spp,rfs4_dbsearch_type_t find_invalid)35417c478bd9Sstevel@tonic-gate rfs4_get_state(stateid4 *stateid, rfs4_state_t **spp,
3542d216dff5SRobert Mastors rfs4_dbsearch_type_t find_invalid)
35437c478bd9Sstevel@tonic-gate {
35447c478bd9Sstevel@tonic-gate return (rfs4_get_state_lockit(stateid, spp, find_invalid, TRUE));
35457c478bd9Sstevel@tonic-gate }
35467c478bd9Sstevel@tonic-gate
35477c478bd9Sstevel@tonic-gate int
rfs4_check_stateid_seqid(rfs4_state_t * sp,stateid4 * stateid,const compound_state_t * cs)3548*f44e1126SVitaliy Gusev rfs4_check_stateid_seqid(rfs4_state_t *sp, stateid4 *stateid,
3549*f44e1126SVitaliy Gusev const compound_state_t *cs)
35507c478bd9Sstevel@tonic-gate {
35517c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid;
3552*f44e1126SVitaliy Gusev bool_t has_session = rfs4_has_session(cs);
35537c478bd9Sstevel@tonic-gate
3554d216dff5SRobert Mastors if (rfs4_lease_expired(sp->rs_owner->ro_client))
35557c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_EXPIRED);
35567c478bd9Sstevel@tonic-gate
3557*f44e1126SVitaliy Gusev if (has_session && id->bits.chgseq == 0)
3558*f44e1126SVitaliy Gusev return (NFS4_CHECK_STATEID_OKAY);
3559*f44e1126SVitaliy Gusev
35607c478bd9Sstevel@tonic-gate /* Stateid is some time in the future - that's bad */
3561d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq < id->bits.chgseq)
35627c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_BAD);
35637c478bd9Sstevel@tonic-gate
3564*f44e1126SVitaliy Gusev if (!has_session &&
3565*f44e1126SVitaliy Gusev sp->rs_stateid.bits.chgseq == id->bits.chgseq + 1) {
35667c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_REPLAY);
3567*f44e1126SVitaliy Gusev }
35687c478bd9Sstevel@tonic-gate
35697c478bd9Sstevel@tonic-gate /* Stateid is some time in the past - that's old */
3570d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq > id->bits.chgseq)
35717c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OLD);
35727c478bd9Sstevel@tonic-gate
35737c478bd9Sstevel@tonic-gate /* Caller needs to know about confirmation before closure */
3574d216dff5SRobert Mastors if (sp->rs_owner->ro_need_confirm)
35757c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_UNCONFIRMED);
35767c478bd9Sstevel@tonic-gate
3577d216dff5SRobert Mastors if (sp->rs_closed == TRUE)
35787c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_CLOSED);
35797c478bd9Sstevel@tonic-gate
35807c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OKAY);
35817c478bd9Sstevel@tonic-gate }
35827c478bd9Sstevel@tonic-gate
35837c478bd9Sstevel@tonic-gate int
rfs4_check_lo_stateid_seqid(rfs4_lo_state_t * lsp,stateid4 * stateid,const compound_state_t * cs)3584*f44e1126SVitaliy Gusev rfs4_check_lo_stateid_seqid(rfs4_lo_state_t *lsp, stateid4 *stateid,
3585*f44e1126SVitaliy Gusev const compound_state_t *cs)
35867c478bd9Sstevel@tonic-gate {
35877c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid;
3588*f44e1126SVitaliy Gusev bool_t has_session = rfs4_has_session(cs);
35897c478bd9Sstevel@tonic-gate
3590d216dff5SRobert Mastors if (rfs4_lease_expired(lsp->rls_state->rs_owner->ro_client))
35917c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_EXPIRED);
35927c478bd9Sstevel@tonic-gate
3593*f44e1126SVitaliy Gusev if (has_session && id->bits.chgseq == 0)
3594*f44e1126SVitaliy Gusev return (NFS4_CHECK_STATEID_OKAY);
3595*f44e1126SVitaliy Gusev
35967c478bd9Sstevel@tonic-gate /* Stateid is some time in the future - that's bad */
3597d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq < id->bits.chgseq)
35987c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_BAD);
35997c478bd9Sstevel@tonic-gate
3600*f44e1126SVitaliy Gusev if (!has_session &&
3601*f44e1126SVitaliy Gusev lsp->rls_lockid.bits.chgseq == id->bits.chgseq + 1) {
36027c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_REPLAY);
3603*f44e1126SVitaliy Gusev }
36047c478bd9Sstevel@tonic-gate
36057c478bd9Sstevel@tonic-gate /* Stateid is some time in the past - that's old */
3606d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq > id->bits.chgseq)
36077c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OLD);
36087c478bd9Sstevel@tonic-gate
3609d216dff5SRobert Mastors if (lsp->rls_state->rs_closed == TRUE)
3610d216dff5SRobert Mastors return (NFS4_CHECK_STATEID_CLOSED);
3611d216dff5SRobert Mastors
36127c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OKAY);
36137c478bd9Sstevel@tonic-gate }
36147c478bd9Sstevel@tonic-gate
36157c478bd9Sstevel@tonic-gate nfsstat4
rfs4_get_deleg_state(stateid4 * stateid,rfs4_deleg_state_t ** dspp)36167c478bd9Sstevel@tonic-gate rfs4_get_deleg_state(stateid4 *stateid, rfs4_deleg_state_t **dspp)
36177c478bd9Sstevel@tonic-gate {
36187c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid;
36197c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp;
36207c478bd9Sstevel@tonic-gate
36217c478bd9Sstevel@tonic-gate *dspp = NULL;
36227c478bd9Sstevel@tonic-gate
36237c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */
36247c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id))
36257c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID);
36267c478bd9Sstevel@tonic-gate
36277c478bd9Sstevel@tonic-gate dsp = rfs4_finddelegstate(id);
36287c478bd9Sstevel@tonic-gate if (dsp == NULL) {
36297c478bd9Sstevel@tonic-gate return (what_stateid_error(id, DELEGID));
36307c478bd9Sstevel@tonic-gate }
36317c478bd9Sstevel@tonic-gate
3632d216dff5SRobert Mastors if (rfs4_lease_expired(dsp->rds_client)) {
36337c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp);
36347c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED);
36357c478bd9Sstevel@tonic-gate }
36367c478bd9Sstevel@tonic-gate
36377c478bd9Sstevel@tonic-gate *dspp = dsp;
36387c478bd9Sstevel@tonic-gate
36397c478bd9Sstevel@tonic-gate return (NFS4_OK);
36407c478bd9Sstevel@tonic-gate }
36417c478bd9Sstevel@tonic-gate
36427c478bd9Sstevel@tonic-gate nfsstat4
rfs4_get_lo_state(stateid4 * stateid,rfs4_lo_state_t ** lspp,bool_t lock_fp)36437c478bd9Sstevel@tonic-gate rfs4_get_lo_state(stateid4 *stateid, rfs4_lo_state_t **lspp, bool_t lock_fp)
36447c478bd9Sstevel@tonic-gate {
36457c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid;
36467c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp;
36477c478bd9Sstevel@tonic-gate
36487c478bd9Sstevel@tonic-gate *lspp = NULL;
36497c478bd9Sstevel@tonic-gate
36507c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */
36517c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id))
36527c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID);
36537c478bd9Sstevel@tonic-gate
36547c478bd9Sstevel@tonic-gate lsp = rfs4_findlo_state(id, lock_fp);
36557c478bd9Sstevel@tonic-gate if (lsp == NULL) {
36567c478bd9Sstevel@tonic-gate return (what_stateid_error(id, LOCKID));
36577c478bd9Sstevel@tonic-gate }
36587c478bd9Sstevel@tonic-gate
3659d216dff5SRobert Mastors if (rfs4_lease_expired(lsp->rls_state->rs_owner->ro_client)) {
36607c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, lock_fp);
36617c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED);
36627c478bd9Sstevel@tonic-gate }
36637c478bd9Sstevel@tonic-gate
36647c478bd9Sstevel@tonic-gate *lspp = lsp;
36657c478bd9Sstevel@tonic-gate
36667c478bd9Sstevel@tonic-gate return (NFS4_OK);
36677c478bd9Sstevel@tonic-gate }
36687c478bd9Sstevel@tonic-gate
36697c478bd9Sstevel@tonic-gate static nfsstat4
rfs4_get_all_state(stateid4 * sid,rfs4_state_t ** spp,rfs4_deleg_state_t ** dspp,rfs4_lo_state_t ** lspp)36707c478bd9Sstevel@tonic-gate rfs4_get_all_state(stateid4 *sid, rfs4_state_t **spp,
3671d216dff5SRobert Mastors rfs4_deleg_state_t **dspp, rfs4_lo_state_t **lspp)
36727c478bd9Sstevel@tonic-gate {
36737c478bd9Sstevel@tonic-gate rfs4_state_t *sp = NULL;
36747c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = NULL;
3675d216dff5SRobert Mastors rfs4_lo_state_t *lsp = NULL;
36767c478bd9Sstevel@tonic-gate stateid_t *id;
36777c478bd9Sstevel@tonic-gate nfsstat4 status;
36787c478bd9Sstevel@tonic-gate
3679d216dff5SRobert Mastors *spp = NULL; *dspp = NULL; *lspp = NULL;
36807c478bd9Sstevel@tonic-gate
36817c478bd9Sstevel@tonic-gate id = (stateid_t *)sid;
36827c478bd9Sstevel@tonic-gate switch (id->bits.type) {
36837c478bd9Sstevel@tonic-gate case OPENID:
36847c478bd9Sstevel@tonic-gate status = rfs4_get_state_lockit(sid, &sp, FALSE, FALSE);
36857c478bd9Sstevel@tonic-gate break;
36867c478bd9Sstevel@tonic-gate case DELEGID:
36877c478bd9Sstevel@tonic-gate status = rfs4_get_deleg_state(sid, &dsp);
36887c478bd9Sstevel@tonic-gate break;
36897c478bd9Sstevel@tonic-gate case LOCKID:
3690d216dff5SRobert Mastors status = rfs4_get_lo_state(sid, &lsp, FALSE);
36917c478bd9Sstevel@tonic-gate if (status == NFS4_OK) {
3692d216dff5SRobert Mastors sp = lsp->rls_state;
3693d216dff5SRobert Mastors rfs4_dbe_hold(sp->rs_dbe);
36947c478bd9Sstevel@tonic-gate }
36957c478bd9Sstevel@tonic-gate break;
36967c478bd9Sstevel@tonic-gate default:
36977c478bd9Sstevel@tonic-gate status = NFS4ERR_BAD_STATEID;
36987c478bd9Sstevel@tonic-gate }
36997c478bd9Sstevel@tonic-gate
37007c478bd9Sstevel@tonic-gate if (status == NFS4_OK) {
37017c478bd9Sstevel@tonic-gate *spp = sp;
37027c478bd9Sstevel@tonic-gate *dspp = dsp;
3703d216dff5SRobert Mastors *lspp = lsp;
37047c478bd9Sstevel@tonic-gate }
37057c478bd9Sstevel@tonic-gate
37067c478bd9Sstevel@tonic-gate return (status);
37077c478bd9Sstevel@tonic-gate }
37087c478bd9Sstevel@tonic-gate
37097c478bd9Sstevel@tonic-gate /*
37107c478bd9Sstevel@tonic-gate * Given the I/O mode (FREAD or FWRITE), this checks whether the
37117c478bd9Sstevel@tonic-gate * rfs4_state_t struct has access to do this operation and if so
37127c478bd9Sstevel@tonic-gate * return NFS4_OK; otherwise the proper NFSv4 error is returned.
37137c478bd9Sstevel@tonic-gate */
37147c478bd9Sstevel@tonic-gate nfsstat4
rfs4_state_has_access(rfs4_state_t * sp,int mode,vnode_t * vp)37157c478bd9Sstevel@tonic-gate rfs4_state_has_access(rfs4_state_t *sp, int mode, vnode_t *vp)
37167c478bd9Sstevel@tonic-gate {
37177c478bd9Sstevel@tonic-gate nfsstat4 stat = NFS4_OK;
37187c478bd9Sstevel@tonic-gate rfs4_file_t *fp;
37197c478bd9Sstevel@tonic-gate bool_t create = FALSE;
37207c478bd9Sstevel@tonic-gate
3721d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe);
37227c478bd9Sstevel@tonic-gate if (mode == FWRITE) {
3723d216dff5SRobert Mastors if (!(sp->rs_share_access & OPEN4_SHARE_ACCESS_WRITE)) {
37247c478bd9Sstevel@tonic-gate stat = NFS4ERR_OPENMODE;
37257c478bd9Sstevel@tonic-gate }
37267c478bd9Sstevel@tonic-gate } else if (mode == FREAD) {
3727d216dff5SRobert Mastors if (!(sp->rs_share_access & OPEN4_SHARE_ACCESS_READ)) {
37287c478bd9Sstevel@tonic-gate /*
37297c478bd9Sstevel@tonic-gate * If we have OPENed the file with DENYing access
37307c478bd9Sstevel@tonic-gate * to both READ and WRITE then no one else could
37317c478bd9Sstevel@tonic-gate * have OPENed the file, hence no conflicting READ
37327c478bd9Sstevel@tonic-gate * deny. This check is merely an optimization.
37337c478bd9Sstevel@tonic-gate */
3734d216dff5SRobert Mastors if (sp->rs_share_deny == OPEN4_SHARE_DENY_BOTH)
37357c478bd9Sstevel@tonic-gate goto out;
37367c478bd9Sstevel@tonic-gate
37377c478bd9Sstevel@tonic-gate /* Check against file struct's DENY mode */
37387c478bd9Sstevel@tonic-gate fp = rfs4_findfile(vp, NULL, &create);
37397c478bd9Sstevel@tonic-gate if (fp != NULL) {
37407c478bd9Sstevel@tonic-gate int deny_read = 0;
3741d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe);
37427c478bd9Sstevel@tonic-gate /*
37437c478bd9Sstevel@tonic-gate * Check if any other open owner has the file
37447c478bd9Sstevel@tonic-gate * OPENed with deny READ.
37457c478bd9Sstevel@tonic-gate */
3746d216dff5SRobert Mastors if (sp->rs_share_deny & OPEN4_SHARE_DENY_READ)
37477c478bd9Sstevel@tonic-gate deny_read = 1;
3748eec118a1SMarcel Telka ASSERT(fp->rf_deny_read >= deny_read);
3749eec118a1SMarcel Telka if (fp->rf_deny_read > deny_read)
37507c478bd9Sstevel@tonic-gate stat = NFS4ERR_OPENMODE;
3751d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
37527c478bd9Sstevel@tonic-gate rfs4_file_rele(fp);
37537c478bd9Sstevel@tonic-gate }
37547c478bd9Sstevel@tonic-gate }
37557c478bd9Sstevel@tonic-gate } else {
37567c478bd9Sstevel@tonic-gate /* Illegal I/O mode */
37577c478bd9Sstevel@tonic-gate stat = NFS4ERR_INVAL;
37587c478bd9Sstevel@tonic-gate }
37597c478bd9Sstevel@tonic-gate out:
3760d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe);
37617c478bd9Sstevel@tonic-gate return (stat);
37627c478bd9Sstevel@tonic-gate }
37637c478bd9Sstevel@tonic-gate
3764*f44e1126SVitaliy Gusev static nfsstat4
check_state_seqid(stateid_t * st,stateid_t * in,bool_t has_session)3765*f44e1126SVitaliy Gusev check_state_seqid(stateid_t *st, stateid_t *in, bool_t has_session)
3766*f44e1126SVitaliy Gusev {
3767*f44e1126SVitaliy Gusev /* rfc56661, section 8.2.2, "seqid to zero" */
3768*f44e1126SVitaliy Gusev if (has_session && in->bits.chgseq == 0)
3769*f44e1126SVitaliy Gusev return (NFS4_OK);
3770*f44e1126SVitaliy Gusev
3771*f44e1126SVitaliy Gusev /* Seqid in the future? - that's bad */
3772*f44e1126SVitaliy Gusev if (st->bits.chgseq < in->bits.chgseq)
3773*f44e1126SVitaliy Gusev return (NFS4ERR_BAD_STATEID);
3774*f44e1126SVitaliy Gusev
3775*f44e1126SVitaliy Gusev /* Seqid in the past? - that's old */
3776*f44e1126SVitaliy Gusev if (st->bits.chgseq > in->bits.chgseq)
3777*f44e1126SVitaliy Gusev return (NFS4ERR_OLD_STATEID);
3778*f44e1126SVitaliy Gusev
3779*f44e1126SVitaliy Gusev return (NFS4_OK);
3780*f44e1126SVitaliy Gusev }
3781*f44e1126SVitaliy Gusev
37827c478bd9Sstevel@tonic-gate /*
37837c478bd9Sstevel@tonic-gate * Given the I/O mode (FREAD or FWRITE), the vnode, the stateid and whether
3784da6c28aaSamw * the file is being truncated, return NFS4_OK if allowed or appropriate
37857c478bd9Sstevel@tonic-gate * V4 error if not. Note NFS4ERR_DELAY will be returned and a recall on
37867c478bd9Sstevel@tonic-gate * the associated file will be done if the I/O is not consistent with any
37877c478bd9Sstevel@tonic-gate * delegation in effect on the file. Should be holding VOP_RWLOCK, either
3788da6c28aaSamw * as reader or writer as appropriate. rfs4_op_open will acquire the
37897c478bd9Sstevel@tonic-gate * VOP_RWLOCK as writer when setting up delegation. If the stateid is bad
37907c478bd9Sstevel@tonic-gate * this routine will return NFS4ERR_BAD_STATEID. In addition, through the
37917c478bd9Sstevel@tonic-gate * deleg parameter, we will return whether a write delegation is held by
37927c478bd9Sstevel@tonic-gate * the client associated with this stateid.
37937c478bd9Sstevel@tonic-gate * If the server instance associated with the relevant client is in its
37947c478bd9Sstevel@tonic-gate * grace period, return NFS4ERR_GRACE.
37957c478bd9Sstevel@tonic-gate */
37967c478bd9Sstevel@tonic-gate
37977c478bd9Sstevel@tonic-gate nfsstat4
rfs4_check_stateid(int mode,vnode_t * vp,stateid4 * stateid,bool_t trunc,bool_t * deleg,bool_t do_access,caller_context_t * ct,compound_state_t * cs)37987c478bd9Sstevel@tonic-gate rfs4_check_stateid(int mode, vnode_t *vp,
3799d216dff5SRobert Mastors stateid4 *stateid, bool_t trunc, bool_t *deleg,
3800*f44e1126SVitaliy Gusev bool_t do_access, caller_context_t *ct, compound_state_t *cs)
38017c478bd9Sstevel@tonic-gate {
38027c478bd9Sstevel@tonic-gate rfs4_file_t *fp;
38037c478bd9Sstevel@tonic-gate bool_t create = FALSE;
38047c478bd9Sstevel@tonic-gate rfs4_state_t *sp;
38057c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp;
38067c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp;
38077c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid;
38087c478bd9Sstevel@tonic-gate nfsstat4 stat = NFS4_OK;
3809*f44e1126SVitaliy Gusev bool_t use_ss = rfs4_has_session(cs);
38107c478bd9Sstevel@tonic-gate
3811da6c28aaSamw if (ct != NULL) {
3812da6c28aaSamw ct->cc_sysid = 0;
3813da6c28aaSamw ct->cc_pid = 0;
3814da6c28aaSamw ct->cc_caller_id = nfs4_srv_caller_id;
381562b9fcbeSjwahlig ct->cc_flags = CC_DONTBLOCK;
3816da6c28aaSamw }
3817da6c28aaSamw
38187c478bd9Sstevel@tonic-gate if (ISSPECIAL(stateid)) {
38197c478bd9Sstevel@tonic-gate fp = rfs4_findfile(vp, NULL, &create);
38207c478bd9Sstevel@tonic-gate if (fp == NULL)
38217c478bd9Sstevel@tonic-gate return (NFS4_OK);
3822*f44e1126SVitaliy Gusev
3823d216dff5SRobert Mastors if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
38247c478bd9Sstevel@tonic-gate rfs4_file_rele(fp);
38257c478bd9Sstevel@tonic-gate return (NFS4_OK);
38267c478bd9Sstevel@tonic-gate }
38277c478bd9Sstevel@tonic-gate if (mode == FWRITE ||
3828d216dff5SRobert Mastors fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE) {
38297c478bd9Sstevel@tonic-gate rfs4_recall_deleg(fp, trunc, NULL);
38307c478bd9Sstevel@tonic-gate rfs4_file_rele(fp);
38317c478bd9Sstevel@tonic-gate return (NFS4ERR_DELAY);
38327c478bd9Sstevel@tonic-gate }
38337c478bd9Sstevel@tonic-gate rfs4_file_rele(fp);
38347c478bd9Sstevel@tonic-gate return (NFS4_OK);
38357c478bd9Sstevel@tonic-gate } else {
38367c478bd9Sstevel@tonic-gate stat = rfs4_get_all_state(stateid, &sp, &dsp, &lsp);
38377c478bd9Sstevel@tonic-gate if (stat != NFS4_OK)
38387c478bd9Sstevel@tonic-gate return (stat);
3839*f44e1126SVitaliy Gusev
38407c478bd9Sstevel@tonic-gate if (lsp != NULL) {
38417c478bd9Sstevel@tonic-gate /* Is associated server instance in its grace period? */
3842d216dff5SRobert Mastors if (rfs4_clnt_in_grace(lsp->rls_locker->rl_client)) {
38437c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE);
38447c478bd9Sstevel@tonic-gate if (sp != NULL)
38457c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
38467c478bd9Sstevel@tonic-gate return (NFS4ERR_GRACE);
38477c478bd9Sstevel@tonic-gate }
3848*f44e1126SVitaliy Gusev
3849*f44e1126SVitaliy Gusev ASSERT(id->bits.type == LOCKID);
3850*f44e1126SVitaliy Gusev stat = check_state_seqid(&lsp->rls_lockid, id, use_ss);
3851*f44e1126SVitaliy Gusev if (stat) {
3852*f44e1126SVitaliy Gusev rfs4_lo_state_rele(lsp, FALSE);
3853*f44e1126SVitaliy Gusev if (sp)
3854*f44e1126SVitaliy Gusev rfs4_state_rele_nounlock(sp);
3855*f44e1126SVitaliy Gusev return (stat);
3856a57549b4SVitaliy Gusev }
3857*f44e1126SVitaliy Gusev
3858*f44e1126SVitaliy Gusev /* Ensure specified filehandle matches */
3859*f44e1126SVitaliy Gusev if (lsp->rls_state->rs_finfo->rf_vp != vp) {
3860*f44e1126SVitaliy Gusev rfs4_lo_state_rele(lsp, FALSE);
3861*f44e1126SVitaliy Gusev if (sp != NULL)
3862*f44e1126SVitaliy Gusev rfs4_state_rele_nounlock(sp);
3863*f44e1126SVitaliy Gusev return (NFS4ERR_BAD_STATEID);
3864*f44e1126SVitaliy Gusev }
3865*f44e1126SVitaliy Gusev
3866da6c28aaSamw if (ct != NULL) {
3867d216dff5SRobert Mastors ct->cc_sysid =
3868d216dff5SRobert Mastors lsp->rls_locker->rl_client->rc_sysidt;
3869d216dff5SRobert Mastors ct->cc_pid = lsp->rls_locker->rl_pid;
3870da6c28aaSamw }
38717c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE);
38727c478bd9Sstevel@tonic-gate }
38737c478bd9Sstevel@tonic-gate
38747c478bd9Sstevel@tonic-gate /* Stateid provided was an "open" stateid */
38757c478bd9Sstevel@tonic-gate if (sp != NULL) {
38767c478bd9Sstevel@tonic-gate /* Is associated server instance in its grace period? */
3877d216dff5SRobert Mastors if (rfs4_clnt_in_grace(sp->rs_owner->ro_client)) {
38787c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
38797c478bd9Sstevel@tonic-gate return (NFS4ERR_GRACE);
38807c478bd9Sstevel@tonic-gate }
3881*f44e1126SVitaliy Gusev /* Skip if is here via the LOCKID */
38827c478bd9Sstevel@tonic-gate if (id->bits.type == OPENID) {
3883*f44e1126SVitaliy Gusev stat = check_state_seqid(&sp->rs_stateid, id,
3884*f44e1126SVitaliy Gusev use_ss);
3885*f44e1126SVitaliy Gusev if (stat) {
38867c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
3887*f44e1126SVitaliy Gusev return (stat);
38887c478bd9Sstevel@tonic-gate }
38897c478bd9Sstevel@tonic-gate }
38907c478bd9Sstevel@tonic-gate /* Ensure specified filehandle matches */
3891d216dff5SRobert Mastors if (sp->rs_finfo->rf_vp != vp) {
38927c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
38937c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
38947c478bd9Sstevel@tonic-gate }
38957c478bd9Sstevel@tonic-gate
3896d216dff5SRobert Mastors if (sp->rs_owner->ro_need_confirm) {
38977c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
38987c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
38997c478bd9Sstevel@tonic-gate }
39007c478bd9Sstevel@tonic-gate
3901d216dff5SRobert Mastors if (sp->rs_closed == TRUE) {
39027c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
39037c478bd9Sstevel@tonic-gate return (NFS4ERR_OLD_STATEID);
39047c478bd9Sstevel@tonic-gate }
39057c478bd9Sstevel@tonic-gate
39067c478bd9Sstevel@tonic-gate if (do_access)
39077c478bd9Sstevel@tonic-gate stat = rfs4_state_has_access(sp, mode, vp);
39087c478bd9Sstevel@tonic-gate else
39097c478bd9Sstevel@tonic-gate stat = NFS4_OK;
39107c478bd9Sstevel@tonic-gate
39117c478bd9Sstevel@tonic-gate /*
39127c478bd9Sstevel@tonic-gate * Return whether this state has write
39137c478bd9Sstevel@tonic-gate * delegation if desired
39147c478bd9Sstevel@tonic-gate */
3915d216dff5SRobert Mastors if (deleg && (sp->rs_finfo->rf_dinfo.rd_dtype ==
3916d216dff5SRobert Mastors OPEN_DELEGATE_WRITE))
39177c478bd9Sstevel@tonic-gate *deleg = TRUE;
39187c478bd9Sstevel@tonic-gate
39197c478bd9Sstevel@tonic-gate /*
39207c478bd9Sstevel@tonic-gate * We got a valid stateid, so we update the
39217c478bd9Sstevel@tonic-gate * lease on the client. Ideally we would like
39227c478bd9Sstevel@tonic-gate * to do this after the calling op succeeds,
39237c478bd9Sstevel@tonic-gate * but for now this will be good
39247c478bd9Sstevel@tonic-gate * enough. Callers of this routine are
39257c478bd9Sstevel@tonic-gate * currently insulated from the state stuff.
39267c478bd9Sstevel@tonic-gate */
3927d216dff5SRobert Mastors rfs4_update_lease(sp->rs_owner->ro_client);
39287c478bd9Sstevel@tonic-gate
39297c478bd9Sstevel@tonic-gate /*
39307c478bd9Sstevel@tonic-gate * If a delegation is present on this file and
39317c478bd9Sstevel@tonic-gate * this is a WRITE, then update the lastwrite
39327c478bd9Sstevel@tonic-gate * time to indicate that activity is present.
39337c478bd9Sstevel@tonic-gate */
3934d216dff5SRobert Mastors if (sp->rs_finfo->rf_dinfo.rd_dtype ==
3935d216dff5SRobert Mastors OPEN_DELEGATE_WRITE &&
3936ed57cab9Srg mode == FWRITE) {
3937d216dff5SRobert Mastors sp->rs_finfo->rf_dinfo.rd_time_lastwrite =
3938ed57cab9Srg gethrestime_sec();
39397c478bd9Sstevel@tonic-gate }
39407c478bd9Sstevel@tonic-gate
3941*f44e1126SVitaliy Gusev /* Fill context for possible nbmand check */
3942*f44e1126SVitaliy Gusev if (ct != NULL && ct->cc_pid == 0) {
3943*f44e1126SVitaliy Gusev ct->cc_sysid =
3944*f44e1126SVitaliy Gusev sp->rs_owner->ro_client->rc_sysidt;
3945*f44e1126SVitaliy Gusev ct->cc_pid =
3946*f44e1126SVitaliy Gusev rfs4_dbe_getid(sp->rs_owner->ro_dbe);
3947*f44e1126SVitaliy Gusev }
3948*f44e1126SVitaliy Gusev
39497c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
39507c478bd9Sstevel@tonic-gate
39517c478bd9Sstevel@tonic-gate return (stat);
39527c478bd9Sstevel@tonic-gate }
39537c478bd9Sstevel@tonic-gate
39547c478bd9Sstevel@tonic-gate if (dsp != NULL) {
39557c478bd9Sstevel@tonic-gate /* Is associated server instance in its grace period? */
3956d216dff5SRobert Mastors if (rfs4_clnt_in_grace(dsp->rds_client)) {
39577c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp);
39587c478bd9Sstevel@tonic-gate return (NFS4ERR_GRACE);
39597c478bd9Sstevel@tonic-gate }
3960*f44e1126SVitaliy Gusev
3961*f44e1126SVitaliy Gusev stat = check_state_seqid(&dsp->rds_delegid, id, use_ss);
3962*f44e1126SVitaliy Gusev if (stat) {
39637c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp);
3964*f44e1126SVitaliy Gusev return (stat);
39657c478bd9Sstevel@tonic-gate }
39667c478bd9Sstevel@tonic-gate
39677c478bd9Sstevel@tonic-gate /* Ensure specified filehandle matches */
3968d216dff5SRobert Mastors if (dsp->rds_finfo->rf_vp != vp) {
39697c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp);
39707c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
39717c478bd9Sstevel@tonic-gate }
39727c478bd9Sstevel@tonic-gate /*
39737c478bd9Sstevel@tonic-gate * Return whether this state has write
39747c478bd9Sstevel@tonic-gate * delegation if desired
39757c478bd9Sstevel@tonic-gate */
3976d216dff5SRobert Mastors if (deleg && (dsp->rds_finfo->rf_dinfo.rd_dtype ==
3977d216dff5SRobert Mastors OPEN_DELEGATE_WRITE))
39787c478bd9Sstevel@tonic-gate *deleg = TRUE;
39797c478bd9Sstevel@tonic-gate
3980d216dff5SRobert Mastors rfs4_update_lease(dsp->rds_client);
39817c478bd9Sstevel@tonic-gate
39827c478bd9Sstevel@tonic-gate /*
39837c478bd9Sstevel@tonic-gate * If a delegation is present on this file and
39847c478bd9Sstevel@tonic-gate * this is a WRITE, then update the lastwrite
39857c478bd9Sstevel@tonic-gate * time to indicate that activity is present.
39867c478bd9Sstevel@tonic-gate */
3987d216dff5SRobert Mastors if (dsp->rds_finfo->rf_dinfo.rd_dtype ==
3988d216dff5SRobert Mastors OPEN_DELEGATE_WRITE && mode == FWRITE) {
3989d216dff5SRobert Mastors dsp->rds_finfo->rf_dinfo.rd_time_lastwrite =
3990ed57cab9Srg gethrestime_sec();
39917c478bd9Sstevel@tonic-gate }
39927c478bd9Sstevel@tonic-gate
39937c478bd9Sstevel@tonic-gate /*
39947c478bd9Sstevel@tonic-gate * XXX - what happens if this is a WRITE and the
39957c478bd9Sstevel@tonic-gate * delegation type of for READ.
39967c478bd9Sstevel@tonic-gate */
39977c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp);
39987c478bd9Sstevel@tonic-gate
39997c478bd9Sstevel@tonic-gate return (stat);
40007c478bd9Sstevel@tonic-gate }
40017c478bd9Sstevel@tonic-gate /*
40027c478bd9Sstevel@tonic-gate * If we got this far, something bad happened
40037c478bd9Sstevel@tonic-gate */
40047c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID);
40057c478bd9Sstevel@tonic-gate }
40067c478bd9Sstevel@tonic-gate }
40077c478bd9Sstevel@tonic-gate
40087c478bd9Sstevel@tonic-gate
40097c478bd9Sstevel@tonic-gate /*
40107c478bd9Sstevel@tonic-gate * This is a special function in that for the file struct provided the
40117c478bd9Sstevel@tonic-gate * server wants to remove/close all current state associated with the
40127c478bd9Sstevel@tonic-gate * file. The prime use of this would be with OP_REMOVE to force the
40137c478bd9Sstevel@tonic-gate * release of state and particularly of file locks.
40147c478bd9Sstevel@tonic-gate *
40157c478bd9Sstevel@tonic-gate * There is an assumption that there is no delegations outstanding on
40167c478bd9Sstevel@tonic-gate * this file at this point. The caller should have waited for those
40177c478bd9Sstevel@tonic-gate * to be returned or revoked.
40187c478bd9Sstevel@tonic-gate */
40197c478bd9Sstevel@tonic-gate void
rfs4_close_all_state(rfs4_file_t * fp)40207c478bd9Sstevel@tonic-gate rfs4_close_all_state(rfs4_file_t *fp)
40217c478bd9Sstevel@tonic-gate {
40227c478bd9Sstevel@tonic-gate rfs4_state_t *sp;
40237c478bd9Sstevel@tonic-gate
4024d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe);
40257c478bd9Sstevel@tonic-gate
40267c478bd9Sstevel@tonic-gate #ifdef DEBUG
40277c478bd9Sstevel@tonic-gate /* only applies when server is handing out delegations */
40280dfe541eSEvan Layton if (nfs4_get_deleg_policy() != SRV_NEVER_DELEGATE)
4029d216dff5SRobert Mastors ASSERT(fp->rf_dinfo.rd_hold_grant > 0);
40307c478bd9Sstevel@tonic-gate #endif
40317c478bd9Sstevel@tonic-gate
40327c478bd9Sstevel@tonic-gate /* No delegations for this file */
4033d216dff5SRobert Mastors ASSERT(list_is_empty(&fp->rf_delegstatelist));
40347c478bd9Sstevel@tonic-gate
40357c478bd9Sstevel@tonic-gate /* Make sure that it can not be found */
4036d216dff5SRobert Mastors rfs4_dbe_invalidate(fp->rf_dbe);
40377c478bd9Sstevel@tonic-gate
4038d216dff5SRobert Mastors if (fp->rf_vp == NULL) {
4039d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
40407c478bd9Sstevel@tonic-gate return;
40417c478bd9Sstevel@tonic-gate }
4042d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
40437c478bd9Sstevel@tonic-gate
40447c478bd9Sstevel@tonic-gate /*
40457c478bd9Sstevel@tonic-gate * Hold as writer to prevent other server threads from
40467c478bd9Sstevel@tonic-gate * processing requests related to the file while all state is
40477c478bd9Sstevel@tonic-gate * being removed.
40487c478bd9Sstevel@tonic-gate */
4049d216dff5SRobert Mastors rw_enter(&fp->rf_file_rwlock, RW_WRITER);
40507c478bd9Sstevel@tonic-gate
40517c478bd9Sstevel@tonic-gate /* Remove ALL state from the file */
4052bd3561fbSToomas Soome while ((sp = rfs4_findstate_by_file(fp)) != NULL) {
40537c478bd9Sstevel@tonic-gate rfs4_state_close(sp, FALSE, FALSE, CRED());
40547c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp);
40557c478bd9Sstevel@tonic-gate }
40567c478bd9Sstevel@tonic-gate
40577c478bd9Sstevel@tonic-gate /*
40587c478bd9Sstevel@tonic-gate * This is only safe since there are no further references to
40597c478bd9Sstevel@tonic-gate * the file.
40607c478bd9Sstevel@tonic-gate */
4061d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe);
4062d216dff5SRobert Mastors if (fp->rf_vp) {
4063d216dff5SRobert Mastors vnode_t *vp = fp->rf_vp;
40641b300de9Sjwahlig
4065d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock);
40661b300de9Sjwahlig (void) vsd_set(vp, nfs4_srv_vkey, NULL);
4067d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
40681b300de9Sjwahlig VN_RELE(vp);
4069d216dff5SRobert Mastors fp->rf_vp = NULL;
40707c478bd9Sstevel@tonic-gate }
4071d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe);
40727c478bd9Sstevel@tonic-gate
40737c478bd9Sstevel@tonic-gate /* Finally let other references to proceed */
4074d216dff5SRobert Mastors rw_exit(&fp->rf_file_rwlock);
40757c478bd9Sstevel@tonic-gate }
40767c478bd9Sstevel@tonic-gate
40777c478bd9Sstevel@tonic-gate /*
40787c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call
40797c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the
40807c478bd9Sstevel@tonic-gate * lockowner_state refers to a file that resides within the exportinfo
40817c478bd9Sstevel@tonic-gate * export. If so, then remove the lock_owner state (file locks and
40827c478bd9Sstevel@tonic-gate * share "locks") for this object since the intent is the server is
40837c478bd9Sstevel@tonic-gate * unexporting the specified directory. Be sure to invalidate the
40847c478bd9Sstevel@tonic-gate * object after the state has been released
40857c478bd9Sstevel@tonic-gate */
40867c478bd9Sstevel@tonic-gate static void
rfs4_lo_state_walk_callout(rfs4_entry_t u_entry,void * e)40877c478bd9Sstevel@tonic-gate rfs4_lo_state_walk_callout(rfs4_entry_t u_entry, void *e)
40887c478bd9Sstevel@tonic-gate {
40897c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry;
40907c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e;
4091b096b66cSnr nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp;
4092b096b66cSnr fhandle_t *efhp;
4093b096b66cSnr
4094b096b66cSnr efhp = (fhandle_t *)&exi->exi_fh;
4095b096b66cSnr exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4;
4096b096b66cSnr
4097b096b66cSnr FH_TO_FMT4(efhp, exi_fhp);
40987c478bd9Sstevel@tonic-gate
4099d216dff5SRobert Mastors finfo_fhp = (nfs_fh4_fmt_t *)lsp->rls_state->rs_finfo->
4100d216dff5SRobert Mastors rf_filehandle.nfs_fh4_val;
41017c478bd9Sstevel@tonic-gate
41027c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) &&
41037c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata,
4104ed57cab9Srg exi_fhp->fh4_xlen) == 0) {
4105d216dff5SRobert Mastors rfs4_state_close(lsp->rls_state, FALSE, FALSE, CRED());
4106d216dff5SRobert Mastors rfs4_dbe_invalidate(lsp->rls_dbe);
4107d216dff5SRobert Mastors rfs4_dbe_invalidate(lsp->rls_state->rs_dbe);
41087c478bd9Sstevel@tonic-gate }
41097c478bd9Sstevel@tonic-gate }
41107c478bd9Sstevel@tonic-gate
41117c478bd9Sstevel@tonic-gate /*
41127c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call
41137c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the state refers
41147c478bd9Sstevel@tonic-gate * to a file that resides within the exportinfo export. If so, then
41157c478bd9Sstevel@tonic-gate * remove the open state for this object since the intent is the
41167c478bd9Sstevel@tonic-gate * server is unexporting the specified directory. The main result for
41177c478bd9Sstevel@tonic-gate * this type of entry is to invalidate it such it will not be found in
41187c478bd9Sstevel@tonic-gate * the future.
41197c478bd9Sstevel@tonic-gate */
41207c478bd9Sstevel@tonic-gate static void
rfs4_state_walk_callout(rfs4_entry_t u_entry,void * e)41217c478bd9Sstevel@tonic-gate rfs4_state_walk_callout(rfs4_entry_t u_entry, void *e)
41227c478bd9Sstevel@tonic-gate {
41237c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry;
41247c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e;
4125b096b66cSnr nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp;
4126b096b66cSnr fhandle_t *efhp;
4127b096b66cSnr
4128b096b66cSnr efhp = (fhandle_t *)&exi->exi_fh;
4129b096b66cSnr exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4;
4130b096b66cSnr
4131b096b66cSnr FH_TO_FMT4(efhp, exi_fhp);
41327c478bd9Sstevel@tonic-gate
41337c478bd9Sstevel@tonic-gate finfo_fhp =
4134d216dff5SRobert Mastors (nfs_fh4_fmt_t *)sp->rs_finfo->rf_filehandle.nfs_fh4_val;
41357c478bd9Sstevel@tonic-gate
41367c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) &&
41377c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata,
4138ed57cab9Srg exi_fhp->fh4_xlen) == 0) {
41397c478bd9Sstevel@tonic-gate rfs4_state_close(sp, TRUE, FALSE, CRED());
4140d216dff5SRobert Mastors rfs4_dbe_invalidate(sp->rs_dbe);
41417c478bd9Sstevel@tonic-gate }
41427c478bd9Sstevel@tonic-gate }
41437c478bd9Sstevel@tonic-gate
41447c478bd9Sstevel@tonic-gate /*
41457c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call
41467c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the state refers
41477c478bd9Sstevel@tonic-gate * to a file that resides within the exportinfo export. If so, then
41487c478bd9Sstevel@tonic-gate * remove the deleg state for this object since the intent is the
41497c478bd9Sstevel@tonic-gate * server is unexporting the specified directory. The main result for
41507c478bd9Sstevel@tonic-gate * this type of entry is to invalidate it such it will not be found in
41517c478bd9Sstevel@tonic-gate * the future.
41527c478bd9Sstevel@tonic-gate */
41537c478bd9Sstevel@tonic-gate static void
rfs4_deleg_state_walk_callout(rfs4_entry_t u_entry,void * e)41547c478bd9Sstevel@tonic-gate rfs4_deleg_state_walk_callout(rfs4_entry_t u_entry, void *e)
41557c478bd9Sstevel@tonic-gate {
41567c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry;
41577c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e;
4158b096b66cSnr nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp;
4159b096b66cSnr fhandle_t *efhp;
4160b096b66cSnr
4161b096b66cSnr efhp = (fhandle_t *)&exi->exi_fh;
4162b096b66cSnr exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4;
4163b096b66cSnr
4164b096b66cSnr FH_TO_FMT4(efhp, exi_fhp);
41657c478bd9Sstevel@tonic-gate
41667c478bd9Sstevel@tonic-gate finfo_fhp =
4167d216dff5SRobert Mastors (nfs_fh4_fmt_t *)dsp->rds_finfo->rf_filehandle.nfs_fh4_val;
41687c478bd9Sstevel@tonic-gate
41697c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) &&
41707c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata,
4171ed57cab9Srg exi_fhp->fh4_xlen) == 0) {
4172d216dff5SRobert Mastors rfs4_dbe_invalidate(dsp->rds_dbe);
41737c478bd9Sstevel@tonic-gate }
41747c478bd9Sstevel@tonic-gate }
41757c478bd9Sstevel@tonic-gate
41767c478bd9Sstevel@tonic-gate /*
41777c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call
41787c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the state refers
41797c478bd9Sstevel@tonic-gate * to a file that resides within the exportinfo export. If so, then
41807c478bd9Sstevel@tonic-gate * release vnode hold for this object since the intent is the server
41817c478bd9Sstevel@tonic-gate * is unexporting the specified directory. Invalidation will prevent
41827c478bd9Sstevel@tonic-gate * this struct from being found in the future.
41837c478bd9Sstevel@tonic-gate */
41847c478bd9Sstevel@tonic-gate static void
rfs4_file_walk_callout(rfs4_entry_t u_entry,void * e)41857c478bd9Sstevel@tonic-gate rfs4_file_walk_callout(rfs4_entry_t u_entry, void *e)
41867c478bd9Sstevel@tonic-gate {
41877c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry;
41887c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e;
4189b096b66cSnr nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp;
4190b096b66cSnr fhandle_t *efhp;
4191b096b66cSnr
4192b096b66cSnr efhp = (fhandle_t *)&exi->exi_fh;
4193b096b66cSnr exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4;
4194b096b66cSnr
4195b096b66cSnr FH_TO_FMT4(efhp, exi_fhp);
41967c478bd9Sstevel@tonic-gate
4197d216dff5SRobert Mastors finfo_fhp = (nfs_fh4_fmt_t *)fp->rf_filehandle.nfs_fh4_val;
41987c478bd9Sstevel@tonic-gate
41997c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) &&
42007c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata,
4201ed57cab9Srg exi_fhp->fh4_xlen) == 0) {
4202d216dff5SRobert Mastors if (fp->rf_vp) {
4203d216dff5SRobert Mastors vnode_t *vp = fp->rf_vp;
4204bb972d76Sjwahlig
4205da6c28aaSamw /*
4206da6c28aaSamw * don't leak monitors and remove the reference
4207da6c28aaSamw * put on the vnode when the delegation was granted.
4208da6c28aaSamw */
4209d216dff5SRobert Mastors if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_READ) {
4210bb972d76Sjwahlig (void) fem_uninstall(vp, deleg_rdops,
4211ed57cab9Srg (void *)fp);
4212da6c28aaSamw vn_open_downgrade(vp, FREAD);
4213d216dff5SRobert Mastors } else if (fp->rf_dinfo.rd_dtype ==
4214d216dff5SRobert Mastors OPEN_DELEGATE_WRITE) {
4215bb972d76Sjwahlig (void) fem_uninstall(vp, deleg_wrops,
4216ed57cab9Srg (void *)fp);
4217da6c28aaSamw vn_open_downgrade(vp, FREAD|FWRITE);
4218da6c28aaSamw }
4219d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock);
4220bb972d76Sjwahlig (void) vsd_set(vp, nfs4_srv_vkey, NULL);
4221d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock);
4222bb972d76Sjwahlig VN_RELE(vp);
4223d216dff5SRobert Mastors fp->rf_vp = NULL;
42247c478bd9Sstevel@tonic-gate }
4225d216dff5SRobert Mastors rfs4_dbe_invalidate(fp->rf_dbe);
42267c478bd9Sstevel@tonic-gate }
42277c478bd9Sstevel@tonic-gate }
42287c478bd9Sstevel@tonic-gate
42297c478bd9Sstevel@tonic-gate /*
42307c478bd9Sstevel@tonic-gate * Given a directory that is being unexported, cleanup/release all
42317c478bd9Sstevel@tonic-gate * state in the server that refers to objects residing underneath this
42327c478bd9Sstevel@tonic-gate * particular export. The ordering of the release is important.
42337c478bd9Sstevel@tonic-gate * Lock_owner, then state and then file.
42340dfe541eSEvan Layton *
42350dfe541eSEvan Layton * NFS zones note: nfs_export.c:unexport() calls this from a
42360dfe541eSEvan Layton * thread in the global zone for NGZ data structures, so we
42370dfe541eSEvan Layton * CANNOT use zone_getspecific anywhere in this code path.
42387c478bd9Sstevel@tonic-gate */
42397c478bd9Sstevel@tonic-gate void
rfs4_clean_state_exi(nfs_export_t * ne,struct exportinfo * exi)42400dfe541eSEvan Layton rfs4_clean_state_exi(nfs_export_t *ne, struct exportinfo *exi)
42417c478bd9Sstevel@tonic-gate {
42420dfe541eSEvan Layton nfs_globals_t *ng;
42430dfe541eSEvan Layton nfs4_srv_t *nsrv4;
42440dfe541eSEvan Layton
42450dfe541eSEvan Layton ng = ne->ne_globals;
42460dfe541eSEvan Layton ASSERT(ng->nfs_zoneid == exi->exi_zoneid);
42470dfe541eSEvan Layton nsrv4 = ng->nfs4_srv;
42480dfe541eSEvan Layton
42490dfe541eSEvan Layton mutex_enter(&nsrv4->state_lock);
42507c478bd9Sstevel@tonic-gate
42510dfe541eSEvan Layton if (nsrv4->nfs4_server_state == NULL) {
42520dfe541eSEvan Layton mutex_exit(&nsrv4->state_lock);
42537c478bd9Sstevel@tonic-gate return;
42547c478bd9Sstevel@tonic-gate }
42557c478bd9Sstevel@tonic-gate
42560dfe541eSEvan Layton rfs4_dbe_walk(nsrv4->rfs4_lo_state_tab,
42570dfe541eSEvan Layton rfs4_lo_state_walk_callout, exi);
42580dfe541eSEvan Layton rfs4_dbe_walk(nsrv4->rfs4_state_tab, rfs4_state_walk_callout, exi);
42590dfe541eSEvan Layton rfs4_dbe_walk(nsrv4->rfs4_deleg_state_tab,
42600dfe541eSEvan Layton rfs4_deleg_state_walk_callout, exi);
42610dfe541eSEvan Layton rfs4_dbe_walk(nsrv4->rfs4_file_tab, rfs4_file_walk_callout, exi);
42627c478bd9Sstevel@tonic-gate
42630dfe541eSEvan Layton mutex_exit(&nsrv4->state_lock);
42647c478bd9Sstevel@tonic-gate }
4265